Imported Upstream version 0.11
[libwww-opensearch-perl.git] / lib / WWW / OpenSearch / Description.pm
index 6ed1e9a..0075e35 100644 (file)
-package WWW::OpenSearch::Description;\r
-\r
-use strict;\r
-use warnings;\r
-\r
-use base qw( Class::Accessor::Fast );\r
-\r
-use Carp;\r
-use XML::LibXML;\r
-use WWW::OpenSearch::Url;\r
-\r
-my @columns = qw(\r
-    AdultContent Contact     Description      Developer\r
-    Format       Image       LongName         Query\r
-    SampleSearch ShortName   SyndicationRight Tags\r
+package WWW::OpenSearch::Description;
+
+use strict;
+use warnings;
+
+use base qw( Class::Accessor::Fast );
+
+use Carp;
+use XML::LibXML;
+use WWW::OpenSearch::Url;
+use WWW::OpenSearch::Query;
+use WWW::OpenSearch::Image;
+
+my @columns = qw(
+    AdultContent Contact     Description      Developer
+    Format       Image       LongName         Query
+    SampleSearch ShortName   SyndicationRight Tags
     Url          Attribution InputEncoding    OutputEncoding
-    Language\r
-);\r
-\r
-__PACKAGE__->mk_accessors( qw( version ns ), map { lc } @columns );\r
-\r
-=head1 NAME\r
-\r
-WWW::OpenSearch::Description - Encapsulate an OpenSearch Description\r
-provided by an A9 OpenSearch compatible engine\r
-\r
-=head1 SYNOPSIS\r
-    \r
-    use WWW::OpenSearch;\r
-    \r
-    my $url = "http://bulkfeeds.net/opensearch.xml";\r
-    my $engine = WWW::OpenSearch->new($url);\r
-    my $description = $engine->description;\r
-    \r
-    my $format   = $description->Format;   # or $description->format\r
-    my $longname = $description->LongName; # or $description->longname\r
-    \r
-=head1 DESCRIPTION\r
-\r
-WWW::OpenSearch::Description is a module designed to encapsulate an\r
-OpenSearch Description provided by an A9 OpenSearch compatible engine.\r
-See http://opensearch.a9.com/spec/1.1/description/ for details.\r
-\r
-=head1 CONSTRUCTOR\r
-\r
-=head2 new( [ $xml ] )\r
-\r
-Constructs a new instance of WWW::OpenSearch::Description. If scalar\r
-parameter $xml is provided, data will be automatically loaded from it\r
-using load( $xml ).\r
-\r
-=head1 METHODS\r
-\r
-=head2 load( $xml )\r
-\r
+    Language
+);
+
+__PACKAGE__->mk_accessors( qw( version ns ), map { lc } @columns );
+
+=head1 NAME
+
+WWW::OpenSearch::Description - Encapsulate an OpenSearch Description
+provided by an A9 OpenSearch compatible engine
+
+=head1 SYNOPSIS
+    
+    use WWW::OpenSearch;
+    
+    my $url = "http://bulkfeeds.net/opensearch.xml";
+    my $engine = WWW::OpenSearch->new($url);
+    my $description = $engine->description;
+    
+    my $format   = $description->Format;   # or $description->format
+    my $longname = $description->LongName; # or $description->longname
+    
+=head1 DESCRIPTION
+
+WWW::OpenSearch::Description is a module designed to encapsulate an
+OpenSearch Description provided by an A9 OpenSearch compatible engine.
+See http://opensearch.a9.com/spec/1.1/description/ for details.
+
+=head1 CONSTRUCTOR
+
+=head2 new( [ $xml ] )
+
+Constructs a new instance of WWW::OpenSearch::Description. If scalar
+parameter $xml is provided, data will be automatically loaded from it
+using load( $xml ).
+
+=head1 METHODS
+
+=head2 load( $xml )
+
 Loads description data by parsing provided argument using XML::LibXML.
 
 =head2 urls( )
 
-Return all of the urls associated with this description in an array.\r
-\r
-=head2 get_best_url( )\r
-\r
-Attempts to retrieve the best URL associated with this description, based\r
-on the following content types (from most preferred to least preferred):\r
-\r
-=over 4\r
-\r
-=item * application/atom+xml\r
-\r
-=item * application/rss+xml\r
-\r
-=item * text/xml\r
-\r
-=back\r
-\r
-=head2 get_url_by_type( $type )\r
-\r
-Retrieves the first WWW::OpenSearch::URL associated with this description\r
-whose type is equal to $type.\r
-\r
-=head1 ACCESSORS\r
-\r
-=head2 version( )\r
-\r
-=head2 ns( )\r
-\r
-=head2 AdultContent( )\r
-\r
-=head2 Contact( )\r
-\r
-=head2 Description( )\r
-\r
-=head2 Developer( )\r
-\r
-=head2 Format( )\r
-\r
-=head2 Image( )\r
-\r
-=head2 LongName( )\r
-\r
-=head2 Query( )\r
-\r
-=head2 SampleSearch( )\r
-\r
-=head2 ShortName( )\r
-\r
-=head2 SyndicationRight( )\r
-\r
-=head2 Tags( )\r
-\r
-=head2 Url( )\r
-\r
-=head1 AUTHOR\r
-\r
-=over 4\r
-\r
-=item * Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt>\r
-\r
-=item * Brian Cassidy E<lt>bricas@cpan.orgE<gt>\r
-\r
-=back\r
-\r
-=head1 COPYRIGHT AND LICENSE\r
-\r
-Copyright 2006 by Tatsuhiko Miyagawa and Brian Cassidy\r
-\r
-This library is free software; you can redistribute it and/or modify\r
-it under the same terms as Perl itself. \r
-\r
-=cut\r
-\r
-for( @columns ) {\r
-    no strict 'refs';\r
-    my $col = lc;\r
-    *$_ = \&$col;\r
-}\r
-\r
-sub new {\r
-    my $class = shift;\r
-    my $xml   = shift;\r
-    \r
-    my $self  = $class->SUPER::new;\r
-    \r
-    eval{ $self->load( $xml ); } if $xml;\r
-    if( $@ ) {\r
-        croak "Error while parsing Description XML: $@";\r
-    }\r
-\r
-    return $self;\r
-}\r
-\r
-sub load {\r
-    my $self = shift;\r
-    my $xml  = shift;\r
-    \r
-    my $parser   = XML::LibXML->new;\r
-    my $doc      = $parser->parse_string( $xml );\r
-    my $element  = $doc->documentElement;\r
-    my $nodename = $element->nodeName;\r
-\r
-    croak "Node should be OpenSearchDescription: $nodename" if $nodename ne 'OpenSearchDescription';\r
-\r
-    my $ns = $element->getNamespace->value;\r
-    my $version;\r
-    if( $ns eq 'http://a9.com/-/spec/opensearch/1.1/' ) {\r
-        $self->ns( $ns );\r
-        $version = '1.1';\r
-    }\r
-    else {\r
-        $version = '1.0';\r
-    }\r
-    $self->version( $version );\r
-\r
-    for my $column ( @columns ) {\r
-        my $node = $doc->documentElement->getChildrenByTagName( $column ) or next;\r
-        if( $column eq 'Url' ) {\r
-            if( $version eq '1.0' ) {\r
-                $self->Url( [ WWW::OpenSearch::Url->new( template => $node->string_value, type => 'application/rss+xml' ) ] );\r
-                next;\r
-            }\r
-\r
-            my @url;\r
-            for my $urlnode ( $node->get_nodelist ) {\r
-                my $type = $urlnode->getAttributeNode( 'type' )->value;\r
-                my $url  = $urlnode->getAttributeNode( 'template' )->value;\r
-                $url =~ s/\?}/}/g; # optional\r
-                my $method = $urlnode->getAttributeNode( 'method' );\r
-                $method = $method->value if $method;\r
-
-                my %params;\r
-                for( $urlnode->getChildrenByTagName( 'Param' ) ) {\r
-                    my $param = $_->getAttributeNode( 'name' )->value;\r
+Return all of the urls associated with this description in an array.
+
+=head2 get_best_url( )
+
+Attempts to retrieve the best URL associated with this description, based
+on the following content types (from most preferred to least preferred):
+
+=over 4
+
+=item * application/atom+xml
+
+=item * application/rss+xml
+
+=item * text/xml
+
+=back
+
+=head2 get_url_by_type( $type )
+
+Retrieves the first WWW::OpenSearch::URL associated with this description
+whose type is equal to $type.
+
+=head1 ACCESSORS
+
+=head2 version( )
+
+=head2 ns( )
+
+=head2 AdultContent( )
+
+=head2 Contact( )
+
+=head2 Description( )
+
+=head2 Developer( )
+
+=head2 Format( )
+
+=head2 Image( )
+
+=head2 LongName( )
+
+=head2 Query( )
+
+=head2 SampleSearch( )
+
+=head2 ShortName( )
+
+=head2 SyndicationRight( )
+
+=head2 Tags( )
+
+=head2 Url( )
+
+=head1 AUTHOR
+
+=over 4
+
+=item * Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt>
+
+=item * Brian Cassidy E<lt>bricas@cpan.orgE<gt>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 by Tatsuhiko Miyagawa and Brian Cassidy
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself. 
+
+=cut
+
+for( @columns ) {
+    no strict 'refs';
+    my $col = lc;
+    *$_ = \&$col;
+}
+
+sub new {
+    my $class = shift;
+    my $xml   = shift;
+    
+    my $self  = $class->SUPER::new;
+    
+    eval{ $self->load( $xml ); } if $xml;
+    if( $@ ) {
+        croak "Error while parsing Description XML: $@";
+    }
+
+    return $self;
+}
+
+sub load {
+    my $self = shift;
+    my $xml  = shift;
+    
+    my $parser   = XML::LibXML->new;
+    my $doc      = $parser->parse_string( $xml );
+    my $element  = $doc->documentElement;
+    my $nodename = $element->nodeName;
+
+    croak "Node should be OpenSearchDescription: $nodename" if $nodename ne 'OpenSearchDescription';
+
+    my $ns = $element->getNamespace->value;
+    my $version;
+    if( $ns eq 'http://a9.com/-/spec/opensearchdescription/1.0/' ) {
+        $self->ns( 'http://a9.com/-/spec/opensearchrss/1.0/' );
+        $version = '1.0';
+    }
+    else {
+        $self->ns( $ns );
+        ( $version ) = $ns =~ m{([^/]+)/?$};
+    }
+    $self->version( $version );
+
+    for my $column ( @columns ) {
+        my $node = $doc->documentElement->getChildrenByTagName( $column ) or next;
+        if( $column eq 'Url' ) {
+            if( $version eq '1.0' ) {
+                $self->Url( [ WWW::OpenSearch::Url->new( template => $node->string_value, type => 'application/rss+xml', ns => $self->ns ) ] );
+                next;
+            }
+
+            my @url;
+            for my $urlnode ( $node->get_nodelist ) {
+                my $type = $urlnode->getAttributeNode( 'type' )->value;
+                my $url  = $urlnode->getAttributeNode( 'template' )->value;
+                $url =~ s/\?}/}/g; # optional
+                my $method = $urlnode->getAttributeNode( 'method' );
+                $method = $method->value if $method;
+
+                my %params;
+                for( $urlnode->getChildrenByTagName( 'Param' ) ) {
+                    my $param = $_->getAttributeNode( 'name' )->value;
                     my $value = $_->getAttributeNode( 'value' )->value;
-                    $value    =~ s/\?}/}/g; # optional\r
-                    $params{ $param } = $value;\r
-                }\r
-\r
-                push @url, WWW::OpenSearch::Url->new( template => $url, type => $type, method => $method, params => \%params );\r
-            }\r
-            $self->Url( \@url );\r
-        }\r
-        elsif( $version eq '1.1' and $column eq 'Query' ) {\r
-            my $query = ( $node->get_nodelist )[ 0 ];\r
-            next if $query->getAttributeNode( 'role' )->value eq 'example';\r
-            $self->SampleSearch( $query->getAttributeNode( 'searchTerms' )->value );\r
-        }\r
-        elsif( $version eq '1.0' and $column eq 'Format' ) {\r
-            $self->Format( $node->string_value );\r
-            $self->ns( $self->Format );\r
-        }\r
-        else {\r
-            $self->$column( $node->string_value );\r
-        }\r
-    }\r
-}\r
-\r
-sub get_best_url {\r
-    my $self = shift;\r
-    \r
-    return $self->get_url_by_type( 'application/atom+xml' )\r
-        || $self->get_url_by_type( 'application/rss+xml' )\r
-        || $self->get_url_by_type( 'text/xml' )\r
-        || $self->url->[ 0 ];\r
-}\r
-\r
-sub get_url_by_type {\r
-    my $self = shift;\r
-    my $type = shift;\r
-    \r
-    my $template;\r
-    for( $self->urls ) {\r
-        $template = $_ if $_->type eq $type;\r
-        last;\r
-    };\r
-    \r
-    return $template;\r
-}\r
+                    $value    =~ s/\?}/}/g; # optional
+                    $params{ $param } = $value;
+                }
+
+                push @url, WWW::OpenSearch::Url->new( template => $url, type => $type, method => $method, params => \%params, ns => $self->ns );
+            }
+            $self->Url( \@url );
+        }
+        elsif( $version eq '1.1' and $column eq 'Query' ) {
+            my $queries = $self->query || [];
+
+            for my $node ( $node->get_nodelist ) {
+                my $query = WWW::OpenSearch::Query->new( {
+                    map { $_ => $node->getAttributeNode( $_ )->value } qw( role searchTerms )
+                } );
+
+                push @$queries, $query;
+            }
+
+            $self->query( $queries );
+        }
+        elsif( $version eq '1.1' and $column eq 'Image' ) {
+            my $images = $self->image || [];
+
+            for my $node ( $node->get_nodelist ) {
+                my $image = WWW::OpenSearch::Image->new( {
+                    ( map { my $attr = $node->getAttributeNode( $_ ); $attr ? ($_ => $attr->value) : () } qw( height width type ) ),
+                    url => $node->string_value
+                } );
+
+                push @$images, $image;
+            }
+
+            $self->image( $images );
+        }
+        else {
+            $self->$column( $node->string_value );
+        }
+    }
+}
+
+sub get_best_url {
+    my $self = shift;
+    
+    return $self->get_url_by_type( 'application/atom+xml' )
+        || $self->get_url_by_type( 'application/rss+xml' )
+        || $self->get_url_by_type( 'text/xml' )
+        || $self->url->[ 0 ];
+}
+
+sub get_url_by_type {
+    my $self = shift;
+    my $type = shift;
+    
+    for( $self->urls ) {
+        return $_ if $_->type eq $type;
+    };
+    
+    return;
+}
 
 sub urls {
     my $self = shift;
     return @{ $self->url };
 }
-\r
-1;\r
+
+1;