Author: reto
Date: Sun Aug  1 22:39:52 2010
New Revision: 981338

URL: http://svn.apache.org/viewvc?rev=981338&view=rev
Log:
CLEREZZA-266: comnparing concreteness of matching writer annotation selecting 
between of accept-headers of same relative preference

Added:
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/InconsistentMediaTypeComparator.java
Modified:
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/ResponseProcessor.java
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/AcceptHeader.java
    
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/MediaTypeComparator.java

Modified: 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/ResponseProcessor.java
URL: 
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/ResponseProcessor.java?rev=981338&r1=981337&r2=981338&view=diff
==============================================================================
--- 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/ResponseProcessor.java
 (original)
+++ 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/ResponseProcessor.java
 Sun Aug  1 22:39:52 2010
@@ -34,6 +34,7 @@ import java.security.PrivilegedException
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -61,6 +62,7 @@ import org.apache.clerezza.triaxrs.util.
 import org.apache.clerezza.triaxrs.util.FirstByteActionOutputStream;
 import org.apache.clerezza.triaxrs.util.MediaTypeComparator;
 import org.apache.clerezza.triaxrs.util.BodyStoringResponse;
+import org.apache.clerezza.triaxrs.util.InconsistentMediaTypeComparator;
 import org.wymiwyg.wrhapi.HandlerException;
 import org.wymiwyg.wrhapi.HeaderName;
 import org.wymiwyg.wrhapi.MessageBody;
@@ -139,26 +141,37 @@ class ResponseProcessor {
                }
                final List<MediaType> expandedMethodProducibleMediaTypesList = 
expandListWithConcreterTypesFromAccept(methodProducibleMediaTypesList, 
acceptHeader);
                MessageBodyWriter<Object> writer = null;
-               Collections.sort(expandedMethodProducibleMediaTypesList,
-                               new MediaTypeComparator(acceptHeader));
+               List<Set<MediaType>> expandedMethodProducibleMediaTypeClasses
+                               = 
getSortedClasses(expandedMethodProducibleMediaTypesList,
+                               new 
InconsistentMediaTypeComparator(acceptHeader));
                Collections.sort(methodProducibleMediaTypesList,
                                new MediaTypeComparator(acceptHeader));
                MediaType relevantMethodProducibleType = null;
 
-               for (MediaType mediaType : 
expandedMethodProducibleMediaTypesList) {
-                       writer = (MessageBodyWriter<Object>) 
JaxRsHandler.providers.getMessageBodyWriter(entity.getClass(), entityType,
-                                       annotations, mediaType);
-                       if (writer != null) {
-                               for (MediaType methodMediaType : 
methodProducibleMediaTypesList) {
-                                       if 
(methodMediaType.isCompatible(mediaType)) {
-                                               relevantMethodProducibleType = 
methodMediaType;
-                                               break;
+               for (Set<MediaType> preferenceClass : 
expandedMethodProducibleMediaTypeClasses) {
+                       int lastWriterConcreteness = -1;
+                       for (MediaType mediaType : preferenceClass) {
+                               MessageBodyWriter<Object> currentWriter = 
(MessageBodyWriter<Object>) 
JaxRsHandler.providers.getMessageBodyWriter(entity.getClass(), entityType,
+                                               annotations, mediaType);
+                               if (currentWriter != null) {
+                                       int writerConcreteness = 
getWriterConcreteness(currentWriter, mediaType);
+                                       if (writerConcreteness > 
lastWriterConcreteness) {
+                                               for (MediaType methodMediaType 
: methodProducibleMediaTypesList) {
+                                                       if 
(methodMediaType.isCompatible(mediaType)) {
+                                                               
relevantMethodProducibleType = methodMediaType;
+                                                               break;
+                                                       }
+                                               }
+                                               writer = currentWriter;
                                        }
                                }
+                       }
+                       if (writer != null) {
                                break;
                        }
                }
 
+
                if (writer == null) {
                        for (MediaType mediaType : 
expandedMethodProducibleMediaTypesList) {
                                try {
@@ -229,7 +242,7 @@ class ResponseProcessor {
                        }
                }
 
-               if (acceptHeader.getAcceptingMediaType(mediaType) == null) {
+               if (acceptHeader.getAcceptingMediaType(mediaType).isEmpty()) {
                        if (!mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
                                throw new WebApplicationException(406);
                        }
@@ -356,11 +369,10 @@ class ResponseProcessor {
        private static List<MediaType> 
expandListWithConcreterTypesFromAccept(List<MediaType> mediaTypesList, 
AcceptHeader acceptHeader) {
                Collection<MediaType> addition = new HashSet<MediaType>();
                for (MediaType mediaType : mediaTypesList) {
-                       MediaType acceptingType = 
acceptHeader.getAcceptingMediaType(mediaType);
-
-                       if ((acceptingType != null) && 
-                                       
(MediaTypeComparator.compareByWildCardCount(acceptingType, mediaType) == -1)) {
-                               addition.add(acceptingType);
+                       for (MediaType acceptingType : 
acceptHeader.getAcceptingMediaType(mediaType)) {
+                               if 
(MediaTypeComparator.compareByWildCardCount(acceptingType, mediaType) == -1) {
+                                       addition.add(acceptingType);
+                               }
                        }
                }
                final List<MediaType> result = new ArrayList<MediaType>();
@@ -478,4 +490,67 @@ class ResponseProcessor {
                return new MediaType(mediaType.getType(), 
mediaType.getSubtype(),
                                resultParams);
        }
+
+       /**
+        *
+        * @param <T>
+        * @param collection
+        * @param comparator
+        * @return a list containing sets of instances for which the comparator 
returns 0
+        * in oder
+        */
+       private static <T> List<Set<T>> getSortedClasses(Collection<T> 
collection,
+                       Comparator<T> comparator) {
+               List<Set<T>> result = new ArrayList<Set<T>>();
+               if (collection.size() > 0) {
+                       Set<T> pivotSet = new HashSet<T>();
+                       Collection<T> before = new ArrayList<T>();
+                       Collection<T> after = new ArrayList<T>();
+                       Iterator<T> iterator = collection.iterator();
+                       T pivot = iterator.next();
+                       pivotSet.add(pivot);
+                       while (iterator.hasNext()) {
+                               T next = iterator.next();
+                               int comparison = comparator.compare(next, 
pivot);
+                               if (comparison > 0) {
+                                       after.add(next);
+                               } else {
+                                       if (comparison < 0) {
+                                               before.add(next);
+                                       } else {
+                                               pivotSet.add(next);
+                                       }
+                               }
+                       }
+                       result.addAll(getSortedClasses(before, comparator));
+                       result.add(pivotSet);
+                       result.addAll(getSortedClasses(after, comparator));
+               }
+               return result;
+
+       }
+
+       /**
+        * 
+        * @param writer
+        * @param mediaType
+        * @return 0 is mediaType ismatched only by wildcard in the @Produces 
of writer,
+        *       1, if the supertype is concrete, 2 if the subtype is concrete 
too
+        */
+       private static int getWriterConcreteness(MessageBodyWriter<Object> 
writer, MediaType mediaType) {
+               Produces produces = 
writer.getClass().getAnnotation(Produces.class);
+               int result = 0;
+               if (produces != null) {
+                       for (String producedValue : produces.value()) {
+                               MediaType producesType = 
MediaType.valueOf(producedValue);
+                               if (producesType.isCompatible(mediaType)) {
+                                       int concreteness = 2 - 
MediaTypeComparator.countWildChars(producesType);
+                                       if (concreteness > result) {
+                                               result = concreteness;
+                                       }
+                               }
+                       }
+               }
+               return result;
+       }
 }

Modified: 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/AcceptHeader.java
URL: 
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/AcceptHeader.java?rev=981338&r1=981337&r2=981338&view=diff
==============================================================================
--- 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/AcceptHeader.java
 (original)
+++ 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/AcceptHeader.java
 Sun Aug  1 22:39:52 2010
@@ -19,7 +19,9 @@
 package org.apache.clerezza.triaxrs.util;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
@@ -123,13 +125,27 @@ public class AcceptHeader {
                return 0;
        }
 
-       public MediaType getAcceptingMediaType(MediaType type) {
+       /**
+        *
+        * @param type
+        * @return the media-types in the accept header that are would best 
accept
+        * type, i.e. all pattern with the highest same q-value accepting type 
are
+        * returned
+        */
+       public Set<MediaType> getAcceptingMediaType(MediaType type) {
+               Set<MediaType> result = new HashSet<MediaType>();
+               double currentQValue = 0;
                for (AcceptHeaderEntry acceptHeaderEntry : entries) {
                        if (acceptHeaderEntry.mediaType.isCompatible(type)) {
-                               return acceptHeaderEntry.mediaType;
+                               if (acceptHeaderEntry.quality >= currentQValue) 
{
+                                       currentQValue = 
acceptHeaderEntry.quality;
+                                       result.add(acceptHeaderEntry.mediaType);
+                               } else {
+                                       break;
+                               }
                        }
                }
-               return null;
+               return result;
        }
 
        /**

Added: 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/InconsistentMediaTypeComparator.java
URL: 
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/InconsistentMediaTypeComparator.java?rev=981338&view=auto
==============================================================================
--- 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/InconsistentMediaTypeComparator.java
 (added)
+++ 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/InconsistentMediaTypeComparator.java
 Sun Aug  1 22:39:52 2010
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.clerezza.triaxrs.util;
+
+import java.util.Comparator;
+
+import javax.ws.rs.core.MediaType;
+
+/**
+ * Sorts media types in accordance with an accept-header inconsistently
+ *
+ * This comparator is not consistent with equals
+ *
+ * @author reto
+ */
+public class InconsistentMediaTypeComparator implements Comparator<MediaType> {
+
+       private AcceptHeader acceptHeader;
+
+       public InconsistentMediaTypeComparator() {
+       }
+
+       public InconsistentMediaTypeComparator(AcceptHeader acceptHeader) {
+               this.acceptHeader = acceptHeader;
+       }
+
+
+       
+       @Override
+       public int compare(MediaType o1, MediaType o2) {
+               if (o1.equals(o2)) return 0;
+               if (acceptHeader != null) {
+                       if (acceptHeader.getAcceptedQuality(o1) > 
acceptHeader.getAcceptedQuality(o2)) {
+                               return -1;
+                       }
+                       if (acceptHeader.getAcceptedQuality(o1) < 
acceptHeader.getAcceptedQuality(o2)) {
+                               return 1;
+                       }
+               }
+               return MediaTypeComparator.inconsistentCompare(o1, o2);
+               
+       }
+
+}

Modified: 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/MediaTypeComparator.java
URL: 
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/MediaTypeComparator.java?rev=981338&r1=981337&r2=981338&view=diff
==============================================================================
--- 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/MediaTypeComparator.java
 (original)
+++ 
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/MediaTypeComparator.java
 Sun Aug  1 22:39:52 2010
@@ -23,8 +23,10 @@ import java.util.Comparator;
 import javax.ws.rs.core.MediaType;
 
 /**
- * Uses wirldcard as firts key and q-value as second key (for selecting 
- * server-side entities as jax-rs spec ignores q-value in annotations.
+ * Sorts media types in accordance with an accept-header, falling back to 
literal
+ * sorting to guarantee constistency.
+ *
+ * Also provides static Utility methods for Media Type comparison.
  *
  * @author reto
  */


Reply via email to