/**
* <copyright>
*
* Copyright (c) 2008,2010 E.D.Willink 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:
* E.D.Willink - initial API and implementation
*
* </copyright>
*
* $Id: UnresolvedEnvironment.java,v 1.2 2010/04/08 06:26:24 ewillink Exp $
*/
package org.eclipse.ocl.examples.parser.environment;
import java.util.List;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.ocl.examples.common.utils.EcoreUtils;
import org.eclipse.ocl.examples.modelregistry.environment.FileHandle;
/**
* The UnresolvedEnvironment maintains a root package named $unresolved$ within which appropriate
* EObjects are created to terminate references that cannot be resolved to semantically valid elements.
*/
public class UnresolvedEnvironment
{
public static final String UNRESOLVED_PACKAGE_NAME = "$unresolved$";
/**
* Return a plausible suggestion for a package namespace for the ePackage within file.
*/
public static String computePackageNs(FileHandle file, EPackage ePackage) {
StringBuilder s = new StringBuilder();
s.append("http://");
s.append(file.getProjectHandle().getName());
s.append("/");
s.append(file.getProjectRelativeName());
s.append("/");
computePackageNs(s, ePackage);
String string = s.toString();
return string;
}
private static void computePackageNs(StringBuilder s, ENamedElement eNamedElement) {
EObject eContainer = eNamedElement.eContainer();
if (eContainer instanceof ENamedElement) {
computePackageNs(s, (ENamedElement) eContainer);
s.append(".");
}
s.append(eNamedElement.getName());
}
protected final ICSTRootEnvironment<?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?> rootEnvironment;
private EPackage rootPackage = null;
public UnresolvedEnvironment(ICSTRootEnvironment<?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?> rootEnvironment) {
this.rootEnvironment = rootEnvironment;
}
public String computePackageNs(EPackage ePackage) {
ICSTFileEnvironment<?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?> fileEnvironment = rootEnvironment.getFileEnvironment();
return computePackageNs(fileEnvironment.getFile(), ePackage);
}
public EAttribute getUnresolvedEAttribute(EClassifier classifier, String featureName) {
EClass unresolvedEClass = getUnresolvedEClass(classifier);
String name = "attribute$" + featureName;
EAttribute unresolvedEAttribute = (EAttribute) unresolvedEClass.getEStructuralFeature(name);
if (unresolvedEAttribute == null) {
unresolvedEAttribute = EcoreFactory.eINSTANCE.createEAttribute();
unresolvedEAttribute.setName(name);
unresolvedEAttribute.setEType(EcorePackage.Literals.ESTRING);
unresolvedEClass.getEStructuralFeatures().add(unresolvedEAttribute);
}
return unresolvedEAttribute;
}
public EClass getUnresolvedEClass(EClassifier eClass) {
if (isUnresolved(eClass))
return (EClass) eClass;
String name = eClass != null ? "class$" + eClass.getName() : "$class$";
EPackage unresolvedEPackage = eClass != null ? getUnresolvedEPackage(eClass.getEPackage()) : getUnresolvedEPackage();
EClass unresolvedEClassifier = (EClass) unresolvedEPackage.getEClassifier(name);
if (unresolvedEClassifier == null) {
unresolvedEClassifier = EcoreFactory.eINSTANCE.createEClass();
unresolvedEClassifier.setName(name);
unresolvedEPackage.getEClassifiers().add(unresolvedEClassifier);
}
return unresolvedEClassifier;
}
/**
* Return the unresolved class named by the tail of path.
*/
public EClass getUnresolvedEClass(List<String> path) {
if (path == null)
return getUnresolvedEClass((EClassifier)null);
EPackage unresolvedEPackage = getUnresolvedEPackage();
for (int i = 0; i < path.size()-1; i++)
unresolvedEPackage = getUnresolvedEPackage(unresolvedEPackage, path.get(i));
String name = "class$" + path.get(path.size()-1);
EClass unresolvedEClass = (EClass) unresolvedEPackage.getEClassifier(name);
if (unresolvedEClass == null) {
unresolvedEClass = EcoreFactory.eINSTANCE.createEClass();
unresolvedEClass.setName(name);
unresolvedEPackage.getEClassifiers().add(unresolvedEClass);
}
return unresolvedEClass;
}
public EDataType getUnresolvedEDataType(EPackage resolvedEPackage, String typeName) {
EPackage unresolvedEPackage = getUnresolvedEPackage(resolvedEPackage);
String name = "datatype$" + typeName;
EDataType unresolvedEDataType = (EDataType) unresolvedEPackage.getEClassifier(name);
if (unresolvedEDataType == null) {
unresolvedEDataType = EcoreFactory.eINSTANCE.createEDataType();
unresolvedEDataType.setName(name);
unresolvedEPackage.getEClassifiers().add(unresolvedEDataType);
}
return unresolvedEDataType;
}
public EOperation getUnresolvedEOperation(EClassifier resolvedEClass, String operationName) {
EClass unresolvedEClass = getUnresolvedEClass(resolvedEClass);
String name = "reference$" + operationName;
EOperation unresolvedEOperation = EcoreUtils.getNamedElement(unresolvedEClass.getEOperations(), name);
if (unresolvedEOperation == null) {
unresolvedEOperation = EcoreFactory.eINSTANCE.createEOperation();
unresolvedEOperation.setName(name);
unresolvedEClass.getEOperations().add(unresolvedEOperation);
}
return unresolvedEOperation;
}
/**
* Return the root unresolved package of the unresolved tree.
*/
public EPackage getUnresolvedEPackage() {
if (rootPackage == null) {
rootPackage = EcoreFactory.eINSTANCE.createEPackage();
rootPackage.setName(UNRESOLVED_PACKAGE_NAME);
rootPackage.setNsPrefix("_unresolved_");
rootPackage.setNsURI(computePackageNs(rootPackage));
}
return rootPackage;
}
public EPackage getUnresolvedEPackage(List<String> sequenceOfNames) {
EPackage ePackage = getUnresolvedEPackage();
for (String name : sequenceOfNames)
ePackage = getUnresolvedEPackage(ePackage, name);
return ePackage;
}
/**
* Return the unresolved package corresponding to ePackage, the root unresolved package if
* ePackage null.
*/
public EPackage getUnresolvedEPackage(EPackage ePackage) {
if (ePackage == null)
return getUnresolvedEPackage();
if (isUnresolved(ePackage))
return ePackage;
EPackage unresolvedParentEPackage = getUnresolvedEPackage(ePackage.getESuperPackage());
return getUnresolvedEPackage(unresolvedParentEPackage, ePackage.getName());
}
/**
* Return the unresolved sub-package named name of a specific unresolved package or the root unresolved
* package if null.
*/
public EPackage getUnresolvedEPackage(EPackage unresolvedPackage, String name) {
if (unresolvedPackage == null)
unresolvedPackage = getUnresolvedEPackage();
EPackage ePackage = EcoreUtils.getNamedElement(unresolvedPackage.getESubpackages(), name);
if (ePackage == null) {
ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName(name);
ePackage.setNsPrefix(name);
ePackage.setNsURI(computePackageNs(ePackage));
unresolvedPackage.getESubpackages().add(ePackage);
}
return ePackage;
}
public EReference getUnresolvedEReference(EClassifier resolvedEClass, String featureName) {
EClass unresolvedEClass = getUnresolvedEClass(resolvedEClass);
String name = "reference$" + featureName;
EReference unresolvedEReference = (EReference) unresolvedEClass.getEStructuralFeature(name);
if (unresolvedEReference == null) {
unresolvedEReference = EcoreFactory.eINSTANCE.createEReference();
unresolvedEReference.setName(featureName);
unresolvedEReference.setEType(unresolvedEClass);
unresolvedEClass.getEStructuralFeatures().add(unresolvedEReference);
}
return unresolvedEReference;
}
/**
* Return true if eObject is an unresolved object. i.e. if eObject has the
* root unresolved package as an ancestor.
*/
public boolean isUnresolved(EObject eObject) {
if (rootPackage != null) {
for ( ; eObject != null; eObject = eObject.eContainer())
if (eObject == rootPackage)
return true;
}
return false;
}
}