/**
* 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.operator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jdt.annotation.NonNull;
import edu.toronto.cs.se.mmint.MMINTException;
import edu.toronto.cs.se.mmint.MIDTypeHierarchy;
import edu.toronto.cs.se.mmint.MIDTypeRegistry;
import edu.toronto.cs.se.mmint.mid.GenericElement;
import edu.toronto.cs.se.mmint.mid.MID;
import edu.toronto.cs.se.mmint.mid.Model;
import edu.toronto.cs.se.mmint.mid.operator.impl.OperatorImpl;
import edu.toronto.cs.se.mmint.mid.reasoning.MIDConstraintChecker;
import edu.toronto.cs.se.mmint.mid.relationship.ModelRel;
import edu.toronto.cs.se.mmint.mid.utils.FileUtils;
public class Filter extends OperatorImpl {
// input-output
private final static @NonNull String IN_MID = "mid";
private final static @NonNull String OUT_MID = "filteredMid";
private final static @NonNull String GENERIC_MODELTYPE = "TYPE";
// constants
private final static @NonNull String FILTERED_MID_SUFFIX = "_filter";
@Override
public boolean isAllowedGeneric(GenericEndpoint genericTypeEndpoint, GenericElement genericType, EList<OperatorInput> inputs) throws MMINTException {
boolean allowed = super.isAllowedGeneric(genericTypeEndpoint, genericType, inputs);
if (!allowed) {
return false;
}
if (genericType.getName().equals("Filter") || genericType.getName().equals("Map") || genericType.getName().equals("Reduce")) {
return false;
}
return true;
}
private @NonNull MID filter(@NonNull Model inputMIDModel, @NonNull Model filterModelType)
throws MMINTException {
MID filteredMID = (MID) inputMIDModel.getEMFInstanceRoot();
Set<Model> modelsToDelete = new HashSet<>();
for (Model model : filteredMID.getModels()) {
// check constraint only if types match (Model and Model, or ModelRel and ModelRel)
if ((model instanceof ModelRel) != (filterModelType instanceof ModelRel)) {
continue;
}
// check constraint
if (MIDTypeHierarchy.instanceOf(model, filterModelType.getUri(), false) && MIDConstraintChecker.checkModelConstraint(model, filterModelType.getConstraint())) {
continue;
}
modelsToDelete.add(model);
}
for (Model modelToDelete : modelsToDelete) {
if (modelToDelete.getMIDContainer() == null) {
// already deleted as side effect of another deletion e.g. model delete that triggers model rel delete
continue;
}
modelToDelete.deleteInstance();
}
return filteredMID;
}
@Override
public Map<String, Model> run(
Map<String, Model> inputsByName, Map<String, GenericElement> genericsByName,
Map<String, MID> outputMIDsByName) throws Exception {
// input
Model inputMIDModel = inputsByName.get(IN_MID);
Model filterModelType = (Model) genericsByName.get(GENERIC_MODELTYPE);
MID instanceMID = outputMIDsByName.get(OUT_MID);
// filter mid models based on property attached to type
MID filteredMID = filter(inputMIDModel, filterModelType);
// output
String filteredMIDModelUri = FileUtils.getUniqueUri(
FileUtils.addFileNameSuffixInUri(inputMIDModel.getUri(), FILTERED_MID_SUFFIX),
true,
false);
FileUtils.writeModelFile(filteredMID, filteredMIDModelUri, true);
Model midModelType = MIDTypeRegistry.getMIDModelType();
Model filteredMIDModel = midModelType.createInstanceAndEditor(filteredMIDModelUri, instanceMID);
Map<String, Model> outputsByName = new HashMap<>();
outputsByName.put(OUT_MID, filteredMIDModel);
return outputsByName;
}
}