/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.yoko.tools.processors.wsdl;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javax.wsdl.Definition;
import javax.wsdl.Input;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.Output;
import javax.wsdl.Part;
import javax.xml.namespace.QName;
import org.apache.schemas.yoko.bindings.corba.ArgType;
import org.apache.schemas.yoko.bindings.corba.ModeType;
import org.apache.schemas.yoko.bindings.corba.ParamType;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaAnnotation;
import org.apache.ws.commons.schema.XmlSchemaChoice;
import org.apache.ws.commons.schema.XmlSchemaComplexContent;
import org.apache.ws.commons.schema.XmlSchemaComplexContentExtension;
import org.apache.ws.commons.schema.XmlSchemaComplexType;
import org.apache.ws.commons.schema.XmlSchemaContentModel;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaImport;
import org.apache.ws.commons.schema.XmlSchemaObject;
import org.apache.ws.commons.schema.XmlSchemaObjectCollection;
import org.apache.ws.commons.schema.XmlSchemaObjectTable;
import org.apache.ws.commons.schema.XmlSchemaParticle;
import org.apache.ws.commons.schema.XmlSchemaSequence;
import org.apache.ws.commons.schema.XmlSchemaType;
import org.apache.yoko.wsdl.CorbaTypeImpl;
public final class WSDLParameter {
static Definition definition;
public void processParameters(WSDLToCorbaBinding wsdlToCorbaBinding,
Operation operation, Definition def, List<XmlSchema> xmlSchemaList,
List<ParamType> params, List<ArgType> returns,
boolean simpleOrdering) throws Exception {
definition = def;
List<ParamType> inputs = new ArrayList<ParamType>();
List<ParamType> outputs = new ArrayList<ParamType>();
List<ArgType> returnOutputs = new ArrayList<ArgType>();
if (inputPartsHaveNoDocWrapper(operation.getName(), operation,
xmlSchemaList)) {
processWrappedInputParams(wsdlToCorbaBinding, operation,
xmlSchemaList, inputs);
} else {
processInputParams(wsdlToCorbaBinding, operation, xmlSchemaList,
inputs);
}
if (outputPartsHaveNoDocWrapper(operation.getName(), operation,
xmlSchemaList)) {
processWrappedOutputParams(wsdlToCorbaBinding, operation,
xmlSchemaList, inputs, outputs);
} else {
processOutputParams(wsdlToCorbaBinding, operation, xmlSchemaList,
inputs, outputs);
}
processReturnParams(outputs, returnOutputs);
orderParameters(inputs, outputs, true);
returns.addAll(returnOutputs);
params.addAll(inputs);
}
private void processWrappedInputParams(
WSDLToCorbaBinding wsdlToCorbaBinding, Operation operation,
List<XmlSchema> xmlSchemaList, List<ParamType> inputs)
throws Exception {
Input input = operation.getInput();
if (input != null) {
Message msg = input.getMessage();
Iterator i = msg.getOrderedParts(null).iterator();
while (i.hasNext()) {
Part part = (Part) i.next();
XmlSchemaType schemaType = null;
schemaType = lookUpType(part, xmlSchemaList);
if (part.getElementName() != null) {
// its an anonymous type
if (schemaType instanceof XmlSchemaComplexType
&& schemaType.getName() == null) {
Iterator it = getSchemaIterator(schemaType);
Iterator iter = getSchemaIterator(schemaType);
addParams(wsdlToCorbaBinding, inputs, it, iter);
} else {
XmlSchemaElement el = getElement(part, xmlSchemaList);
if (schemaType == null) {
addParam(wsdlToCorbaBinding, schemaType, part
.getName(), el.getSchemaTypeName(), el
.isNillable(), inputs);
} else {
addParam(wsdlToCorbaBinding, schemaType, part
.getName(), part.getElementName(), el
.isNillable(), inputs);
}
}
} else {
if (part.getTypeName() != null) {
addParam(wsdlToCorbaBinding, schemaType,
part.getName(), part.getTypeName(), false,
inputs);
}
}
}
}
}
private void addParams(WSDLToCorbaBinding wsdlToCorbaBinding,
List<ParamType> inputs, Iterator it, Iterator iter)
throws Exception {
if (it != null) {
while (it.hasNext()) {
if (it.next() instanceof XmlSchemaElement) {
XmlSchemaElement el = (XmlSchemaElement) iter.next();
addParam(wsdlToCorbaBinding, el.getSchemaType(), el
.getQName().getLocalPart(), el.getSchemaTypeName(),
el.isNillable(), inputs);
}
}
}
}
private void processInputParams(WSDLToCorbaBinding wsdlToCorbaBinding,
Operation operation, List<XmlSchema> xmlSchemaList,
List<ParamType> inputs) throws Exception {
Input input = operation.getInput();
if (input != null) {
Message msg = input.getMessage();
Iterator i = msg.getOrderedParts(null).iterator();
while (i.hasNext()) {
Part part = (Part) i.next();
XmlSchemaType schemaType = null;
schemaType = lookUpType(part, xmlSchemaList);
if (part.getElementName() != null) {
XmlSchemaElement el = getElement(part, xmlSchemaList);
addParam(wsdlToCorbaBinding, schemaType, part.getName(),
part.getElementName(), el.isNillable(), inputs);
} else if (part.getTypeName() != null) {
addParam(wsdlToCorbaBinding, schemaType, part.getName(),
part.getTypeName(), false, inputs);
}
}
}
}
private void addParam(WSDLToCorbaBinding wsdlToCorbaBinding,
XmlSchemaType schemaType, String name, QName typeName,
boolean nillable, List<ParamType> inputs) throws Exception {
ParamType paramtype = createParam(wsdlToCorbaBinding, "in", schemaType,
name, typeName, nillable);
if (paramtype != null) {
inputs.add(paramtype);
}
}
private void processWrappedOutputParams(
WSDLToCorbaBinding wsdlToCorbaBinding, Operation operation,
List<XmlSchema> xmlSchemaList, List<ParamType> inputs,
List<ParamType> outputs) throws Exception {
Output output = operation.getOutput();
if (output != null) {
Message msg = output.getMessage();
Iterator i = msg.getOrderedParts(null).iterator();
while (i.hasNext()) {
Part part = (Part) i.next();
XmlSchemaType schemaType = null;
schemaType = lookUpType(part, xmlSchemaList);
// check if in input list
if (part.getElementName() != null) {
if (schemaType instanceof XmlSchemaComplexType
&& schemaType.getName() == null) {
Iterator it = getSchemaIterator(schemaType);
Iterator iter = getSchemaIterator(schemaType);
updateLists(wsdlToCorbaBinding, inputs, outputs, it,
iter);
} else {
XmlSchemaElement el = getElement(part, xmlSchemaList);
if (schemaType == null) {
updateList(wsdlToCorbaBinding, schemaType, part
.getName(), el.getSchemaTypeName(), inputs,
outputs, el.isNillable());
} else {
updateList(wsdlToCorbaBinding, schemaType, part
.getName(), part.getElementName(), inputs,
outputs, el.isNillable());
}
}
} else {
if (part.getTypeName() != null) {
updateList(wsdlToCorbaBinding, schemaType, part
.getName(), part.getTypeName(), inputs,
outputs, false);
}
}
}
}
}
private void updateLists(WSDLToCorbaBinding wsdlToCorbaBinding,
List<ParamType> inputs, List<ParamType> outputs, Iterator it,
Iterator iter) throws Exception {
if (it != null) {
while (it.hasNext()) {
if (it.next() instanceof XmlSchemaElement) {
XmlSchemaElement el = (XmlSchemaElement) iter.next();
updateList(wsdlToCorbaBinding, el.getSchemaType(), el
.getQName().getLocalPart(), el.getSchemaTypeName(),
inputs, outputs, el.isNillable());
}
}
}
}
private void processOutputParams(WSDLToCorbaBinding wsdlToCorbaBinding,
Operation operation, List<XmlSchema> xmlSchemaList,
List<ParamType> inputs, List<ParamType> outputs) throws Exception {
Output output = operation.getOutput();
if (output != null) {
Message msg = output.getMessage();
Iterator i = msg.getOrderedParts(null).iterator();
while (i.hasNext()) {
Part part = (Part) i.next();
XmlSchemaType schemaType = null;
schemaType = lookUpType(part, xmlSchemaList);
// check if in input list
String mode = "out";
ParamType paramtype = null;
for (int x = 0; x < inputs.size(); x++) {
paramtype = null;
ParamType d2 = (ParamType) inputs.get(x);
if (part.getName() != null
&& d2.getName().equals(part.getName())) {
inputs.remove(x);
if (part.getElementName() != null) {
XmlSchemaElement el = getElement(part,
xmlSchemaList);
paramtype = createParam(wsdlToCorbaBinding,
"inout", schemaType, part.getName(), part
.getElementName(), el.isNillable());
} else {
paramtype = createParam(wsdlToCorbaBinding,
"inout", schemaType, part.getName(), part
.getTypeName(), false);
}
inputs.add(paramtype);
}
}
if (paramtype == null) {
if (part.getElementName() != null) {
XmlSchemaElement el = getElement(part, xmlSchemaList);
paramtype = createParam(wsdlToCorbaBinding, mode,
schemaType, part.getName(), part
.getElementName(), el.isNillable());
} else {
paramtype = createParam(wsdlToCorbaBinding, mode,
schemaType, part.getName(), part.getTypeName(),
false);
}
if (paramtype != null) {
outputs.add(paramtype);
}
}
}
}
}
private void processReturnParams(List<ParamType> outputs,
List<ArgType> returns) {
if (outputs.size() > 0) {
ParamType d2 = (ParamType) outputs.get(0);
if (d2.getMode().value().equals("out")) {
ArgType argType = new ArgType();
argType.setName(d2.getName());
argType.setIdltype(d2.getIdltype());
returns.add(argType);
outputs.remove(0);
}
}
}
private void orderParameters(List<ParamType> inputs,
List<ParamType> outputs, boolean simpleOrdering) {
ListIterator<ParamType> inputit = inputs.listIterator();
while (inputit.hasNext()) {
ParamType d2 = (ParamType) inputit.next();
if (d2.getMode().value().equals("inout")) {
ListIterator it = outputs.listIterator();
while (it.hasNext()) {
ParamType d3 = (ParamType) it.next();
if (!d3.getName().equals(d2.getName())) {
if ((!simpleOrdering)
&& (!d3.getMode().value().equals("inout"))) {
// the in/outs are in a different order in the
// output than the input
// we'll try and use the input oder for the INOUT's,
// but also try and
// maintain some sort of ordering for the OUT's
it.remove();
inputit.previous();
inputit.add(d3);
inputit.next();
}
}
}
}
}
ListIterator<ParamType> it = outputs.listIterator();
while (it.hasNext()) {
ParamType d3 = (ParamType) it.next();
inputs.add(d3);
}
}
private void updateList(WSDLToCorbaBinding wsdlToCorbaBinding,
XmlSchemaType schemaType, String name, QName typeName,
List<ParamType> inputs, List<ParamType> outputs, boolean nillable)
throws Exception {
ParamType paramtype = null;
for (int x = 0; x < inputs.size(); x++) {
paramtype = null;
ParamType d2 = (ParamType) inputs.get(x);
if (d2.getName().equals(name)) {
inputs.remove(x);
paramtype = createParam(wsdlToCorbaBinding, "inout",
schemaType, name, typeName, nillable);
if (paramtype != null) {
inputs.add(paramtype);
}
}
}
if (paramtype == null) {
paramtype = createParam(wsdlToCorbaBinding, "out", schemaType,
name, typeName, nillable);
if (paramtype != null) {
outputs.add(paramtype);
}
}
}
private Iterator getSchemaIterator(XmlSchemaType schemaType) {
if (schemaType instanceof XmlSchemaComplexType) {
XmlSchemaComplexType cpt = (XmlSchemaComplexType) schemaType;
XmlSchemaParticle particle = null;
if (cpt.getParticle() != null) {
particle = (XmlSchemaParticle) cpt.getParticle();
if (particle instanceof XmlSchemaSequence) {
XmlSchemaSequence seq = (XmlSchemaSequence) particle;
return seq.getItems().getIterator();
} else if (particle instanceof XmlSchemaChoice) {
XmlSchemaChoice choice = (XmlSchemaChoice) particle;
return choice.getItems().getIterator();
}
}
if (cpt.getContentModel() != null) {
XmlSchemaContentModel xscm = (XmlSchemaContentModel) cpt
.getContentModel();
if (xscm instanceof XmlSchemaComplexContent) {
XmlSchemaComplexContent xscc = (XmlSchemaComplexContent) xscm;
XmlSchemaComplexContentExtension ext = null;
if (xscc.getContent() instanceof XmlSchemaComplexContentExtension) {
ext = (XmlSchemaComplexContentExtension) xscc
.getContent();
}
if (ext.getParticle() instanceof XmlSchemaSequence) {
XmlSchemaSequence seq = (XmlSchemaSequence) ext
.getParticle();
return seq.getItems().getIterator();
} else if (ext.getParticle() instanceof XmlSchemaChoice) {
XmlSchemaChoice choice = (XmlSchemaChoice) ext
.getParticle();
return choice.getItems().getIterator();
}
}
}
}
return null;
}
private static XmlSchemaType lookUpType(Part part,
List<XmlSchema> xmlSchemaList) throws Exception {
XmlSchemaType schemaType = null;
Iterator i = xmlSchemaList.iterator();
while (i.hasNext()) {
XmlSchema xmlSchemaType = (XmlSchema) i.next();
if (part.getElementName() != null) {
XmlSchemaElement schemaElement = xmlSchemaType
.getElementByName(part.getElementName());
if (schemaElement == null) {
QName elName = part.getElementName();
String prefix = definition.getPrefix(elName
.getNamespaceURI());
QName name = new QName(elName.getNamespaceURI(), prefix
+ ":" + elName.getLocalPart(), prefix);
schemaElement = xmlSchemaType.getElementByName(name);
}
if (schemaElement != null) {
if (schemaElement.getSchemaType() != null) {
schemaType = schemaElement.getSchemaType();
}
}
} else {
if (part.getTypeName() != null) {
schemaType = xmlSchemaType
.getTypeByName(part.getTypeName());
// Endpoint reference types will give a null schemaType
// here, so we need to
// go through the list of imports to find the definition for
// an Endpoint
// reference type.
if (schemaType == null
&& xmlSchemaType.getIncludes().getCount() > 0) {
XmlSchemaObjectCollection includes = xmlSchemaType
.getIncludes();
Iterator includeIter = includes.getIterator();
while (includeIter.hasNext()) {
Object obj = includeIter.next();
if (!(obj instanceof XmlSchemaImport)) {
continue;
}
XmlSchemaImport xmlImport = (XmlSchemaImport) obj;
if (xmlImport.getNamespace().equals(
part.getTypeName().getNamespaceURI())) {
XmlSchema importSchema = xmlImport.getSchema();
schemaType = importSchema.getTypeByName(part
.getTypeName());
}
}
}
}
}
if (schemaType != null) {
return schemaType;
}
}
return schemaType;
}
private static XmlSchemaElement getElement(Part part,
List<XmlSchema> xmlSchemaList) throws Exception {
XmlSchemaElement schemaElement = null;
Iterator i = xmlSchemaList.iterator();
while (i.hasNext()) {
XmlSchema xmlSchemaType = (XmlSchema) i.next();
if (part.getElementName() != null) {
schemaElement = xmlSchemaType.getElementByName(part
.getElementName());
if (schemaElement == null) {
QName elName = part.getElementName();
String prefix = definition.getPrefix(elName
.getNamespaceURI());
QName name = new QName(elName.getNamespaceURI(), prefix
+ ":" + elName.getLocalPart(), prefix);
schemaElement = xmlSchemaType.getElementByName(name);
}
if (schemaElement != null) {
return schemaElement;
}
}
}
return schemaElement;
}
private static ParamType createParam(WSDLToCorbaBinding wsdlToCorbaBinding,
String mode, XmlSchemaType schemaType, String name, QName typeName,
boolean nill) throws Exception {
CorbaTypeImpl corbaTypeImpl = null;
ParamType paramtype = new ParamType();
ModeType modeType = ModeType.fromValue(mode);
paramtype.setName(name);
paramtype.setMode(modeType);
if (schemaType == null) {
corbaTypeImpl = (CorbaTypeImpl) WSDLToCorbaHelper.CORBAPRIMITIVEMAP
.get(typeName);
if (nill) {
QName qname = corbaTypeImpl.getQName();
qname = wsdlToCorbaBinding.getHelper()
.createQNameCorbaNamespace(
qname.getLocalPart() + "_nil");
paramtype.setIdltype(qname);
} else {
paramtype.setIdltype(corbaTypeImpl.getQName());
}
} else {
// We need to get annotation information for the schema type we are about to pass in.
// This is used to produce the correct object reference type.
List<XmlSchema> schemaList = wsdlToCorbaBinding.getHelper().getXMLSchemaList();
Iterator<XmlSchema> schemaIterator = schemaList.iterator();
XmlSchemaObject schemaObj = null;
while (schemaIterator.hasNext()) {
XmlSchema s = schemaIterator.next();
XmlSchemaObjectTable schemaTable = s.getElements();
schemaObj = schemaTable.getItem(typeName);
if (schemaObj != null) {
break;
}
}
XmlSchemaAnnotation annotation = null;
if (schemaObj != null && schemaObj instanceof XmlSchemaElement) {
annotation = ((XmlSchemaElement)schemaObj).getAnnotation();
}
corbaTypeImpl = wsdlToCorbaBinding.getHelper()
.convertSchemaToCorbaType(schemaType, typeName, null, annotation, false);
if (corbaTypeImpl == null) {
return null;
} else {
if (nill) {
QName qname = corbaTypeImpl.getQName();
qname = wsdlToCorbaBinding.getHelper()
.createQNameCorbaNamespace(
qname.getLocalPart() + "_nil");
paramtype.setIdltype(qname);
} else {
paramtype.setIdltype(corbaTypeImpl.getQName());
}
}
return paramtype;
}
return paramtype;
}
private static boolean inputPartsHaveNoDocWrapper(String opName,
Operation operation, List<XmlSchema> xmlSchemaList)
throws Exception {
XmlSchemaType schemaType = null;
Iterator i = null;
Input input = operation.getInput();
if (input != null) {
Message msg = input.getMessage();
i = msg.getParts().values().iterator();
if (msg.getParts().size() == 0) {
return false;
}
Part part = (Part) i.next();
if (i.hasNext()) {
return true;
}
schemaType = lookUpType(part, xmlSchemaList);
if (!(part.getName().equals(opName))) {
return true;
}
if (!(schemaType instanceof XmlSchemaComplexType)) {
return true;
}
XmlSchemaComplexType cpt = (XmlSchemaComplexType) schemaType;
return checkComplex(cpt);
}
return false;
}
private static boolean outputPartsHaveNoDocWrapper(String opName,
Operation operation, List<XmlSchema> xmlSchemaList)
throws Exception {
XmlSchemaType schemaType = null;
Iterator i = null;
Output output = operation.getOutput();
if (output != null) {
Message msg = output.getMessage();
i = msg.getParts().values().iterator();
if (msg.getParts().size() == 0) {
return false;
}
Part part = (Part) i.next();
if (i.hasNext()) {
return true;
}
schemaType = lookUpType(part, xmlSchemaList);
if (!part.getName().equals(opName)) {
return true;
}
if (!(schemaType instanceof XmlSchemaComplexType)) {
return true;
}
XmlSchemaComplexType cpt = (XmlSchemaComplexType) schemaType;
return checkComplex(cpt);
}
return false;
}
private static boolean checkComplex(XmlSchemaComplexType cpt)
throws Exception {
XmlSchemaParticle particle = (XmlSchemaParticle) cpt.getParticle();
if (particle == null) {
return true;
}
if (!(particle instanceof XmlSchemaSequence)) {
return true;
}
if (cpt.getAttributes().getCount() != 0) {
return true;
}
if (particle instanceof XmlSchemaSequence) {
XmlSchemaSequence seq = (XmlSchemaSequence) particle;
Iterator it = seq.getItems().getIterator();
while (it.hasNext()) {
if (!(it.next() instanceof XmlSchemaElement)) {
return true;
}
}
}
return false;
}
}