| /******************************************************************************* |
| * Copyright (c) 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.bpel.model.util; |
| |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Set; |
| |
| import javax.xml.namespace.QName; |
| |
| import org.eclipse.bpel.model.messageproperties.MessagepropertiesPackage; |
| import org.eclipse.bpel.model.messageproperties.Property; |
| import org.eclipse.bpel.model.partnerlinktype.PartnerLinkType; |
| import org.eclipse.bpel.model.partnerlinktype.PartnerlinktypePackage; |
| import org.eclipse.bpel.model.partnerlinktype.Role; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.wst.wsdl.Definition; |
| import org.eclipse.wst.wsdl.Message; |
| import org.eclipse.wst.wsdl.Operation; |
| import org.eclipse.wst.wsdl.Part; |
| import org.eclipse.wst.wsdl.PortType; |
| import org.eclipse.wst.wsdl.Service; |
| import org.eclipse.wst.wsdl.Types; |
| import org.eclipse.wst.wsdl.WSDLPackage; |
| import org.eclipse.wst.wsdl.XSDSchemaExtensibilityElement; |
| import org.eclipse.wst.wsdl.internal.impl.ImportImpl; |
| import org.eclipse.xsd.XSDElementDeclaration; |
| import org.eclipse.xsd.XSDPackage; |
| import org.eclipse.xsd.XSDSchema; |
| import org.eclipse.xsd.XSDTypeDefinition; |
| import org.eclipse.xsd.impl.XSDSchemaImpl; |
| import org.eclipse.xsd.util.XSDConstants; |
| |
| |
| |
| /** |
| * WSDLUtil supplies resolution (lookup) of various things that are useful in the BPEL |
| * world. |
| * |
| */ |
| |
| public class WSDLUtil |
| { |
| /** The WSDL Message attribute/name, most likely "message" */ |
| |
| public static final String WSDL_MESSAGE = WSDLPackage.eINSTANCE.getMessage().getName(); |
| |
| /** The WSDL Port Type attribute/name, most likely "portType" */ |
| public static final String WSDL_PORT_TYPE = WSDLPackage.eINSTANCE.getPortType().getName(); |
| |
| /** The WSDL Operation attribute/name, most likely "operation" */ |
| public static final String WSDL_OPERATION = WSDLPackage.eINSTANCE.getOperation().getName(); |
| |
| /** The WSDL Part attribute/name, most likely "part" */ |
| public static final String WSDL_PART = WSDLPackage.eINSTANCE.getPart().getName(); |
| |
| /** The WSDL Service attribute/name, most likely "service" */ |
| public static final String WSDL_SERVICE = WSDLPackage.eINSTANCE.getService().getName(); |
| |
| /** The XSD Type Definition attribute/name, most likely "type" */ |
| public static final String XSD_TYPE_DEFINITION = XSDPackage.eINSTANCE.getXSDTypeDefinition().getName(); |
| |
| /** The XSD Element Declaration attribute/name, most likely "element" */ |
| public static final String XSD_ELEMENT_DECLARATION = XSDPackage.eINSTANCE.getXSDElementDeclaration().getName(); |
| |
| /** The BPEL Partner Link Type attribute/name, most likely "partnerLinkType" */ |
| public static final String BPEL_PARTNER_LINK_TYPE = PartnerlinktypePackage.eINSTANCE.getPartnerLinkType().getName(); |
| |
| /** The BPEL Role attribute/name, most likely "role" */ |
| public static final String BPEL_ROLE = PartnerlinktypePackage.eINSTANCE.getRole().getName(); |
| |
| /** The BPEL Property attribute/name, most likely "property" */ |
| public static final String BPEL_PROPERTY = MessagepropertiesPackage.eINSTANCE.getProperty().getName(); |
| |
| /** This should be a preference that can be easily turned on/off */ |
| private static boolean RESOLVING_DEEPLY = true; // TODO: Preference based ? |
| |
| |
| /** |
| * Answer true if the type name passed is a WSDL thing. |
| * |
| * @param typeName |
| * @return true if yes, false if no. |
| */ |
| |
| public static boolean isWSDLType(String typeName) |
| { |
| return typeName == null ? false : |
| WSDL_MESSAGE.equals(typeName) |
| || WSDL_PORT_TYPE.equals(typeName) |
| || WSDL_OPERATION.equals(typeName) |
| || WSDL_PART.equals(typeName) |
| || WSDL_SERVICE.equals(typeName) |
| || XSD_TYPE_DEFINITION.equals(typeName) |
| || XSD_ELEMENT_DECLARATION.equals(typeName) |
| || BPEL_PARTNER_LINK_TYPE.equals(typeName) |
| || BPEL_ROLE.equals(typeName) |
| || BPEL_PROPERTY.equals(typeName); |
| } |
| |
| |
| /** |
| * Set to resolve deeply. |
| * @param resolveDeeply |
| */ |
| |
| public static void setResolveDeeply ( boolean resolveDeeply ) { |
| RESOLVING_DEEPLY = resolveDeeply; |
| } |
| |
| /** |
| * Answer if resolving deeply. |
| * @return answer true if resolving deeply, false otherwise. |
| */ |
| |
| public static boolean isResolvingDeeply () { |
| return RESOLVING_DEEPLY; |
| } |
| |
| /** |
| * Resolve with the given definition the QName given. |
| * @param definition the definition to use. |
| * @param qname the QName to resolve. |
| * @param name |
| * @param refType what to resolve (that things from WSDL that we can resolve). |
| * @return the EMF object that the QName resolves to. |
| */ |
| |
| public static EObject resolveWSDLReference(Definition definition, QName qname, String name, String refType) |
| { |
| EObject resolvedObject = null; |
| |
| if (WSDL_PORT_TYPE.equals(refType)) { |
| resolvedObject = resolvePortType(definition, qname); |
| } else if (WSDL_MESSAGE.equals(refType)) { |
| resolvedObject = resolveMessage(definition, qname); |
| } else if (WSDL_OPERATION.equals(refType)) { |
| resolvedObject = resolveOperation(definition, qname, name); |
| } else if (WSDL_PART.equals(refType)) { |
| resolvedObject = resolvePart(definition, qname, name); |
| } else if (WSDL_SERVICE.equals(refType)) { |
| resolvedObject = resolveService(definition, qname); |
| } else if (XSD_TYPE_DEFINITION.equals(refType)) { |
| resolvedObject = resolveXSDTypeDefinition(definition, qname); |
| } else if (XSD_ELEMENT_DECLARATION.equals(refType)) { |
| resolvedObject = resolveXSDElementDeclaration(definition, qname); |
| } else if (BPEL_PARTNER_LINK_TYPE.equals(refType)) { |
| resolvedObject = resolveBPELPartnerLinkType(definition, qname); |
| } else if (BPEL_ROLE.equals(refType)) { |
| resolvedObject = resolveBPELRole(definition, qname, name); |
| } else if (BPEL_PROPERTY.equals(refType)) { |
| resolvedObject = resolveBPELProperty(definition, qname); |
| } else { |
| System.err.println(WSDLUtil.class.getName() + ": unrecognized refType: " + refType); //$NON-NLS-1$ |
| } |
| |
| return resolvedObject; |
| } |
| |
| |
| |
| /** |
| * Use Java generics to write the "finders" of various elements, so that the general code |
| * which does the lookups and follows imports does not need to be repeated. |
| * |
| * @author Michal Chmielewski (michal.chmielewski@oracle.com) |
| * @date Feb 27, 2007 |
| * |
| * @param <T> the type that we are looking up (PortType, Message, PartnerLinkType) |
| */ |
| |
| interface Finder<S,T> { |
| /** |
| * Find the thing in the container |
| * |
| * @param source the source where to look (definition, schema) |
| * @param qname the QName to lookup |
| * @return the resolved entity, or null |
| */ |
| T find (S source, QName qname); |
| } |
| |
| |
| /** Generic way of looking up port types */ |
| static final Finder<Definition,PortType> PORT_TYPE_FINDER = new Finder<Definition, PortType>() { |
| @Override |
| public PortType find (Definition defn, QName qname) { |
| return (PortType) defn.getPortType(qname) ; |
| } |
| }; |
| |
| /** Generic way of looking up messages */ |
| static final Finder<Definition,Message> MESSAGE_FINDER = new Finder<Definition,Message> () { |
| @Override |
| public Message find (Definition defn, QName qname) { |
| return (Message) defn.getMessage(qname); |
| } |
| }; |
| |
| /** Generic way of looking up partner link types */ |
| static final Finder<Definition,PartnerLinkType> PARTNER_LINK_TYPE_FINDER = new Finder<Definition,PartnerLinkType>() { |
| |
| @Override |
| public PartnerLinkType find (Definition defn, QName qname) { |
| |
| if (defn.getTargetNamespace() == null) |
| return null; |
| |
| if (defn.getTargetNamespace().equals(qname.getNamespaceURI()) == false) { |
| return null; |
| } |
| Iterator<?> it = defn.getExtensibilityElements().iterator(); |
| while (it.hasNext()) { |
| Object e = it.next(); |
| if (e instanceof PartnerLinkType) { |
| PartnerLinkType plt = (PartnerLinkType) e; |
| if (plt.getName().equals(qname.getLocalPart())) { |
| return plt; |
| } |
| } |
| } |
| return null; |
| } |
| }; |
| |
| /** Generic way of lookup up BPEL properties */ |
| static final Finder<Definition,Property> PROPERTY_FINDER = new Finder<Definition,Property>() { |
| |
| @Override |
| public Property find(Definition defn, QName qname) { |
| if (defn.getTargetNamespace().equals(qname.getNamespaceURI()) == false) { |
| return null; |
| } |
| Iterator<?> it = defn.getExtensibilityElements().iterator(); |
| while (it.hasNext()) { |
| Object e = it.next(); |
| if (e instanceof Property) { |
| Property property = (Property) e; |
| if (property.getName().equals(qname.getLocalPart())) { |
| return property; |
| } |
| } |
| } |
| return null; |
| } |
| }; |
| |
| /** Type definition finder */ |
| static private final Finder<XSDSchema,XSDTypeDefinition> TYPE_DEFINITION_FINDER = new Finder<XSDSchema,XSDTypeDefinition>() { |
| |
| @Override |
| public XSDTypeDefinition find(XSDSchema schema, QName typeName) { |
| // Perhaps this is what we want ... |
| // http://www.eclipse.org/modeling/emf/faq/#dev20040602-1383194195 |
| // |
| XSDTypeDefinition typeDef = schema.resolveTypeDefinition(typeName.getNamespaceURI(), typeName.getLocalPart()); |
| if (typeDef.getContainer() == null) { |
| return null; |
| } |
| return typeDef; |
| } |
| }; |
| |
| /** Element declaration finder */ |
| static private final Finder<XSDSchema,XSDElementDeclaration> ELEMENT_DECLARATION_FINDER = new Finder<XSDSchema,XSDElementDeclaration> () { |
| |
| @Override |
| public XSDElementDeclaration find(XSDSchema schema, QName qn) { |
| XSDElementDeclaration decl = schema.resolveElementDeclaration( qn.getNamespaceURI(), qn.getLocalPart()); |
| |
| // TODO: (Hack) |
| // Why has this started returning instances of XSDElementDeclrarion that are not proxies or null |
| // if the element declaration is missing in the schema ? |
| // Perhaps this is what we want: http://www.eclipse.org/modeling/emf/faq/#dev20040602-1383194195 |
| |
| if (decl.getContainer() == null) { |
| return null; |
| } |
| return decl; |
| } |
| }; |
| |
| /** |
| * Resolve the port type in the definition given. |
| * |
| * @param definition the WSDL definition |
| * @param qname the QName of the portType |
| * @return the resolved portType, or null |
| */ |
| |
| public static PortType resolvePortType (Definition definition, QName qname) |
| { |
| return resolveUsingFinder ( definition, qname, PORT_TYPE_FINDER, new HashSet<Definition>() ); |
| } |
| |
| |
| /** |
| * Resolve using finder resolves the QName in the definitions passed. The return object |
| * extends from EObject (so PortType, Message, PartnerLinkType, etc). The finder has the actual lookup |
| * code while the general code flow that deals with following the imports is shared among the lookup |
| * methods in this class. |
| * |
| * @param <T> the type |
| * @param defn the definition to use as the lookup |
| * @param qname the QName to lookup |
| * @param finder the finder to use. |
| * @param seen the seen set |
| * @return the object to be resolved. |
| */ |
| |
| @SuppressWarnings("restriction") |
| static <T extends EObject> T resolveUsingFinder ( Definition defn, QName qname, Finder<Definition,T> finder , Set<Definition> seen) { |
| |
| if (seen.contains(defn)) { |
| return null; |
| } |
| seen.add(defn); |
| |
| T result = finder.find ( defn, qname ); |
| |
| if (result != null || RESOLVING_DEEPLY == false) { |
| return result; |
| } |
| |
| Iterator<?> it = defn.getImports(qname.getNamespaceURI()).iterator(); |
| while (it.hasNext() && result == null) { |
| ImportImpl imp = (ImportImpl) it.next(); |
| imp.importDefinitionOrSchema(); |
| Definition importedDefinition = (Definition) imp.getDefinition(); |
| if (importedDefinition != null) { |
| result = resolveUsingFinder (importedDefinition, qname, finder, seen ); |
| } |
| } |
| return result; |
| } |
| |
| |
| |
| |
| /** |
| * Resolve the message name in the definitions passed. |
| * @param definition the definitions |
| * @param qname the message name |
| * @return the message name or null |
| */ |
| |
| public static Message resolveMessage(Definition definition, QName qname) |
| { |
| return resolveUsingFinder(definition, qname, MESSAGE_FINDER, new HashSet<Definition>()); |
| } |
| |
| |
| /** |
| * Resolve operation within a portType. First lookup portType, then find the operation by name given. |
| * @param definition the definition to search |
| * @param portTypeQName QName of the portType to lookup operation on |
| * @param operationName the operation name. |
| * @return the operation or null |
| */ |
| |
| public static Operation resolveOperation(Definition definition, QName portTypeQName, String operationName) |
| { |
| PortType portType = resolvePortType(definition, portTypeQName); |
| return findOperation(portType, operationName); |
| } |
| |
| /** |
| * Resolve the part within a message. |
| * @param definition the definition to use |
| * @param qname QName of the message |
| * @param name the name of the message part. |
| * @return the part, or null |
| */ |
| |
| public static Part resolvePart(Definition definition, QName qname, String name) |
| { |
| return findPart( resolveMessage(definition, qname) , name ); |
| } |
| |
| |
| |
| /** |
| * Resolve (lookup) a partner link type in the definitions given. |
| * @param defn the definitions to use |
| * @param qname the QName to lookup |
| * @return the partner link type or null |
| */ |
| |
| public static PartnerLinkType resolveBPELPartnerLinkType(Definition defn, QName qname) |
| { |
| return resolveUsingFinder(defn, qname, PARTNER_LINK_TYPE_FINDER, new HashSet<Definition>() ); |
| } |
| |
| /** |
| * Resolve BPEL Role on the partner link specified. |
| * |
| * @param definition the definition to use |
| * @param qname QNAme of the partner link type |
| * @param name the name of the role on that partner link type |
| * @return the BPEL role, or null |
| */ |
| |
| public static EObject resolveBPELRole(Definition definition, QName qname, String name) |
| { |
| return findRole ( resolveBPELPartnerLinkType(definition, qname) , name ); |
| } |
| |
| |
| /** |
| * Lookup the BPEL property in the definition given. |
| * |
| * @param defn the definition |
| * @param qname the property QName to lookup |
| * @return the property or null |
| */ |
| |
| public static Property resolveBPELProperty(Definition defn, QName qname) |
| { |
| return resolveUsingFinder(defn, qname, PROPERTY_FINDER, new HashSet<Definition>()); |
| } |
| |
| |
| |
| private static Service resolveService(Definition definition, QName qname) { |
| return (Service) definition.getService(qname); |
| } |
| |
| |
| |
| /** |
| * Common code for resolving XSDTypeDefinitions and XSDElementDeclarations |
| */ |
| @SuppressWarnings("restriction") |
| static <T> T resolveXSD (Definition definition, QName qname, Finder<XSDSchema,T> finder, Set<Definition> seen ) |
| { |
| T result = null; |
| |
| if (seen.contains(definition)) { |
| return result; |
| } |
| seen.add(definition); |
| |
| // Check for built-in types |
| // TODO Slightly inefficient to evaluate this when recursing |
| |
| XSDSchema schema = null; |
| String namespace = qname.getNamespaceURI(); |
| |
| if ("".equals(namespace)) { //$NON-NLS-1$ |
| namespace = null; |
| } |
| |
| if (XSDConstants.isSchemaForSchemaNamespace(namespace)) { |
| schema = XSDSchemaImpl.getSchemaForSchema(namespace); |
| } else if (XSDConstants.isSchemaInstanceNamespace(namespace)) { |
| schema = XSDSchemaImpl.getSchemaInstance(namespace); |
| } |
| if (schema != null) { |
| result = finder.find(schema, qname); |
| if (result != null) { |
| return result; |
| } |
| } |
| |
| // Check in-line schema |
| Types types = definition.getETypes(); |
| if (types != null) { |
| Iterator<?> it = types.getExtensibilityElements().iterator(); |
| while (it.hasNext()) { |
| Object e = it.next(); |
| if (e instanceof XSDSchemaExtensibilityElement == false) { |
| continue; |
| } |
| XSDSchemaExtensibilityElement schemaEE = (XSDSchemaExtensibilityElement) e; |
| schema = schemaEE.getSchema(); |
| if (schema != null) { |
| result = finder.find(schema, qname); |
| if (result != null) |
| return result; |
| } |
| } |
| } |
| |
| /** |
| * Check imported schemas and definitions. |
| * If we are here, then result is still null |
| */ |
| |
| // TODO: I think I need to check all imports, not just those |
| // matching the same namespace... |
| |
| Iterator<?> it = definition.getImports(qname.getNamespaceURI()).iterator(); |
| while (it.hasNext()) { |
| ImportImpl imp = (ImportImpl) it.next(); |
| imp.importDefinitionOrSchema(); |
| schema = imp.getESchema(); |
| if (schema != null) { |
| result = finder.find(schema, qname); |
| if (result != null) |
| return result; |
| } |
| Definition importedDefinition = imp.getEDefinition(); |
| if (importedDefinition != null) { |
| result = resolveXSD(importedDefinition, qname, finder, seen ); |
| if (result != null) { |
| return result; |
| } |
| } |
| } |
| return result; |
| } |
| |
| |
| /** |
| * Resolve type definition. Basically lookup type by QName. |
| * |
| * @param definition |
| * @param qname |
| * @return the XSDTypeDefinition found or null if it does not exist. |
| */ |
| |
| public static XSDTypeDefinition resolveXSDTypeDefinition(Definition definition, QName qname) |
| { |
| return resolveXSD(definition, qname ,TYPE_DEFINITION_FINDER, new HashSet<Definition>() ); |
| } |
| |
| /** |
| * Resolve the XSDElement declaration in this definition. Basically, lookup element declaration using the |
| * QName specified in the definition indicated. |
| * |
| * @param definition |
| * @param qname |
| * @return the XSDElement declaration if found. null otherwise. |
| */ |
| |
| public static XSDElementDeclaration resolveXSDElementDeclaration(Definition definition, QName qname) |
| { |
| return resolveXSD(definition, qname, ELEMENT_DECLARATION_FINDER, new HashSet<Definition>() ); |
| } |
| |
| |
| |
| |
| /** |
| * Find a role in the partner link type. |
| * @param plt the partner link type |
| * @param name the role name to find. |
| * @return the found role or null if it does not exist. |
| */ |
| public static Role findRole ( PartnerLinkType plt, String name ) { |
| |
| if (plt != null) { |
| Iterator<Role> it = plt.getRole().iterator(); |
| while (it.hasNext()) { |
| Role role = it.next(); |
| if (name.equals(role.getName())) { |
| return role; |
| } |
| } |
| } |
| return null; |
| } |
| |
| |
| /** |
| * Find the operation in the port type. |
| * @param portType the port type |
| * @param operationName the operation name |
| * @return return the operation in the port type or null |
| */ |
| |
| @SuppressWarnings("unchecked") |
| public static Operation findOperation (PortType portType, String operationName) { |
| if (portType != null) { |
| Iterator<Operation> it = portType.getOperations().iterator(); |
| while (it.hasNext()) { |
| Operation operation = it.next(); |
| if (operation.getName().equals(operationName)) { |
| return operation; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Find the message part in the message structure. |
| * @param message |
| * @param name |
| * @return the part or null |
| */ |
| public static Part findPart(Message message, String name) { |
| Part result = null; |
| if (message != null) { |
| result = (Part) message.getPart(name); |
| } |
| return result; |
| } |
| } |