blob: 9e77f4d07f74a39b53a91e7ec7657bb09dccd5ed [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2018 IBM Corporation, Zeligsoft Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* IBM - Initial API and implementation
* Zeligsoft - Bug 238050
*******************************************************************************/
package org.eclipse.ocl.uml.tests;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.ocl.Environment;
import org.eclipse.ocl.OCLInput;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.expressions.OCLExpression;
import org.eclipse.ocl.helper.Choice;
import org.eclipse.ocl.helper.ChoiceKind;
import org.eclipse.ocl.helper.ConstraintKind;
import org.eclipse.ocl.internal.l10n.OCLMessages;
import org.eclipse.ocl.options.ParsingOptions;
import org.eclipse.ocl.types.SetType;
import org.eclipse.ocl.uml.OCL;
import org.eclipse.ocl.util.TypeUtil;
import org.eclipse.ocl.utilities.UMLReflection;
import org.eclipse.uml2.uml.CallOperationAction;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Classifier;
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;
/**
* Tests for def expressions (additional properties and operations).
*
* @author Christian W. Damus (cdamus)
*/
@SuppressWarnings("nls")
public class DefExpressionTest
extends AbstractTestSuite {
Resource instanceResource;
Package instancePackage;
/**
* Tests the parsing the def expression for an operation from raw text.
*/
public void test_defExpression_raw_operation() {
try {
OCLExpression<Classifier> expr = parseDef(
"package ocltest context Fruit " +
"def: bestColor(c : Color) : Color = " +
"if self.color = Color::black then c else self.color endif" +
" endpackage");
Constraint constraint = (Constraint) expr.eContainer().eContainer();
assertNotNull(constraint);
assertEquals(UMLReflection.DEFINITION, getStereotype(constraint));
assertSame(color, expr.getType());
expr = parse(
"package ocltest context Fruit " +
"inv: bestColor(Color::red) = Color::red" +
" endpackage");
InstanceSpecification anApple = instantiate(instancePackage, apple);
setValue(anApple, fruit_color, color_black);
assertTrue(ocl.check(anApple, expr));
setValue(anApple, fruit_color, color_green);
assertFalse(ocl.check(anApple, expr));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
/**
* Tests the parsing the def expression for an operation using the helper.
*/
public void test_defExpression_helper_operation() {
helper.setContext(fruit);
try {
helper.defineOperation(
"bestColor(c : Color) : Color = " +
"if self.color = Color::black then c else self.color endif");
Constraint expr = helper.createInvariant(
"bestColor(Color::red) = Color::red");
InstanceSpecification anApple = instantiate(instancePackage, apple);
setValue(anApple, fruit_color, color_black);
assertTrue(ocl.check(anApple, expr));
setValue(anApple, fruit_color, color_green);
assertFalse(ocl.check(anApple, expr));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
/**
* Tests the parsing the def expression for an attribute from raw text.
*/
public void test_defExpression_raw_attribute() {
try {
OCLExpression<Classifier> expr = parseDef(
"package ocltest context Apple " +
"def: fallen : Boolean = tree.oclIsUndefined()" +
" endpackage");
Constraint constraint = (Constraint) expr.eContainer().eContainer();
assertNotNull(constraint);
assertEquals(UMLReflection.DEFINITION, getStereotype(constraint));
assertSame(getOCLStandardLibrary().getBoolean(), expr.getType());
expr = parse(
"package ocltest context Apple " +
"inv: not fallen" +
" endpackage");
InstanceSpecification anApple = instantiate(instancePackage, apple);
setValue(anApple, apple_tree, instantiate(instancePackage, tree));
assertTrue(ocl.check(anApple, expr));
setValue(anApple, apple_tree, null);
assertFalse(ocl.check(anApple, expr));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
/**
* Tests the parsing the def expression for an attribute using the helper.
*/
public void test_defExpression_helper_attribute() {
helper.setContext(apple);
try {
helper.defineAttribute(
"fallen : Boolean = " +
"tree.oclIsUndefined()");
Constraint expr = helper.createInvariant("not fallen");
InstanceSpecification anApple = instantiate(instancePackage, apple);
setValue(anApple, apple_tree, instantiate(instancePackage, tree));
assertTrue(ocl.check(anApple, expr));
setValue(anApple, apple_tree, null);
assertFalse(ocl.check(anApple, expr));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
/**
* Tests the parsing the def expression for a reference from raw text.
*/
public void test_defExpression_raw_reference() {
try {
OCLExpression<Classifier> expr = parseDef(
"package ocltest context Apple " +
"def: otherApples : Set(Apple) = Apple.allInstances()->excluding(self)" +
" endpackage");
Constraint constraint = (Constraint) expr.eContainer().eContainer();
assertNotNull(constraint);
assertEquals(UMLReflection.DEFINITION, getStereotype(constraint));
assertTrue(expr.getType() instanceof SetType<?, ?>);
assertSame(
((org.eclipse.ocl.uml.SetType) expr.getType()).getElementType(),
apple);
expr = parse(
"package ocltest context Apple " +
"inv: self.otherApples" +
" endpackage");
InstanceSpecification anApple = instantiate(instancePackage, apple);
InstanceSpecification anotherApple = instantiate(instancePackage, apple);
Map<Class, Set<InstanceSpecification>> extentMap =
new java.util.HashMap<Class, Set<InstanceSpecification>>();
Set<InstanceSpecification> allApples = new java.util.HashSet<InstanceSpecification>();
allApples.add(anApple);
allApples.add(anotherApple);
extentMap.put(apple, allApples);
ocl.setExtentMap(extentMap);
Object otherApples = ocl.evaluate(anApple, expr);
assertEquals(Collections.singleton(anotherApple), otherApples);
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
public void test_defExpression_inheritance_operation() {
helper.setContext(getMetaclass("Classifier"));
try {
helper.defineOperation(
"oclAllParents() : Set(Classifier) = " +
"self->closure(generalization.general)");
OCLExpression<Classifier> expr = helper.createQuery("self.oclAllParents()");
Object oclAllParents = ocl.evaluate(apple, expr);
assertTrue(oclAllParents instanceof Set<?>);
assertTrue(((Set<?>) oclAllParents).contains(fruit));
oclAllParents = ocl.evaluate(color, expr);
assertTrue(oclAllParents instanceof Set<?>);
assertTrue(((Set<?>) oclAllParents).isEmpty());
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
public void test_defExpression_inheritance_attribute() {
helper.setContext(getMetaclass("Classifier"));
try {
helper.defineAttribute(
"oclAllParents : Set(Classifier) = " +
"self->closure(generalization.general)");
OCLExpression<Classifier> expr = helper.createQuery("self.oclAllParents");
Object oclAllParents = ocl.evaluate(apple, expr);
assertTrue(oclAllParents instanceof Set<?>);
assertTrue(((Set<?>) oclAllParents).contains(fruit));
oclAllParents = ocl.evaluate(color, expr);
assertTrue(oclAllParents instanceof Set<?>);
assertTrue(((Set<?>) oclAllParents).isEmpty());
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
/**
* Tests the parsing the def expression for static attributes and operations.
*/
public void test_defExpression_static() {
try {
Environment<Package, Classifier, Operation, Property, EnumerationLiteral, Parameter, State, CallOperationAction, SendSignalAction, Constraint, Class, EObject> env = ocl.getEnvironment();
UMLReflection<Package, Classifier, Operation, Property, EnumerationLiteral, Parameter, State, CallOperationAction, SendSignalAction, Constraint> umlReflection = env.getUMLReflection();
ParsingOptions.setOption(ocl.getEnvironment(), ParsingOptions.SUPPORT_STATIC_FEATURES, true);
parseDef("package ocltest context Fruit " +
"def: bestColor1() : Color = null " +
"static def: bestColor2() : Color = null " +
"def: goodColor1 : Color = null " +
"static def: goodColor2 : Color = null " +
"endpackage");
Operation operation1 = env.lookupOperation(fruit, "bestColor1", null);
assertNotNull(operation1);
assertEquals(false, umlReflection.isStatic(operation1));
Operation operation2 = env.lookupOperation(fruit, "bestColor2", null);
assertNotNull(operation2);
assertEquals(true, umlReflection.isStatic(operation2));
Property property1 = env.lookupProperty(fruit, "goodColor1");
assertNotNull(property1);
assertEquals(false, umlReflection.isStatic(property1));
Property property2 = env.lookupProperty(fruit, "goodColor2");
assertNotNull(property2);
assertEquals(true, umlReflection.isStatic(property2));
ParsingOptions.setOption(ocl.getEnvironment(), ParsingOptions.SUPPORT_STATIC_FEATURES, false);
try {
ocl.parse(new OCLInput("package ocltest context Fruit " +
"def: bestColor3() : Color = null " +
"static def: bestColor4() : Color = null " +
"endpackage"));
fail("Should have failed to parse the unsupported static");
} catch (ParserException e) {
// success!
assertEquals(OCLMessages.UnsupportedStatic_ERROR_, e.getMessage());
debugPrintln("Got the expected exception: " + e.getLocalizedMessage());
}
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
public void test_malformedDefExpression_attribute() {
helper.setContext(getMetaclass("Classifier"));
try {
// non-conformant expression type
helper.defineAttribute(
"oclAllParents : Set(Classifier) = " +
"self.name");
fail("Should not have parsed");
} catch (Exception e) {
// success
debugPrintln("Got expected error: " + e.getLocalizedMessage());
}
try {
// missing type declaration
helper.defineAttribute(
"myName = " +
"self.name");
fail("Should not have parsed");
} catch (Exception e) {
// success
debugPrintln("Got expected error: " + e.getLocalizedMessage());
}
}
public void test_malformedDefExpression_operation() {
helper.setContext(getMetaclass("Classifier"));
try {
// non-conformant expression type
helper.defineOperation(
"oclAllParents() : Set(Classifier) = " +
"self.name");
fail("Should not have parsed");
} catch (Exception e) {
// success
debugPrintln("Got expected error: " + e.getLocalizedMessage());
}
try {
// missing type declaration
helper.defineOperation(
"bestName(s : String) = " +
"if self.oclIsKindOf(Class) then self.name else s endif");
fail("Should not have parsed");
} catch (Exception e) {
// success
debugPrintln("Got expected error: " + e.getLocalizedMessage());
}
try {
// missing type declaration in parameter
helper.defineOperation(
"bestName(s) : String = " +
"if self.oclIsKindOf(Class) then self.name else s endif");
fail("Should not have parsed");
} catch (Exception e) {
// success
debugPrintln("Got expected error: " + e.getLocalizedMessage());
}
}
public void test_duplicateDefinition_attribute() {
helper.setContext(getMetaclass("Classifier"));
try {
// same name and type as existing property
helper.defineAttribute(
"name : String = " +
"if self.oclIsKindOf(Class) then 'foo' else '' endif");
fail("Should not have parsed");
} catch (Exception e) {
// success
debugPrintln("Got expected error: " + e.getLocalizedMessage());
}
try {
// same name but different type
helper.defineAttribute(
"generalization : Set(String) = " +
"Set{'a', 'b', 'c'}");
fail("Should not have parsed");
} catch (Exception e) {
// success
debugPrintln("Got expected error: " + e.getLocalizedMessage());
}
}
public void test_duplicateDefinition_operation() {
helper.setContext(apple);
try {
// same signature as existing operation (note different param name)
helper.defineOperation(
"preferredLabel(s : String) : String = " +
"if s.oclIsUndefined() then 'foo' else s endif");
fail("Should not have parsed");
} catch (Exception e) {
// success
debugPrintln("Got expected error: " + e.getLocalizedMessage());
}
try {
// same signature as existing operation (note different return type)
helper.defineOperation(
"preferredLabel(s : String) : Integer = " +
"if s.oclIsUndefined() then 0 else s.size() endif");
fail("Should not have parsed");
} catch (Exception e) {
// success
debugPrintln("Got expected error: " + e.getLocalizedMessage());
}
try {
// same name but different signature is OK
helper.defineOperation(
"preferredLabel(text : Integer) : String = " +
"if text > 0 then 'foo' else 'bar' endif");
} catch (Exception e) {
fail("Failed to parse: " + e.getLocalizedMessage());
}
}
public void test_undefine_property_152018() {
helper.setContext(getMetaclass("Classifier"));
Property property = null;
try {
// define some additional property
property = helper.defineAttribute(
"other : Classifier = " +
"if general->notEmpty() then general->asSequence()->first() else null endif");
} catch (Exception e) {
fail("Failed to parse: " + e.getLocalizedMessage());
}
assertNotNull(property);
// now, undefine this property
ocl.getEnvironment().undefine(property);
assertNull(property.eContainer());
assertNull(property.eResource());
try {
// try to define this property again. We should succeed
property = helper.defineAttribute(
"other : Classifier = " +
"if general->notEmpty() then general->asSequence()->first() else null endif");
} catch (Exception e) {
fail("Failed to parse: " + e.getLocalizedMessage());
}
}
public void test_undefine_operation_152018() {
helper.setContext(getMetaclass("Classifier"));
Operation operation = null;
try {
// define some additional property
operation = helper.defineOperation(
"other(x : Integer) : Classifier = " +
"if general->size() >= x then general->asSequence()->at(x) else null endif");
} catch (Exception e) {
fail("Failed to parse: " + e.getLocalizedMessage());
}
assertNotNull(operation);
// now, undefine this operation
ocl.getEnvironment().undefine(operation);
assertNull(operation.eContainer());
assertNull(operation.eResource());
try {
// try to define this property again. We should succeed
operation = helper.defineOperation(
"other(x : Integer) : Classifier = " +
"if general->size() >= x then general->asSequence()->at(x) else null endif");
} catch (Exception e) {
fail("Failed to parse: " + e.getLocalizedMessage());
}
}
public void test_recursive_property_152018() {
helper.setContext(getMetaclass("Classifier"));
Property property = null;
try {
// first, attempt a definition with an invalid body
property = helper.defineAttribute(
"friend : Classifier = " +
"if general->notEmpty() then getNearestPackage() else self endif");
fail("Should not have parsed");
} catch (Exception e) {
// success
debugPrintln("Got expected error: " + e.getLocalizedMessage());
}
try {
// now, attempt a correct definition. This should not find that
// 'other' is already defined, because it should have been
// undefined when we failed to parse, above
property = helper.defineAttribute(
"friend : Classifier = " +
"if general->notEmpty() then general->asSequence()->first().friend else self endif");
} catch (Exception e) {
fail("Failed to parse: " + e.getLocalizedMessage());
}
assertNotNull(property);
try {
// now, attempt to use this additional property
helper.createInvariant(
"not friend.oclIsUndefined() implies friend = self");
} catch (Exception e) {
fail("Failed to parse: " + e.getLocalizedMessage());
}
}
public void test_recursive_operation_152018() {
helper.setContext(getMetaclass("Classifier"));
Operation operation = null;
try {
// first, attempt a definition with an invalid body
operation = helper.defineOperation(
"friend(x : Integer) : Classifier = " +
"if general->size() >= x then getNearestPackage() else self endif");
fail("Should not have parsed");
} catch (Exception e) {
// success
debugPrintln("Got expected error: " + e.getLocalizedMessage());
}
try {
// now, attempt a correct definition. This should not find that
// 'other' is already defined, because it should have been
// undefined when we failed to parse, above
operation = helper.defineOperation(
"friend(x : Integer) : Classifier = " +
"if general->size() >= x then general->asSequence()->at(x).friend(x) else self endif");
} catch (Exception e) {
fail("Failed to parse: " + e.getLocalizedMessage());
}
assertNotNull(operation);
try {
// now, attempt to use this additional property
helper.createInvariant(
"not friend(1).oclIsUndefined() implies friend(1) = self");
} catch (Exception e) {
fail("Failed to parse: " + e.getLocalizedMessage());
}
}
public void test_defExpression_completion_operation() {
helper.setContext(getMetaclass("Classifier"));
try {
helper.defineOperation(
"oclAllParents() : Set(Classifier) = " +
"self->closure(generalization.general)");
Collection<Choice> choices = helper.getSyntaxHelp(
ConstraintKind.INVARIANT, "self.");
assertChoice(choices, ChoiceKind.OPERATION, "oclAllParents");
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
public void test_defExpression_completion_attribute() {
helper.setContext(getMetaclass("Classifier"));
try {
helper.defineAttribute(
"oclAllParents : Set(Classifier) = " +
"self->closure(generalization.general)");
Collection<Choice> choices = helper.getSyntaxHelp(
ConstraintKind.INVARIANT, "self.");
assertChoice(choices, ChoiceKind.PROPERTY, "oclAllParents");
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
/**
* Tests the definition of additional attributes on the metamodel's
* representation of a primitive type for which OCL has a counterpart.
*/
public void test_defAttributeOnPrimitiveType_172782() {
// context is the UML String primitive type
helper.setContext(getUMLString());
try {
Property feature = helper.defineAttribute(
"reverse : String = " +
"Sequence{1..size()}->sortedBy(i | -i)->iterate(i; s : String = '' |" +
" s.concat(self.substring(i, i)))");
// the other representation of 'String'
helper.setContext(ocl.getEnvironment().getOCLStandardLibrary().getString());
Collection<Choice> choices = helper.getSyntaxHelp(
ConstraintKind.INVARIANT, "self.");
assertChoice(choices, ChoiceKind.PROPERTY, "reverse");
OCLExpression<Classifier> expr = helper.createQuery(
"self.reverse");
assertEquals(
"ablE was i ere I saw elbA",
ocl.evaluate("Able was I ere i saw Elba", expr));
// verify that TypeUtil produces the correct result
assertTrue(TypeUtil.getAttributes(ocl.getEnvironment(), ocl.getEnvironment().getOCLStandardLibrary().getString())
.contains(feature));
assertTrue(TypeUtil.getAttributes(ocl.getEnvironment(), getUMLString())
.contains(feature));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
// now, make sure that this definition was local to the OCL that
// parsed it (that it is not shared via the standard library package)
OCL localOCL = OCL.newInstance();
OCL.Helper localHelper = localOCL.createOCLHelper();
localHelper.setContext(ocl.getEnvironment().getOCLStandardLibrary().getString());
try {
Collection<Choice> choices = localHelper.getSyntaxHelp(
ConstraintKind.INVARIANT, "self.");
assertNotChoice(choices, ChoiceKind.PROPERTY, "reverse");
localHelper.createQuery("self.reverse");
fail("Should have failed to parse the undefined attribute");
} catch (ParserException e) {
// success!
debugPrintln("Got the expected exception: " + e.getLocalizedMessage());
}
}
/**
* Tests the definition of additional operations on the metamodel's
* representation of a primitive type for which OCL has a counterpart.
*/
public void test_defOperationOnPrimitiveType_172782() {
// context is the UML String primitive type
helper.setContext(getUMLString());
try {
Operation feature = helper.defineOperation(
"reversed() : String = " +
"Sequence{1..size()}->sortedBy(i | -i)->iterate(i; s : String = '' |" +
" s.concat(self.substring(i, i)))");
// the other representation of 'String'
helper.setContext(ocl.getEnvironment().getOCLStandardLibrary().getString());
Collection<Choice> choices = helper.getSyntaxHelp(
ConstraintKind.INVARIANT, "self.");
assertChoice(choices, ChoiceKind.OPERATION, "reversed");
OCLExpression<Classifier> expr = helper.createQuery(
"self.reversed()");
assertEquals(
"ablE was i ere I saw elbA",
ocl.evaluate("Able was I ere i saw Elba", expr));
// verify that TypeUtil produces the correct result
assertTrue(TypeUtil.getOperations(ocl.getEnvironment(), ocl.getEnvironment().getOCLStandardLibrary().getString())
.contains(feature));
assertTrue(TypeUtil.getOperations(ocl.getEnvironment(), getUMLString())
.contains(feature));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
// now, make sure that this definition was local to the OCL that
// parsed it (that it is not shared via the standard library package)
OCL localOCL = OCL.newInstance();
OCL.Helper localHelper = localOCL.createOCLHelper();
localHelper.setContext(ocl.getEnvironment().getOCLStandardLibrary().getString());
try {
Collection<Choice> choices = localHelper.getSyntaxHelp(
ConstraintKind.INVARIANT, "self.");
assertNotChoice(choices, ChoiceKind.OPERATION, "reversed");
localHelper.createQuery("self.reversed()");
fail("Should have failed to parse the undefined operation");
} catch (ParserException e) {
// success!
debugPrintln("Got the expected exception: " + e.getLocalizedMessage());
}
}
/**
* Tests the definition of additional attributes on an OCL pre-defined type.
*/
public void test_defAttributeOnPredefinedType_172782() {
// context is the predefined OCL String type
helper.setContext(ocl.getEnvironment().getOCLStandardLibrary().getString());
try {
Property feature = helper.defineAttribute(
"reverse : String = " +
"Sequence{1..size()}->sortedBy(i | -i)->iterate(i; s : String = '' |" +
" s.concat(self.substring(i, i)))");
// the other representation of 'String'
helper.setContext(getUMLString());
Collection<Choice> choices = helper.getSyntaxHelp(
ConstraintKind.INVARIANT, "self.");
assertChoice(choices, ChoiceKind.PROPERTY, "reverse");
OCLExpression<Classifier> expr = helper.createQuery(
"self.reverse");
assertEquals(
"ablE was i ere I saw elbA",
ocl.evaluate("Able was I ere i saw Elba", expr));
// verify that TypeUtil produces the correct result
assertTrue(TypeUtil.getAttributes(ocl.getEnvironment(), ocl.getEnvironment().getOCLStandardLibrary().getString())
.contains(feature));
assertTrue(TypeUtil.getAttributes(ocl.getEnvironment(), getUMLString())
.contains(feature));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
// now, make sure that this definition was local to the OCL that
// parsed it (that it is not shared via the standard library package)
OCL localOCL = OCL.newInstance();
OCL.Helper localHelper = localOCL.createOCLHelper();
localHelper.setContext(ocl.getEnvironment().getOCLStandardLibrary().getString());
try {
Collection<Choice> choices = localHelper.getSyntaxHelp(
ConstraintKind.INVARIANT, "self.");
assertNotChoice(choices, ChoiceKind.PROPERTY, "reverse");
localHelper.createQuery("self.reverse");
fail("Should have failed to parse the undefined attribute");
} catch (ParserException e) {
// success!
debugPrintln("Got the expected exception: " + e.getLocalizedMessage());
}
}
/**
* Tests the definition of additional attributes on an OCL pre-defined type.
*/
public void test_defOperationOnPredefinedType_172782() {
// context is the predefined OCL String type
helper.setContext(ocl.getEnvironment().getOCLStandardLibrary().getString());
try {
Operation feature = helper.defineOperation(
"reversed() : String = " +
"Sequence{1..size()}->sortedBy(i | -i)->iterate(i; s : String = '' |" +
" s.concat(self.substring(i, i)))");
// the other representation of 'String'
helper.setContext(getUMLString());
Collection<Choice> choices = helper.getSyntaxHelp(
ConstraintKind.INVARIANT, "self.");
assertChoice(choices, ChoiceKind.OPERATION, "reversed");
OCLExpression<Classifier> expr = helper.createQuery(
"self.reversed()");
assertEquals(
"ablE was i ere I saw elbA",
ocl.evaluate("Able was I ere i saw Elba", expr));
// verify that TypeUtil produces the correct result
assertTrue(TypeUtil.getOperations(ocl.getEnvironment(), ocl.getEnvironment().getOCLStandardLibrary().getString())
.contains(feature));
assertTrue(TypeUtil.getOperations(ocl.getEnvironment(), getUMLString())
.contains(feature));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
// now, make sure that this definition was local to the OCL that
// parsed it (that it is not shared via the standard library package)
OCL localOCL = OCL.newInstance();
OCL.Helper localHelper = localOCL.createOCLHelper();
localHelper.setContext(ocl.getEnvironment().getOCLStandardLibrary().getString());
try {
Collection<Choice> choices = localHelper.getSyntaxHelp(
ConstraintKind.INVARIANT, "self.");
assertNotChoice(choices, ChoiceKind.OPERATION, "reversed");
localHelper.createQuery("self.reversed()");
fail("Should have failed to parse the undefined operation");
} catch (ParserException e) {
// success!
debugPrintln("Got the expected exception: " + e.getLocalizedMessage());
}
}
/**
* Tests that the {@link UMLReflection} API provides the correct owner of an
* additional operation.
*/
public void test_defExpression_operation_owner() {
helper.setContext(fruit);
try {
Operation o = helper.defineOperation(
"bestColor(c : Color) : Color = " +
"if self.color = Color::black then c else self.color endif");
UMLReflection<?, Classifier, ?, ?, ?, ?, ?, ?, ?, ?> uml =
ocl.getEnvironment().getUMLReflection();
// sanity check
assertSame(fruit, uml.getOwningClassifier(fruit_ripen));
// check the owner of the additional operation
assertSame(fruit, uml.getOwningClassifier(o));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
/**
* Tests that the {@link UMLReflection} API provides the correct owner of an
* additional attribute.
*/
public void test_defExpression_attribute_owner() {
helper.setContext(apple);
try {
Property p = helper.defineAttribute(
"fallen : Boolean = " +
"tree.oclIsUndefined()");
UMLReflection<?, Classifier, ?, ?, ?, ?, ?, ?, ?, ?> uml =
ocl.getEnvironment().getUMLReflection();
// sanity check
assertSame(apple, uml.getOwningClassifier(apple_label));
// check the owner of the additional operation
assertSame(apple, uml.getOwningClassifier(p));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
/**
* Tests that when we define additional operations on the <code>OclAny</code>
* type, they can be invoked on user model types.
*/
public void test_def_operation_OclAny_192892() {
// define an operation on OclAny
helper.setContext(getOCLStandardLibrary().getOclAny());
try {
helper.defineOperation("isBlack() : Boolean = true");
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
// switch to context of a user model classifier
helper.setContext(fruit);
try {
InstanceSpecification anApple = instantiate(instancePackage, apple);
assertTrue(check(helper, anApple, "self.isBlack()"));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
/**
* Tests that when we define additional attributes on the <code>OclAny</code>
* type, they can be invoked on user model types.
*/
public void test_def_attribute_OclAny_192892() {
// define an operation on OclAny
helper.setContext(getOCLStandardLibrary().getOclAny());
try {
helper.defineAttribute("isBlack : Boolean = true");
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
// switch to context of a user model classifier
helper.setContext(fruit);
try {
InstanceSpecification anApple = instantiate(instancePackage, apple);
assertTrue(check(helper, anApple, "self.isBlack"));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
/**
* Tests def expression for an operations with multiple parameters of
* the same type.
*/
public void test_defExpression_operation_similarParams_238050() {
helper.setContext(fruit);
try {
helper.defineOperation(
"displayName(first : String, last : String) : String = " +
"if self.color = Color::red then first else last endif");
OCLExpression<Classifier> expr = helper.createQuery(
"self.displayName('Roger', 'Bacon')");
InstanceSpecification anApple = instantiate(instancePackage, apple);
setValue(anApple, fruit_color, color_black);
assertEquals("Bacon", ocl.evaluate(anApple, expr));
setValue(anApple, fruit_color, color_red);
assertEquals("Roger", ocl.evaluate(anApple, expr));
} catch (Exception e) {
fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
}
}
//
// Test framework
//
@Override
protected void setUp() {
super.setUp();
instanceResource = resourceSet.createResource(
URI.createFileURI("/tmp/instances.uml"));
instancePackage = umlf.createPackage();
instancePackage.setName("instances");
instanceResource.getContents().add(instancePackage);
}
}