Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/imageio/spi/PartiallyOrderedSet.java
38830 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</code>s with pairwise orderings between them.36* The <code>iterator</code> method provides the elements in37* topologically sorted order. Elements participating in a cycle38* are not returned.39*40* Unlike the <code>SortedSet</code> and <code>SortedMap</code>41* interfaces, which require their elements to implement the42* <code>Comparable</code> interface, this class receives ordering43* information via its <code>setOrdering</code> and44* <code>unsetPreference</code> 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 extends AbstractSet {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 poNodes = new HashMap();6162// The set of Objects63private Set nodes = poNodes.keySet();6465/**66* Constructs a <code>PartiallyOrderedSet</code>.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</code> method.82*/83public Iterator iterator() {84return new PartialOrderIterator(poNodes.values().iterator());85}8687/**88* Adds an <code>Object</code> to this89* <code>PartiallyOrderedSet</code>.90*/91public boolean add(Object o) {92if (nodes.contains(o)) {93return false;94}9596DigraphNode node = new DigraphNode(o);97poNodes.put(o, node);98return true;99}100101/**102* Removes an <code>Object</code> from this103* <code>PartiallyOrderedSet</code>.104*/105public boolean remove(Object o) {106DigraphNode node = (DigraphNode)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</code> if no prior ordering existed127* between the nodes, <code>false</code>otherwise.128*/129public boolean setOrdering(Object first, Object second) {130DigraphNode firstPONode =131(DigraphNode)poNodes.get(first);132DigraphNode secondPONode =133(DigraphNode)poNodes.get(second);134135secondPONode.removeEdge(firstPONode);136return firstPONode.addEdge(secondPONode);137}138139/**140* Removes any ordering between two nodes.141*142* @return true if a prior prefence existed between the nodes.143*/144public boolean unsetOrdering(Object first, Object second) {145DigraphNode firstPONode =146(DigraphNode)poNodes.get(first);147DigraphNode secondPONode =148(DigraphNode)poNodes.get(second);149150return firstPONode.removeEdge(secondPONode) ||151secondPONode.removeEdge(firstPONode);152}153154/**155* Returns <code>true</code> if an ordering exists between two156* nodes.157*/158public boolean hasOrdering(Object preferred, Object other) {159DigraphNode preferredPONode =160(DigraphNode)poNodes.get(preferred);161DigraphNode otherPONode =162(DigraphNode)poNodes.get(other);163164return preferredPONode.hasEdge(otherPONode);165}166}167168class PartialOrderIterator implements Iterator {169170LinkedList zeroList = new LinkedList();171Map inDegrees = new HashMap(); // DigraphNode -> Integer172173public PartialOrderIterator(Iterator iter) {174// Initialize scratch in-degree values, zero list175while (iter.hasNext()) {176DigraphNode node = (DigraphNode)iter.next();177int inDegree = node.getInDegree();178inDegrees.put(node, new Integer(inDegree));179180// Add nodes with zero in-degree to the zero list181if (inDegree == 0) {182zeroList.add(node);183}184}185}186187public boolean hasNext() {188return !zeroList.isEmpty();189}190191public Object next() {192DigraphNode first = (DigraphNode)zeroList.removeFirst();193194// For each out node of the output node, decrement its in-degree195Iterator outNodes = first.getOutNodes();196while (outNodes.hasNext()) {197DigraphNode node = (DigraphNode)outNodes.next();198int inDegree = ((Integer)inDegrees.get(node)).intValue() - 1;199inDegrees.put(node, new Integer(inDegree));200201// If the in-degree has fallen to 0, place the node on the list202if (inDegree == 0) {203zeroList.add(node);204}205}206207return first.getData();208}209210public void remove() {211throw new UnsupportedOperationException();212}213}214215216