/*******************************************************************************
 * 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.ecore.tests;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.ocl.OCLInput;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.ecore.Constraint;
import org.eclipse.ocl.ecore.OCL;
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.util.TypeUtil;
import org.eclipse.ocl.utilities.UMLReflection;

/**
 * Tests for def expressions (additional properties and operations).
 *
 * @author Christian W. Damus (cdamus)
 */
@SuppressWarnings("nls")
public class DefExpressionTest
extends AbstractTestSuite {

	/**
	 * Tests the parsing the def expression for an operation from raw text.
	 */
	public void test_defExpression_raw_operation() {
		try {
			OCLExpression<EClassifier> 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, constraint.getStereotype());

			assertSame(color, expr.getType());

			expr = parse(
				"package ocltest context Fruit " +
						"inv: bestColor(Color::red) = Color::red" +
					" endpackage");

			EObject anApple = fruitFactory.create(apple);
			anApple.eSet(fruit_color, color_black);

			assertTrue(ocl.check(anApple, expr));

			anApple.eSet(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");

			EObject anApple = fruitFactory.create(apple);
			anApple.eSet(fruit_color, color_black);

			assertTrue(ocl.check(anApple, expr));

			anApple.eSet(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<EClassifier> expr = parseDef(
				"package ocltest context Apple " +
						"def: fallen : Boolean = stem.oclIsUndefined()" +
					" endpackage");

			Constraint constraint = (Constraint) expr.eContainer().eContainer();
			assertNotNull(constraint);

			assertEquals(UMLReflection.DEFINITION, constraint.getStereotype());

			assertSame(getOCLStandardLibrary().getBoolean(), expr.getType());

			expr = parse(
				"package ocltest context Apple " +
						"inv: not fallen" +
					" endpackage");

			EObject anApple = fruitFactory.create(apple);
			anApple.eSet(apple_stem, fruitFactory.create(stem));

			assertTrue(ocl.check(anApple, expr));

			anApple.eSet(apple_stem, 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 = " +
					"stem.oclIsUndefined()");

			Constraint expr = helper.createInvariant("not fallen");

			EObject anApple = fruitFactory.create(apple);
			anApple.eSet(apple_stem, fruitFactory.create(stem));

			assertTrue(ocl.check(anApple, expr));

			anApple.eSet(apple_stem, 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<EClassifier> 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, constraint.getStereotype());

			assertTrue(expr.getType() instanceof SetType<?, ?>);
			assertSame(
				((org.eclipse.ocl.ecore.SetType) expr.getType()).getElementType(),
				apple);

			expr = parse(
				"package ocltest context Apple " +
						"inv: self.otherApples" +
					" endpackage");

			EObject anApple = fruitFactory.create(apple);
			EObject anotherApple = fruitFactory.create(apple);
			Map<EClass, Set<EObject>> extentMap = new java.util.HashMap<EClass, Set<EObject>>();
			Set<EObject> allApples = new java.util.HashSet<EObject>();
			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(EcorePackage.Literals.ECLASSIFIER);

		try {
			helper.defineOperation(
				"allParents() : Set(EClassifier) = " +
					"if self.oclIsKindOf(EClass) then self.oclAsType(EClass)->closure(eSuperTypes) else Set{} endif");

			OCLExpression<EClassifier> expr = helper.createQuery("self.allParents()");

			Object allParents = ocl.evaluate(apple, expr);
			assertTrue(allParents instanceof Set<?>);
			assertTrue(((Set<?>) allParents).contains(fruit));

			allParents = ocl.evaluate(color, expr);
			assertTrue(allParents instanceof Set<?>);
			assertTrue(((Set<?>) allParents).isEmpty());
		} catch (Exception e) {
			fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
		}
	}

	public void test_defExpression_inheritance_attribute() {
		helper.setContext(EcorePackage.Literals.ECLASSIFIER);

		try {
			helper.defineAttribute(
				"allParents : Set(EClassifier) = " +
					"if self.oclIsKindOf(EClass) then self.oclAsType(EClass)->closure(eSuperTypes) else Set{} endif");

			OCLExpression<EClassifier> expr = helper.createQuery("self.allParents");

			Object allParents = ocl.evaluate(apple, expr);
			assertTrue(allParents instanceof Set<?>);
			assertTrue(((Set<?>) allParents).contains(fruit));

			allParents = ocl.evaluate(color, expr);
			assertTrue(allParents instanceof Set<?>);
			assertTrue(((Set<?>) allParents).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 {
			ParsingOptions.setOption(ocl.getEnvironment(), ParsingOptions.SUPPORT_STATIC_FEATURES, true);
			try {
				ocl.parse(new OCLInput("package ocltest context Fruit " +
						"def: bestColor1() : Color = null " +
						"static def: bestColor2() : Color = null " +
						"def: goodColor1 : Color = null " +
						"static def: goodColor2 : Color = null " +
						"endpackage"));
				fail("Should have failed to parse the unimplemented static");
			} catch (ParserException e) {
				// success!
				assertEquals(OCLMessages.UnimplementedStatic_ERROR_, e.getMessage());
				debugPrintln("Got the expected exception: " + e.getLocalizedMessage());
			}

			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(EcorePackage.Literals.ECLASSIFIER);

		try {
			// non-conformant expression type
			helper.defineAttribute(
				"allParents : Set(EClassifier) = " +
					"if self.oclIsKindOf(EClass) then self.name else '' endif");

			fail("Should not have parsed");
		} catch (Exception e) {
			// success
			debugPrintln("Got expected error: " + e.getLocalizedMessage());
		}

		try {
			// missing type declaration
			helper.defineAttribute(
				"myName = " +
					"if self.oclIsKindOf(EClass) then self.name else '' endif");

			fail("Should not have parsed");
		} catch (Exception e) {
			// success
			debugPrintln("Got expected error: " + e.getLocalizedMessage());
		}
	}

	public void test_malformedDefExpression_operation() {
		helper.setContext(EcorePackage.Literals.ECLASSIFIER);

		try {
			// non-conformant expression type
			helper.defineOperation(
				"allParents() : Set(EClassifier) = " +
					"if self.oclIsKindOf(EClass) then self.name else '' endif");

			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(EClass) 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(EClass) 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(EcorePackage.Literals.ECLASSIFIER);

		try {
			// same name and type as existing property
			helper.defineAttribute(
				"name : String = " +
					"if self.oclIsKindOf(EClass) 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(
				"eAnnotations : 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 self.oclIsKindOf(EClass) 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 self.oclIsKindOf(EClass) 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(EcorePackage.Literals.ECLASS);

		EStructuralFeature property = null;

		try {
			// define some additional property
			property = helper.defineAttribute(
				"other : EClass = " +
					"if eSuperTypes->notEmpty() then eSuperTypes->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 : EClass = " +
					"if eSuperTypes->notEmpty() then eSuperTypes->first() else null endif");
		} catch (Exception e) {
			fail("Failed to parse: " + e.getLocalizedMessage());
		}
	}

	public void test_undefine_operation_152018() {
		helper.setContext(EcorePackage.Literals.ECLASS);

		EOperation operation = null;

		try {
			// define some additional property
			operation = helper.defineOperation(
				"other(x : Integer) : EClass = " +
					"if eSuperTypes->notEmpty() then eSuperTypes->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) : EClass = " +
					"if eSuperTypes->size() >= x then eSuperTypes->at(x) else null endif");
		} catch (Exception e) {
			fail("Failed to parse: " + e.getLocalizedMessage());
		}
	}

	public void test_recursive_property_152018() {
		helper.setContext(EcorePackage.Literals.ECLASS);

		EStructuralFeature property = null;

		try {
			// first, attempt a definition with an invalid body
			property = helper.defineAttribute(
				"friend : EClass = " +
					"if eSuperTypes->notEmpty() then ePackage 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 : EClass = " +
					"if eSuperTypes->notEmpty() then eSuperTypes->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(EcorePackage.Literals.ECLASS);

		EOperation operation = null;

		try {
			// first, attempt a definition with an invalid body
			operation = helper.defineOperation(
				"friend(x : Integer) : EClass = " +
					"if eSuperTypes->size() >= x then ePackage 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) : EClass = " +
					"if eSuperTypes->size() >= x then eSuperTypes->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(EcorePackage.Literals.ECLASSIFIER);

		try {
			helper.defineOperation(
				"allParents() : Set(EClassifier) = " +
					"if self.oclIsKindOf(EClass) then self.oclAsType(EClass)->closure(eSuperTypes) else Set{} endif");

			Collection<Choice> choices = helper.getSyntaxHelp(
				ConstraintKind.INVARIANT, "self.");

			assertChoice(choices, ChoiceKind.OPERATION, "allParents");
		} catch (Exception e) {
			fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
		}
	}

	public void test_defExpression_completion_attribute() {
		helper.setContext(EcorePackage.Literals.ECLASSIFIER);

		try {
			helper.defineAttribute(
				"allParents : Set(EClassifier) = " +
					"if self.oclIsKindOf(EClass) then self.oclAsType(EClass)->closure(eSuperTypes) else Set{} endif");

			Collection<Choice> choices = helper.getSyntaxHelp(
				ConstraintKind.INVARIANT, "self.");

			assertChoice(choices, ChoiceKind.PROPERTY, "allParents");
		} 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 Ecore metamodel's EString data type
		helper.setContext(EcorePackage.Literals.ESTRING);

		try {
			EStructuralFeature 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<EClassifier> 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(), EcorePackage.Literals.ESTRING)
				.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 Ecore metamodel's EString data type
		helper.setContext(EcorePackage.Literals.ESTRING);

		try {
			EOperation 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<EClassifier> 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(), EcorePackage.Literals.ESTRING)
				.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 {
			EStructuralFeature 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(EcorePackage.Literals.ESTRING);

			Collection<Choice> choices = helper.getSyntaxHelp(
				ConstraintKind.INVARIANT, "self.");

			assertChoice(choices, ChoiceKind.PROPERTY, "reverse");

			OCLExpression<EClassifier> 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(), EcorePackage.Literals.ESTRING)
				.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 an OCL pre-defined type.
	 */
	public void test_defOperationOnPredefinedType_172782() {
		// context is the predefined OCL String type
		helper.setContext(ocl.getEnvironment().getOCLStandardLibrary().getString());

		try {
			EOperation 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(EcorePackage.Literals.ESTRING);

			Collection<Choice> choices = helper.getSyntaxHelp(
				ConstraintKind.INVARIANT, "self.");

			assertChoice(choices, ChoiceKind.OPERATION, "reversed");

			OCLExpression<EClassifier> 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(), EcorePackage.Literals.ESTRING)
				.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 {
			EOperation o = helper.defineOperation(
				"bestColor(c : Color) : Color = " +
					"if self.color = Color::black then c else self.color endif");

			UMLReflection<?, EClassifier, ?, ?, ?, ?, ?, ?, ?, ?> 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(fruit);

		try {
			EStructuralFeature p = helper.defineAttribute(
				"isBlack : Boolean = " +
					"color = Color::black");

			UMLReflection<?, EClassifier, ?, ?, ?, ?, ?, ?, ?, ?> uml =
					ocl.getEnvironment().getUMLReflection();

			// sanity check
			assertSame(fruit, uml.getOwningClassifier(fruit_color));

			// check the owner of the additional operation
			assertSame(fruit, 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 {
			EObject instance = fruitFactory.create(apple);
			assertTrue(check(helper, instance, "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 {
			EObject instance = fruitFactory.create(apple);
			assertTrue(check(helper, instance, "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<EClassifier> expr = helper.createQuery(
					"self.displayName('Roger', 'Bacon')");

			EObject anApple = fruitFactory.create(apple);
			anApple.eSet(fruit_color, color_black);

			assertEquals("Bacon", ocl.evaluate(anApple, expr));

			anApple.eSet(fruit_color, color_red);

			assertEquals("Roger", ocl.evaluate(anApple, expr));
		} catch (Exception e) {
			fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
		}
	}
}
