org.eclipse.ocl.AbstractEnvironmentFactory Maven / Gradle / Ivy
/**
*
*
* Copyright (c) 2005, 2010 IBM Corporation, Borland Software Corp., 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 - Initial API and implementation
* E.D.Willink - Refactoring to support extensibility and flexible error handling
* Borland - Bug 265066
* Adolfo Sanchez-Barbudo Herrera (Open Canarias) - Bug 333032
*
*
*
* $Id: AbstractEnvironmentFactory.java,v 1.8 2010/12/24 10:18:07 asanchez Exp $
*/
package org.eclipse.ocl;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.ocl.expressions.Variable;
import org.eclipse.ocl.helper.OCLSyntaxHelper;
import org.eclipse.ocl.internal.evaluation.TracingEvaluationVisitor;
import org.eclipse.ocl.parser.AbstractOCLParser;
import org.eclipse.ocl.parser.OCLAnalyzer;
import org.eclipse.ocl.parser.OCLFactoryWithHistory;
import org.eclipse.ocl.parser.ValidationVisitor;
import org.eclipse.ocl.util.Adaptable;
import org.eclipse.ocl.util.TypeUtil;
import org.eclipse.ocl.utilities.OCLFactory;
import org.eclipse.ocl.utilities.UMLReflection;
import org.eclipse.ocl.utilities.Visitor;
/**
* Partial implementation of the {@link EnvironmentFactory} interface, useful
* for subclassing to define the OCL binding for a metamodel. This abstract
* class takes care of some of the more common (and mundane) chores, such as:
*
* - defining the "self" variable in the classifier context
* - creating variables for operation parameters in an operation context
*
*
* The subclass's responsibility (in addition to implementing any other
* interface methods not implemented here) is to define how to:
*
*
* - {@linkplain #getClassifier obtain} the classifier in the
* user model of an input element (which may already be a classifier
* or an may be an M0 instance)
* - {@linkplain #lookupPackage lookup} a package in the model associated
* with this environment factory
*
*
* This class is intended to be extended by clients, for the purpose of
* implementing metamodel-specific environment factories.
*
*
* See the {@link EnvironmentFactory} class for a description of the
* generic type parameters of this class.
*
*
* @author Christian W. Damus (cdamus)
*/
public abstract class AbstractEnvironmentFactory
implements EnvironmentFactory,
Adaptable {
private boolean traceEvaluation;
/**
* Initializes me.
*/
protected AbstractEnvironmentFactory() {
super();
}
/**
* Creates an environment for the specified package context.
*
* @param parent the parent environment of the environment to be created
* @param context the package context (must not be null
)
* @return the new nested environment
*/
protected Environment
createPackageContext(
Environment parent,
PK context) {
Environment result =
createEnvironment(parent);
if (result instanceof AbstractEnvironment, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?>) {
((AbstractEnvironment) result)
.setContextPackage(context);
}
return result;
}
// implements the interface method
public Environment
createPackageContext(
Environment parent,
List pathname) {
PK contextPackage = lookupPackage(pathname);
return (contextPackage == null)? null : createPackageContext(parent, contextPackage);
}
/**
* Looks up the package identified by the specified qualified name by
* whatever means is appropriate to the particular environment implementation.
*
* @param pathname the qualified name of the package to find
* @return the matching package, or null
if none is found
*/
protected abstract PK lookupPackage(List pathname);
// implements the interface method
public Environment
createClassifierContext(
Environment parent,
C context) {
Environment result =
createEnvironment(parent);
// in case it corresponds to an OCL primitive type
UMLReflection uml = parent.getUMLReflection();
context = uml.asOCLType(context);
Variable self = parent.getOCLFactory().createVariable();
uml.setName(self, Environment.SELF_VARIABLE_NAME);
uml.setType(self, context);
result.addElement(self.getName(), self, true);
result.setSelfVariable(self);
return result;
}
// implements the interface method
public Environment
createInstanceContext(
Environment parent,
Object context) {
return createClassifierContext(parent, getClassifier(context));
}
// implements the interface method
public Environment
createOperationContext(
Environment parent,
O operation) {
Environment result =
createEnvironment(parent);
if (result instanceof AbstractEnvironment, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?>) {
((AbstractEnvironment) result)
.setContextOperation(operation);
}
UMLReflection uml = parent.getUMLReflection();
OCLFactory oclFactory = parent.getOCLFactory();
for (PM next : parent.getUMLReflection().getParameters(operation)) {
// ensure that we use the OCL primitive types wherever possible
Variable var = oclFactory.createVariable();
uml.setName(var, uml.getName(next));
uml.setType(var, TypeUtil.resolveType(result, uml.getOCLType(next)));
var.setRepresentedParameter(next);
result.addElement(var.getName(), var, true);
}
return result;
}
// implements the interface method
public Environment
createAttributeContext(
Environment parent,
P property) {
Environment result =
createEnvironment(parent);
if (result instanceof AbstractEnvironment, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?>) {
((AbstractEnvironment) result)
.setContextProperty(property);
}
return result;
}
// implements the interface method
public EvaluationVisitor createEvaluationVisitor(
Environment env,
EvaluationEnvironment evalEnv,
Map extends CLS, ? extends Set extends E>> extentMap) {
EvaluationVisitor result =
new EvaluationVisitorImpl(
env, evalEnv, extentMap);
if (isEvaluationTracingEnabled()) {
// decorate the evaluation visitor with tracing support
result = new TracingEvaluationVisitor(
result);
}
return result;
}
/**
* @since 3.1
*/
public OCLAnalyzer createOCLAnalyzer(
Environment env, String input) {
return new OCLAnalyzer(env, input);
}
/**
* @since 3.1
*/
public OCLAnalyzer createOCLAnalyzer(
AbstractOCLParser parser) {
return new OCLAnalyzer(parser);
}
/**
* @since 3.1
*/
public OCLFactoryWithHistory createOCLFactoryWithHistory(
Environment env) {
return new OCLFactoryWithHistory(env.getOCLFactory());
}
/**
* @since 3.1
*/
public OCLSyntaxHelper createOCLSyntaxHelper(
Environment env) {
return new org.eclipse.ocl.internal.helper.OCLSyntaxHelper(env);
}
/**
* @since 3.1
*/
public Visitor createValidationVisitor(
Environment env) {
return new ValidationVisitor(env);
}
/**
* Obtains client metamodel's classifier for the specified
* context
object, which may be an instance of a classifier
* in the user model or may actually be a classifier in the user model.
*
* @param context a context object or classifier
* @return the user model's classifier for this context object, or the
* context itself if it is a classifier
*/
protected abstract C getClassifier(Object context);
/**
* Queries whether tracing of evaluation is enabled. Tracing
* logs the progress of evaluation to the console, which may
* be of use in diagnosing problems.
*
* In an Eclipse environment, tracing is also enabled by turning on the
* org.eclipse.ocl/debug/evaluation debug option.
*
*
* @return whether evaluation tracing is enabled
*
* @see #setEvaluationTracingEnabled(boolean)
*/
protected boolean isEvaluationTracingEnabled() {
return traceEvaluation;
}
/**
* Sets whether tracing of evaluation is enabled. Tracing logs
* the progress of parsing to the console, which may be of use in diagnosing
* problems.
*
* In an Eclipse environment, tracing is also enabled by turning on the
* org.eclipse.ocl/debug/evaluation debug option.
*
*
* param b whether evaluation tracing is enabled
*
* @see #isEvaluationTracingEnabled()
*/
protected void setEvaluationTracingEnabled(boolean b) {
traceEvaluation = b;
}
/**
* The abstract environment factory implementation is adaptable. The
* default implementation adapts to and interface actually implemented by
* the receiver.
*
* Subclasses may override or extend this implementation.
*
*
* @since 1.2
*/
@SuppressWarnings("unchecked")
public T getAdapter(Class adapterType) {
T result;
if (adapterType.isAssignableFrom(getClass())) {
result = (T) this;
} else {
result = null;
}
return result;
}
}