/**
* Copyright (c) 2012-2016 Marsha Chechik, Alessio Di Sandro, Michalis Famelis,
* Rick Salay.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alessio Di Sandro - Implementation.
*/
package edu.toronto.cs.se.mmint.mid.relationship.impl;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import edu.toronto.cs.se.mmint.MMINT;
import edu.toronto.cs.se.mmint.MMINTException;
import edu.toronto.cs.se.mmint.MIDTypeHierarchy;
import edu.toronto.cs.se.mmint.mid.ExtendibleElement;
import edu.toronto.cs.se.mmint.mid.ExtendibleElementEndpoint;
import edu.toronto.cs.se.mmint.mid.MID;
import edu.toronto.cs.se.mmint.mid.MIDLevel;
import edu.toronto.cs.se.mmint.mid.MIDPackage;
import edu.toronto.cs.se.mmint.mid.ModelElement;
import edu.toronto.cs.se.mmint.mid.impl.ExtendibleElementEndpointImpl;
import edu.toronto.cs.se.mmint.mid.relationship.BinaryMappingReference;
import edu.toronto.cs.se.mmint.mid.relationship.Mapping;
import edu.toronto.cs.se.mmint.mid.relationship.MappingReference;
import edu.toronto.cs.se.mmint.mid.relationship.ModelElementEndpoint;
import edu.toronto.cs.se.mmint.mid.relationship.ModelElementEndpointReference;
import edu.toronto.cs.se.mmint.mid.relationship.ModelElementReference;
import edu.toronto.cs.se.mmint.mid.relationship.ModelEndpointReference;
import edu.toronto.cs.se.mmint.mid.relationship.ModelRel;
import edu.toronto.cs.se.mmint.mid.relationship.RelationshipPackage;
import edu.toronto.cs.se.mmint.mid.utils.MIDRegistry;
import edu.toronto.cs.se.mmint.mid.utils.MIDTypeFactory;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Model Element Endpoint</b></em>'.
* <!-- end-user-doc -->
*
* @generated
*/
public class ModelElementEndpointImpl extends ExtendibleElementEndpointImpl implements ModelElementEndpoint {
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected ModelElementEndpointImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return RelationshipPackage.Literals.MODEL_ELEMENT_ENDPOINT;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public ModelElementEndpoint getSupertype() {
ExtendibleElementEndpoint supertype = super.getSupertype();
return (supertype == null) ? null : (ModelElementEndpoint) supertype;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public MID getMIDContainer() {
return (MID) this.eContainer().eContainer().eContainer();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public ModelElement getTarget() {
ExtendibleElement target = super.getTarget();
return (target == null) ? null : (ModelElement) target;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public ModelElementEndpoint getMetatype() {
ExtendibleElementEndpoint metatype = super.getMetatype();
return (metatype == null) ? null : (ModelElementEndpoint) metatype;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public int eDerivedOperationID(int baseOperationID, Class<?> baseClass) {
if (baseClass == ExtendibleElement.class) {
switch (baseOperationID) {
case MIDPackage.EXTENDIBLE_ELEMENT___GET_METATYPE: return RelationshipPackage.MODEL_ELEMENT_ENDPOINT___GET_METATYPE;
case MIDPackage.EXTENDIBLE_ELEMENT___GET_MID_CONTAINER: return RelationshipPackage.MODEL_ELEMENT_ENDPOINT___GET_MID_CONTAINER;
default: return super.eDerivedOperationID(baseOperationID, baseClass);
}
}
if (baseClass == ExtendibleElementEndpoint.class) {
switch (baseOperationID) {
case MIDPackage.EXTENDIBLE_ELEMENT_ENDPOINT___GET_METATYPE: return RelationshipPackage.MODEL_ELEMENT_ENDPOINT___GET_METATYPE;
case MIDPackage.EXTENDIBLE_ELEMENT_ENDPOINT___GET_SUPERTYPE: return RelationshipPackage.MODEL_ELEMENT_ENDPOINT___GET_SUPERTYPE;
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 RelationshipPackage.MODEL_ELEMENT_ENDPOINT___GET_METATYPE:
return getMetatype();
case RelationshipPackage.MODEL_ELEMENT_ENDPOINT___GET_SUPERTYPE:
return getSupertype();
case RelationshipPackage.MODEL_ELEMENT_ENDPOINT___GET_MID_CONTAINER:
return getMIDContainer();
case RelationshipPackage.MODEL_ELEMENT_ENDPOINT___GET_TARGET:
return getTarget();
case RelationshipPackage.MODEL_ELEMENT_ENDPOINT___CREATE_TYPE_REFERENCE__MODELELEMENTENDPOINTREFERENCE_MODELELEMENTREFERENCE_BOOLEAN_BOOLEAN_MAPPINGREFERENCE:
try {
return createTypeReference((ModelElementEndpointReference)arguments.get(0), (ModelElementReference)arguments.get(1), (Boolean)arguments.get(2), (Boolean)arguments.get(3), (MappingReference)arguments.get(4));
}
catch (Throwable throwable) {
throw new InvocationTargetException(throwable);
}
case RelationshipPackage.MODEL_ELEMENT_ENDPOINT___CREATE_SUBTYPE_AND_REFERENCE__STRING_MODELELEMENTREFERENCE_BOOLEAN_MAPPINGREFERENCE:
try {
return createSubtypeAndReference((String)arguments.get(0), (ModelElementReference)arguments.get(1), (Boolean)arguments.get(2), (MappingReference)arguments.get(3));
}
catch (Throwable throwable) {
throw new InvocationTargetException(throwable);
}
case RelationshipPackage.MODEL_ELEMENT_ENDPOINT___REPLACE_SUBTYPE_AND_REFERENCE__MODELELEMENTENDPOINTREFERENCE_STRING_MODELELEMENTREFERENCE:
try {
replaceSubtypeAndReference((ModelElementEndpointReference)arguments.get(0), (String)arguments.get(1), (ModelElementReference)arguments.get(2));
return null;
}
catch (Throwable throwable) {
throw new InvocationTargetException(throwable);
}
case RelationshipPackage.MODEL_ELEMENT_ENDPOINT___DELETE_TYPE__BOOLEAN:
try {
deleteType((Boolean)arguments.get(0));
return null;
}
catch (Throwable throwable) {
throw new InvocationTargetException(throwable);
}
case RelationshipPackage.MODEL_ELEMENT_ENDPOINT___CREATE_INSTANCE_REFERENCE__MODELELEMENTREFERENCE_MAPPINGREFERENCE:
try {
return createInstanceReference((ModelElementReference)arguments.get(0), (MappingReference)arguments.get(1));
}
catch (Throwable throwable) {
throw new InvocationTargetException(throwable);
}
case RelationshipPackage.MODEL_ELEMENT_ENDPOINT___CREATE_INSTANCE_AND_REFERENCE__MODELELEMENTREFERENCE_MAPPINGREFERENCE:
try {
return createInstanceAndReference((ModelElementReference)arguments.get(0), (MappingReference)arguments.get(1));
}
catch (Throwable throwable) {
throw new InvocationTargetException(throwable);
}
case RelationshipPackage.MODEL_ELEMENT_ENDPOINT___REPLACE_INSTANCE_AND_REFERENCE__MODELELEMENTENDPOINTREFERENCE_MODELELEMENTREFERENCE:
try {
replaceInstanceAndReference((ModelElementEndpointReference)arguments.get(0), (ModelElementReference)arguments.get(1));
return null;
}
catch (Throwable throwable) {
throw new InvocationTargetException(throwable);
}
}
return super.eInvoke(operationID, arguments);
}
/**
* @generated NOT
*/
public ModelElementEndpointReference createTypeReference(ModelElementEndpointReference modelElemTypeEndpointRef, ModelElementReference targetModelElemTypeRef, boolean isModifiable, boolean isBinarySrc, MappingReference containerMappingTypeRef) throws MMINTException {
MMINTException.mustBeType(this);
ModelElementEndpointReference newModelElemTypeEndpointRef = super.createThisReferenceEClass();
super.addTypeReference(newModelElemTypeEndpointRef, modelElemTypeEndpointRef, isModifiable, false);
newModelElemTypeEndpointRef.setModelElemRef(targetModelElemTypeRef);
containerMappingTypeRef.getModelElemEndpointRefs().add(newModelElemTypeEndpointRef);
if (containerMappingTypeRef instanceof BinaryMappingReference) {
((BinaryMappingReference) containerMappingTypeRef).addModelElementTypeReference(targetModelElemTypeRef, isBinarySrc);
}
return newModelElemTypeEndpointRef;
}
/**
* @generated NOT
*/
public ModelElementEndpointReference createSubtypeAndReference(String newModelElemTypeEndpointName, ModelElementReference targetModelElemTypeRef, boolean isBinarySrc, MappingReference containerMappingTypeRef) throws MMINTException {
MMINTException.mustBeType(this);
if (containerMappingTypeRef instanceof BinaryMappingReference) {
if (containerMappingTypeRef.getModelElemEndpointRefs().size() == 2) {
throw new MMINTException("Can't add more than 2 model element type endpoints to a binary mapping type");
}
if (MIDTypeHierarchy.getOverriddenModelElementTypeEndpoint(containerMappingTypeRef, targetModelElemTypeRef) != this) {
throw new MMINTException("Invalid overriding of this model element type endpoint");
}
}
ModelElementEndpointReference modelElemTypeEndpointRef = MIDRegistry.getReference(getUri(), containerMappingTypeRef.getModelElemEndpointRefs());
Mapping mappingType = containerMappingTypeRef.getObject();
ModelElement targetModelElemType = targetModelElemTypeRef.getObject();
ModelRel modelRelType = (ModelRel) containerMappingTypeRef.eContainer();
ModelEndpointReference modelTypeEndpointRef = (ModelEndpointReference) targetModelElemTypeRef.eContainer();
MID typeMID = modelRelType.getMIDContainer();
// create the "thing" and the corresponding reference
ModelElementEndpoint newModelElemTypeEndpoint = super.createThisEClass();
super.addSubtype(newModelElemTypeEndpoint, mappingType, mappingType.getName() + MMINT.ENDPOINT_SEPARATOR + targetModelElemTypeRef.getObject().getName(), newModelElemTypeEndpointName);
MIDTypeFactory.addModelElementTypeEndpoint(newModelElemTypeEndpoint, targetModelElemType, mappingType);
ModelElementEndpointReference newModelElemTypeEndpointRef = newModelElemTypeEndpoint.createTypeReference(modelElemTypeEndpointRef, targetModelElemTypeRef, true, isBinarySrc, containerMappingTypeRef);
MIDTypeFactory.addModelElementTypeEndpointReference(newModelElemTypeEndpointRef, mappingType);
// create references of the "thing" in subtypes of the container's container
for (ModelRel modelRelSubtype : MIDTypeHierarchy.getSubtypes(modelRelType, typeMID)) {
MappingReference containerMappingSubtypeRef = MIDRegistry.getReference(containerMappingTypeRef, modelRelSubtype.getMappingRefs());
ModelElementEndpointReference modelElemSubtypeEndpointRef = null;
if (modelElemTypeEndpointRef != null) {
MappingReference mappingTypeRefSuper = (MappingReference) modelElemTypeEndpointRef.eContainer();
MappingReference mappingSubtypeRefSuper = MIDRegistry.getReference(mappingTypeRefSuper, modelRelSubtype.getMappingRefs());
modelElemSubtypeEndpointRef = MIDRegistry.getReference(modelElemTypeEndpointRef, mappingSubtypeRefSuper.getModelElemEndpointRefs());
}
ModelEndpointReference modelSubtypeEndpointRef = MIDRegistry.getReference(modelTypeEndpointRef, modelRelSubtype.getModelEndpointRefs());
ModelElementReference targetModelElemSubtypeRef = MIDRegistry.getReference(targetModelElemTypeRef, modelSubtypeEndpointRef.getModelElemRefs());
newModelElemTypeEndpoint.createTypeReference(modelElemSubtypeEndpointRef, targetModelElemSubtypeRef, false, isBinarySrc, containerMappingSubtypeRef);
}
// create references of the "thing" in subtypes of the container
for (Mapping mappingSubtype : MIDTypeHierarchy.getSubtypes(mappingType, typeMID)) {
MIDTypeFactory.addModelElementTypeEndpointReference(newModelElemTypeEndpointRef, mappingSubtype);
}
return newModelElemTypeEndpointRef;
}
/**
* @generated NOT
*/
public void replaceSubtypeAndReference(ModelElementEndpointReference oldModelElemTypeEndpointRef, String newModelElemTypeEndpointName, ModelElementReference targetModelElemTypeRef) throws MMINTException {
MMINTException.mustBeType(this);
MappingReference containerMappingTypeRef = (MappingReference) oldModelElemTypeEndpointRef.eContainer();
if (containerMappingTypeRef instanceof BinaryMappingReference) {
if (MIDTypeHierarchy.getOverriddenModelElementTypeEndpoint(containerMappingTypeRef, targetModelElemTypeRef) != this) {
throw new MMINTException("Invalid overriding of this model element type endpoint");
}
}
ModelElementEndpointReference modelElemTypeEndpointRef = MIDRegistry.getReference(getUri(), containerMappingTypeRef.getModelElemEndpointRefs());
oldModelElemTypeEndpointRef.deleteTypeAndReference(false);
ModelElementEndpoint oldModelElemTypeEndpoint = oldModelElemTypeEndpointRef.getObject();
Mapping mappingType = containerMappingTypeRef.getObject();
ModelElement newModelElemType = targetModelElemTypeRef.getObject();
ModelRel modelRelType = (ModelRel) containerMappingTypeRef.eContainer();
ModelEndpointReference modelTypeEndpointRef = (ModelEndpointReference) targetModelElemTypeRef.eContainer();
MID typeMID = containerMappingTypeRef.getMIDContainer();
// modify the "thing" and the corresponding reference
super.addSubtype(oldModelElemTypeEndpoint, mappingType, mappingType.getName() + MMINT.ENDPOINT_SEPARATOR + newModelElemType.getName(), newModelElemTypeEndpointName);
if (containerMappingTypeRef instanceof BinaryMappingReference) {
boolean isBinarySrc = ((BinaryMappingReference) containerMappingTypeRef).getSourceModelElemRef() == oldModelElemTypeEndpointRef.getModelElemRef();
((BinaryMappingReference) containerMappingTypeRef).addModelElementTypeReference(targetModelElemTypeRef, isBinarySrc);
}
oldModelElemTypeEndpoint.setTarget(newModelElemType);
oldModelElemTypeEndpointRef.setModelElemRef(targetModelElemTypeRef);
if (modelElemTypeEndpointRef != null) {
oldModelElemTypeEndpointRef.setSupertypeRef(modelElemTypeEndpointRef);
}
// modify references of the "thing" in subtypes of the container's container
for (ModelRel modelRelSubtype : MIDTypeHierarchy.getSubtypes(modelRelType, typeMID)) {
MappingReference mappingSubtypeRef = MIDRegistry.getReference(containerMappingTypeRef, modelRelSubtype.getMappingRefs());
ModelElementEndpointReference modelElemSubtypeEndpointRef = null;
if (modelElemTypeEndpointRef != null) {
MappingReference mappingTypeRefSuper = (MappingReference) modelElemTypeEndpointRef.eContainer();
MappingReference mappingSubtypeRefSuper = MIDRegistry.getReference(mappingTypeRefSuper, modelRelSubtype.getMappingRefs());
modelElemSubtypeEndpointRef = MIDRegistry.getReference(modelElemTypeEndpointRef, mappingSubtypeRefSuper.getModelElemEndpointRefs());
}
ModelEndpointReference modelSubtypeEndpointRef = MIDRegistry.getReference(modelTypeEndpointRef, modelRelSubtype.getModelEndpointRefs());
ModelElementReference newModelElemSubtypeRef = MIDRegistry.getReference(targetModelElemTypeRef, modelSubtypeEndpointRef.getModelElemRefs());
ModelElementEndpointReference oldModelElemSubtypeEndpointRef = MIDRegistry.getReference(oldModelElemTypeEndpointRef, mappingSubtypeRef.getModelElemEndpointRefs());
oldModelElemTypeEndpointRef.setModelElemRef(newModelElemSubtypeRef);
oldModelElemSubtypeEndpointRef.setSupertypeRef(modelElemSubtypeEndpointRef);
}
}
/**
* @generated NOT
*/
public void deleteType(boolean isFullDelete) throws MMINTException {
MMINTException.mustBeType(this);
super.delete();
if (isFullDelete) {
((Mapping) this.eContainer()).getModelElemEndpoints().remove(this);
}
}
/**
* @generated NOT
*/
public ModelElementEndpointReference createInstanceReference(ModelElementReference targetModelElemRef, MappingReference containerMappingRef) throws MMINTException {
MMINTException.mustBeInstance(this);
ModelElementEndpointReference newModelElemEndpointRef = super.createThisReferenceEClass();
boolean isContainer = containerMappingRef.eContainer().eContainer() == null;
super.addInstanceReference(newModelElemEndpointRef, isContainer);
newModelElemEndpointRef.setModelElemRef(targetModelElemRef);
containerMappingRef.getModelElemEndpointRefs().add(newModelElemEndpointRef);
if (containerMappingRef instanceof BinaryMappingReference) {
boolean isBinarySrc = containerMappingRef.getModelElemEndpointRefs().size() == 1;
if (isBinarySrc) {
((BinaryMappingReference) containerMappingRef).setSourceModelElemRef(targetModelElemRef);
}
else {
((BinaryMappingReference) containerMappingRef).setTargetModelElemRef(targetModelElemRef);
}
}
return newModelElemEndpointRef;
}
/**
* @generated NOT
*/
public ModelElementEndpointReference createInstanceAndReference(ModelElementReference targetModelElemRef, MappingReference containerMappingRef) throws MMINTException {
MMINTException.mustBeType(this);
if ((containerMappingRef instanceof BinaryMappingReference) && (containerMappingRef.getModelElemEndpointRefs().size() == 2)) {
throw new MMINTException("Can't add more than 2 model element endpoints to a binary mapping");
}
ModelElementEndpoint newModelElemEndpoint = super.createThisEClass();
super.addBasicInstance(newModelElemEndpoint, null, targetModelElemRef.getObject().getName(), MIDLevel.INSTANCES);
super.addInstanceEndpoint(newModelElemEndpoint, targetModelElemRef.getObject());
containerMappingRef.getObject().getModelElemEndpoints().add(newModelElemEndpoint);
ModelElementEndpointReference modelElemEndpointRef = newModelElemEndpoint.createInstanceReference(targetModelElemRef, containerMappingRef);
containerMappingRef.getObject().getModelElemEndpointRefs().add(modelElemEndpointRef);
return modelElemEndpointRef;
}
/**
* @generated NOT
*/
public void replaceInstanceAndReference(ModelElementEndpointReference oldModelElemEndpointRef, ModelElementReference targetModelElemRef) throws MMINTException {
MMINTException.mustBeType(this);
MappingReference containerMappingRef = (MappingReference) oldModelElemEndpointRef.eContainer();
oldModelElemEndpointRef.deleteInstanceAndReference(false);
ModelElementEndpoint oldModelElemEndpoint = oldModelElemEndpointRef.getObject();
super.addBasicInstance(oldModelElemEndpoint, null, null, MIDLevel.INSTANCES);
if (containerMappingRef instanceof BinaryMappingReference) {
boolean isBinarySrc = ((BinaryMappingReference) containerMappingRef).getSourceModelElemRef() == oldModelElemEndpointRef.getModelElemRef();
if (isBinarySrc) {
((BinaryMappingReference) containerMappingRef).setSourceModelElemRef(targetModelElemRef);
}
else {
((BinaryMappingReference) containerMappingRef).setTargetModelElemRef(targetModelElemRef);
}
}
oldModelElemEndpoint.setTarget(targetModelElemRef.getObject());
oldModelElemEndpointRef.setModelElemRef(targetModelElemRef);
}
} //ModelElementEndpointImpl