You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wink.apache.org by el...@apache.org on 2009/07/14 09:29:58 UTC

svn commit: r793805 - in /incubator/wink/trunk/wink-common/src: main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java test/java/org/apache/wink/common/internal/providers/ProvidersContextResolverTest.java

Author: elman
Date: Tue Jul 14 07:29:58 2009
New Revision: 793805

URL: http://svn.apache.org/viewvc?rev=793805&view=rev
Log:
Fixing sort algorithm [WINK-82]

Modified:
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java
    incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/providers/ProvidersContextResolverTest.java

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java?rev=793805&r1=793804&r2=793805&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java Tue Jul 14 07:29:58 2009
@@ -32,7 +32,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeMap;
 import java.util.TreeSet;
 import java.util.Map.Entry;
 import java.util.concurrent.locks.Lock;
@@ -47,14 +46,14 @@
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.MessageBodyWriter;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.wink.common.WinkApplication;
 import org.apache.wink.common.internal.application.ApplicationValidator;
 import org.apache.wink.common.internal.lifecycle.LifecycleManagersRegistry;
 import org.apache.wink.common.internal.lifecycle.ObjectFactory;
 import org.apache.wink.common.internal.runtime.RuntimeContext;
 import org.apache.wink.common.internal.utils.GenericsUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Keeps the registry of providers.
@@ -394,7 +393,7 @@
         private final Map<MediaType, Set<ObjectFactory<T>>> data =
                                                                      new LinkedHashMap<MediaType, Set<ObjectFactory<T>>>();
         private final Class<?>                              rawType;
-
+        
         public MediaTypeMap(Class<?> rawType) {
             super();
             this.rawType = rawType;
@@ -439,6 +438,7 @@
             // from the Providers interface, therefore isCompatible method
             // should be used
             // the search here is less efficient that the regular search
+            // see https://issues.apache.org/jira/browse/WINK-47
 
             List<ObjectFactory<T>> list = new ArrayList<ObjectFactory<T>>();
 
@@ -449,29 +449,41 @@
                     compatibleList.add(entry);
                 }
             }
-            // sort list according to n / m > n / * > * / *
-            Collections.sort(compatibleList,
-                             new Comparator<Entry<MediaType, Set<ObjectFactory<T>>>>() {
-
-                                 public int compare(Entry<MediaType, Set<ObjectFactory<T>>> o1,
-                                                    Entry<MediaType, Set<ObjectFactory<T>>> o2) {
-                                     MediaType m1 = o1.getKey();
-                                     MediaType m2 = o2.getKey();
-                                     if (m1.getType().equals(MediaType.MEDIA_TYPE_WILDCARD)) {
-                                         if (m2.getType().equals(MediaType.MEDIA_TYPE_WILDCARD)) {
-                                             return 0;
-                                         }
-                                         // m2 > m1
-                                         return -1;
-                                     } else {
-                                         if (!m2.getType().equals(MediaType.MEDIA_TYPE_WILDCARD)) {
-                                             return 0;
-                                         }
-                                         // m1 > m2
-                                         return 1;
-                                     }
-                                 }
-                             });
+
+            // sorts according to the following algorithm: n / m  >  n / *  >  * / * in descending order 
+            // see https://issues.apache.org/jira/browse/WINK-82
+            Collections.sort(compatibleList, Collections.reverseOrder(new Comparator<Entry<MediaType, Set<ObjectFactory<T>>>>() {
+
+                public int compare(Entry<MediaType, Set<ObjectFactory<T>>> o1,
+                                   Entry<MediaType, Set<ObjectFactory<T>>> o2) {
+                    MediaType m1 = o1.getKey();
+                    MediaType m2 = o2.getKey();
+                    int compareTypes = compareTypes(m1.getType(), m2.getType());
+                    if (compareTypes == 0) {
+                        return compareTypes(m1.getSubtype(), m2.getSubtype());
+                    }
+                    return compareTypes;
+                }
+                
+                private int compareTypes(String type1, String type2) {
+                    if (type1.equals(MediaType.MEDIA_TYPE_WILDCARD)) {
+                        if (type2.equals(MediaType.MEDIA_TYPE_WILDCARD)) {
+                            // both types are wildcards
+                            return 0;
+                        }
+                        // only type2 is concrete
+                        // type2 > type1
+                        return -1;
+                    }
+                    if (type2.equals(MediaType.MEDIA_TYPE_WILDCARD)) {
+                        // only type1 is concrete
+                        return 1;
+                    }
+                    // both types are concrete
+                    return 0;
+                }
+            }));
+            
             for (Entry<MediaType, Set<ObjectFactory<T>>> entry : compatibleList) {
                 limitByType(list, entry.getValue(), cls);
             }

Modified: incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/providers/ProvidersContextResolverTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/providers/ProvidersContextResolverTest.java?rev=793805&r1=793804&r2=793805&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/providers/ProvidersContextResolverTest.java (original)
+++ incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/providers/ProvidersContextResolverTest.java Tue Jul 14 07:29:58 2009
@@ -40,6 +40,8 @@
 
     private static final String  STRING    = "String";
     private static final String  STRING2    = "String2";
+    private static final String  STRING3    = "String3";
+    private static final String  STRING4    = "String4";
     private static final String  ATOM      = "Atom";
     private static final byte[]  BYTE      = new byte[0];
     private static final Integer _12345    = new Integer(12345);
@@ -55,13 +57,31 @@
     }
     
     @Provider
-    @Produces( "text/*" )
+    @Produces( {MediaType.TEXT_PLAIN})
     public static class StringContextResolver2 implements ContextResolver<String> {
 
         public String getContext(Class<?> type) {
             return STRING2;
         }
     }
+    
+    @Provider
+    @Produces( "text/*" )
+    public static class StringContextResolver3 implements ContextResolver<String> {
+
+        public String getContext(Class<?> type) {
+            return STRING3;
+        }
+    }
+    
+    @Provider
+    @Produces( "*/*" )
+    public static class StringContextResolver4 implements ContextResolver<String> {
+        
+        public String getContext(Class<?> type) {
+            return STRING4;
+        }
+    }
 
     @Provider
     @Produces(MediaType.APPLICATION_FORM_URLENCODED)
@@ -118,6 +138,7 @@
     private ProvidersRegistry createProvidersRegistryImpl() {
         ProvidersRegistry providers =
             new ProvidersRegistry(new LifecycleManagersRegistry(), new ApplicationValidator());
+        ;
         return providers;
     }
 
@@ -155,12 +176,12 @@
          * AtomContextResolver comes before StringContextResolver, therefore it
          * should be invoked after
          */
-        assertEquals(STRING, providers.getContextResolver(String.class,
+        assertEquals(ATOM, providers.getContextResolver(String.class,
                                                           MediaType.WILDCARD_TYPE,
                                                           null).getContext(null));
 
         /*
-         * AtomContextResolver returnes null, if the parameter is not null,
+         * AtomContextResolver returns null, if the parameter is not null,
          * therefore StringContextResolver should be invoked
          */
         assertEquals(STRING, providers.getContextResolver(String.class,
@@ -178,7 +199,7 @@
     public void testContextResolverWildCards() {
         ProvidersRegistry providers = createProvidersRegistryImpl();
         assertTrue(providers.addProvider(new MyContextResolver()));
-        assertTrue(providers.addProvider(new StringContextResolver2()));
+        assertTrue(providers.addProvider(new StringContextResolver3()));
 
         /*
          * Check various wildcard permutations
@@ -199,12 +220,39 @@
         assertSame(MYCLASS, providers
             .getContextResolver(MyClass.class, new MediaType("*", "x-www-form-urlencoded"), null)
             .getContext(MyClass.class));
-
+        
         // should hit an exact match when search expands out to "text/*"
-        assertSame(STRING2, providers.getContextResolver(String.class,
+        assertSame(STRING3, providers.getContextResolver(String.class,
                 new MediaType("text",
                               "blarg"),
                 null).getContext(String.class));
     }
+    
+    public void testContextResolverSortingAlgorithm() {
+        ProvidersRegistry providers = createProvidersRegistryImpl();
+        // note: the order these are added is important to the test
+        assertTrue(providers.addProvider(new StringContextResolver4()));
+        assertTrue(providers.addProvider(new StringContextResolver3()));
+        assertTrue(providers.addProvider(new StringContextResolver2()));
+        
+        
+        // StringContextResolver2 takes priority over the others due to the media type in @Produces
+        assertSame(STRING2, providers.getContextResolver(String.class,
+                new MediaType("text",
+                              "*"),
+                null).getContext(String.class));
+        
+        // StringContextResolver2 takes priority over the others due to the media type in @Produces
+        assertSame(STRING2, providers.getContextResolver(String.class,
+                new MediaType("*",
+                              "*"),
+                null).getContext(String.class));
+        
+        // StringContextResolver2 takes priority over the others due to the media type in @Produces
+        assertSame(STRING2, providers.getContextResolver(String.class,
+                new MediaType("text",
+                              "plain"),
+                null).getContext(String.class));
+    }
 
 }