/**
* 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.idl;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.wsdl.Binding;
import javax.wsdl.BindingOperation;
import javax.wsdl.Definition;
import javax.wsdl.Port;
import javax.wsdl.Types;
import javax.wsdl.WSDLException;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.ExtensionRegistry;
import javax.wsdl.extensions.schema.Schema;
import javax.wsdl.factory.WSDLFactory;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import antlr.ASTVisitor;
import antlr.collections.AST;
import org.apache.cxf.tools.common.WSDLConstants;
import org.apache.cxf.wsdl.JAXBExtensionHelper;
import org.apache.schemas.yoko.bindings.corba.AddressType;
import org.apache.schemas.yoko.bindings.corba.BindingType;
import org.apache.schemas.yoko.bindings.corba.OperationType;
import org.apache.schemas.yoko.bindings.corba.TypeMappingType;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaCollection;
import org.apache.ws.commons.schema.XmlSchemaSerializer;
import org.apache.ws.commons.schema.XmlSchemaType;
import org.apache.ws.commons.schema.constants.Constants;
import org.apache.ws.commons.schema.utils.NamespaceMap;
import org.apache.yoko.tools.common.WSDLUtils;
import org.apache.yoko.wsdl.CorbaConstants;
public class WSDLASTVisitor implements ASTVisitor {
Definition definition;
WSDLFactory wsdlFactory;
XmlSchema schema;
XmlSchemaCollection schemas;
TypeMappingType typeMap;
public WSDLASTVisitor(String tns)
throws WSDLException, JAXBException {
createWsdlDefinition(tns);
schemas = new XmlSchemaCollection();
schema = new XmlSchema(definition.getTargetNamespace(), schemas);
addAnyType();
createCorbaTypeMap();
}
public void visit(AST node) {
// <specification> ::= <definition>+
while (node != null) {
DefinitionVisitor definitionVisitor = new DefinitionVisitor(new Scope(),
definition,
schemas,
schema,
typeMap);
definitionVisitor.visit(node);
node = node.getNextSibling();
}
try {
attachSchema();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public Definition getDefinition() {
return definition;
}
public WSDLFactory getFactory() {
return wsdlFactory;
}
public Binding[] getCorbaBindings() {
List<Binding> result = new ArrayList<Binding>();
Map bindings = definition.getBindings();
Iterator it = bindings.values().iterator();
while (it.hasNext()) {
Binding binding = (Binding) it.next();
List extElements = binding.getExtensibilityElements();
for (int i = 0; i < extElements.size(); i++) {
ExtensibilityElement el = (ExtensibilityElement) extElements.get(i);
if (el.getElementType().equals(CorbaConstants.NE_CORBA_BINDING)) {
result.add(binding);
break;
}
}
}
return (Binding[]) result.toArray(new Binding[result.size()]);
}
public boolean writeDefinition(Writer writer) throws Exception {
WSDLUtils.writeWSDL(definition, writer);
return true;
}
private void createWsdlDefinition(String tns) throws WSDLException, JAXBException {
wsdlFactory = WSDLFactory.newInstance();
definition = wsdlFactory.newDefinition();
definition.setTargetNamespace(tns);
definition.addNamespace(WSDLConstants.WSDL_PREFIX, WSDLConstants.NS_WSDL);
definition.addNamespace(WSDLConstants.XSD_PREFIX, WSDLConstants.XSD_NAMESPACE);
definition.addNamespace(WSDLConstants.SOAP_PREFIX, WSDLConstants.SOAP11_NAMESPACE);
definition.addNamespace(WSDLConstants.TNS_PREFIX, tns);
definition.addNamespace(CorbaConstants.NP_WSDL_CORBA, CorbaConstants.NU_WSDL_CORBA);
addCorbaExtensions(definition.getExtensionRegistry());
}
private void createCorbaTypeMap() throws WSDLException {
typeMap = (TypeMappingType)
definition.getExtensionRegistry().createExtension(Definition.class,
CorbaConstants.NE_CORBA_TYPEMAPPING);
typeMap.setTargetNamespace(definition.getTargetNamespace()
+ "/"
+ CorbaConstants.NS_CORBA_TYPEMAP);
definition.addExtensibilityElement(typeMap);
}
private void addCorbaExtensions(ExtensionRegistry extReg) throws JAXBException {
try {
JAXBExtensionHelper.addExtensions(extReg, Binding.class, BindingType.class);
JAXBExtensionHelper.addExtensions(extReg, BindingOperation.class, OperationType.class);
JAXBExtensionHelper.addExtensions(extReg, Definition.class, TypeMappingType.class);
JAXBExtensionHelper.addExtensions(extReg, Port.class, AddressType.class);
extReg.mapExtensionTypes(Binding.class, CorbaConstants.NE_CORBA_BINDING, BindingType.class);
extReg.mapExtensionTypes(BindingOperation.class, CorbaConstants.NE_CORBA_OPERATION,
org.apache.schemas.yoko.bindings.corba.OperationType.class);
extReg.mapExtensionTypes(Definition.class, CorbaConstants.NE_CORBA_TYPEMAPPING,
TypeMappingType.class);
extReg.mapExtensionTypes(Port.class, CorbaConstants.NE_CORBA_ADDRESS,
org.apache.schemas.yoko.bindings.corba.AddressType.class);
} catch (javax.xml.bind.JAXBException ex) {
throw new JAXBException(ex.getMessage());
}
}
private void attachSchema() throws Exception {
Types types = definition.createTypes();
Schema wsdlSchema = (Schema)
definition.getExtensionRegistry().createExtension(Types.class,
new QName(Constants.URI_2001_SCHEMA_XSD,
"schema"));
// See if a NamespaceMap has already been added to the schema (this can be the case with object
// references. If so, simply add the XSD URI to the map. Otherwise, create a new one.
NamespaceMap nsMap = null;
try {
nsMap = (NamespaceMap)schema.getNamespaceContext();
} catch (ClassCastException ex) {
// Consume. This will mean that the context has not been set.
}
if (nsMap == null) {
nsMap = new NamespaceMap();
nsMap.add("xs", Constants.URI_2001_SCHEMA_XSD);
schema.setNamespaceContext(nsMap);
} else {
nsMap.add("xs", Constants.URI_2001_SCHEMA_XSD);
}
org.w3c.dom.Element el = XmlSchemaSerializer.serializeSchema(schema, true)[0].getDocumentElement();
wsdlSchema.setElement(el);
types.addExtensibilityElement(wsdlSchema);
definition.setTypes(types);
}
private void addAnyType() {
XmlSchema[] schemaList = schemas.getXmlSchemas();
if (schemaList != null) {
for (int i = 0; i < schemaList.length; i++) {
if (schemaList[i].getTargetNamespace().equals(Constants.URI_2001_SCHEMA_XSD)) {
XmlSchemaType anyType = new XmlSchemaType(schemaList[0]);
anyType.setName(Constants.XSD_ANYTYPE.getLocalPart());
schemaList[i].addType(anyType);
break;
}
}
}
}
}