/* * Copyright 2015 ArcBees Inc. * * Licensed 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 com.gwtplatform.dispatch.rest.shared; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; /** * Represent each parts of a content type. Formatting is based on * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7">RFC 2616, section 3.7</a>. */ public class ContentType { private static final String KEY_VALUE_DELIMITER = "="; private static final String PARAMETER_DELIMITER = ";"; private static final String TYPE_DELIMITER = "/"; private static final String WILDCARD = "*"; private final String type; private final String subType; private final Map<String, String> parameters; public ContentType( String type, String subType, Map<String, String> parameters) { this.type = valueOrWildcard(type); this.subType = valueOrWildcard(subType); this.parameters = parameters; } /** * Parses a content type and return an object representation. Input may look like: * <p/> * application/json; charset=utf-8; q=0.9 */ public static ContentType valueOf(String value) { String type = WILDCARD; String subType = WILDCARD; Map<String, String> parameters = new HashMap<>(); if (value != null) { String[] parts = value.split(PARAMETER_DELIMITER); String[] types = parts[0].split(TYPE_DELIMITER); type = types[0]; if (types.length > 1) { subType = types[1]; } // Element 0 is type/sub-type, others are parameters for (int i = 1; i < parts.length; ++i) { String[] keyValue = parts[i].split(KEY_VALUE_DELIMITER); if (keyValue.length == 2) { parameters.put(keyValue[0].trim(), keyValue[1].trim()); } } } return new ContentType(type, subType, parameters); } @Override public String toString() { StringBuilder builder = new StringBuilder().append(type).append('/').append(subType); for (Entry<String, String> parameter : parameters.entrySet()) { builder.append("; ").append(parameter.getKey()).append('=').append(parameter.getValue()); } return builder.toString(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ContentType that = (ContentType) o; return parameters.equals(that.parameters) && subType.equals(that.subType) && type.equals(that.type); } @Override public int hashCode() { int result = type.hashCode(); result = 31 * result + subType.hashCode(); result = 31 * result + parameters.hashCode(); return result; } public String getType() { return type; } /** * Checks if the primary type is a wildcard. * * @return <code>true</code> if the primary type is a wildcard. */ public boolean isWildcardType() { return getType().equals(WILDCARD); } public String getSubType() { return subType; } /** * Checks if the sub type is a wildcard. * * @return <code>true</code> if the sub type is a wildcard. */ public boolean isWildcardSubType() { return getSubType().equals(WILDCARD); } /** * Checks if either the primary type or the sub type is a wildcard. * * @return <code>true</code> if the primary type or sub type is a wildcard. */ public boolean isWildcard() { return isWildcardType() || isWildcardSubType(); } public Map<String, String> getParameters() { return parameters; } public boolean isCompatible(ContentType other) { if (other == null) { return false; } else if (getType().equals(WILDCARD) || other.getType().equals(WILDCARD)) { return true; } else if (getType().equals(other.getType())) { return getSubType().equals(WILDCARD) || other.getSubType().equals(WILDCARD) || getSubType().equals(other.getSubType()); } return false; } private String valueOrWildcard(String type) { return type == null || type.trim().isEmpty() ? WILDCARD : type.trim().toLowerCase(); } }