1# ======================================================================
2#
3# Copyright (C) 2000-2001 Paul Kulchenko (paulclinger@yahoo.com)
4# SOAP::Lite is free software; you can redistribute it
5# and/or modify it under the same terms as Perl itself.
6#
7# $Id: Lite.pm,v 1.6 2004/11/14 19:30:50 byrnereese Exp $
8#
9# ======================================================================
10
11package UDDI::Lite;
12
13use 5.004;
14use strict;
15use vars qw($VERSION);
16#$VERSION = sprintf("%d.%s", map {s/_//g; $_} q$Name:  $ =~ /-(\d+)_([\d_]+)/);
17$VERSION = $SOAP::Lite::VERSION;
18
19use SOAP::Lite;
20
21# ======================================================================
22
23package UDDI::Constants;
24
25BEGIN {
26  use vars qw(%UDDI_VERSIONS $ELEMENTS $ATTRIBUTES $WITHNAMES $NAMESPACE $GENERIC);
27
28  %UDDI_VERSIONS = (
29    1 => {
30      ELEMENTS => {address=>{addressLine=>1},authToken=>{authInfo=>1},bindingDetail=>{bindingTemplate=>1},bindingTemplate=>{accessPoint=>1,description=>1,hostingRedirector=>1,tModelInstanceDetails=>1},bindingTemplates=>{bindingTemplate=>1},businessDetail=>{businessEntity=>1},businessDetailExt=>{businessEntityExt=>1},businessEntity=>{businessServices=>1,categoryBag=>1,contacts=>1,description=>1,discoveryURLs=>1,identifierBag=>1,name=>1},businessEntityExt=>{businessEntity=>1},businessInfo=>{description=>1,name=>1,serviceInfos=>1},businessInfos=>{businessInfo=>1},businessList=>{businessInfos=>1},businessService=>{bindingTemplates=>1,categoryBag=>1,description=>1,name=>1},businessServices=>{businessService=>1},categoryBag=>{keyedReference=>1},contact=>{address=>1,description=>1,email=>1,personName=>1,phone=>1},contacts=>{contact=>1},delete_binding=>{authInfo=>1,bindingKey=>1},delete_business=>{authInfo=>1,businessKey=>1},delete_service=>{authInfo=>1,serviceKey=>1},delete_tModel=>{authInfo=>1,tModelKey=>1},discard_authToken=>{authInfo=>1},discoveryURLs=>{discoveryUrl=>1},dispositionReport=>{result=>1},findQualifiers=>{findQualifier=>1},find_binding=>{findQualifiers=>1,tModelBag=>1},find_business=>{categoryBag=>1,discoveryURLs=>1,findQualifiers=>1,identifierBag=>1,name=>1,tModelBag=>1},find_service=>{categoryBag=>1,findQualifiers=>1,name=>1,tModelBag=>1},find_tModel=>{categoryBag=>1,findQualifiers=>1,identifierBag=>1,name=>1},get_bindingDetail=>{bindingKey=>1},get_businessDetail=>{businessKey=>1},get_businessDetailExt=>{businessKey=>1},get_registeredInfo=>{authInfo=>1},get_serviceDetail=>{serviceKey=>1},get_tModelDetail=>{tModelKey=>1},identifierBag=>{keyedReference=>1},instanceDetails=>{description=>1,instanceParms=>1,overviewDoc=>1},overviewDoc=>{description=>1,overviewURL=>1},registeredInfo=>{businessInfos=>1,tModelInfos=>1},result=>{errInfo=>1},save_binding=>{authInfo=>1,bindingTemplate=>1},save_business=>{authInfo=>1,businessEntity=>1,uploadRegister=>1},save_service=>{authInfo=>1,businessService=>1},save_tModel=>{authInfo=>1,tModel=>1,uploadRegister=>1},serviceDetail=>{businessService=>1},serviceInfo=>{name=>1},serviceInfos=>{serviceInfo=>1},serviceList=>{serviceInfos=>1},tModel=>{categoryBag=>1,description=>1,identifierBag=>1,name=>1,overviewDoc=>1},tModelBag=>{tModelKey=>1},tModelDetail=>{tModel=>1},tModelInfo=>{name=>1},tModelInfos=>{tModelInfo=>1},tModelInstanceDetails=>{tModelInstanceInfo=>1},tModelInstanceInfo=>{description=>1,instanceDetails=>1},tModelList=>{tModelInfos=>1},validate_categorization=>{businessEntity=>1,businessService=>1,keyValue=>1,tModel=>1,tModelKey=>1}},
31      ATTRIBUTES => {accessPoint=>{URLType=>2},address=>{sortCode=>2,useType=>2},authToken=>{generic=>2,operator=>2},bindingDetail=>{generic=>2,operator=>2,truncated=>2},bindingTemplate=>{bindingKey=>2,serviceKey=>2},businessDetail=>{generic=>2,operator=>2,truncated=>2},businessDetailExt=>{generic=>2,operator=>2,truncated=>2},businessEntity=>{authorizedName=>2,businessKey=>2,operator=>2},businessInfo=>{businessKey=>2},businessList=>{generic=>2,operator=>2,truncated=>2},businessService=>{businessKey=>2,serviceKey=>2},contact=>{useType=>2},delete_binding=>{generic=>2},delete_business=>{generic=>2},delete_service=>{generic=>2},delete_tModel=>{generic=>2},description=>{lang=>2},discard_authToken=>{generic=>2},discoveryUrl=>{useType=>2},dispositionReport=>{generic=>2,operator=>2,truncated=>2},email=>{useType=>2},errInfo=>{errCode=>2},find_binding=>{generic=>2,maxRows=>2,serviceKey=>2},find_business=>{generic=>2,maxRows=>2},find_service=>{businessKey=>2,generic=>2,maxRows=>2},find_tModel=>{generic=>2,maxRows=>2},get_authToken=>{cred=>2,generic=>2,userID=>2},get_bindingDetail=>{generic=>2},get_businessDetail=>{generic=>2},get_businessDetailExt=>{generic=>2},get_registeredInfo=>{generic=>2},get_serviceDetail=>{generic=>2},get_tModelDetail=>{generic=>2},hostingRedirector=>{bindingKey=>2},keyedReference=>{keyName=>2,keyValue=>2,tModelKey=>2},phone=>{useType=>2},registeredInfo=>{generic=>2,operator=>2,truncated=>2},result=>{errno=>2,keyType=>2},save_binding=>{generic=>2},save_business=>{generic=>2},save_service=>{generic=>2},save_tModel=>{generic=>2},serviceDetail=>{generic=>2,operator=>2,truncated=>2},serviceInfo=>{businessKey=>2,serviceKey=>2},serviceList=>{generic=>2,operator=>2,truncated=>2},tModel=>{authorizedName=>2,operator=>2,tModelKey=>2},tModelDetail=>{generic=>2,operator=>2,truncated=>2},tModelInfo=>{tModelKey=>2},tModelInstanceInfo=>{tModelKey=>2},tModelList=>{generic=>2,operator=>2,truncated=>2},validate_categorization=>{generic=>2}},
32      WITHNAMES => [qw/accessPoint address addressLine authInfo authToken bindingDetail bindingKey bindingTemplate bindingTemplates businessDetail businessDetailExt businessEntity businessEntityExt businessInfo businessInfos businessKey businessList businessService businessServices categoryBag contact contacts description discoveryURLs discoveryUrl dispositionReport email errInfo findQualifier findQualifiers hostingRedirector identifierBag instanceDetails instanceParms keyValue keyedReference name overviewDoc overviewURL personName phone registeredInfo result serviceDetail serviceInfo serviceInfos serviceKey serviceList tModel tModelBag tModelDetail tModelInfo tModelInfos tModelInstanceDetails tModelInstanceInfo tModelKey tModelList uploadRegister/],
33      NAMESPACE => 'urn:uddi-org:api',
34      GENERIC => '1.0', # string, not number; '.0' matters
35    },
36    2 => {
37      ELEMENTS => {add_publisherAssertions=>{authInfo=>1,publisherAssertion=>1},address=>{addressLine=>1},assertionStatusItem=>{fromKey=>1,keyedReference=>1,keysOwned=>1,toKey=>1},assertionStatusReport=>{assertionStatusItem=>1},authToken=>{authInfo=>1},bindingDetail=>{bindingTemplate=>1},bindingTemplate=>{accessPoint=>1,description=>1,hostingRedirector=>1,tModelInstanceDetails=>1},bindingTemplates=>{bindingTemplate=>1},businessDetail=>{businessEntity=>1},businessDetailExt=>{businessEntityExt=>1},businessEntity=>{businessServices=>1,categoryBag=>1,contacts=>1,description=>1,discoveryURLs=>1,identifierBag=>1,name=>1},businessEntityExt=>{businessEntity=>1},businessInfo=>{description=>1,name=>1,serviceInfos=>1},businessInfos=>{businessInfo=>1},businessList=>{businessInfos=>1},businessService=>{bindingTemplates=>1,categoryBag=>1,description=>1,name=>1},businessServices=>{businessService=>1},categoryBag=>{keyedReference=>1},contact=>{address=>1,description=>1,email=>1,personName=>1,phone=>1},contacts=>{contact=>1},delete_binding=>{authInfo=>1,bindingKey=>1},delete_business=>{authInfo=>1,businessKey=>1},delete_publisherAssertions=>{authInfo=>1,publisherAssertion=>1},delete_service=>{authInfo=>1,serviceKey=>1},delete_tModel=>{authInfo=>1,tModelKey=>1},discard_authToken=>{authInfo=>1},discoveryURLs=>{discoveryURL=>1},dispositionReport=>{result=>1},findQualifiers=>{findQualifier=>1},find_binding=>{findQualifiers=>1,tModelBag=>1},find_business=>{categoryBag=>1,discoveryURLs=>1,findQualifiers=>1,identifierBag=>1,name=>1,tModelBag=>1},find_relatedBusinesses=>{businessKey=>1,findQualifiers=>1,keyedReference=>1},find_service=>{categoryBag=>1,findQualifiers=>1,name=>1,tModelBag=>1},find_tModel=>{categoryBag=>1,findQualifiers=>1,identifierBag=>1,name=>1},get_assertionStatusReport=>{authInfo=>1,completionStatus=>1},get_bindingDetail=>{bindingKey=>1},get_businessDetail=>{businessKey=>1},get_businessDetailExt=>{businessKey=>1},get_publisherAssertions=>{authInfo=>1},get_registeredInfo=>{authInfo=>1},get_serviceDetail=>{serviceKey=>1},get_tModelDetail=>{tModelKey=>1},identifierBag=>{keyedReference=>1},instanceDetails=>{description=>1,instanceParms=>1,overviewDoc=>1},keysOwned=>{fromKey=>1,toKey=>1},overviewDoc=>{description=>1,overviewURL=>1},publisherAssertion=>{fromKey=>1,keyedReference=>1,toKey=>1},publisherAssertions=>{publisherAssertion=>1},registeredInfo=>{businessInfos=>1,tModelInfos=>1},relatedBusinessInfo=>{businessKey=>1,description=>1,name=>1,sharedRelationships=>1},relatedBusinessInfos=>{relatedBusinessInfo=>1},relatedBusinessesList=>{businessKey=>1,relatedBusinessInfos=>1},result=>{errInfo=>1},save_binding=>{authInfo=>1,bindingTemplate=>1},save_business=>{authInfo=>1,businessEntity=>1,uploadRegister=>1},save_service=>{authInfo=>1,businessService=>1},save_tModel=>{authInfo=>1,tModel=>1,uploadRegister=>1},serviceDetail=>{businessService=>1},serviceInfo=>{name=>1},serviceInfos=>{serviceInfo=>1},serviceList=>{serviceInfos=>1},set_publisherAssertions=>{authInfo=>1,publisherAssertion=>1},sharedRelationships=>{keyedReference=>1},tModel=>{categoryBag=>1,description=>1,identifierBag=>1,name=>1,overviewDoc=>1},tModelBag=>{tModelKey=>1},tModelDetail=>{tModel=>1},tModelInfo=>{name=>1},tModelInfos=>{tModelInfo=>1},tModelInstanceDetails=>{tModelInstanceInfo=>1},tModelInstanceInfo=>{description=>1,instanceDetails=>1},tModelList=>{tModelInfos=>1},validate_values=>{businessEntity=>1,businessService=>1,tModel=>1}},
38      ATTRIBUTES => {accessPoint=>{URLType=>2},add_publisherAssertions=>{generic=>2},address=>{sortCode=>2,tModelKey=>2,useType=>2},addressLine=>{keyName=>2,keyValue=>2},assertionStatusItem=>{completionStatus=>2},assertionStatusReport=>{generic=>2,operator=>2},authToken=>{generic=>2,operator=>2},bindingDetail=>{generic=>2,operator=>2,truncated=>2},bindingTemplate=>{bindingKey=>2,serviceKey=>2},businessDetail=>{generic=>2,operator=>2,truncated=>2},businessDetailExt=>{generic=>2,operator=>2,truncated=>2},businessEntity=>{authorizedName=>2,businessKey=>2,operator=>2},businessInfo=>{businessKey=>2},businessList=>{generic=>2,operator=>2,truncated=>2},businessService=>{businessKey=>2,serviceKey=>2},contact=>{useType=>2},delete_binding=>{generic=>2},delete_business=>{generic=>2},delete_publisherAssertions=>{generic=>2},delete_service=>{generic=>2},delete_tModel=>{generic=>2},description=>{lang=>2},discard_authToken=>{generic=>2},discoveryURL=>{useType=>2},dispositionReport=>{generic=>2,operator=>2,truncated=>2},email=>{useType=>2},errInfo=>{errCode=>2},find_binding=>{generic=>2,maxRows=>2,serviceKey=>2},find_business=>{generic=>2,maxRows=>2},find_relatedBusinesses=>{generic=>2,maxRows=>2},find_service=>{businessKey=>2,generic=>2,maxRows=>2},find_tModel=>{generic=>2,maxRows=>2},get_assertionStatusReport=>{generic=>2},get_authToken=>{cred=>2,generic=>2,userID=>2},get_bindingDetail=>{generic=>2},get_businessDetail=>{generic=>2},get_businessDetailExt=>{generic=>2},get_publisherAssertions=>{generic=>2},get_registeredInfo=>{generic=>2},get_serviceDetail=>{generic=>2},get_tModelDetail=>{generic=>2},hostingRedirector=>{bindingKey=>2},keyedReference=>{keyName=>2,keyValue=>2,tModelKey=>2},name=>{lang=>2},phone=>{useType=>2},publisherAssertions=>{authorizedName=>2,generic=>2,operator=>2},registeredInfo=>{generic=>2,operator=>2,truncated=>2},relatedBusinessesList=>{generic=>2,operator=>2,truncated=>2},result=>{errno=>2,keyType=>2},save_binding=>{generic=>2},save_business=>{generic=>2},save_service=>{generic=>2},save_tModel=>{generic=>2},serviceDetail=>{generic=>2,operator=>2,truncated=>2},serviceInfo=>{businessKey=>2,serviceKey=>2},serviceList=>{generic=>2,operator=>2,truncated=>2},set_publisherAssertions=>{generic=>2},sharedRelationships=>{direction=>2},tModel=>{authorizedName=>2,operator=>2,tModelKey=>2},tModelDetail=>{generic=>2,operator=>2,truncated=>2},tModelInfo=>{tModelKey=>2},tModelInstanceInfo=>{tModelKey=>2},tModelList=>{generic=>2,operator=>2,truncated=>2},validate_values=>{generic=>2}},
39      WITHNAMES => [qw/accessPoint address addressLine assertionStatusItem assertionStatusReport authInfo authToken bindingDetail bindingKey bindingTemplate bindingTemplates businessDetail businessDetailExt businessEntity businessEntityExt businessInfo businessInfos businessKey businessList businessService businessServices categoryBag completionStatus contact contacts description discoveryURL discoveryURLs dispositionReport email errInfo findQualifier findQualifiers fromKey hostingRedirector identifierBag instanceDetails instanceParms keyedReference keysOwned name overviewDoc overviewURL personName phone publisherAssertion publisherAssertions registeredInfo relatedBusinessInfo relatedBusinessInfos relatedBusinessesList result serviceDetail serviceInfo serviceInfos serviceKey serviceList sharedRelationships tModel tModelBag tModelDetail tModelInfo tModelInfos tModelInstanceDetails tModelInstanceInfo tModelKey tModelList toKey uploadRegister/],
40      NAMESPACE => 'urn:uddi-org:api_v2',
41      GENERIC => '2.0',
42    },
43    3 => {
44      ELEMENTS => {add_publisherAssertions=>{authInfo=>1,publisherAssertion=>1},address=>{addressLine=>1},assertionStatusItem=>{fromKey=>1,keyedReference=>1,keysOwned=>1,toKey=>1},assertionStatusReport=>{assertionStatusItem=>1},authToken=>{authInfo=>1},bindingDetail=>{bindingTemplate=>1,listDescription=>1},bindingTemplate=>{accessPoint=>1,categoryBag=>1,description=>1,Signature=>1,hostingRedirector=>1,tModelInstanceDetails=>1},bindingTemplates=>{bindingTemplate=>1},businessDetail=>{businessEntity=>1},businessEntity=>{businessServices=>1,categoryBag=>1,contacts=>1,description=>1,discoveryURLs=>1,Signature=>1,identifierBag=>1,name=>1},businessInfo=>{description=>1,name=>1,serviceInfos=>1},businessInfos=>{businessInfo=>1},businessList=>{businessInfos=>1,listDescription=>1},businessService=>{bindingTemplates=>1,categoryBag=>1,description=>1,Signature=>1,name=>1},businessServices=>{businessService=>1},categoryBag=>{keyedReference=>1,keyedReferenceGroup=>1,keyedReferenceGroup=>1},contact=>{address=>1,description=>1,email=>1,personName=>1,phone=>1},contacts=>{contact=>1},delete_binding=>{authInfo=>1,bindingKey=>1},delete_business=>{authInfo=>1,businessKey=>1},delete_publisherAssertions=>{authInfo=>1,publisherAssertion=>1},delete_service=>{authInfo=>1,serviceKey=>1},delete_tModel=>{authInfo=>1,tModelKey=>1},discard_authToken=>{authInfo=>1},discoveryURLs=>{discoveryURL=>1},dispositionReport=>{result=>1},findQualifiers=>{findQualifier=>1},find_binding=>{authInfo=>1,categoryBag=>1,findQualifiers=>1,find_tModel=>1,tModelBag=>1},find_business=>{authInfo=>1,categoryBag=>1,discoveryURLs=>1,findQualifiers=>1,find_relatedBusinesses=>1,find_tModel=>1,identifierBag=>1,name=>1,tModelBag=>1},find_relatedBusinesses=>{authInfo=>1,businessKey=>1,findQualifiers=>1,fromKey=>1,keyedReference=>1,toKey=>1},find_service=>{authInfo=>1,categoryBag=>1,findQualifiers=>1,find_tModel=>1,name=>1,tModelBag=>1},find_tModel=>{authInfo=>1,categoryBag=>1,findQualifiers=>1,identifierBag=>1,name=>1},get_assertionStatusReport=>{authInfo=>1,completionStatus=>1},get_bindingDetail=>{authInfo=>1,bindingKey=>1},get_businessDetail=>{authInfo=>1,businessKey=>1},get_operationalInfo=>{authInfo=>1,entityKey=>1},get_publisherAssertions=>{authInfo=>1},get_registeredInfo=>{authInfo=>1},get_serviceDetail=>{authInfo=>1,serviceKey=>1},get_tModelDetail=>{authInfo=>1,tModelKey=>1},identifierBag=>{keyedReference=>1},instanceDetails=>{description=>1,instanceParms=>1,instanceParms=>1,overviewDoc=>1},keyedReferenceGroup=>{keyedReference=>1},keysOwned=>{fromKey=>1,toKey=>1,toKey=>1},listDescription=>{actualCount=>1,includeCount=>1,listHead=>1},operationalInfo=>{authorizedName=>1,created=>1,modified=>1,modifiedIncludingChildren=>1,nodeID=>1},operationalInfos=>{operationalInfo=>1},overviewDoc=>{description=>1,overviewURL=>1,overviewURL=>1},publisherAssertion=>{Signature=>1,fromKey=>1,keyedReference=>1,toKey=>1},publisherAssertions=>{publisherAssertion=>1},registeredInfo=>{businessInfos=>1,tModelInfos=>1},relatedBusinessInfo=>{businessKey=>1,description=>1,name=>1,sharedRelationships=>1},relatedBusinessInfos=>{relatedBusinessInfo=>1},relatedBusinessesList=>{businessKey=>1,listDescription=>1,relatedBusinessInfos=>1},result=>{errInfo=>1},save_binding=>{authInfo=>1,bindingTemplate=>1},save_business=>{authInfo=>1,businessEntity=>1},save_service=>{authInfo=>1,businessService=>1},save_tModel=>{authInfo=>1,tModel=>1},serviceDetail=>{businessService=>1},serviceInfo=>{name=>1},serviceInfos=>{serviceInfo=>1},serviceList=>{listDescription=>1,serviceInfos=>1},set_publisherAssertions=>{authInfo=>1,publisherAssertion=>1},sharedRelationships=>{keyedReference=>1,publisherAssertion=>1},tModel=>{categoryBag=>1,description=>1,Signature=>1,identifierBag=>1,name=>1,overviewDoc=>1},tModelBag=>{tModelKey=>1},tModelDetail=>{tModel=>1},tModelInfo=>{description=>1,name=>1},tModelInfos=>{tModelInfo=>1},tModelInstanceDetails=>{tModelInstanceInfo=>1},tModelInstanceInfo=>{description=>1,instanceDetails=>1},tModelList=>{listDescription=>1,tModelInfos=>1}},
45      ATTRIBUTES => {accessPoint=>{useType=>2},address=>{sortCode=>2,tModelKey=>2,useType=>2,lang=>2},addressLine=>{keyName=>2,keyValue=>2},assertionStatusItem=>{completionStatus=>2},bindingDetail=>{truncated=>2},bindingTemplate=>{bindingKey=>2,serviceKey=>2},businessDetail=>{truncated=>2},businessEntity=>{businessKey=>2},businessInfo=>{businessKey=>2},businessList=>{truncated=>2},businessService=>{businessKey=>2,serviceKey=>2},contact=>{useType=>2},description=>{lang=>2},discoveryURL=>{useType=>2},dispositionReport=>{truncated=>2},email=>{useType=>2},errInfo=>{errCode=>2},find_binding=>{listHead=>2,maxRows=>2,serviceKey=>2},find_business=>{listHead=>2,maxRows=>2},find_relatedBusinesses=>{listHead=>2,maxRows=>2},find_service=>{businessKey=>2,listHead=>2,maxRows=>2},find_tModel=>{listHead=>2,maxRows=>2},get_authToken=>{cred=>2,userID=>2},get_registeredInfo=>{infoSelection=>2},hostingRedirector=>{bindingKey=>2},keyedReference=>{keyName=>2,keyValue=>2,tModelKey=>2},keyedReferenceGroup=>{tModelKey=>2},name=>{lang=>2},operationalInfo=>{entityKey=>2},operationalInfos=>{truncated=>2},overviewURL=>{useType=>2},personName=>{lang=>2},phone=>{useType=>2},registeredInfo=>{truncated=>2},relatedBusinessesList=>{truncated=>2},result=>{errno=>2,keyType=>2},serviceDetail=>{truncated=>2},serviceInfo=>{businessKey=>2,serviceKey=>2},serviceList=>{truncated=>2},sharedRelationships=>{direction=>2},tModel=>{deleted=>2,tModelKey=>2},tModelDetail=>{truncated=>2},tModelInfo=>{tModelKey=>2},tModelInstanceInfo=>{tModelKey=>2},tModelList=>{truncated=>2}},
46      WITHNAMES => [qw/accessPoint actualCount address addressLine assertionStatusItem assertionStatusReport authToken authorizedName bindingDetail bindingKey bindingTemplate bindingTemplates businessDetail businessEntity businessInfo businessInfos businessKey businessList businessService businessServices categoryBag completionStatus contact contacts created description discoveryURL discoveryURLs dispositionReport email entityKey errInfo findQualifier findQualifiers fromKey hostingRedirector identifierBag includeCount infoSelection instanceDetails instanceParms keyedReference keyedReferenceGroup keysOwned listDescription listHead modified modifiedIncludingChildren name nodeID operationalInfo operationalInfos overviewDoc overviewURL personName phone publisherAssertion publisherAssertions registeredInfo relatedBusinessInfo relatedBusinessInfos relatedBusinessesList result serviceDetail serviceInfo serviceInfos serviceKey serviceList sharedRelationships tModel tModelBag tModelDetail tModelInfo tModelInfos tModelInstanceDetails tModelInstanceInfo tModelKey tModelList toKey/],
47      NAMESPACE => 'urn:uddi-org:api_v3',
48      GENERIC => undef,
49    },
50  );
51}
52
53# ======================================================================
54
55package UDDI::SOM;
56
57use vars qw(@ISA);
58@ISA = qw(SOAP::SOM);
59
60sub result { # result should point to immediate child of Body
61  my $self = shift;
62  my $result = '/Envelope/Body/[1]';
63  ref $self or return $result;
64  defined $self->fault ? undef : $self->valueof($result);
65};
66
67# ======================================================================
68
69package UDDI::Data;
70
71use Carp ();
72
73use vars qw(@ISA $AUTOLOAD);
74@ISA = qw(SOAP::Data);
75
76use overload fallback => 1, '""' => sub { shift->SUPER::value };
77
78sub _init {
79  use vars qw(@EXPORT_OK %EXPORT_TAGS);
80  @EXPORT_OK = (with => @$UDDI::Constants::WITHNAMES);
81  %EXPORT_TAGS = (all => [@EXPORT_OK]);
82
83  use vars qw($elements $attributes);
84  $elements = $UDDI::Constants::ELEMENTS;
85  $attributes = $UDDI::Constants::ATTRIBUTES;
86}
87
88sub new {
89  my $self = shift;
90  my $class = ref($self) || $self;
91
92  unless (ref $self) {
93    $self = $class->SUPER::new(@_, type => 'uddi');
94  }
95  return $self;
96}
97
98sub with {
99  my $self = shift;
100  $self = (__PACKAGE__->can($self) || Carp::croak "Don't know what to do with '$self'")->()
101    unless ref $self && UNIVERSAL::isa($self => __PACKAGE__);
102
103  my $name = $self->SUPER::name;
104  my @values;
105  while (@_) {
106    my $data = shift;
107    my($method, $attr, @value) = UNIVERSAL::isa($data => __PACKAGE__)
108      ? ($data->SUPER::name, $data->SUPER::attr, $data->SUPER::value)
109      : ($data, {}, shift);
110    exists $attributes->{$name}{$method}
111      # attribute
112      ? $self->$method(@value)
113      # sub element
114      : push(@values, ($self->can($method) || Carp::croak "Don't know what to do with '$method'")->(@value)->attr($attr));
115  }
116  $self->set_value([@values]);
117}
118
119sub _compileit {
120  no strict 'refs';
121  my $method = shift;
122  *$method = sub {
123
124    # GENERATE element if no parameters: businessInfo()
125    return __PACKAGE__->SUPER::name($method)
126      if !@_ && exists $elements->{$method};
127
128    die "Expected element (UDDI::Data) as parameter for $method()\n"
129      if !ref $_[0] && exists $elements->{$method};
130
131    # MAKE ELEMENT: name( [{attr => value},] 'old')
132    if (!UNIVERSAL::isa($_[0] => __PACKAGE__)) {
133      # get optional list of attributes as a first parameter
134      my $attr = ref $_[0] eq 'HASH' ? shift @_ : {};
135      return __PACKAGE__->SUPER::name($method => @_)->attr($attr);
136    }
137
138    my $name = $_[0]->SUPER::name;
139
140    if (defined $name) {
141      # GET/SET ATTRIBUTE: businessInfo->businessKey
142      return @_ > 1
143          ? scalar($_[0]->attr->{$method} = $_[1], $_[0])               # SET
144          : __PACKAGE__->SUPER::name($method => $_[0]->attr->{$method}) # GET
145        if exists $attributes->{$name} && exists $attributes->{$name}{$method};
146
147      # GET ELEMENT: businessInfos->businessInfo
148      my @elems = grep {
149        ref $_ && UNIVERSAL::isa($_ => __PACKAGE__) && $_->SUPER::name eq $method
150      } map {ref $_ eq 'ARRAY' ? @$_ : $_} $_[0]->value;
151      return wantarray? @elems : $elems[0]
152        if exists $elements->{$name} && exists $elements->{$name}{$method};
153
154      # MAKE ELEMENT: businessInfos(businessInfo('something'))
155      return __PACKAGE__->SUPER::name($method => @_)
156        if exists $elements->{$method} && exists $elements->{$method}{$name};
157    }
158
159    # handle UDDI::Data->method() calls for those SOAP::Data methods
160    #  that conflict with UDDI methods, like name()
161    if (UNIVERSAL::can($ISA[0] => $method)) {
162      my $pkg = shift @_;
163      return eval "\$pkg->SUPER::$method(\@_)";
164    }
165
166    Carp::croak "Don't know what to do with '$method' and '$name' elements";
167  }
168}
169
170sub BEGIN { _compileit('name') }
171
172sub AUTOLOAD {
173  my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::') + 2);
174  return if $method eq 'DESTROY';
175
176  _compileit($method);
177  goto &$AUTOLOAD;
178}
179
180# ======================================================================
181
182package UDDI::Serializer;
183
184use vars qw(@ISA);
185@ISA = qw(SOAP::Serializer);
186
187sub new {
188  my $self = shift;
189  my $class = ref($self) || $self;
190
191  unless (ref $self) {
192    $self = $class->SUPER::new(
193      attr => {},
194      namespaces => {
195        $SOAP::Constants::PREFIX_ENV ? ($SOAP::Constants::NS_ENV => $SOAP::Constants::PREFIX_ENV) : (),
196      },
197      autotype => 0,
198      @_,
199    );
200  }
201  return $self;
202}
203
204use overload; # protect from stringification in UDDI::Data
205sub gen_id { overload::StrVal($_[1]) =~ /\((0x\w+)\)/o; $1 }
206
207sub as_uddi {
208  my $self = shift;
209  my($value, $name, $type, $attr) = @_;
210  return $self->encode_array($value, $name, undef, $attr) if ref $value eq 'ARRAY';
211  return $self->encode_hash($value, $name, undef, $attr) if ref $value eq 'HASH';
212  [$name, {%{$attr || {}}}, ref $value ? ([$self->encode_object($value)], $self->gen_id($value)) : $value];
213}
214
215sub encode_array {
216  my $self = shift;
217  my $encoded = $self->SUPER::encode_array(@_);
218  delete $encoded->[1]->{SOAP::Utils::qualify($self->encprefix => 'arrayType')};
219  return $encoded;
220}
221
222# ======================================================================
223
224package UDDI::Deserializer;
225
226use vars qw(@ISA);
227@ISA = qw(SOAP::Deserializer);
228
229sub decode_value {
230  my $self = shift;
231  my $ref = shift;
232  my($name, $attrs, $children, $value) = @$ref;
233
234  # base class knows what to do with elements in SOAP namespace
235  return $self->SUPER::decode_value($ref)
236    if exists $attrs->{href} ||
237       (SOAP::Utils::splitlongname($name))[0] eq $SOAP::Constants::NS_ENV;
238
239  UDDI::Data
240    -> SOAP::Data::name($name)
241    -> attr($attrs)
242    -> set_value(ref $children && @$children ? map(scalar(($self->decode_object($_))[1]), @$children) : $value);
243}
244
245sub deserialize {
246  bless shift->SUPER::deserialize(@_) => 'UDDI::SOM';
247}
248
249# ======================================================================
250
251package UDDI::Lite;
252
253use vars qw(@ISA $AUTOLOAD %EXPORT_TAGS);
254use Exporter;
255use Carp ();
256@ISA = qw(SOAP::Lite Exporter);
257
258BEGIN { # handle exports
259  %EXPORT_TAGS = (
260    'delete'   => [qw/delete_binding delete_business delete_service
261                      delete_tModel delete_publisherAssertions/],
262                                  # ^-------------------- v2/3
263    'auth'     => [qw/get_authToken discard_authToken get_registeredInfo/],
264    'save'     => [qw/save_binding save_business save_service save_tModel
265                      add_publisherAssertions set_publisherAssertions/],
266                    # ^----------------- v2/3 ^----------------- v2/3
267    'validate' => [qw/validate_categorization validate_values/],
268                    # ^------------------- v1 ^------------v2
269    'find'     => [qw/find_binding find_business find_service find_tModel
270                      find_relatedBusinesses/],
271                    # ^---------------- v2/3
272    'get'      => [qw/get_bindingDetail get_businessDetail get_businessDetailExt
273                      get_serviceDetail get_tModelDetail
274                      get_assertionStatusReport get_publisherAssertions/],
275                    # ^------------------- v2/3 ^----------------- v2/3
276  );
277  $EXPORT_TAGS{inquiry} = [map {@{$EXPORT_TAGS{$_}}} qw/find get/];
278  $EXPORT_TAGS{publish} = [map {@{$EXPORT_TAGS{$_}}} qw/delete auth save validate/];
279  $EXPORT_TAGS{all} =     [map {@{$EXPORT_TAGS{$_}}} qw/inquiry publish/];
280  Exporter::export_ok_tags('all');
281}
282
283my $uddiversion;
284
285sub uddiversion {
286  my $self = shift;
287  my $version = shift or return $uddiversion;
288
289  die qq!Wrong UDDI version. Supported versions: @{[
290        join ", ", keys %UDDI::Constants::UDDI_VERSIONS]}\n!
291    unless defined $UDDI::Constants::UDDI_VERSIONS{$version};
292
293  foreach (keys %{$UDDI::Constants::UDDI_VERSIONS{$version}}) {
294    eval "\$UDDI::Constants::$_ = \$UDDI::Constants::UDDI_VERSIONS{$version}->{$_}" or die;
295  }
296
297  UDDI::Data->_init;
298
299  $uddiversion = $version;
300  $self;
301}
302
303BEGIN { UDDI::Lite->uddiversion(1) }
304
305sub new {
306  my $self = shift;
307  my $class = ref($self) || $self;
308
309  unless (ref $self) {
310    $self = $class->SUPER::new(
311      on_action    => sub {'""'},
312      serializer   => UDDI::Serializer->new,   # register UDDI Serializer
313      deserializer => UDDI::Deserializer->new, # and Deserializer
314      @_,
315    );
316  }
317  return $self;
318}
319
320sub AUTOLOAD {
321  my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::') + 2);
322  return if $method eq 'DESTROY';
323
324  no strict 'refs';
325  *$AUTOLOAD = sub {
326    return shift->call($method => @_) if UNIVERSAL::isa($_[0] => __PACKAGE__);
327    my $som = (__PACKAGE__->self || Carp::croak "Method call on unspecified object. Died")->call($method => @_);
328    UNIVERSAL::isa($som => 'SOAP::SOM') ? $som->result : $som;
329  };
330  goto &$AUTOLOAD;
331}
332
333sub call { SOAP::Trace::trace('()');
334  my $self = shift;
335  my $method = shift;
336  my @parameters;
337  my $attr = ref $_[0] eq 'HASH' ? shift() : {};
338  while (@_) {
339    push(@parameters, UNIVERSAL::isa($_[0] => 'UDDI::Data')
340      ? shift : SOAP::Data->name(shift, shift));
341  }
342  my $message = SOAP::Data
343    -> name($method => \SOAP::Data->value(@parameters))
344    -> attr({xmlns => $UDDI::Constants::NAMESPACE,
345             (defined $UDDI::Constants::GENERIC ? (generic => $UDDI::Constants::GENERIC) : ()),
346             %$attr});
347
348  my $serializer = $self->serializer;
349  $serializer->on_nonserialized($self->on_nonserialized);
350
351  my $respond = $self->transport->send_receive(
352    endpoint => $self->endpoint,
353    action   => $self->on_action->($self->uri),
354    envelope => $serializer->envelope(freeform => $message),
355    encoding => $serializer->encoding,
356  );
357
358  return $respond if $self->outputxml;
359
360  unless ($self->transport->is_success) {
361    my $result = eval { $self->deserializer->deserialize($respond) } if $respond;
362    return $self->on_fault->($self, $@ ? $respond : $result) || $result;
363  }
364
365  return unless $respond; # nothing to do for one-ways
366  return $self->deserializer->deserialize($respond);
367}
368
369# ======================================================================
370
3711;
372
373__END__
374
375=head1 NAME
376
377UDDI::Lite - Library for UDDI clients in Perl
378
379=head1 SYNOPSIS
380
381  use UDDI::Lite;
382  print UDDI::Lite
383    -> proxy('http://uddi.microsoft.com/inquire')
384    -> find_business(name => 'old')
385    -> result
386    -> businessInfos->businessInfo->serviceInfos->serviceInfo->name;
387
388The same code with autodispatch:
389
390  use UDDI::Lite +autodispatch =>
391    proxy => 'http://uddi.microsoft.com/inquire'
392  ;
393
394  print find_business(name => 'old')
395    -> businessInfos->businessInfo->serviceInfos->serviceInfo->name;
396
397Or with importing:
398
399  use UDDI::Lite
400    'UDDI::Lite' => [':inquiry'],
401    proxy => 'http://uddi.microsoft.com/inquire'
402  ;
403
404  print find_business(name => 'old')
405    -> businessInfos->businessInfo->serviceInfos->serviceInfo->name;
406
407Publishing API:
408
409  use UDDI::Lite
410    import => ['UDDI::Data'],
411    import => ['UDDI::Lite'],
412    proxy => "https://some.server.com/endpoint_fot_publishing_API";
413
414  my $auth = get_authToken({userID => 'USERID', cred => 'CRED'})->authInfo;
415  my $busent = with businessEntity =>
416    name("Contoso Manufacturing"),
417    description("We make components for business"),
418    businessKey(''),
419    businessServices with businessService =>
420      name("Buy components"),
421      description("Bindings for buying our components"),
422      serviceKey(''),
423      bindingTemplates with bindingTemplate =>
424        description("BASDA invoices over HTTP post"),
425        accessPoint('http://www.contoso.com/buy.asp'),
426        bindingKey(''),
427        tModelInstanceDetails with tModelInstanceInfo =>
428          description('some tModel'),
429          tModelKey('UUID:C1ACF26D-9672-4404-9D70-39B756E62AB4')
430  ;
431  print save_business($auth, $busent)->businessEntity->businessKey;
432
433=head1 DESCRIPTION
434
435UDDI::Lite for Perl is a collection of Perl modules which provides a
436simple and lightweight interface to the Universal Description, Discovery
437and Integration (UDDI) server.
438
439To learn more about UDDI, visit http://www.uddi.org/.
440
441The main features of the library are:
442
443=over 3
444
445=item *
446
447Supports both inquiry and publishing API
448
449=item *
450
451Builded on top of SOAP::Lite module, hence inherited syntax and features
452
453=item *
454
455Supports easy-to-use interface with convinient access to (sub)elements
456and attributes
457
458=item *
459
460Supports HTTPS protocol
461
462=item *
463
464Supports SMTP protocol
465
466=item *
467
468Supports Basic/Digest server authentication
469
470=back
471
472=head1 OVERVIEW OF CLASSES AND PACKAGES
473
474This table should give you a quick overview of the classes provided by the
475library.
476
477 UDDI::Lite.pm
478 -- UDDI::Lite         -- Main class provides all logic
479 -- UDDI::Data         -- Provides extensions for serialization architecture
480 -- UDDI::Serializer   -- Serializes data structures to UDDI/SOAP package
481 -- UDDI::Deserializer -- Deserializes result into objects
482 -- UDDI::SOM          -- Provides access to deserialized object tree
483
484=head2 UDDI::Lite
485
486All methods that UDDI::Lite gives you access to can be used for both
487setting and retrieving values. If you provide no parameters, you'll
488get current value, and if you'll provide parameter(s), new value
489will be assigned and method will return object (if not stated something
490else). This is suitable for stacking these calls like:
491
492  $uddi = UDDI::Lite
493    -> on_debug(sub{print@_})
494    -> proxy('http://uddi.microsoft.com/inquire')
495  ;
496
497Order is insignificant and you may call new() method first. If you
498don't do it, UDDI::Lite will do it for you. However, new() method
499gives you additional syntax:
500
501  $uddi = new UDDI::Lite
502    on_debug => sub {print@_},
503    proxy => 'http://uddi.microsoft.com/inquire'
504  ;
505
506new() accepts hash with method names and values, and will call
507appropriate method with passed value.
508
509Since new() is optional it won't be mentioned anymore.
510
511Other available methods inherited from SOAP::Lite and most usable are:
512
513=over 4
514
515=item proxy()
516
517Shortcut for C<transport-E<gt>proxy()>. This lets you specify an endpoint and
518also loads the required module at the same time. It is required for dispatching SOAP
519calls. The name of the module will be defined depending on the protocol
520specific for the endpoint. SOAP::Lite will do the rest work.
521
522=item on_fault()
523
524Lets you specify handler for on_fault event. Default behavior is die
525on transport error and does nothing on others. You can change this
526behavior globally or locally, for particular object.
527
528=item on_debug()
529
530Lets you specify handler for on_debug event. Default behavior is do
531nothing. Use +trace/+debug option for UDDI::Lite instead.
532
533=back
534
535To change to UDDI Version 2, use the following pragma:
536
537  use UDDI::Lite uddiversion => 2;
538
539=head2 UDDI::Data
540
541You can use this class if you want to specify value and name for UDDI
542elements.
543For example, C<UDDI::Data-E<gt>name('businessInfo')-E<gt>value(123)> will
544be serialized to C<E<lt>businessInfoE<gt>123E<lt>/businessInfoE<gt>>, as
545well as C<UDDI::Data->name(businessInfo =E<gt> 123)>.
546
547If you want to provide names for your parameters you can either specify
548
549  find_business(name => 'old')
550
551or do it with UDDI::Data:
552
553  find_business(UDDI::Data->name(name => 'old'))
554
555Later has some advantages: it'll work on any level, so you can do:
556
557  find_business(UDDI::Data->name(name => UDDI::Data->name(subname => 'old')))
558
559and also you can create arrays with this syntax:
560
561  find_business(UDDI::Data->name(name =>
562    [UDDI::Data->name(subname1 => 'name1'),
563     UDDI::Data->name(subname2 => 'name2')]))
564
565will be serialized into:
566
567  <find_business xmlns="urn:uddi-org:api" generic="1.0">
568    <name>
569      <subname1>name1</subname1>
570      <subname2>name2</subname2>
571    </name>
572  </find_business>
573
574For standard elements more convinient syntax is available:
575
576  find_business(
577    findQualifiers(findQualifier('sortByNameAsc',
578                                 'caseSensitiveMatch')),
579    name('M')
580  )
581
582and
583
584  find_business(
585    findQualifiers([findQualifier('sortByNameAsc'),
586                    findQualifier('caseSensitiveMatch')]),
587    name('M')
588  )
589
590both will generate:
591
592  <SOAP-ENV:Envelope
593    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
594    <SOAP-ENV:Body>
595      <find_business xmlns="urn:uddi-org:api" generic="1.0">
596        <findQualifiers>
597          <findQualifier>sortByNameAsc</findQualifier>
598          <findQualifier>caseSensitiveMatch</findQualifier>
599        </findQualifiers>
600        <name>M</name>
601      </find_business>
602    </SOAP-ENV:Body>
603  </SOAP-ENV:Envelope>
604
605You can use ANY valid combinations (according to "UDDI Programmer's
606API Specification"). If you try to generate something unusual, like
607C<name(name('myname'))>, you'll get:
608
609  Don't know what to do with 'name' and 'name' elements ....
610
611If you REALLY need to do it, use C<UDDI::Data> syntax described above.
612
613As special case you can pass hash as the first parameter of method
614call and values of this hash will be added as attributes to top element:
615
616  find_business({maxRows => 10}, UDDI::Data->name(name => old))
617
618gives you
619
620  <find_business xmlns="urn:uddi-org:api" generic="1.0" maxRows="10">
621    ....
622  </find_business>
623
624You can also pass back parameters exactly as you get it from method call
625(like you probably want to do with authInfo).
626
627You can get access to attributes and elements through the same interface:
628
629  my $list = find_business(name => old);
630  my $bis = $list->businessInfos;
631  for ($bis->businessInfo) {
632    my $s = $_->serviceInfos->serviceInfo;
633    print $s->name,        # element
634          $s->businessKey, # attribute
635          "\n";
636  }
637
638To match advantages provided by C<with> operator available in other
639languages (like VB) we provide similar functionality that adds you
640flexibility:
641
642    with findQualifiers =>
643      findQualifier => 'sortByNameAsc',
644      findQualifier => 'caseSensitiveMatch'
645
646is the same as:
647
648    with(findQualifiers =>
649      findQualifier('sortByNameAsc'),
650      findQualifier('caseSensitiveMatch'),
651    )
652
653and:
654
655    findQualifiers->with(
656      findQualifier('sortByNameAsc'),
657      findQualifier('caseSensitiveMatch'),
658    )
659
660will all generate the same code as mentioned above:
661
662    findQualifiers(findQualifier('sortByNameAsc',
663                                 'caseSensitiveMatch')),
664
665Advantage of C<with> syntax is the you can specify both attributes and
666elements through the same interface. First argument is element where all
667other elements and attributes will be attached. Provided examples and
668tests cover different syntaxes.
669
670=head2 AUTODISPATCHING
671
672UDDI::Lite provides autodispatching feature that lets you create
673code that looks similar for local and remote access.
674
675For example:
676
677  use UDDI::Lite +autodispatch =>
678    proxy => 'http://uddi.microsoft.com/inquire';
679
680tells autodispatch all UDDI calls to
681'http://uddi.microsoft.com/inquire'. All subsequent calls can look
682like:
683
684  find_business(name => 'old');
685  find_business(UDDI::Data->name(name => 'old'));
686  find_business(name('old'));
687
688=head1 BUGS AND LIMITATIONS
689
690=over 4
691
692=item *
693
694Interface is still subject to change.
695
696=item *
697
698Though HTTPS/SSL is supported you should specify it yourself (with
699C<proxy> or C<endpoint>) for publishing API calls.
700
701=back
702
703=head1 AVAILABILITY
704
705For now UDDI::Lite is distributed as part of SOAP::Lite package.
706You can download it from ( http://soaplite.com/ )
707or from CPAN ( http://search.cpan.org/search?dist=SOAP-Lite ).
708
709=head1 SEE ALSO
710
711L<SOAP::Lite> ( http://search.cpan.org/search?dist=SOAP-Lite )
712L<UDDI> ( http://search.cpan.org/search?dist=UDDI )
713
714=head1 COPYRIGHT
715
716Copyright (C) 2000-2004 Paul Kulchenko. All rights reserved.
717
718This library is free software; you can redistribute it and/or modify
719it under the same terms as Perl itself.
720
721=head1 AUTHOR
722
723Paul Kulchenko (paulclinger@yahoo.com)
724
725=cut
726