/** * */ package org.feature.multi.perspective.model.editor.editors.algorithms; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.feature.multi.perspective.model.viewmodel.AbstractGroup; import org.feature.multi.perspective.model.viewmodel.CoreGroup; import org.feature.multi.perspective.model.viewmodel.Group; import org.feature.multi.perspective.model.viewmodel.GroupModel; import org.feature.multi.perspective.model.viewmodel.ViewPoint; import org.feature.multi.perspective.model.editor.editors.View; import org.js.model.feature.Feature; import org.js.model.feature.FeatureModel; /** * This class represent the BruteForceAlgorithm which validates the {@link ViewPoint} * * @author Tim Winkelmann * */ public class BruteForceAlgorithm { private Logger log = Logger.getLogger(BruteForceAlgorithm.class); private Map<ViewPoint, View> viewPoints; private GroupModel groupModel; private List<View> views; private FeatureModel featureModel; public BruteForceAlgorithm(GroupModel groupModel, List<View> views, FeatureModel featureModel) { this.groupModel = groupModel; this.views = views; this.featureModel = featureModel; } /** * iterate over each view point and there groups. checks then the combined view consistency * * @param groupModel contains the view points * @param views2 contains all views */ public List<ViewPointWrapper> checkViewPoints() { List<ViewPointWrapper> vpWrapper = new ArrayList<ViewPointWrapper>(); EList<ViewPoint> viewPointsToCheck = groupModel.getViewPointContainer().getViewPoints(); HashMap<EObject, View> viewMemory = new HashMap<EObject, View>(); viewPoints = new HashMap<ViewPoint, View>(); for (ViewPoint viewPoint : viewPointsToCheck) { // log.debug("ViewPoint: " + viewPoint.getName()); View view = checkViewpoint(viewPoint, groupModel.getCoreGroup(), viewMemory); viewPoints.put(viewPoint, view); boolean isConsistent = view.isConsistent(); ViewPointWrapper wrapper = new ViewPointWrapper(viewPoint, isConsistent); vpWrapper.add(wrapper); } // log.debug("BF: " + (System.currentTimeMillis()-time)); return vpWrapper; } /** * determine if the given viewpoint is consistent. * @param viewpoint * @return */ public boolean isViewpointConsistent(ViewPoint viewpoint) { View view = checkViewpoint(viewpoint); return view.isConsistent(); } /** * check a viewpoint and return the according view. * @param viewpoint * @return */ public View checkViewpoint(ViewPoint viewpoint) { HashMap<EObject, View> viewMemory = new HashMap<EObject, View>(); CoreGroup coreGroup = groupModel.getCoreGroup(); View view = checkViewpoint(viewpoint, coreGroup, viewMemory); return view; } /** * check the viewpoint * * @param viewPoint the view point * @param views the views * @param coreGroup the coreGroup */ public View checkViewpoint(ViewPoint viewPoint, CoreGroup coreGroup, HashMap<EObject, View> viewMemory) { EList<AbstractGroup> containedInGroup = viewPoint.getContainedInGroup(); Set<Set<View>> setOfPaths = new HashSet<Set<View>>(); for (AbstractGroup group : containedInGroup) { List<EObject> groups = getGroupPath(group); // log.debug("check path for: " + group.getName()); viewMemory.clear(); // performance test without memory Set<View> path = new HashSet<View>(); if (!viewMemory.containsKey(group)) { path = checkPath(groups, views, viewMemory); } else { path = new HashSet<View>(); path.add(viewMemory.get(group)); } setOfPaths.add(path); } if (setOfPaths.isEmpty()) { // log.debug("check path for: coreGroup"); // log.debug(views.get(0).group); views.get(0).isConsistent(); // log.debug(views.get(0).isConsistent()); return views.get(0); } else { Set<Feature> features = new HashSet<Feature>(); for (Set<View> path : setOfPaths) { for (View view : path) { // log.debug(view.isConsistent()); features.addAll(view.getFeatures()); } } View view = new View(viewPoint, features, this.featureModel); String logMsg = "BruteForceAlg "; logMsg += viewPoint.getName(); logMsg += " contained in "; EList<AbstractGroup> conInGroup = viewPoint.getContainedInGroup(); for (AbstractGroup group : conInGroup) { logMsg += group.getName() + ", "; } log.debug(logMsg); return view; } } /** * create views for every group. the views extends the previous one. * * @param path has to be sorted from root to target! * @param views * @param viewMemory * @return */ private Set<View> checkPath(List<EObject> path, List<View> views, HashMap<EObject, View> viewMemory) { Set<View> pathViews = new HashSet<View>(); for (EObject group : path) { View view = viewMemory.get(group); if (view != null) {// check if view was already calculated pathViews.add(view); // log.debug("skipped: " + group); continue; } // find a view for (View v : views) { if (EcoreUtil.equals(v.getGroup(),group)) { view = v; break; } } if (view == null) { log.error("could not find a view"); return pathViews; } Set<Feature> features = new HashSet<Feature>();// combine view features.addAll(view.getFeatures()); for (View v : pathViews) { features.addAll(v.getFeatures()); } if (!features.isEmpty()) {// check if there is something to combine view = new View(group, features, this.featureModel); } // log.debug("add: " + group); pathViews.add(view); viewMemory.put(group, view); } return pathViews; } /** * get all ancestors from that group * * @param group a group from the tree * @param coreGroup the core group * @return the path from the coreGroup to the group */ private List<EObject> getGroupPath(AbstractGroup group) { List<EObject> groups = new LinkedList<EObject>(); groups.add(group); getParentRecursively(group, groups); Collections.reverse(groups); return groups; } private void getParentRecursively(AbstractGroup group, List<EObject> groups ){ EObject eContainer = group.eContainer(); if (eContainer instanceof AbstractGroup){ AbstractGroup parent = (AbstractGroup) eContainer; groups.add(parent); getParentRecursively(parent, groups); } } /** * @return the viewPoints */ public Collection<View> getViewPoints() { return viewPoints.values(); } }