/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.xml.ws.typeprovider.paraminfo; import gw.internal.xml.xsd.typeprovider.IXmlSchemaElementTypeData; import gw.internal.xml.xsd.typeprovider.XmlSchemaPropertySpec; import gw.internal.xml.xsd.typeprovider.XmlSchemaTypeSchemaInfo; import gw.internal.xml.xsd.typeprovider.schema.XmlSchemaElement; import gw.internal.xml.xsd.typeprovider.schemaparser.XmlSchemaParser; import gw.lang.reflect.IType; import gw.xml.XmlElement; import javax.xml.namespace.QName; public abstract class WsdlOperationParameterInfo { private final IType _parameterElementType; private final QName _parameterElementName; protected WsdlOperationParameterInfo( IType parameterElementType, QName parameterElementName ) { _parameterElementType = parameterElementType; _parameterElementName = parameterElementName; } public static WsdlOperationParameterInfo create( XmlSchemaPropertySpec parameterPropertySpec ) throws AnonymousElementException { return createComponent( parameterPropertySpec, false, true ); } private static WsdlOperationParameterInfo createComponent( XmlSchemaPropertySpec componentPropertySpec, boolean isComponent, boolean primitiveOk ) throws AnonymousElementException { IXmlSchemaElementTypeData componentTypeData = componentPropertySpec.getElementPropertyGosuTypeData(); XmlSchemaTypeSchemaInfo componentSchemaInfo = componentTypeData.getSchemaInfo(); // perform pre-checks to see if we have a strategy to unwrap this component boolean identity = false; XmlSchemaElement element = (XmlSchemaElement) componentPropertySpec.getXmlSchemaObject(); boolean hasAttributes = hasAttributes( componentSchemaInfo ); boolean hasAny = hasAny( componentSchemaInfo ); if ( ! isComponent ) { // top level parameter must be single and non-nillable if ( componentPropertySpec.isPlural() ) { identity = true; // cannot be plural since there is no wrapping list for now } if ( element.isNillable() ) { identity = true; } } if ( componentPropertySpec.hasSimpleContent() && ! hasAttributes && ! hasAny ) { if ( isComponent && ! primitiveOk && ! element.isNillable() ) { identity = true; } else { return new SimpleContentWsdlOperationParameterInfo( componentPropertySpec, isComponent, primitiveOk ); } } if ( identity ) { return new IdentityWsdlOperationParameterInfo( componentPropertySpec.getElementPropertyGosuType(), componentPropertySpec.getQName(), ! isComponent ); } if ( ! componentSchemaInfo.getTypeData().isAnonymous() ) { return new XmlTypeInstanceWsdlOperationParameterInfo( componentPropertySpec ); } if ( componentSchemaInfo.getProperties().size() == 0 && ! hasAttributes && hasAny ) { return new XmlElementWsdlOperationParameterInfo( componentPropertySpec, null ); } if ( componentSchemaInfo.getProperties().size() == 1 && ! hasAttributes && ! hasAny ) { XmlSchemaPropertySpec childPropertySpec = componentSchemaInfo.getProperties().get( 0 ); if ( childPropertySpec.isPlural() ) { if ( XmlSchemaParser.VIEWAS_LIST.equals( element.getGwViewAs() ) ) { WsdlOperationParameterInfo childParamInfo = createComponent( childPropertySpec, true, false ); if ( childParamInfo != null ) { return new ListWsdlOperationParameterInfo( componentPropertySpec.getElementPropertyGosuType(), componentPropertySpec.getQName(), childParamInfo ); } } else { WsdlOperationParameterInfo childParamInfo = createComponent( childPropertySpec, true, true ); if ( childParamInfo != null ) { return new ArrayWsdlOperationParameterInfo( componentPropertySpec.getElementPropertyGosuType(), componentPropertySpec.getQName(), childParamInfo ); } } } IXmlSchemaElementTypeData childTypeData = childPropertySpec.getElementPropertyGosuTypeData(); if ( ! childTypeData.isAnonymous() ) { return new XmlElementWsdlOperationParameterInfo( componentPropertySpec, childPropertySpec ); } else if ( ! childTypeData.getSchemaInfo().getTypeData().isAnonymous() ) { return new XmlTypeInstanceWsdlOperationParameterInfo( componentPropertySpec ); } } else if ( componentTypeData.isAnonymous() && ! componentSchemaInfo.getTypeData().isAnonymous() ) { // we normally prefer elements, but we prefer a non-anonymous typeinstance over an anonymous element return new XmlTypeInstanceWsdlOperationParameterInfo( componentPropertySpec ); } return new IdentityWsdlOperationParameterInfo( componentPropertySpec.getElementPropertyGosuType(), componentPropertySpec.getQName(), ! isComponent ); } public static boolean hasAttributes( XmlSchemaTypeSchemaInfo componentSchemaInfo ) { return componentSchemaInfo.getXsdType().getAnyAttributeRecursiveIncludingSupertypes() != null || ! componentSchemaInfo.getAttributeNames().isEmpty(); } public static boolean hasAny( XmlSchemaTypeSchemaInfo componentSchemaInfo ) { return componentSchemaInfo.getXsdType().getAnyRecursiveIncludingSupertypes() != null; } public abstract IType getType(); public abstract Object unwrap( XmlElement node ); public abstract String getName(); public abstract XmlElement wrap( Object obj, XmlElement componentElement ); public IType getParameterElementType() { return _parameterElementType; } public QName getParameterElementName() { return _parameterElementName; } }