/* * 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.addthis.basis.kv; import com.addthis.basis.util.LessStrings; import com.addthis.basis.util.LessBytes; /** * Class that represents a key/value pair. Has helpers for parsing * pairs in common forms, including HTTP headers. Keys are always * converted to uppercase. Values are always urldecoded for storage. * Use toString() to regenerate the KVPair. */ public class KVPair { /** * Construct a KVPair wrapper from a string key and string value. * * @param key * @param val */ public KVPair(String key, String val) { setKeyValue(key, val); } private String key; private String val; /** * Turn an URLencoded 'name=value' string into a KVPair * * @param str * @return */ public static KVPair parsePair(String str) { int sep = str.indexOf('='); if (sep == 0 || str.length() == 0) { return null; } if (sep < 0) { return new KVPair(LessBytes.urldecode(str), ""); } if (sep < str.length() - 1) { return new KVPair(LessBytes.urldecode(str.substring(0, sep)), LessBytes.urldecode(str.substring(sep + 1))); } return new KVPair(LessBytes.urldecode(str.substring(0, sep)), ""); } /** * Turn an http header in the form "name: value" into a KVPair. * * @param str http header line * @return KVPair */ public static KVPair parseHttpHeader(String str) { int idx = str.indexOf(':'); if (idx == 0) { return null; } if (idx > 0) { if (idx < str.length() - 1) { int si = idx + 1; while (Character.isWhitespace(str.charAt(si)) && si < str.length() - 1) { si++; } return new KVPair(str.substring(0, idx), str.substring(si)); } else { return new KVPair(str.substring(0, idx), ""); } } else { return new KVPair(str, ""); } } /** * Set key and value at the same time. * * @param key * @param val */ public void setKeyValue(String key, String val) { if (key == null) { new Exception("null key").printStackTrace(); } setKey(key); setValue(val); } /** * @return key string */ public String getKey() { return key; } /** * returns true if keys match ignoring case. */ public boolean keyMatch(String k) { return key.equalsIgnoreCase(k); } /** * Set a new key. * * @param nk key string */ public void setKey(String nk) { this.key = nk; } /** * @param nv new value in urlencoded UTF-8 format * @return previous value */ public String setValue(String nv) { String oval = val; this.val = nv; return oval; } /** * Returns the urldecoded value. * * @return the urldecoded value */ public String getValue() { return val; } /** * Returns a urlencoded "name"=value pair. */ public String toQuotedKeyString() { if (val == null) { return LessStrings.cat("\"", LessBytes.urlencode(key), "\"="); } else { return LessStrings.cat("\"", LessBytes.urlencode(key), "\"=", LessBytes.urlencode(val)); } } /** * Returns a urlencoded name=value pair. */ public String toString() { if (val == null) { return LessStrings.cat(LessBytes.urlencode(key), "="); } else { return LessStrings.cat(LessBytes.urlencode(key), "=", LessBytes.urlencode(val)); } } /** * basic equals function * TODO: override hashcode() method as recommended by java api * * @return true if other KVPair has equal key (ignore key case) and value */ public boolean equals(KVPair other) { return other != null && getKey().equalsIgnoreCase(other.getKey()) && getValue().equals(other.getValue()); } }