View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *  http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.any23.mime;
19  
20  /**
21   * A MIME type with an optional q (quality) value.
22   *
23   * @author Richard Cyganiak (richard@cyganiak.de)
24   */
25  public class MIMEType implements Comparable<MIMEType> {
26  
27      private static final String MSG = "Cannot parse MIME type (expected type/subtype[;q=x.y] format): ";
28  
29      private final String type;
30  
31      private final String subtype;
32  
33      private final double q;
34  
35      private MIMEType(String type, String subtype, double q) {
36          this.type = type;
37          this.subtype = subtype;
38          this.q = q;
39      }
40  
41      /**
42       * Parses the given MIME type string returning an instance of {@link MIMEType}. The expected format for
43       * <code>mimeType</code> is <code>type/subtype[;q=x.y]</code> . An example of valid mime type is:
44       * <code>application/rdf+xml;q=0.9</code>
45       *
46       * @param mimeType
47       *            a provided mimetype string.
48       * 
49       * @return the mime type instance.
50       * 
51       * @throws IllegalArgumentException
52       *             if the <code>mimeType</code> is not well formatted.
53       */
54      public static MIMEType parse(String mimeType) {
55          if (mimeType == null) {
56              return null;
57          }
58          int i = mimeType.indexOf(';');
59          double q = 1.0;
60          if (i > -1) {
61              String[] params = mimeType.substring(i + 1).split(";");
62              for (String param : params) {
63                  int i2 = param.indexOf('=');
64                  if (i2 == -1) {
65                      continue;
66                  }
67                  if (!"q".equals(param.substring(0, i2).trim().toLowerCase(java.util.Locale.ROOT))) {
68                      continue;
69                  }
70                  String value = param.substring(i2 + 1);
71                  try {
72                      q = Double.parseDouble(value);
73                  } catch (NumberFormatException ex) {
74                      continue;
75                  }
76                  if (q <= 0.0 || q >= 1.0) {
77                      q = 1.0;
78                  }
79              }
80          } else {
81              i = mimeType.length();
82          }
83          String type = mimeType.substring(0, i);
84          int i2 = type.indexOf('/');
85          if (i2 == -1) {
86              throw new IllegalArgumentException(MSG + mimeType);
87          }
88          String p1 = type.substring(0, i2).trim().toLowerCase(java.util.Locale.ROOT);
89          String p2 = type.substring(i2 + 1).trim().toLowerCase(java.util.Locale.ROOT);
90          if ("*".equals(p1)) {
91              if (!"*".equals(p2)) {
92                  throw new IllegalArgumentException(MSG + mimeType);
93              }
94              return new MIMEType(null, null, q);
95          }
96          if ("*".equals(p2)) {
97              return new MIMEType(p1, null, q);
98          }
99          return new MIMEType(p1, p2, q);
100     }
101 
102     public String getMajorType() {
103         return type == null ? "*" : type;
104     }
105 
106     public String getSubtype() {
107         return subtype == null ? "*" : subtype;
108     }
109 
110     public String getFullType() {
111         return getMajorType() + "/" + getSubtype();
112     }
113 
114     public double getQuality() {
115         return q;
116     }
117 
118     public boolean isAnyMajorType() {
119         return type == null;
120     }
121 
122     public boolean isAnySubtype() {
123         return subtype == null;
124     }
125 
126     @Override
127     public String toString() {
128         if (q == 1.0) {
129             return getFullType();
130         }
131         return getFullType() + ";q=" + q;
132     }
133 
134     @Override
135     public int compareTo(MIMEType other) {
136         return getFullType().compareTo(other.getFullType());
137     }
138 
139 }