/* * Copyright 2003-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.util.containers; import gnu.trove.THashMap; import gnu.trove.THashSet; import java.util.*; public class ManyToManyMap<F, S> { private Map<F, Set<S>> myFToS = new THashMap<F, Set<S>>(); private Map<S, Set<F>> mySToF = new THashMap<S, Set<F>>(); public void clearFirst(F f) { if (!myFToS.containsKey(f)) return; for (S s : new HashSet<S>(myFToS.get(f))) { removeLink(f, s); } } public void clearSecond(S s) { if (!mySToF.containsKey(s)) return; for (F f : new THashSet<F>(mySToF.get(s))) { removeLink(f, s); } } public void addLink(F f, S s) { if (!myFToS.containsKey(f)) { myFToS.put(f, new THashSet<S>(1)); } if (!mySToF.containsKey(s)) { mySToF.put(s, new THashSet<F>(1)); } myFToS.get(f).add(s); mySToF.get(s).add(f); } public void removeLink(F f, S s) { if (!myFToS.containsKey(f) || !mySToF.containsKey(s)) return; myFToS.get(f).remove(s); mySToF.get(s).remove(f); if (myFToS.get(f).isEmpty()) { myFToS.remove(f); } if (mySToF.get(s).isEmpty()) { mySToF.remove(s); } } public Set<F> getFirst() { return Collections.unmodifiableSet(myFToS.keySet()); } public Set<S> getSecond() { return Collections.unmodifiableSet(mySToF.keySet()); } public Set<S> getByFirst(F f) { if (myFToS.containsKey(f)) { return Collections.unmodifiableSet(myFToS.get(f)); } else { return Collections.emptySet(); } } public Set<F> getBySecond(S s) { if (mySToF.containsKey(s)) { return Collections.unmodifiableSet(mySToF.get(s)); } else { return Collections.emptySet(); } } public boolean contains(F f, S s) { return myFToS.containsKey(f) && myFToS.get(f).contains(s); } public boolean containsFirst(F f) { return myFToS.containsKey(f); } public boolean containsSecond(S s) { return mySToF.containsKey(s); } public void clear() { myFToS.clear(); mySToF.clear(); } }