/**
 */
package org.etsi.mts.tdl.impl;

import java.lang.reflect.InvocationTargetException;

import java.util.Collection;

import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;

import org.eclipse.emf.ecore.util.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.InternalEList;

import org.eclipse.ocl.pivot.evaluation.Executor;
import org.eclipse.ocl.pivot.ids.IdResolver;
import org.eclipse.ocl.pivot.library.collection.CollectionIsEmptyOperation;
import org.eclipse.ocl.pivot.messages.PivotMessages;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.InvalidValueException;
import org.eclipse.ocl.pivot.values.SetValue;
import org.eclipse.ocl.pivot.values.SetValue.Accumulator;
import org.etsi.mts.tdl.ComponentInstance;
import org.etsi.mts.tdl.ComponentInstanceBinding;
import org.etsi.mts.tdl.Connection;
import org.etsi.mts.tdl.GateInstance;
import org.etsi.mts.tdl.GateReference;
import org.etsi.mts.tdl.TestConfiguration;
import org.etsi.mts.tdl.tdlPackage;
import org.etsi.mts.tdl.tdlTables;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Test Configuration</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * </p>
 * <ul>
 *   <li>{@link org.etsi.mts.tdl.impl.TestConfigurationImpl#getComponentInstance <em>Component Instance</em>}</li>
 *   <li>{@link org.etsi.mts.tdl.impl.TestConfigurationImpl#getConnection <em>Connection</em>}</li>
 * </ul>
 *
 * @generated
 */
public class TestConfigurationImpl extends PackageableElementImpl implements TestConfiguration
{
	/**
	 * The cached value of the '{@link #getComponentInstance() <em>Component Instance</em>}' containment reference list.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getComponentInstance()
	 * @generated
	 * @ordered
	 */
	protected EList<ComponentInstance> componentInstance;

	/**
	 * The cached value of the '{@link #getConnection() <em>Connection</em>}' containment reference list.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getConnection()
	 * @generated
	 * @ordered
	 */
	protected EList<Connection> connection;

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected TestConfigurationImpl()
	{
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass()
	{
		return tdlPackage.Literals.TEST_CONFIGURATION;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public EList<ComponentInstance> getComponentInstance()
	{
		if (componentInstance == null) {
			componentInstance = new EObjectContainmentEList<ComponentInstance>(ComponentInstance.class, this, tdlPackage.TEST_CONFIGURATION__COMPONENT_INSTANCE);
		}
		return componentInstance;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public EList<Connection> getConnection()
	{
		if (connection == null) {
			connection = new EObjectContainmentEList<Connection>(Connection.class, this, tdlPackage.TEST_CONFIGURATION__CONNECTION);
		}
		return connection;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean compatibleWith(final TestConfiguration tc, final EList<ComponentInstanceBinding> cb)
	{
		/**
		 *
		 * self.componentInstance->forAll(c |
		 *   cb->exists(formalComponent = c)) and
		 * self.connection->forAll(c1 |
		 *   tc.connection->exists(c2 |
		 *     c1.endPoint->reject(ep1 |
		 *       c2.endPoint->exists(ep2 |
		 *         cb->any(formalComponent = ep1.component).actualComponent = ep2.component and ep1.gate = ep2.gate))
		 *     ->isEmpty()))
		 */
		assert cb != null;
		final /*@NonInvalid*/ Executor executor = PivotUtil.getExecutor(this);
		final /*@NonInvalid*/ IdResolver idResolver = executor.getIdResolver();
		/*@Caught*/ Object CAUGHT_forAll;
		try {
			final /*@NonInvalid*/ List<ComponentInstance> componentInstance = this.getComponentInstance();
			final /*@NonInvalid*/ SetValue BOXED_componentInstance = idResolver.createSetOfAll(tdlTables.SET_CLSSid_ComponentInstance, componentInstance);
			/*@Thrown*/ Object accumulator = ValueUtil.TRUE_VALUE;
			Iterator<Object> ITERATOR_c = BOXED_componentInstance.iterator();
			/*@Thrown*/ Boolean forAll;
			while (true) {
				if (!ITERATOR_c.hasNext()) {
					if (accumulator == null) {
						forAll = null;
					}
					else if (accumulator == ValueUtil.TRUE_VALUE) {
						forAll = ValueUtil.TRUE_VALUE;
					}
					else {
						throw (InvalidValueException)accumulator;
					}
					break;
				}
				/*@NonInvalid*/ ComponentInstance c = (ComponentInstance)ITERATOR_c.next();
				/**
				 * cb->exists(formalComponent = c)
				 */
				final /*@NonInvalid*/ SetValue BOXED_cb = idResolver.createSetOfAll(tdlTables.SET_CLSSid_ComponentInstanceBinding, cb);
				/*@Thrown*/ Object accumulator_0 = ValueUtil.FALSE_VALUE;
				Iterator<Object> ITERATOR__1 = BOXED_cb.iterator();
				/*@NonInvalid*/ Boolean exists;
				while (true) {
					if (!ITERATOR__1.hasNext()) {
						if (accumulator_0 == ValueUtil.FALSE_VALUE) {
							exists = ValueUtil.FALSE_VALUE;
						}
						else {
							throw (InvalidValueException)accumulator_0;
						}
						break;
					}
					/*@NonInvalid*/ ComponentInstanceBinding _1 = (ComponentInstanceBinding)ITERATOR__1.next();
					/**
					 * formalComponent = c
					 */
					final /*@NonInvalid*/ ComponentInstance formalComponent = _1.getFormalComponent();
					final /*@NonInvalid*/ boolean eq = formalComponent.equals(c);
					//
					if (eq) {					// Normal successful body evaluation result
						exists = ValueUtil.TRUE_VALUE;
						break;														// Stop immediately
					}
					else if (!eq) {				// Normal unsuccessful body evaluation result
						;															// Carry on
					}
					else {															// Impossible badly typed result
						accumulator_0 = new InvalidValueException(PivotMessages.NonBooleanBody, "exists");
					}
				}
				//
				if (exists == ValueUtil.FALSE_VALUE) {					// Normal unsuccessful body evaluation result
					forAll = ValueUtil.FALSE_VALUE;
					break;														// Stop immediately
				}
				else if (exists == ValueUtil.TRUE_VALUE) {				// Normal successful body evaluation result
					;															// Carry on
				}
				else if (exists == null) {								// Abnormal null body evaluation result
					if (accumulator == ValueUtil.TRUE_VALUE) {
						accumulator = null;										// Cache a null failure
					}
				}
				else {															// Impossible badly typed result
					accumulator = new InvalidValueException(PivotMessages.NonBooleanBody, "forAll");
				}
			}
			CAUGHT_forAll = forAll;
		}
		catch (Exception e) {
			CAUGHT_forAll = ValueUtil.createInvalidValue(e);
		}
		final /*@Thrown*/ Boolean and_0;
		if (CAUGHT_forAll == ValueUtil.FALSE_VALUE) {
			and_0 = ValueUtil.FALSE_VALUE;
		}
		else {
			/*@Caught*/ Object CAUGHT_forAll_0;
			try {
				final /*@NonInvalid*/ List<Connection> connection = this.getConnection();
				final /*@NonInvalid*/ SetValue BOXED_connection = idResolver.createSetOfAll(tdlTables.SET_CLSSid_Connection, connection);
				/*@Thrown*/ Object accumulator_1 = ValueUtil.TRUE_VALUE;
				Iterator<Object> ITERATOR_c1 = BOXED_connection.iterator();
				/*@Thrown*/ Boolean forAll_0;
				while (true) {
					if (!ITERATOR_c1.hasNext()) {
						if (accumulator_1 == null) {
							forAll_0 = null;
						}
						else if (accumulator_1 == ValueUtil.TRUE_VALUE) {
							forAll_0 = ValueUtil.TRUE_VALUE;
						}
						else {
							throw (InvalidValueException)accumulator_1;
						}
						break;
					}
					/*@NonInvalid*/ Connection c1 = (Connection)ITERATOR_c1.next();
					/**
					 *
					 * tc.connection->exists(c2 |
					 *   c1.endPoint->reject(ep1 |
					 *     c2.endPoint->exists(ep2 |
					 *       cb->any(formalComponent = ep1.component).actualComponent = ep2.component and ep1.gate = ep2.gate))
					 *   ->isEmpty())
					 */
					/*@Caught*/ Object CAUGHT_exists_0;
					try {
						final /*@NonInvalid*/ List<Connection> connection_0 = tc.getConnection();
						final /*@NonInvalid*/ SetValue BOXED_connection_0 = idResolver.createSetOfAll(tdlTables.SET_CLSSid_Connection, connection_0);
						/*@Thrown*/ Object accumulator_2 = ValueUtil.FALSE_VALUE;
						Iterator<Object> ITERATOR_c2 = BOXED_connection_0.iterator();
						/*@Thrown*/ Boolean exists_0;
						while (true) {
							if (!ITERATOR_c2.hasNext()) {
								if (accumulator_2 == ValueUtil.FALSE_VALUE) {
									exists_0 = ValueUtil.FALSE_VALUE;
								}
								else {
									throw (InvalidValueException)accumulator_2;
								}
								break;
							}
							/*@NonInvalid*/ Connection c2 = (Connection)ITERATOR_c2.next();
							/**
							 *
							 * c1.endPoint->reject(ep1 |
							 *   c2.endPoint->exists(ep2 |
							 *     cb->any(formalComponent = ep1.component).actualComponent = ep2.component and ep1.gate = ep2.gate))
							 * ->isEmpty()
							 */
							/*@Caught*/ Object CAUGHT_isEmpty;
							try {
								final /*@NonInvalid*/ List<GateReference> endPoint = c1.getEndPoint();
								final /*@NonInvalid*/ SetValue BOXED_endPoint = idResolver.createSetOfAll(tdlTables.SET_CLSSid_GateReference, endPoint);
								/*@Thrown*/ Accumulator accumulator_3 = ValueUtil.createSetAccumulatorValue(tdlTables.SET_CLSSid_GateReference);
								Iterator<Object> ITERATOR_ep1 = BOXED_endPoint.iterator();
								/*@Thrown*/ SetValue reject;
								while (true) {
									if (!ITERATOR_ep1.hasNext()) {
										reject = accumulator_3;
										break;
									}
									/*@NonInvalid*/ GateReference ep1 = (GateReference)ITERATOR_ep1.next();
									/**
									 *
									 * c2.endPoint->exists(ep2 |
									 *   cb->any(formalComponent = ep1.component).actualComponent = ep2.component and ep1.gate = ep2.gate)
									 */
									final /*@NonInvalid*/ List<GateReference> endPoint_0 = c2.getEndPoint();
									final /*@NonInvalid*/ SetValue BOXED_endPoint_0 = idResolver.createSetOfAll(tdlTables.SET_CLSSid_GateReference, endPoint_0);
									/*@Thrown*/ Object accumulator_4 = ValueUtil.FALSE_VALUE;
									Iterator<Object> ITERATOR_ep2 = BOXED_endPoint_0.iterator();
									/*@Thrown*/ Boolean exists_1;
									while (true) {
										if (!ITERATOR_ep2.hasNext()) {
											if (accumulator_4 == null) {
												exists_1 = null;
											}
											else if (accumulator_4 == ValueUtil.FALSE_VALUE) {
												exists_1 = ValueUtil.FALSE_VALUE;
											}
											else {
												throw (InvalidValueException)accumulator_4;
											}
											break;
										}
										/*@NonInvalid*/ GateReference ep2 = (GateReference)ITERATOR_ep2.next();
										/**
										 *
										 * cb->any(formalComponent = ep1.component).actualComponent = ep2.component and ep1.gate = ep2.gate
										 */
										final /*@NonInvalid*/ SetValue BOXED_cb_0 = idResolver.createSetOfAll(tdlTables.SET_CLSSid_ComponentInstanceBinding, cb);
										Iterator<Object> ITERATOR__1_0 = BOXED_cb_0.iterator();
										/*@NonInvalid*/ ComponentInstanceBinding any;
										while (true) {
											if (!ITERATOR__1_0.hasNext()) {
												throw new InvalidValueException("Nothing to return for ''any''");
											}
											/*@NonInvalid*/ ComponentInstanceBinding _1_0 = (ComponentInstanceBinding)ITERATOR__1_0.next();
											/**
											 * formalComponent = ep1.component
											 */
											final /*@NonInvalid*/ ComponentInstance formalComponent_0 = _1_0.getFormalComponent();
											final /*@NonInvalid*/ ComponentInstance component = ep1.getComponent();
											final /*@NonInvalid*/ boolean eq_0 = formalComponent_0.equals(component);
											//
											if (eq_0) {			// Carry on till something found
												any = _1_0;
												break;
											}
										}
										final /*@NonInvalid*/ ComponentInstance actualComponent = any.getActualComponent();
										final /*@NonInvalid*/ ComponentInstance component_0 = ep2.getComponent();
										final /*@NonInvalid*/ boolean eq_1 = actualComponent.equals(component_0);
										final /*@NonInvalid*/ Boolean and;
										if (!eq_1) {
											and = ValueUtil.FALSE_VALUE;
										}
										else {
											final /*@NonInvalid*/ GateInstance gate = ep1.getGate();
											final /*@NonInvalid*/ GateInstance gate_0 = ep2.getGate();
											final /*@NonInvalid*/ boolean eq_2 = gate.equals(gate_0);
											if (!eq_2) {
												and = ValueUtil.FALSE_VALUE;
											}
											else {
												and = ValueUtil.TRUE_VALUE;
											}
										}
										//
										if (and == ValueUtil.TRUE_VALUE) {					// Normal successful body evaluation result
											exists_1 = ValueUtil.TRUE_VALUE;
											break;														// Stop immediately
										}
										else if (and == ValueUtil.FALSE_VALUE) {				// Normal unsuccessful body evaluation result
											;															// Carry on
										}
										else if (and == null) {								// Abnormal null body evaluation result
											if (accumulator_4 == ValueUtil.FALSE_VALUE) {
												accumulator_4 = null;										// Cache a null failure
											}
										}
										else {															// Impossible badly typed result
											accumulator_4 = new InvalidValueException(PivotMessages.NonBooleanBody, "exists");
										}
									}
									if (exists_1 == null) {
										throw new InvalidValueException("Null body for \'Set(T).reject(Set.T[?] | Lambda T() : Boolean[1]) : Set(T)\'");
									}
									//
									if (exists_1 == ValueUtil.FALSE_VALUE) {
										accumulator_3.add(ep1);
									}
								}
								final /*@Thrown*/ boolean isEmpty = CollectionIsEmptyOperation.INSTANCE.evaluate(reject).booleanValue();
								CAUGHT_isEmpty = isEmpty;
							}
							catch (Exception e) {
								CAUGHT_isEmpty = ValueUtil.createInvalidValue(e);
							}
							//
							if (CAUGHT_isEmpty == ValueUtil.TRUE_VALUE) {					// Normal successful body evaluation result
								exists_0 = ValueUtil.TRUE_VALUE;
								break;														// Stop immediately
							}
							else if (CAUGHT_isEmpty == ValueUtil.FALSE_VALUE) {				// Normal unsuccessful body evaluation result
								;															// Carry on
							}
							else if (CAUGHT_isEmpty instanceof InvalidValueException) {		// Abnormal exception evaluation result
								accumulator_2 = CAUGHT_isEmpty;									// Cache an exception failure
							}
							else {															// Impossible badly typed result
								accumulator_2 = new InvalidValueException(PivotMessages.NonBooleanBody, "exists");
							}
						}
						CAUGHT_exists_0 = exists_0;
					}
					catch (Exception e) {
						CAUGHT_exists_0 = ValueUtil.createInvalidValue(e);
					}
					//
					if (CAUGHT_exists_0 == ValueUtil.FALSE_VALUE) {					// Normal unsuccessful body evaluation result
						forAll_0 = ValueUtil.FALSE_VALUE;
						break;														// Stop immediately
					}
					else if (CAUGHT_exists_0 == ValueUtil.TRUE_VALUE) {				// Normal successful body evaluation result
						;															// Carry on
					}
					else if (CAUGHT_exists_0 == null) {								// Abnormal null body evaluation result
						if (accumulator_1 == ValueUtil.TRUE_VALUE) {
							accumulator_1 = null;										// Cache a null failure
						}
					}
					else if (CAUGHT_exists_0 instanceof InvalidValueException) {		// Abnormal exception evaluation result
						accumulator_1 = CAUGHT_exists_0;									// Cache an exception failure
					}
					else {															// Impossible badly typed result
						accumulator_1 = new InvalidValueException(PivotMessages.NonBooleanBody, "forAll");
					}
				}
				CAUGHT_forAll_0 = forAll_0;
			}
			catch (Exception e) {
				CAUGHT_forAll_0 = ValueUtil.createInvalidValue(e);
			}
			if (CAUGHT_forAll_0 == ValueUtil.FALSE_VALUE) {
				and_0 = ValueUtil.FALSE_VALUE;
			}
			else {
				if (CAUGHT_forAll instanceof InvalidValueException) {
					throw (InvalidValueException)CAUGHT_forAll;
				}
				if (CAUGHT_forAll_0 instanceof InvalidValueException) {
					throw (InvalidValueException)CAUGHT_forAll_0;
				}
				if ((CAUGHT_forAll == null) || (CAUGHT_forAll_0 == null)) {
					and_0 = null;
				}
				else {
					and_0 = ValueUtil.TRUE_VALUE;
				}
			}
		}
		if (and_0 == null) {
			throw new InvalidValueException("Null body for \'tdl::TestConfiguration::compatibleWith(tdl::TestConfiguration[1],Set(tdl::ComponentInstanceBinding)) : Boolean[1]\'");
		}
		return and_0;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs)
	{
		switch (featureID) {
			case tdlPackage.TEST_CONFIGURATION__COMPONENT_INSTANCE:
				return ((InternalEList<?>)getComponentInstance()).basicRemove(otherEnd, msgs);
			case tdlPackage.TEST_CONFIGURATION__CONNECTION:
				return ((InternalEList<?>)getConnection()).basicRemove(otherEnd, msgs);
		}
		return super.eInverseRemove(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType)
	{
		switch (featureID) {
			case tdlPackage.TEST_CONFIGURATION__COMPONENT_INSTANCE:
				return getComponentInstance();
			case tdlPackage.TEST_CONFIGURATION__CONNECTION:
				return getConnection();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void eSet(int featureID, Object newValue)
	{
		switch (featureID) {
			case tdlPackage.TEST_CONFIGURATION__COMPONENT_INSTANCE:
				getComponentInstance().clear();
				getComponentInstance().addAll((Collection<? extends ComponentInstance>)newValue);
				return;
			case tdlPackage.TEST_CONFIGURATION__CONNECTION:
				getConnection().clear();
				getConnection().addAll((Collection<? extends Connection>)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eUnset(int featureID)
	{
		switch (featureID) {
			case tdlPackage.TEST_CONFIGURATION__COMPONENT_INSTANCE:
				getComponentInstance().clear();
				return;
			case tdlPackage.TEST_CONFIGURATION__CONNECTION:
				getConnection().clear();
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID)
	{
		switch (featureID) {
			case tdlPackage.TEST_CONFIGURATION__COMPONENT_INSTANCE:
				return componentInstance != null && !componentInstance.isEmpty();
			case tdlPackage.TEST_CONFIGURATION__CONNECTION:
				return connection != null && !connection.isEmpty();
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	@SuppressWarnings("unchecked")
	public Object eInvoke(int operationID, EList<?> arguments) throws InvocationTargetException
	{
		switch (operationID) {
			case tdlPackage.TEST_CONFIGURATION___COMPATIBLE_WITH__TESTCONFIGURATION_ELIST:
				return compatibleWith((TestConfiguration)arguments.get(0), (EList<ComponentInstanceBinding>)arguments.get(1));
		}
		return super.eInvoke(operationID, arguments);
	}

} //TestConfigurationImpl
