/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package org.pentaho.di.trans.steps.webservices.wsdl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;
/*
This looks a little scary, but isn't so bad. Pretty much all that needs to be done here is to
parse a NAMED complex type in the wsdl's types section. We really only care about the <element>'s
contained within the complex type. The semantics don't matter (choice, sequence, etc). The end result
should be a ComplexType object which contains only elements. This type will be used during client
type registration.
*/
/**
* A ComplexType contians a map of the elementName -> elementXmlType of all the elements in a named complex type.
*/
public final class ComplexType implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private final HashMap<String, QName> _elements = new HashMap<String, QName>();
private final List<String> _elementNames = new ArrayList<String>();
private final String _name;
private WsdlTypes _wsdlTypes;
/**
* Create a new complex type for the specified element.
*
* @param type
* DOM element of the complex type.
* @param wsdlTypes
* Namespace resolver instance.
*/
ComplexType( Element type, WsdlTypes wsdlTypes ) {
_name = type.getAttribute( "name" );
_wsdlTypes = wsdlTypes;
// annotation?, (simpleContent | complexContent
// | ((group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute?))
Element child;
if ( ( child = DomUtils.getChildElementByName( type, "simpleContent" ) ) != null ) {
processSimpleContent( child );
} else if ( ( child = DomUtils.getChildElementByName( type, "complexContent" ) ) != null ) {
processComplexContent( child );
} else if ( ( child = DomUtils.getChildElementByName( type, "group" ) ) != null ) {
processGroup( child );
} else if ( ( child = DomUtils.getChildElementByName( type, "all" ) ) != null ) {
processAll( child );
} else if ( ( child = DomUtils.getChildElementByName( type, "choice" ) ) != null ) {
processChoice( child );
} else if ( ( child = DomUtils.getChildElementByName( type, "sequence" ) ) != null ) {
processSequence( child );
}
// release the resolver, we don't need it after the parse is complete
_wsdlTypes = null;
}
/**
* Get the complex type name.
*
* @return String containing name of complex type.
*/
public String getName() {
return _name;
}
/**
* Given the name of an element contained within the complex type, get its xml type.
*
* @param elementName
* Name of element contained within complex type.
* @return Xmltype of the element or null if element can not be found in the complex type.
*/
public QName getElementType( String elementName ) {
return _elements.get( elementName.toLowerCase() );
}
/**
* Get the set of all element names contained in this complex type.
*
* @return Set.
*/
public List<String> getElementNames() {
return _elementNames;
}
/* ---- Private Methods --- */
/**
* Process an 'all' element.
*
* @param all
*/
private void processAll( Element all ) {
// annotation?, element*
List<Element> elements = DomUtils.getChildElementsByName( all, "element" );
for ( Iterator<Element> itr = elements.iterator(); itr.hasNext(); ) {
processElement( itr.next() );
}
}
/**
* Process an 'any' element.
*
* @param any
*/
private void processAny( Element any ) {
// annotation?
// *** noop ***
}
// private void processAttribute(Element attribute) {
// // <complexType name="ArrayOf_xsd_short">
// // <complexContent>
// // <restriction base="soapenc:Array">
// // <attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:short[]"/>
// // </restriction>
// // </complexContent>
// // </complexType>
// if (attribute.hasAttribute("wsdl:arrayType")) {
// String attributeName = attribute.getAttribute("ref");
// String arrayType = attribute.getAttribute("wsdl:arrayType");
// _elements.put(attributeName, _wsdlTypes.getTypeQName(arrayType));
// }
// }
/**
* Process a 'choice' element.
*
* @param choice
*/
private void processChoice( Element choice ) {
// annotation?, (element | group | choice | sequence | any)*
// just call process sequence, same elements
processSequence( choice );
}
/**
* Process a 'complexContent' element.
*
* @param complexContent
*/
private void processComplexContent( Element complexContent ) {
// annotation?, (extension | restriction)
Element child;
if ( ( child = DomUtils.getChildElementByName( complexContent, "extension" ) ) != null ) {
processComplexExtension( child );
} else if ( ( child = DomUtils.getChildElementByName( complexContent, "restriction" ) ) != null ) {
processComplexRestriction( child );
}
}
/**
* Process an 'extension' element whose parent is 'complexContent'.
*
* @param complexExtension
*/
private void processComplexExtension( Element complexExtension ) {
// annotation?, (group, | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute?
Element child;
if ( ( child = DomUtils.getChildElementByName( complexExtension, "group" ) ) != null ) {
processGroup( child );
} else if ( ( child = DomUtils.getChildElementByName( complexExtension, "all" ) ) != null ) {
processAll( child );
} else if ( ( child = DomUtils.getChildElementByName( complexExtension, "choice" ) ) != null ) {
processChoice( child );
} else if ( ( child = DomUtils.getChildElementByName( complexExtension, "sequence" ) ) != null ) {
processSequence( child );
}
}
/**
* Process a 'restriction' element whose parent is 'complexContent'.
*
* @param complexRestriction
*/
private void processComplexRestriction( Element complexRestriction ) {
// annotation?, (group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute?
Element child;
if ( ( child = DomUtils.getChildElementByName( complexRestriction, "group" ) ) != null ) {
processGroup( child );
} else if ( ( child = DomUtils.getChildElementByName( complexRestriction, "all" ) ) != null ) {
processAll( child );
} else if ( ( child = DomUtils.getChildElementByName( complexRestriction, "choice" ) ) != null ) {
processChoice( child );
} else if ( ( child = DomUtils.getChildElementByName( complexRestriction, "sequence" ) ) != null ) {
processSequence( child );
}
// else if (DomUtils.getChildElementByName(complexRestriction, "attribute") != null) {
// List<Element> attributes = DomUtils.getChildElementsByName(complexRestriction, "attribute");
// for (Element attribute : attributes) {
// processAttribute(attribute);
// }
// }
}
/**
* Process an 'element'.
*
* @param element
*/
private void processElement( Element element ) {
// annotation?
if ( element.hasAttribute( "name" ) ) {
String elementName = element.getAttribute( "name" );
String elementType = element.getAttribute( "type" );
_elements.put( elementName.toLowerCase(), _wsdlTypes.getTypeQName( elementType ) );
_elementNames.add( elementName );
}
}
/**
* Process a 'group' element.
*
* @param group
*/
private void processGroup( Element group ) {
// annotation?, (all | choice | sequence)
Element child;
if ( ( child = DomUtils.getChildElementByName( group, "all" ) ) != null ) {
processAll( child );
} else if ( ( child = DomUtils.getChildElementByName( group, "choice" ) ) != null ) {
processChoice( child );
} else if ( ( child = DomUtils.getChildElementByName( group, "sequence" ) ) != null ) {
processSequence( child );
}
}
/**
* Process a 'sequence' element.
*
* @param sequence
*/
private void processSequence( Element sequence ) {
// annotation?, (element | group | choice | sequence | any)*
List<Element> elements = DomUtils.getChildElementsByName( sequence, "element" );
for ( Iterator<Element> itr = elements.iterator(); itr.hasNext(); ) {
processElement( itr.next() );
}
elements = DomUtils.getChildElementsByName( sequence, "group" );
for ( Iterator<Element> itr = elements.iterator(); itr.hasNext(); ) {
processGroup( itr.next() );
}
elements = DomUtils.getChildElementsByName( sequence, "choice" );
for ( Iterator<Element> itr = elements.iterator(); itr.hasNext(); ) {
processChoice( itr.next() );
}
elements = DomUtils.getChildElementsByName( sequence, "sequence" );
for ( Iterator<Element> itr = elements.iterator(); itr.hasNext(); ) {
processSequence( itr.next() );
}
elements = DomUtils.getChildElementsByName( sequence, "any" );
for ( Iterator<Element> itr = elements.iterator(); itr.hasNext(); ) {
processAny( itr.next() );
}
}
/**
* Process a 'simpleContent' element.
*
* @param simpleContent
*/
private void processSimpleContent( Element simpleContent ) {
// annotation?, (extension | restriction)
Element child;
if ( ( child = DomUtils.getChildElementByName( simpleContent, "extension" ) ) != null ) {
processSimpleExtension( child );
} else if ( ( child = DomUtils.getChildElementByName( simpleContent, "restriction" ) ) != null ) {
processSimpleRestriction( child );
}
}
/**
* Process an 'extension' element whose parent is 'simpleContent'.
*
* @param any
*/
private void processSimpleExtension( Element any ) {
// annotation?, (attribute | attributeGroup)*, anyAttribute?
// *** noop ***
}
/**
* Process a 'restriction' element whose parent is 'simpleContent'.
*
* @param simpleRestriction
*/
private void processSimpleRestriction( Element simpleRestriction ) {
// annotation?, simpleType?, (enumeration | length | maxExclusive | maxInclusive
// | maxLength | minExclusive | minInclusive | minLength | pattern | fractionDigits
// | totalDigits | whiteSpace)*, (attribute | attributeGroup)*, anyAttribute?
// *** noop ***
}
}