/**
* 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.modelepedia.kleisli.impl;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import edu.toronto.cs.se.mmint.MMINTException;
import edu.toronto.cs.se.mmint.MIDTypeRegistry;
import edu.toronto.cs.se.mmint.mid.EMFInfo;
import edu.toronto.cs.se.mmint.mid.ExtendibleElementConstraint;
import edu.toronto.cs.se.mmint.mid.MID;
import edu.toronto.cs.se.mmint.mid.MIDFactory;
import edu.toronto.cs.se.mmint.mid.MIDLevel;
import edu.toronto.cs.se.mmint.mid.Model;
import edu.toronto.cs.se.mmint.mid.ModelElement;
import edu.toronto.cs.se.mmint.mid.ModelEndpoint;
import edu.toronto.cs.se.mmint.mid.ModelOrigin;
import edu.toronto.cs.se.mmint.mid.editor.Editor;
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.impl.ModelRelImpl;
import edu.toronto.cs.se.mmint.mid.ui.GMFUtils;
import edu.toronto.cs.se.mmint.mid.utils.FileUtils;
import edu.toronto.cs.se.mmint.mid.utils.MIDRegistry;
import edu.toronto.cs.se.modelepedia.kleisli.KleisliModelEndpoint;
import edu.toronto.cs.se.modelepedia.kleisli.KleisliModelEndpointReference;
import edu.toronto.cs.se.modelepedia.kleisli.KleisliModelRel;
import edu.toronto.cs.se.modelepedia.kleisli.KleisliPackage;
import edu.toronto.cs.se.modelepedia.kleisli.reasoning.KleisliReasoningEngine;
import edu.toronto.cs.se.modelepedia.ocl.reasoning.OCLReasoningEngine;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Model Rel</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* </p>
* <ul>
* <li>{@link edu.toronto.cs.se.modelepedia.kleisli.impl.KleisliModelRelImpl#getExtendedUri <em>Extended Uri</em>}</li>
* </ul>
*
* @generated
*/
public class KleisliModelRelImpl extends ModelRelImpl implements KleisliModelRel {
/**
* The default value of the '{@link #getExtendedUri() <em>Extended Uri</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getExtendedUri()
* @generated
* @ordered
*/
protected static final String EXTENDED_URI_EDEFAULT = null;
/**
* The cached value of the '{@link #getExtendedUri() <em>Extended Uri</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getExtendedUri()
* @generated
* @ordered
*/
protected String extendedUri = EXTENDED_URI_EDEFAULT;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected KleisliModelRelImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return KleisliPackage.Literals.KLEISLI_MODEL_REL;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public String getExtendedUri() {
return extendedUri;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setExtendedUri(String newExtendedUri) {
String oldExtendedUri = extendedUri;
extendedUri = newExtendedUri;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, KleisliPackage.KLEISLI_MODEL_REL__EXTENDED_URI, oldExtendedUri, extendedUri));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case KleisliPackage.KLEISLI_MODEL_REL__EXTENDED_URI:
return getExtendedUri();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case KleisliPackage.KLEISLI_MODEL_REL__EXTENDED_URI:
setExtendedUri((String)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case KleisliPackage.KLEISLI_MODEL_REL__EXTENDED_URI:
setExtendedUri(EXTENDED_URI_EDEFAULT);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case KleisliPackage.KLEISLI_MODEL_REL__EXTENDED_URI:
return EXTENDED_URI_EDEFAULT == null ? extendedUri != null : !EXTENDED_URI_EDEFAULT.equals(extendedUri);
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public String toString() {
if (eIsProxy()) return super.toString();
StringBuffer result = new StringBuffer(super.toString());
result.append(" (extendedUri: ");
result.append(extendedUri);
result.append(')');
return result.toString();
}
/**
* Gets the uri of a Kleisli model relationship type extension.
*
* @param modelRelType
* The Kleisli model relationship type.
* @return The uri of the Kleisli model relationship type extension.
* @generated NOT
*/
private String getModelRelTypeExtendedUri(KleisliModelRel modelRelType) {
return modelRelType.getName();
}
/**
* Kleisli version. {@inheritDoc}
*
* @generated NOT
*/
@Override
protected void addSubtype(Model newModelRelType, String newModelRelTypeName, boolean isMetamodelExtension) throws MMINTException {
super.addSubtype(newModelRelType, newModelRelTypeName, false);
String newModelRelTypeExtendedUri = getModelRelTypeExtendedUri((KleisliModelRel) newModelRelType);
((KleisliModelRel) newModelRelType).setExtendedUri(newModelRelTypeExtendedUri);
if (!FileUtils.isFileOrDirectoryInState(newModelRelTypeExtendedUri)) {
try {
FileUtils.createDirectoryInState(newModelRelTypeExtendedUri);
}
catch (Exception e) {
newModelRelType.deleteType();
throw new MMINTException("Error creating directory for extended metamodels", e);
}
}
}
/**
* @generated NOT
*/
@Override
public ModelRel copySubtype(ModelRel origModelRelType) throws MMINTException {
ModelRel newModelRelType = super.copySubtype(origModelRelType);
MID typeMID = newModelRelType.getMIDContainer();
ExtendibleElementConstraint newConstraint, origConstraint;
ModelElement newModelElemType;
for (ModelEndpointReference origModelTypeEndpointRef : origModelRelType.getModelEndpointRefs()) {
if (!(origModelTypeEndpointRef instanceof KleisliModelEndpointReference)) {
continue;
}
for (ModelElementReference origModelElemTypeRef : origModelTypeEndpointRef.getModelElemRefs()) {
if (!origModelElemTypeRef.isModifiable()) {
continue;
}
origConstraint = origModelElemTypeRef.getObject().getConstraint();
if (origConstraint != null) {
newConstraint = MIDFactory.eINSTANCE.createExtendibleElementConstraint();
newConstraint.setLanguage(origConstraint.getLanguage());
newConstraint.setImplementation(origConstraint.getImplementation());
newModelElemType = typeMID.getExtendibleElement(origModelElemTypeRef.getUri());
newModelElemType.setConstraint(newConstraint);
}
}
}
return newModelRelType;
}
/**
* @generated NOT
*/
@Override
public void deleteType() throws MMINTException {
super.deleteType();
FileUtils.deleteDirectoryInState(getExtendedUri());
}
/**
* @generated NOT
*/
@Override
public ResourceSet getOutlineResourceTypes() throws MMINTException {
MMINTException.mustBeType(this);
ResourceSet resourceSet = new ResourceSetImpl();
List<Resource> resources = resourceSet.getResources();
for (ModelEndpointReference modelTypeEndpointRef : getModelEndpointRefs()) {
ModelEndpoint modelTypeEndpoint = modelTypeEndpointRef.getObject();
Model modelType = (modelTypeEndpoint instanceof KleisliModelEndpoint) ?
((KleisliModelEndpoint) modelTypeEndpoint).getExtendedTarget() :
modelTypeEndpoint.getTarget();
do {
resources.add(modelType.getEMFTypeRoot().eResource());
modelType = modelType.getSupertype();
}
while (modelType != null && !modelType.isAbstract());
}
return resourceSet;
}
/**
* Kleisli version. {@inheritDoc}
*
* @generated NOT
*/
@Override
protected void addInstance(@NonNull Model newModelRel, @Nullable String newModelRelId, @NonNull String newModelRelName, @NonNull ModelOrigin origin, @NonNull String fileExtension, @NonNull MIDLevel midLevel, @Nullable MID instanceMID) throws MMINTException {
super.addInstance(newModelRel, newModelRelId, newModelRelName, origin, fileExtension, midLevel, instanceMID);
String baseModelRelExtendedUri = FileUtils.replaceLastSegmentInUri(MIDRegistry.getModelAndModelElementUris(newModelRel, MIDLevel.INSTANCES)[0], getName());
String modelRelExtendedUri = FileUtils.getUniqueUri(baseModelRelExtendedUri, true, true);
((KleisliModelRel) newModelRel).setExtendedUri(modelRelExtendedUri);
try {
FileUtils.createDirectory(modelRelExtendedUri, true);
}
catch (Exception e) {
newModelRel.deleteInstance();
throw new MMINTException("Error creating directory for extended models", e);
}
}
/**
* @generated NOT
*/
@Override
public void deleteInstance() throws MMINTException {
super.deleteInstance();
FileUtils.deleteDirectory(getExtendedUri(), true);
}
/**
* @generated NOT
*/
@Override
public ResourceSet getOutlineResourceInstances() throws MMINTException {
MMINTException.mustBeInstance(this);
ResourceSet resourceSet = new ResourceSetImpl();
List<Resource> resources = resourceSet.getResources();
for (ModelEndpointReference modelEndpointRef : getModelEndpointRefs()) {
ModelEndpoint modelEndpoint = modelEndpointRef.getObject();
Model model = (modelEndpoint instanceof KleisliModelEndpoint) ?
((KleisliModelEndpoint) modelEndpoint).getExtendedTarget() :
modelEndpoint.getTarget();
resources.add(model.getEMFInstanceRoot().eResource());
}
return resourceSet;
}
/**
* @generated NOT
*/
@Override
public void openType() throws Exception {
super.openType();
Model ecoreModelType = MIDTypeRegistry.getType(EcorePackage.eNS_URI);
Editor ecoreEditorType = ecoreModelType.getEditors().get(0);
for (ModelEndpoint modelTypeEndpoint : getModelEndpoints()) {
if (!(modelTypeEndpoint instanceof KleisliModelEndpoint)) {
continue;
}
String kModelTypeUriRelative = ((KleisliModelEndpoint) modelTypeEndpoint).getExtendedTargetUri();
String kModelTypeUri = (FileUtils.isFileOrDirectoryInState(kModelTypeUriRelative)) ?
kModelTypeUriRelative:
null;
if (kModelTypeUri != null) { // the root KleisliModelRel has no extended metamodel to open
String kModelTypeDiagramUri = (FileUtils.isFileOrDirectoryInState(kModelTypeUriRelative + GMFUtils.DIAGRAM_SUFFIX)) ?
kModelTypeUriRelative + GMFUtils.DIAGRAM_SUFFIX:
null;
String kUri = (kModelTypeDiagramUri == null) ? kModelTypeUri : kModelTypeDiagramUri;
//TODO MMINT[ECORE] Try to open ecore diagram
String editorId = (kModelTypeDiagramUri == null) ? ecoreEditorType.getId() : ecoreEditorType.getId();
try {
FileUtils.openEclipseEditorInState(kUri, editorId);
}
catch (MMINTException e) {
MMINTException.print(IStatus.ERROR, "Error opening extended metamodel file", e);
}
}
}
}
/**
* @generated NOT
*/
@Override
public void openInstance() throws Exception {
super.openInstance();
// extend models (doing it at every open is robust against model change)
OCLReasoningEngine oclReasoner = new OCLReasoningEngine();
KleisliReasoningEngine kReasoner = new KleisliReasoningEngine();
for (ModelEndpoint modelEndpoint : getModelEndpoints()) {
ModelEndpoint modelTypeEndpoint = modelEndpoint.getMetatype();
if (!(modelTypeEndpoint instanceof KleisliModelEndpoint)) {
continue;
}
KleisliModelEndpoint kModelTypeEndpoint = (KleisliModelEndpoint) modelTypeEndpoint;
KleisliModelEndpoint kModelEndpoint = (KleisliModelEndpoint) modelEndpoint;
try {
EPackage kModelTypePackage = kModelTypeEndpoint.getExtendedTarget().getEMFTypeRoot();
EFactory kModelTypeFactory = kModelTypePackage.getEFactoryInstance();
KleisliModelEndpointReference kModelTypeEndpointRef = (KleisliModelEndpointReference) MIDRegistry.getReference(kModelTypeEndpoint.getUri(), ((ModelRel) kModelTypeEndpoint.eContainer()).getModelEndpointRefs());
String modelUri = kModelEndpoint.getTargetUri();
String kModelUri = kModelEndpoint.getExtendedTargetUri();
String extendedMetamodelUri = MIDTypeRegistry.getExtendedMetamodelPath(kModelTypeEndpoint.getTarget());
if (extendedMetamodelUri != null) { // xmi model file
String kModelUriTemp = kModelUri + "temp";
String deleteText =
"xsi:schemaLocation=\"" +
kModelTypeEndpoint.getTargetUri() +
" file:" +
extendedMetamodelUri +
"\"";
FileUtils.copyTextFileAndReplaceText(
modelUri,
kModelUriTemp,
deleteText,
"",
true
);
modelUri = kModelUriTemp;
}
String newText =
kModelTypeEndpoint.getTargetUri() +
KleisliReasoningEngine.KLEISLI_MODELTYPE_URI_SUFFIX +
"\" xsi:schemaLocation=\"" +
kModelTypeEndpoint.getTargetUri() +
KleisliReasoningEngine.KLEISLI_MODELTYPE_URI_SUFFIX +
" file:" +
FileUtils.prependStatePathToUri(kModelTypeEndpoint.getExtendedTargetUri()) +
"\"";
FileUtils.copyTextFileAndReplaceText(
modelUri,
kModelUri,
kModelTypeEndpoint.getTargetUri() + "\"",
newText,
true
);
EObject kRootModelObj = kModelEndpoint.getExtendedTarget().getEMFInstanceRoot();
Map<String, Map<String, Map<EObject, EObject>>> queryMap = new HashMap<String, Map<String, Map<EObject, EObject>>>();
// first pass: EClasses
for (ModelElementReference kModelElemTypeRef : kModelTypeEndpointRef.getModelElemRefs()) {
EMFInfo kModelElemTypeEInfo = kModelElemTypeRef.getObject().getEInfo();
ExtendibleElementConstraint kConstraint = kModelElemTypeRef.getObject().getConstraint();
if (
kModelElemTypeEInfo.getFeatureName() != null ||
kConstraint == null ||
kConstraint.getImplementation().equals("")
) {
continue;
}
Map<String, Map<EObject, EObject>> queryUnion = new LinkedHashMap<String, Map<EObject, EObject>>();
queryMap.put(kModelElemTypeEInfo.getClassName(), queryUnion);
EClass kModelElemTypeClass = (EClass) kModelTypePackage.getEClassifier(kModelElemTypeEInfo.getClassName());
kReasoner.evaluateEClassQuery(kConstraint.getImplementation(), oclReasoner, kRootModelObj, kModelElemTypeClass, kModelTypeFactory, queryUnion);
}
// second pass: EReferences
for (ModelElementReference kModelElemTypeRef : kModelTypeEndpointRef.getModelElemRefs()) {
EMFInfo kModelElemTypeEInfo = kModelElemTypeRef.getObject().getEInfo();
ExtendibleElementConstraint kConstraint = kModelElemTypeRef.getObject().getConstraint();
if (
kModelElemTypeEInfo.getFeatureName() == null ||
kModelElemTypeEInfo.isAttribute() ||
kConstraint == null ||
kConstraint.getImplementation().equals("")
) {
continue;
}
Map<String, Map<EObject, EObject>> queryUnion = queryMap.get(kModelElemTypeEInfo.getRelatedClassName());
if (queryUnion == null) {
continue;
}
kReasoner.evaluateEReferenceQuery(kConstraint.getImplementation(), oclReasoner, kModelElemTypeEInfo, queryUnion, queryMap);
}
// third pass: EAttributes
for (ModelElementReference kModelElemTypeRef : kModelTypeEndpointRef.getModelElemRefs()) {
EMFInfo kModelElemTypeEInfo = kModelElemTypeRef.getObject().getEInfo();
ExtendibleElementConstraint kConstraint = kModelElemTypeRef.getObject().getConstraint();
if (
!kModelElemTypeEInfo.isAttribute() ||
kConstraint == null ||
kConstraint.getImplementation().equals("")
) {
continue;
}
kReasoner.evaluateEAttributeQuery(kConstraint.getImplementation(), oclReasoner, kRootModelObj, kModelElemTypeEInfo);
}
// save the derived model
FileUtils.writeModelFile(kRootModelObj, kModelUri, true);
}
catch (Exception e) {
MMINTException.print(IStatus.WARNING, "Error creating extended model file, fallback to no extension", e);
}
}
}
} //KleisliModelRelImpl