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

import java.lang.reflect.InvocationTargetException;

import java.math.BigInteger;

import java.util.Iterator;
import org.eclipse.emf.common.notify.Notification;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;

import org.eclipse.emf.ecore.impl.ENotificationImpl;

import org.eclipse.ocl.pivot.evaluation.Executor;
import org.eclipse.ocl.pivot.ids.IdResolver;
import org.eclipse.ocl.pivot.library.classifier.ClassifierAllInstancesOperation;
import org.eclipse.ocl.pivot.library.collection.CollectionAsOrderedSetOperation;
import org.eclipse.ocl.pivot.library.collection.OrderedCollectionFirstOperation;
import org.eclipse.ocl.pivot.library.oclany.OclAnyOclAsTypeOperation;
import org.eclipse.ocl.pivot.library.oclany.OclAnyOclIsTypeOfOperation;
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.OrderedSetValue;
import org.eclipse.ocl.pivot.values.SetValue;
import org.eclipse.ocl.pivot.values.SetValue.Accumulator;
import org.etsi.mts.tdl.DataType;
import org.etsi.mts.tdl.DataUse;
import org.etsi.mts.tdl.Element;
import org.etsi.mts.tdl.LiteralValueUse;
import org.etsi.mts.tdl.Member;
import org.etsi.mts.tdl.MemberAssignment;
import org.etsi.mts.tdl.Parameter;
import org.etsi.mts.tdl.ParameterBinding;
import org.etsi.mts.tdl.SimpleDataType;
import org.etsi.mts.tdl.tdlPackage;
import org.etsi.mts.tdl.tdlTables;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Literal Value Use</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * </p>
 * <ul>
 *   <li>{@link org.etsi.mts.tdl.impl.LiteralValueUseImpl#getValue <em>Value</em>}</li>
 *   <li>{@link org.etsi.mts.tdl.impl.LiteralValueUseImpl#getIntValue <em>Int Value</em>}</li>
 *   <li>{@link org.etsi.mts.tdl.impl.LiteralValueUseImpl#getBoolValue <em>Bool Value</em>}</li>
 *   <li>{@link org.etsi.mts.tdl.impl.LiteralValueUseImpl#getDataType <em>Data Type</em>}</li>
 * </ul>
 *
 * @generated
 */
public class LiteralValueUseImpl extends StaticDataUseImpl implements LiteralValueUse
{
	/**
	 * The default value of the '{@link #getValue() <em>Value</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getValue()
	 * @generated
	 * @ordered
	 */
	protected static final String VALUE_EDEFAULT = null;

	/**
	 * The cached value of the '{@link #getValue() <em>Value</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getValue()
	 * @generated
	 * @ordered
	 */
	protected String value = VALUE_EDEFAULT;

	/**
	 * The default value of the '{@link #getIntValue() <em>Int Value</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getIntValue()
	 * @generated
	 * @ordered
	 */
	protected static final BigInteger INT_VALUE_EDEFAULT = null;

	/**
	 * The cached value of the '{@link #getIntValue() <em>Int Value</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getIntValue()
	 * @generated
	 * @ordered
	 */
	protected BigInteger intValue = INT_VALUE_EDEFAULT;

	/**
	 * The default value of the '{@link #getBoolValue() <em>Bool Value</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getBoolValue()
	 * @generated
	 * @ordered
	 */
	protected static final Boolean BOOL_VALUE_EDEFAULT = null;

	/**
	 * The cached value of the '{@link #getBoolValue() <em>Bool Value</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getBoolValue()
	 * @generated
	 * @ordered
	 */
	protected Boolean boolValue = BOOL_VALUE_EDEFAULT;

	/**
	 * The cached value of the '{@link #getDataType() <em>Data Type</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getDataType()
	 * @generated
	 * @ordered
	 */
	protected DataType dataType;

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

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

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public String getValue()
	{
		return value;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void setValue(String newValue)
	{
		String oldValue = value;
		value = newValue;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, tdlPackage.LITERAL_VALUE_USE__VALUE, oldValue, value));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public BigInteger getIntValue()
	{
		return intValue;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void setIntValue(BigInteger newIntValue)
	{
		BigInteger oldIntValue = intValue;
		intValue = newIntValue;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, tdlPackage.LITERAL_VALUE_USE__INT_VALUE, oldIntValue, intValue));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Boolean getBoolValue()
	{
		return boolValue;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void setBoolValue(Boolean newBoolValue)
	{
		Boolean oldBoolValue = boolValue;
		boolValue = newBoolValue;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, tdlPackage.LITERAL_VALUE_USE__BOOL_VALUE, oldBoolValue, boolValue));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public DataType getDataType()
	{
		if (dataType != null && dataType.eIsProxy()) {
			InternalEObject oldDataType = (InternalEObject)dataType;
			dataType = (DataType)eResolveProxy(oldDataType);
			if (dataType != oldDataType) {
				if (eNotificationRequired())
					eNotify(new ENotificationImpl(this, Notification.RESOLVE, tdlPackage.LITERAL_VALUE_USE__DATA_TYPE, oldDataType, dataType));
			}
		}
		return dataType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public DataType basicGetDataType()
	{
		return dataType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void setDataType(DataType newDataType)
	{
		DataType oldDataType = dataType;
		dataType = newDataType;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, tdlPackage.LITERAL_VALUE_USE__DATA_TYPE, oldDataType, dataType));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public DataType resolveDataType()
	{
		/**
		 *
		 * if not self.dataType.oclIsUndefined()
		 * then self.dataType
		 * else
		 *   if self.container().oclIsTypeOf(MemberAssignment)
		 *   then
		 *     self.container()
		 *     .oclAsType(MemberAssignment).member.dataType
		 *   else
		 *     if self.container().oclIsTypeOf(ParameterBinding)
		 *     then
		 *       self.container()
		 *       .oclAsType(ParameterBinding).parameter.dataType
		 *     else
		 *       if not self.intValue.oclIsUndefined()
		 *       then
		 *         SimpleDataType.allInstances()
		 *         ->select(t | t.name = 'Integer')
		 *         ->asOrderedSet()
		 *         ->first()
		 *       else
		 *         if not self.boolValue.oclIsUndefined()
		 *         then
		 *           SimpleDataType.allInstances()
		 *           ->select(t | t.name = 'Boolean')
		 *           ->asOrderedSet()
		 *           ->first()
		 *         else
		 *           SimpleDataType.allInstances()
		 *           ->select(t | t.name = 'String')
		 *           ->asOrderedSet()
		 *           ->first()
		 *         endif
		 *       endif
		 *     endif
		 *   endif
		 * endif
		 */
		final /*@NonInvalid*/ Executor executor = PivotUtil.getExecutor(this);
		final /*@NonInvalid*/ IdResolver idResolver = executor.getIdResolver();
		final /*@NonInvalid*/ DataType dataType_0 = this.getDataType();
		final /*@NonInvalid*/ boolean oclIsUndefined = dataType_0 == null;
		final /*@NonInvalid*/ Boolean not;
		if (!oclIsUndefined) {
			not = ValueUtil.TRUE_VALUE;
		}
		else {
			if (oclIsUndefined) {
				not = ValueUtil.FALSE_VALUE;
			}
			else {
				not = null;
			}
		}
		if (not == null) {
			throw new InvalidValueException("Null if condition");
		}
		/*@Thrown*/ DataType local_4;
		if (not) {
			local_4 = dataType_0;
		}
		else {
			final /*@NonInvalid*/ org.eclipse.ocl.pivot.Class TYP_tdl_c_c_MemberAssignment_0 = idResolver.getClass(tdlTables.CLSSid_MemberAssignment, null);
			final /*@NonInvalid*/ Element container = this.container();
			final /*@NonInvalid*/ boolean oclIsTypeOf = OclAnyOclIsTypeOfOperation.INSTANCE.evaluate(executor, container, TYP_tdl_c_c_MemberAssignment_0).booleanValue();
			/*@Thrown*/ DataType local_3;
			if (oclIsTypeOf) {
				final /*@Thrown*/ MemberAssignment oclAsType = (MemberAssignment)OclAnyOclAsTypeOperation.INSTANCE.evaluate(executor, container, TYP_tdl_c_c_MemberAssignment_0);
				final /*@Thrown*/ Member member = oclAsType.getMember();
				final /*@Thrown*/ DataType dataType_1 = member.getDataType();
				local_3 = dataType_1;
			}
			else {
				final /*@NonInvalid*/ org.eclipse.ocl.pivot.Class TYP_tdl_c_c_ParameterBinding_0 = idResolver.getClass(tdlTables.CLSSid_ParameterBinding, null);
				final /*@NonInvalid*/ boolean oclIsTypeOf_0 = OclAnyOclIsTypeOfOperation.INSTANCE.evaluate(executor, container, TYP_tdl_c_c_ParameterBinding_0).booleanValue();
				/*@Thrown*/ DataType local_2;
				if (oclIsTypeOf_0) {
					final /*@Thrown*/ ParameterBinding oclAsType_0 = (ParameterBinding)OclAnyOclAsTypeOperation.INSTANCE.evaluate(executor, container, TYP_tdl_c_c_ParameterBinding_0);
					final /*@Thrown*/ Parameter parameter = oclAsType_0.getParameter();
					final /*@Thrown*/ DataType dataType_2 = parameter.getDataType();
					local_2 = dataType_2;
				}
				else {
					final /*@NonInvalid*/ org.eclipse.ocl.pivot.Class TYP_tdl_c_c_SimpleDataType_0 = idResolver.getClass(tdlTables.CLSSid_SimpleDataType, null);
					final /*@NonInvalid*/ SetValue allInstances = ClassifierAllInstancesOperation.INSTANCE.evaluate(executor, tdlTables.SET_CLSSid_SimpleDataType, TYP_tdl_c_c_SimpleDataType_0);
					final /*@NonInvalid*/ BigInteger intValue = this.getIntValue();
					final /*@NonInvalid*/ boolean oclIsUndefined_0 = intValue == null;
					final /*@NonInvalid*/ Boolean not_0;
					if (!oclIsUndefined_0) {
						not_0 = ValueUtil.TRUE_VALUE;
					}
					else {
						if (oclIsUndefined_0) {
							not_0 = ValueUtil.FALSE_VALUE;
						}
						else {
							not_0 = null;
						}
					}
					if (not_0 == null) {
						throw new InvalidValueException("Null if condition");
					}
					/*@Thrown*/ SimpleDataType local_1;
					if (not_0) {
						/*@Thrown*/ Accumulator accumulator = ValueUtil.createSetAccumulatorValue(tdlTables.SET_CLSSid_SimpleDataType);
						Iterator<Object> ITERATOR_t = allInstances.iterator();
						/*@NonInvalid*/ SetValue select;
						while (true) {
							if (!ITERATOR_t.hasNext()) {
								select = accumulator;
								break;
							}
							/*@NonInvalid*/ SimpleDataType t = (SimpleDataType)ITERATOR_t.next();
							/**
							 * t.name = 'Integer'
							 */
							final /*@NonInvalid*/ String name = t.getName();
							final /*@NonInvalid*/ boolean eq = tdlTables.STR_Integer.equals(name);
							//
							if (eq) {
								accumulator.add(t);
							}
						}
						final /*@NonInvalid*/ OrderedSetValue asOrderedSet = CollectionAsOrderedSetOperation.INSTANCE.evaluate(select);
						final /*@Thrown*/ SimpleDataType first = (SimpleDataType)OrderedCollectionFirstOperation.INSTANCE.evaluate(asOrderedSet);
						local_1 = first;
					}
					else {
						final /*@NonInvalid*/ Boolean boolValue = this.getBoolValue();
						final /*@NonInvalid*/ boolean oclIsUndefined_1 = boolValue == null;
						final /*@NonInvalid*/ Boolean not_1;
						if (!oclIsUndefined_1) {
							not_1 = ValueUtil.TRUE_VALUE;
						}
						else {
							if (oclIsUndefined_1) {
								not_1 = ValueUtil.FALSE_VALUE;
							}
							else {
								not_1 = null;
							}
						}
						if (not_1 == null) {
							throw new InvalidValueException("Null if condition");
						}
						/*@Thrown*/ SimpleDataType local_0;
						if (not_1) {
							/*@Thrown*/ Accumulator accumulator_0 = ValueUtil.createSetAccumulatorValue(tdlTables.SET_CLSSid_SimpleDataType);
							Iterator<Object> ITERATOR_t_0 = allInstances.iterator();
							/*@NonInvalid*/ SetValue select_0;
							while (true) {
								if (!ITERATOR_t_0.hasNext()) {
									select_0 = accumulator_0;
									break;
								}
								/*@NonInvalid*/ SimpleDataType t_0 = (SimpleDataType)ITERATOR_t_0.next();
								/**
								 * t.name = 'Boolean'
								 */
								final /*@NonInvalid*/ String name_0 = t_0.getName();
								final /*@NonInvalid*/ boolean eq_0 = tdlTables.STR_Boolean.equals(name_0);
								//
								if (eq_0) {
									accumulator_0.add(t_0);
								}
							}
							final /*@NonInvalid*/ OrderedSetValue asOrderedSet_0 = CollectionAsOrderedSetOperation.INSTANCE.evaluate(select_0);
							final /*@Thrown*/ SimpleDataType first_0 = (SimpleDataType)OrderedCollectionFirstOperation.INSTANCE.evaluate(asOrderedSet_0);
							local_0 = first_0;
						}
						else {
							/*@Thrown*/ Accumulator accumulator_1 = ValueUtil.createSetAccumulatorValue(tdlTables.SET_CLSSid_SimpleDataType);
							Iterator<Object> ITERATOR_t_1 = allInstances.iterator();
							/*@NonInvalid*/ SetValue select_1;
							while (true) {
								if (!ITERATOR_t_1.hasNext()) {
									select_1 = accumulator_1;
									break;
								}
								/*@NonInvalid*/ SimpleDataType t_1 = (SimpleDataType)ITERATOR_t_1.next();
								/**
								 * t.name = 'String'
								 */
								final /*@NonInvalid*/ String name_1 = t_1.getName();
								final /*@NonInvalid*/ boolean eq_1 = tdlTables.STR_String.equals(name_1);
								//
								if (eq_1) {
									accumulator_1.add(t_1);
								}
							}
							final /*@NonInvalid*/ OrderedSetValue asOrderedSet_1 = CollectionAsOrderedSetOperation.INSTANCE.evaluate(select_1);
							final /*@Thrown*/ SimpleDataType first_1 = (SimpleDataType)OrderedCollectionFirstOperation.INSTANCE.evaluate(asOrderedSet_1);
							local_0 = first_1;
						}
						local_1 = local_0;
					}
					local_2 = local_1;
				}
				local_3 = local_2;
			}
			local_4 = local_3;
		}
		return local_4;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType)
	{
		switch (featureID) {
			case tdlPackage.LITERAL_VALUE_USE__VALUE:
				return getValue();
			case tdlPackage.LITERAL_VALUE_USE__INT_VALUE:
				return getIntValue();
			case tdlPackage.LITERAL_VALUE_USE__BOOL_VALUE:
				return getBoolValue();
			case tdlPackage.LITERAL_VALUE_USE__DATA_TYPE:
				if (resolve) return getDataType();
				return basicGetDataType();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eSet(int featureID, Object newValue)
	{
		switch (featureID) {
			case tdlPackage.LITERAL_VALUE_USE__VALUE:
				setValue((String)newValue);
				return;
			case tdlPackage.LITERAL_VALUE_USE__INT_VALUE:
				setIntValue((BigInteger)newValue);
				return;
			case tdlPackage.LITERAL_VALUE_USE__BOOL_VALUE:
				setBoolValue((Boolean)newValue);
				return;
			case tdlPackage.LITERAL_VALUE_USE__DATA_TYPE:
				setDataType((DataType)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eUnset(int featureID)
	{
		switch (featureID) {
			case tdlPackage.LITERAL_VALUE_USE__VALUE:
				setValue(VALUE_EDEFAULT);
				return;
			case tdlPackage.LITERAL_VALUE_USE__INT_VALUE:
				setIntValue(INT_VALUE_EDEFAULT);
				return;
			case tdlPackage.LITERAL_VALUE_USE__BOOL_VALUE:
				setBoolValue(BOOL_VALUE_EDEFAULT);
				return;
			case tdlPackage.LITERAL_VALUE_USE__DATA_TYPE:
				setDataType((DataType)null);
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID)
	{
		switch (featureID) {
			case tdlPackage.LITERAL_VALUE_USE__VALUE:
				return VALUE_EDEFAULT == null ? value != null : !VALUE_EDEFAULT.equals(value);
			case tdlPackage.LITERAL_VALUE_USE__INT_VALUE:
				return INT_VALUE_EDEFAULT == null ? intValue != null : !INT_VALUE_EDEFAULT.equals(intValue);
			case tdlPackage.LITERAL_VALUE_USE__BOOL_VALUE:
				return BOOL_VALUE_EDEFAULT == null ? boolValue != null : !BOOL_VALUE_EDEFAULT.equals(boolValue);
			case tdlPackage.LITERAL_VALUE_USE__DATA_TYPE:
				return dataType != null;
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public int eDerivedOperationID(int baseOperationID, Class<?> baseClass)
	{
		if (baseClass == DataUse.class) {
			switch (baseOperationID) {
				case tdlPackage.DATA_USE___RESOLVE_DATA_TYPE: return tdlPackage.LITERAL_VALUE_USE___RESOLVE_DATA_TYPE;
				default: return super.eDerivedOperationID(baseOperationID, baseClass);
			}
		}
		return super.eDerivedOperationID(baseOperationID, baseClass);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eInvoke(int operationID, EList<?> arguments) throws InvocationTargetException
	{
		switch (operationID) {
			case tdlPackage.LITERAL_VALUE_USE___RESOLVE_DATA_TYPE:
				return resolveDataType();
		}
		return super.eInvoke(operationID, arguments);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public String toString()
	{
		if (eIsProxy()) return super.toString();

		StringBuilder result = new StringBuilder(super.toString());
		result.append(" (value: ");
		result.append(value);
		result.append(", intValue: ");
		result.append(intValue);
		result.append(", boolValue: ");
		result.append(boolValue);
		result.append(')');
		return result.toString();
	}

} //LiteralValueUseImpl
