/** * 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.operator.diff; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.jdt.annotation.NonNull; 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.GenericElement; import edu.toronto.cs.se.mmint.mid.MID; import edu.toronto.cs.se.mmint.mid.MIDLevel; import edu.toronto.cs.se.mmint.mid.Model; import edu.toronto.cs.se.mmint.mid.ModelEndpoint; import edu.toronto.cs.se.mmint.mid.operator.impl.OperatorImpl; import edu.toronto.cs.se.mmint.mid.relationship.BinaryModelRel; 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.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.utils.MIDRegistry; public class ModelDifference extends OperatorImpl { // input-output private final static @NonNull String IN_MODELREL = "match"; private final static @NonNull String OUT_MODELREL = "diff"; // constants private final static String MODELREL_NAME = "diff"; private final static String DELETED_ELEMENT_LINK_NAME = "del"; private final static String ADDED_ELEMENT_LINK_NAME = "add"; private HashMap<String, ModelElementReference> createModelElementReferenceTable(ModelEndpointReference modelEndpointRef) { HashMap<String, ModelElementReference> modelElemRefTable = new HashMap<String, ModelElementReference>(); for (ModelElementReference modelElemRef : modelEndpointRef.getModelElemRefs()) { String modelElemUri = modelElemRef.getUri().substring(0, modelElemRef.getUri().indexOf(MMINT.ROLE_SEPARATOR)); modelElemRefTable.put(modelElemUri, modelElemRef); } return modelElemRefTable; } private List<EObject> getDiffModelObjects(Model model, HashMap<String, ModelElementReference> modelElemRefTable) throws MMINTException { List<EObject> diffModelEObjects = new ArrayList<EObject>(); TreeIterator<EObject> iterator = EcoreUtil.getAllContents(model.getEMFInstanceRoot(), true); while (iterator.hasNext()) { EObject modelObj = iterator.next(); String modelElemUri = MIDRegistry.getModelAndModelElementUris(modelObj, MIDLevel.INSTANCES)[1]; if (modelElemRefTable.get(modelElemUri) == null) { diffModelEObjects.add(modelObj); } } return diffModelEObjects; } private ModelEndpointReference createModelEndpointReference(ModelEndpoint rootModelTypeEndpoint, Mapping rootMappingType, ModelElementEndpoint rootModelElemTypeEndpoint, ModelRel diffModelRel, ModelEndpointReference modelEndpointRef, String linksName) throws MMINTException { Model model = modelEndpointRef.getObject().getTarget(); HashMap<String, ModelElementReference> modelElemRefTable = createModelElementReferenceTable(modelEndpointRef); List<EObject> diffModelObjs = getDiffModelObjects(model, modelElemRefTable); ModelEndpointReference newModelEndpointRef = rootModelTypeEndpoint.createInstance(model, diffModelRel); for (EObject modelObj : diffModelObjs) { // create unary link MappingReference diffMappingRef = rootMappingType.createInstanceAndReference(false, diffModelRel); diffMappingRef.getObject().setName(linksName); // create model element ModelElementReference diffModelElemRef = newModelEndpointRef.createModelElementInstanceAndReference(modelObj, null); // create model element endpoint rootModelElemTypeEndpoint.createInstanceAndReference(diffModelElemRef, diffMappingRef); } return newModelEndpointRef; } @Override public Map<String, Model> run( Map<String, Model> inputsByName, Map<String, GenericElement> genericsByName, Map<String, MID> outputMIDsByName) throws Exception { // input ModelRel matchRel = (ModelRel) inputsByName.get(IN_MODELREL); // create diff model relationship ModelRel rootModelRelType = MIDTypeHierarchy.getRootModelRelType(); BinaryModelRel diffModelRel = rootModelRelType.createBinaryInstance(null, outputMIDsByName.get(OUT_MODELREL)); diffModelRel.setName(MODELREL_NAME); ModelEndpoint rootModelTypeEndpoint = MIDTypeHierarchy.getRootModelTypeEndpoint(); Mapping rootMappingType = MIDTypeHierarchy.getRootMappingType(); ModelElementEndpoint rootModelElemTypeEndpoint = MIDTypeHierarchy.getRootModelElementTypeEndpoint(); // create src model endpoint with deleted elements createModelEndpointReference(rootModelTypeEndpoint, rootMappingType, rootModelElemTypeEndpoint, diffModelRel, matchRel.getModelEndpointRefs().get(0), DELETED_ELEMENT_LINK_NAME); // create tgt model endpoint with added elements createModelEndpointReference(rootModelTypeEndpoint, rootMappingType, rootModelElemTypeEndpoint, diffModelRel, matchRel.getModelEndpointRefs().get(1), ADDED_ELEMENT_LINK_NAME); // output Map<String, Model> outputs = new HashMap<>(); outputs.put(OUT_MODELREL, diffModelRel); return outputs; } }