@@ -33,15 +33,32 @@ private MediaType(String type, String subtype, Map<String, String> parameters) {
3333 this .parameters = Collections .unmodifiableMap (new LinkedHashMap <>(parameters ));
3434 }
3535
36+ /**
37+ * Creates a new media type with the given type and subtype.
38+ *
39+ * @param type the media type
40+ * @param subtype the media subtype
41+ * @return the media type
42+ */
3643 public static MediaType create (String type , String subtype ) {
3744 return new MediaType (type , subtype , Map .of ());
3845 }
3946
4047 /**
41- * Parses strings like:
42- * - "application/json"
43- * - "application/json; charset=UTF-8"
44- * - "text/plain; charset=\"utf-8\"; format=flowed"
48+ * Parses a media type string into a MediaType object.
49+ * <p>
50+ * Supports parsing of:
51+ * - Simple media types: "application/json"
52+ * - Media types with charset: "application/json; charset=UTF-8"
53+ * - Media types with multiple parameters: "text/plain; charset=\"utf-8\"; format=flowed"
54+ * <p>
55+ * Parameter names and values are normalized according to HTTP standards.
56+ * Type and subtype are converted to lowercase.
57+ *
58+ * @param input the media type string to parse
59+ * @return the parsed MediaType object
60+ * @throws NullPointerException if input is null
61+ * @throws IllegalArgumentException if input is empty or malformed
4562 */
4663 public static MediaType parse (String input ) {
4764 Objects .requireNonNull (input , "input" );
@@ -62,7 +79,9 @@ public static MediaType parse(String input) {
6279 Map <String , String > params = new LinkedHashMap <>();
6380 for (int i = 1 ; i < parts .length ; i ++) {
6481 String p = parts [i ].trim ();
65- if (p .isEmpty ()) continue ;
82+ if (p .isEmpty ()) {
83+ continue ;
84+ }
6685
6786 int eq = p .indexOf ('=' );
6887 if (eq <= 0 || eq == p .length () - 1 ) {
@@ -84,34 +103,87 @@ public static MediaType parse(String input) {
84103 return new MediaType (type , subtype , params );
85104 }
86105
106+ /**
107+ * Returns the primary type of this media type.
108+ * <p>
109+ * For example, "application" in "application/json".
110+ *
111+ * @return the primary type, normalized to lowercase
112+ */
87113 public String type () {
88114 return type ;
89115 }
90116
117+ /**
118+ * Returns the subtype of this media type.
119+ * <p>
120+ * For example, "json" in "application/json".
121+ *
122+ * @return the subtype, normalized to lowercase
123+ */
91124 public String subtype () {
92125 return subtype ;
93126 }
94127
128+ /**
129+ * Checks if this media type contains a wildcard in either the type or subtype.
130+ * <p>
131+ * Examples of wildcards:
132+ * <ul>
133+ * <li>"*/*" (matches any type)</li>
134+ * <li>"text/*" (matches any text subtype)</li>
135+ * </ul>
136+ *
137+ * @return true if type or subtype is "*", false otherwise
138+ */
95139 public boolean hasWildcard () {
96140 return "*" .equals (type ) || "*" .equals (subtype );
97141 }
98142
143+ /**
144+ * Returns the charset parameter of this media type, if present and valid.
145+ * <p>
146+ * If the charset parameter is not present, blank, or refers to an unknown/invalid
147+ * charset name, returns an empty Optional.
148+ *
149+ * @return an Optional containing the Charset if valid, or empty otherwise
150+ */
99151 public Optional <Charset > charset () {
100152 String cs = parameters .get ("charset" );
101153 if (cs == null || cs .isBlank ()) return Optional .empty ();
102154 try {
103155 return Optional .of (Charset .forName (cs ));
104- } catch (Exception e ) {
156+ } catch (Exception _ ) {
105157 // unknown/invalid charset => behave safely
106158 return Optional .empty ();
107159 }
108160 }
109161
162+ /**
163+ * Returns a new MediaType with the specified charset parameter.
164+ * <p>
165+ * The charset name is normalized to lowercase.
166+ *
167+ * @param charset the charset to set
168+ * @return a new MediaType with the charset parameter
169+ * @throws NullPointerException if charset is null
170+ */
110171 public MediaType withCharset (Charset charset ) {
111172 Objects .requireNonNull (charset , "charset" );
112173 return withParameter ("charset" , charset .name ().toLowerCase (Locale .ROOT ));
113174 }
114175
176+ /**
177+ * Returns a new MediaType with the specified parameter added or replaced.
178+ * <p>
179+ * Parameter names are normalized to lowercase. If the parameter already exists,
180+ * its value is replaced. The charset parameter value is also normalized to lowercase.
181+ *
182+ * @param attribute the parameter name
183+ * @param value the parameter value
184+ * @return a new MediaType with the parameter
185+ * @throws NullPointerException if attribute or value is null
186+ */
115187 public MediaType withParameter (String attribute , String value ) {
116188 Objects .requireNonNull (attribute , "attribute" );
117189 Objects .requireNonNull (value , "value" );
@@ -128,11 +200,25 @@ public MediaType withParameter(String attribute, String value) {
128200 return new MediaType (type , subtype , copy );
129201 }
130202
203+ /**
204+ * Returns a new MediaType with all parameters removed.
205+ * <p>
206+ * If this media type has no parameters, returns this instance.
207+ *
208+ * @return a MediaType without parameters
209+ */
131210 public MediaType withoutParameters () {
132211 if (parameters .isEmpty ()) return this ;
133212 return new MediaType (type , subtype , Map .of ());
134213 }
135214
215+ /**
216+ * Returns an unmodifiable map of all parameters.
217+ * <p>
218+ * Parameter names are normalized to lowercase. The map preserves insertion order.
219+ *
220+ * @return an unmodifiable map of parameters
221+ */
136222 public Map <String , String > parameters () {
137223 return parameters ;
138224 }
@@ -162,8 +248,6 @@ public int hashCode() {
162248 return Objects .hash (type , subtype , parameters );
163249 }
164250
165- // ---------- helpers ----------
166-
167251 private static String normalizeToken (String token ) {
168252 String t = Objects .requireNonNull (token , "token" ).trim ();
169253 if (t .isEmpty ()) throw new IllegalArgumentException ("Invalid token: empty" );
@@ -188,6 +272,29 @@ private static String quoteIfNeeded(String v) {
188272 return v ;
189273 }
190274
275+ /**
276+ * Checks if this media type matches the specified media type.
277+ * <p>
278+ * Matching rules:
279+ * <ul>
280+ * <li>Wildcards ("*") in the other media type match any value</li>
281+ * <li>Type and subtype must match (unless wildcarded)</li>
282+ * <li>All parameters in the other media type must be present in this media type with the same values</li>
283+ * <li>This media type may have additional parameters not present in the other</li>
284+ * </ul>
285+ * <p>
286+ * Examples:
287+ * <ul>
288+ * <li>"application/json" matches "application/json"</li>
289+ * <li>"application/json" matches "*/*"</li>
290+ * <li>"text/plain; charset=utf-8" matches "text/plain"</li>
291+ * <li>"text/plain" does NOT match "text/plain; charset=utf-8"</li>
292+ * </ul>
293+ *
294+ * @param other the media type to match against
295+ * @return true if this media type matches the other, false otherwise
296+ * @throws NullPointerException if other is null
297+ */
191298 public boolean is (MediaType other ) {
192299 Objects .requireNonNull (other , "other" );
193300
0 commit comments