/*
* Copyright (C) 2008-2011 by Claas Wilke (claas.wilke@tu-dresden.de)
*
* This file is part of the OCL2Java Code Generator of Dresden OCL.
*
* Dresden OCL is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* Dresden OCL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with Dresden OCL. If not, see <http://www.gnu.org/licenses/>.
*/
package org.dresdenocl.tools.codegen.ocl2java.internal;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.EObject;
import org.osgi.framework.Bundle;
import org.dresdenocl.essentialocl.EssentialOclPlugin;
import org.dresdenocl.essentialocl.expressions.BooleanLiteralExp;
import org.dresdenocl.essentialocl.expressions.CollectionItem;
import org.dresdenocl.essentialocl.expressions.CollectionLiteralExp;
import org.dresdenocl.essentialocl.expressions.CollectionLiteralPart;
import org.dresdenocl.essentialocl.expressions.CollectionRange;
import org.dresdenocl.essentialocl.expressions.EnumLiteralExp;
import org.dresdenocl.essentialocl.expressions.ExpressionInOcl;
import org.dresdenocl.essentialocl.expressions.IfExp;
import org.dresdenocl.essentialocl.expressions.IntegerLiteralExp;
import org.dresdenocl.essentialocl.expressions.InvalidLiteralExp;
import org.dresdenocl.essentialocl.expressions.IterateExp;
import org.dresdenocl.essentialocl.expressions.IteratorExp;
import org.dresdenocl.essentialocl.expressions.LetExp;
import org.dresdenocl.essentialocl.expressions.OclExpression;
import org.dresdenocl.essentialocl.expressions.OperationCallExp;
import org.dresdenocl.essentialocl.expressions.PropertyCallExp;
import org.dresdenocl.essentialocl.expressions.RealLiteralExp;
import org.dresdenocl.essentialocl.expressions.StringLiteralExp;
import org.dresdenocl.essentialocl.expressions.TupleLiteralExp;
import org.dresdenocl.essentialocl.expressions.TupleLiteralPart;
import org.dresdenocl.essentialocl.expressions.TypeLiteralExp;
import org.dresdenocl.essentialocl.expressions.UndefinedLiteralExp;
import org.dresdenocl.essentialocl.expressions.UnlimitedNaturalExp;
import org.dresdenocl.essentialocl.expressions.Variable;
import org.dresdenocl.essentialocl.expressions.VariableExp;
import org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch;
import org.dresdenocl.essentialocl.types.AnyType;
import org.dresdenocl.essentialocl.types.BagType;
import org.dresdenocl.essentialocl.types.CollectionType;
import org.dresdenocl.essentialocl.types.InvalidType;
import org.dresdenocl.essentialocl.types.OclLibrary;
import org.dresdenocl.essentialocl.types.OrderedSetType;
import org.dresdenocl.essentialocl.types.SequenceType;
import org.dresdenocl.essentialocl.types.SetType;
import org.dresdenocl.essentialocl.types.TupleType;
import org.dresdenocl.essentialocl.types.TypeType;
import org.dresdenocl.essentialocl.types.VoidType;
import org.dresdenocl.model.IModel;
import org.dresdenocl.model.ModelConstants;
import org.dresdenocl.pivotmodel.Constraint;
import org.dresdenocl.pivotmodel.Enumeration;
import org.dresdenocl.pivotmodel.EnumerationLiteral;
import org.dresdenocl.pivotmodel.Expression;
import org.dresdenocl.pivotmodel.Feature;
import org.dresdenocl.pivotmodel.NamedElement;
import org.dresdenocl.pivotmodel.Operation;
import org.dresdenocl.pivotmodel.Parameter;
import org.dresdenocl.pivotmodel.PrimitiveType;
import org.dresdenocl.pivotmodel.PrimitiveTypeKind;
import org.dresdenocl.pivotmodel.Property;
import org.dresdenocl.pivotmodel.Type;
import org.dresdenocl.tools.codegen.code.ITransformedCode;
import org.dresdenocl.tools.codegen.code.ITransformedType;
import org.dresdenocl.tools.codegen.code.impl.TransformedCodeImpl;
import org.dresdenocl.tools.codegen.code.impl.TransformedTypeImpl;
import org.dresdenocl.tools.codegen.exception.Ocl2CodeException;
import org.dresdenocl.tools.codegen.ocl2java.IOcl2Java;
import org.dresdenocl.tools.codegen.ocl2java.IOcl2JavaSettings;
import org.dresdenocl.tools.codegen.ocl2java.Ocl2JavaPlugin;
import org.dresdenocl.tools.codegen.ocl2java.code.IOcl2JavaEnvironment;
import org.dresdenocl.tools.codegen.ocl2java.code.impl.Ocl2JavaEnvironment;
import org.dresdenocl.tools.template.ITemplate;
import org.dresdenocl.tools.template.ITemplateGroup;
import org.dresdenocl.tools.template.TemplatePlugin;
import org.dresdenocl.tools.template.exception.TemplateException;
/**
* <p>
* This class provides the logic to transform java code from given
* {@link Constraint}s.
* </p>
*
* @author Claas Wilke
*/
public class Ocl2Java extends ExpressionsSwitch<ITransformedCode> implements
IOcl2Java {
/** The {@link Logger} for this class. */
private static final Logger LOGGER = Logger.getLogger(Ocl2Java.class);
/** The paths of the String templates for the code transformation. */
private final static String TEMPLATE_PATH = "/resources/template/java/";
private final static String EXPRESSION_TEMPLATE_FILE = "expressions.stg";
private final static String JAVA_TEMPLATE_FILE = "java.stg";
private final static String INSTRUMENTATION_TEMPLATE_FILE = "instrumentations.stg";
private final static String OPERATION_TEMPLATE_FILE = "operations.stg";
private final static String TYPE_TEMPLATE_FILE = "types.stg";
/**
* Contains operation names that must be renamed to support them in
* languages like Java. E.g., '=' ist renamed to equals.
*/
private static Map<String, String> renamedOperationNames = new HashMap<String, String>();
/* static initialization. */
static {
renamedOperationNames.put("=", "equals");
renamedOperationNames.put("<>", "notEquals");
renamedOperationNames.put("+", "plus");
renamedOperationNames.put("-", "minus");
renamedOperationNames.put("*", "multiply");
renamedOperationNames.put("/", "division");
renamedOperationNames.put("<", "lesser");
renamedOperationNames.put(">", "greater");
renamedOperationNames.put("<=", "lesserEquals");
renamedOperationNames.put(">=", "greaterEquals");
}
/** Cache used to improve speed of {@link Type} transformation. */
protected Map<Type, ITransformedType> cachedTransformedTypes = new WeakHashMap<Type, ITransformedType>();
/**
* The environment to provide and store some values during code
* transformation.
*/
protected IOcl2JavaEnvironment environment;
/** The Settings used during code generation. */
protected IOcl2JavaSettings settings;
/**
* The engine to provide all {@link ITemplate}s used for code
* transformation.
*/
protected ITemplateGroup templateGroup;
/**
* <p>
* Creates a new {@link Ocl2Java} instance.
* </p>
*
* @throws Ocl2CodeException
* If the initialization fails.
*/
public Ocl2Java() throws Ocl2CodeException {
this.init();
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.ocl2java.IOcl2Code#getSettings()
*/
public IOcl2JavaSettings getSettings() {
return this.settings;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.ocl2java.IOcl22Code#resetEnvironment()
*/
public void resetEnvironment() {
this.environment = new Ocl2JavaEnvironment();
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.tools.codegen.IOcl2Code#setSettings(org.dresdenocl
* .pivot.tools.codegen.IOcl2CodeSettings)
*/
public void setSettings(IOcl2JavaSettings settings) {
this.settings = settings;
/* Clear the cache to avoid side effects. */
this.cachedTransformedTypes.clear();
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.ocl2java.IOcl2Code#transformFragmentCode(java.util
* .List)
*/
public List<String> transformFragmentCode(List<Constraint> constraints)
throws Ocl2CodeException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformFragmentCode(List<Constraint>) - start");
}
// no else.
List<String> result = new ArrayList<String>(constraints.size());
for (Constraint aConstraint : constraints) {
this.environment.resetEnvironmentForNextConstraint();
ITransformedCode aTransformedConstraint = this
.transformFragmentCode(aConstraint);
String aResult = aTransformedConstraint.getCode();
if (aResult.length() > 0) {
aResult += "\n";
}
// no else.
aResult += aTransformedConstraint.getResultExp();
result.add(aResult);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformFragmentCode(List<Constraint>)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.ocl2java.IOcl2Code#transformInstrumentationCode
* (java.util.List)
*/
public List<String> transformInstrumentationCode(
List<Constraint> constraints) throws Ocl2CodeException {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformInstrumentationCode"
+ "(List<Constraint>) - start");
}
// no else.
List<String> result = new ArrayList<String>(constraints.size());
/* Iterate through all constraints and compute their code. */
for (Constraint aConstraint : constraints) {
this.environment.resetEnvironmentForNextConstraint();
result.add(this.transformInstrumentationCode(aConstraint));
}
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformInstrumentationCode"
+ "(List<Constraint>) - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseBooleanLiteralExp
* (org.dresdenocl.essentialocl.expressions.BooleanLiteralExp)
*/
public ITransformedCode caseBooleanLiteralExp(
BooleanLiteralExp aBooleanLiteralExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseBooleanLiteralExp(BooleanLiteralExp) - start");
}
// no else.
ITemplate template = this.templateGroup.getTemplate("literalExp");
template.setAttribute("type",
this.transformType(aBooleanLiteralExp.getType()).toString());
template.setAttribute("value", aBooleanLiteralExp.isBooleanSymbol());
ITransformedCode result = new TransformedCodeImpl();
result.setResultExp(template.toString());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseBooleanLiteralExp(BooleanLiteralExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseCollectionLiteralExp
* (org.dresdenocl.essentialocl.expressions.CollectionLiteralExp)
*/
public ITransformedCode caseCollectionLiteralExp(
CollectionLiteralExp aCollectionLiteralExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseCollectionLiteralExp(CollectionLiteralExp) - start");
}
// no else.
ITransformedCode result = new TransformedCodeImpl();
/* Compute the result type first. */
ITransformedType resultType = this
.transformInitializableType(aCollectionLiteralExp.getType());
String collectionName = this.environment.getNewCollectionVarName();
/* Prepare the template for the collection expression. */
ITemplate template = this.templateGroup
.getTemplate("collectionLiteralExp");
template.setAttribute("collectionName", collectionName);
template.setAttribute("collectionType", resultType.toString());
this.environment
.pushExpectedReturnType(((CollectionType) aCollectionLiteralExp
.getType()).getElementType());
/* Transform Code for all initial elements. */
for (CollectionLiteralPart aCollectionPart : aCollectionLiteralExp
.getPart()) {
/* Transform initial Code for all CollectionItems. */
if (aCollectionPart instanceof CollectionItem) {
CollectionItem anItem = (CollectionItem) aCollectionPart;
ITransformedCode anItemsCode = this.doSwitch(anItem.getItem());
/* Transform code for element expression. */
ITemplate elemTemplate = this.templateGroup
.getTemplate("collectionLiteralExp_collectionItem");
elemTemplate.setAttribute("collectionName", collectionName);
elemTemplate
.setAttribute("itemExp", anItemsCode.getResultExp());
/* Add element code to collection code. */
template.setAttribute("elementCodes", anItemsCode.getCode());
template.setAttribute("elementExps", elemTemplate.toString());
}
/* Collection can also be initialized using a for-loop. */
else if (aCollectionPart instanceof CollectionRange) {
CollectionRange aRange = (CollectionRange) aCollectionPart;
ITransformedCode firstExpCode = this
.doSwitch(aRange.getFirst());
ITransformedType firstExpType = this.transformType(aRange
.getFirst().getType());
ITransformedCode lastExpCode = this.doSwitch(aRange.getLast());
String elementCode = firstExpCode.getCode();
if (elementCode.length() > 0) {
elementCode += "\n";
}
// no else.
elementCode = lastExpCode.getCode();
ITemplate elemTemplate = this.templateGroup
.getTemplate("collectionLiteralExp_collectionRange");
elemTemplate.setAttribute("collectionName", collectionName);
elemTemplate.setAttribute("indexVar",
this.environment.getNewIndexVarName());
elemTemplate.setAttribute("indexType", firstExpType.toString());
elemTemplate.setAttribute("firstExp",
firstExpCode.getResultExp());
elemTemplate
.setAttribute("lastExp", lastExpCode.getResultExp());
/* Add element code to collection code. */
template.setAttribute("elementCodes", elementCode);
template.setAttribute("elementExps", elemTemplate.toString());
}
}
// end for.
this.environment.popExpectedReturnType();
result.addCode(template.toString());
result.setResultExp(collectionName);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseCollectionLiteralExp(CollectionLiteralExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseEnumLiteralExp
* (org.dresdenocl.essentialocl.expressions.EnumLiteralExp)
*/
public ITransformedCode caseEnumLiteralExp(EnumLiteralExp anEnumLiteralExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseEnumLiteralExp(EnumLiteralExp) - start");
}
// no else.
ITransformedCode result = new TransformedCodeImpl();
EnumerationLiteral anEnumerationLiteral = anEnumLiteralExp
.getReferredEnumLiteral();
anEnumerationLiteral.getEnumeration();
Enumeration anEnumeration = anEnumerationLiteral.getEnumeration();
/* Use a canonical name for the enumeration name. */
String enumerationName = anEnumeration.getQualifiedName();
enumerationName = enumerationName.replaceAll("::", ".");
/* Probably remove the root package. */
if (enumerationName.startsWith(ModelConstants.ROOT_PACKAGE_NAME)) {
enumerationName = enumerationName.substring(5);
}
// no else.
/* Probably add some extra packages. */
if (this.settings.getBasisPackage() != null
&& this.settings.getBasisPackage().length() > 0)
enumerationName = this.settings.getBasisPackage() + "."
+ enumerationName;
// no else.
ITemplate template = this.templateGroup.getTemplate("enumLiteralExp");
template.setAttribute("enumerationName", enumerationName);
template.setAttribute("literalName", anEnumerationLiteral.getName());
result.setResultExp(template.toString());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseEnumLiteralExp(EnumLiteralExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseExpressionInOcl
* (org.dresdenocl.essentialocl.expressions.ExpressionInOcl)
*/
public ITransformedCode caseExpressionInOcl(
ExpressionInOcl anExpressionInOcl) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseExpressionInOcl(ExpressionInOcl) - start");
}
// no else.
/* Transform bodyCode. */
ITransformedCode result = this.doSwitch(anExpressionInOcl
.getBodyExpression());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseExpressionInOcl(ExpressionInOcl)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseIfExp(org.dresdenocl.essentialocl.expressions.IfExp)
*/
public ITransformedCode caseIfExp(IfExp anIfExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseIfExp(IfExp) - start");
}
// no else.
ITransformedCode result = new TransformedCodeImpl();
/* Transform ifExp, thenExp and elseExp. */
ITransformedCode ifCode = doSwitch(anIfExp.getCondition());
ITransformedCode thenCode = doSwitch(anIfExp.getThenExpression());
ITransformedCode elseCode = doSwitch(anIfExp.getElseExpression());
/* Declare variable for result of if-then-else expression. */
String resultVarName = this.environment.getNewIfExpResultName();
result.setResultExp(resultVarName);
ITransformedType resultType = this.transformType(anIfExp.getType());
/* Transform ifExp. */
ITemplate template = this.templateGroup.getTemplate("ifExp");
template.setAttribute("ifCode", ifCode.getCode());
template.setAttribute("ifExp", ifCode.getResultExp());
template.setAttribute("thenCode", thenCode.getCode());
template.setAttribute("thenExp", thenCode.getResultExp());
template.setAttribute("elseCode", elseCode.getCode());
template.setAttribute("elseExp", elseCode.getResultExp());
template.setAttribute("resultVar", resultVarName);
template.setAttribute("resultType", resultType.toString());
result.addCode(template.toString());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseIfExp(IfExp)" + " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseIntegerLiteralExp
* (org.dresdenocl.essentialocl.expressions.IntegerLiteralExp)
*/
public ITransformedCode caseIntegerLiteralExp(
IntegerLiteralExp anIntegerLiteralExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseIntegerLiteralExp(IntegerLiteralExp) - start");
}
// no else.
ITemplate template = this.templateGroup.getTemplate("literalExp");
template.setAttribute("type",
this.transformType(anIntegerLiteralExp.getType()).toString());
template.setAttribute("value", anIntegerLiteralExp.getIntegerSymbol());
ITransformedCode result = new TransformedCodeImpl();
result.setResultExp(template.toString());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseIntegerLiteralExp(IntegerLiteralExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseInvalidLiteralExp
* (org.dresdenocl.essentialocl.expressions.InvalidLiteralExp)
*/
public ITransformedCode caseInvalidLiteralExp(
InvalidLiteralExp anInvalidLiteralExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseInvalidLiteralExp(InvalidLiteralExp) - start");
}
// no else.
ITemplate template = this.templateGroup
.getTemplate("invalidLiteralExp");
if (this.environment.getExpectedReturnType() != null)
template.setAttribute(
"resultType",
this.transformType(this.environment.getExpectedReturnType())
.toString());
// no else.
ITransformedCode result = new TransformedCodeImpl();
result.setResultExp(template.toString());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseInvalidLiteralExp(InvalidLiteralExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseIterateExp (org.dresdenocl.essentialocl.expressions.IterateExp)
*/
public ITransformedCode caseIterateExp(IterateExp anIterateExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseIterateExp(IterateExp) - start");
}
// no else.
ITransformedType resultType = this
.transformType(anIterateExp.getType());
ITransformedCode sourceCode = this.doSwitch(anIterateExp.getSource());
ITransformedType sourceType = this.transformType(anIterateExp
.getSource().getType());
OclExpression bodyExp = anIterateExp.getBody();
/* TODO Find a solution without modifying the ASM. */
/*
* Get the first iterator variable (probaly further exist during
* recursive calls).
*/
Variable iterateVariable = anIterateExp.getIterator().remove(0);
String iterateVarName = iterateVariable.getName();
String resultVarName = anIterateExp.getResult().getName();
this.environment.addVariableMapping(iterateVarName,
this.environment.getNewIteratorVarName());
this.environment.addVariableMapping(resultVarName,
this.environment.getNewResultVarName());
/*
* If the Expression has more than one iterator variable. Create an
* inner IterateExp without the first iterator variable.
*/
if (anIterateExp.getIterator().size() > 0) {
/* the first iterator has been already removed. */
bodyExp = (OclExpression) anIterateExp;
/*
* The Expression will be transformed inside the transformation of
* the first iterator Variable later on.
*/
}
/* Begin with code transformation. */
this.environment.pushExpectedReturnType(anIterateExp.getType());
ITransformedCode bodyCode = this.doSwitch(bodyExp);
this.environment.popExpectedReturnType();
/* TODO Find a solution without modifying the ASM (part 2). */
/* Add the iterator Variable to the IterateExp again. */
anIterateExp.getIterator().add(0, iterateVariable);
ITemplate template = this.templateGroup.getTemplate("iterateExp");
template.setAttribute("sourceCode", sourceCode.getCode());
template.setAttribute("sourceExp", sourceCode.getResultExp());
template.setAttribute("itVar",
this.environment.getVariableMapping(iterateVarName));
template.setAttribute("bodyCode", bodyCode.getCode());
template.setAttribute("bodyExp", bodyCode.getResultExp());
ITransformedCode resultVarInitCode = this.doSwitch(anIterateExp
.getResult().getInitExpression());
template.setAttribute("resultVarInitCode", resultVarInitCode.getCode());
template.setAttribute("resultVarInitExp",
resultVarInitCode.getResultExp());
template.setAttribute("resultVar",
this.environment.getVariableMapping(resultVarName));
template.setAttribute("resultType", resultType.toString());
template.setAttribute("sourceGenericType", sourceType.getGenericType()
.toString());
ITransformedCode result = new TransformedCodeImpl();
result.addCode(template.toString());
result.setResultExp(this.environment.getVariableMapping(resultVarName));
this.environment.removeVariableMapping(iterateVarName);
this.environment.removeVariableMapping(resultVarName);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseIterateExp(IterateExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseIteratorExp (org.dresdenocl.essentialocl.expressions.IteratorExp)
*/
public ITransformedCode caseIteratorExp(IteratorExp anIteratorExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseIteratorExp(IteratorExp) - start");
}
// no else.
ITransformedCode result = new TransformedCodeImpl();
ITransformedType resultType = this
.transformInitializableType(anIteratorExp.getType());
/* Get the name of the iterator */
String itName = anIteratorExp.getName();
/* Get unique name iterateResultName and iterateVarName. */
String resultVarName = this.environment.getNewResultVarName();
/* Transform code for source of the iteratorExp. */
ITransformedCode sourceCode = this.doSwitch(anIteratorExp.getSource());
ITransformedType sourceType = this.transformType(anIteratorExp
.getSource().getType());
/* TODO Find a solution without modifying the ASM (Part 1). */
/* Get the first iterator variable. */
Variable itVariable = anIteratorExp.getIterator().remove(0);
String itVarName = itVariable.getName();
this.environment.addVariableMapping(itVarName,
this.environment.getNewIteratorVarName());
OclExpression bodyExp = anIteratorExp.getBody();
/*
* If the Expression has more than one iterator variable. Create an
* inner IterateExp without the first Iterator Variable.
*/
if (anIteratorExp.getIterator().size() > 0) {
/* the first iterator has been already removed. */
bodyExp = anIteratorExp;
/*
* The Expression will be transformed inside the transformation of
* the first iterator Variable later on.
*/
}
// no else.
/* Transform code for bodyExp of the iteratorExp. */
ITransformedCode bodyCode = this.doSwitch(bodyExp);
ITransformedType bodyType = this.transformType(bodyExp.getType());
/* Needed for iterators of type 'sortedBy'. */
ITransformedCode bodyCode2 = null;
String itVarName2 = null;
/*
* For the iterator sorted by, create a second body expression with a
* different iterator variable.
*/
if (itName.equals("sortedBy")) {
/*
* This is required because the code has to contain two different
* variables.
*/
itVarName2 = this.environment.getNewIteratorVarName();
this.environment.addVariableMapping(itVariable.getName(),
itVarName2);
bodyCode2 = this.doSwitch(bodyExp);
this.environment.removeVariableMapping(itVariable.getName());
}
/* TODO Find a solution without modifying the ASM (Part 2). */
/* Add the iterator Variable to the model again. */
anIteratorExp.getIterator().add(0, itVariable);
/* Begin code transformation of IteratorExp. */
ITemplate template = this.templateGroup.getTemplate("iteratorExp_"
+ itName);
if (itName.equals("any") || itName.equals("exists")
|| itName.equals("forAll") || itName.equals("one")) {
/* Set iterator specific template attributes. */
template.setAttribute("itType", sourceType.getGenericType()
.toString());
}
else if (itName.equals("isUnique")) {
/* Set iterator specific template attributes. */
template.setAttribute("itType", sourceType.getGenericType()
.toString());
template.setAttribute("bodyExpType", bodyType.toString());
template.setAttribute("collectionVar",
this.environment.getNewCollectionVarName());
}
else if (itName.equals("closure")) {
/*
* Decide whether body returns a collection ore only one result
* element.
*/
if (bodyExp.getType().conformsTo(
anIteratorExp.getSource().getType())) {
template.setAttribute("bodyResultsInCollection", "true");
}
// no else.
/* Set iterator specific template attributes. */
template.setAttribute("itType", sourceType.getGenericType()
.toString());
template.setAttribute("resultType", resultType.toString());
template.setAttribute("bodyResultType", bodyType.toString());
template.setAttribute("bodyResultVar",
this.environment.getNewBodyResultVarName());
template.setAttribute("toVisitVar",
this.environment.getNewToVisitVarName());
}
else if (itName.equals("collect")) {
String addOp;
/*
* Collect does not add collections to collections, thus the add
* operation must be computed.
*/
if (bodyType.isGenericType()) {
addOp = this.templateGroup.getTemplate("addAllOperationName")
.toString();
} else {
addOp = this.templateGroup.getTemplate("addOperationName")
.toString();
}
/* Set iterator specific template attributes. */
template.setAttribute("itType", sourceType.getGenericType()
.toString());
template.setAttribute("resultType", resultType.toString());
template.setAttribute("addOp", addOp);
}
else if (itName.equals("collectNested") || itName.equals("reject")
|| itName.equals("select")) {
/* Set iterator specific template attributes. */
template.setAttribute("itType", sourceType.getGenericType()
.toString());
template.setAttribute("resultType", resultType.toString());
}
else if (itName.equals("sortedBy")) {
/* Set iterator specific template attributes. */
template.setAttribute("itType", sourceType.getGenericType()
.toString());
template.setAttribute("comparatorName",
this.environment.getNewComparatorName());
template.setAttribute("compareResult",
this.environment.getNewResultVarName());
template.setAttribute("resultType", resultType.toString());
template.setAttribute("itVar2", itVarName2);
template.setAttribute("bodyCode2", bodyCode2.getCode());
template.setAttribute("bodyExp2", bodyCode2.getResultExp());
}
/* Set template attributes which are needed for all iterators. */
template.setAttribute("sourceCode", sourceCode.getCode());
template.setAttribute("sourceExp", sourceCode.getResultExp());
template.setAttribute("itVar",
this.environment.getVariableMapping(itVarName));
template.setAttribute("bodyCode", bodyCode.getCode());
template.setAttribute("bodyExp", bodyCode.getResultExp());
template.setAttribute("resultVar", resultVarName);
result.addCode(template.toString());
result.setResultExp(resultVarName);
this.environment.removeVariableMapping(itVarName);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseIteratorExp(IteratorExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseLetExp(org.dresdenocl.essentialocl.expressions.LetExp)
*/
public ITransformedCode caseLetExp(LetExp aLetExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseLetExp(LetExp) - start");
}
// no else.
Variable aVar = aLetExp.getVariable();
Type aVarsType = aVar.getType();
OclExpression initExp = aVar.getInitExpression();
OclExpression inExp = aLetExp.getIn();
/* Generate the code for the inExp. */
ITransformedCode inCode = doSwitch(inExp);
ITemplate template = this.templateGroup.getTemplate("letExp");
template.setAttribute("varType", this.transformType(aVarsType)
.toString());
String varName = aVar.getName();
if (this.environment.existsMappingForVariable(varName))
varName = this.environment.getVariableMapping(varName);
// no else.
template.setAttribute("varName", varName);
template.setAttribute("inCode", inCode.getCode());
/* Generate the code for the initExp. */
if (initExp != null) {
this.environment.pushExpectedReturnType(aLetExp.getVariable()
.getType());
ITransformedCode initCode = doSwitch(initExp);
this.environment.popExpectedReturnType();
template.setAttribute("initCode", initCode.getCode());
template.setAttribute("initExp", initCode.getResultExp());
}
// no else.
ITransformedCode result = new TransformedCodeImpl();
result.addCode(template.toString());
result.setResultExp(inCode.getResultExp());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseLetExp(LetExp) - end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Generates the code for a binary {@link Operation} of an
* {@link OperationCallExp}.
* </p>
*
* @param anOperationCallExp
* The {@link OperationCallExp} the code shall be transformed
* for.
* @param anOperation
* The {@link Operation} which shall be transformed.
* @return The {@link ITransformedCode} for the {@link Operation} which
* shall be transformed.
*/
public ITransformedCode caseOperationCallExp(
OperationCallExp anOperationCallExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseOperationCallExp(OperationCallExp) - start");
}
// no else.
ITransformedCode result = new TransformedCodeImpl();
/* Transform Code for the source of the operation call. */
OclExpression sourceExp = anOperationCallExp.getSource();
Operation referredOperation = anOperationCallExp.getReferredOperation();
List<Type> parameterTypes = new ArrayList<Type>();
/* Operation can be null (@pre Operation). */
if (referredOperation != null) {
for (Parameter parameter : referredOperation.getInputParameter()) {
parameterTypes.add(parameter.getType());
}
// end for.
}
// no else.
OclLibrary oclLibrary = EssentialOclPlugin.getOclLibraryProvider()
.getOclLibrary();
/* Compute the source expression. */
Type sourceType = sourceExp.getType();
ITransformedCode sourceCode;
/*
* Especially handle static operations since type literals are hard to
* handle in Java.
*/
if (referredOperation != null && referredOperation.isStatic()
&& sourceExp instanceof TypeLiteralExp) {
sourceCode = new TransformedCodeImpl();
sourceCode.setResultExp(this.transformType(
((TypeLiteralExp) sourceExp).getReferredType())
.getTypeName());
}
else {
if (referredOperation != null)
this.environment.pushExpectedReturnType(referredOperation
.getOwningType());
// no else.
sourceCode = this.doSwitch(sourceExp);
if (referredOperation != null)
this.environment.popExpectedReturnType();
// no else.
}
// end else.
result.addCode(sourceCode.getCode());
String operationName;
/* Get the operation name and handle the special case @pre. */
if (anOperationCallExp.getName().equals("atPre")) {
operationName = "atPre";
}
else {
operationName = anOperationCallExp.getReferredOperation().getName();
}
String resultExp = null;
ITemplate template = null;
/*
* Search for the template of the operation. Start with concrete types
* and continue with more and more abstract types.
*/
if (sourceType != null) {
/* Special treatement of atPre operation. */
if (operationName.equals("atPre")) {
/* The variable is initialized later during instrumentation. */
String atPreVar = this.environment.addAtPreValue(sourceCode,
sourceType);
resultExp = atPreVar;
}
// no else.
/* Operations on BagType. */
if (template == null && sourceType instanceof BagType) {
/*
* Do not use the source type here. Otherwise the operation
* check will fail.
*/
BagType bagType = oclLibrary.getBagType(oclLibrary.getOclAny());
/*
* Check if the given operation is defined and probably load its
* template.
*/
Operation operation = bagType.lookupOperation(operationName,
parameterTypes);
if (operation != null
&& operation.getOwningType().equals(bagType)) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames
.get(operationName);
}
// no else.
template = this.templateGroup.getTemplate(operationName
+ "OperationOnBag");
}
// no else.
}
// no else.
/* Operations on OrderedSetType. */
if (template == null && sourceType instanceof OrderedSetType) {
/*
* Do not use the source type here. Otherwise the operation
* check will fail.
*/
OrderedSetType orderedSetType = oclLibrary
.getOrderedSetType(oclLibrary.getOclAny());
/*
* Check if the given operation is defined and probably load its
* template.
*/
Operation operation = orderedSetType.lookupOperation(
operationName, parameterTypes);
if (operation != null
&& operation.getOwningType().equals(orderedSetType)) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames
.get(operationName);
}
// no else.
template = this.templateGroup.getTemplate(operationName
+ "OperationOnOrderedSet");
}
// no else.
}
// no else.
/* Operations on SequenceType. */
if (template == null && sourceType instanceof SequenceType) {
/*
* Do not use the source type here. Otherwise the operation
* check will fail.
*/
SequenceType sequenceType = oclLibrary
.getSequenceType(oclLibrary.getOclAny());
/*
* Check if the given operation is defined and probably load its
* template.
*/
Operation operation = sequenceType.lookupOperation(
operationName, parameterTypes);
if (operation != null
&& operation.getOwningType().equals(sequenceType)) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames
.get(operationName);
}
// no else.
template = this.templateGroup.getTemplate(operationName
+ "OperationOnSequence");
}
// no else.
}
// no else.
/* Operations on SetType. */
if (template == null && sourceType instanceof SetType) {
/* Especially handle the union operation. */
if (operationName.equals("union")) {
if (parameterTypes.size() == 1
&& parameterTypes.get(0) instanceof BagType) {
template = this.templateGroup
.getTemplate("unionOperationWithBagOnSet");
}
else if (parameterTypes.size() == 1
&& parameterTypes.get(0) instanceof SetType) {
template = this.templateGroup
.getTemplate("unionOperationWithSetOnSet");
}
}
// no else.
if (template == null) {
/*
* Do not use the source type here. Otherwise the operation
* check will fail.
*/
SetType setType = oclLibrary.getSetType(oclLibrary
.getOclAny());
/*
* Check if the given operation is defined and probably load
* its template.
*/
Operation operation;
operation = setType.lookupOperation(operationName,
parameterTypes);
if (operation != null
&& operation.getOwningType().equals(setType)) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames
.get(operationName);
}
// no else.
template = this.templateGroup.getTemplate(operationName
+ "OperationOnSet");
}
// no else.
}
// no else.
}
// no else.
/* Operations on CollectionType. */
if (template == null && sourceType instanceof CollectionType) {
/*
* Do not use the source type here. Otherwise the operation
* check will fail.
*/
CollectionType collectionType = oclLibrary
.getCollectionType(oclLibrary.getOclAny());
/*
* Check if the given operation is defined and probably load its
* template.
*/
Operation operation = collectionType.lookupOperation(
operationName, parameterTypes);
if (operation != null
&& operation.getOwningType().equals(collectionType)) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames
.get(operationName);
}
// no else.
template = this.templateGroup.getTemplate(operationName
+ "OperationOnCollection");
}
// no else.
/*
* Sum operation requires special argument because result must
* be cast to result type.
*/
if (template != null && operationName.equals("sum")) {
String resultType;
resultType = this.transformType(
anOperationCallExp.getType()).toString();
template.setAttribute("resultType", resultType);
/*
* Set additional parameter to convert from number to result
* type.
*/
template.setAttribute("typeConversion", this.templateGroup
.getTemplate("numberConversionTo" + resultType)
.toString());
}
// no else.
}
// no else (OclCollection).
/*
* Flatten operation requires special argument because result must
* be cast to result type.
*/
if (template != null && operationName.equals("flatten")) {
template.setAttribute("resultType",
this.transformType(anOperationCallExp.getType())
.toString());
}
// no else.
/* Operations on OclBoolean. */
if (template == null
&& referredOperation != null
&& referredOperation.getOwner() != null
&& referredOperation.getOwner().equals(
oclLibrary.getOclBoolean())) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames.get(operationName);
}
// no else.
template = this.templateGroup.getTemplate(operationName
+ "OperationOnBoolean");
}
// no else (OclBoolean).
/* Operations on OclInteger. */
if (template == null
&& referredOperation != null
&& referredOperation.getOwner() != null
&& referredOperation.getOwner().equals(
oclLibrary.getOclInteger())) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames.get(operationName);
}
// no else.
/* Especially handle the minus operations. */
if (operationName.equals("minus")) {
/* Decide between binary minus and ... */
if (anOperationCallExp.getArgument().size() > 0) {
template = this.templateGroup
.getTemplate("minusOperationOnInteger");
}
/* ... unary negative. */
else {
template = this.templateGroup
.getTemplate("negativeOperationOnInteger");
}
}
else {
template = this.templateGroup.getTemplate(operationName
+ "OperationOnInteger");
}
}
// no else (OclInteger).
/* Operations on OclReal. */
if (template == null
&& referredOperation != null
&& referredOperation.getOwner() != null
&& referredOperation.getOwner().equals(
oclLibrary.getOclReal())) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames.get(operationName);
}
// no else.
/* Especially handle the minus operations. */
if (operationName.equals("minus")) {
/* Decide between binary minus and ... */
if (anOperationCallExp.getArgument().size() > 0) {
template = this.templateGroup
.getTemplate("minusOperationOnReal");
}
/* ... unary negative. */
else {
template = this.templateGroup
.getTemplate("negativeOperationOnReal");
}
}
else {
template = this.templateGroup.getTemplate(operationName
+ "OperationOnReal");
}
}
// no else (OclReal).
/*
* Especially handle equality operations on Boolean, Real or
* Integer.
*/
if (template == null
&& sourceType instanceof PrimitiveType
&& (((PrimitiveType) sourceType).getKind() == PrimitiveTypeKind.BOOLEAN || (((PrimitiveType) sourceType)
.getKind() == PrimitiveTypeKind.INTEGER || (((PrimitiveType) sourceType)
.getKind() == PrimitiveTypeKind.REAL)))) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames.get(operationName);
}
// no else.
if (operationName.equals("equals")) {
template = this.templateGroup
.getTemplate("equalsOperationOnPrimitiveType");
}
else if (operationName.equals("notEquals")) {
template = this.templateGroup
.getTemplate("notEqualsOperationOnPrimitiveType");
}
// no else.
}
// no else (special equality for primitive types).
/* Operations on OclString. */
/* TODO AST of characters seems to be wrong. */
if (template == null
&& (referredOperation != null
&& referredOperation.getOwner() != null && referredOperation
.getOwner().equals(oclLibrary.getOclString()))
|| operationName.equals("characters")) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames.get(operationName);
}
// no else.
template = this.templateGroup.getTemplate(operationName
+ "OperationOnString");
/* Characters operation requires special attributes because. */
if (template != null && operationName.equals("characters")) {
String resultVar = this.environment.getNewResultVarName();
template.setAttribute("sourceExp",
sourceCode.getResultExp());
template.setAttribute("resultVar", resultVar);
template.setAttribute("elementName",
this.environment.getNewIteratorVarName());
result.addCode(template.toString());
resultExp = resultVar;
}
// no else.
}
// no else (OclString).
/* Operations on OclAny. */
/* TODO AST of oclAsType seems to be wrong. */
/* TODO AST of oclType seems to be wrong. */
/* TODO asSet operation not defined on OclAny. */
if (template == null
&& (referredOperation != null
&& referredOperation.getOwner() != null && referredOperation
.getOwner().equals(oclLibrary.getOclAny()))
|| operationName.equals("oclAsType")
|| operationName.equals("oclType")
|| (operationName.equals("asSet") && (referredOperation
.getOwningType() == null || !(referredOperation
.getOwningType() instanceof CollectionType)))) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames.get(operationName);
}
// no else.
template = this.templateGroup.getTemplate(operationName
+ "OperationOnOclAny");
/*
* oclIsNew Operation calls must be registered at the
* evironment.
*/
if (template != null && operationName.equals("oclIsNew")) {
this.environment.addIsNewClass(this.transformType(
sourceExp.getType()).toString());
}
/* oclIsInvalid Operation requires special attributes. */
else if (template != null
&& operationName.equals("oclIsInvalid")) {
String resultVar = this.environment.getNewResultVarName();
if (result.containsCode())
template.setAttribute("sourceCode", result.getCode());
// no else.
template.setAttribute("sourceExp",
sourceCode.getResultExp());
template.setAttribute("resultVar", resultVar);
if (sourceExp.getType() != null)
template.setAttribute("sourceHasType", "true");
// no else.
/*
* Reset resulting code because all code must be contained
* within the try block (has been added to the template
* before).
*/
result = new TransformedCodeImpl();
result.addCode(template.toString());
resultExp = resultVar;
}
/*
* asSet Operation requires special attributes and special
* handling.
*/
else if (template != null && operationName.equals("asSet")) {
String resultVar = this.environment.getNewResultVarName();
template.setAttribute("sourceExp",
sourceCode.getResultExp());
template.setAttribute("resultVar", resultVar);
if (sourceExp.getType() != null) {
template.setAttribute("elementType",
this.transformType(sourceExp.getType()));
}
else {
template.setAttribute("elementType", this.templateGroup
.getTemplate("anyType").toString());
}
result.addCode(template.toString());
resultExp = resultVar;
}
/*
* oclIsUndefined Operation requires special attributes and
* special handling for primitive types since they can be
* primitive types in Java on which null checks are not allowed.
*/
else if (template != null
&& operationName.equals("oclIsUndefined")
&& sourceExp.getType() != null
&& sourceExp.getType() instanceof PrimitiveType) {
template = this.templateGroup
.getTemplate("oclIsUndefinedOperationOnPrimitiveType");
template.setAttribute("sourceType",
this.transformType(sourceExp.getType()));
}
// no else.
}
// no else (OclAny).
/* Operations on OclType. */
/* TODO AST of allInstances seems to be wrong. */
if (template == null
&& (referredOperation != null
&& referredOperation.getOwner() != null && referredOperation
.getOwner().equals(oclLibrary.getOclAny()))
|| operationName.equals("allInstances")) {
/* Probably rename the operation. */
if (renamedOperationNames.containsKey(operationName)) {
operationName = renamedOperationNames.get(operationName);
}
// no else.
template = this.templateGroup.getTemplate(operationName
+ "OperationOnOclType");
/*
* allInstances Operation calls must be registered at the
* evironment.
*/
if (template != null && operationName.equals("allInstances")) {
/* Esspecially handle type literal exps. */
if (sourceExp instanceof TypeLiteralExp) {
Type typeLiteralType = ((TypeLiteralExp) sourceExp)
.getReferredType();
sourceCode = new TransformedCodeImpl();
sourceCode.setResultExp(this.transformType(
(typeLiteralType)).getTypeName());
if (typeLiteralType instanceof PrimitiveType
&& ((PrimitiveType) typeLiteralType).getKind() == PrimitiveTypeKind.BOOLEAN) {
template = this.templateGroup
.getTemplate(operationName
+ "OperationOnOclBoolean");
template.setAttribute("typeName",
sourceCode.getResultExp());
resultExp = this.environment.getNewResultVarName();
template.setAttribute("resultVar", resultExp);
result.addCode(template.toString());
}
else if (typeLiteralType instanceof VoidType) {
template = this.templateGroup
.getTemplate(operationName
+ "OperationOnOclVoid");
resultExp = this.environment.getNewResultVarName();
template.setAttribute("resultVar", resultExp);
result.addCode(template.toString());
}
else if (typeLiteralType instanceof InvalidType) {
template = this.templateGroup
.getTemplate(operationName
+ "OperationOnOclInvalid");
template.setAttribute(
"typeName",
this.transformType(
anOperationCallExp.getType())
.toString());
}
else {
template.setAttribute("typeName",
sourceCode.getResultExp());
this.environment.addAllInstancesClass(sourceCode
.getResultExp());
}
}
// no else.
}
// no else.
}
// no else (OclType).
}
// no else.
/* Code for operations on non Ocl Types. */
if (template == null) {
template = this.templateGroup.getTemplate("umlOperation");
template.setAttribute("operationName", operationName);
}
// no else.
/* Probably set more attributes of the template. */
if (template != null && resultExp == null) {
template.setAttribute("sourceExp", sourceCode.getResultExp());
/* Probably set code for arguments of the operation. */
int index = 0;
for (OclExpression anArgument : anOperationCallExp.getArgument()) {
/* Especially handle type literals for some operations. */
if (operationName.equals("oclAsType")
&& anArgument instanceof TypeLiteralExp) {
template.setAttribute(
"argsExp",
this.transformType(
((TypeLiteralExp) anArgument)
.getReferredType()).getTypeName());
}
else {
this.environment.pushExpectedReturnType(referredOperation
.getInputParameter().get(index).getType());
ITransformedCode argCode = this.doSwitch(anArgument);
this.environment.popExpectedReturnType();
result.addCode(argCode.getCode());
template.setAttribute("argsExp", argCode.getResultExp());
}
index++;
}
// end for.
resultExp = template.toString();
}
// no else.
result.setResultExp(resultExp);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseOperationCallExp(OperationCallExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #casePropertyCallExp
* (org.dresdenocl.essentialocl.expressions.PropertyCallExp)
*/
public ITransformedCode casePropertyCallExp(PropertyCallExp aPropertyCallExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("casePropertyCallExp(PropertyCallExp) - start");
}
// no else.
ITransformedCode result = new TransformedCodeImpl();
/* Get parameters for property call code. */
Property referredProperty = aPropertyCallExp.getReferredProperty();
/* Transform the code for the sourceExp. */
ITransformedCode sourceCode;
/*
* Esspecially handle static properties since type literals are hard to
* handle in Java.
*/
if (referredProperty.isStatic()
&& aPropertyCallExp.getSource() instanceof TypeLiteralExp) {
sourceCode = new TransformedCodeImpl();
sourceCode.setResultExp(this.transformType(
((TypeLiteralExp) aPropertyCallExp.getSource())
.getReferredType()).getTypeName());
}
else
sourceCode = doSwitch(aPropertyCallExp.getSource());
// end else.
/* Add source code to result. */
result.addCode(sourceCode.getCode());
ITemplate template;
/* The property calls on tuples must be adapted. */
if (aPropertyCallExp.getSource() != null
&& aPropertyCallExp.getSource().getType() instanceof TupleType) {
template = this.templateGroup.getTemplate("propertyCallExpOnTuple");
}
else {
template = this.templateGroup.getTemplate("propertyCallExp");
}
/* Set template attributes. */
template.setAttribute("sourceExp", sourceCode.getResultExp());
String propertyName = referredProperty.getName();
/* Probably use getters instead of properties. */
if (!(aPropertyCallExp.getSource() != null && aPropertyCallExp
.getSource().getType() instanceof TupleType)
&& this.settings.isGettersForPropertyCallsEnabled()) {
String newName;
if (referredProperty.getType() instanceof PrimitiveType
&& ((PrimitiveType) referredProperty.getType()).getKind() == PrimitiveTypeKind.BOOLEAN)
newName = "is";
else
newName = "get";
newName = newName + propertyName.substring(0, 1).toUpperCase();
if (propertyName.length() > 1)
newName += propertyName.substring(1, propertyName.length());
// no else.
propertyName = newName + "()";
}
// no else.
template.setAttribute("propertyName", propertyName);
result.setResultExp(template.toString());
/*
* Store the called properties in the environment (Probably needed for
* invariant instrumentation). Only store properties, which are
* properties of the constrained element. Thus their source must be a
* self variable.
*/
if (aPropertyCallExp.getSource() instanceof VariableExp) {
VariableExp aVariableExp = (VariableExp) aPropertyCallExp
.getSource();
Variable aVariable = aVariableExp.getReferredVariable();
if (aVariable.getName().equals("self")) {
this.environment.addCalledProperty(referredProperty.getName());
}
// no else.
}
// no else.
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("casePropertyCallExp(PropertyCallExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseRealLiteralExp
* (org.dresdenocl.essentialocl.expressions.RealLiteralExp)
*/
public ITransformedCode caseRealLiteralExp(RealLiteralExp aRealLiteralExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseRealLiteralExp(RealLiteralExp) - start");
}
// no else.
ITemplate template = this.templateGroup.getTemplate("literalExp");
template.setAttribute("type",
this.transformType(aRealLiteralExp.getType()).toString());
template.setAttribute("value", aRealLiteralExp.getRealSymbol());
ITransformedCode result = new TransformedCodeImpl();
result.setResultExp(template.toString());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseRealLiteralExp(RealLiteralExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseStringLiteralExp
* (org.dresdenocl.essentialocl.expressions.StringLiteralExp)
*/
public ITransformedCode caseStringLiteralExp(
StringLiteralExp aStringLiteralExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseStringLiteralExp(StringLiteralExp) - start");
}
// no else.
ITemplate template = this.templateGroup.getTemplate("stringLiteralExp");
template.setAttribute("value", aStringLiteralExp.getStringSymbol());
ITransformedCode result = new TransformedCodeImpl();
result.setResultExp(template.toString());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseStringLiteralExp(StringLiteralExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseTupleLiteralExp
* (org.dresdenocl.essentialocl.expressions.TupleLiteralExp)
*/
public ITransformedCode caseTupleLiteralExp(TupleLiteralExp aTupleLiteralExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseTupleLiteralExp(TupleLiteralExp) - start");
}
// no else.
ITransformedCode result = new TransformedCodeImpl();
String tupleName = aTupleLiteralExp.getName();
/* If the tuple has no name, compute a new name. */
if (tupleName.equals("")) {
tupleName = this.environment.getNewTupleVarName();
}
// no else.
/* Get template for tupleLiteralExp. */
ITemplate template = this.templateGroup.getTemplate("tupleLiteralExp");
template.setAttribute("tupleName", tupleName);
/* Transform Code for all initial elements. */
for (TupleLiteralPart aTupleElement : aTupleLiteralExp.getPart()) {
ITransformedCode elementCode = this
.doSwitch((EObject) aTupleElement.getValue());
template.setAttribute("argCodes", elementCode.getCode());
template.setAttribute("argExps", elementCode.getResultExp());
template.setAttribute("argNames", aTupleElement.getProperty()
.getName());
}
/* Set the result. */
result.addCode(template.toString());
result.setResultExp(tupleName);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseTupleLiteralExp(TupleLiteralExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseTypeLiteralExp
* (org.dresdenocl.essentialocl.expressions.TypeLiteralExp)
*/
public ITransformedCode caseTypeLiteralExp(TypeLiteralExp aTypeLiteralExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseTypeLiteralExp(TypeLiteralExp) - start");
}
// no else.
ITemplate template = this.templateGroup.getTemplate("typeLiteralExp");
template.setAttribute("type",
this.transformType(aTypeLiteralExp.getReferredType())
.toString());
ITransformedCode result = new TransformedCodeImpl();
result.setResultExp(template.toString());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseTypeLiteralExp(TypeLiteralExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseUndefinedLiteralExp
* (org.dresdenocl.essentialocl.expressions.UndefinedLiteralExp)
*/
public ITransformedCode caseUndefinedLiteralExp(
UndefinedLiteralExp anUndefinedLiteralExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseUndefinedLiteralExp(UndefinedLiteralExp) - start");
}
// no else.
ITemplate template = this.templateGroup
.getTemplate("undefinedLiteralExp");
ITransformedCode result = new TransformedCodeImpl();
result.setResultExp(template.toString());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseUndefinedLiteralExp(UndefinedLiteralExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseUnlimitedNaturalExp
* (org.dresdenocl.essentialocl.expressions.UnlimitedNaturalExp)
*/
public ITransformedCode caseUnlimitedNaturalExp(
UnlimitedNaturalExp anUnlimitedNaturalExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseUnlimitedNaturalExp(UnlimitedNaturalExp) - start");
}
// no else.
ITransformedCode result;
ITemplate template = this.templateGroup.getTemplate("literalExp");
template.setAttribute("type",
this.transformType(anUnlimitedNaturalExp.getType()).toString());
template.setAttribute("value", anUnlimitedNaturalExp.getSymbol());
result = new TransformedCodeImpl();
result.setResultExp(template.toString());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseUnlimitedNaturalExp(UnlimitedNaturalExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.essentialocl.expressions.util.ExpressionsSwitch
* #caseVariableExp (org.dresdenocl.essentialocl.expressions.VariableExp)
*/
public ITransformedCode caseVariableExp(VariableExp aVariableExp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseVariableExp(VariableExp) - start");
}
// no else.
Variable aVariable = aVariableExp.getReferredVariable();
ITransformedCode result = new TransformedCodeImpl();
ITemplate template;
/*
* The keyword 'self' has to be transformed into the name of the
* variable which references the constrained class
*/
if (aVariable.getName().equals("self")) {
template = this.templateGroup.getTemplate("selfVariable");
result.setResultExp(template.toString());
this.environment.setIsUsigSelfVariable(true);
}
/*
* The special OCL variable 'result' has to be transformed in their name
* in Java.
*
* The second check avoids to faulty handle declared 'result' variables
* from iterator or let expressions.
*/
else if (aVariable.getName().equals("result")
&& aVariable.getInitExpression() == null) {
template = this.templateGroup.getTemplate("resultVariable");
result.setResultExp(template.toString());
}
/* All other VariableExp lead to the name of the Variable. */
else {
String varName = aVariable.getName();
/* Probably map the variable to another name. */
if (this.environment.existsMappingForVariable(varName))
varName = this.environment.getVariableMapping(varName);
// no else.
result.setResultExp(varName);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("caseVariableExp(VariableExp)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Initializes the code generator.
* </p>
*
* @throws Ocl2CodeException
* Thrown, if a String template for code transformation can not
* be found.
*/
protected void init() throws Ocl2CodeException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("init() - start");
}
// no else.
this.environment = new Ocl2JavaEnvironment();
/* Try to load the template engine. */
try {
LinkedList<String> templatePaths = new LinkedList<String>();
templatePaths.add(getUrl(TEMPLATE_PATH + JAVA_TEMPLATE_FILE));
templatePaths.add(getUrl(TEMPLATE_PATH + TYPE_TEMPLATE_FILE));
templatePaths.add(getUrl(TEMPLATE_PATH + OPERATION_TEMPLATE_FILE));
templatePaths.add(getUrl(TEMPLATE_PATH + EXPRESSION_TEMPLATE_FILE));
templatePaths.add(getUrl(TEMPLATE_PATH
+ INSTRUMENTATION_TEMPLATE_FILE));
TemplatePlugin.getTemplateGroupRegistry().removeTemplateGroup(
"Ocl2Java");
this.templateGroup = TemplatePlugin.getTemplateGroupRegistry()
.addDefaultTemplateGroup("Ocl2Java", null);
this.templateGroup.addFiles(templatePaths);
this.settings = new Ocl2JavaSettings();
}
catch (TemplateException e) {
String msg = "The template for code transformation could not be loaded. ";
msg += e.getMessage();
if (LOGGER.isDebugEnabled()) {
LOGGER.error("init() - failed", e);
}
// no else.
throw new Ocl2CodeException(msg);
} catch (IOException e) {
throw new Ocl2CodeException(e.getMessage(), e);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("init() - end");
}
// no else.
}
/**
* Helper method to get the URL for a given resource in this plug-in.
*
* @param path
* The path of the resource.
* @throws IOException
*/
private String getUrl(String path) throws IOException {
File file = null;
if (Platform.isRunning()) {
Bundle bundle = Platform.getBundle(Ocl2JavaPlugin.PLUGIN_ID);
if (bundle != null) {
try {
URL url = bundle.getEntry(path);
file = new File(FileLocator.toFileURL(url).toURI());
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
else {
File testLocation = new File(
System.getProperty("DRESDENOCL_LOCATION_TESTS")
+ Ocl2JavaPlugin.PLUGIN_ID);
File eclipseLocation = new File(
System.getProperty("DRESDENOCL_LOCATION_ECLIPSE")
+ Ocl2JavaPlugin.PLUGIN_ID);
File bundleFile = null;
if (testLocation != null && testLocation.exists()
&& testLocation.isDirectory()) {
bundleFile = testLocation;
} else if (eclipseLocation != null && eclipseLocation.exists()
&& eclipseLocation.isDirectory()) {
bundleFile = eclipseLocation;
}
if (bundleFile != null)
file = new File(bundleFile + File.separator + path);
else
throw new RuntimeException("Bundle or directory '"
+ Ocl2JavaPlugin.PLUGIN_ID + "' was not found.");
}
return file.getAbsolutePath();
}
/**
* <p>
* Returns The canonical Name of a {@link NamedElement} in the
* {@link IModel}.
* </p>
*
* @returns The canonical Name of a {@link NamedElement}.
*/
private String getCanonicalName(NamedElement anElement) {
String result = "";
if (anElement.getOwner() != null) {
result += this.getPackagePath(anElement) + ".";
}
// no else.
result += anElement.getName();
return result;
}
/**
* <p>
* Returns the constraint package to a given packagePath. They are the same
* if no constraint directory has been set. Else the constraint directory is
* a sub package.
* </p>
*
* @param packagePath
* @return The constraint package to a given packagePath.
*/
private String getConstraintPackage(String packagePath) {
String result = packagePath;
String constDirectory = this.settings.getConstraintDirectory();
if (constDirectory.length() > 0) {
result += "." + constDirectory.replaceAll("/", ".");
}
// no else.
return result;
}
/**
* <p>
* Returns the path of the package in the {@link IModel} where the given
* {@link NamedElement} is located.
* </p>
*
* @returns The path of the package.
*/
private String getPackagePath(NamedElement anElement) {
String result;
NamedElement anOwner = anElement.getOwner();
result = anOwner.getName();
while (anOwner != null) {
anOwner = anOwner.getOwner();
if (anOwner != null && !anOwner.getName().equals("")
&& !anOwner.getName().equals("root")
&& !anOwner.getName().equals("generatedTopLevelModel")) {
result = anOwner.getName() + "." + result;
}
// no else
}
if (this.settings.getBasisPackage().length() > 0)
result = this.settings.getBasisPackage() + "." + result;
// no else.
return result;
}
/**
* <p>
* Generates an Aspect for the instrumentation of body constraints.
* </p>
*
* @param constraint
* The {@link Constraint} which shall be instrumented.
*/
protected String instrumentCodeForBody(Constraint constraint)
throws Ocl2CodeException {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForBody(Constraint) - start");
}
// no else.
String result;
ITemplate aspectTemplate = this.templateGroup.getTemplate("aspectFile");
/* Get the constrained operation. */
Operation constrainedOperation = ((Operation) constraint
.getConstrainedElement().get(0));
/* Get the path of the package where the constraint class is located. */
String contextPackage = this.getPackagePath(constraint);
aspectTemplate.setAttribute("package",
this.getConstraintPackage(contextPackage));
/* Compute the aspect's file name. */
String className = constrainedOperation.getOwner().getName();
String aspectName = className + "_"
+ Ocl2JavaEnvironment.BODY_ASPECT_NAME + "_"
+ constrainedOperation.getName();
if (this.environment.isUsedAspectName(aspectName))
aspectName = className + "_"
+ this.environment.getNewBodyAspectName();
// no else.
this.environment.addUsedAspectName(aspectName);
aspectTemplate.setAttribute("name", aspectName);
/* Generate the code which shall be inside the advice(s). */
this.environment.pushExpectedReturnType(constrainedOperation.getType());
ITransformedCode constrainedCode = this
.transformFragmentCode(constraint);
this.environment.popExpectedReturnType();
/* Probably collect allInstances for some classes. */
if (this.environment.hasAllInstancesClasses()) {
Set<String> allInstancesClasses = this.environment
.getAllInstancesClasses();
for (String aClassName : allInstancesClasses) {
aspectTemplate.setAttribute("allInstanceClasses", aClassName);
}
}
// no else.
NamedElement constrainedClass = constrainedOperation.getOwner();
String operationName = constrainedOperation.getName();
String operationResultType = this.transformType(
constrainedOperation.getType()).toString();
/* Create Template for the advice code. */
ITemplate adviceTemplate = this.templateGroup
.getTemplate("bodyInstrumentation");
/* Set template parameters. */
adviceTemplate.setAttribute("class", constrainedClass.getName());
adviceTemplate.setAttribute("package", contextPackage);
adviceTemplate.setAttribute("constCode", constrainedCode.getCode());
adviceTemplate.setAttribute("constExp", constrainedCode.getResultExp());
adviceTemplate.setAttribute("oclBody", constraint.getSpecification()
.getBody().trim().replaceAll("\r\n", " ").replaceAll("\r", " ")
.replaceAll("\n", " "));
adviceTemplate.setAttribute("method", operationName);
/* Probably set the returnType. */
if (!operationResultType.equals(this.templateGroup.getTemplate(
"voidType").toString())) {
adviceTemplate.setAttribute("returnType", operationResultType);
}
// no else.
/* Probably set the arguments of the operation. */
this.setArgumentsForInstrumentationTemplate(constraint, adviceTemplate);
/* Probably set that the constraint operation is static. */
if (constrainedOperation.isStatic()) {
adviceTemplate.setAttribute("opIsStatic", "true");
}
// no else.
/* Add the advice code to the aspect template. */
aspectTemplate.setAttribute("advice", adviceTemplate.toString());
result = aspectTemplate.toString();
/* Probably save the generated Code. */
if (this.settings.isSaveCode()) {
this.saveTransformedCode(result, aspectName + ".aj",
this.getConstraintPackage(contextPackage));
}
// no else.
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForBody(Constraint)"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Generates an Aspect for the instrumentation of definition constraints.
* </p>
*
* @param constraint
* The {@link Constraint} which shall be instrumented.
*/
protected String instrumentCodeForDef(Constraint constraint)
throws Ocl2CodeException {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForDef(Constraint) - start");
}
// no else.
String result;
ITemplate aspectTemplate = this.templateGroup.getTemplate("aspectFile");
/* Get the constrained element. */
Feature definedFeature = constraint.getDefinedFeature();
/* Get the path of the package where the constraint class is located. */
String contextPackage = this.getPackagePath(constraint);
aspectTemplate.setAttribute("package",
this.getConstraintPackage(contextPackage));
/* Compute the aspect's file name. */
String className = definedFeature.getOwner().getName();
String aspectName = className + "_"
+ Ocl2JavaEnvironment.DEF_ASPECT_NAME + "_"
+ definedFeature.getName();
if (this.environment.isUsedAspectName(aspectName))
aspectName = className + "_"
+ this.environment.getNewDefAspectName();
// no else.
this.environment.addUsedAspectName(aspectName);
aspectTemplate.setAttribute("name", aspectName);
/* Generate the code which shall be inside the advice(s). */
this.environment.pushExpectedReturnType(definedFeature.getType());
ITransformedCode constrainedCode = this
.transformFragmentCode(constraint);
this.environment.popExpectedReturnType();
/* Probably collect allInstances for some classes. */
if (this.environment.hasAllInstancesClasses()) {
Set<String> allInstancesClasses;
allInstancesClasses = this.environment.getAllInstancesClasses();
for (String aClassName : allInstancesClasses) {
aspectTemplate.setAttribute("allInstanceClasses", aClassName);
}
}
// no else.
ITemplate adviceTemplate;
Type type = (Type) constraint.getConstrainedElement().get(0);
/* Differentiate between defined properties and operations. */
if (definedFeature instanceof Property) {
/* Get the defined property. */
Property definedProperty = (Property) definedFeature;
String propertyName = definedProperty.getName();
String propertyType = this.transformType(definedProperty.getType())
.toString();
/* Create the template for the advice code. */
adviceTemplate = this.templateGroup
.getTemplate("defAttributeInstrumentation");
/* Set attribute specific template attributes. */
adviceTemplate.setAttribute("attribute", propertyName);
adviceTemplate.setAttribute("attributeType", propertyType);
if (definedProperty.isStatic())
adviceTemplate.setAttribute("isStatic", "true");
// no else.
/* Probably also create a new getter method for the new attribute. */
if (this.settings.isGettersForDefinedAttributesEnabled()) {
String getterName = "get"
+ propertyName.substring(0, 1).toUpperCase()
+ propertyName.substring(1, propertyName.length());
adviceTemplate.setAttribute("getterName", getterName);
}
// no else.
}
else if (definedFeature instanceof Operation) {
/* Get the defined operation. */
Operation definedOperation = (Operation) definedFeature;
String operationName = definedOperation.getName();
String operationReturnType = this.transformType(
definedOperation.getType()).toString();
/* Create a template for the advice code. */
adviceTemplate = this.templateGroup
.getTemplate("defMethodInstrumentation");
/* Set operation specific template parameters. */
adviceTemplate.setAttribute("method", operationName);
/* Probably set the returnType. */
if (!operationReturnType.equals(this.templateGroup.getTemplate(
"voidType").toString())) {
adviceTemplate.setAttribute("returnType", operationReturnType);
}
// no else.
/* Set all arguments of the Operation. */
for (Parameter anArgument : definedOperation.getInputParameter()) {
String anArgumentsName = anArgument.getName();
if (this.environment.existsMappingForVariable(anArgumentsName))
anArgumentsName = this.environment
.getVariableMapping(anArgumentsName);
// no else.
String anArgumentsType = this.transformType(
anArgument.getType()).toString();
adviceTemplate.setAttribute("args", anArgumentsName);
adviceTemplate.setAttribute("argTypes", anArgumentsType);
}
if (definedOperation.isStatic())
adviceTemplate.setAttribute("isStatic", true);
if (this.environment.isUsingSelfVariable())
adviceTemplate.setAttribute("usesSelfVariable", "true");
}
/* No other things can be defined by definition constraints. */
else {
String msg;
msg = "An def value defined for an invalid Type of Feature.";
msg += "Expected Type was Operation or Property but was ";
msg += definedFeature.getClass().getName();
throw new Ocl2CodeException(msg);
}
/* Set advice template parameters. */
adviceTemplate.setAttribute("class", type.getName());
adviceTemplate.setAttribute("package", contextPackage);
adviceTemplate.setAttribute("constFolder",
this.settings.getConstraintDirectory());
adviceTemplate.setAttribute("constCode", constrainedCode.getCode());
adviceTemplate.setAttribute("constExp", constrainedCode.getResultExp());
adviceTemplate.setAttribute("oclBody", constraint.getSpecification()
.getBody().trim().replaceAll("\r\n", " ").replaceAll("\r", " ")
.replaceAll("\n", " "));
/* Add the advice code to the aspect template. */
aspectTemplate.setAttribute("advice", adviceTemplate.toString());
result = aspectTemplate.toString();
/* Probably save the generated Code. */
if (this.settings.isSaveCode()) {
this.saveTransformedCode(result, aspectName + ".aj",
this.getConstraintPackage(contextPackage));
}
// no else.
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForDef(Constraint)"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Generates an Aspect for the instrumentation of derive constraints.
* </p>
*
* @param constraint
* The {@link Constraint} which shall be instrumented.
*/
protected String instrumentCodeForDerive(Constraint constraint)
throws Ocl2CodeException {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForDerive(Constraint) - start");
}
// no else.
String result;
/* Get the constrained property. */
Property constrainedProperty = ((Property) constraint
.getConstrainedElement().get(0));
ITemplate aspectTemplate = this.templateGroup.getTemplate("aspectFile");
/* Get the path of the package where the constraint class is located. */
String contextPackage = this.getPackagePath(constraint);
aspectTemplate.setAttribute("package",
this.getConstraintPackage(contextPackage));
/* Compute the aspect's file name. */
String className = constrainedProperty.getOwner().getName();
String aspectName = className + "_"
+ Ocl2JavaEnvironment.DERIVE_ASPECT_NAME + "_"
+ constrainedProperty.getName();
if (this.environment.isUsedAspectName(aspectName))
aspectName = className + "_"
+ this.environment.getNewDeriveAspectName();
// no else.
this.environment.addUsedAspectName(aspectName);
aspectTemplate.setAttribute("name", aspectName);
/* Generate the code which shall be inside the advice(s). */
this.environment.pushExpectedReturnType(constrainedProperty.getType());
ITransformedCode constrainedCode = this
.transformFragmentCode(constraint);
this.environment.popExpectedReturnType();
/* Probably collect allInstances for some classes. */
if (this.environment.hasAllInstancesClasses()) {
Set<String> allInstancesClasses = this.environment
.getAllInstancesClasses();
for (String aClassName : allInstancesClasses) {
aspectTemplate.setAttribute("allInstanceClasses", aClassName);
}
}
// no else.
NamedElement constrainedClass;
/*
* Compute the constrained class. Especially handle static defined
* properties.
*/
if (constrainedProperty.isStatic()) {
constrainedClass = ((ExpressionInOcl) constraint.getSpecification())
.getContext().getType();
}
else {
constrainedClass = constrainedProperty.getOwner();
}
String propertyName = constrainedProperty.getName();
String propertyType = this.transformType(constrainedProperty.getType())
.toString();
/* Create Template for the advice code. */
ITemplate adviceTemplate = this.templateGroup
.getTemplate("deriveInstrumentation");
/* Set template parameters. */
adviceTemplate.setAttribute("attribute", propertyName);
adviceTemplate.setAttribute("attributeType", propertyType);
adviceTemplate.setAttribute("class", constrainedClass.getName());
adviceTemplate.setAttribute("package", contextPackage);
adviceTemplate.setAttribute("constCode", constrainedCode.getCode());
adviceTemplate.setAttribute("constExp", constrainedCode.getResultExp());
adviceTemplate.setAttribute("oclBody", constraint.getSpecification()
.getBody().trim().replaceAll("\r\n", " ").replaceAll("\r", " ")
.replaceAll("\n", " "));
/* Probably set that the constrained attribute is static. */
if (constrainedProperty.isStatic()) {
adviceTemplate.setAttribute("attIsStatic", "true");
}
// no else.
/* Add the advice code to the aspect template. */
aspectTemplate.setAttribute("advice", adviceTemplate.toString());
result = aspectTemplate.toString();
/* Probably save the generated Code. */
if (this.settings.isSaveCode()) {
this.saveTransformedCode(result, aspectName + ".aj",
this.getConstraintPackage(contextPackage));
}
// no else.
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForDerive(Constraint)"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Generates an Aspect for the instrumentation of initial constraints.
* </p>
*
* @param constraint
* The {@link Constraint} which shall be instrumented.
*/
protected String instrumentCodeForInit(Constraint constraint)
throws Ocl2CodeException {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForInit(Constraint) - start");
}
// no else.
String result;
/* Get the constrained property. */
Property constrainedProperty = ((Property) constraint
.getConstrainedElement().get(0));
ITemplate aspectTemplate = this.templateGroup.getTemplate("aspectFile");
/* Get the path of the package where the constraint class is located. */
String contextPackage = this.getPackagePath(constraint);
aspectTemplate.setAttribute("package",
this.getConstraintPackage(contextPackage));
/* Compute the aspect's file name. */
String className = constrainedProperty.getOwner().getName();
String aspectName = className + "_"
+ Ocl2JavaEnvironment.INIT_ASPECT_NAME + "_"
+ constrainedProperty.getName();
if (this.environment.isUsedAspectName(aspectName))
aspectName = className + "_"
+ this.environment.getNewInitAspectName();
// no else.
this.environment.addUsedAspectName(aspectName);
aspectTemplate.setAttribute("name", aspectName);
/* Generate the code which shall be inside the advice(s). */
this.environment.pushExpectedReturnType(constrainedProperty.getType());
ITransformedCode constrainedCode = this
.transformFragmentCode(constraint);
this.environment.popExpectedReturnType();
/* Probably collect allInstances for some classes. */
if (this.environment.hasAllInstancesClasses()) {
Set<String> allInstancesClasses = this.environment
.getAllInstancesClasses();
for (String aClassName : allInstancesClasses) {
aspectTemplate.setAttribute("allInstanceClasses", aClassName);
}
}
// no else.
/*
* Compute the constrained class name. Especially handle static defined
* properties.
*/
if (constrainedProperty.isStatic()) {
className = ((ExpressionInOcl) constraint.getSpecification())
.getContext().getType().getName();
}
else {
className = constrainedProperty.getOwner().getName();
}
ITemplate adviceTemplate;
/* Get the template and handle static attribute specially. */
if (constrainedProperty.isStatic()) {
adviceTemplate = this.templateGroup
.getTemplate("staticInitInstrumentation");
}
else {
adviceTemplate = this.templateGroup
.getTemplate("initInstrumentation");
}
adviceTemplate.setAttribute("class", className);
adviceTemplate.setAttribute("package", contextPackage);
adviceTemplate.setAttribute("attribute", constrainedProperty.getName());
adviceTemplate.setAttribute("constCode", constrainedCode.getCode());
adviceTemplate.setAttribute("constExp", constrainedCode.getResultExp());
adviceTemplate.setAttribute("oclBody", constraint.getSpecification()
.getBody().trim().replaceAll("\r\n", " ").replaceAll("\r", " ")
.replaceAll("\n", " "));
aspectTemplate.setAttribute("advice", adviceTemplate.toString());
result = aspectTemplate.toString();
/* Probably save the generated Code. */
if (this.settings.isSaveCode()) {
this.saveTransformedCode(result, aspectName + ".aj",
this.getConstraintPackage(contextPackage));
}
// no else.
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForInit(Constraint)"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Generates an Aspect for the instrumentation of invariants.
* </p>
*
* @param constraint
* The {@link Constraint} which shall be instrumented.
*/
protected String instrumentCodeForInv(Constraint constraint)
throws Ocl2CodeException {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForInv(Constraint) - start");
}
// no else.
String result;
ITemplate aspectTemplate = this.templateGroup.getTemplate("aspectFile");
/* Get the path of the package where the constraint class is located. */
String contextPackage = this.getPackagePath(constraint);
aspectTemplate.setAttribute("package",
this.getConstraintPackage(contextPackage));
/* Compute the aspect's file name. */
String className = ((Type) constraint.getConstrainedElement().get(0))
.getName();
String aspectName = className + "_"
+ Ocl2JavaEnvironment.INV_ASPECT_NAME + "_"
+ constraint.getName();
if (constraint.getName() == null || constraint.getName().length() == 0
|| this.environment.isUsedAspectName(aspectName))
aspectName = className + "_"
+ this.environment.getNewInvAspectName();
// no else.
this.environment.addUsedAspectName(aspectName);
aspectTemplate.setAttribute("name", aspectName);
/* Generate the code which shall be inside the advice(s). */
this.environment.pushExpectedReturnType(EssentialOclPlugin
.getOclLibraryProvider().getOclLibrary().getOclBoolean());
ITransformedCode constrainedCode = this
.transformFragmentCode(constraint);
this.environment.popExpectedReturnType();
/* Probably collect allInstances for some classes. */
if (this.environment.hasAllInstancesClasses()) {
Set<String> allInstancesClasses = this.environment
.getAllInstancesClasses();
for (String aClassName : allInstancesClasses) {
aspectTemplate.setAttribute("allInstanceClasses", aClassName);
}
}
// no else.
Type constrainedClass = (Type) constraint.getConstrainedElement()
.get(0);
ITemplate adviceTemplate;
/*
* Check which type of invariant check mode shall be used and create the
* template for the advice code.
*/
switch (this.settings.getInvariantCheckMode(constraint)) {
case IOcl2JavaSettings.INVARIANT_CHECK_AFTER_CONSTRUCT_AND_PUBLIC_METHOD_EXECUTION:
adviceTemplate = this.templateGroup
.getTemplate("invInstrumentation2");
break;
case IOcl2JavaSettings.INVARIANT_CHECK_AFTER_SPECIAL_METHOD_INVOCATION:
adviceTemplate = this.templateGroup
.getTemplate("invInstrumentation3");
String checkOperationName = this.templateGroup.getTemplate(
"checkInvariantsOperationName").toString();
/* Probably declare te check method inside the aspect. */
if (!this.environment.isMethodAlreadyDefined(checkOperationName,
constrainedClass.getQualifiedName())) {
adviceTemplate.setAttribute("defineCheckMethod", "true");
this.environment.addDefinedMethod(checkOperationName,
constrainedClass.getQualifiedName());
}
// no else.
break;
default:
adviceTemplate = this.templateGroup
.getTemplate("invInstrumentation1");
}
/* Set template parameters. */
adviceTemplate.setAttribute("class", constrainedClass.getName());
adviceTemplate.setAttribute("package", contextPackage);
adviceTemplate.setAttribute("constCode", constrainedCode.getCode());
adviceTemplate.setAttribute("constExp", constrainedCode.getResultExp());
adviceTemplate.setAttribute("oclBody", constraint.getSpecification()
.getBody().trim().replaceAll("\r\n", " ").replaceAll("\r", " ")
.replaceAll("\n", " "));
adviceTemplate.setAttribute("errorCode",
this.settings.getViolationMacro(constraint));
/*
* Probably add called attributes as parameters (only if the invariant
* shall be verified after the change of an depending attribute).
*/
if (this.settings.getInvariantCheckMode(constraint) == IOcl2JavaSettings.INVARIANT_CHECK_AFTER_CONSTRUCT_AND_ATTRIBUTE_CHANGE) {
if (this.environment.hasCalledProperties()) {
for (String aCalledProperty : this.environment
.getCalledProperties()) {
adviceTemplate.setAttribute("calledAttPaths",
aCalledProperty);
adviceTemplate.setAttribute("calledAttNames",
aCalledProperty.replaceAll("\\.", "_"));
}
}
// no else.
}
// no else.
/* Probably disable the inheritance for this invariant. */
if (this.settings.isInheritanceDisabled(constraint)) {
adviceTemplate.setAttribute("disableInheritance", "true");
}
// no else.
/* Add the advice code to the aspect template. */
aspectTemplate.setAttribute("advice", adviceTemplate.toString());
result = aspectTemplate.toString();
/* Probably save the generated Code. */
if (this.settings.isSaveCode()) {
this.saveTransformedCode(result, aspectName + ".aj",
this.getConstraintPackage(contextPackage));
}
// no else.
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForInv(Constraint)"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Generates an Aspect for the instrumentation of postconditions.
* </p>
*
* @param constraint
* The {@link Constraint} which shall be instrumented.
*/
protected String instrumentCodeForPost(Constraint constraint)
throws Ocl2CodeException {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForPost(Constraint) - start");
}
// no else.
String result;
/* Get the constrained operation. */
Operation constrainedOperation = ((Operation) constraint
.getConstrainedElement().get(0));
ITemplate aspectTemplate = this.templateGroup.getTemplate("aspectFile");
/* Get the path of the package where the constraint class is located. */
String contextPackage = this.getPackagePath(constraint);
aspectTemplate.setAttribute("package",
this.getConstraintPackage(contextPackage));
/* Compute the aspect's file name. */
String className = constrainedOperation.getOwner().getName();
String aspectName = className + "_"
+ Ocl2JavaEnvironment.POST_ASPECT_NAME + "_"
+ constrainedOperation.getName();
if (this.environment.isUsedAspectName(aspectName))
aspectName = className + "_"
+ this.environment.getNewPostAspectName();
// no else.
this.environment.addUsedAspectName(aspectName);
aspectTemplate.setAttribute("name", aspectName);
/* Generate the code which shall be inside the advice(s). */
this.environment.pushExpectedReturnType(EssentialOclPlugin
.getOclLibraryProvider().getOclLibrary().getOclBoolean());
ITransformedCode constrainedCode = this
.transformFragmentCode(constraint);
this.environment.popExpectedReturnType();
/* Probably collect allInstances for some classes. */
if (this.environment.hasAllInstancesClasses()) {
Set<String> allInstancesClasses = this.environment
.getAllInstancesClasses();
for (String aClassName : allInstancesClasses) {
aspectTemplate.setAttribute("allInstanceClasses", aClassName);
}
}
// no else.
/* Probably collect newInstances for some classes. */
if (this.environment.hasIsNewClasses()) {
Set<String> isNewClasses = this.environment.getIsNewClasses();
for (String aClassName : isNewClasses) {
aspectTemplate.setAttribute("isNewClasses", aClassName);
}
}
// no else.
NamedElement constrainedClass = constrainedOperation.getOwner();
String operationName = constrainedOperation.getName();
String operationResultType = this.transformType(
constrainedOperation.getType()).toString();
/* Create Template for the advice code. */
ITemplate adviceTemplate = this.templateGroup
.getTemplate("postInstrumentation");
/* Set template parameters. */
adviceTemplate.setAttribute("class", constrainedClass.getName());
adviceTemplate.setAttribute("package", contextPackage);
adviceTemplate.setAttribute("constCode", constrainedCode.getCode());
adviceTemplate.setAttribute("constExp", constrainedCode.getResultExp());
adviceTemplate.setAttribute("oclBody", constraint.getSpecification()
.getBody().trim().replaceAll("\r\n", " ").replaceAll("\r", " ")
.replaceAll("\n", " "));
adviceTemplate.setAttribute("method", operationName);
adviceTemplate.setAttribute("errorCode",
this.settings.getViolationMacro(constraint));
/* Probably set the returnType. */
if (!operationResultType.equals(this.templateGroup.getTemplate(
"voidType").toString())) {
adviceTemplate.setAttribute("returnType", operationResultType);
}
// no else.
/* Probably set the arguments of the operation. */
this.setArgumentsForInstrumentationTemplate(constraint, adviceTemplate);
/* Probably store some atPre values */
if (this.environment.hasAtPreValues()) {
Map<ITransformedCode, Object[]> atPreValues = this.environment
.getAtPreValues();
Set<ITransformedCode> valueCodes = atPreValues.keySet();
Set<String> atPreTypes = new HashSet<String>();
for (ITransformedCode aValueCode : valueCodes) {
Object[] typeAndName = atPreValues.get(aValueCode);
Type aType = (Type) typeAndName[0];
String transformedType = this.transformInitializableType(aType)
.toString();
/*
* The atPre values for primitive and collection types are
* initialized different from user defined types.
*/
if (aType instanceof PrimitiveType
|| aType instanceof CollectionType) {
adviceTemplate.setAttribute("primitiveAtPreCodes",
aValueCode.getCode());
adviceTemplate.setAttribute("primitiveAtPreExps",
aValueCode.getResultExp());
adviceTemplate.setAttribute("primitiveAtPreTypes",
transformedType);
adviceTemplate.setAttribute("primitiveAtPreVars",
typeAndName[1].toString());
}
else {
adviceTemplate.setAttribute("atPreCodes",
aValueCode.getCode());
adviceTemplate.setAttribute("atPreExps",
aValueCode.getResultExp());
adviceTemplate.setAttribute("atPreTypes", transformedType);
adviceTemplate.setAttribute("atPreVars",
typeAndName[1].toString());
/*
* Collect the types to provide user defined copy methods.
*/
atPreTypes.add(transformedType);
}
}
// end for.
/* Add initialization methods for the atPreTypes. */
for (String aType : atPreTypes) {
adviceTemplate.setAttribute("atPreTypeSet", aType);
}
}
// no else.
/* Probably use the special OCL operation oclIsNew. */
if (this.environment.hasIsNewClasses()) {
adviceTemplate.setAttribute("oclIsNewUsed", "true");
}
// no else.
/* Probably disable inheritance for this post condition. */
if (this.settings.isInheritanceDisabled(constraint)) {
adviceTemplate.setAttribute("disableInheritance", "true");
}
// no else.
/* Probably set that the constraint operation is static. */
if (constrainedOperation.isStatic()) {
adviceTemplate.setAttribute("opIsStatic", "true");
}
// no else.
/* Probably set that the constrained operation is a constructor. */
if (operationName.equals(constrainedClass.getName())) {
adviceTemplate.setAttribute("opIsConstructor", "true");
}
// no else.
/* Add the advice code to the aspect template. */
aspectTemplate.setAttribute("advice", adviceTemplate.toString());
result = aspectTemplate.toString();
/* Probably save the generated Code. */
if (this.settings.isSaveCode()) {
this.saveTransformedCode(result, aspectName + ".aj",
this.getConstraintPackage(contextPackage));
}
// no else.
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForPost(Constraint)"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Generates an Aspect for the instrumentation of preconditions.
* </p>
*
* @param constraint
* The {@link Constraint} which shall be instrumented.
*/
protected String instrumentCodeForPre(Constraint constraint)
throws Ocl2CodeException {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForPre(Constraint) - start");
}
// no else.
String result;
/* Get the constrained operation. */
Operation constrainedOperation = ((Operation) constraint
.getConstrainedElement().get(0));
ITemplate aspectTemplate = this.templateGroup.getTemplate("aspectFile");
/* Get the path of the package where the constraint class is located. */
String contextPackage = this.getPackagePath(constraint);
aspectTemplate.setAttribute("package",
this.getConstraintPackage(contextPackage));
/* Compute the aspect's file name. */
String className = constrainedOperation.getOwner().getName();
String aspectName = className + "_"
+ Ocl2JavaEnvironment.PRE_ASPECT_NAME + "_"
+ constrainedOperation.getName();
if (this.environment.isUsedAspectName(aspectName))
aspectName = className + "_"
+ this.environment.getNewPreAspectName();
// no else.
this.environment.addUsedAspectName(aspectName);
aspectTemplate.setAttribute("name", aspectName);
/* Generate the code which shall be inside the advice(s). */
this.environment.pushExpectedReturnType(EssentialOclPlugin
.getOclLibraryProvider().getOclLibrary().getOclBoolean());
ITransformedCode constrainedCode = this
.transformFragmentCode(constraint);
this.environment.popExpectedReturnType();
/* Probably collect allInstances for some classes. */
if (this.environment.hasAllInstancesClasses()) {
Set<String> allInstancesClasses;
allInstancesClasses = this.environment.getAllInstancesClasses();
for (String aClassName : allInstancesClasses) {
aspectTemplate.setAttribute("allInstanceClasses", aClassName);
}
}
// no else.
NamedElement constrainedClass = constrainedOperation.getOwner();
String operationName = constrainedOperation.getName();
String operationResultType = this.transformType(
constrainedOperation.getType()).toString();
/* Create Template for the advice code. */
ITemplate adviceTemplate = this.templateGroup
.getTemplate("preInstrumentation");
/* Set template parameters. */
adviceTemplate.setAttribute("class", constrainedClass.getName());
adviceTemplate.setAttribute("package", contextPackage);
adviceTemplate.setAttribute("constCode", constrainedCode.getCode());
adviceTemplate.setAttribute("constExp", constrainedCode.getResultExp());
adviceTemplate.setAttribute("oclBody", constraint.getSpecification()
.getBody().trim().replaceAll("\r\n", " ").replaceAll("\r", " ")
.replaceAll("\n", " "));
adviceTemplate.setAttribute("method", operationName);
adviceTemplate.setAttribute("errorCode",
this.settings.getViolationMacro(constraint));
/* Probably set the returnType. */
if (!operationResultType.equals(this.templateGroup.getTemplate(
"voidType").toString())) {
adviceTemplate.setAttribute("returnType", operationResultType);
}
// no else.
/* Probably set the arguments of the operation. */
this.setArgumentsForInstrumentationTemplate(constraint, adviceTemplate);
/* Probably disable inheritance for this post condition. */
if (this.settings.isInheritanceDisabled(constraint)) {
adviceTemplate.setAttribute("disableInheritance", "true");
}
// no else.
/* Probably set that the constraint operation is static. */
if (constrainedOperation.isStatic()) {
adviceTemplate.setAttribute("opIsStatic", "true");
}
// no else.
/* Probably set that the constrained operation is a constructor. */
if (operationName.equals(constrainedClass.getName())) {
adviceTemplate.setAttribute("opIsConstructor", "true");
}
// no else.
/* Add the advice code to the aspect template. */
aspectTemplate.setAttribute("advice", adviceTemplate.toString());
result = aspectTemplate.toString();
/* Probably save the generated Code. */
if (this.settings.isSaveCode()) {
this.saveTransformedCode(result, aspectName + ".aj",
this.getConstraintPackage(contextPackage));
}
// no else.
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("instrumentCodeForPre(Constraint)"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* A helper method which saves a given generated code into a given file name
* at a given location.
* </p>
*
* @param generatedCode
* The code which shall be saved.
* @param fileName
* The name of the File into which the transformed code shall be
* saved.
* @param subFolder
* The subFolder(s) into which the File shall be located
* (relative) to the sourcePath.
* @throws Ocl2CodeException
* Thrown if the given file or location can not be found.
*/
protected void saveTransformedCode(String generatedCode, String fileName,
String subFolder) throws Ocl2CodeException {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("saveTransformedCode(String, String, String)");
}
// no else.
try {
/* Replace all '.' with '/'. Does not work with String#replaceAll. */
String[] directories = subFolder.split("\\.");
subFolder = "";
for (int i = 0; i < directories.length; i++) {
subFolder += directories[i] + "/";
}
File outputFolder = new File(this.settings.getSourceDirectory()
+ subFolder);
/* Check if output folder does exists. */
if (!outputFolder.isDirectory()) {
outputFolder.mkdirs();
}
// no else.
File outputFile = new File(outputFolder.getAbsolutePath() + "/"
+ fileName);
/* Create the output file. */
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
fileOutputStream.write(generatedCode.getBytes());
fileOutputStream.close();
}
catch (FileNotFoundException e) {
String msg;
msg = "File for saving generated code not found. ";
msg += "File location was ";
msg += this.settings.getSourceDirectory() + fileName + ".";
LOGGER.fatal(msg);
throw new Ocl2CodeException(msg);
}
catch (IOException e) {
String msg;
msg = "Opening of File for saving failed. ";
msg += "File location was ";
msg += this.settings.getSourceDirectory() + fileName + ".";
LOGGER.fatal(msg);
throw new Ocl2CodeException(msg);
}
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("saveTransformedCode(String, String, String) - end");
}
// no else.
}
/**
* <p>
* Sets the argument names and {@link Type}s of a given {@link Constraint}
* for its instrumentation template.
* </p>
*
* @param constraint
* The {@link Constraint} for that the arguments shall be set.
* @param adviceTemplate
* The {@link ITemplate} to set the names and {@link Type}s.
*/
private void setArgumentsForInstrumentationTemplate(Constraint constraint,
ITemplate adviceTemplate) {
for (Variable anArgument : ((ExpressionInOcl) constraint
.getSpecification()).getParameter()) {
String anArgumentsName;
String anArgumentsType;
anArgumentsName = anArgument.getName();
if (this.environment.existsMappingForVariable(anArgumentsName))
anArgumentsName = this.environment
.getVariableMapping(anArgumentsName);
// no else.
anArgumentsType = this.transformType(anArgument.getType())
.toString();
adviceTemplate.setAttribute("args", anArgumentsName);
adviceTemplate.setAttribute("argTypes", anArgumentsType);
}
// end for.
}
/**
* <p>
* Transforms a given {@link CollectionType} into an
* {@link ITransformedType}.
* </p>
*
* @param aCollectionType
* The {@link CollectionType} for which code shall be returned.
* @return The code for a given {@link CollectionType}.
*/
private ITransformedType transformCollectionType(
CollectionType aCollectionType) {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformCollectionType(CollectionType) - start");
}
// no else.
ITransformedType result = null;
ITemplate template = null;
if (aCollectionType instanceof BagType) {
template = this.templateGroup.getTemplate("bagType");
}
else if (aCollectionType instanceof OrderedSetType) {
template = this.templateGroup.getTemplate("orderedSetType");
}
else if (aCollectionType instanceof SequenceType) {
template = this.templateGroup.getTemplate("sequenceType");
}
else if (aCollectionType instanceof SetType) {
template = this.templateGroup.getTemplate("setType");
}
else {
template = this.templateGroup.getTemplate("collectionType");
}
// no else.
if (template != null) {
result = new TransformedTypeImpl(template.toString());
}
// no else.
/* Get the generic type of the Collection. */
Type elementType = aCollectionType.getElementType();
/* Set the generic type, if it is not null. */
if (elementType != null && result != null) {
ITransformedType elementTypeInJava;
elementTypeInJava = this.transformType(elementType);
if (!elementTypeInJava.equals("null"))
result.setGenericType(elementTypeInJava);
// no else.
}
// no else.
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformCollectionType(CollectionType)"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* This method transforms the fragment code for a given {@link Constraint}.
* </p>
*
* @param aConstraint
* The {@link Constraint} for which code shall be transformed.
* @return An {@link ITransformedCode} containing the Code transformed for
* the given {@link Constraint}'s {@link OclExpression}.
* @throws Ocl2CodeException
*/
protected ITransformedCode transformFragmentCode(Constraint aConstraint)
throws Ocl2CodeException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformFragmentCode(Constraint) - start");
}
// no else.
Expression anExpression = aConstraint.getSpecification();
ITransformedCode result = this.doSwitch(anExpression);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformFragmentCode(Constraint)"
+ " - end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Transforms the given {@link CollectionType} into a Java class that can be
* initialized.
* </p>
*
* @param aCollectionType
* The {@link CollectionType} for which code shall be returned.
* @return The {@link ITransformedType} for a given {@link CollectionType}.
*/
private ITransformedType transformInitializableCollectionType(
CollectionType aCollectionType) {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformInitializableCollectionType(CollectionType) - start");
}
// no else.
ITransformedType result = null;
ITemplate template = null;
if (aCollectionType instanceof BagType) {
template = this.templateGroup.getTemplate("bagTypeInitialization");
}
else if (aCollectionType instanceof OrderedSetType) {
template = this.templateGroup
.getTemplate("orderedSetTypeInitialization");
}
else if (aCollectionType instanceof SequenceType) {
template = this.templateGroup
.getTemplate("sequenceTypeInitialization");
}
else if (aCollectionType instanceof SetType) {
template = this.templateGroup.getTemplate("setTypeInitialization");
}
else {
template = this.templateGroup
.getTemplate("collectionTypeInitialization");
}
// no else.
if (template != null) {
result = new TransformedTypeImpl(template.toString());
}
// no else.
/* Get the generic type of the Collection. */
Type elementType = aCollectionType.getElementType();
/* Set the generic type, if it is not null. */
if (elementType != null && result != null) {
ITransformedType elementTypeInJava = this
.transformType(elementType);
if (!elementTypeInJava.equals("null")) {
result.setGenericType(elementTypeInJava);
}
// no else.
}
// no else.
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformInitializableCollectionType(CollectionType)"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Transforms the {@link Type} into a java class that can be instantiated.
* </p>
*
* @param aType
* The {@link Type} for which code shall be returned.
* @return The code for a given {@link Type}.
*/
protected ITransformedType transformInitializableType(Type aType) {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformInitializableType(Type) - start");
}
// no else.
ITransformedType result;
if (aType instanceof AnyType) {
result = new TransformedTypeImpl(this.templateGroup.getTemplate(
"anyType").toString());
}
else if (aType instanceof CollectionType) {
result = this
.transformInitializableCollectionType((CollectionType) aType);
}
else if (aType instanceof Enumeration) {
result = new TransformedTypeImpl(this.templateGroup.getTemplate(
"enumerationType").toString());
}
else if (aType instanceof InvalidType) {
result = new TransformedTypeImpl(this.templateGroup.getTemplate(
"invalidType").toString());
}
else if (aType instanceof PrimitiveType) {
result = this.transformPrimitiveType((PrimitiveType) aType);
}
else if (aType instanceof TupleType) {
result = new TransformedTypeImpl(this.templateGroup.getTemplate(
"tupleType").toString());
}
else if (aType instanceof TypeType) {
result = new TransformedTypeImpl(this.templateGroup.getTemplate(
"typeType").toString());
}
else if (aType instanceof VoidType) {
result = new TransformedTypeImpl(this.templateGroup.getTemplate(
"voidType").toString());
}
else {
/*
* For other types return their canonical name as type (these are
* model-defined types).
*/
result = new TransformedTypeImpl(this.getCanonicalName(aType));
}
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformInitializableType(Type)"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Transforms instrumentation code for a given {@link Constraint}.
* </p>
*
* @param aConstraint
* The {@link Constraint} for which the code shall be
* transformed.
* @return The transformed Code for the given {@link Constraint}.
* @throws Ocl2CodeException
* Thrown, if an unknown or illegal Type or Expression is found
* during code transformation.
*/
protected String transformInstrumentationCode(Constraint aConstraint)
throws Ocl2CodeException {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformInstrumentationCode(Constraint) - start");
}
// no else.
String result;
/*
* Each constraint code use local variables. Thus the counters for
* generated variables in the Environment can be reseted.
*/
this.environment.resetEnvironmentForNextConstraint();
/* Detect the kind of Constraint and transform its instrumentation code. */
switch (aConstraint.getKind()) {
case DEFINITION:
result = this.instrumentCodeForDef(aConstraint);
break;
case DERIVED:
result = this.instrumentCodeForDerive(aConstraint);
break;
case INITIAL:
result = this.instrumentCodeForInit(aConstraint);
break;
case BODY:
result = this.instrumentCodeForBody(aConstraint);
break;
case INVARIANT:
result = this.instrumentCodeForInv(aConstraint);
break;
case PRECONDITION:
result = this.instrumentCodeForPre(aConstraint);
break;
case POSTCONDITION:
result = this.instrumentCodeForPost(aConstraint);
break;
default:
String msg = "An unknown or unsupported kind of Constraint was found. ";
msg += "Found Kind was ";
msg += aConstraint.getKind() + ".";
LOGGER.fatal(msg);
throw new Ocl2CodeException(msg);
}
// end switch.
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformInstrumentationCode(Constraint"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Transforms a given {@link PrimitiveType} into an {@link ITransformedType}
* .
* </p>
*
* @param aPrimitiveType
* The {@link PrimitiveType} for which code shall be returned.
* @return The {@link ITransformedType} for a given {@link PrimitiveType}.
*/
private ITransformedType transformPrimitiveType(PrimitiveType aPrimitiveType) {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformPrimitiveType(PrimitiveType) - start");
}
// no else.
ITransformedType result = null;
ITemplate template = null;
switch (aPrimitiveType.getKind()) {
case BOOLEAN:
template = this.templateGroup.getTemplate("booleanType");
break;
case INTEGER:
template = this.templateGroup.getTemplate("integerType");
break;
case REAL:
template = this.templateGroup.getTemplate("realType");
break;
case STRING:
template = this.templateGroup.getTemplate("stringType");
break;
case VOID:
template = this.templateGroup.getTemplate("voidType");
break;
default:
template = this.templateGroup.getTemplate("unknownType");
}
// end switch.
result = new TransformedTypeImpl(template.toString());
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformPrimitiveType(PrimitiveType)"
+ "- end - return value=" + result);
}
// no else.
return result;
}
/**
* <p>
* Transforms a given {@link Type} into an {@link ITransformedType}.
* </p>
*
* @param aType
* The {@link Type} for which code shall be returned.
* @return The {@link ITransformedType} for a given {@link Type}.
*/
protected ITransformedType transformType(Type aType) {
/* Probably log the entry into this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformType(Type) - start");
}
// no else.
ITransformedType result;
if (this.cachedTransformedTypes.containsKey(aType)) {
result = this.cachedTransformedTypes.get(aType);
}
else {
if (aType instanceof AnyType) {
result = new TransformedTypeImpl(this.templateGroup
.getTemplate("anyType").toString());
}
else if (aType instanceof CollectionType) {
result = this.transformCollectionType((CollectionType) aType);
}
else if (aType instanceof Enumeration) {
result = new TransformedTypeImpl(this.templateGroup
.getTemplate("enumerationType").toString());
}
else if (aType instanceof InvalidType) {
result = new TransformedTypeImpl(this.templateGroup
.getTemplate("invalidType").toString());
}
else if (aType instanceof PrimitiveType) {
result = this.transformPrimitiveType((PrimitiveType) aType);
}
else if (aType instanceof TupleType) {
result = new TransformedTypeImpl(this.templateGroup
.getTemplate("tupleType").toString());
}
else if (aType instanceof TypeType) {
result = new TransformedTypeImpl(this.templateGroup
.getTemplate("typeType").toString());
}
else if (aType instanceof VoidType) {
result = new TransformedTypeImpl(this.templateGroup
.getTemplate("voidType").toString());
}
else {
/*
* For other types return their canonical name as type (used to
* handle model-defined types).
*/
String typeName = this.getCanonicalName(aType);
result = new TransformedTypeImpl(typeName);
}
/* Cache the result. */
this.cachedTransformedTypes.put(aType, result);
}
/* Probably log the exit from this method. */
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("transformType(Type)" + "- end - return value="
+ result);
}
// no else.
return result;
}
}