/*******************************************************************************
* Copyright (c) 2006 Oracle 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:
* Oracle Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.bpel.validator.helpers;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Stack;
import javax.xml.namespace.QName;
import org.eclipse.bpel.model.Import;
import org.eclipse.bpel.model.Process;
import org.eclipse.bpel.model.util.XSDUtil;
import org.eclipse.bpel.validator.EmfModelQuery;
import org.eclipse.bpel.validator.model.Filters;
import org.eclipse.bpel.validator.model.IConstants;
import org.eclipse.bpel.validator.model.IFilter;
import org.eclipse.bpel.validator.model.IFunctionMeta;
import org.eclipse.bpel.validator.model.IModelQuery;
import org.eclipse.bpel.validator.model.INode;
import org.eclipse.bpel.validator.model.NodeAttributeValueFilter;
import org.eclipse.bpel.validator.model.NodeNameFilter;
import org.eclipse.bpel.validator.model.Selector;
import org.eclipse.bpel.validator.model.UndefinedNode;
import org.eclipse.bpel.validator.model.XNotImplemented;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDTypeDefinition;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Base implementation of the IModelQuery interface with references
* only to DOM elements.
*
* This does not fully implement the IModelQuery interface contract as
* type look ups, WSDL information look ups are not implemented here.
* This is meant to be a starting point for implementing your own
* model backend to the IModelQuer interface.
*
* @author Michal Chmielewski (michal.chmielewski@oracle.com)
* @date Sep 21, 2006
*
*/
@SuppressWarnings("nls")
public class ModelQueryImpl implements IModelQuery {
/**
* The handle to the EMF root of the BPEL process that we will
* validate.
*/
static final protected Selector mSelector = new Selector();
/**
* https://jira.jboss.org/browse/JBIDE-7351
* Need an EmfModelQuery to contain the XSDComparer object so that
* we can grab diagnostics from it after a failed XSD compare (used
* for error reporting!)
*/
protected EmfModelQuery emfModelQuery;
/**
* Protected constructor, just to initialize the basics the basics.
*
*/
public ModelQueryImpl () {
emfModelQuery = new EmfModelQuery();
}
/**
* Return error message from XSDComparer if assignments are incompatible
*
* https://jira.jboss.org/browse/JBIDE-7351
*/
public String getDiagnostic(int index)
{
return emfModelQuery.getXSDComparer().getDiagnostic(index);
}
/**
* Return an answer that decides whether the model has support for
* the given aspects that the validator wants.
* @param item
* @param value
* @return true if support present, false otherwise.
*
* @see org.eclipse.bpel.validator.model.IModelQuery#hasSupport(int, java.lang.String)
*/
public boolean hasSupport (int item, String value) {
switch (item) {
case SUPPORT_QUERY_LANGUAGE :
return
IConstants.XMLNS_XPATH_QUERY_LANGUAGE.equals ( value ) ||
IConstants.XMLNS_XPATH_QUERY_LANGUAGE_2.equals( value );
case SUPPORT_EXPRESSION_LANGUAGE :
return
IConstants.XMLNS_XPATH_EXPRESSION_LANGUAGE.equals ( value ) ||
IConstants.XMLNS_XPATH_EXPRESSION_LANGUAGE_2.equals( value );
case SUPPORT_IMPORT_TYPE :
return IConstants.AT_VAL_IMPORT_XSD.equals ( value ) ||
IConstants.AT_VAL_IMPORT_WSDL.equals ( value ) ;
case SUPPORT_EXTENSION :
// by default we have no extensions that we support
return false;
}
throw new XNotImplemented("Not implemented: hasSupport(item=" + item + ")");
}
/**
* Answer if these two nodes are the same thing.
* @param test the test to perform
* @param n1 node 1
* @param n2 node 2
*
* @return true/false depending if the objects are the same.
*/
public boolean check ( int test, INode n1, INode n2 ) {
switch (test) {
case TEST_EQUAL :
// is this enough for EMF model ?
if (n1 == n2) {
return true;
}
if (n1 == null || n2 == null) {
return false;
}
// TODO: this is not this simple ...
Object v1 = n1.nodeValue();
Object v2 = n2.nodeValue();
// both identical or null
if (v1 == v2) {
return true;
}
// not identical and *not* both null.
if (v1 != null) {
return v1.equals(v2);
}
// v1 is null and not identical to v2 so false.
return false;
case TEST_COMPATIBLE_PARTNER_ACTIVITY_MESSAGE:
// n1 is source
// n2 is destination
break;
case TEST_COMPATIBLE_TYPE :
// n1 is the source
// n2 is the destination
break;
case TEST_IS_SIMPLE_TYPE :
if (n1 == null || n1.isResolved() == false) {
return false;
}
break;
case TEST_RESOVLED :
if (n1 == null) {
return false;
}
return n1.isResolved();
}
throw new XNotImplemented("Not implemented: check(test=" + test + ")");
}
/**
* Lookup the function meta which is identified by this QName.
* @return the function name
* @see org.eclipse.bpel.validator.model.IModelQuery#lookupFunction(String language, String ns, String name)
*/
public IFunctionMeta lookupFunction (String language, String ns, String name) {
// TODO Fill in function meta
return null;
}
/**
* Lookup the variable which has this name, starting at the current
* context node. Since this is a local BPEL file lookup, we simply
* do it using the INode facade.
*
* @see org.eclipse.bpel.validator.model.IModelQuery#lookupVariable(org.eclipse.bpel.validator.model.INode, java.lang.String)
*/
protected INode lookupVariable (INode context, final String name) {
IFilter<INode> aFilterByName = new NodeAttributeValueFilter(IConstants.AT_NAME, name );
IFilter<INode> aFilterByFaultVariable = new NodeAttributeValueFilter(IConstants.AT_FAULT_VARIABLE, name );
IFilter<INode> aFilterByVariable = new NodeAttributeValueFilter(IConstants.AT_VARIABLE, name );
IFilter<INode> aFilterByCounterName = new NodeAttributeValueFilter(IConstants.AT_COUNTER_NAME, name );
IFilter<INode> nFilterForEach = new NodeNameFilter(IConstants.ND_FOR_EACH);
while (context != null) {
if (Filters.SCOPE_OR_PROCESS.select (context) ) {
// select variables defined in a scope or process
INode var = mSelector.selectNode(context,IConstants.ND_VARIABLES,IConstants.ND_VARIABLE,aFilterByName);
if (var != null) {
return var;
}
// select catch name defined in faultHandlers
var = mSelector.selectNode(context,IConstants.ND_FAULT_HANDLERS,IConstants.ND_CATCH,aFilterByFaultVariable);
if (var != null) {
return var;
}
// https://issues.jboss.org/browse/JBIDE-8044
// select variable defined in onEvent of eventHandlers
var = mSelector.selectNode(context,IConstants.ND_EVENT_HANDLERS,IConstants.ND_ON_EVENT,aFilterByVariable);
if (var != null) {
return var;
}
// select counterName defined in forEach
INode parent = mSelector.selectParent(context,nFilterForEach);
if (parent != null) {
if (aFilterByCounterName.select(parent)) {
return parent;
}
}
}
context = context.parentNode();
}
return null;
}
/**
* Lookup the partner link specified using the context node. Scoping
* rules as in variables are used. The lookup is in the local BPEL file,
* so we simply use the INode facade for that.
*
* @param context
* @param name
* @return the partner link found, or nothing.
*/
protected INode lookupPartnerLink (INode context, String name) {
IFilter<INode> aFilter = new NodeAttributeValueFilter(IConstants.AT_NAME,name );
while (context != null) {
if (Filters.SCOPE_OR_PROCESS.select(context) ) {
INode obj = mSelector.selectNode(context, IConstants.ND_PARTNER_LINKS, IConstants.ND_PARTNER_LINK, aFilter);
if (obj != null) {
return obj;
}
}
context = context.parentNode();
}
return null;
}
/**
* Lookup the correlation set by the name given starting at current
* reference object.
*
* @param context
* @param name
* @return the correlation set or null
*/
protected INode lookupCorrelationSet (INode context, String name) {
IFilter<INode> aFilter = new NodeAttributeValueFilter(IConstants.AT_NAME,name );
while (context != null) {
if (Filters.SCOPE_OR_PROCESS.select(context) ) {
INode obj = mSelector.selectNode(context, IConstants.ND_CORRELATION_SETS, IConstants.ND_CORRELATION_SET, aFilter);
if (obj != null) {
return obj;
}
}
context = context.parentNode();
}
return null;
}
/**
* Lookup and return the specified link name based on the context node.
* @param context
* @param name
* @return the link node or null,
*/
public INode lookupLink ( INode context, String name ) {
IFilter<INode> aFilter = new NodeAttributeValueFilter(IConstants.AT_NAME, name );
while (context != null) {
QName contextNodeName = context.nodeName();
if (contextNodeName.equals(IConstants.ND_FLOW)) {
INode link = mSelector.selectNode(context,IConstants.ND_LINKS,IConstants.ND_LINK, aFilter);
if (link != null) {
return link;
}
}
context = context.parentNode();
}
return null;
}
/**
* General node lookup.
*
* @param context
* @param what
* @param name
* @return the result of the lookup
*/
public INode lookup (INode context, int what, String name ) {
if (isEmpty(name)) {
return null;
}
//
if (name.indexOf(':') >= 0) {
return lookup(context,what,createQName(context, name));
}
return lookup (context, what, new QName(name) );
}
/**
* General node lookup.
*
* @param context the context node, it cannot be null.
* @param what the thing to lookup
* @param qname the QName of the node to lookup
* @return the result of the lookup
*/
public INode lookup ( INode context, int what, QName qname ) {
String name = qname.getLocalPart();
Object modelObject = null;
INode result = null;
// Make sure all the lookup items are switched.
switch (what) {
case LOOKUP_NODE_VARIABLE :
if (context.isResolved()) {
result = lookupVariable(context,name);
}
if (result == null) {
result = new UndefinedNode(IConstants.ND_VARIABLE, IConstants.AT_NAME, name);
}
break;
case LOOKUP_NODE_LINK :
if (context.isResolved()) {
result = lookupLink(context, name);
}
if (result == null) {
result = new UndefinedNode(IConstants.ND_LINK,IConstants.AT_NAME,name);
}
break;
case LOOKUP_NODE_IMPORT :
if (context.isResolved()) {
// lookup in model
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode(IConstants.ND_IMPORT);
}
break;
case LOOKUP_NODE_PARTNER_LINK :
if (context.isResolved() ) {
result = lookupPartnerLink (context, name);
}
if (result == null) {
result = new UndefinedNode(IConstants.ND_PARTNER_LINK,IConstants.AT_NAME,name);
}
break;
case LOOKUP_NODE_CORRELLETION_SET :
if (context.isResolved()) {
result = lookupCorrelationSet (context,name);
}
if (result == null) {
result = new UndefinedNode(IConstants.ND_CORRELATION_SET,IConstants.AT_NAME,name);
}
break;
/**
* The items below are queried from the EMF model. These are largely resolved
* by the model and we rely on that resolution to produce the right result.
*
*/
case LOOKUP_NODE_PARTNER_LINK_TYPE :
if ( context.isResolved() ) {
// lookup in model
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode(IConstants.PLNK_ND_PARTNER_LINK_TYPE, IConstants.AT_NAME, qname.getLocalPart() );
}
break;
case LOOKUP_NODE_ROLE :
if ( context.isResolved() ) {
// lookup in model
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode(IConstants.PLNK_ND_PARTNER_LINK_TYPE, IConstants.AT_NAME, name );
}
break;
case LOOKUP_NODE_OPERATION :
if ( context.isResolved()) {
// lookup in model
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode ( IConstants.WSDL_ND_OPERATION, IConstants.AT_NAME, name );
}
break;
case LOOKUP_NODE_PORT_TYPE :
if ( context.isResolved() ) {
// lookup in model
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode ( IConstants.WSDL_ND_PORT_TYPE, IConstants.AT_NAME, qname.getLocalPart() );
}
break;
case LOOKUP_NODE_MESSAGE_TYPE :
if ( context.isResolved() ) {
// lookup in model
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode(IConstants.WSDL_ND_MESSAGE, IConstants.AT_NAME, qname.getLocalPart() );
}
break;
case LOOKUP_NODE_MESSAGE_PART :
if (modelObject == null) {
result = new UndefinedNode(IConstants.WSDL_ND_PART, IConstants.AT_NAME, qname.getLocalPart() );
}
break;
case LOOKUP_NODE_XSD_ELEMENT :
if ( context.isResolved() ) {
// lookup model object
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode(IConstants.AT_ELEMENT,IConstants.AT_NAME, qname.getLocalPart());
}
break;
case LOOKUP_NODE_XSD_TYPE :
if (context.isResolved()) {
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode(IConstants.AT_TYPE,IConstants.AT_NAME, qname.getLocalPart());
}
break;
case LOOKUP_NODE_PROPERTY :
if (context.isResolved()) {
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode(IConstants.VPROP_ND_PROPERTY, IConstants.AT_NAME, qname.getLocalPart());
}
break;
case LOOKUP_NODE_NAME_STEP :
if (context.isResolved()) {
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode(IConstants.AT_ELEMENT,IConstants.AT_NAME,qname.getLocalPart() );
}
break;
case LOOKUP_NODE_NAME_STEP_ATTRIBUTE :
if (context.isResolved()) {
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode(IConstants.AT_ELEMENT,IConstants.AT_NAME,qname.getLocalPart() );
}
break;
case LOOKUP_NODE_TYPE_OF_PART :
if (context.isResolved()) {
modelObject = null;
}
if (modelObject == null) {
result = new UndefinedNode(IConstants.AT_ELEMENT,IConstants.AT_NAME,"Unknown");
}
break ;
default :
throw new XNotImplemented("Not implemented: lookupNode(item=" + what + ")");
}
if (modelObject == null) {
return result ;
}
return adapt ( modelObject, INode.class, ADAPT_HINT_NONE );
}
/**
* Lookup some text related item in the model object.
*
* @param context the context node
* @param what what to lookup
* @param key the value to lookup
* @param def the default value to return
* @return the looked up value.
*
*/
@SuppressWarnings("nls")
public String lookup ( INode context, int what, String key, String def) {
Element elm ;
switch (what) {
case LOOKUP_TEXT_LOCATION :
// Should this be anything else ?
return context.nodeName().getLocalPart();
case LOOKUP_TEXT_NS2PREFIX :
if (key == null) {
break;
}
elm = adapt(context,Element.class,ADAPT_HINT_NONE);
if (elm != null) {
String result = elm.lookupPrefix(key);
return result != null ? result : def;
}
break;
case LOOKUP_TEXT_PREFIX2NS :
if (key == null) {
break;
}
elm = adapt(context,Element.class,ADAPT_HINT_NONE);
if (elm != null) {
String result = elm.lookupNamespaceURI(key);
return result != null ? result : def;
}
break;
case LOOKUP_TEXT_TEXT :
elm = adapt(context,Element.class,ADAPT_HINT_NONE);
if (elm == null) {
break;
}
StringBuilder text = new StringBuilder();
Node n = elm.getFirstChild();
while (n != null) {
text.append( n.getTextContent() );
n = n.getNextSibling();
}
return text.toString();
case LOOKUP_TEXT_HREF :
// not implement here.
break;
case LOOKUP_TEXT_RESOURCE_PATH :
elm = adapt(context,Element.class,ADAPT_HINT_NONE);
if (elm == null) {
return def;
}
Document document = elm.getOwnerDocument();
return document.getDocumentURI();
case LOOKUP_TEXT_HREF_XPATH :
elm = adapt(context,Element.class,ADAPT_HINT_NONE);
if (elm == null) {
return def;
}
return computeXPathTo ( elm );
default :
throw new XNotImplemented("Not implemented: lookupText(item=" + what + ")");
}
return def;
}
/**
* Lookup a number value or parameter in the model.
* @param context
* @param what
* @param def
* @return the looked-up value, or the default return value passed.
*
*/
@SuppressWarnings("nls")
public int lookup ( INode context, int what, int def ) {
Element elm = adapt(context,Element.class,ADAPT_HINT_NONE);
if (elm == null) {
return def;
}
String key = null;
switch (what) {
case LOOKUP_NUMBER_LINE_NO :
key = "location.line";
break;
case LOOKUP_NUMBER_COLUMN_NO :
key = "location.column";
break;
case LOOKUP_NUMBER_CHAR_START :
key = "location.charStart";
break;
case LOOKUP_NUMBER_CHAR_END :
key = "location.charEnd";
break;
case LOOKUP_NUMBER_LINE_NO_2 :
key = "location2.line";
break;
case LOOKUP_NUMBER_COLUMN_NO_2 :
key = "location2.column";
break;
case LOOKUP_NUMBER_CHAR_START_2 :
key = "location2.charStart";
break;
case LOOKUP_NUMBER_CHAR_END_2 :
key = "location2.charEnd";
break;
default :
throw new XNotImplemented("Not implemented: lookupNumber(item=" + what + ")");
}
try {
return ((Number)elm.getUserData(key)).intValue();
} catch (Throwable t) {
//
}
return def;
}
/**
* Create the QName from the name indicated. The context node is used to resolve
* namespaces prefixes.
*
* @param context the context node
* @param name
* @return the QName parsed out from name.
*/
@SuppressWarnings("nls")
public QName createQName ( INode context, String name ) {
int index = name.indexOf(':');
String prefix = (index != -1)? name.substring(0, index): "";
String localPart = name.substring(index + 1);
String namespaceURI = lookup(context, LOOKUP_TEXT_PREFIX2NS, prefix, null );
// namespaceURI may be null. That's okay.
return new QName(namespaceURI, localPart, prefix );
}
/**
* Adapt the target to a type. This goes through the platform adapter
* mechanism.
*
* @param <T>
* @param target
* @param type
* @param hint hint for the adapter
* @return an object that is the adapter the target with the given class.
*/
public <T extends Object> T adapt (Object target, Class<T> type, int hint) {
if (type.isInstance(target) || target == null) {
return type.cast(target);
}
if (target instanceof Node) {
Node node = (Node) target;
// Node -> INode
if (type == INode.class) {
Object adapter = node.getUserData(DOMNodeAdapter.KEY);
if (adapter instanceof DOMNodeAdapter) {
return type.cast(adapter);
}
adapter = new DOMNodeAdapter( node );
node.setUserData(DOMNodeAdapter.KEY, adapter, null );
return type.cast(adapter);
}
}
if (target instanceof INode) {
INode aTarget = (INode) target;
// INode -> ... whatever
Object value = aTarget.nodeValue();
if (type.isInstance(value)) {
return type.cast(value);
}
}
return null;
}
static protected boolean isEmpty ( String value ) {
return value == null || value.length() == 0;
}
/**
* Compute the the XPath to the node child from the root of the XML
* tree. Since this is just based on the instance of this document,
* we must proceed every element selection by an index [] of the element.
* @param child
* @return the XPath from the root of the document tree.
*/
@SuppressWarnings("nls")
static public String computeXPathTo (Node child) {
Stack<String> stack = new Stack<String>();
Node parent = null;
if (child.getNodeType() == Node.CDATA_SECTION_NODE) {
return "--No XPath to CDATA NODE exists --";
}
// Attribute nodes are special since they are children of
// the element node.
if (child.getNodeType() == Node.ATTRIBUTE_NODE) {
Attr att = (Attr) child;
stack.push("/@" + att.getName());
child = att.getOwnerElement();
}
parent = child.getParentNode();
while (parent != null && parent != child) {
NodeList nl = parent.getChildNodes();
int idx = 1;
int cnt = 0;
for (int i = 0, j = nl.getLength(); i < j; i++) {
Node anode = nl.item(i);
if (anode.getNodeType() != child.getNodeType()) {
continue;
}
if (anode.getNodeName().equals(child.getNodeName()) == false) {
continue;
}
// We have seen cnt nodes that match the type and the name
// to the one that we are. In other words, our parent
// has "cnt" children nodes.
cnt += 1;
if (anode.equals(child)) {
idx = cnt;
}
}
// this is the node, figure how to get here.
// Since this is based on the instance of XML document,
// we can figure out the path by doing some shortcuts.
String cmd = "";
switch (child.getNodeType()) {
case Node.TEXT_NODE:
cmd = "/text()";
break;
case Node.COMMENT_NODE:
cmd = "/comment()";
break;
default :
String ns = child.getNamespaceURI();
if (ns == null || ns.length() == 0) {
cmd = "/" + child.getNodeName();
} else if (child.getPrefix() == null) {
cmd = "/:" + child.getLocalName();
} else {
cmd = "/" + child.getPrefix() + ":" + child.getLocalName();
}
break;
}
stack.push(cmd + (cnt == 1 ? "" : "[" + idx + "]"));
// Go up
parent = parent.getParentNode();
child = child.getParentNode();
}
// Now we are done.
StringBuilder xpath = new StringBuilder(256);
while (stack.isEmpty() == false) {
xpath.append(stack.pop());
}
return xpath.toString();
}
/**
* Return our priority.
* @return we are at priority 0
*/
public int priority () {
return 0;
}
/**
* The rest is a static implementation which deals with collecting model query
* implementations from other plugins.
*/
static IModelQuery gModelQuery = null;
static IModelQuery[] gaModelQuery = {};
static ArrayList<IModelQuery> gModelQueryList = new ArrayList<IModelQuery> (8) ;
/**
*
* @param mq
*/
static public final void register ( IModelQuery mq ) {
gModelQuery = mq;
gModelQueryList.add(mq);
// Force re computation of the query model chain.
gaModelQuery = null;
}
/**
* @return the model query interface.
*/
static public final IModelQuery getModelQuery () {
if (gModelQuery != null) {
return gModelQuery;
}
gaModelQuery = gModelQueryList.toArray(gaModelQuery);
if (gaModelQuery.length == 0) {
gModelQuery = new ModelQueryImpl();
} else if (gaModelQuery.length == 1) {
gModelQuery = gaModelQuery[0];
} else {
Arrays.sort(gaModelQuery, new Comparator<IModelQuery>() {
public int compare(IModelQuery o1, IModelQuery o2) {
return o1.priority() - o2.priority();
}
});
gModelQuery = (IModelQuery) java.lang.reflect.Proxy.newProxyInstance(
ModelQueryImpl.class.getClassLoader(),
new Class<?>[]{ IModelQuery.class },
new InvocationHandler () {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
for(IModelQuery mq : gaModelQuery) {
try {
result = method.invoke(mq, args);
if (result != null) {
return result;
}
} catch (XNotImplemented xnotImpl) {
// not implemented by this model query instance
}
}
return result;
}
});
}
// Return the model query object
return gModelQuery;
}
/**
* Searches all imports in the given Process for conflicting XSD definitions
*
* @param process the containing Process
* @param node the XSD element reference
* @return the list of Imports that contain conflicting definitions or null
* if there are no conflicts.
* @see https://issues.jboss.org/browse/JBIDE-8088
*/
@Override
public List<Import> findConflictingXSD(Process process, INode node) {
EObject o1 = adapt(node, EObject.class, ADAPT_HINT_NONE);
List<Import> imports = null;
List<Import> conflicts = new ArrayList<Import>();
QName qname = null;
if (o1 instanceof XSDTypeDefinition) {
qname = this.createQName(node, ((XSDTypeDefinition) o1).getName());
if ("".equals(qname.getNamespaceURI())) {
qname = new QName(((XSDTypeDefinition) o1).getTargetNamespace(), qname.getLocalPart());
}
imports = emfModelQuery.scanAllImports(process, qname, XSDUtil.XSD_TYPE_DEFINITION);
} else if (o1 instanceof XSDElementDeclaration) {
qname = this.createQName(node, ((XSDElementDeclaration) o1).getName());
if ("".equals(qname.getNamespaceURI())) {
qname = new QName(((XSDElementDeclaration) o1).getTargetNamespace(), qname.getLocalPart());
}
imports = emfModelQuery.scanAllImports(process, qname, XSDUtil.XSD_ELEMENT_DECLARATION);
}
if (imports != null && imports.size() > 1) {
EObject o2 = null;
o1 = null;
for (Import imp : imports) {
EObject resolvedImport = emfModelQuery.lookupImport(imp, null);
if (o1 == null) {
if (o1 instanceof XSDTypeDefinition) {
o1 = emfModelQuery.lookupXSDType(resolvedImport, qname);
} else {
o1 = emfModelQuery.lookupXSDElement(resolvedImport, qname);
}
conflicts.add(imp);
} else {
if (o2 instanceof XSDTypeDefinition) {
o2 = emfModelQuery.lookupXSDType(resolvedImport, qname);
} else {
o2 = emfModelQuery.lookupXSDElement(resolvedImport, qname);
}
if (!emfModelQuery.compatibleType(o1, o2)) {
conflicts.add(imp);
}
}
}
}
return conflicts.size()>1 ? conflicts : null;
}
/**
* Returns the Process that corresponds to the given node
*
* @param node the Process element
* @return the Process or null
* @see https://issues.jboss.org/browse/JBIDE-8088
*/
@Override
public Process lookupProcess(INode node) {
EObject root = emfModelQuery.getRoot( adapt(node, EObject.class, ADAPT_HINT_NONE) );
if (root instanceof Process)
return (Process) root;
return null;
}
}