blob: 7f7173db4ac9a60c2dd65bc238ff7c4d906fe680 [file] [log] [blame]
/*
* 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.axis2.wsdl.codegen.extension;
import org.apache.axis2.AxisFault;
import org.apache.axis2.description.AxisMessage;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.axis2.wsdl.WSDLUtil;
import org.apache.axis2.wsdl.codegen.CodeGenConfiguration;
import org.apache.axis2.wsdl.codegen.CodeGenerationException;
import org.apache.axis2.wsdl.util.Constants;
import org.apache.axis2.wsdl.util.MessagePartInformationHolder;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaComplexType;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaImport;
import org.apache.ws.commons.schema.XmlSchemaInclude;
import org.apache.ws.commons.schema.XmlSchemaObjectCollection;
import org.apache.ws.commons.schema.XmlSchemaParticle;
import org.apache.ws.commons.schema.XmlSchemaSequence;
import org.apache.ws.commons.schema.XmlSchemaType;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class JAXWSWapperExtension extends AbstractCodeGenerationExtension {
private CodeGenConfiguration codeGenConfiguration;
public void engage(CodeGenConfiguration configuration) throws CodeGenerationException {
this.codeGenConfiguration = configuration;
if (!codeGenConfiguration.isParametersWrapped() && codeGenConfiguration.getOutputLanguage().equals("jax-ws")) {
//walk the schema and find the top level elements
List services = configuration.getAxisServices();
AxisService axisService;
for (Iterator servicesIter = services.iterator(); servicesIter.hasNext();) {
axisService = (AxisService) servicesIter.next();
for (Iterator operations = axisService.getOperations();
operations.hasNext();) {
AxisOperation op = (AxisOperation) operations.next();
boolean wrappable = true;
//get the input parameter details to unwrap the requests
if (WSDLUtil.isInputPresentForMEP(op.getMessageExchangePattern())) {
AxisMessage message = op.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
XmlSchemaElement schemaElement = message.getSchemaElement();
String opName = ((AxisOperation) message.getParent()).getName().getLocalPart();
if(!schemaElement.getName().equals(opName))
return;
wrappable = walkSchema(op.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE),
WSDLConstants.INPUT_PART_QNAME_SUFFIX);
}
//get the out put parameter details as well to unwrap the responses
if (WSDLUtil.isOutputPresentForMEP(op.getMessageExchangePattern()) && wrappable) {
walkSchema(op.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE),
WSDLConstants.OUTPUT_PART_QNAME_SUFFIX);
}
}
}
}
}
public boolean walkSchema(AxisMessage message, String qnameSuffix) throws CodeGenerationException {
//nothing to unwrap
if (message.getSchemaElement() == null) {
return false;
}
List partNameList = new LinkedList();
XmlSchemaElement schemaElement = message.getSchemaElement();
// String opName = ((AxisOperation) message.getParent()).getName().getLocalPart();
// if(!schemaElement.getName().equals(opName))
// return false;
XmlSchemaType schemaType = schemaElement.getSchemaType();
QName schemaTypeQname = schemaElement.getSchemaTypeName();
if (schemaType == null) {
if (schemaTypeQname != null) {
// find the schema type from all the schemas
// now we need to get the schema of the extension type from the parent schema. For that let's first retrieve
// the parent schema
AxisService axisService = (AxisService) message.getParent().getParent();
ArrayList schemasList = axisService.getSchema();
XmlSchema schema = null;
for (Iterator iter = schemasList.iterator(); iter.hasNext();) {
schema = (XmlSchema) iter.next();
schemaType = getSchemaType(schema, schemaTypeQname);
if (schemaType != null) {
break;
}
}
}
}
if (schemaType instanceof XmlSchemaComplexType) {
if(!handleAllCasesOfComplexTypes(schemaType,
message,
partNameList,
qnameSuffix)){
return false;
}
} else {
return false;
}
// else if ((schemaType instanceof XmlSchemaSimpleType) ||
// ((schemaTypeQname != null) && (schemaTypeQname.equals(new QName("http://www.w3.org/2001/XMLSchema", "anyType"))))) {
// QName opName = ((AxisOperation) message.getParent()).getName();
// partNameList.add(WSDLUtil.getPartQName(opName.getLocalPart(),
// qnameSuffix,
// schemaElement.getQName().getLocalPart()));
// } else if (schemaType == null) {
// throw new CodeGenerationException("Can not determine the schema type for the "
// + schemaElement.getName());
// } else {
// //we've no idea how to unwrap a non complexType!!!!!!
// throw new CodeGenerationException(
// CodegenMessages.getMessage("extension.unsupportedSchemaFormat",
// schemaType.getName(), "complexType"));
// }
try {
//set in the axis message that the unwrapping was success
message.addParameter(getParameter(
Constants.UNWRAPPED_KEY,
Boolean.TRUE));
// attach the opName and the parts name list into the
// axis message by using the holder
MessagePartInformationHolder infoHolder = new MessagePartInformationHolder();
infoHolder.setOperationName(((AxisOperation) message.getParent()).getName());
infoHolder.setPartsList(partNameList);
//attach it to the parameters
message.addParameter(
getParameter(Constants.UNWRAPPED_DETAILS,
infoHolder));
} catch (AxisFault axisFault) {
throw new CodeGenerationException(axisFault);
}
return true;
}
/**
* Generate a parametes object
*
* @param key
* @param value
*/
private Parameter getParameter(String key, Object value) {
Parameter myParameter = new Parameter();
myParameter.setName(key);
myParameter.setValue(value);
return myParameter;
}
private XmlSchemaType getSchemaType(XmlSchema schema, QName typeName) {
XmlSchemaType xmlSchemaType = null;
if (schema != null) {
xmlSchemaType = schema.getTypeByName(typeName);
if (xmlSchemaType == null) {
// try to find in an import or an include
XmlSchemaObjectCollection includes = schema.getIncludes();
if (includes != null) {
Iterator includesIter = includes.getIterator();
Object object = null;
while (includesIter.hasNext()) {
object = includesIter.next();
if (object instanceof XmlSchemaImport) {
XmlSchema schema1 = ((XmlSchemaImport) object).getSchema();
xmlSchemaType = getSchemaType(schema1, typeName);
}
if (object instanceof XmlSchemaInclude) {
XmlSchema schema1 = ((XmlSchemaInclude) object).getSchema();
xmlSchemaType = getSchemaType(schema1, typeName);
}
if (xmlSchemaType != null) {
break;
}
}
}
}
}
return xmlSchemaType;
}
private boolean handleAllCasesOfComplexTypes(XmlSchemaType schemaType,
AxisMessage message,
List partNameList,
String qnameSuffix) throws CodeGenerationException {
// if a complex type name exits for a element then
// we keep that complex type to support unwrapping
if (schemaType instanceof XmlSchemaComplexType) {
XmlSchemaComplexType cmplxType = (XmlSchemaComplexType) schemaType;
XmlSchemaObjectCollection xmlObjectCollection = cmplxType.getAttributes();
if (xmlObjectCollection.getCount() != 0)
return false;
if (cmplxType.getContentModel() == null) {
if (cmplxType.getParticle() != null) {
return processXMLSchemaSequence(cmplxType.getParticle(), message, partNameList,
qnameSuffix);
}
} else {
// now lets handle case with extensions
return processComplexContentModel(cmplxType, message, partNameList, qnameSuffix);
}
// handle attributes here
// processAttributes(cmplxType, message, partNameList, qnameSuffix);
}
return false;
}
private boolean processComplexContentModel(XmlSchemaComplexType cmplxType,
AxisMessage message,
List partNameList,
String qnameSuffix) throws CodeGenerationException {
//TODO implement this method
return false;
}
private boolean processXMLSchemaSequence(XmlSchemaParticle schemaParticle,
AxisMessage message,
List partNameList,
String qnameSuffix) throws CodeGenerationException {
if (schemaParticle instanceof XmlSchemaSequence) {
// get the name of the operation name and namespace,
// part name and hang them somewhere ? The ideal place
// would be the property bag in the codegen config!
QName opName = ((AxisOperation) message.getParent()).getName();
XmlSchemaSequence sequence = (XmlSchemaSequence) schemaParticle;
XmlSchemaObjectCollection items = sequence.getItems();
// if this is an empty sequence, return
if (items.getCount() == 0) {
/*be carefull */
return true;
}
for (Iterator i = items.getIterator(); i.hasNext();) {
Object item = i.next();
// get each and every element in the sequence and
// traverse through them
if (item instanceof XmlSchemaElement) {
//add the element name to the part name list
XmlSchemaElement xmlSchemaElement = (XmlSchemaElement) item;
// if(xmlSchemaElement.isNillable()){
// return false;
// }
XmlSchemaType schemaType = xmlSchemaElement.getSchemaType();
String partName = null;
if (xmlSchemaElement.getRefName() != null) {
partName = xmlSchemaElement.getRefName().getLocalPart();
} else {
partName = xmlSchemaElement.getName();
}
// part names are not unique across messages. Hence
// we need some way of making the part name a unique
// one (due to the fact that the type mapper
// is a global list of types).
// The seemingly best way to do that is to
// specify a namespace for the part QName reference which
// is stored in the list. This part qname is
// temporary and should not be used with it's
// namespace URI (which happened to be the operation name)
// with _input attached to it
partNameList.add(
WSDLUtil.getPartQName(opName.getLocalPart(),
qnameSuffix,
partName));
// if the particle contains anything other than
// a XMLSchemaElement then we are not in a position
// to unwrap it
// }
// else if (item instanceof XmlSchemaAny) {
//
// // if this is an instance of xs:any, then there is no part name for it. Using ANY_ELEMENT_FIELD_NAME
// // for it for now
//
// //we have to handle both maxoccurs 1 and maxoccurs > 1 situation
// XmlSchemaAny xmlSchemaAny = (XmlSchemaAny) item;
//
// partNameList.add(
// WSDLUtil.getPartQName(opName.getLocalPart(),
// qnameSuffix,
// Constants.ANY_ELEMENT_FIELD_NAME));
} else {
// throw new CodeGenerationException(
// CodegenMessages.getMessage("extension.unsupportedSchemaFormat",
// "unknown type", "Element"));
return false;
}
}
return true;
//we do not know how to deal with other particles
//such as xs:all or xs:choice. Usually occurs when
//passed with the user built WSDL where the style
//is document.
// } else if (schemaParticle instanceof XmlSchemaChoice) {
// throw new CodeGenerationException(
// CodegenMessages.getMessage("extension.unsupportedSchemaFormat",
// "choice", "sequence"));
//
// } else if (schemaParticle instanceof XmlSchemaAll) {
// throw new CodeGenerationException(
// CodegenMessages.getMessage("extension.unsupportedSchemaFormat",
// "all", "sequence"));
} else {
// throw new CodeGenerationException(
// CodegenMessages.getMessage("extension.unsupportedSchemaFormat",
// "unknown", "sequence"));
return false;
}
}
}