fixed recursive_children cvterm function, and added tests for parents and children
[cxgn-corelibs.git] / lib / MOBY / service_instance.pm
blob153ae4c71c23c67fbda83f262d7d7cfce0fd4a1c
1 package MOBY::service_instance;
2 use SOAP::Lite;
3 use strict;
4 use Carp;
5 use vars qw($AUTOLOAD @ISA);
6 use MOBY::central_db_connection;
7 use MOBY::OntologyServer;
8 use MOBY::authority;
9 use MOBY::Config;
11 #@ISA = qw(MOBY::central_db_connection); # can't do this yet...
13 =head1 NAME
15 MOBY::service_instance - a lightweight connection to the
16 service_instance table in the database
18 =head1 SYNOPSIS
20 use MOBY::service_instance;
21 my $Instance = MOBY::service_instance->new(
22 authority => $AUTHORITY,
23 servicename => 'marksFabulousService',
24 service_type => $SERVICE_TYPE,
25 category => 'moby',
26 url => "http://www.illuminae.com/mobyservice.pl",
27 contact_email => "markw@illuminae.com",
28 authoritative => 1,
29 inputs => \@inputs,
30 output => \@outputs,
31 description => 'retrieves random sequences from a database');
33 print $Instance->service_instance_id;
34 print $Instance->authority->authority_common_name;
37 =cut
39 =head1 DESCRIPTION
41 representation of the service_instance table. Can write to the database
43 =head1 AUTHORS
45 Mark Wilkinson (mwilkinson@mrl.ubc.ca)
48 =cut
52 # Encapsulated:
53 # DATA
54 #___________________________________________________________
55 #ATTRIBUTES
56 my %_attr_data = # DEFAULT ACCESSIBILITY
58 service_instance_id => [ undef, 'read/write' ],
59 category => [ undef, 'read/write' ],
60 servicename => [ undef, 'read/write' ],
61 _authority => [ undef, 'read/write' ], # the authority object
62 service_type => [ undef, 'read/write' ],
63 service_type_uri => [ undef, 'read/write' ],
64 authority => [ undef, 'read/write' ],
65 authority_uri => [ undef, 'read/write' ],
66 signatureURL => [ undef, 'read/write' ],
67 url => [ undef, 'read/write' ],
68 inputs => [ undef, 'read/write' ],
69 outputs => [ undef, 'read/write' ],
70 secondaries => [ undef, 'read/write' ],
71 contact_email => [ undef, 'read/write' ],
72 authoritative => [ 0, 'read/write' ],
73 description => [ undef, 'read/write' ],
74 registry => [ 'MOBY_Central', 'read/write' ],
75 lsid => [ undef, 'read/write' ],
76 test => [ 0, 'read/write' ]
77 , # toggles create or test_existence behaviour
80 #_____________________________________________________________
81 # METHODS, to operate on encapsulated class data
82 # Is a specified object attribute accessible in a given mode
83 sub _accessible {
84 my ( $self, $attr, $mode ) = @_;
85 $_attr_data{$attr}[1] =~ /$mode/;
88 # Classwide default value for a specified object attribute
89 sub _default_for {
90 my ( $self, $attr ) = @_;
91 $_attr_data{$attr}[0];
94 # List of names of all specified object attributes
95 sub _standard_keys {
96 keys %_attr_data;
99 sub service_name
100 { # give them a break if they chose service_name or servicename as the parameter
101 my ( $self, $val ) = @_;
102 if ( defined $val ) {
103 if ( defined $self->{servicename} ) {
104 return
105 undef # you are not allowed to change it once it has been set!
106 } else {
107 $self->{servicename} = $val;
110 return $self->{servicename};
113 sub category {
114 my ( $self, $val ) = @_;
115 if ( ( defined $val ) && $self->category ) { return undef }
116 ( defined $val ) && ( $self->{category} = $val );
117 return $self->{category};
120 sub service_type {
121 my ( $self, $val ) = @_;
122 if ( defined $val && $self->service_type ) { return undef }
123 ( defined $val ) && ( $self->{service_type} = $val );
124 return $self->{service_type};
127 sub url {
128 my ( $self, $val ) = @_;
129 if ( defined $val && $self->url ) { return undef }
130 ( defined $val ) && ( $self->{url} = $val );
131 return $self->{url};
134 sub signatureURL {
135 my ( $self, $val ) = @_;
136 if ( defined $val && $self->signatureURL ) { return undef }
137 ( defined $val ) && ( $self->{signatureURL} = $val );
138 return $self->{signatureURL};
141 sub contact_email {
142 my ( $self, $val ) = @_;
143 if ( defined $val && $self->contact_email ) { return undef }
144 ( defined $val ) && ( $self->{contact_email} = $val );
145 return $self->{contact_email};
148 sub description {
149 my ( $self, $val ) = @_;
150 if ( defined $val && $self->description ) { return undef }
151 ( defined $val ) && ( $self->{description} = $val );
152 return $self->{description};
155 sub dbh {
156 $CONFIG ||= MOBY::Config->new; # exported by Config.pm
157 my $adaptor =
158 $CONFIG->getDataAdaptor( datasource => 'mobycentral' )->dbh;
161 sub adaptor {
162 $CONFIG ||= MOBY::Config->new; # exported by Config.pm
163 my $adaptor = $CONFIG->getDataAdaptor( datasource => 'mobycentral' );
167 sub new {
168 my ( $caller, %args ) = @_;
169 my $caller_is_obj = ref($caller);
170 return $caller if $caller_is_obj;
171 my $class = $caller_is_obj || $caller;
172 my $proxy;
173 my ($self) = bless {}, $class;
174 foreach my $attrname ( $self->_standard_keys ) {
175 if ( exists $args{$attrname} ) {
176 $self->{$attrname} = $args{$attrname};
177 } elsif ($caller_is_obj) {
178 $self->{$attrname} = $caller->{$attrname};
179 } else {
180 $self->{$attrname} = $self->_default_for($attrname);
183 return undef unless $self->authority_uri;
184 return undef unless $self->servicename;
186 if ( $self->test ) { return $self->service_instance_exists } # returns boolean
188 $self->authority( $self->_get_authority() ); # as MOBY::authority object
190 if ( $self->service_type ) {
191 my $OE = MOBY::OntologyServer->new( ontology => 'service' );
192 my ( $success, $message, $servicetypeURI ) =
193 $OE->serviceExists( term => $self->service_type );
194 unless (
195 $success || ( ( $self->service_type =~ /urn:lsid/i ) && !( $self->service_type =~ /urn:lsid:biomoby.org/i ) )
198 return undef;
200 ( $self->service_type =~ /urn:lsid/ )?
201 $self->service_type_uri( $self->service_type )
202 : $self->service_type_uri($servicetypeURI);
204 my $existing_services = $self->adaptor->query_service_instance(servicename => $self->servicename,
205 authority_uri => $self->authority_uri);
206 my $existing_service = shift(@$existing_services);
207 if ($existing_service->{servicename}) { # if service exists, then instantiate it from the database retrieval we just did
208 $self->servicename( $existing_service->{'servicename'} );
209 $self->authoritative( $existing_service->{'authoritative'} );
210 $self->service_instance_id( $existing_service->{'service_instance_id'} );
211 $self->category( $existing_service->{'category'} );
212 $self->service_type( $existing_service->{'service_type_uri'} );
213 $self->url( $existing_service->{'url'} );
214 $self->contact_email( $existing_service->{'contact_email'} );
215 $self->description( $existing_service->{'description'} );
216 $self->authority( $existing_service->{'authURI'} );
217 $self->signatureURL( $existing_service->{'signatureURL'} );
218 $self->lsid( $existing_service->{'lsid'} );
219 $self->{__exists__} = 1; # this service already existed
220 } elsif (!($existing_service->{servicename}) # if it doesn't exist
221 && (defined $self->category) # and you have given me things I need to create it
222 && ( defined $self->service_type )
223 && ( defined $self->url )
224 && ( defined $self->contact_email )
225 && ( defined $self->description )
226 ) { # then create it de novo if we have enough information
227 # create a timestamp for the LSID
228 my ($sec,$min,$hour,$mday,$month,$year, $wday,$yday,$dst) =gmtime(time);
229 my $date = sprintf ("%02d-%02d-%02dT%02d-%02d-%02dZ",$year+1900,$month+1,$mday,$hour,$min,$sec);
231 #create LSID for service and register it in the DB
232 my $_config ||= MOBY::Config->new;
233 my $LSID_Auth = $_config->{mobycentral}->{lsid_authority};
234 my $LSID_NS = $_config->{mobycentral}->{lsid_namespace};
235 $LSID_Auth ||="biomoby.org";
236 $LSID_NS ||="serviceinstance";
237 my $service_lsid = "urn:lsid:$LSID_Auth:$LSID_NS:"
238 . $self->authority_uri . ","
239 . $self->servicename.":"."$date"; # LSID with timestamp
240 $self->lsid($service_lsid);
241 my $id = $self->adaptor->insert_service_instance(
242 category => $self->category,
243 servicename => $self->servicename,
244 service_type_uri => $self->service_type_uri,
245 authority_uri => $self->authority_uri,
246 url => $self->url,
247 contact_email => $self->contact_email,
248 authoritative => $self->authoritative,
249 description => $self->description,
250 signatureURL => $self->signatureURL,
251 lsid => $service_lsid
253 return undef unless $id;
254 $self->service_instance_id($id);
255 $self->{__exists__} = 1; # this service now exists
256 } else { # if it doesn't exist, and you havne't given me anyting I need to create it, then bail out
257 return undef;
259 return $self;
262 sub DELETE_THYSELF {
263 my ($self) = @_;
264 my $dbh = $self->dbh;
265 unless ( $self->{__exists__} ) {
266 return undef;
268 $CONFIG ||= MOBY::Config->new;
269 my $adaptor = $CONFIG->getDataAdaptor( datasource => 'mobycentral' );
271 #********FIX this should really be delete_input and delete_output
272 # the routines below know too much about the database (e.g. that
273 # the delete_simple_input routines are broken into two parts - by LSID and
274 # by collecion ID... BAD BAD BAD
275 $adaptor->delete_simple_input(service_instance_lsid => $self->lsid);
276 $adaptor->delete_simple_output(service_instance_lsid => $self->lsid);
278 my $result = $adaptor->query_collection_input(service_instance_lsid => $self->lsid);
280 foreach my $row (@$result) {
281 my $id = $row->{collection_input_id};
282 $adaptor->delete_simple_input(collection_input_id => $id);
284 $result = $adaptor->query_collection_output(service_instance_lsid => $self->lsid);
286 foreach my $row (@$result) {
287 my $id = $row->{collection_output_id};
289 $adaptor->delete_simple_output(collection_output_id => $id);
291 $adaptor->delete_collection_input(service_instance_lsid => $self->lsid);
292 $adaptor->delete_collection_output(service_instance_lsid => $self->lsid);
293 $adaptor->delete_secondary_input(service_instance_lsid => $self->lsid);
294 $adaptor->delete_service_instance(service_instance_lsid => $self->lsid);
296 return 1;
299 sub authority_id {
300 my ($self) = @_;
301 return $self->authority->authority_id;
304 sub service_instance_exists {
305 my ($self) = @_;
306 $CONFIG ||= MOBY::Config->new;
307 my $adaptor = $CONFIG->getDataAdaptor( datasource => 'mobycentral' );
308 my $dbh = $self->dbh;
309 my $authority;
311 my $result = $adaptor->query_service_existence(authority_uri => $self->authority_uri, servicename => $self->servicename);
312 return $result
315 sub _get_authority
316 { # there's somethign fishy here... the authority.pm object already knows about authority_id and authorty_uri, doens't it?
317 my ($self) = @_;
318 my $dbh = $self->dbh;
319 my $authority;
320 $CONFIG ||= MOBY::Config->new;
321 my $adaptor = $CONFIG->getDataAdaptor( datasource => 'mobycentral' );
322 my $result = $adaptor->query_authority(authority_uri => $self->authority_uri);
323 #*********FIX we should nver need to know the authority ID in this level of code!
324 if ( @$result[0]) {
325 my $row = shift(@$result);
326 #my $id = $row->{authority_id};
327 my $name = $row->{authority_common_name};
328 my $uri = $row->{authority_uri};
329 my $email = $row->{contact_email};
331 $authority = MOBY::authority->new(
332 dbh => $self->dbh,
333 # authority_id => $id,
334 authority_uri => $uri,
335 contact_email => $email,
337 } else {
338 $authority = MOBY::authority->new(
339 dbh => $self->dbh,
340 authority_uri => $self->authority_uri,
341 contact_email => $self->contact_email,
344 return $authority;
347 sub add_simple_input {
348 my ( $self, %a ) = @_;
350 # validate here... one day...
351 my $simple = MOBY::simple_input->new(
352 object_type_uri => $a{'object_type_uri'},
353 namespace_type_uris => $a{'namespace_type_uris'},
354 article_name => $a{'article_name'},
355 service_instance_id => $self->service_instance_id,
356 service_instance_lsid => $self->lsid,
357 collection_input_id => $a{'collection_input_id'}
359 push @{ $self->{inputs} }, $simple;
360 return $simple->simple_input_id;
363 sub add_simple_output {
364 my ( $self, %a ) = @_;
366 # validate here... one day...
367 my $simple = MOBY::simple_output->new(
368 object_type_uri => $a{'object_type_uri'},
369 namespace_type_uris => $a{'namespace_type_uris'},
370 article_name => $a{'article_name'},
371 service_instance_id => $self->service_instance_id,
372 service_instance_lsid => $self->lsid,
373 collection_output_id => $a{'collection_output_id'}
375 push @{ $self->{outputs} }, $simple;
376 return $simple->simple_output_id;
379 sub add_collection_input {
380 my ( $self, %a ) = @_;
382 # validate here... one day...
383 my $coll = MOBY::collection_input->new(
384 article_name => $a{'article_name'},
385 service_instance_lsid => $self->lsid,
386 service_instance_id => $self->service_instance_id, );
387 push @{ $self->{inputs} }, $coll;
388 return $coll->collection_input_id;
391 sub add_collection_output {
392 my ( $self, %a ) = @_;
394 # validate here... one day...
395 my $coll = MOBY::collection_output->new(
396 article_name => $a{'article_name'},
397 service_instance_lsid => $self->lsid,
398 service_instance_id => $self->service_instance_id, );
399 push @{ $self->{outputs} }, $coll;
400 return $coll->collection_output_id;
403 sub add_secondary_input {
404 my ( $self, %a ) = @_;
406 # validate here... one day...
407 my $sec = MOBY::secondary_input->new(
408 default_value => $a{'default_value'},
409 maximum_value => $a{'maximum_value'},
410 minimum_value => $a{'minimum_value'},
411 enum_value => $a{'enum_value'},
412 datatype => $a{'datatype'},
413 article_name => $a{'article_name'},
414 service_instance_id => $self->service_instance_id,
415 service_instance_lsid => $self->lsid,
417 push @{ $self->{inputs} }, $sec;
418 return $sec->secondary_input_id;
421 sub AUTOLOAD {
422 no strict "refs";
423 my ( $self, $newval ) = @_;
424 $AUTOLOAD =~ /.*::(\w+)/;
425 my $attr = $1;
426 if ( $self->_accessible( $attr, 'write' ) ) {
427 *{$AUTOLOAD} = sub {
428 if ( defined $_[1] ) { $_[0]->{$attr} = $_[1] }
429 return $_[0]->{$attr};
430 }; ### end of created subroutine
431 ### this is called first time only
432 if ( defined $newval ) {
433 $self->{$attr} = $newval;
435 return $self->{$attr};
436 } elsif ( $self->_accessible( $attr, 'read' ) ) {
437 *{$AUTOLOAD} = sub {
438 return $_[0]->{$attr};
439 }; ### end of created subroutine
440 return $self->{$attr};
443 # Must have been a mistake then...
444 croak "No such method: $AUTOLOAD";
446 sub DESTROY { }