use OpenILS::WWW::AddedContent;
use XML::LibXML;
use MIME::Base64;
-use DateTime;
# Hack country_data to allow B&T fake ISBNs LP#1559281
$Business::ISBN::country_data{630} = ['B&T' => ['0000000' => '9999999']];
my $AC = 'OpenILS::WWW::AddedContent';
-my $post_url = 'http://contentcafe2.btol.com/ContentCafe/ContentCafe.asmx/XmlPost';
+my $base_url = 'http://contentcafe2.btol.com/ContentCafe/ContentCafe.asmx/Single';
+my $cover_base_url = 'http://contentcafe2.btol.com/ContentCafe/Jacket.aspx';
sub new {
my( $class, $args ) = @_;
return $self->{ContentCafe}->{password};
}
-sub identifier_order {
+sub return_behavior_on_no_jacket_image {
my $self = shift;
- if ($self->{ContentCafe}->{identifier_order}) {
- my $order = [ split(',',$self->{ContentCafe}->{identifier_order}) ];
- return $order;
- }
- return ['isbn','upc'];
-}
-
-sub expects_keyhash {
- # we expect a keyhash as opposed to a simple scalar containing an ISBN
- return 1;
-}
-
-# --------------------------------------------------------------------------
-
-# This function fetches everything and returns:
-# 0 if we had no usable keys
-# 0 if we had a lookup failure
-# A hash of format_type => result if you called that directly
-sub fetch_all {
- my( $self, $keyhash ) = @_;
- my $doc = $self->fetch_xmldoc([
- 'TocDetail', # toc_*
- 'BiographyDetail', #anotes_*
- 'ExcerptDetail', #excerpt_*
- 'ReviewDetail', #reviews_*
- 'AnnotationDetail', #summary_*
- {name => 'JacketDetail', attributes => [['Type','S'],['Encoding','HEX']]}, # jacket_small
- {name => 'JacketDetail', attributes => [['Type','M'],['Encoding','HEX']]}, # jacket_medium
- {name => 'JacketDetail', attributes => [['Type','L'],['Encoding','HEX']]}, # jacket_large
- ], $keyhash);
- return 0 unless defined $doc;
- my $resulthash = {
- toc_html => $self->parse_toc_html($doc),
- toc_json => $self->send_json($doc, 'TocItems'),
- toc_xml => $self->send_xml($doc, 'TocItems'),
- anotes_html => $self->parse_anotes_html($doc),
- anotes_json => $self->send_json($doc, 'BiographyItems'),
- anotes_xml => $self->send_xml($doc, 'BiographyItems'),
- excerpt_html => $self->parse_excerpt_html($doc),
- excerpt_json => $self->send_json($doc, 'ExcerptItems'),
- excerpt_xml => $self->send_xml($doc, 'ExcerptItems'),
- reviews_html => $self->parse_reviews_html($doc),
- reviews_json => $self->send_json($doc, 'ReviewItems'),
- reviews_xml => $self->send_xml($doc, 'ReviewItems'),
- summary_html => $self->parse_summary_html($doc),
- summary_json => $self->send_json($doc, 'AnnotationItems'),
- summary_xml => $self->send_xml($doc, 'AnnotationItems'),
- jacket_small => $self->parse_jacket($doc, 'S'),
- jacket_medium => $self->parse_jacket($doc, 'M'),
- jacket_large => $self->parse_jacket($doc, 'L')
- };
- return $resulthash;
+ return $self->{ContentCafe}->{return_behavior_on_no_jacket_image};
}
# --------------------------------------------------------------------------
sub jacket_small {
- my( $self, $keyhash ) = @_;
- return $self->send_jacket( $keyhash, 'S' );
+ my( $self, $key ) = @_;
+ return $self->send_img(
+ $self->fetch_cover_response('S', $key));
}
sub jacket_medium {
- my( $self, $keyhash ) = @_;
- return $self->send_jacket( $keyhash, 'M' );
-}
+ my( $self, $key ) = @_;
+ return $self->send_img(
+ $self->fetch_cover_response('M', $key));
+}
sub jacket_large {
- my( $self, $keyhash ) = @_;
- return $self->send_jacket( $keyhash, 'L' );
+ my( $self, $key ) = @_;
+ return $self->send_img(
+ $self->fetch_cover_response('L', $key));
}
# --------------------------------------------------------------------------
sub toc_html {
- my( $self, $keyhash ) = @_;
- my $doc = $self->fetch_xmldoc('TocDetail', $keyhash);
- return 0 unless defined $doc;
- return $self->parse_toc_html($doc);
-}
-
-sub parse_toc_html {
- my( $self, $doc ) = @_;
+ my( $self, $key ) = @_;
+ my $xml = $self->fetch_content('TocDetail', $key);
+ my $doc = XML::LibXML->new->parse_string($xml);
+ $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
my $html = '';
- my @nodes = $doc->findnodes('//cc:TocItems[*]');
- return 0 if (scalar(@nodes) < 1);
- @nodes = $nodes[0]->findnodes('.//cc:Toc');
+ my @nodes = $doc->findnodes('//cc:Toc');
return 0 if (scalar(@nodes) < 1);
foreach my $node ( @nodes ) {
$html .= $node->textContent . '</P></P>';
}
sub toc_xml {
- my( $self, $keyhash ) = @_;
+ my( $self, $key ) = @_;
return $self->send_xml(
- $self->fetch_xmldoc('TocDetail', $keyhash),
- 'TocItems');
+ $self->fetch_content('TocDetail', $key));
}
sub toc_json {
- my( $self, $keyhash ) = @_;
+ my( $self, $key ) = @_;
return $self->send_json(
- $self->fetch_xmldoc('TocDetail', $keyhash),
- 'TocItems');
+ $self->fetch_content('TocDetail', $key));
}
# --------------------------------------------------------------------------
sub anotes_html {
- my( $self, $keyhash ) = @_;
- my $doc = $self->fetch_xmldoc('BiographyDetail', $keyhash);
- return 0 unless defined $doc;
- return $self->parse_anotes_html($doc);
-}
-
-sub parse_anotes_html {
- my( $self, $doc ) = @_;
+ my( $self, $key ) = @_;
+ my $xml = $self->fetch_content('BiographyDetail', $key);
+ my $doc = XML::LibXML->new->parse_string($xml);
+ $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
my $html = '';
- my @nodes = $doc->findnodes('//cc:BiographyItems[*]');
- return 0 if (scalar(@nodes) < 1);
- @nodes = $nodes[0]->findnodes('.//cc:Biography');
+ my @nodes = $doc->findnodes('//cc:Biography');
return 0 if (scalar(@nodes) < 1);
foreach my $node ( @nodes ) {
$html .= '<P class="biography">' . $node->textContent . '</P>';
}
sub anotes_xml {
- my( $self, $keyhash ) = @_;
+ my( $self, $key ) = @_;
return $self->send_xml(
- $self->fetch_xmldoc('BiographyDetail', $keyhash),
- 'BiographyItems');
+ $self->fetch_content('BiographyDetail', $key));
}
sub anotes_json {
- my( $self, $keyhash ) = @_;
+ my( $self, $key ) = @_;
return $self->send_json(
- $self->fetch_xmldoc('BiographyDetail', $keyhash),
- 'BiographyItems');
+ $self->fetch_content('BiographyDetail', $key));
}
# --------------------------------------------------------------------------
sub excerpt_html {
- my( $self, $keyhash ) = @_;
- my $doc = $self->fetch_xmldoc('ExcerptDetail', $keyhash);
- return 0 unless defined $doc;
- return $self->parse_excerpt_html($doc);
-}
-
-sub parse_excerpt_html {
- my( $self, $doc ) = @_;
+ my( $self, $key ) = @_;
+ my $xml = $self->fetch_content('ExcerptDetail', $key);
+ my $doc = XML::LibXML->new->parse_string($xml);
+ $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
my $html = '';
- my @nodes = $doc->findnodes('//cc:ExcerptItems[*]');
- return 0 if (scalar(@nodes) < 1);
- @nodes = $nodes[0]->findnodes('.//cc:Excerpt');
+ my @nodes = $doc->findnodes('//cc:Excerpt');
return 0 if (scalar(@nodes) < 1);
foreach my $node ( @nodes ) {
$html .= $node->textContent;
}
sub excerpt_xml {
- my( $self, $keyhash ) = @_;
+ my( $self, $key ) = @_;
return $self->send_xml(
- $self->fetch_xmldoc('ExcerptDetail', $keyhash),
- 'ExcerptItems');
+ $self->fetch_content('ExcerptDetail', $key));
}
sub excerpt_json {
- my( $self, $keyhash ) = @_;
+ my( $self, $key ) = @_;
return $self->send_json(
- $self->fetch_xmldoc('ExcerptDetail', $keyhash),
- 'ExcerptItems');
+ $self->fetch_content('ExcerptDetail', $key));
}
# --------------------------------------------------------------------------
sub reviews_html {
- my( $self, $keyhash ) = @_;
- my $doc = $self->fetch_xmldoc('ReviewDetail', $keyhash);
- return 0 unless defined $doc;
- return $self->parse_reviews_html($doc);
-}
-
-sub parse_reviews_html {
- my( $self, $doc ) = @_;
+ my( $self, $key ) = @_;
+ my $xml = $self->fetch_content('ReviewDetail', $key);
+ my $doc = XML::LibXML->new->parse_string($xml);
+ $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
my $html = '<ul>';
- my @nodes = $doc->findnodes('//cc:ReviewItems[*]');
- return 0 if (scalar(@nodes) < 1);
- @nodes = $nodes[0]->findnodes('.//cc:ReviewItem');
+ my @nodes = $doc->findnodes('//cc:ReviewItem');
return 0 if (scalar(@nodes) < 1);
foreach my $node ( @nodes ) {
my @s_nodes = $node->findnodes('./cc:Supplier');
}
sub reviews_xml {
- my( $self, $keyhash ) = @_;
+ my( $self, $key ) = @_;
return $self->send_xml(
- $self->fetch_xmldoc('ReviewDetail', $keyhash),
- 'ReviewItems');
+ $self->fetch_content('ReviewDetail', $key));
}
sub reviews_json {
- my( $self, $keyhash ) = @_;
+ my( $self, $key ) = @_;
return $self->send_json(
- $self->fetch_xmldoc('ReviewDetail', $keyhash),
- 'ReviewItems');
+ $self->fetch_content('ReviewDetail', $key));
}
# --------------------------------------------------------------------------
sub summary_html {
- my( $self, $keyhash ) = @_;
- my $doc = $self->fetch_xmldoc('AnnotationDetail', $keyhash);
- return 0 unless defined $doc;
- return $self->parse_summary_html($doc);
-}
-
-sub parse_summary_html {
- my( $self, $doc ) = @_;
+ my( $self, $key ) = @_;
+ my $xml = $self->fetch_content('AnnotationDetail', $key);
+ my $doc = XML::LibXML->new->parse_string($xml);
+ $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
my $html = '<ul>';
- my @nodes = $doc->findnodes('//cc:AnnotationItems[*]');
- return 0 if (scalar(@nodes) < 1);
- @nodes = $nodes[0]->findnodes('.//cc:AnnotationItem');
+ my @nodes = $doc->findnodes('//cc:AnnotationItem');
return 0 if (scalar(@nodes) < 1);
foreach my $node ( @nodes ) {
my @s_nodes = $node->findnodes('./cc:Supplier');
}
sub summary_xml {
- my( $self, $keyhash ) = @_;
+ my( $self, $key ) = @_;
return $self->send_xml(
- $self->fetch_xmldoc('AnnotationDetail', $keyhash),
- 'AnnotationItems');
+ $self->fetch_content('AnnotationDetail', $key));
}
sub summary_json {
- my( $self, $keyhash ) = @_;
+ my( $self, $key ) = @_;
return $self->send_json(
- $self->fetch_xmldoc('AnnotationDetail', $keyhash),
- 'AnnotationItems');
+ $self->fetch_content('AnnotationDetail', $key));
+}
+
+sub available_json {
+ my($self, $key) = @_;
+ my $xml = $self->fetch_content('AvailableContent', $key);
+ my $doc = XML::LibXML->new->parse_string($xml);
+
+ my @avail;
+ for my $node ($doc->findnodes('//*[text()="true"]')) {
+ push(@avail, 'summary') if $node->nodeName eq 'Annotation';
+ push(@avail, 'jacket') if $node->nodeName eq 'Jacket';
+ push(@avail, 'toc') if $node->nodeName eq 'TOC';
+ push(@avail, 'anotes') if $node->nodeName eq 'Biography';
+ push(@avail, 'excerpt') if $node->nodeName eq 'Excerpt';
+ push(@avail, 'reviews') if $node->nodeName eq 'Review';
+ }
+
+ return {
+ content_type => 'text/plain',
+ content => OpenSRF::Utils::JSON->perl2JSON(\@avail)
+ };
}
+
# --------------------------------------------------------------------------
-sub build_keylist {
- my ( $self, $keyhash ) = @_;
- my $keys = []; # Start with an empty array
- foreach my $identifier (@{$self->identifier_order}) {
- foreach my $key (@{$keyhash->{$identifier}}) {
- push @{$keys}, $key;
- }
- }
- return $keys;
+
+sub data_exists {
+ my( $self, $data ) = @_;
+ return 0 if $data =~ m/<title>error<\/title>/iog;
+ return 1;
}
+
sub send_json {
- my( $self, $doc, $contentNode ) = @_;
- return 0 unless defined $doc;
- my @nodes = $doc->findnodes('//cc:' . $contentNode . '[*]');
- return 0 if (scalar(@nodes) < 1);
- my $perl = OpenSRF::Utils::SettingsParser::XML2perl($nodes[0]);
+ my( $self, $xml ) = @_;
+ return 0 unless $self->data_exists($xml);
+ my $doc;
+
+ try {
+ $doc = XML::LibXML->new->parse_string($xml);
+ } catch Error with {
+ my $err = shift;
+ $logger->error("added content XML parser error: $err\n\n$xml");
+ $doc = undef;
+ };
+
+ return 0 unless $doc;
+ my $perl = OpenSRF::Utils::SettingsParser::XML2perl($doc->documentElement);
my $json = OpenSRF::Utils::JSON->perl2JSON($perl);
return { content_type => 'text/plain', content => $json };
}
sub send_xml {
- my( $self, $doc, $contentNode ) = @_;
- return 0 unless defined $doc;
- my @nodes = $doc->findnodes('//cc:' . $contentNode . '[*]');
- return 0 if (scalar(@nodes) < 1);
- my $newdoc = XML::LibXML::Document->new( '1.0', 'utf-8' );
- my $clonenode = $nodes[0]->cloneNode(1);
- $newdoc->adoptNode($clonenode);
- $newdoc->setDocumentElement($clonenode);
- return { content_type => 'application/xml', content => $newdoc->toString() };
+ my( $self, $xml ) = @_;
+ return 0 unless $self->data_exists($xml);
+ return { content_type => 'application/xml', content => $xml };
}
sub send_html {
my( $self, $content ) = @_;
+ return 0 unless $self->data_exists($content);
# Hide anything that might contain a link since it will be broken
my $HTML = <<" HTML";
return { content_type => 'text/html', content => $HTML };
}
-sub send_jacket {
- my( $self, $keyhash, $size ) = @_;
-
- my $doc = $self->fetch_xmldoc({name => 'JacketDetail', attributes => [['Type',$size],['Encoding','HEX']]}, $keyhash);
- return 0 unless defined $doc;
-
- return $self->parse_jacket($doc, $size);
-}
-
-sub parse_jacket {
- my( $self, $doc, $size ) = @_;
- my @nodes = $doc->findnodes("//cc:JacketItem[cc:Type/\@Code = '$size']");
- return 0 if (scalar(@nodes) < 1);
-
- my $jacketItem = shift(@nodes); # We only care about the first jacket
- my @formatNodes = $jacketItem->findnodes('./cc:Format');
- my $format = $formatNodes[0]->textContent;
- my @jacketNodes = $jacketItem->findnodes('./cc:Jacket');
- my $imageData = pack('H*',$jacketNodes[0]->textContent);
-
- return {
- content_type => 'image/' . lc($format),
- content => $imageData,
+sub send_img {
+ my($self, $response) = @_;
+ return {
+ content_type => $response->header('Content-type'),
+ content => $response->content,
binary => 1
};
}
-# returns an XML document ready for parsing if $keyhash contained usable keys
-# otherwise returns undef
-sub fetch_xmldoc {
- my( $self, $contentTypes, $keyhash ) = @_;
-
- my $keys = $self->build_keylist($keyhash);
- return undef unless @{$keys};
-
- my $content = $self->fetch_response($contentTypes, $keys)->content;
- my $doc = XML::LibXML->new->parse_string($content);
- $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
- return $doc;
+# returns the raw content returned from the URL fetch
+sub fetch_content {
+ my( $self, $contentType, $key ) = @_;
+ return $self->fetch_response($contentType, $key)->content;
}
# returns the HTTP response object from the URL fetch
sub fetch_response {
- my( $self, $contentTypes, $keys ) = @_;
-
- if (ref($contentTypes) ne 'ARRAY') {
- $contentTypes = [ $contentTypes ];
- }
+ my( $self, $contentType, $key ) = @_;
+ my $userid = $self->userid;
+ my $password = $self->password;
+ my $url = $base_url . "?UserID=$userid&Password=$password&Key=$key&Content=$contentType";
+ return $AC->get_url($url);
+}
- my $xmlRequest = XML::LibXML::Document->new( '1.0', 'utf-8' );
- my $root = $xmlRequest->createElementNS('http://ContentCafe2.btol.com','ContentCafe');
- $root->addChild($xmlRequest->createAttribute('DateTime', DateTime->now()->datetime));
- $xmlRequest->setDocumentElement($root);
- my $requestItems = $xmlRequest->createElement('RequestItems');
- $requestItems->addChild($xmlRequest->createAttribute('UserID', $self->userid));
- $requestItems->addChild($xmlRequest->createAttribute('Password', $self->password));
- $root->addChild($requestItems);
-
- foreach my $key (@{$keys}) {
- my $requestItem = $xmlRequest->createElement('RequestItem');
- my $keyNode = $xmlRequest->createElement('Key');
- $keyNode->addChild($xmlRequest->createTextNode($key));
- $requestItem->addChild($keyNode);
-
- foreach my $contentType (@{$contentTypes}) {
- my $contentNode = $xmlRequest->createElement('Content');
- if (ref($contentType) eq 'HASH') {
- $contentNode->addChild($xmlRequest->createTextNode($contentType->{name}));
- foreach my $contentAttribute (@{$contentType->{attributes}}) {
- $contentNode->addChild($xmlRequest->createAttribute($contentAttribute->[0], $contentAttribute->[1]));
- }
- } else {
- $contentNode->addChild($xmlRequest->createTextNode($contentType));
- }
- $requestItem->addChild($contentNode);
- }
-
- $requestItems->addChild($requestItem);
- }
- my $response = $AC->post_url($post_url, $xmlRequest->toString);
- return $response;
+# returns the HTTP response object from the URL fetch
+sub fetch_cover_response {
+ my( $self, $size, $key ) = @_;
+ my $userid = $self->userid;
+ my $password = $self->password;
+ my $return = $self->return_behavior_on_no_jacket_image;
+ my $url = $cover_base_url . "?UserID=$userid&Password=$password&Return=$return&Type=$size&Value=$key";
+ return $AC->get_url($url);
}
+
1;