/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You 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.esri.gpt.framework.collection;
import com.esri.gpt.framework.util.Val;
import java.util.LinkedHashMap;
/**
* Maintains an ordered map where are all map keys are stored as
* lower case strings.
* <p/>
* The primary intent is to provide a map having case insensitive keys.
* <p/>
* <br/>Map keys are trimmed and converted to lower case.
* <br/>Null map keys are converted to empty strings.
* <br/>Empty map keys are only set if specified as allowed on the constructor.
* <p/>
* Null values are not stored.
*/
public class CaseInsensitiveMap<T> extends LinkedHashMap<String,T> {
// class variables =============================================================
// instance variables ==========================================================
private boolean _allowEmptyKey = false;
// constructors ================================================================
/** Default constructor. */
private CaseInsensitiveMap() {}
/**
* Construct with a flag indicating if an empty map key is allowed.
* @param allowEmptyKey true if an empty key is allowed
*/
public CaseInsensitiveMap(boolean allowEmptyKey) {
setAllowEmptyKey(allowEmptyKey);
}
// properties ==================================================================
/**
* Gets the status indicating whether an empty key is allowed.
* @return true if an empty key is allowed
*/
protected boolean getAllowEmptyKey() {
return _allowEmptyKey;
}
/**
* Sets the status indicating whether an empty key is allowed.
* @param allowEmptyKey true if an empty key is allowed
*/
private void setAllowEmptyKey(boolean allowEmptyKey) {
_allowEmptyKey = allowEmptyKey;
}
// methods =====================================================================
/**
* Checks a key.
* <br/>Keys are trimmed and converted to lower case.
* <br/>Null keys are converted to empty strings.
* @param key the key to check
* @return the checked key
*/
private String checkKey(Object key) {
if ((key != null) && (key instanceof String)) {
return Val.chkStr((String)key).toLowerCase();
}
return "";
}
/**
* Determines if a key is contained within the map.
* @param key the key to check
* @return true if the key is contained
*/
@Override
public boolean containsKey(Object key) {
return super.containsKey(checkKey(key));
}
/**
* Gets the value associated with a key.
* @param key the key associated with the value to find
* @return the corresponding value (null if none was found)
*/
@Override
public T get(Object key) {
return super.get(checkKey(key));
}
/**
* Sets a value within the map.
* <p/>
* <br/>Keys are trimmed and converted to lower case.
* <br/>Null keys are converted to empty strings.
* <br/>Empty map keys are only set if specified as allowed on the constructor.
* <p/>
* Null values are not stored. If a null value is supplied, the value
* associated with the supplied key is removed (if it exists);
* @param key the key to set
* @param member the value to set
* @return the previously mapped value associated with the key,
* or null if there was no existing mapping for the key
*/
@Override
public T put(String key, T member) {
key = checkKey(key);
if (getAllowEmptyKey() || (key.length() > 0)) {
if (member == null) {
return this.remove(key);
} else {
return super.put(key,member);
}
}
return null;
}
/**
* Returns the string representation of the object.
* @return the string
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer(getClass().getName());
if (size() == 0) {
sb.append(" ()");
} else {
sb.append(" (\n");
for (T value: values()) {
sb.append(value).append("\n");
}
sb.append(") ===== end ").append(getClass().getName());
}
return sb.toString();
}
}