/* * 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.typesystem.inference.util; import jetbrains.mps.lang.pattern.util.IMatchModifier; import jetbrains.mps.lang.pattern.util.MatchingUtil; import org.jetbrains.mps.openapi.model.SNode; import java.util.*; public class StructuralNodeSet<T> implements Set<SNode> { private Set<SNodeWrapper> myWrappers = new LinkedHashSet<SNodeWrapper>(); public StructuralNodeSet() { } public StructuralNodeSet(StructuralNodeSet<T> set) { myWrappers.addAll(set.myWrappers); } public StructuralNodeSet(Collection<? extends SNode> collection) { addAll(collection); } public boolean containsStructurally(SNode ourNode) { return myWrappers.contains(new SNodeWrapper(ourNode)); } public boolean removeStructurally(SNode ourNode) { return myWrappers.remove(new SNodeWrapper(ourNode)); } public boolean addStructurally(SNode ourNode) { return myWrappers.add(new SNodeWrapper(ourNode)); } public boolean addCollectionStructurally(Collection<? extends SNode> ourNodes) { boolean result = false; if (ourNodes == null) return false; for (SNode ourNode : ourNodes) { boolean someResult = addStructurally(ourNode); result = result || someResult; } return result; } public boolean addAllStructurally(StructuralNodeSet ourNodes) { return myWrappers.addAll(ourNodes.myWrappers); } public void putAllStructurally(StructuralNodeSet<T> ourNodes) { for (SNodeWrapper w : ourNodes.myWrappers) { if (!myWrappers.contains(w)) { myWrappers.add(w); } } } @Override public int size() { return myWrappers.size(); } @Override public boolean isEmpty() { return myWrappers.isEmpty(); } @Override public void clear() { myWrappers.clear(); } @Override public boolean contains(Object o) { if (!(o instanceof SNode)) return false; return containsStructurally((SNode) o); } @Override public Iterator<SNode> iterator() { return getNodes().iterator(); } private List<SNode> getNodes() { List<SNode> nodes = new ArrayList<SNode>(); for (SNodeWrapper w : myWrappers) { nodes.add(w.myNode); } return nodes; } @Override public boolean add(SNode o) { return addStructurally(o); } @Override public boolean addAll(Collection<? extends SNode> c) { return addCollectionStructurally(c); } @Override public boolean remove(Object o) { if (!(o instanceof SNode)) return false; return removeStructurally((SNode) o); } @Override public Object[] toArray() { return getNodes().toArray(); } @Override public <T> T[] toArray(T[] a) { return getNodes().toArray(a); } @Override public boolean containsAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } public void addAndRewrite(SNode node) { if (!containsStructurally(node)) { myWrappers.add(new SNodeWrapper(node)); } else { SNodeWrapper wrapper = new SNodeWrapper(node); myWrappers.remove(wrapper); myWrappers.add(wrapper); } } private static class SNodeWrapper { private SNode myNode; private int myHashCode; private SNodeWrapper(SNode node) { myNode = node; myHashCode = MatchingUtil.hash(myNode); } @Override public int hashCode() { return myHashCode; } @Override public boolean equals(Object obj) { if (!(obj instanceof SNodeWrapper)) return false; SNodeWrapper wrapper = (SNodeWrapper) obj; return MatchingUtil.matchNodes(wrapper.myNode, myNode, IMatchModifier.DEFAULT, false); } } }