/*
* 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();
}
}