/** * */ package org.feature.multi.perspective.model.editor.editors.algorithms; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; 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.mapping.viewmapping.MappingModel; import org.feature.multi.perspective.model.editor.editors.View; import org.feature.multi.perspective.model.editor.editors.ViewCreator; import org.feature.multi.perspective.model.editor.util.Flag; import org.feature.multi.perspective.model.editor.util.Util; import org.feature.multi.perspective.model.viewmodel.AbstractGroup; 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.viewmodel.ViewPointContainer; import org.js.model.feature.Feature; import org.js.model.feature.FeatureModel; /** * @author Tim Winkelmann * */ public class IncrementalAlgorithm { private static Logger log = Logger.getLogger(IncrementalAlgorithm.class); private HashMap<EObject, View> viewMap; private GroupModel groupModel; private UsedGroup usedGroupCoreGroup; private FeatureModel featureModel; private boolean checkRun = false; private List<ViewPoint> inConsistentViewpoints = new ArrayList<ViewPoint>(); // private int i = 0; //used for tests /** * Constructor that initializes views for the given featuremapping. * * @param mapping */ public IncrementalAlgorithm(MappingModel mapping) { this.featureModel = mapping.getFeatureModel(); this.groupModel = mapping.getViewModel(); ViewCreator viewCreater = new ViewCreator(mapping); List<View> views = viewCreater.getViews(); initViewMap(views); } public IncrementalAlgorithm(GroupModel groupModel, List<View> views, FeatureModel featureModel) { this.featureModel = featureModel; this.groupModel = groupModel; initViewMap(views); } /** * * @param views * @param groupModel */ public IncrementalAlgorithm(List<View> views, MappingModel mapping) { this.featureModel = mapping.getFeatureModel(); this.groupModel = mapping.getViewModel(); initViewMap(views); } private void initViewMap(List<View> views) { this.viewMap = new HashMap<EObject, View>(); for (View view : views) { viewMap.put(view.getGroup(), view); } } /** * Single check of a {@link ViewPoint}. * * @param viewPoint the {@link ViewPoint} for the check. * @return true if all direct connected groups are consistent. */ public boolean checkViewPoint(ViewPoint viewPoint) { List<ViewPoint> vps = new ArrayList<ViewPoint>(); vps.add(viewPoint); Map<AbstractGroup, UsedGroup> groupFeatureModel = buildGroupFeatureModel(vps); boolean isCon = true; for (AbstractGroup group : viewPoint.getContainedInGroup()) { UsedGroup usedGroup = groupFeatureModel.get(group); boolean consistent = usedGroup.isConsistent(); if (isCon && !consistent) { isCon = false; } } return isCon; } /** * collect for each group the features and checks if they are consistent. * * @return null if no viewpoints where found */ private Map<AbstractGroup, UsedGroup> buildGroupFeatureModel(List<ViewPoint> viewPoints) { // log.info("Number of ViewPoints: " + viewPoints.size()); Set<AbstractGroup> groups = new HashSet<AbstractGroup>(); // get groups from viewpoints for (ViewPoint viewPoint : viewPoints) { groups.addAll(viewPoint.getContainedInGroup()); } Map<AbstractGroup, UsedGroup> usedGroups = createMSGM(groups); for (Group g : usedGroupCoreGroup.getGroup().getGroups()) { if (usedGroups.containsKey(g)) { UsedGroup mostSpecificGroup = usedGroups.get(g); Flag f = new Flag(); // pre-consistency check FeatureModel view = Util.createFeatureModel(featureModel, mostSpecificGroup.getFeatures(), f); if (f.isChanged() && f.isFlagged()) { mostSpecificGroup.setConsistent(false); } else { mostSpecificGroup.setConsistent(Util.isConsistent(view)); } // msg.setConsistent(Util.isConsistent(msg.getFeatures())); mostSpecificGroup.setDone(); // i++;//used for tests checkGroupModel(g, usedGroups); } } return usedGroups; } /** * * @return */ public List<ViewPointWrapper> checkViewpoints() { List<ViewPointWrapper> viewPointConsistency = new ArrayList<ViewPointWrapper>(); ViewPointContainer container = groupModel.getViewPointContainer(); if (container != null) { EList<ViewPoint> viewPoints = container.getViewPoints(); Map<AbstractGroup, UsedGroup> groupFeatureModel = buildGroupFeatureModel(viewPoints); for (ViewPoint viewPoint : viewPoints) { String logMsg = "Heuristic "; logMsg += viewPoint.getName(); logMsg += " contained in "; EList<AbstractGroup> containedInGroup = viewPoint.getContainedInGroup(); for (AbstractGroup group : containedInGroup) { logMsg += group.getName() + ", "; } log.debug(logMsg); boolean isCon = true; Set<Feature> combinedFeaturesForViewPoint = new HashSet<Feature>(); for (AbstractGroup group : viewPoint.getContainedInGroup()) { UsedGroup usedGroup = groupFeatureModel.get(group); combinedFeaturesForViewPoint.addAll(usedGroup.getFeatures()); boolean consistent = usedGroup.isConsistent(); if (isCon && !consistent) { isCon = false; } } if (!isCon) { // log.debug("recheck"); Flag flag = new Flag(); FeatureModel view = Util.createFeatureModel(featureModel, combinedFeaturesForViewPoint, flag); if (!flag.isChanged() && !flag.isFlagged()) { isCon = Util.isConsistent(view); // log.debug(isCon); } } ViewPointWrapper wrapper = new ViewPointWrapper(viewPoint, isCon); viewPointConsistency.add(wrapper); if (!isCon) { inConsistentViewpoints.add(viewPoint); } } } else { log.info("There are no viewpoints defined yet."); } checkRun = true; return viewPointConsistency; } /** * return all inconsistent viewpoints. * * @return */ public List<ViewPoint> getInConsistentViewpoints() { if (!checkRun) { checkViewpoints(); } return inConsistentViewpoints; } /** * * @param group * @param usedGroups */ private void checkGroupModel(AbstractGroup group, Map<AbstractGroup, UsedGroup> usedGroups) { for (Group g : group.getGroups()) { if (usedGroups.containsKey(g)) { UsedGroup ug = usedGroups.get(g); Flag f = new Flag(); FeatureModel view = Util.createFeatureModel(featureModel, ug.getFeatures(), f); if (f.isChanged() && f.isFlagged()) { ug.setConsistent(false); } else { ug.setConsistent(Util.isConsistent(view)); } // ug.setConsistent(Util.isConsistent(ug.getFeatures())); ug.setDone(); // i++;//used for tests checkGroupModel(g, usedGroups); } } } /** * uses the most specific groups to create a new group model * * @param groups most specific groups * @return */ private Map<AbstractGroup, UsedGroup> createMSGM(Set<AbstractGroup> groups) { Map<AbstractGroup, UsedGroup> usedGroups = new HashMap<AbstractGroup, UsedGroup>(); usedGroupCoreGroup = new UsedGroup(null, groupModel.getCoreGroup(), viewMap.get(groupModel.getCoreGroup()).getFeatures()); usedGroupCoreGroup.setDone(); Flag f = new Flag(); FeatureModel view = Util.createFeatureModel(featureModel, usedGroupCoreGroup.getFeatures(), f); if (f.isChanged() && f.isFlagged()) { usedGroupCoreGroup.setConsistent(false); } else { usedGroupCoreGroup.setConsistent(Util.isConsistent(view)); } // ugCG.setConsistent(Util.isConsistent(ugCG.getFeatures())); usedGroups.put(groupModel.getCoreGroup(), usedGroupCoreGroup); for (AbstractGroup group : groups) { if (!usedGroups.containsKey(group)) { Set<Feature> features = new HashSet<Feature>(); features.addAll(viewMap.get(group).getFeatures()); UsedGroup ugParent = null; if (group instanceof Group) { Group g = (Group) group; if (g.getParentGroup() != null) { if (g.getParentGroup().equals(groupModel.getCoreGroup())) { ugParent = usedGroupCoreGroup; } else { ugParent = createMSG((AbstractGroup) g.getParentGroup(), usedGroups); } features.addAll(ugParent.getFeatures()); } UsedGroup ug = new UsedGroup(ugParent, group, features); usedGroups.put(group, ug); } } } return usedGroups; } /** * create a {@link UsedGroup} and his parents (except the ugCG) from the {@link Group} and adds it and his parents to * the list. * * @param group a most specific group. * @param ugs a list of most specific group. * @return the most specific group. */ private UsedGroup createMSG(AbstractGroup group, Map<AbstractGroup, UsedGroup> ugs) { if (ugs.containsKey(group)) { return ugs.get(group); } UsedGroup ugParent; if (group instanceof Group) { Group g = (Group) group; if (EcoreUtil.equals(g.getParentGroup(),groupModel.getCoreGroup())) { ugParent = usedGroupCoreGroup; } else { ugParent = createMSG((Group) g.getParentGroup(), ugs); } Set<Feature> features = new HashSet<Feature>(); features.addAll(ugParent.getFeatures()); features.addAll(viewMap.get(group).getFeatures()); UsedGroup ug = new UsedGroup(ugParent, group, features); ugs.put(group, ug); return ug; } return null; } }