| /** |
| * <copyright> |
| * |
| * Copyright (c) 2007 IBM 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: |
| * IBM - Initial API and implementation |
| * |
| * </copyright> |
| * |
| * $Id: UMLEnvironmentTest.java,v 1.3 2007/10/16 20:30:32 cdamus Exp $ |
| */ |
| |
| package org.eclipse.ocl.uml.tests; |
| |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import junit.framework.Test; |
| import junit.framework.TestSuite; |
| |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.ocl.Environment; |
| import org.eclipse.ocl.EnvironmentFactory; |
| import org.eclipse.ocl.EvaluationEnvironment; |
| import org.eclipse.ocl.uml.OCL; |
| import org.eclipse.ocl.uml.UMLEnvironment; |
| import org.eclipse.ocl.uml.UMLEnvironmentFactory; |
| import org.eclipse.ocl.uml.UMLEvaluationEnvironment; |
| import org.eclipse.uml2.uml.CallOperationAction; |
| import org.eclipse.uml2.uml.Class; |
| import org.eclipse.uml2.uml.Classifier; |
| import org.eclipse.uml2.uml.Comment; |
| import org.eclipse.uml2.uml.Constraint; |
| import org.eclipse.uml2.uml.EnumerationLiteral; |
| import org.eclipse.uml2.uml.InstanceSpecification; |
| import org.eclipse.uml2.uml.Operation; |
| import org.eclipse.uml2.uml.Package; |
| import org.eclipse.uml2.uml.Parameter; |
| import org.eclipse.uml2.uml.Property; |
| import org.eclipse.uml2.uml.SendSignalAction; |
| import org.eclipse.uml2.uml.State; |
| import org.eclipse.uml2.uml.UMLFactory; |
| import org.eclipse.uml2.uml.UMLPackage; |
| |
| /** |
| * Tests the {@link UMLEnvironment} class. |
| * |
| * @author Christian W. Damus (cdamus) |
| */ |
| public class UMLEnvironmentTest |
| extends AbstractTestSuite { |
| |
| public UMLEnvironmentTest(String name) { |
| super(name); |
| } |
| |
| public static Test suite() { |
| return new TestSuite(UMLEnvironmentTest.class, "UML Environment Tests"); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Tests extensibility of the OCL Ecore environment. |
| */ |
| public void test_extensibility_156360() { |
| OCL ocl = OCL.newInstance(new MyEnvironmentFactory()); |
| |
| OCL.Helper helper = ocl.createOCLHelper(); |
| helper.setContext(getUMLString()); |
| |
| Constraint constraint = null; |
| |
| try { |
| constraint = helper.createInvariant( |
| "self.regexMatch('\\d{3}-\\d{3}-\\d{3}') <> null"); //$NON-NLS-1$ |
| } catch (Exception e) { |
| fail("Failed to parse: " + e.getLocalizedMessage()); //$NON-NLS-1$ |
| } |
| |
| assertTrue(ocl.check("123-456-789", constraint)); //$NON-NLS-1$ |
| assertFalse(ocl.check("123-4567-890", constraint)); //$NON-NLS-1$ |
| assertFalse(ocl.check("123-abc-456", constraint)); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Tests the instance-model evaluation mode. |
| */ |
| public void test_evaluationMode_instanceModel_194390() { |
| UMLEnvironmentFactory factory = new UMLEnvironmentFactory(resourceSet); |
| factory.setEvaluationMode(UMLEnvironmentFactory.EvaluationMode.INSTANCE_MODEL); |
| |
| OCL ocl = OCL.newInstance(factory); |
| |
| OCL.Helper helper = ocl.createOCLHelper(); |
| helper.setContext(getMetaclass("Element")); //$NON-NLS-1$ |
| |
| Constraint constraint = null; |
| |
| try { |
| constraint = helper.createInvariant( |
| "self.oclIsKindOf(InstanceSpecification)"); //$NON-NLS-1$ |
| } catch (Exception e) { |
| fail("Failed to parse: " + e.getLocalizedMessage()); //$NON-NLS-1$ |
| } |
| |
| InstanceSpecification instance1 = (InstanceSpecification) fruitPackage.createPackagedElement( |
| null, UMLPackage.Literals.INSTANCE_SPECIFICATION); |
| instance1.getClassifiers().add(apple); |
| |
| try { |
| // if we had treated this as an EObject (not an InstanceSpecification) |
| // then this would have checked true |
| assertFalse(ocl.check(instance1, constraint)); |
| |
| instance1.getClassifiers().add(getMetaclass("InstanceSpecification")); //$NON-NLS-1$ |
| |
| // now we really are an instance of InstanceSpecification |
| assertTrue(ocl.check(instance1, constraint)); |
| } finally { |
| // clean up |
| instance1.destroy(); |
| } |
| } |
| |
| /** |
| * Tests the Java-EObjects evaluation mode. |
| */ |
| public void test_evaluationMode_runtimeObjects_194390() { |
| UMLEnvironmentFactory factory = new UMLEnvironmentFactory(resourceSet); |
| factory.setEvaluationMode(UMLEnvironmentFactory.EvaluationMode.RUNTIME_OBJECTS); |
| |
| OCL ocl = OCL.newInstance(factory); |
| |
| OCL.Helper helper = ocl.createOCLHelper(); |
| helper.setContext(getMetaclass("Element")); //$NON-NLS-1$ |
| |
| Constraint constraint1 = null; |
| Constraint constraint2 = null; |
| |
| try { |
| constraint1 = helper.createInvariant( |
| "self.oclIsKindOf(InstanceSpecification)"); //$NON-NLS-1$ |
| constraint2 = helper.createInvariant( |
| "self.oclIsKindOf(ocltest::Apple)"); //$NON-NLS-1$ |
| } catch (Exception e) { |
| fail("Failed to parse: " + e.getLocalizedMessage()); //$NON-NLS-1$ |
| } |
| |
| InstanceSpecification instance1 = (InstanceSpecification) fruitPackage.createPackagedElement( |
| null, UMLPackage.Literals.INSTANCE_SPECIFICATION); |
| instance1.getClassifiers().add(apple); |
| |
| try { |
| // now we really are an instance of InstanceSpecification |
| assertTrue(ocl.check(instance1, constraint1)); |
| |
| // if we had treated this as an InstanceSpecification (not an EObject) |
| // then this would have checked true |
| assertFalse(ocl.check(instance1, constraint2)); |
| } finally { |
| // clean up |
| instance1.destroy(); |
| } |
| } |
| |
| /** |
| * Tests the adaptive evaluation mode. |
| */ |
| public void test_evaluationMode_adaptive_194390() { |
| UMLEnvironmentFactory factory = new UMLEnvironmentFactory(resourceSet); |
| factory.setEvaluationMode(UMLEnvironmentFactory.EvaluationMode.ADAPTIVE); |
| |
| OCL ocl = OCL.newInstance(factory); |
| |
| OCL.Helper helper = ocl.createOCLHelper(); |
| helper.setContext(getMetaclass("Element")); //$NON-NLS-1$ |
| |
| Constraint constraint = null; |
| |
| try { |
| constraint = helper.createInvariant( |
| "self.oclIsKindOf(InstanceSpecification) or self.owner.oclIsKindOf(InstanceSpecification)"); //$NON-NLS-1$ |
| } catch (Exception e) { |
| fail("Failed to parse: " + e.getLocalizedMessage()); //$NON-NLS-1$ |
| } |
| |
| InstanceSpecification instance1 = (InstanceSpecification) fruitPackage.createPackagedElement( |
| null, UMLPackage.Literals.INSTANCE_SPECIFICATION); |
| instance1.getClassifiers().add(apple); |
| Comment comment = instance1.createOwnedComment(); |
| InstanceSpecification instance2 = (InstanceSpecification) fruitPackage.createPackagedElement( |
| null, UMLPackage.Literals.INSTANCE_SPECIFICATION); |
| instance2.getClassifiers().add(getMetaclass("InstanceSpecification")); //$NON-NLS-1$ |
| |
| try { |
| // adaptive mode handles instance specification (M1 level) when it |
| // happens to be classified by the "InstanceSpecification" metaclass |
| assertTrue(ocl.check(instance2, constraint)); |
| |
| // adaptive mode handles Java instance (M0 level) based on context |
| // being a non-instance-like element |
| assertTrue(ocl.check(comment, constraint)); |
| |
| // adaptive mode does not handle Java instance when it is a |
| // value- or instance-specification (M0 level) |
| assertFalse(ocl.check(instance1, constraint)); |
| } finally { |
| // clean up |
| instance2.destroy(); |
| comment.destroy(); |
| instance1.destroy(); |
| } |
| } |
| |
| // |
| // Framework methods |
| // |
| |
| class MyEnvironment extends UMLEnvironment { |
| Operation regexMatch; |
| |
| // this constructor is used to initialize the root environment |
| MyEnvironment(EPackage.Registry registry, ResourceSet rset) { |
| super(registry, rset); |
| |
| defineCustomOperations(); |
| } |
| |
| // this constructor is used to initialize child environments |
| MyEnvironment(MyEnvironment parent) { |
| super(parent); |
| |
| // get the parent's custom operations |
| regexMatch = parent.regexMatch; |
| } |
| |
| @Override |
| protected void setFactory( |
| EnvironmentFactory<Package, Classifier, Operation, Property, EnumerationLiteral, Parameter, State, CallOperationAction, SendSignalAction, Constraint, Class, EObject> factory) { |
| super.setFactory(factory); |
| } |
| |
| // use the AbstractEnvironment's mechanism for defining "additional operations" |
| // to add our custom operation to OCL's String primitive type |
| private void defineCustomOperations() { |
| // pattern-matching operation |
| regexMatch = UMLFactory.eINSTANCE.createOperation(); |
| regexMatch.setName("regexMatch"); //$NON-NLS-1$ |
| regexMatch.setType(getOCLStandardLibrary().getString()); |
| regexMatch.createOwnedParameter("pattern", getOCLStandardLibrary().getString()); //$NON-NLS-1$ |
| regexMatch.setIsQuery(true); |
| |
| // annotate it so that we will recognize it in the evaluation environment |
| regexMatch.addKeyword("MyEnvironment"); //$NON-NLS-1$ |
| |
| // define it as an additional operation on OCL String |
| addOperation(getOCLStandardLibrary().getString(), regexMatch); |
| } |
| } |
| |
| class MyEvaluationEnvironment extends UMLEvaluationEnvironment { |
| MyEvaluationEnvironment(UMLEnvironmentFactory factory) { |
| super(factory); |
| } |
| |
| MyEvaluationEnvironment( |
| EvaluationEnvironment<Classifier, Operation, Property, Class, EObject> parent) { |
| super(parent); |
| } |
| |
| @Override |
| public Object callOperation(Operation operation, int opcode, Object source, Object[] args) { |
| if (!operation.getKeywords().contains("MyEnvironment")) { //$NON-NLS-1$ |
| // not our custom regex operation |
| return super.callOperation(operation, opcode, source, args); |
| } |
| |
| if ("regexMatch".equals(operation.getName())) { //$NON-NLS-1$ |
| Pattern pattern = Pattern.compile((String) args[0]); |
| Matcher matcher = pattern.matcher((String) source); |
| |
| return matcher.matches()? matcher.group() : null; |
| } |
| |
| throw new UnsupportedOperationException(); // unknown operation |
| } |
| } |
| |
| class MyEnvironmentFactory extends UMLEnvironmentFactory { |
| @Override |
| public MyEnvironment createEnvironment() { |
| MyEnvironment result = new MyEnvironment(getEPackageRegistry(), getResourceSet()); |
| result.setFactory(this); |
| return result; |
| } |
| |
| @Override |
| public Environment<Package, Classifier, Operation, Property, EnumerationLiteral, Parameter, State, CallOperationAction, SendSignalAction, Constraint, Class, EObject> |
| createEnvironment(Environment<Package, Classifier, Operation, Property, EnumerationLiteral, Parameter, State, CallOperationAction, SendSignalAction, Constraint, Class, EObject> parent) { |
| if (!(parent instanceof MyEnvironment)) { |
| throw new IllegalArgumentException( |
| "Parent environment must be my environment: " + parent); //$NON-NLS-1$ |
| } |
| |
| MyEnvironment result = new MyEnvironment((MyEnvironment) parent); |
| result.setFactory(this); |
| return result; |
| } |
| |
| @Override |
| public EvaluationEnvironment<Classifier, Operation, Property, Class, EObject> |
| createEvaluationEnvironment() { |
| return new MyEvaluationEnvironment(this); |
| } |
| |
| @Override |
| public EvaluationEnvironment<Classifier, Operation, Property, Class, EObject> |
| createEvaluationEnvironment( |
| EvaluationEnvironment<Classifier, Operation, Property, Class, EObject> parent) { |
| return new MyEvaluationEnvironment(parent); |
| } |
| |
| |
| } |
| } |