Merge branch 'master' into topic/parent_string
[cxgn-corelibs.git] / lib / MOBY / Client / CollectionArticle.pm
blobd443a1c11aea085ddc982dc6d79f1c9b8119acab
1 package MOBY::Client::CollectionArticle;
2 use strict;
3 use Carp;
4 use XML::LibXML;
5 use MOBY::MobyXMLConstants;
6 use vars qw($AUTOLOAD @ISA);
7 use MOBY::Client::SimpleArticle;
9 =head1 NAME
11 MOBY::Client::CollectionArticle - a small object describing the
12 Collection articles from the findService Response message of MOBY
13 Central or representing the collection part of a MOBY invocation or
14 response block
16 =head1 SYNOPSIS
18 This module can be used in two ways. One is to represent the Collection
19 portion of a findService response. The other is to represent the Collecion
20 portion of a MOBY service invocation or response message.
22 Parsing a MOBY Service Invocation
24 use MOBY::CommonSubs qw(:all);
26 sub myService {
27 my ($caller, $data) = @_;
29 my (@inputs)= serviceInputParser($data);
31 foreach (@inputs){
32 my ($articleType, $qID, $OBJECT) = @{$_};
33 if ($articleType == COLLECTION){
34 $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; # send back a blank response for this queryID
35 next;
36 } elsif ($articleType == SIMPLE) {
38 } elsif ($articleType == SECONDARY){
45 =head1 DESCRIPTION
47 This describes the Collection articles from either the findService Response of MOBY Central
48 (i.e. the description of the service), or Collection articles
49 as provided in a service invocation or response message
50 (i.e. simple articles containing data)
52 Basically it parses the following part of a findService response:
54 <Collection articleName="foo">
55 <Simple>
56 <objectType>someNbject</objectType>
57 <Namespace>someNamespace</Namespace>
58 <Namespace>someNamespace2</Namespace>
59 </Simple>
60 <Simple>
61 <objectType>someNbject</objectType>
62 <Namespace>someNamespace</Namespace>
63 <Namespace>someNamespace2</Namespace>
64 </Simple>
65 </Collection>
67 OR it parses the following part of a service invocation or response message:
69 <Collection articleName="foo">
70 <Simple>
71 <SomeObject namespace='someNamespace' id='someID'>.....</SomeObject>
72 </Simple>
73 <Simple>
74 <SomeObject namespace='someNamespace' id='someID'>.....</SomeObject>
75 </Simple>
76 </Collection>
79 The articleName is retrieved with ->articleName
80 The contained Simples are retrieved as MOBY::Client::SimpleArticle objects
81 using the ->Simples method call.
84 =head1 AUTHORS
86 Mark Wilkinson (markw at illuminae dot com)
88 =head1 METHODS
91 =head2 new
93 Usage : my $IN = MOBY::Client::CollectionArticle->new(%args)
94 Function : create CollectionArticle object
95 Returns : MOBY::Client::SimpleArticle object
96 Args : either of the following two methods may be used to auto-generate the
97 object by passing the appropriate XML node as a string, or XML::DOM node object
99 XML => $XML
100 XML_DOM => $XML::DOM::NODE
102 =head2 articleName
104 Usage : $name = $IN->articleName($name)
105 Function : get/set articleName
106 Returns : string
107 Arguments : (optional) string to set articleName
109 =head2 Simples
111 Usage : $type = $IN->Simples(\@SimpleArticles)
112 Function : get/set name
113 Returns : arrayRef of MOBY::Client::SimpleArticle's in this collection
114 Arguments : (optional) arrayRef of MOBY::Client::SimpleArticle's in this collection
116 =head2 addSimple
118 Usage : $namespaces = $IN->addNamespace($SimpleArticle)
119 Function : add another SimpleArticle
120 Returns : arrayref of MOBY::Client::SimpleArticle's or 0 if argument
121 was not a MOBY::Client::SimpleArticle (or other failure)
122 Arguments : a new MOBY::Client::SimpleArticle to add to collection
124 =head2 XML
126 Usage : $SA = $SA->XML($XML)
127 Function : set/reset all parameters for this object from the XML
128 Returns : MOBY::Client::SimpleArticle
129 Arguments : (optional) XML fragment from and including <Simple>...</Simple>
131 =head2 XML_DOM
133 Usage : $namespaces = $SA->XML_DOM($XML_DOM_NODE)
134 Function : set/reset all parameters for this object from the XML::DOM node for <Simple>
135 Returns : MOBY::Client::SimpleArticle
136 Arguments : (optional) an $XML::DOM node from the <Simple> article of a DOM
138 =head2 isSimple
140 Usage : $boolean = $IN->isSimple()
141 Function : is this a SimpleArticle type
142 (yes, I know this is obvious, but since you can
143 get both Simple and Collection objects in your
144 Input and output lists, it is good to be able
145 to test what you have in-hand)
146 Returns : 0 (false)
148 =head2 isCollection
150 Usage : $boolean = $IN->isCollection()
151 Function : is this a CollectionArticle type
152 (yes, I know this is obvious, but since you can
153 get both Simple and Collection objects in your
154 Input and output lists, it is good to be able
155 to test what you have in-hand)
156 Returns : 1 (true)
158 =head2 isSecondary
160 Usage : $boolean = $IN->isSecondary()
161 Function : is this a SecondaryArticle type?
162 (yes, I know this is obvious)
163 Returns : 0 (true)
165 =cut
169 # Encapsulated:
170 # DATA
171 #___________________________________________________________
172 #ATTRIBUTES
173 my %_attr_data = # DEFAULT ACCESSIBILITY
175 articleName => [ undef, 'read/write' ],
176 Simples => [ [], 'read/write' ],
177 isSimple => [ 0, 'read' ],
178 isSecondary => [ 0, 'read' ],
179 isCollection => [ 1, 'read' ],
180 XML => [ undef, 'read/write' ],
181 XML_DOM => [ undef, 'read/write' ],
184 #_____________________________________________________________
185 # METHODS, to operate on encapsulated class data
186 # Is a specified object attribute accessible in a given mode
187 sub _accessible {
188 my ( $self, $attr, $mode ) = @_;
189 $_attr_data{$attr}[1] =~ /$mode/;
192 # Classwide default value for a specified object attribute
193 sub _default_for {
194 my ( $self, $attr ) = @_;
195 $_attr_data{$attr}[0];
198 # List of names of all specified object attributes
199 sub _standard_keys {
200 keys %_attr_data;
203 sub addSimple {
204 my ( $self, $s ) = @_;
205 return $self->{Simples} unless $s;
206 return 0 unless $s->isa( "MOBY::Client::SimpleArticle" );
207 push @{ $self->{Simples} }, $s;
208 return $self->{Simples};
212 sub new {
213 my ( $caller, %args ) = @_;
214 my $caller_is_obj = ref( $caller );
215 return $caller if $caller_is_obj;
216 my $class = $caller_is_obj || $caller;
217 my $proxy;
218 my $self = bless {}, $class;
219 foreach my $attrname ( $self->_standard_keys ) {
220 if ( exists $args{$attrname} ) {
221 $self->{$attrname} = $args{$attrname};
222 } elsif ( $caller_is_obj ) {
223 $self->{$attrname} = $caller->{$attrname};
224 } else {
225 $self->{$attrname} = $self->_default_for( $attrname );
228 if ( $self->XML && ref( $self->XML ) ) {
229 return 0;
230 } elsif ( $self->XML_DOM && !( ref( $self->XML_DOM ) =~ /libxml/i ) ) {
231 return 0;
233 $self->createFromXML if ( $self->XML );
234 $self->createFromDOM( $self->XML_DOM ) if ( $self->XML_DOM );
235 return $self;
238 sub createFromXML {
239 my ( $self ) = @_;
240 my $p = XML::LibXML->new;
241 my $doc = $p->parse_string( $self->XML );
242 my $root = $doc->getDocumentElement;
243 return 0 unless ( $root && ( $root->nodeName eq "Collection" ) );
244 return $self->createFromDOM( $root );
247 sub createFromDOM {
248 my ( $self, $dom ) = @_;
249 return 0 unless ( $dom && ( $dom->nodeName eq "Collection" ) );
250 $self->XML( $dom->toString ); # set the string version of the DOM
251 $self->articleName( "" );
252 $self->Simples( [] );
253 my $attr = $dom->getAttributeNode( 'articleName' );
254 my $articleName = "";
255 $articleName = $attr->getValue if $attr;
256 $self->articleName( $articleName );
257 my $objects = $dom->getElementsByTagName( "Simple" );
259 for my $n ( 1 .. $objects->size ) {
260 $self->addSimple(
261 MOBY::Client::SimpleArticle->new(
262 articleName => $self->articleName,
263 XML_DOM => $objects->get_node( $n )
267 return $self;
270 sub AUTOLOAD {
271 no strict "refs";
272 my ( $self, $newval ) = @_;
273 $AUTOLOAD =~ /.*::(\w+)/;
274 my $attr = $1;
275 if ( $self->_accessible( $attr, 'write' ) ) {
276 *{$AUTOLOAD} = sub {
277 if ( defined $_[1] ) { $_[0]->{$attr} = $_[1] }
278 return $_[0]->{$attr};
279 }; ### end of created subroutine
280 ### this is called first time only
281 if ( defined $newval ) {
282 $self->{$attr} = $newval;
284 return $self->{$attr};
285 } elsif ( $self->_accessible( $attr, 'read' ) ) {
286 *{$AUTOLOAD} = sub {
287 return $_[0]->{$attr};
288 }; ### end of created subroutine
289 return $self->{$attr};
292 # Must have been a mistake then...
293 croak "No such method: $AUTOLOAD";
295 sub DESTROY { }