/usr/local/CPAN/CORBA-XMLSchemas/CORBA/XMLSchemas/XsdVisitor.pm
#
# Interface Definition Language (OMG IDL CORBA v3.0)
#
# CORBA to WSDL/SOAP Interworking Specification, Version 1.1 February 2005
#
package CORBA::XMLSchemas::XsdVisitor;
use strict;
use warnings;
our $VERSION = '2.60';
use CORBA::XMLSchemas::BaseVisitor;
use base qw(CORBA::XMLSchemas::BaseVisitor);
use File::Basename;
use POSIX qw(ctime);
use XML::DOM;
# needs $node->{xsd_name} $node->{xsd_qname} (XsdNameVisitor)
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless $self, $class;
my ($parser, $standalone) = @_;
$self->{standalone} = $standalone;
$self->{beautify} = $parser->YYData->{opt_t};
$self->{_xsd} = 'xs';
$self->{xsd} = $parser->YYData->{opt_q} ? 'xs:' : q{};
$self->{_tns} = 'tns';
$self->{tns} = 'tns:';
$self->{_corba} = 'corba';
$self->{corba} = 'corba:';
$self->{srcname} = $parser->YYData->{srcname};
$self->{srcname_size} = $parser->YYData->{srcname_size};
$self->{srcname_mtime} = $parser->YYData->{srcname_mtime};
$self->{symbtab} = $parser->YYData->{symbtab};
$self->{base} = $parser->YYData->{opt_b} || q{};
$self->{root} = $parser->YYData->{root};
my $filename = basename($self->{srcname}, '.idl') . '.xsd';
$self->open_stream($filename);
$self->{done_hash} = {};
$self->{num_key} = 'num_inc_xsd';
$self->{need_corba} = undef;
return $self;
}
sub _standalone {
my $self = shift;
my ($node, $dom_parent) = @_;
if ($self->{standalone}) {
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute("name", $node->{xsd_name});
$element->setAttribute("type", $node->{xsd_qname});
$dom_parent->appendChild($element);
}
}
#
# 3.5 OMG IDL Specification
#
sub visitSpecification {
my $self = shift;
my ($node) = @_;
my $FH = $self->{out};
$self->{dom_doc} = new XML::DOM::Document();
$self->{dom_parent} = $self->{dom_doc};
my $schema = $self->{dom_doc}->createElement($self->{xsd} . 'schema');
$schema->setAttribute('targetNamespace', 'http://www.omg.org/IDL-Mapped/');
unless ($self->{xsd}) {
$schema->setAttribute('xmlns', 'http://www.w3.org/2001/XMLSchema');
}
$schema->setAttribute('xmlns:' . $self->{_xsd}, 'http://www.w3.org/2001/XMLSchema');
$schema->setAttribute('xmlns:' . $self->{_corba}, 'http://www.omg.org/IDL-WSDL/1.0/');
$schema->setAttribute('xmlns:' . $self->{_tns}, 'http://www.omg.org/IDL-Mapped/');
if ($self->{xsd}) {
$schema->setAttribute('elementFormDefault', 'qualified');
$schema->setAttribute('attributeFormDefault', 'unqualified');
}
$self->{dom_parent}->appendChild($schema);
if ($self->{root}->{need_corba} or $self->{root}->{need_any}) {
my $import = $self->{dom_doc}->createElement($self->{xsd} . 'import');
$import->setAttribute('namespace', 'http://www.omg.org/IDL-WSDL/1.0/');
$import->setAttribute('schemaLocation', $self->{base} . 'corba.xsd');
$schema->appendChild($import);
}
if (exists $node->{list_import}) {
foreach (@{$node->{list_import}}) {
$_->visit($self, $schema);
}
}
foreach (@{$node->{list_decl}}) {
$self->_get_defn($_)->visit($self, $schema);
}
if ($self->{beautify}) {
print $FH "<!-- This file was generated (by ",$0,"). DO NOT modify it -->\n";
print $FH "<!-- From file : ",$self->{srcname},", ",$self->{srcname_size}," octets, ",POSIX::ctime($self->{srcname_mtime});
print $FH "-->\n";
print $FH "\n";
print $FH $self->_beautify($self->{dom_doc}->toString());
print $FH "\n\n";
print $FH "<!-- end of file : ",$self->{filename}," -->\n";
}
else {
print $FH $self->{dom_doc}->toString();
}
close $FH;
$self->{dom_doc}->dispose();
}
#
# 3.9 Value Declaration
#
# See 1.2.7.10 ValueType
#
sub visitRegularValue {
my $self = shift;
my ($node, $dom_parent, $indirect) = @_;
foreach (@{$node->{list_decl}}) {
my $value_element = $self->_get_defn($_);
if ( $value_element->isa('StateMembers')
or $value_element->isa('Initializer')
or $value_element->isa('Operation')
or $value_element->isa('Attributes') ) {
next;
}
$value_element->visit($self, $dom_parent);
}
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$complexType->setAttribute('name', $node->{xsd_name});
$dom_parent->appendChild($complexType);
my $extension;
if (exists $node->{inheritance} and exists $node->{inheritance}->{list_value}) {
for (@{$node->{inheritance}->{list_value}}) {
my $base = $self->_get_defn($_);
next unless ($base->isa('RegularValue'));
my $complexContent = $self->{dom_doc}->createElement($self->{xsd} . 'complexContent');
$complexType->appendChild($complexContent);
$extension = $self->{dom_doc}->createElement($self->{xsd} . 'extension');
$extension->setAttribute('base', $self->{tns} . $base->{xsd_name});
$complexContent->appendChild($extension);
last;
}
}
my $sequence = $self->{dom_doc}->createElement($self->{xsd} . 'sequence');
if ($extension) {
$extension->appendChild($sequence);
}
else {
$complexType->appendChild($sequence);
$self->_value_id($complexType);
}
foreach (@{$node->{list_decl}}) {
my $defn = $self->_get_defn($_);
if ($defn->isa('StateMembers')) {
$defn->visit($self, $sequence);
}
}
$self->_standalone($node, $dom_parent) unless ($indirect);
}
sub _value_id {
my $self = shift;
my ($dom_parent) = @_;
my $attribute = $self->{dom_doc}->createElement($self->{xsd} . 'attribute');
$attribute->setAttribute('name', 'id');
$attribute->setAttribute('type', $self->{xsd} . 'ID');
$attribute->setAttribute('use', 'optional');
$dom_parent->appendChild($attribute);
}
sub visitStateMember {
my $self = shift;
my ($node, $dom_parent) = @_;
my $type = $self->_get_defn($node->{type});
if (exists $node->{array_size}) {
# like Array
my $idx = scalar(@{$node->{array_size}}) - 1;
my $current = $type;
while ($current->isa('SequenceType')) {
$idx ++;
$current = $self->_get_defn($current->{type});
}
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute('name', $node->{xsd_name});
$element->setAttribute('maxOccurs', '1');
$element->setAttribute('minOccurs', '1');
$dom_parent->appendChild($element);
$current = $element;
my $first = 1;
foreach (reverse @{$node->{array_size}}) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$current->appendChild($complexType);
my $sequence = $self->{dom_doc}->createElement($self->{xsd} . 'sequence');
$complexType->appendChild($sequence);
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
my $item = ($idx != 0) ? 'item' . $idx : 'item';
$element->setAttribute('name', $item);
$element->setAttribute('minOccurs', $self->_value($_));
$element->setAttribute('maxOccurs', $self->_value($_));
$sequence->appendChild($element);
$current = $element;
$idx --;
$first = 0;
}
if ($type->isa('SequenceType')) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$current->appendChild($complexType);
$type->visit($self, $complexType);
}
else {
$current->setAttribute('type', $type->{xsd_qname});
}
}
else {
if ($type->isa('RegularValue')) {
my $choice = $self->{dom_doc}->createElement($self->{xsd} . 'choice');
$dom_parent->appendChild($choice);
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute('name', $node->{xsd_name});
$element->setAttribute('maxOccurs', '1');
$element->setAttribute('minOccurs', '1');
$element->setAttribute('type', $type->{xsd_qname});
$choice->appendChild($element);
$element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute('name', '_REF_' . $node->{xsd_name});
$element->setAttribute('maxOccurs', '1');
$element->setAttribute('minOccurs', '1');
$element->setAttribute('type', $self->{corba} . '_VALREF');
$choice->appendChild($element);
}
else {
# like Single
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute('name', $node->{xsd_name});
$element->setAttribute('maxOccurs', '1');
$element->setAttribute('minOccurs', '1');
$element->setAttribute('nillable', 'true')
if ($type->isa('StringType') or $type->isa('WideStringType'));
$dom_parent->appendChild($element);
if ($type->isa('SequenceType')) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$element->appendChild($complexType);
$type->visit($self, $complexType);
}
else {
$element->setAttribute('type', $type->{xsd_qname});
}
}
}
}
sub visitBoxedValue {
my $self = shift;
my ($node, $dom_parent, $indirect) = @_;
my $type = $self->_get_defn($node->{type});
if ( $type->isa('StructType')
or $type->isa('UnionType')
or $type->isa('EnumType') ) {
$type->visit($self, $dom_parent);
}
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$complexType->setAttribute('name', $node->{xsd_name});
$dom_parent->appendChild($complexType);
my $sequence = $self->{dom_doc}->createElement($self->{xsd} . 'sequence');
$complexType->appendChild($sequence);
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute('name', 'value');
$element->setAttribute('maxOccurs', '1');
$element->setAttribute('minOccurs', '1');
$element->setAttribute('nillable', 'true')
if ($type->isa('StringType') or $type->isa('WideStringType'));
$sequence->appendChild($element);
if ($type->isa('SequenceType')) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$element->appendChild($complexType);
$type->visit($self, $complexType);
}
else {
$element->setAttribute('type', $type->{xsd_qname});
}
$self->_value_id($complexType);
$self->_standalone($node, $dom_parent) unless ($indirect);
}
#
# 3.11 Type Declaration
#
# See 1.2.7.3 Typedefs
#
sub visitTypeDeclarator {
my $self = shift;
my ($node, $dom_parent, $indirect) = @_;
my $type = $self->_get_defn($node->{type});
while ($type->isa('TypeDeclarator') and !exists $type->{array_size}) {
$type = $self->_get_defn($type->{type});
}
if ( $type->isa('StructType')
or $type->isa('UnionType')
or $type->isa('EnumType') ) {
$type->visit($self, $dom_parent);
}
if (exists $node->{array_size}) {
#
# See 1.2.7.6 Arrays
#
warn __PACKAGE__,"::visitTypeDecalarator $node->{idf} : empty array_size.\n"
unless (@{$node->{array_size}});
my $idx = scalar(@{$node->{array_size}}) - 1;
my $current = $type;
while ($current->isa('SequenceType')) {
$idx ++;
$current = $self->_get_defn($current->{type});
}
$current = $dom_parent;
my $first = 1;
foreach (reverse @{$node->{array_size}}) {
my $complexType;
if ($indirect and $first) {
$complexType = $dom_parent;
}
else {
$complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$complexType->setAttribute("name", $node->{xsd_name})
if ($first);
$current->appendChild($complexType);
}
my $sequence = $self->{dom_doc}->createElement($self->{xsd} . 'sequence');
$complexType->appendChild($sequence);
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
my $item = ($idx != 0) ? 'item' . $idx : 'item';
$element->setAttribute('name', $item);
$element->setAttribute('minOccurs', $self->_value($_));
$element->setAttribute('maxOccurs', $self->_value($_));
$sequence->appendChild($element);
$current = $element;
$idx --;
$first = 0;
}
if ($type->isa('SequenceType')) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$current->appendChild($complexType);
$type->visit($self, $complexType);
}
else {
$current->setAttribute("type", $type->{xsd_qname});
}
}
else {
if ( $type->isa('SequenceType')
or $type->isa('TypeDeclarator') ) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$complexType->setAttribute('name', $node->{xsd_name});
$dom_parent->appendChild($complexType);
$type->visit($self, $complexType, 1);
}
else {
if ( $type->isa('Value')
or $type->isa('StructType')
or $type->isa('UnionType') ) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$complexType->setAttribute('name', $node->{xsd_name});
$dom_parent->appendChild($complexType);
my $complexContext = $self->{dom_doc}->createElement($self->{xsd} . 'complexContent');
$complexType->appendChild($complexContext);
my $restriction = $self->{dom_doc}->createElement($self->{xsd} . 'restriction');
$restriction->setAttribute('base', $type->{xsd_qname});
$complexContext->appendChild($restriction);
$type->visit($self, $restriction, 1);
}
else {
my $simpleType = $self->{dom_doc}->createElement($self->{xsd} . 'simpleType');
$simpleType->setAttribute('name', $node->{xsd_name});
$dom_parent->appendChild($simpleType);
if ( $type->isa('EnumType')
or $type->isa('BaseInterface') ) {
my $restriction = $self->{dom_doc}->createElement($self->{xsd} . 'restriction');
$restriction->setAttribute('base', $type->{xsd_qname});
$simpleType->appendChild($restriction);
}
else {
$type->visit($self, $simpleType);
}
}
}
}
$self->_standalone($node, $dom_parent) unless ($indirect);
}
#
# 3.11.1 Basic Types
#
sub visitCharType {
my $self = shift;
my ($node, $dom_parent) = @_;
my $restriction = $self->{dom_doc}->createElement($self->{xsd} . 'restriction');
$restriction->setAttribute('base', $node->{xsd_qname});
$dom_parent->appendChild($restriction);
my $length = $self->{dom_doc}->createElement($self->{xsd} . 'length');
$length->setAttribute('value', '1');
$length->setAttribute('fixed', 'true');
$restriction->appendChild($length);
}
sub visitBasicType {
my $self = shift;
my ($node, $dom_parent) = @_;
my $restriction = $self->{dom_doc}->createElement($self->{xsd} . 'restriction');
$restriction->setAttribute('base', $node->{xsd_qname});
$dom_parent->appendChild($restriction);
}
#
# 3.11.2 Constructed Types
#
# 3.11.2.1 Structures
#
# See 1.2.7.2 Structure
#
sub visitStructType {
my $self = shift;
my ($node, $dom_parent, $indirect) = @_;
if ($indirect) {
$self->_StructType_Content($node, $dom_parent);
return;
}
return if (exists $self->{done_hash}->{$node->{xsd_name}});
$self->{done_hash}->{$node->{xsd_name}} = 1;
foreach (@{$node->{list_expr}}) {
my $type = $self->_get_defn($_->{type});
if ( $type->isa('StructType')
or $type->isa('UnionType') ) {
$type->visit($self, $dom_parent);
}
}
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$complexType->setAttribute('name', $node->{xsd_name});
$dom_parent->appendChild($complexType);
$self->_StructType_Content($node, $complexType);
$self->_standalone($node, $dom_parent) unless ($indirect);
}
sub _StructType_Content {
my $self = shift;
my ($node, $dom_parent) = @_;
my $sequence = $self->{dom_doc}->createElement($self->{xsd} . 'sequence');
$dom_parent->appendChild($sequence);
foreach (@{$node->{list_member}}) {
$self->_get_defn($_)->visit($self, $sequence);
}
}
sub visitMember {
my $self = shift;
my ($node, $dom_parent) = @_;
my $type = $self->_get_defn($node->{type});
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute('name', $node->{xsd_name});
$element->setAttribute('maxOccurs', '1');
$element->setAttribute('minOccurs', '1');
$dom_parent->appendChild($element);
my $current = $element;
if (exists $node->{array_size}) {
my $idx = scalar(@{$node->{array_size}}) - 1;
my $curr = $type;
while ($curr->isa('SequenceType')) {
$idx ++;
$curr = $self->_get_defn($curr->{type});
}
my $first = 1;
foreach (reverse @{$node->{array_size}}) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$current->appendChild($complexType);
my $sequence = $self->{dom_doc}->createElement($self->{xsd} . 'sequence');
$complexType->appendChild($sequence);
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
my $item = ($idx != 0) ? 'item' . $idx : 'item';
$element->setAttribute('name', $item);
$element->setAttribute('minOccurs', $self->_value($_));
$element->setAttribute('maxOccurs', $self->_value($_));
$sequence->appendChild($element);
$current = $element;
$idx --;
$first = 0;
}
}
if ($type->isa('SequenceType')) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$current->appendChild($complexType);
$type->visit($self, $complexType);
}
else {
$current->setAttribute('type', $type->{xsd_qname});
}
}
# 3.11.2.2 Discriminated Unions
#
# See 1.2.7.4 Unions
#
sub visitUnionType {
my $self = shift;
my ($node, $dom_parent, $indirect) = @_;
if ($indirect) {
$self->_UnionType_Content($node, $dom_parent);
return;
}
return if (exists $self->{done_hash}->{$node->{xsd_name}});
$self->{done_hash}->{$node->{xsd_name}} = 1;
foreach (@{$node->{list_expr}}) {
my $type = $self->_get_defn($_->{element}->{type});
if ( $type->isa('StructType')
or $type->isa('UnionType') ) {
$type->visit($self, $dom_parent);
}
}
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$complexType->setAttribute('name', $node->{xsd_name});
$dom_parent->appendChild($complexType);
$self->_UnionType_Content($node, $complexType);
$self->_standalone($node, $dom_parent) unless ($indirect);
}
sub _UnionType_Content {
my $self = shift;
my ($node, $dom_parent) = @_;
my $type = $self->_get_defn($node->{type});
my $sequence = $self->{dom_doc}->createElement($self->{xsd} . 'sequence');
$dom_parent->appendChild($sequence);
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute('name', 'discriminator');
$sequence->appendChild($element);
if ($type->isa('EnumType')) {
$type->visit($self, $element, 1);
}
else {
$element->setAttribute('type', $type->{xsd_qname});
}
my $choice = $self->{dom_doc}->createElement($self->{xsd} . 'choice');
$sequence->appendChild($choice);
foreach (@{$node->{list_expr}}) {
$_->visit($self, $choice); # case
}
}
sub visitCase {
my $self = shift;
my ($node, $dom_parent) = @_;
my $str = ' case';
my $first = 1;
foreach (@{$node->{list_label}}) {
$str .= ',' unless ($first);
$str .= q{ };
if ($_->isa('Default')) {
$str .= 'default';
}
else {
$str .= $self->_value($_);
}
$first = 0;
}
$str .= q{ };
my $comment = $self->{dom_doc}->createComment($str);
$dom_parent->appendChild($comment);
$self->_get_defn($node->{element}->{value})->visit($self, $dom_parent); # single or array
}
# 3.11.2.4 Enumerations
#
# See 1.2.7.1 Enum
#
sub visitEnumType {
my $self = shift;
my ($node, $dom_parent, $indirect) = @_;
return if (exists $self->{done_hash}->{$node->{xsd_name}});
$self->{done_hash}->{$node->{xsd_name}} = 1;
my $simpleType = $self->{dom_doc}->createElement($self->{xsd} . 'simpleType');
$simpleType->setAttribute('name', $node->{xsd_name})
unless ($indirect);
$dom_parent->appendChild($simpleType);
my $restriction = $self->{dom_doc}->createElement($self->{xsd} . 'restriction');
$restriction->setAttribute('base', $self->{xsd} . 'string');
$simpleType->appendChild($restriction);
foreach (@{$node->{list_expr}}) {
$_->visit($self, $restriction); # enum
}
$self->_standalone($node, $dom_parent) unless ($indirect);
}
sub visitEnum {
my $self = shift;
my ($node, $dom_parent) = @_;
my $FH = $self->{out};
my $enumeration = $self->{dom_doc}->createElement($self->{xsd} . 'enumeration');
$enumeration->setAttribute('value', $node->{xsd_name});
$dom_parent->appendChild($enumeration);
}
#
# 3.11.3 Template Types
#
# See 1.2.7.5 Sequences
#
sub visitSequenceType {
my $self = shift;
my ($node, $dom_parent) = @_;
my $type = $self->_get_defn($node->{type});
my $idx = 0;
my $current = $type;
while ($current->isa('SequenceType')) {
$idx ++;
$current = $self->_get_defn($current->{type});
}
my $sequence = $self->{dom_doc}->createElement($self->{xsd} . 'sequence');
$dom_parent->appendChild($sequence);
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
my $item = ($idx != 0) ? 'item' . $idx : 'item';
$element->setAttribute('name', $item);
$element->setAttribute('minOccurs', 0);
my $max = (exists $node->{max}) ? $self->_value($node->{max}) : 'unbounded';
$element->setAttribute('maxOccurs', $max);
$sequence->appendChild($element);
if ($type->isa('SequenceType')) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$element->appendChild($complexType);
$type->visit($self, $complexType);
}
else {
$element->setAttribute('type', $type->{xsd_qname});
}
}
#
# See 1.2.6 Primitive Types
#
sub visitStringType {
my $self = shift;
my ($node, $dom_parent) = @_;
my $restriction = $self->{dom_doc}->createElement($self->{xsd} . 'restriction');
$restriction->setAttribute('base', $node->{xsd_qname});
$dom_parent->appendChild($restriction);
if (exists $node->{max}) {
my $maxLength = $self->{dom_doc}->createElement($self->{xsd} . 'maxLength');
$maxLength->setAttribute('value', $self->_value($node->{max}));
$maxLength->setAttribute('fixed', 'true');
$restriction->appendChild($maxLength);
}
}
#
# See 1.2.6 Primitive Types
#
sub visitWideStringType {
my $self = shift;
my ($node, $dom_parent) = @_;
my $restriction = $self->{dom_doc}->createElement($self->{xsd} . 'restriction');
$restriction->setAttribute('base', $node->{xsd_qname});
$dom_parent->appendChild($restriction);
}
#
# See 1.2.7.9 Fixed
#
sub visitFixedPtType {
my $self = shift;
my ($node, $dom_parent) = @_;
my $restriction = $self->{dom_doc}->createElement($self->{xsd} . 'restriction');
$restriction->setAttribute('base', $node->{xsd_qname});
$dom_parent->appendChild($restriction);
my $totalDigits = $self->{dom_doc}->createElement($self->{xsd} . 'totalDigits');
$totalDigits->setAttribute('value', $self->_value($node->{d}));
$restriction->appendChild($totalDigits);
my $fractionDigits = $self->{dom_doc}->createElement($self->{xsd} . 'fractionDigits');
$fractionDigits->setAttribute('value', $self->_value($node->{s}));
$fractionDigits->setAttribute('fixed', 'true');
$restriction->appendChild($fractionDigits);
}
#
# 3.12 Exception Declaration
#
# See 1.2.8.5 Exceptions
#
sub visitException {
my $self = shift;
my ($node, $dom_parent, $indirect) = @_;
if ($indirect) {
$self->_StructType_Content($node, $dom_parent);
return;
}
return if (exists $self->{done_hash}->{$node->{xsd_name}});
$self->{done_hash}->{$node->{xsd_name}} = 1;
if (exists $node->{list_expr}) {
warn __PACKAGE__,"::visitException $node->{idf} : empty list_expr.\n"
unless (@{$node->{list_expr}});
foreach (@{$node->{list_expr}}) {
my $type = $self->_get_defn($_->{type});
if ( $type->isa('StructType')
or $type->isa('UnionType') ) {
$type->visit($self, $dom_parent);
}
}
}
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$complexType->setAttribute('name', $node->{xsd_name});
$dom_parent->appendChild($complexType);
$self->_StructType_Content($node, $complexType);
$self->_standalone($node, $dom_parent) unless ($indirect);
}
#
# 3.13 Operation Declaration
#
# See 1.2.8.2 Interface as Binding Operations
#
sub visitOperation {
my $self = shift;
my ($node, $dom_parent) = @_;
return unless ($self->{standalone});
if (scalar(@{$node->{list_in}}) + scalar(@{$node->{list_inout}})) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$complexType->setAttribute('name', $node->{xsd_name});
$dom_parent->appendChild($complexType);
my $sequence = $self->{dom_doc}->createElement($self->{xsd} . 'sequence');
$complexType->appendChild($sequence);
foreach (@{$node->{list_param}}) { # parameter
if ( $_->{attr} eq 'in'
or $_->{attr} eq 'inout' ) {
$_->visit($self, $sequence);
}
}
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute('name', $node->{xsd_name});
$element->setAttribute('type', $node->{xsd_qname});
$dom_parent->appendChild($element);
}
my $type = $self->_get_defn($node->{type});
if (scalar(@{$node->{list_inout}}) + scalar(@{$node->{list_out}})
or ! $type->isa('VoidType') ) {
my $complexType = $self->{dom_doc}->createElement($self->{xsd} . 'complexType');
$complexType->setAttribute('name', $node->{xsd_name} . 'Response');
$dom_parent->appendChild($complexType);
my $sequence = $self->{dom_doc}->createElement($self->{xsd} . 'sequence');
$complexType->appendChild($sequence);
unless ($type->isa('VoidType')) {
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute('name', '_return');
$element->setAttribute('maxOccurs', '1');
$element->setAttribute('minOccurs', '1');
$element->setAttribute('nillable', 'true')
if ($type->isa('StringType') or $type->isa('WideStringType'));
$element->setAttribute('type', $type->{xsd_qname});
$sequence->appendChild($element);
}
foreach (@{$node->{list_param}}) { # parameter
if ( $_->{attr} eq 'inout'
or $_->{attr} eq 'out' ) {
$_->visit($self, $sequence);
}
}
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute('name', $node->{xsd_name} . 'Response');
$element->setAttribute('type', $node->{xsd_qname} . 'Response');
$dom_parent->appendChild($element);
}
}
sub visitParameter {
my $self = shift;
my ($node, $dom_parent) = @_;
my $type = $self->_get_defn($node->{type});
my $element = $self->{dom_doc}->createElement($self->{xsd} . 'element');
$element->setAttribute('name', $node->{xsd_name});
$element->setAttribute('maxOccurs', '1');
$element->setAttribute('minOccurs', '1');
$element->setAttribute('nillable', 'true')
if ($type->isa('StringType') or $type->isa('WideStringType'));
$element->setAttribute('type', $type->{xsd_qname});
$dom_parent->appendChild($element);
}
1;