package de.ovgu.cide.features.source; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import de.ovgu.cide.af.Alternative; import de.ovgu.cide.features.IFeature; import de.ovgu.cide.features.IFeatureModel; import de.ovgu.cide.features.IFeatureModelWithID; abstract class AbstractColorManager { private final IStorageProvider storageProvider; private Map<String, Set<IFeature>> id2colors = null; private final IProject project; private final Object resource; protected final IFeatureModel featureModel; public AbstractColorManager(IStorageProvider storageProvider, IProject project, Object annotatedResource, IFeatureModel featureModel) { this.storageProvider = storageProvider; this.project = project; this.resource = annotatedResource; this.featureModel = featureModel; updateColors(); } private void save() { if (tempMode) return; if (!changed) return; if (batch != 0) return; try { if (storageProvider.storeAnnotations(project, resource, id2colors, getID2isOptional(), getID2parentIDs(), null)) changed = false; } catch (CoreException e) { e.printStackTrace(); } } protected Map<String, List<String>> getID2parentIDs() { return null; } protected Map<String, Boolean> getID2isOptional() { return null; } protected Set<IFeature> getOwnColors(String id) { Set<IFeature> colors = id2colors.get(id); HashSet<IFeature> result = new HashSet<IFeature>(); if (colors != null) { result.addAll(colors); for (IFeature f : colors) { addRequiredFeatures(result, f); } } return Collections.unmodifiableSet(result); } private void addRequiredFeatures(Set<IFeature> featureList, IFeature f) { Set<IFeature> requiredFeatures = f.getRequiredFeatures(); for (IFeature requiredFeature : requiredFeatures) { if (!featureList.contains(requiredFeature)) { featureList.add(requiredFeature); addRequiredFeatures(featureList, requiredFeature); } } } protected boolean addColor(String id, IFeature color) { Set<IFeature> colors = id2colors.get(id); if (colors == null) { colors = new HashSet<IFeature>(); id2colors.put(id, colors); } boolean success = colors.add(color); changed |= success; save(); return success; } protected boolean removeColor(String id, IFeature color) { Set<IFeature> colors = id2colors.get(id); boolean success = false; if (colors != null) { success |= colors.remove(color); // Achtung: Auch wenn colors hier leer ist, darf der Eintrag nicht aus id2colors geloescht werden, // weil beim Abspeichern der Annotationen sonst vergessen werden kann, dass die Faerbung // aufgehoben wurde. } changed |= success; save(); return success; } /** * Liefert alle Alternativen zu allen AST-Knoten. * @param featureModel * @return */ public Map<String, List<Alternative>> getAllAlternatives(IFeatureModelWithID featureModel) { return storageProvider.getAllAlternatives(project, resource, featureModel); } protected boolean activateAlternative(Alternative alternative, Map<String, String> id2oldText) { boolean success = storageProvider.activateAlternative(project, resource, alternative, id2oldText); // TODO MRO: Graumsam uneffizient! Wir muessen nicht alle Annotationen neu von der Platte lesen, // sondern nur die der neuen Alternative (davon aber alle Kinder!). updateColors(); return success; } protected boolean createAlternative(Alternative alternative, Map<String, String> id2oldText) { if (alternative == null) return false; boolean success = storageProvider.storeNewAlternative(project, resource, alternative, id2oldText); // TODO MRO: Graumsam uneffizient! Wir muessen nicht alle Annotationen neu von der Platte lesen, // sondern nur die der neuen Alternative (davon aber alle Kinder!). updateColors(); return success; } private void updateColors() { id2colors = storageProvider.readAnnotations(project, resource, featureModel); } protected boolean hasColor(String id, IFeature color) { return getOwnColors(id).contains(color); } private int batch = 0; private boolean changed = false; private Stack<Boolean> changeStack = null; private boolean tempMode; private boolean lastTempMode; public void beginBatch() { if (batch > 0) { if (changeStack == null) changeStack = new Stack<Boolean>(); changeStack.push(new Boolean(changed)); } batch++; changed = false; } public void endBatch() { batch--; if (batch > 0) { changed = changeStack.pop().booleanValue() | changed; } else { save(); } } protected boolean clearColor(String id) { Set<IFeature> colors = id2colors.get(id); boolean success = colors != null && colors.size() > 0; if (colors != null) id2colors.put(id, new HashSet<IFeature>()); // Achtung: Der Eintrag darf nicht aus id2colors geloescht werden, weil beim Abspeichern der Annotationen // sonst vergessen werden kann, dass die Faerbung aufgehoben wurde. changed |= success; save(); return success; } public boolean hasColors() { for (String id : id2colors.keySet()) { Set<IFeature> colors = id2colors.get(id); if (colors != null && !colors.isEmpty()) return true; } return false; } /** * in temporary mode changes will not be saved and as soon as temporary mode * is disabled all changes will be discarded * * @param enable */ public void setTemporaryMode(boolean enable) { if (tempMode == true && enable == false) id2colors = storageProvider.readAnnotations(project, resource, featureModel); this.lastTempMode = this.tempMode; this.tempMode = enable; } public void resetTemporaryMode() { setTemporaryMode(lastTempMode); } protected void setColors(String id, Set<IFeature> newColors) { if (newColors == null) newColors = new HashSet<IFeature>(); Set<IFeature> previousColors = id2colors.get(id); id2colors.put(id, new HashSet<IFeature>(newColors)); boolean success = previousColors == null || !previousColors.equals(newColors); changed |= success; save(); } /** * returns all features that are ever used in any entry of this * color-manager (file or directory). * * this function is only added temporary for experimental purposes. note * that features might be stored for elements that have been deleted. do not * rely on this function. * * * @return */ public Set<IFeature> getAllUsedColors() { Set<IFeature> result = new HashSet<IFeature>(); for (Set<IFeature> v : id2colors.values()) { result.addAll(v); } return result; } /** * to be used only for special access. usually use the higher level access * functions in concrete instances of the color manager. */ public Set<IFeature> getOwnColorsS(String id) { return getOwnColors(id); } }