/*******************************************************************************
* Copyright (c) 2007, 2014 Borland Software 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:
* Borland Software Corporation - initial API and implementation
* Alex Paperno - bugs 416584
* Christine Gerpheide - bug 432969
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.ast.env;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EPackage.Registry;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.impl.EPackageRegistryImpl;
import org.eclipse.m2m.internal.qvt.oml.NLS;
import org.eclipse.m2m.internal.qvt.oml.QvtPlugin;
import org.eclipse.m2m.internal.qvt.oml.evaluator.InternalEvaluator;
import org.eclipse.m2m.internal.qvt.oml.evaluator.QvtGenericVisitorDecorator;
import org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl;
import org.eclipse.m2m.internal.qvt.oml.expressions.Module;
import org.eclipse.m2m.qvt.oml.util.IContext;
import org.eclipse.ocl.Environment;
import org.eclipse.ocl.EvaluationEnvironment;
import org.eclipse.ocl.EvaluationVisitor;
import org.eclipse.ocl.ecore.CallOperationAction;
import org.eclipse.ocl.ecore.Constraint;
import org.eclipse.ocl.ecore.EcoreEnvironmentFactory;
import org.eclipse.ocl.ecore.SendSignalAction;
/**
* A factory class for operational QVT environments creation.
*/
public class QvtOperationalEnvFactory extends EcoreEnvironmentFactory {
/**
* A shared instance of the QV environment factory using the global package registry
* for creating environments.
* <p>
* FIXME - Using a copy of the global registry until it's ensured that QVT environments do not
* store into its package registry imported metamodels, so other EMF clients are not affected.
*/
public static final QvtOperationalEnvFactory INSTANCE = new QvtOperationalEnvFactory();
/* TODO - Do we need a default constructor? */
public QvtOperationalEnvFactory() {
super(copyPackageRegistry(EPackage.Registry.INSTANCE));
}
/**
* Initializes me with an <code>EPackage.Registry</code> that the
* environments I create will use to look up packages.
*
* @param reg my package registry (must not be <code>null</code>)
*/
public QvtOperationalEnvFactory(Registry reg) {
super(reg);
}
@Override
public QvtOperationalEnv createEnvironment() {
QvtOperationalEnv env = new QvtOperationalEnv(getEPackageRegistry(), null);
env.setFactory(this);
return env;
}
public QvtOperationalFileEnv createEnvironment(final URI uri) {
QvtOperationalFileEnv env = new QvtOperationalFileEnv(uri, getEPackageRegistry());
env.setFactory(this);
return env;
}
@Override
public QvtOperationalEnv createEnvironment(Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> parent) {
if (!(parent instanceof QvtOperationalEnv)) {
throw new IllegalArgumentException(
"Parent environment must be a QvtOperationalEnv: " + parent); //$NON-NLS-1$
}
return createEnvironment((QvtOperationalEnv) parent);
}
public QvtOperationalEnv createEnvironment(final QvtOperationalEnv parent) {
QvtOperationalEnv env = new QvtOperationalEnv(parent);
env.setFactory(this);
return env;
}
public QvtOperationalModuleEnv createModuleEnvironment(final Module module) {
QvtOperationalModuleEnv env = new QvtOperationalModuleEnv(getEPackageRegistry(), module.eResource());
env.setFactory(this);
env.setContextModule(module);
QvtOperationalStdLibrary.INSTANCE.importTo(env);
return env;
}
public QvtOperationalModuleEnv createModuleEnvironment(final Module module, QvtOperationalFileEnv parentEnv) {
QvtOperationalModuleEnv moduleEnv = new QvtOperationalModuleEnv(parentEnv.getEPackageRegistry(), parentEnv.getTypeResolver().getResource());
moduleEnv.setFactory(this);
moduleEnv.setContextModule(module);
QvtOperationalStdLibrary.INSTANCE.importTo(moduleEnv);
parentEnv.addInnerEnvironment(moduleEnv);
moduleEnv.setFileParent(parentEnv);
moduleEnv.setASTNodeToCSTNodeMap(parentEnv.getASTNodeToCSTNodeMap());
return moduleEnv;
}
@Override
public QvtOperationalEnv createOperationContext(
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> parent,
EOperation operation) {
QvtOperationalEnv newEnv = createEnvironment(parent);
QvtOperationalEnv parentEnv = (QvtOperationalEnv) parent;
newEnv.setASTNodeToCSTNodeMap(parentEnv.getASTNodeToCSTNodeMap());
newEnv.setContextOperation(operation);
return newEnv;
}
@Override
public EvaluationEnvironment<EClassifier, EOperation, EStructuralFeature, EClass, EObject> createEvaluationEnvironment(
EvaluationEnvironment<EClassifier, EOperation, EStructuralFeature, EClass, EObject> parent) {
if(parent instanceof QvtOperationalEvaluationEnv) {
QvtOperationalEvaluationEnv qvtParentEnv = (QvtOperationalEvaluationEnv) parent;
return new QvtOperationalEvaluationEnv(qvtParentEnv.getContext(), qvtParentEnv);
}
return super.createEvaluationEnvironment(parent);
}
public QvtOperationalEvaluationEnv createEvaluationEnvironment(IContext context, QvtOperationalEvaluationEnv parent) {
return new QvtOperationalEvaluationEnv(context, parent);
}
@Override
public EvaluationVisitor<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> createEvaluationVisitor(
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env,
EvaluationEnvironment<EClassifier, EOperation, EStructuralFeature, EClass, EObject> evalEnv,
Map<? extends EClass, ? extends Set<? extends EObject>> extentMap) {
if((env instanceof QvtOperationalEnv == false) || (evalEnv instanceof QvtOperationalEvaluationEnv == false)) {
return super.createEvaluationVisitor(env, evalEnv, extentMap);
}
InternalEvaluator visitor = (InternalEvaluator) QvtOperationalEvaluationVisitorImpl.createVisitor((QvtOperationalEnv)env, (QvtOperationalEvaluationEnv)evalEnv);
// Wrap in any decorators
for(Class<? extends QvtGenericVisitorDecorator> cls : ((QvtOperationalEvaluationEnv)evalEnv).getVisitorDecoratorClasses()) {
try {
visitor = cls.getDeclaredConstructor(InternalEvaluator.class).newInstance(visitor);
} catch(Exception e) {
String message = NLS.bind("Error while constructing visitor decorator:''{0}''", cls.getName());
QvtPlugin.getDefault().log(new Status(IStatus.ERROR, QvtPlugin.ID, message, e));
}
}
return visitor;
}
private static EPackage.Registry copyPackageRegistry(EPackage.Registry registry) {
EPackageRegistryImpl result = new EPackageRegistryImpl();
result.putAll(registry);
return result;
}
}