package jetbrains.mps.vcs.changesmanager.tree; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import org.jetbrains.mps.openapi.module.SRepository; import java.util.Map; import jetbrains.mps.vcs.changesmanager.tree.features.Feature; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.HashMap; import jetbrains.mps.util.CounterMap; import java.util.List; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import org.jetbrains.annotations.NotNull; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import jetbrains.mps.internal.collections.runtime.IVisitor; import org.jetbrains.annotations.Nullable; import org.apache.log4j.Level; /** * This is a map from 'Feature' to arbitrary value. Also it stores which features are ancestors of * features which are added in this map. * * @param <V> map value */ public class FeatureForestMap<V> { private static final Logger LOG = LogManager.getLogger(FeatureForestMap.class); private static boolean ourLoggingEnabled = "true".equals(System.getProperty("changesmanager.debug")); private final SRepository myRepo; private final Map<Feature, V> myFeatureToValue = MapSequence.fromMap(new HashMap<Feature, V>()); private final Map<Feature, Feature[]> myFeatureToAncestors = MapSequence.fromMap(new HashMap<Feature, Feature[]>()); private final CounterMap<Feature> myFeaturesIsAncestorCounterMap = new CounterMap<Feature>(new FeatureForestMap.MyCounterMapHandler()); private final List<FeatureForestMapListener> myListeners = ListSequence.fromList(new ArrayList<FeatureForestMapListener>()); public FeatureForestMap(SRepository repository) { myRepo = repository; } public void put(@NotNull Feature feature, @NotNull V value) { if (MapSequence.fromMap(myFeatureToValue).containsKey(feature)) { log("Trying to put already present feature " + feature); } Feature[] ancestors = feature.getAncestors(myRepo); Feature ancestor = Sequence.fromIterable(Sequence.fromArray(ancestors)).findFirst(new IWhereFilter<Feature>() { public boolean accept(Feature a) { return MapSequence.fromMap(myFeatureToValue).containsKey(a); } }); if (ancestor != null) { log(String.format("Trying to put feature (%s) which is ancestor of already added (%s)", feature, ancestor)); } MapSequence.fromMap(myFeatureToValue).put(feature, value); MapSequence.fromMap(myFeatureToAncestors).put(feature, ancestors); Sequence.fromIterable(Sequence.fromArray(ancestors)).visitAll(new IVisitor<Feature>() { public void visit(Feature a) { myFeaturesIsAncestorCounterMap.increment(a); } }); fireFeatureStateChanged(feature); } public void removeKey(@NotNull Feature feature) { if (!(MapSequence.fromMap(myFeatureToValue).containsKey(feature))) { log("Trying to remove feature which is not added: " + feature); } Feature[] ancestors = MapSequence.fromMap(myFeatureToAncestors).get(feature); MapSequence.fromMap(myFeatureToValue).removeKey(feature); MapSequence.fromMap(myFeatureToAncestors).removeKey(feature); Sequence.fromIterable(Sequence.fromArray(ancestors)).visitAll(new IVisitor<Feature>() { public void visit(Feature a) { myFeaturesIsAncestorCounterMap.decrement(a); } }); fireFeatureStateChanged(feature); } @Nullable public V get(@NotNull Feature feature) { return MapSequence.fromMap(myFeatureToValue).get(feature); } public boolean isAncestorOfAddedFeature(@NotNull Feature feature) { return !(myFeaturesIsAncestorCounterMap.isZero(feature)); } @Nullable public Feature getAddedAncestor(@NotNull Feature feature) { return Sequence.fromIterable(Sequence.fromArray(feature.getAncestors(myRepo))).findFirst(new IWhereFilter<Feature>() { public boolean accept(Feature a) { return MapSequence.fromMap(myFeatureToValue).containsKey(a); } }); } @Nullable public V getAddedAncestorValue(@NotNull Feature feature) { return MapSequence.fromMap(myFeatureToValue).get(getAddedAncestor(feature)); } public void addListener(@NotNull FeatureForestMapListener listener) { synchronized (myListeners) { ListSequence.fromList(myListeners).addElement(listener); } } public void removeListener(@NotNull FeatureForestMapListener listener) { synchronized (myListeners) { ListSequence.fromList(myListeners).removeElement(listener); } } @NotNull private List<FeatureForestMapListener> copyListeners() { synchronized (myListeners) { return ListSequence.fromListWithValues(new ArrayList<FeatureForestMapListener>(), myListeners); } } private void fireFeatureStateChanged(@NotNull Feature feature) { for (FeatureForestMapListener listener : ListSequence.fromList(copyListeners())) { try { listener.featureStateChanged(feature); } catch (Throwable t) { if (t instanceof InterruptedException || check_tcy57o_a0a0a0a0a0ab(t) instanceof InterruptedException) { // ignore } else { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error("Exception on firing featureStateChanged event", t); } } } } } public static void setLoggingEnabled(boolean loggingEnabled) { ourLoggingEnabled = loggingEnabled; } private static void log(String msg) { if (ourLoggingEnabled) { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error(msg); } } } private class MyCounterMapHandler implements CounterMap.CounterMapHandler<Feature> { public MyCounterMapHandler() { } @Override public void counterZero(@NotNull Feature feature) { fireFeatureStateChanged(feature); } @Override public void counterNonZero(@NotNull Feature feature) { fireFeatureStateChanged(feature); } } private static Throwable check_tcy57o_a0a0a0a0a0ab(Throwable checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getCause(); } return null; } }