### Eclipse Workspace Patch 1.0 #P imageio Index: src/main/java/javax/imageio/ImageIO.java =================================================================== --- src/main/java/javax/imageio/ImageIO.java (revision 941893) +++ src/main/java/javax/imageio/ImageIO.java (working copy) @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.Arrays; +import java.util.List; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.net.URL; @@ -104,7 +105,7 @@ } public static String[] getReaderFormatNames() { - ArrayList FormatNames = new ArrayList(); + List FormatNames = new ArrayList(); Iterator it = registry.getServiceProviders(ImageReaderSpi.class, true); while (it.hasNext()) { @@ -116,7 +117,7 @@ } public static String[] getReaderMIMETypes() { - ArrayList MIMETypes = new ArrayList(); + List MIMETypes = new ArrayList(); Iterator it = registry.getServiceProviders(ImageReaderSpi.class, true); while (it.hasNext()) { Index: src/test/java/javax/imageio/spi/ServiceRegistryTest.java =================================================================== --- src/test/java/javax/imageio/spi/ServiceRegistryTest.java (revision 0) +++ src/test/java/javax/imageio/spi/ServiceRegistryTest.java (revision 0) @@ -0,0 +1,82 @@ +package javax.imageio.spi; + +import java.util.Arrays; +import java.util.Iterator; + +import junit.framework.TestCase; + +import org.apache.harmony.x.imageio.plugins.gif.GIFImageReaderSpi; +import org.apache.harmony.x.imageio.plugins.jpeg.JPEGImageReaderSpi; +import org.apache.harmony.x.imageio.plugins.jpeg.JPEGImageWriterSpi; +import org.apache.harmony.x.imageio.plugins.png.PNGImageReaderSpi; + +public class ServiceRegistryTest extends TestCase { + + @SuppressWarnings({ "unchecked" }) + public void testGetServiceProviders() { + Class[] CATEGORIES = new Class[] { + javax.imageio.spi.ImageReaderSpi.class}; + + ServiceRegistry registry = new ServiceRegistry(Arrays.> asList(CATEGORIES).iterator()); + + JPEGImageReaderSpi jpegReader = new JPEGImageReaderSpi(); + PNGImageReaderSpi pngReader = new PNGImageReaderSpi(); + GIFImageReaderSpi gifReader = new GIFImageReaderSpi(); + + // Add 3 different providers to the registry + registry.registerServiceProvider(jpegReader, CATEGORIES[0]); + registry.registerServiceProvider(pngReader, CATEGORIES[0]); + registry.registerServiceProvider(gifReader, CATEGORIES[0]); + + // Add a different type of provider to the category + JPEGImageWriterSpi jpegWriter = new JPEGImageWriterSpi(); + try { + registry.registerServiceProvider(jpegWriter, CATEGORIES[0]); + fail("ClassCastException expected"); + } + catch (ClassCastException expected) { + //Ignored + } + + // Set ordering between these providers + // gifReader > pngReader > jpegReader + assertTrue("Failed to set ordering: gifReader > pngReader", registry.setOrdering(CATEGORIES[0], gifReader, pngReader)); + assertTrue("Failed to set ordering: pngReader > jpegReader", registry.setOrdering(CATEGORIES[0], pngReader, jpegReader)); + + // Return false if this ordering has already been set + assertFalse("Failed to check if the ordering has been set", registry.setOrdering(CATEGORIES[0], pngReader, jpegReader)); + + // If two providers are the same + try { + registry.setOrdering(CATEGORIES[0], gifReader, gifReader); + fail("IllegalArgumentException expected"); + } + catch (IllegalArgumentException expected) { + assertEquals("providers are the same!", expected.getMessage()); + } + + // If either provider is null + try { + registry.setOrdering(CATEGORIES[0], null, gifReader); + fail("IllegalArgumentException expected"); + } + catch (IllegalArgumentException expected) { + assertEquals("provider is null!", expected.getMessage()); + } + + // Get the iterator of sorted providers + Iterator it = registry.getServiceProviders(CATEGORIES[0], true); + + // Verify the order + assertEquals("Failed to return gifReader", it.next(), gifReader); + assertEquals("Failed to return pngReader", it.next(), pngReader); + assertEquals("Failed to return jpegReader", it.next(), jpegReader); + + // Unset orderings + assertTrue("Failed to unset ordering: gifReader > pngReader", registry.unsetOrdering(CATEGORIES[0], gifReader, pngReader)); + assertTrue("Failed to unset ordering: pngReader > jpegReader", registry.unsetOrdering(CATEGORIES[0], pngReader, jpegReader)); + + // Return false if this ordering is not set + assertFalse("Failed to check if the ordering is not set", registry.unsetOrdering(CATEGORIES[0], pngReader, jpegReader)); + } +} \ No newline at end of file Index: src/main/java/javax/imageio/spi/ServiceRegistry.java =================================================================== --- src/main/java/javax/imageio/spi/ServiceRegistry.java (revision 941893) +++ src/main/java/javax/imageio/spi/ServiceRegistry.java (working copy) @@ -90,14 +90,12 @@ throw new NotImplementedException(); } - public boolean setOrdering(Class category, T firstProvider, T secondProvider) throws NotImplementedException { - // TODO: implement - throw new NotImplementedException(); + public boolean setOrdering(Class category, T firstProvider, T secondProvider) { + return categories.setOrdering(category, firstProvider, secondProvider); } - public boolean unsetOrdering(Class category, T firstProvider, T secondProvider) throws NotImplementedException { - // TODO: implement - throw new NotImplementedException(); + public boolean unsetOrdering(Class category, T firstProvider, T secondProvider) { + return categories.unsetOrdering(category, firstProvider, secondProvider); } public void deregisterAll(Class category) throws NotImplementedException { @@ -138,6 +136,26 @@ this.registry = registry; } + boolean setOrdering(Class category, T firstProvider, T secondProvider) { + ProvidersMap providers = categories.get(category); + + if (providers == null) { + throw new IllegalArgumentException(Messages.getString("imageio.92", category)); + } + + return providers.setOrdering(firstProvider, secondProvider); + } + + boolean unsetOrdering(Class category, T firstProvider, T secondProvider) { + ProvidersMap providers = categories.get(category); + + if (providers == null) { + throw new IllegalArgumentException(Messages.getString("imageio.92", category)); + } + + return providers.unsetOrdering(firstProvider, secondProvider); + } + //-- TODO: useOrdering Iterator getProviders(Class category, boolean useOrdering) { ProvidersMap providers = categories.get(category); @@ -183,6 +201,9 @@ } private boolean addToNamed(Object provider, Class category) { + if (!category.isAssignableFrom(provider.getClass())) { + throw new ClassCastException(); + } Object obj = categories.get(category); if (null == obj) { @@ -204,22 +225,84 @@ } private static class ProvidersMap { - //-- TODO: providers ordering support Map, Object> providers = new HashMap, Object>(); + Map nodeMap = new HashMap(); boolean addProvider(Object provider) { - return providers.put(provider.getClass(), provider) != null; + ProviderNode node = new ProviderNode(provider); + nodeMap.put(provider, node); + Object obj = providers.put(provider.getClass(), provider); + + if (obj != null) { + nodeMap.remove(obj); + return false; + } + + return true; } - Iterator> getProviderClasses() { + Iterator getProviderClasses() { return providers.keySet().iterator(); } - //-- TODO ordering - Iterator getProviders(boolean userOrdering) { + Iterator getProviders(boolean useOrdering) { + if (useOrdering) { + return new OrderedProviderIterator(nodeMap.values().iterator()); + } + return providers.values().iterator(); } + + public boolean setOrdering(T firstProvider, T secondProvider) { + if (firstProvider == secondProvider) { + throw new IllegalArgumentException("providers are the same!"); + } + + if ((firstProvider == null) || (secondProvider == null)) { + throw new IllegalArgumentException("provider is null!"); + } + + ProviderNode firstNode = nodeMap.get(firstProvider); + ProviderNode secondNode = nodeMap.get(secondProvider); + + // if the ordering is already set, return false + if ((firstNode == null) || (firstNode.contains(secondNode))) { + return false; + } + + // put secondProvider into firstProvider's outgoing nodes list + firstNode.addOutEdge(secondNode); + // increase secondNode's incoming edge by 1 + secondNode.addInEdge(); + + return true; + } + + public boolean unsetOrdering(T firstProvider, T secondProvider) { + if (firstProvider == secondProvider) { + throw new IllegalArgumentException("providers are the same!"); + } + + if ((firstProvider == null) || (secondProvider == null)) { + throw new IllegalArgumentException("provider is null!"); + } + + ProviderNode firstNode = nodeMap.get(firstProvider); + ProviderNode secondNode = nodeMap.get(secondProvider); + + // if the ordering is not set, return false + if ((firstNode == null) || (!firstNode.contains(secondNode))) { + return false; + } + + // remove secondProvider from firstProvider's outgoing nodes list + firstNode.removeOutEdge(secondNode); + // decrease secondNode's incoming edge by 1 + secondNode.removeInEdge(); + + return true; + } } private static class FilteredIterator implements Iterator { @@ -265,4 +348,105 @@ } } } -} + + private static class ProviderNode { + // number of incoming edges + private int incomingEdges; + // all outgoing nodes + private Set outgoingNodes; + private Object provider; + + public ProviderNode(Object provider) { + incomingEdges = 0; + outgoingNodes = new HashSet(); + this.provider = provider; + } + + public Object getProvider() { + return provider; + } + + public Iterator getOutgoingNodes() { + return outgoingNodes.iterator(); + } + + public boolean addOutEdge(Object secondProvider) { + return outgoingNodes.add(secondProvider); + } + + public boolean removeOutEdge(Object provider) { + return outgoingNodes.remove(provider); + } + + public void addInEdge() { + incomingEdges++; + } + + public void removeInEdge() { + incomingEdges--; + } + + public int getIncomingEdges() { + return incomingEdges; + } + + public boolean contains(Object provider) { + return outgoingNodes.contains(provider); + } + } + + private static class OrderedProviderIterator implements Iterator { + + // store nodes which has 0 incoming edge + private Stack emptyList = new Stack(); + private Map incomingEdges = new HashMap(); + + public OrderedProviderIterator(Iterator it) { + // find all the nodes that with 0 incoming edge and add them to the emptyList + while (it.hasNext()) { + ProviderNode node = (ProviderNode)it.next(); + incomingEdges.put(node, new Integer(node.getIncomingEdges())); + if (node.getIncomingEdges()==0) { + emptyList.push(node); + } + } + } + + public boolean hasNext() { + return !emptyList.empty(); + } + + public Object next() { + if (emptyList.empty()) { + throw new NoSuchElementException(); + } + + // get a node from emptyList + ProviderNode node = emptyList.pop(); + + // find all the outgoing nodes + Iterator it = node.getOutgoingNodes(); + while (it.hasNext()) { + ProviderNode outNode = (ProviderNode) it.next(); + + // remove the incoming edge from the node. + int edges = incomingEdges.get(outNode); + edges--; + incomingEdges.put(outNode, new Integer(edges)); + + // add to the emptyList if this node's incoming edge is equal to 0 + if (edges == 0) { + emptyList.push(outNode); + } + } + + incomingEdges.remove(node); + + return node.getProvider(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } +} \ No newline at end of file