@Test
  public void compareToMediaTypeAll() {
    MockHttpServletRequest request = new MockHttpServletRequest();

    ProducesRequestCondition condition1 = new ProducesRequestCondition();
    ProducesRequestCondition condition2 = new ProducesRequestCondition("application/json");

    assertTrue(
        "Should have picked '*/*' condition as an exact match",
        condition1.compareTo(condition2, request) < 0);
    assertTrue(
        "Should have picked '*/*' condition as an exact match",
        condition2.compareTo(condition1, request) > 0);

    condition1 = new ProducesRequestCondition("*/*");
    condition2 = new ProducesRequestCondition("application/json");

    assertTrue(condition1.compareTo(condition2, request) < 0);
    assertTrue(condition2.compareTo(condition1, request) > 0);

    request.addHeader("Accept", "*/*");

    condition1 = new ProducesRequestCondition();
    condition2 = new ProducesRequestCondition("application/json");

    assertTrue(condition1.compareTo(condition2, request) < 0);
    assertTrue(condition2.compareTo(condition1, request) > 0);

    condition1 = new ProducesRequestCondition("*/*");
    condition2 = new ProducesRequestCondition("application/json");

    assertTrue(condition1.compareTo(condition2, request) < 0);
    assertTrue(condition2.compareTo(condition1, request) > 0);
  }
  @Test
  public void combine() {
    ProducesRequestCondition condition1 = new ProducesRequestCondition("text/plain");
    ProducesRequestCondition condition2 = new ProducesRequestCondition("application/xml");

    ProducesRequestCondition result = condition1.combine(condition2);
    assertEquals(condition2, result);
  }
  @Test
  public void combineWithDefault() {
    ProducesRequestCondition condition1 = new ProducesRequestCondition("text/plain");
    ProducesRequestCondition condition2 = new ProducesRequestCondition();

    ProducesRequestCondition result = condition1.combine(condition2);
    assertEquals(condition1, result);
  }
  @Test
  public void matchSingle() {
    ProducesRequestCondition condition = new ProducesRequestCondition("text/plain");

    MockHttpServletRequest request = new MockHttpServletRequest();
    request.addHeader("Accept", "application/xml");

    assertNull(condition.getMatchingCondition(request));
  }
  @Test
  public void matchByRequestParameter() {
    ProducesRequestCondition condition =
        new ProducesRequestCondition(new String[] {"text/plain"}, new String[] {});

    MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.txt");

    assertNotNull(condition.getMatchingCondition(request));
  }
  @Test
  public void matchParseError() {
    ProducesRequestCondition condition = new ProducesRequestCondition("text/plain");

    MockHttpServletRequest request = new MockHttpServletRequest();
    request.addHeader("Accept", "bogus");

    assertNull(condition.getMatchingCondition(request));
  }
  @Test
  public void compareToMediaTypeAllWithParameter() {
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.addHeader("Accept", "*/*;q=0.9");

    ProducesRequestCondition condition1 = new ProducesRequestCondition();
    ProducesRequestCondition condition2 = new ProducesRequestCondition("application/json");

    assertTrue(condition1.compareTo(condition2, request) < 0);
    assertTrue(condition2.compareTo(condition1, request) > 0);
  }
  @Test
  public void compareToWithSingleExpression() {
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.addHeader("Accept", "text/plain");

    ProducesRequestCondition condition1 = new ProducesRequestCondition("text/plain");
    ProducesRequestCondition condition2 = new ProducesRequestCondition("text/*");

    int result = condition1.compareTo(condition2, request);
    assertTrue("Invalid comparison result: " + result, result < 0);

    result = condition2.compareTo(condition1, request);
    assertTrue("Invalid comparison result: " + result, result > 0);
  }
  @Test
  public void compareToEqualMatch() {
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.addHeader("Accept", "text/*");

    ProducesRequestCondition condition1 = new ProducesRequestCondition("text/plain");
    ProducesRequestCondition condition2 = new ProducesRequestCondition("text/xhtml");

    int result = condition1.compareTo(condition2, request);
    assertTrue("Should have used MediaType.equals(Object) to break the match", result < 0);

    result = condition2.compareTo(condition1, request);
    assertTrue("Should have used MediaType.equals(Object) to break the match", result > 0);
  }
 /**
  * Compares "this" info (i.e. the current instance) with another info in the context of a request.
  *
  * <p>Note: it is assumed both instances have been obtained via {@link
  * #getMatchingInfo(HttpServletRequest)} to ensure they have conditions with content relevant to
  * current request.
  */
 public int compareTo(RequestMappingInfo other, HttpServletRequest request) {
   int result = patternsCondition.compareTo(other.getPatternsCondition(), request);
   if (result != 0) {
     return result;
   }
   result = paramsCondition.compareTo(other.getParamsCondition(), request);
   if (result != 0) {
     return result;
   }
   result = headersCondition.compareTo(other.getHeadersCondition(), request);
   if (result != 0) {
     return result;
   }
   result = consumesCondition.compareTo(other.getConsumesCondition(), request);
   if (result != 0) {
     return result;
   }
   result = producesCondition.compareTo(other.getProducesCondition(), request);
   if (result != 0) {
     return result;
   }
   result = methodsCondition.compareTo(other.getMethodsCondition(), request);
   if (result != 0) {
     return result;
   }
   result = customCondition.compareTo(other.customCondition, request);
   if (result != 0) {
     return result;
   }
   return 0;
 }
  /**
   * Checks if all conditions in this request mapping info match the provided request and returns a
   * potentially new request mapping info with conditions tailored to the current request.
   *
   * <p>For example the returned instance may contain the subset of URL patterns that match to the
   * current request, sorted with best matching patterns on top.
   *
   * @return a new instance in case all conditions match; or {@code null} otherwise
   */
  public RequestMappingInfo getMatchingInfo(HttpServletRequest request) {
    RequestMethodsRequestCondition methods = methodsCondition.getMatchingCondition(request);
    ParamsRequestCondition params = paramsCondition.getMatchingCondition(request);
    HeadersRequestCondition headers = headersCondition.getMatchingCondition(request);
    ConsumesRequestCondition consumes = consumesCondition.getMatchingCondition(request);
    ProducesRequestCondition produces = producesCondition.getMatchingCondition(request);

    if (methods == null
        || params == null
        || headers == null
        || consumes == null
        || produces == null) {
      return null;
    }

    PatternsRequestCondition patterns = patternsCondition.getMatchingCondition(request);
    if (patterns == null) {
      return null;
    }

    CustomRequestCondition custom = customCondition.getMatchingCondition(request);
    if (custom == null) {
      return null;
    }

    return new RequestMappingInfo(
        patterns, methods, params, headers, consumes, produces, custom.getCondition());
  }
  @Test
  public void getMatchingCondition() {
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.addHeader("Accept", "text/plain");

    ProducesRequestCondition condition =
        new ProducesRequestCondition("text/plain", "application/xml");

    ProducesRequestCondition result = condition.getMatchingCondition(request);
    assertConditions(result, "text/plain");

    condition = new ProducesRequestCondition("application/xml");

    result = condition.getMatchingCondition(request);
    assertNull(result);
  }
  private int compareMatchingMediaTypes(
      ProducesRequestCondition condition1,
      int index1,
      ProducesRequestCondition condition2,
      int index2) {

    int result = 0;
    if (index1 != index2) {
      result = index2 - index1;
    } else if (index1 != -1) {
      ProduceMediaTypeExpression expr1 = condition1.getExpressionsToCompare().get(index1);
      ProduceMediaTypeExpression expr2 = condition2.getExpressionsToCompare().get(index2);
      result = expr1.compareTo(expr2);
      result = (result != 0) ? result : expr1.getMediaType().compareTo(expr2.getMediaType());
    }
    return result;
  }
  @Test
  public void compareToMultipleExpressionsAndMultipeAcceptHeaderValues() {
    ProducesRequestCondition condition1 = new ProducesRequestCondition("text/*", "text/plain");
    ProducesRequestCondition condition2 =
        new ProducesRequestCondition("application/*", "application/xml");

    MockHttpServletRequest request = new MockHttpServletRequest();
    request.addHeader("Accept", "text/plain");
    request.addHeader("Accept", "application/xml");

    int result = condition1.compareTo(condition2, request);
    assertTrue("Invalid comparison result: " + result, result < 0);

    result = condition2.compareTo(condition1, request);
    assertTrue("Invalid comparison result: " + result, result > 0);

    request = new MockHttpServletRequest();
    request.addHeader("Accept", "application/xml");
    request.addHeader("Accept", "text/plain");

    result = condition1.compareTo(condition2, request);
    assertTrue("Invalid comparison result: " + result, result > 0);

    result = condition2.compareTo(condition1, request);
    assertTrue("Invalid comparison result: " + result, result < 0);
  }
 /**
  * Compares this and another "produces" condition as follows:
  *
  * <ol>
  *   <li>Sort 'Accept' header media types by quality value via {@link
  *       MediaType#sortByQualityValue(List)} and iterate the list.
  *   <li>Get the first index of matching media types in each "produces" condition first matching
  *       with {@link MediaType#equals(Object)} and then with {@link
  *       MediaType#includes(MediaType)}.
  *   <li>If a lower index is found, the condition at that index wins.
  *   <li>If both indexes are equal, the media types at the index are compared further with {@link
  *       MediaType#SPECIFICITY_COMPARATOR}.
  * </ol>
  *
  * <p>It is assumed that both instances have been obtained via {@link
  * #getMatchingCondition(HttpServletRequest)} and each instance contains the matching producible
  * media type expression only or is otherwise empty.
  */
 @Override
 public int compareTo(ProducesRequestCondition other, HttpServletRequest request) {
   try {
     List<MediaType> acceptedMediaTypes = getAcceptedMediaTypes(request);
     for (MediaType acceptedMediaType : acceptedMediaTypes) {
       int thisIndex = this.indexOfEqualMediaType(acceptedMediaType);
       int otherIndex = other.indexOfEqualMediaType(acceptedMediaType);
       int result = compareMatchingMediaTypes(this, thisIndex, other, otherIndex);
       if (result != 0) {
         return result;
       }
       thisIndex = this.indexOfIncludedMediaType(acceptedMediaType);
       otherIndex = other.indexOfIncludedMediaType(acceptedMediaType);
       result = compareMatchingMediaTypes(this, thisIndex, other, otherIndex);
       if (result != 0) {
         return result;
       }
     }
     return 0;
   } catch (HttpMediaTypeNotAcceptableException e) {
     // should never happen
     throw new IllegalStateException("Cannot compare without having any requested media types");
   }
 }
 @Override
 public int hashCode() {
   int result = hash;
   if (result == 0) {
     result = patternsCondition.hashCode();
     result = 31 * result + methodsCondition.hashCode();
     result = 31 * result + paramsCondition.hashCode();
     result = 31 * result + headersCondition.hashCode();
     result = 31 * result + consumesCondition.hashCode();
     result = 31 * result + producesCondition.hashCode();
     result = 31 * result + customCondition.hashCode();
     hash = result;
   }
   return result;
 }
 private void assertConditions(ProducesRequestCondition condition, String... expected) {
   Collection<ProduceMediaTypeExpression> expressions = condition.getContent();
   assertEquals("Invalid number of conditions", expressions.size(), expected.length);
   for (String s : expected) {
     boolean found = false;
     for (ProduceMediaTypeExpression expr : expressions) {
       String conditionMediaType = expr.getMediaType().toString();
       if (conditionMediaType.equals(s)) {
         found = true;
         break;
       }
     }
     if (!found) {
       fail("Condition [" + s + "] not found");
     }
   }
 }
  @Test
  public void compareTo() {
    ProducesRequestCondition html = new ProducesRequestCondition("text/html");
    ProducesRequestCondition xml = new ProducesRequestCondition("application/xml");
    ProducesRequestCondition none = new ProducesRequestCondition();

    MockHttpServletRequest request = new MockHttpServletRequest();
    request.addHeader("Accept", "application/xml, text/html");

    assertTrue(html.compareTo(xml, request) > 0);
    assertTrue(xml.compareTo(html, request) < 0);
    assertTrue(xml.compareTo(none, request) < 0);
    assertTrue(none.compareTo(xml, request) > 0);
    assertTrue(html.compareTo(none, request) < 0);
    assertTrue(none.compareTo(html, request) > 0);

    request = new MockHttpServletRequest();
    request.addHeader("Accept", "application/xml, text/*");

    assertTrue(html.compareTo(xml, request) > 0);
    assertTrue(xml.compareTo(html, request) < 0);

    request = new MockHttpServletRequest();
    request.addHeader("Accept", "application/pdf");

    assertTrue(html.compareTo(xml, request) == 0);
    assertTrue(xml.compareTo(html, request) == 0);

    // See SPR-7000
    request = new MockHttpServletRequest();
    request.addHeader("Accept", "text/html;q=0.9,application/xml");

    assertTrue(html.compareTo(xml, request) > 0);
    assertTrue(xml.compareTo(html, request) < 0);
  }
 @Test
 public void getProducibleMediaTypes() {
   ProducesRequestCondition condition = new ProducesRequestCondition("!application/xml");
   assertEquals(Collections.emptySet(), condition.getProducibleMediaTypes());
 }