[MOBY-guts] biomoby commit
Mark Wilkinson
mwilkinson at dev.open-bio.org
Thu Feb 8 23:03:45 UTC 2007
mwilkinson
Thu Feb 8 18:03:45 EST 2007
Update of /home/repository/moby/moby-live/Perl/MOBY
In directory dev.open-bio.org:/tmp/cvs-serv31321/MOBY
Modified Files:
CommonSubs.pm
Log Message:
significant updates to CommonSubs. Revamp of documentation to reveal client-side functionality that hasnt been discussed anywhere else. Added a new function (just a renamed reference to an old function) to show that the server-side parser can also be used client-side for parsing a MOBY message. rearranged order of functions in documentation to make more sense.
moby-live/Perl/MOBY CommonSubs.pm,1.93,1.94
===================================================================
RCS file: /home/repository/moby/moby-live/Perl/MOBY/CommonSubs.pm,v
retrieving revision 1.93
retrieving revision 1.94
diff -u -r1.93 -r1.94
--- /home/repository/moby/moby-live/Perl/MOBY/CommonSubs.pm 2007/01/30 22:50:52 1.93
+++ /home/repository/moby/moby-live/Perl/MOBY/CommonSubs.pm 2007/02/08 23:03:45 1.94
@@ -23,11 +23,58 @@
FUNCTION WITH SERVICES THAT ARE NOT COMPLIANT WITH THE NEW API - FOR EXAMPLE
SERVICES THAT ARE NOT USING NAMED INPUTS AND OUTPUTS!
-=head1 PARADIGMATIC USAGE
+=head1 COMMON USAGE EXAMPLES
=head2 Client Side Paradigm
-not written yet
+
+The following is a generalized architecture for all
+BioMOBY services showing how to parse response messages
+using the subroutines provided in CommonSubs
+
+=head3 Services Returning Simples
+
+ my $resp = $SI->execute(XMLInputList => \@input_data);
+
+ my $responses = serviceResponseParser($resp); # returns MOBY objects
+ foreach my $queryID(keys %$responses){
+ $this_invocation = $inputs->{$queryID}; # this is the <mobyData> block with this queryID
+ my $this_output = "";
+
+ if (my $data = $this_invocation->{'responseArticleName'}){
+ # $data is a MOBY::Client::Simple|Collection|ParameterArticle
+ my ($namespace) = @{$data->namespaces};
+ my $id = $data->id;
+ my $XML_LibXML = $input->XML_DOM; # get access to the DOM
+ my $desc = getNodeContentWithArticle($XML_LibXML, "String", "Description");
+ ###################
+ # DO SOMETHING TO RESPOSE DATA HERE
+ ###################
+ }
+
+ }
+
+
+=head3 Services Returning Collections
+
+ my $resp = $SI->execute(XMLInputList => \@input_data);
+
+ my $responses = serviceResponseParser($resp); # returns MOBY objects
+ foreach my $queryID(keys %$responses){ # $inputs is a hashref of $input{queryid}->{articlename} = input object
+ my $this_invocation = $inputs->{$queryID};
+ if (my $data = $this_invocation->{'responseArticleName'}){ # $input is a MOBY::Client::Simple|Collection|Parameter object
+ my $simples = $data->Simples;
+ foreach my $simple(@$simples){
+ my $id = $simple->id;
+ my $id = $simple->namespace;
+ my $XML_LibXML = $input->XML_DOM; # get access to the DOM
+
+ }
+ }
+ }
+
+
+
=head2 Service-Side Paradigm
@@ -35,7 +82,7 @@
BioMOBY services showing how to parse incoming messages
using the subroutines provided in CommonSubs
-=head3 SIMPLE SERVICES
+=head3 Services Generating simple outputs
sub _generic_service_name {
my ($caller, $data) = @_;
@@ -68,7 +115,7 @@
return SOAP::Data->type('base64' => (responseHeader("illuminae.com") . $MOBY_RESPONSE . responseFooter));
}
-=head3 COLLECTION SERVICES
+=head3 Services generating collection outputs
sub _generic_service_returning_collections {
my($caller, $message) = @_;
@@ -169,12 +216,6 @@
}
-=head1 AUTHORS
-
-Mark Wilkinson (markw at illuminae dot com), Pieter Neerincx, Frank Gibbons
-
-BioMOBY Project: http://www.biomoby.org
-
=cut
package MOBY::CommonSubs;
@@ -243,32 +284,38 @@
our @EXPORT_OK = (@{$EXPORT_TAGS{'all'}});
-=head1 PARSING MOBY SERVICE INVOCATIONS
+=head1 PARSING MOBY INPUT AND OUTPUT
-=head2 serviceInputParser
+=head2 serviceInputParser and serviceResponseParser
-B<function:> This routine will take a MOBY service invocation
-message and extract the Simple/Collection/Parameter objects out of it
+B<function:> These routines will take a Moby invocation (server side usage) or
+response (client-side usage) and extract the Simple/Collection/Parameter objects out of it
as MOBY::Client::SimpleArticle, MOBY::Client::CollectionArticle,
and/or MOBY::Client::SecondaryArticle objects. The inputs are broken
-up into individual queryID's (invocations). Each queryID is associated with
-one or more individual input articles that are required to invoke that service, and
-each input article is available by its articleName.
+up into individual queryID's. Each queryID is associated with
+one or more individual articles, and each article is available by its articleName.
-B<usage:> C<my $inputs = serviceInputParser($MOBY_mssage));>
+B<usage:> C<my $inputs = serviceInputParser($MOBY_invocation_mssage));>
+B<usage:> C<my $outputs = serviceResponseParser($MOBY_response_message));>
B<args:> C<$message> - this is the SOAP payload; i.e. the XML document containing the MOBY message
-B<returns:> C<$inputs> is a hashref with the following structure:
+B<returns:> C<$inputs> or C<$outputs> are a hashref with the following structure:
- $inputs->{$queryID}->{articleName} =
+ $Xputs->{$queryID}->{articleName} =
MOBY::Client::SimpleArticle |
MOBY::Client::CollectionArticle |
MOBY::Client::SecondaryArticle
-See also:
+the SimpleArticle and CollectionArticle have methods to provide you with their
+objectType, their namespace and their ID. If you want to get more out of them,
+you should retrieve the XML::LibXML DOM using the ->XML_DOM method call
+in either of those objects. This can be passed into other CommonSubs routines
+such as getNodeContentWithArticle in order to retrieve sub-components of the
+Moby object you have in-hand.
+See also:
=head3 Simples
@@ -289,8 +336,7 @@
$inputs->{a1a}->{cutoff} = $MOBY::Client::Secondary # <Parameter> block
-
-=head3 Collections
+=head3 Collections
With inputs that have collections these are presented as a listref of
Simple article DOM's. So for the following message:
@@ -311,8 +357,8 @@
will become
- $inputs->{2b2}->{name1} $MOBY::Client::Collection, # the <Collection> Block
- $inputs->{2b2}->{cutoff} $MOBY::Client::Secondary, # the <Parameter> Block
+ $inputs->{2b2}->{name1} = $MOBY::Client::Collection, # the <Collection> Block
+ $inputs->{2b2}->{cutoff} = $MOBY::Client::Secondary, # the <Parameter> Block
@@ -322,11 +368,11 @@
sub serviceInputParser {
my ( $message ) = @_; # get the incoming MOBY query XML
my @inputs; # set empty response
- my @queries = getInputs( $message ); # returns XML::LibXML nodes <mobyData>...</mobyData>
+ my @queries = _getInputs( $message ); # returns XML::LibXML nodes <mobyData>...</mobyData>
my %input_parameters; # $input_parameters{$queryID} = [
foreach my $query ( @queries ) {
- my $queryID = getInputID( $query ); # get the queryID attribute of the mobyData
- my @input_articles = getArticlesAsObjects( $query );
+ my $queryID = _getQID( $query ); # get the queryID attribute of the mobyData
+ my @input_articles = _getArticlesAsObjects( $query );
foreach my $article ( @input_articles ) {
${$input_parameters{$queryID}}{$article->articleName} = $article;
}
@@ -334,7 +380,58 @@
return \%input_parameters;
}
+*serviceResponseParser = \&serviceInputParser;
+*serviceResponseParser = \&serviceInputParser;
+
+sub _getInputs {
+ my ( $XML ) = @_;
+ my $moby = _string_to_DOM($XML);
+ my @queries;
+ foreach my $querytag qw(mobyData moby:mobyData )
+ {
+ my $x = $moby->getElementsByTagName( $querytag ); # get the mobyData block
+ for ( 1 .. $x->size() ) { # there may be more than one mobyData per message
+ push @queries, $x->get_node( $_ );
+ }
+ }
+ return @queries; # return them in the order that they were discovered.
+}
+
+
+sub _getArticlesAsObjects {
+ my ( $moby ) = @_;
+ $moby = _string_to_DOM($moby);
+ return undef unless $moby->nodeType == ELEMENT_NODE;
+ return undef
+ unless ($moby->nodeName =~ /^(moby:|)mobyData$/);
+ my @articles;
+ foreach my $child ( $moby->childNodes )
+ { # there may be more than one Simple/Collection per input; iterate over them
+ next unless $child->nodeType == ELEMENT_NODE; # ignore whitespace
+ next
+ unless ( $child->nodeName =~ /^(moby:|)(Simple|Collection|Parameter)$/ );
+ my $object;
+ if ( $child->nodeName =~ /^(moby:|)Simple$/ ) {
+ $object = MOBY::Client::SimpleArticle->new( XML_DOM => $child );
+ } elsif ( $child->nodeName =~ /^(moby:|)Collection$/ ) {
+ $object = MOBY::Client::CollectionArticle->new( XML_DOM => $child );
+ } elsif ( $child->nodeName =~ /^(moby:|)Parameter$/ ) {
+ $object = MOBY::Client::SecondaryArticle->new( XML_DOM => $child );
+ }
+ next unless $object;
+ push @articles, $object; # take the child elements, which are <Simple/> or <Collection/>
+ }
+ return @articles; # return them.
+}
+
+sub _getQID {
+ my ( $XML ) = @_;
+ my $moby = _string_to_DOM($XML);
+ return '' unless ( $moby->nodeName =~ /^(moby:|)mobyData$/ );
+ my $qid = _moby_getAttribute($moby, 'queryID' );
+ return defined( $qid ) ? $qid : '';
+}
=head1 MESSAGE COMPONENT IDENTITY AND VALIDATION
@@ -735,6 +832,65 @@
}
+=head1 Client-Side Common Subroutines
+
+These are the subroutines that will be most commonly used Client-Side for
+processing the output of a MOBY service
+
+=head2 processResponse
+
+=cut
+
+sub processResponse {
+ my ( $result ) = @_;
+ return ( [], [] ) unless $result;
+ my $moby;
+ unless ( ref( $result ) =~ /XML\:\:LibXML/ ) {
+ my $parser = XML::LibXML->new();
+ my $doc = $parser->parse_string( $result );
+ $moby = $doc->getDocumentElement();
+ } else {
+ $moby = $result->getDocumentElement();
+ }
+ my @objects;
+ my @collections;
+ my @Xrefs;
+ my $success = 0;
+ foreach my $which ('mobyData', 'moby:mobyData') {
+ my $responses = $moby->getElementsByTagName( $which );
+ next unless $responses;
+ foreach my $n ( 1 .. ( $responses->size() ) ) {
+ my $resp = $responses->get_node( $n );
+ foreach my $response_component ( $resp->childNodes ) {
+ next unless $response_component->nodeType == ELEMENT_NODE;
+ if ( $response_component->nodeName =~ /^(moby:|)Simple$/ )
+ {
+ foreach my $Object ( $response_component->childNodes ) {
+ next unless $Object->nodeType == ELEMENT_NODE;
+ $success = 1;
+ push @objects, $Object;
+ }
+ } elsif ( $response_component->nodeName =~ /^(moby:|)Collection$/ )
+ {
+ my @objects;
+ foreach my $simple ( $response_component->childNodes ) {
+ next unless $simple->nodeType == ELEMENT_NODE;
+ next unless ( $simple->nodeName =~ /^(moby:|)Simple$/ );
+ foreach my $Object ( $simple->childNodes ) {
+ next unless $Object->nodeType == ELEMENT_NODE;
+ $success = 1;
+ push @objects, $Object;
+ }
+ }
+ push @collections, \@objects
+ ; #I'm not using collections yet, so we just use Simples.
+ }
+ }
+ }
+ }
+ return ( \@collections, \@objects );
+}
+
=head1 ANCILIARY ELEMENTS
@@ -879,16 +1035,13 @@
}
-=head1 MISCELLANEOUS
+=head1 MISCELLANEOUS FUNCTIONS
This section contains routines that didn't quite seem to fit anywhere else.
-=cut
-
-
=head2 getNodeContentWithArticle
-<B><function:> give me a DOM, a TagName, an articleName and I will return you the content
+B<function:> give me a DOM, a TagName, an articleName and I will return you the content
of that node **as a string** (beware if there are additional XML tags in there!)
this is meant for MOBYesque PRIMITIVES - things like:
<String articleName="SequenceString">TAGCTGATCGAGCTGATGCTGA </String>
@@ -1032,24 +1185,21 @@
}
-
-=head2 _moby_getAttributeNode, _moby_getAttribute
-
-B<function:> Perform the same task as the DOM routine
-getAttribute(Node), but check for both the prefixed and un-prefixed
-attribute name (the prefix in question being, of course,
-"moby:").
-
-B<usage:>
-
- $id = _moby_getAttribute($xml_libxml, "id");
-
-where C<id> is an attribute in the XML block given as C<$xml_libxml>
-
-B<notes:> This function is intended for use internal to this package
-only. It's not exported.
-
-=cut
+#B<function:> Perform the same task as the DOM routine
+#getAttribute(Node), but check for both the prefixed and un-prefixed
+#attribute name (the prefix in question being, of course,
+#"moby:").
+#
+#B<usage:>
+#
+# $id = _moby_getAttribute($xml_libxml, "id");
+#
+#where C<id> is an attribute in the XML block given as C<$xml_libxml>
+#
+#B<notes:> This function is intended for use internal to this package
+#only. It's not exported.
+#
+#=cut
sub _moby_getAttributeNode {
# Mimics behavior of XML::LibXML method getAttributeNode, but if the unqualified attribute cannot be found,
@@ -1214,11 +1364,30 @@
sub _getQueryID {
my ( $query ) = @_;
$query = _string_to_XML($query);
- return '' unless ( $query->nodeName =~ /^(moby:|)(queryInput|mobyData)$/ ); #Eddie - unsure
+ return '' unless ( $query->nodeName =~ /^(moby:|)mobyData$/ ); #Eddie - unsure
return _moby_getAttribute($query, 'queryID' );
}
-=head1 DEPRECATED
+
+sub _string_to_DOM {
+# Convert string to DOM.
+# If DOM passed in, just return it (i.e., this should be idempotent)
+# By Frank Gibbons, Aug. 2005
+# Utility subroutine, not for external use (no export), widely used in this package.
+ my $XML = shift;
+ my $moby;
+ return $XML if ( ref($XML) =~ /^XML\:\:LibXML/ );
+
+ my $parser = XML::LibXML->new();
+ my $doc;
+ eval { $doc = $parser->parse_string( $XML ) };
+ die("CommonSubs couldn't parse XML '$XML' because\n\t$@") if $@;
+ return $doc->getDocumentElement();
+}
+
+
+
+=head1 DEPRECATED FUNCTIONS
=head2 genericServiceInputParser
@@ -1228,6 +1397,7 @@
=cut
sub genericServiceInputParser {
+print STDERR "the genericServiceInputParser function of MOBY::CommonSubs is deprecated. Please see documentation\n";
my ( $message ) = @_; # get the incoming MOBY query XML
my @inputs; # set empty response
my @queries = getInputs( $message ); # returns XML::LibXML nodes <mobyData>...</mobyData>
@@ -1259,6 +1429,7 @@
=cut
sub complexServiceInputParser {
+print STDERR "the complexServiceInputParser function of MOBY::CommonSubs is deprecated. Please see documentation\n";
my ( $message ) = @_; # get the incoming MOBY query XML
my @inputs; # set empty response
my @queries = getInputs( $message ); # returns XML::LibXML nodes <mobyData>...</mobyData>
@@ -1291,6 +1462,7 @@
=cut
sub getArticles {
+print STDERR "the getArticles function of MOBY::CommonSubs is deprecated. Please see documentation\n";
my ( $moby ) = @_;
$moby = _string_to_DOM($moby);
return undef
@@ -1316,6 +1488,7 @@
sub getSimpleArticleIDs {
+print STDERR "the getSimpleArticleIDs function of MOBY::CommonSubs is deprecated. Please see documentation\n";
my ( $desired_namespace, $input_nodes ) = @_;
if ( $desired_namespace && !$input_nodes )
{ # if called with ONE argument, then these are the input nodes!
@@ -1390,6 +1563,7 @@
sub getSimpleArticleNamespaceURI {
+print STDERR "the getSimpleArticleNamespaceURI function of MOBY::CommonSubs is deprecated. Please see documentation\n";
# pass me a <SIMPLE> input node and I will give you the lsid of the namespace of that input object
my ( $input_node ) = @_;
@@ -1410,21 +1584,6 @@
}
}
-sub _string_to_DOM {
-# Convert string to DOM.
-# If DOM passed in, just return it (i.e., this should be idempotent)
-# By Frank Gibbons, Aug. 2005
-# Utility subroutine, not for external use (no export), widely used in this package.
- my $XML = shift;
- my $moby;
- return $XML if ( ref($XML) =~ /^XML\:\:LibXML/ );
-
- my $parser = XML::LibXML->new();
- my $doc;
- eval { $doc = $parser->parse_string( $XML ) };
- die("CommonSubs couldn't parse XML '$XML' because\n\t$@") if $@;
- return $doc->getDocumentElement();
-}
=head2 getInputs
@@ -1433,6 +1592,7 @@
=cut
sub getInputs {
+ print STDERR "getInputs is now deprecated. Please update your code to use the serviceInputParser\n";
my ( $XML ) = @_;
my $moby = _string_to_DOM($XML);
my @queries;
@@ -1453,6 +1613,7 @@
=cut
sub getInputID {
+ print STDERR "getInputID method is now deprecated. Please use serviceInputParser or serviceResponseParser\n";
my ( $XML ) = @_;
my $moby = _string_to_DOM($XML);
return '' unless ( $moby->nodeName =~ /^(moby:|)queryInput|mobyData$/ );
@@ -1467,6 +1628,7 @@
=cut
sub getArticlesAsObjects {
+ print STDERR "getArticlesAsObjects is now deprecated. Please use the serviceInputParser";
my ( $moby ) = @_;
$moby = _string_to_DOM($moby);
return undef unless $moby->nodeType == ELEMENT_NODE;
@@ -1499,6 +1661,7 @@
=cut
sub getCollectedSimples {
+print STDERR "the getCollectedSimples function of MOBY::CommonSubs is deprecated. Please see documentation\n";
my ( $moby ) = @_;
$moby = _string_to_DOM($moby);
return undef unless $moby->nodeType == ELEMENT_NODE;
@@ -1520,6 +1683,8 @@
=cut
sub getInputArticles {
+print STDERR "the getInputArticles function of MOBY::CommonSubs is deprecated. Please see documentation\n";
+
my ( $moby ) = @_;
$moby = _string_to_DOM($moby);
my $x;
@@ -1548,6 +1713,7 @@
=cut
sub extractRawContent {
+print STDERR "the extractRawContent function of MOBY::CommonSubs is deprecated. Please see documentation\n";
my ( $article ) = @_;
return "" unless ( $article || (ref( $article ) =~ /XML\:\:LibXML/) );
my $response;
@@ -1569,6 +1735,7 @@
=cut
sub extractResponseArticles {
+print STDERR "the extractResponseArticles function of MOBY::CommonSubs is deprecated. Please see documentation\n";
my ( $result ) = @_;
return ( [], [] ) unless $result;
my $moby;
@@ -1620,6 +1787,14 @@
return ( \@collections, \@objects );
}
+
+=head1 AUTHORS
+
+Mark Wilkinson (markw at illuminae dot com), Pieter Neerincx, Frank Gibbons
+
+BioMOBY Project: http://www.biomoby.org
+
+
=head1 SEE ALSO
More information about the MOBY-guts
mailing list