/* The contents of this file are subject to the license and copyright terms * detailed in the license directory at the root of the source tree (also * available online at http://fedora-commons.org/license/). */ package org.fcrepo.server; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MultiValueMap<T> { private static final Logger logger = LoggerFactory.getLogger(MultiValueMap.class); private static final String [] EMPTY_STRING_ARRAY = new String[0]; private boolean locked = false; private final Map<T,String[]> attributes = new HashMap<T,String[]>(); /** * Creates and initializes the <code>WritableContext</code>. * <p> * </p> * A pre-loaded Map of name-value pairs comprising the context. */ public MultiValueMap() { } public T setReturn(T name, String value) throws IllegalArgumentException, IllegalStateException { set(name, value); return name; } public void set(T name, String value) throws IllegalArgumentException, IllegalStateException { audit(name, value); if (value != null) { String [] temp = attributes.get(name); if (temp == null || temp.length != 1) { attributes.put(name, new String[]{value}); } else temp[0] = value; } else { attributes.put(name, EMPTY_STRING_ARRAY); } } public T setReturn(T name, String[] value) throws IllegalArgumentException, IllegalStateException { set(name, value); return name; } public void set(T name, String[] value) throws IllegalArgumentException, IllegalStateException { audit(name, value); if (value != null) { attributes.put(name, value); } else { attributes.put(name, EMPTY_STRING_ARRAY); } } public void lock() { locked = true; } public Iterator<T> names() { return attributes.keySet().iterator(); } public int length(T name) { if (attributes.get(name) != null) { return attributes.get(name).length; } else { return 0; } } /** * Returns the first (or only) value for an attribute * @param name * @return first available value */ public String getString(T name) { return (attributes.containsKey(name)) ? attributes.get(name)[0] : null; } public String[] getStringArray(T name) { return attributes.get(name); } @Override public String toString() { StringBuilder buffer = new StringBuilder(128*attributes.size()); Iterator<T> it = attributes.keySet().iterator(); while (it.hasNext()) { T key = it.next(); buffer.append(key.toString() + "=["); if (attributes.get(key) != null) { String[] temp = attributes.get(key); boolean second = false; for (String element : temp) { if (second) buffer.append(','); buffer.append(element); second |= true; } } buffer.append("]\n"); } return buffer.toString(); } /** * Test whether this map is equal to another similar one. We can't just test * for equality of the underlying maps, since they may contain arrays of * Strings as values, and those arrays are only equal if identical. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj == null) { return false; } if (!(obj instanceof MultiValueMap)) { return false; } @SuppressWarnings("unchecked") MultiValueMap<T> that = (MultiValueMap<T>) obj; return locked == that.locked && equalMaps(attributes, that.attributes); } private boolean equalMaps(Map<T,String[]> thisMap, Map<T,String[]> thatMap) { /* Check for obvious differences (same number and value of keys) */ if (!thisMap.keySet().equals(thatMap.keySet())) { return false; } Iterator<T> theseKeys = thisMap.keySet().iterator(); /* Now do a deep compare of contents.. */ while (theseKeys.hasNext()) { T key = theseKeys.next(); if (!Arrays.equals(thisMap.get(key), thatMap.get(key))) { return false; } } return true; } @Override public int hashCode() { return attributes.hashCode() + (locked ? 1 : 0); } public static <S> MultiValueMap<S> empty(Class<S> klazz) { MultiValueMap<S> result = new MultiValueMap<S>(); result.lock(); return result; } protected static final String here = "MultiValueMap"; private void audit(T key, Object value) throws IllegalArgumentException, IllegalStateException { if (key == null) { String msg = "{}: set() has null name, value={}"; logger.debug(msg, here, value); throw new IllegalArgumentException(msg); } if (locked) { String msg = "{}: set() has object locked"; logger.debug(msg, here); throw new IllegalStateException(msg); } } }