Path: blob/master/src/java.desktop/share/classes/javax/imageio/spi/PartiallyOrderedSet.java
41155 views
/*1* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.imageio.spi;2627import java.util.AbstractSet;28import java.util.HashMap;29import java.util.Iterator;30import java.util.LinkedList;31import java.util.Map;32import java.util.Set;3334/**35* A set of {@code Object}s with pairwise orderings between them.36* The {@code iterator} method provides the elements in37* topologically sorted order. Elements participating in a cycle38* are not returned.39*40* Unlike the {@code SortedSet} and {@code SortedMap}41* interfaces, which require their elements to implement the42* {@code Comparable} interface, this class receives ordering43* information via its {@code setOrdering} and44* {@code unsetPreference} methods. This difference is due to45* the fact that the relevant ordering between elements is unlikely to46* be inherent in the elements themselves; rather, it is set47* dynamically accoring to application policy. For example, in a48* service provider registry situation, an application might allow the49* user to set a preference order for service provider objects50* supplied by a trusted vendor over those supplied by another.51*52*/53class PartiallyOrderedSet<E> extends AbstractSet<E> {5455// The topological sort (roughly) follows the algorithm described in56// Horowitz and Sahni, _Fundamentals of Data Structures_ (1976),57// p. 315.5859// Maps Objects to DigraphNodes that contain them60private Map<E, DigraphNode<E>> poNodes = new HashMap<>();6162// The set of Objects63private Set<E> nodes = poNodes.keySet();6465/**66* Constructs a {@code PartiallyOrderedSet}.67*/68public PartiallyOrderedSet() {}6970public int size() {71return nodes.size();72}7374public boolean contains(Object o) {75return nodes.contains(o);76}7778/**79* Returns an iterator over the elements contained in this80* collection, with an ordering that respects the orderings set81* by the {@code setOrdering} method.82*/83public Iterator<E> iterator() {84return new PartialOrderIterator<>(poNodes.values().iterator());85}8687/**88* Adds an {@code Object} to this89* {@code PartiallyOrderedSet}.90*/91public boolean add(E o) {92if (nodes.contains(o)) {93return false;94}9596DigraphNode<E> node = new DigraphNode<>(o);97poNodes.put(o, node);98return true;99}100101/**102* Removes an {@code Object} from this103* {@code PartiallyOrderedSet}.104*/105public boolean remove(Object o) {106DigraphNode<E> node = poNodes.get(o);107if (node == null) {108return false;109}110111poNodes.remove(o);112node.dispose();113return true;114}115116public void clear() {117poNodes.clear();118}119120/**121* Sets an ordering between two nodes. When an iterator is122* requested, the first node will appear earlier in the123* sequence than the second node. If a prior ordering existed124* between the nodes in the opposite order, it is removed.125*126* @return {@code true} if no prior ordering existed127* between the nodes, {@code false} otherwise.128*/129public boolean setOrdering(E first, E second) {130DigraphNode<E> firstPONode = poNodes.get(first);131DigraphNode<E> secondPONode = poNodes.get(second);132133secondPONode.removeEdge(firstPONode);134return firstPONode.addEdge(secondPONode);135}136137/**138* Removes any ordering between two nodes.139*140* @return true if a prior prefence existed between the nodes.141*/142public boolean unsetOrdering(E first, E second) {143DigraphNode<E> firstPONode = poNodes.get(first);144DigraphNode<E> secondPONode = poNodes.get(second);145146return firstPONode.removeEdge(secondPONode) ||147secondPONode.removeEdge(firstPONode);148}149150/**151* Returns {@code true} if an ordering exists between two152* nodes.153*/154public boolean hasOrdering(E preferred, E other) {155DigraphNode<E> preferredPONode = poNodes.get(preferred);156DigraphNode<E> otherPONode = poNodes.get(other);157158return preferredPONode.hasEdge(otherPONode);159}160}161162class PartialOrderIterator<E> implements Iterator<E> {163164LinkedList<DigraphNode<E>> zeroList = new LinkedList<>();165Map<DigraphNode<E>, Integer> inDegrees = new HashMap<>();166167public PartialOrderIterator(Iterator<DigraphNode<E>> iter) {168// Initialize scratch in-degree values, zero list169while (iter.hasNext()) {170DigraphNode<E> node = iter.next();171int inDegree = node.getInDegree();172inDegrees.put(node, inDegree);173174// Add nodes with zero in-degree to the zero list175if (inDegree == 0) {176zeroList.add(node);177}178}179}180181public boolean hasNext() {182return !zeroList.isEmpty();183}184185public E next() {186DigraphNode<E> first = zeroList.removeFirst();187188// For each out node of the output node, decrement its in-degree189Iterator<DigraphNode<E>> outNodes = first.getOutNodes();190while (outNodes.hasNext()) {191DigraphNode<E> node = outNodes.next();192int inDegree = inDegrees.get(node).intValue() - 1;193inDegrees.put(node, inDegree);194195// If the in-degree has fallen to 0, place the node on the list196if (inDegree == 0) {197zeroList.add(node);198}199}200201return first.getData();202}203204public void remove() {205throw new UnsupportedOperationException();206}207}208209210