| /* |
| * Copyright (c) 2007, 2010 Borland Software Corporation and others |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Dmitry Stadnik (Borland) - initial API and implementation |
| */ |
| |
| «IMPORT 'http://www.eclipse.org/gmf/2009/GenModel'» |
| |
| «DEFINE OCLExpressionFactory FOR gmfgen::GenExpressionInterpreter-» |
| «EXPAND xpt::Common::copyright FOR container.editorGen-» |
| package «container.expressionsPackageName»; |
| |
| «EXPAND xpt::Common::generatedClassComment» |
| public class «className» { |
| |
| «EXPAND _initInterpreterFactory» |
| |
| «EXPAND xpt::Common::generatedMemberComment» |
| public static «container.getAbstractExpressionQualifiedClassName()» getExpression(String body, org.eclipse.emf.ecore.EClassifier context, java.util.Map«EXPAND CodeStyle::G2('String', 'org.eclipse.emf.ecore.EClassifier') FOR container.editorGen.diagram» environment) { |
| return new Expression(body, context, environment); |
| } |
| |
| «EXPAND xpt::Common::generatedMemberComment('This method will become private in the next release')»«REM»FIXME private or completely remove in the next release «ENDREM» |
| public static «container.getAbstractExpressionQualifiedClassName()» getExpression(String body, org.eclipse.emf.ecore.EClassifier context) { |
| return getExpression(body, context, «EXPAND CodeStyle::emptyMap('String, org.eclipse.emf.ecore.EClassifier') FOR container.editorGen.diagram»); |
| } |
| |
| «EXPAND xpt::Common::generatedMemberComment» |
| private static class Expression extends «container.getAbstractExpressionQualifiedClassName()» { |
| |
| «EXPAND xpt::Common::generatedMemberComment» |
| private final org.eclipse.ocl.ecore.OCL oclInstance; |
| |
| «EXPAND xpt::Common::generatedMemberComment» |
| private org.eclipse.ocl.ecore.OCLExpression oclExpression; |
| |
| «EXPAND xpt::Common::generatedMemberComment» |
| public Expression(String body, org.eclipse.emf.ecore.EClassifier context, java.util.Map«EXPAND CodeStyle::G2('String', 'org.eclipse.emf.ecore.EClassifier') FOR container.editorGen.diagram» environment) { |
| super(body, context); |
| oclInstance = org.eclipse.ocl.ecore.OCL.newInstance(); |
| initCustomEnv(oclInstance.getEnvironment(), environment); |
| «REM» |
| I've moved expression initialization right into constructor because: |
| - Caching and weak references done at the caller are more effective for this usecase (we have an instance/static field to reference this Expression anyway) |
| - Expression's status is known right away, not only after protected getQuery get invoked |
| «ENDREM»«-» |
| org.eclipse.ocl.ecore.OCL.Helper oclHelper = oclInstance.createOCLHelper(); |
| oclHelper.setContext(context()); |
| try { |
| oclExpression = oclHelper.createQuery(body()); |
| setStatus(org.eclipse.core.runtime.IStatus.OK, null, null); |
| } catch (org.eclipse.ocl.ParserException e) { |
| setStatus(org.eclipse.core.runtime.IStatus.ERROR, e.getMessage(), e); |
| } |
| } |
| |
| «EXPAND xpt::Common::generatedMemberComment» |
| «EXPAND CodeStyle::SuppressWarnings('"rawtypes"') FOR container.editorGen.diagram-» |
| protected Object doEvaluate(Object context, java.util.Map env) { |
| if (oclExpression == null) { |
| return null; |
| } |
| // on the first call, both evalEnvironment and extentMap are clear, for later we have finally, below. |
| org.eclipse.ocl.EvaluationEnvironment«EXPAND CodeStyle::G('?,?,?,?,?') FOR container.editorGen.diagram» evalEnv = oclInstance.getEvaluationEnvironment(); |
| // initialize environment«REM»Using Object below because Map env comes as raw type, and Object(unlike String) works fine for both Iterator<Type> = iterable.iterator() and for (Type a : iterable) code styles «ENDREM» |
| «EXPAND CodeStyle::iterate('nextKey', 'Object', 'env.keySet()') FOR container.editorGen.diagram-» |
| evalEnv.replace((String) nextKey, env.get(nextKey)); |
| } |
| try { |
| Object result = oclInstance.evaluate(context, oclExpression); |
| return oclInstance.isInvalid(result) ? null : result; |
| } finally { |
| evalEnv.clear(); |
| oclInstance.setExtentMap(null); // clear allInstances cache, and get the oclInstance ready for the next call |
| } |
| } |
| |
| «EXPAND xpt::Common::generatedMemberComment» |
| private static void initCustomEnv(org.eclipse.ocl.Environment«EXPAND CodeStyle::G('?,org.eclipse.emf.ecore.EClassifier,?,?,?,org.eclipse.emf.ecore.EParameter,?,?,?,?,?,?') FOR container.editorGen.diagram» ecoreEnv, java.util.Map«EXPAND CodeStyle::G2('String', 'org.eclipse.emf.ecore.EClassifier') FOR container.editorGen.diagram» environment) { |
| «EXPAND initializeEnvironment('ecoreEnv')-» |
| «EXPAND CodeStyle::iterate('varName', 'String', 'environment.keySet()') FOR container.editorGen.diagram-» |
| org.eclipse.emf.ecore.EClassifier varType = «EXPAND CodeStyle::castTyped('org.eclipse.emf.ecore.EClassifier') FOR container.editorGen.diagram»environment.get(varName); |
| ecoreEnv.addElement(varName, createVar(ecoreEnv, varName, varType), false); |
| } |
| } |
| |
| «EXPAND xpt::Common::generatedMemberComment» |
| private static org.eclipse.ocl.ecore.Variable createVar(org.eclipse.ocl.Environment«EXPAND CodeStyle::G('?,org.eclipse.emf.ecore.EClassifier,?,?,?,?,?,?,?,?,?,?') FOR container.editorGen.diagram» ecoreEnv, String name, org.eclipse.emf.ecore.EClassifier type) { |
| org.eclipse.ocl.ecore.Variable var = org.eclipse.ocl.ecore.EcoreFactory.eINSTANCE.createVariable(); |
| var.setName(name); |
| var.setType(«EXPAND CodeStyle::castTyped('org.eclipse.emf.ecore.EClassifier') FOR container.editorGen.diagram»ecoreEnv.getUMLReflection().getOCLType(type)); |
| return var; |
| } |
| } |
| «EXPAND additions-» |
| } |
| «ENDDEFINE» |
| |
| «REM» |
| Clients may override if they don't need |
| «ENDREM» |
| «DEFINE initializeEnvironment(String environmentVar) FOR gmfgen::GenExpressionInterpreter-» |
| // Use EObject as implicit root class for any object, to allow eContainer() and other EObject operations from OCL expressions |
| org.eclipse.ocl.options.ParsingOptions.setOption(«environmentVar», org.eclipse.ocl.options.ParsingOptions.implicitRootClass(«environmentVar»), org.eclipse.emf.ecore.EcorePackage.eINSTANCE.getEObject()); |
| «ENDDEFINE» |
| |
| «DEFINE additions FOR gmfgen::GenExpressionInterpreter»«ENDDEFINE» |
| |
| // just to avoid identical piece of template in the RegexpExpressionFactory |
| «DEFINE _initInterpreterFactory FOR gmfgen::GenExpressionInterpreter-» |
| «EXPAND xpt::Common::generatedMemberComment» |
| private final «container.getAbstractExpressionQualifiedClassName()»[] expressions; |
| |
| «EXPAND xpt::Common::generatedMemberComment» |
| protected «className»() { |
| this.expressions = new «container.getAbstractExpressionQualifiedClassName()»[«expressions->size()»]; |
| } |
| |
| «EXPAND xpt::Common::generatedMemberComment» |
| public static «container.getAbstractExpressionQualifiedClassName()» getExpression(int index, org.eclipse.emf.ecore.EClassifier context) { |
| «className» cached = «EXPAND plugin::Activator::instanceAccess FOR container.editorGen».get«className»(); |
| if (cached == null) { |
| «EXPAND plugin::Activator::instanceAccess FOR container.editorGen».set«className»(cached = new «className»()); |
| } |
| if (index < 0 || index >= cached.expressions.length) { |
| throw new IllegalArgumentException(); |
| } |
| if (cached.expressions[index] == null) { |
| final String[] exprBodies = new String[] { |
| «FOREACH expressions.getBodyString() AS b»«b», «EXPAND xpt::Common::nonNLS» |
| «ENDFOREACH-» |
| }; |
| cached.expressions[index] = getExpression(exprBodies[index], context); |
| } |
| return cached.expressions[index]; |
| } |
| «ENDDEFINE» |