/*******************************************************************************
* Copyright (c) 2010 SAP AG.
* 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:
* Emil Simeonov - initial API and implementation.
* Dimitar Donchev - initial API and implementation.
* Dimitar Tenev - initial API and implementation.
* Nevena Manova - initial API and implementation.
* Georgi Konstantinov - initial API and implementation.
*******************************************************************************/
package org.eclipse.wst.sse.sieditor.model.validation;
import java.util.Collection;
import java.util.Stack;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xsd.XSDAttributeDeclaration;
import org.eclipse.xsd.XSDAttributeUse;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDDiagnostic;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDFacet;
import org.eclipse.xsd.XSDFeature;
import org.eclipse.xsd.XSDImport;
import org.eclipse.xsd.XSDModelGroup;
import org.eclipse.xsd.XSDNamedComponent;
import org.eclipse.xsd.XSDParticle;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDTypeDefinition;
import org.eclipse.wst.sse.sieditor.model.api.IModelObject;
import org.eclipse.wst.sse.sieditor.model.api.INamedObject;
import org.eclipse.wst.sse.sieditor.model.api.IXSDModelRoot;
import org.eclipse.wst.sse.sieditor.model.impl.XSDFactory;
import org.eclipse.wst.sse.sieditor.model.xsd.api.IElement;
import org.eclipse.wst.sse.sieditor.model.xsd.api.ISchema;
import org.eclipse.wst.sse.sieditor.model.xsd.api.IStructureType;
import org.eclipse.wst.sse.sieditor.model.xsd.api.IType;
import org.eclipse.wst.sse.sieditor.model.xsd.impl.Schema;
public class EsmXsdModelAdapter implements IModelAdapter {
public EObject adapatToEMF(Object source) {
if (source instanceof INamedObject) {
if (source instanceof IType) {
final IType type = (IType) source;
return type.isAnonymous() ? type.getParent().getComponent() : type.getComponent();
}
return ((INamedObject) source).getComponent();
} else if (source instanceof ISchema) {
return ((ISchema) source).getComponent();
}
return null;
}
public IModelObject adaptToModelObject(EObject source) {
if (!(source instanceof XSDConcreteComponent)) {
return null;
}
if (source instanceof XSDDiagnostic) {
return adaptToModelObject(((XSDDiagnostic) source).getPrimaryComponent());
}
IXSDModelRoot modelRoot = getXSDModelRoot(source);
if (source instanceof XSDImport) {
XSDSchema resolvedSchema = ((XSDImport) source).getResolvedSchema();
if (resolvedSchema != null) {
ISchema referredSchema = modelRoot.getSchema().getReferredSchema(resolvedSchema);
return referredSchema;
}
return null;
}
final XSDConcreteComponent xsdComponent = (XSDConcreteComponent) source;
final ISchema schema = modelRoot.getSchema();
final String targetNamespace = schema.getComponent().getTargetNamespace();
final String componentTargetNamespace = xsdComponent.getSchema().getTargetNamespace();
if ((targetNamespace != null && componentTargetNamespace == null)
|| (targetNamespace == null && componentTargetNamespace != null)) {
return null;
}
if ((targetNamespace == null && componentTargetNamespace == null) || targetNamespace.equals(componentTargetNamespace)) {
if (xsdComponent instanceof XSDSchema) {
return modelRoot.getSchema();
} else if (xsdComponent instanceof XSDTypeDefinition) {
return adaptTypeDefiniton(false, (XSDTypeDefinition) xsdComponent);
} else if (xsdComponent instanceof XSDElementDeclaration && ((XSDElementDeclaration) xsdComponent).isGlobal()) {
return adaptTypeDefiniton(true, ((XSDElementDeclaration) xsdComponent));
} else if (xsdComponent instanceof XSDFeature) {
return adaptXSDFeature((XSDFeature) xsdComponent);
} else if (xsdComponent instanceof XSDFacet) {
return adaptXSDFacet((XSDFacet) xsdComponent);
} else if (xsdComponent instanceof XSDModelGroup) {
return adaptToParentNamedComponent(xsdComponent);
} else if (xsdComponent instanceof XSDAttributeUse) {
return adaptToParentNamedComponent(xsdComponent);
}
}
return null;
}
private IModelObject adaptToParentNamedComponent(XSDConcreteComponent xsdComponent) {
XSDConcreteComponent container = xsdComponent.getContainer();
while (container != null) {
if (container instanceof XSDNamedComponent && ((XSDNamedComponent) container).getName() != null) {
return adaptToModelObject(container);
}
container = container.getContainer();
}
return null;
}
private IModelObject adaptXSDFacet(XSDFacet xsdFacet) {
return adaptTypeDefiniton(false, xsdFacet.getSimpleTypeDefinition());
}
private IModelObject adaptXSDFeature(XSDFeature xsdFeature) {
IXSDModelRoot modelRoot = getXSDModelRoot(xsdFeature);
if (xsdFeature.isGlobal()) {
final IType[] types = ((Schema) modelRoot.getSchema()).getAllTypes(xsdFeature.getName());
if (types != null) {
for (IType type : types) {
if (type.getComponent() == xsdFeature) {
return type;
}
}
}
}
final Stack<XSDNamedComponent> path = new Stack<XSDNamedComponent>();
XSDConcreteComponent parent = xsdFeature;
while (!(parent instanceof XSDSchema)) {
if (parent instanceof XSDNamedComponent) {
final XSDNamedComponent namedComponent = (XSDNamedComponent) parent;
if (namedComponent.getName() != null) {
path.add(namedComponent);
} else {
if (namedComponent instanceof XSDElementDeclaration) {
XSDElementDeclaration xsdElementDeclaration = (XSDElementDeclaration) namedComponent;
if (xsdElementDeclaration.isElementDeclarationReference()) {
XSDElementDeclaration resolvedElementDeclaration = xsdElementDeclaration
.getResolvedElementDeclaration();
path.add(resolvedElementDeclaration);
}
}
}
}
parent = parent.getContainer();
}
IType type = null;
if (!path.isEmpty()) {
XSDNamedComponent namedComponent = path.pop();
type = modelRoot.getSchema().getType(namedComponent instanceof XSDElementDeclaration, namedComponent.getName());
}
return resolveElement((IStructureType) type, xsdFeature, path);
}
private IElement resolveElement(IStructureType type, XSDFeature xsdFeature, Stack<XSDNamedComponent> path) {
if (type == null || path.size() == 0) {
return null;
}
final Collection<IElement> elements = type.getElements(path.pop().getName());
if (elements.size() == 0) {
return null;
}
// final IElement element = elements.iterator().next();
for (IElement element : elements) {
XSDConcreteComponent component = element.getComponent();
if (component instanceof XSDParticle && ((XSDParticle) component).getContent() == xsdFeature) {
return element;
} else if ((component instanceof XSDAttributeDeclaration) && component == xsdFeature) {
return element;
}
}
IType nextType = elements.iterator().next().getType();
IStructureType structureType = (IStructureType) nextType;
return resolveElement(structureType, xsdFeature, path);
}
private IModelObject adaptTypeDefiniton(boolean isElementDeclaration, XSDNamedComponent typeDefinition) {
if (typeDefinition.getName() != null) {
IXSDModelRoot modelRoot = getXSDModelRoot(typeDefinition);
IType[] allTypes = modelRoot.getSchema().getAllTypes(typeDefinition.getName());
if(allTypes == null){
return adaptToModelObject(typeDefinition.eContainer());
}
for (IType iType : allTypes) {
if (iType.getComponent().equals(typeDefinition)) {
return iType;
}
}
}
return adaptToModelObject(typeDefinition.eContainer());
}
private IXSDModelRoot getXSDModelRoot(EObject xsdObject) {
IXSDModelRoot xsdModelRoot = null;
if (xsdObject instanceof XSDSchema) {
return XSDFactory.getInstance().createXSDModelRoot((XSDSchema) xsdObject);
} else if (xsdObject != null) {
xsdModelRoot = getXSDModelRoot(xsdObject.eContainer());
}
return xsdModelRoot;
}
}