/*******************************************************************************
 * Copyright (c) 2009, 2018 SAP AG 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:
 *     SAP AG - initial API and implementation
 ******************************************************************************/
package org.eclipse.ocl.examples.impactanalyzer.tests.instanceScope;

import java.util.Collection;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.SemanticException;
import org.eclipse.ocl.ecore.LoopExp;
import org.eclipse.ocl.ecore.OCL;
import org.eclipse.ocl.ecore.OCL.Helper;
import org.eclipse.ocl.ecore.OCLExpression;
import org.eclipse.ocl.examples.testutils.BaseTest;
import org.eclipse.ocl.util.Bag;
import org.junit.Before;
import org.junit.Test;

import company.CompanyFactory;
import company.CompanyPackage;
import data.classes.ClassTypeDefinition;
import data.classes.ClassesFactory;
import data.classes.ClassesPackage;
import data.classes.MethodSignature;
import data.classes.Parameter;
import data.classes.SapClass;


public class QuickOclParseAndEvalTest extends BaseTest
{
	private SapClass class1;
	private SapClass class2;
	private Parameter param;
	private ClassTypeDefinition ctd;
	private MethodSignature signature;
	private OCL ocl;
	private Helper oclHelper;

	private void assertInvalid(Object object) {
		assertEquals(ocl.getEnvironment().getOCLStandardLibrary().getInvalid(), object);
	}

	@Override
	@Before
	public void setUp()
	{
		class1 = ClassesFactory.eINSTANCE.createSapClass();
		class1.setName("class1");
		class2 = ClassesFactory.eINSTANCE.createSapClass();
		class2.setName("class2");
		signature = ClassesFactory.eINSTANCE.createMethodSignature();
		signature.setName("context");
		param = ClassesFactory.eINSTANCE.createParameter();
		param.setName("p");
		ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
		ctd.setClazz(class1);
		param.setOwnedTypeDefinition(ctd);
		signature.setOwner(class2);
		ocl = org.eclipse.ocl.examples.impactanalyzer.util.OCL.newInstance();
		oclHelper = ocl.createOCLHelper();
		oclHelper.setContext(ClassesPackage.eINSTANCE.getParameter());
	}

	/**
	 * Check if it is possible to create an expression in context Boolean
	 */
	@Test
	public void testParseAndEvaluateOclExpressionInContextBoolean() throws ParserException {
		oclHelper.setContext(EcorePackage.eINSTANCE.getEBoolean());
		{
			OCLExpression expression4 = oclHelper.createQuery("self");
			Object result4 = ocl.evaluate(true, expression4);
			assertTrue((Boolean) result4);
			Object result5 = ocl.evaluate(false, expression4);
			assertFalse((Boolean) result5);
		}
		{
			OCLExpression expression4 = oclHelper.createQuery("not self");
			Object result4 = ocl.evaluate(true, expression4);
			assertFalse((Boolean) result4);
			Object result5 = ocl.evaluate(false, expression4);
			assertTrue((Boolean) result5);
		}
	}

	/**
	 * Check if a type name parses as a type literal
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithTypeLiteral() throws ParserException {
		oclHelper.setContext(CompanyPackage.eINSTANCE.getDepartment());
		OCLExpression expression4 = oclHelper.createQuery("company::Division");
		Object result4 = ocl.evaluate(null, expression4);
		assertTrue(result4 instanceof EClass);
		assertEquals(CompanyPackage.eINSTANCE.getDivision(), result4);
		OCLExpression expression5 = oclHelper.createQuery("Division");
		Object result5 = ocl.evaluate(null, expression5);
		assertTrue(result5 instanceof EClass);
		assertEquals(CompanyPackage.eINSTANCE.getDivision(), result5);
	}

	/**
	 * Check what happens when ->at(...) argument is out of bounds
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithOutOfBoundsAtArgument() throws ParserException {
		oclHelper.setContext(CompanyPackage.eINSTANCE.getDepartment());
		OCLExpression expression4 = oclHelper.createQuery("Sequence{1..2}->at(3)");
		Object result4 = ocl.evaluate(CompanyFactory.eINSTANCE.createDepartment(), expression4);
		assertInvalid(result4);
	}


	/**
	 * Check what happens when last value of a range is invalid instead of an Integer. Interestingly, this aborts the whole
	 * evaluation and even "bypasses" a trailing oclIsInvalid().
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithInvalidAsLastPartOfRange() throws ParserException {
		oclHelper.setContext(CompanyPackage.eINSTANCE.getDepartment());
		OCLExpression expression4 = oclHelper.createQuery("(Sequence{1..(self.parentDepartment.subDepartment->size())}->select(i | i>0)).oclIsInvalid()");
		Object result4 = ocl.evaluate(CompanyFactory.eINSTANCE.createDepartment(), expression4);
		assertInvalid(result4);
	}

	/**
	 * Check if invalid can be passed into an operation as argument
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithMixOfPrimitiveAndObjectTypesInCollectionLiteral() throws ParserException {
		OCLExpression expression4 = oclHelper.createQuery("Set{1, 2, self}->select(i | i.oclIsKindOf(Integer))");
		Object result4 = ocl.evaluate(CompanyFactory.eINSTANCE.createDepartment(), expression4);
		assertTrue(result4 instanceof Collection);
		assertTrue(((Collection<?>) result4).contains(1));
		assertTrue(((Collection<?>) result4).contains(2));
	}

	/**
	 * Check if invalid can be passed into an operation as argument
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithInvalidInOperationArgument() throws ParserException {
		EClass cl = CompanyPackage.eINSTANCE.getDepartment();
		EOperation op = EcoreFactory.eINSTANCE.createEOperation();
		try {
			op.setName("myOp");
			op.setEType(EcorePackage.eINSTANCE.getEBoolean());
			EParameter param = EcoreFactory.eINSTANCE.createEParameter();
			param.setName("humba");
			param.setEType(org.eclipse.emf.ecore.EcorePackage.eINSTANCE
					.getEClassifier());
			op.getEParameters().add(param);
			cl.getEOperations().add(op);
			oclHelper.setOperationContext(cl, op);
			oclHelper.createBodyCondition("humba.oclIsInvalid()");
			oclHelper.setContext(cl);
			OCLExpression expression4 = oclHelper
					.createQuery("self.myOp(invalid)");
			Object result4 = ocl.evaluate(
					CompanyFactory.eINSTANCE.createDepartment(), expression4);
			assertEquals(true, result4);
		} finally {
			cl.getEOperations().remove(op);
		}
	}

	/**
	 * Ensure that "or" and "and" do shortcut evaluation for invalid arguments
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithInvalidInBooleanShortcutEval() throws ParserException {
		OCLExpression expression4 = oclHelper.createQuery("false and invalid");
		Object result4 = ocl.evaluate(null, expression4);
		assertEquals(false, result4);
		OCLExpression expression5 = oclHelper.createQuery("true or invalid");
		Object result5 = ocl.evaluate(null, expression5);
		assertEquals(true, result5);
		OCLExpression expression6 = oclHelper.createQuery("(invalid or true).oclIsInvalid()");
		Object result6 = ocl.evaluate(null, expression6);
		assertEquals(false, result6);
		OCLExpression expression7 = oclHelper.createQuery("(invalid and false).oclIsInvalid()");
		Object result7 = ocl.evaluate(null, expression7);
		assertEquals(false, result7);
		OCLExpression expression8 = oclHelper.createQuery("(invalid or true)");
		Object result8 = ocl.evaluate(null, expression8);
		assertEquals(true, result8);
		OCLExpression expression9 = oclHelper.createQuery("(invalid and false)");
		Object result9 = ocl.evaluate(null, expression9);
		assertEquals(false, result9);
	}

	/**
	 * Testing if a let-expression evaluates to OclInvalid if the initExpression evaluates to OclInvalid although
	 * the variable is not used in the "in" expression.
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithInvalidLetInitExpression() throws ParserException {
		OCLExpression expression4 = oclHelper
				.createQuery("let x:Integer=self.name.size() in 1+2");
		Object result4 = ocl.evaluate(null, expression4);
		assertEquals(3, result4);
	}

	/**
	 * Testing if two iterator variables appear as such
	 */
	@Test
	public void testParseAndEvaluateOclExpressionForAllWithTwoIterators() throws ParserException {
		OCLExpression expression4 = oclHelper
				.createQuery("Set{1, 2, 3}->forAll(i, j | i+j <> 7)");
		assertEquals(2, ((LoopExp) expression4).getIterator().size());
		Object result4 = ocl.evaluate(param, expression4);
		assertEquals(true, result4);
	}

	/**
	 * Testing if an iterate's accumulator expression is really evaluated even when the iterate is applied to an empty collection
	 */
	@Test
	public void testParseAndEvaluateOclExpressionAccumulatorForIterateOnEmptyCollection() throws ParserException {
		OCLExpression expression4 = oclHelper
				.createQuery("let s:Set(Integer)=Set{} in s->iterate(i:Integer; acc:Integer=1 | acc+1)");
		Object result4 = ocl.evaluate(param, expression4);
		assertEquals(1, result4);
	}

	/**
	 * Testing if shadowing a variable by an iterator leads to incorrect results because the shadowed
	 * variable is overwritten by the iterator values
	 */
	@Test
	public void testParseAndEvaluateOclExpressionIteratorShadowingLetVariable() throws ParserException
	{
		param.setOwnedTypeDefinition(ctd);
		ctd.setClazz(null);
		try {
			OCLExpression expression4 = oclHelper.createQuery("let i:Integer=1 in if self.ownedTypeDefinition->select(i|i.oclAsType(ClassTypeDefinition).clazz->notEmpty())->isEmpty() then i else 0 endif");
			Object result4 = ocl.evaluate(param, expression4);
			assertEquals(1, result4);
		} catch (SemanticException e) {
			// it's ok if the OCL implementation doesn't accept shadowing:
			assertEquals("Variable name already used: (i)", e.getMessage());
		}
	}

	/**
	 * Ensures that an OclInvalid value does not pass a select filter, yet the select iterator
	 * returns a valid result
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithTupleWithNull() throws ParserException
	{
		param.setName(null);
		OCLExpression expression5 = oclHelper.createQuery("Tuple{c:Tuple(d:String)=Tuple{d=self.name}}.c.d");
		Object result5 = ocl.evaluate(param, expression5);
		assertNull(result5);
	}

	/**
	 * Ensures that an OclInvalid value does not pass a select filter, yet the select iterator
	 * returns a valid result
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithCollectOfNullValue() throws ParserException
	{
		OCLExpression expression5 = oclHelper.createQuery("Set{1, 2}->collect(null)");
		Object result5 = ocl.evaluate(param, expression5);
		assertEquals(2, ((Collection<?>) result5).size());
		assertTrue(((Collection<?>) result5).contains(null));
	}

	/**
	 * Ensures that an OclInvalid value does not pass a select filter, yet the select iterator
	 * returns a valid result
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithIncludingNullInSequence() throws ParserException
	{
		OCLExpression expression5 = oclHelper.createQuery("Sequence{1}->including(null)");
		Object result5 = ocl.evaluate(param, expression5);
		assertEquals(2, ((Collection<?>) result5).size());
		assertTrue(((Collection<?>) result5).contains(null));
	}

	/**
	 * Ensures that an OclInvalid value does not pass a select filter, yet the select iterator
	 * returns a valid result
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithSizeOverSequenceContainingNull() throws ParserException
	{
		OCLExpression expression5 = oclHelper.createQuery("Sequence{1}->including(null)->size()");
		Object result5 = ocl.evaluate(param, expression5);
		assertEquals(2, result5);
	}

	/**
	 * Ensures that an OclInvalid value does not pass a select filter, yet the select iterator
	 * returns a valid result
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithCollectOverOclInvalid() throws ParserException
	{
		OCLExpression expression5 = oclHelper.createQuery("Set{self, invalid}->collect(i | i)");
		Object result5 = ocl.evaluate(param, expression5);
		assertInvalid(result5);
	}

	/**
	 * Ensures that an OclInvalid value propagates from a collection literal to the overall expression
	 */
	@Test
	public void testParseAndEvaluateOclExpressionWithSelectOverOclInvalid() throws ParserException
	{
		OCLExpression expression5 = oclHelper.createQuery("Set{self, invalid}->select(i | i.name = 'p')");
		Object result5 = ocl.evaluate(param, expression5);
		assertInvalid(result5);
	}

	@Test
	public void testParseAndEvaluateOclExpression() throws ParserException
	{
		OCLExpression expression = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition).clazz");
		Object result = ocl.evaluate(param, expression);
		assertEquals(class1, result);
	}

	@Test
	public void testParseAndEvaluateOclExpressionWithOperationCallOnNullValue() throws ParserException
	{
		param.setOwnedTypeDefinition(null);
		OCLExpression expression2 = oclHelper.createQuery("self.ownedTypeDefinition.getInnermost()");
		Object result = ocl.evaluate(param, expression2);
		assertEquals(ocl.getEnvironment().getOCLStandardLibrary().getInvalid(), result);
	}

	@Test
	public void testParseAndEvaluateOclExpressionWithPropertyCallOnNullValue() throws ParserException
	{
		param.setOwnedTypeDefinition(null);
		OCLExpression expression2 = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition).clazz.oclIsInvalid()");
		Object result2 = ocl.evaluate(param, expression2);
		assertTrue((Boolean)result2);
	}

	@Test
	public void testParseAndEvaluateOclExpressionWithCollectOverNullValue() throws ParserException
	{
		param.setOwnedTypeDefinition(null);
		OCLExpression expression3 = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition)->collect(clazz)");
		Object result3 = ocl.evaluate(param, expression3);
		assertEquals(0, ((Collection< ? >)result3).size());
	}

	@Test
	public void testParseAndEvaluateOclExpressionCollectWithBodyEvaluatingToNull() throws ParserException
	{
		param.setOwnedTypeDefinition(ctd);
		ctd.setClazz(null);
		OCLExpression expression4 = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition)->collect(clazz)");
		Object result4 = ocl.evaluate(param, expression4);
		assertTrue(((Bag< ? >)result4).contains(null));
	}

	@Test
	public void testParseAndEvaluateOclExpressionWithImplicitCollectOverOperationCallResult() throws ParserException
	{
		OCLExpression expression4 = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition).clazz.getAssociationEnds().otherEnd()");
		Object result4 = ocl.evaluate(param, expression4);
		assertTrue(((Collection<?>) result4).isEmpty());
	}

	@Test
	public void testParseAndEvaluateOclExpressionWithDelegatesToSimulation() throws ParserException
	{
		OCLExpression expression4 = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition).clazz.getAssociationEnds().otherEnd()->select(delegation->notEmpty()).type.clazz->reject(c|c=self)->asSet()");
		Object result4 = ocl.evaluate(param, expression4);
		assertTrue(((Collection<?>) result4).isEmpty());
	}

	@Test
	public void testParseAndEvaluateOclExpressionWithImplicitSetLiteral() throws ParserException
	{
		OCLExpression expression4 = oclHelper.createQuery("self.ownedTypeDefinition->isEmpty()");
		Object result4 = ocl.evaluate(param, expression4);
		assertFalse((Boolean) result4);
	}

	@Test
	public void testParseAndEvaluateOclExpressionWithImplicitSetLiteralCheckingForIsEmpty() throws ParserException
	{
		param.setOwnedTypeDefinition(null);
		OCLExpression expression5 = oclHelper.createQuery("self.ownedTypeDefinition->isEmpty()");
		Object result5 = ocl.evaluate(param, expression5);
		assertTrue((Boolean) result5);
	}

	@Test
	public void testParseAndEvaluateOclExpressionWithNullInSetLiteral() throws ParserException
	{
		param.setOwnedTypeDefinition(null);
		OCLExpression expression5 = oclHelper.createQuery("Set{null}->isEmpty()");
		Object result5 = ocl.evaluate(param, expression5);
		assertFalse((Boolean) result5);
		OCLExpression expression6 = oclHelper.createQuery("null->isEmpty()");
		Object result6 = ocl.evaluate(param, expression6);
		assertTrue((Boolean) result6);
	}

	@Test
	public void testParseAndEvaluateOclExpressionWithEmptySetLiteralIncludingNull() throws ParserException
	{
		OCLExpression expression4 = oclHelper.createQuery("Set{}->including(null)->isEmpty()");
		Object result4 = ocl.evaluate(param, expression4);
		assertFalse((Boolean) result4);
	}

}
