blob: d7639ce4020f71c0da359de1e25192db8847da3c [file] [log] [blame]
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF 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 org.apache.james.mime4j.util;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import org.apache.james.mime4j.message.Header;
import org.apache.james.mime4j.parser.ContentHandler;
import org.apache.james.mime4j.parser.Field;
/**
* An object, which may be used to implement header, or parameter
* maps. The maps keys are the header or parameter names. The
* maps values are strings (single value), lists, or arrays.
* <p>
* Note that this class is not directly used anywhere in Mime4j.
* Instead a user might choose to use it instead of {@link Header}
* and {@link Field} in a custom {@link ContentHandler} implementation.
* See also MIME4j-24.
*/
public class StringArrayMap implements Serializable {
private static final long serialVersionUID = -5833051164281786907L;
private final Map<String, Object> map = new HashMap<String, Object>();
/**
* <p>Converts the given object into a string. The object may be either of:
* <ul>
* <li>a string, which is returned without conversion</li>
* <li>a list of strings, in which case the first element is returned</li>
* <li>an array of strings, in which case the first element is returned</li>
* </ul>
*/
public static String asString(Object pValue) {
if (pValue == null) {
return null;
}
if (pValue instanceof String) {
return (String) pValue;
}
if (pValue instanceof String[]) {
return ((String[]) pValue)[0];
}
if (pValue instanceof List) {
return (String) ((List<?>) pValue).get(0);
}
throw new IllegalStateException("Invalid parameter class: " + pValue.getClass().getName());
}
/**
* <p>Converts the given object into a string array. The object may be either of:
* <ul>
* <li>a string, which is returned as an array with one element</li>
* <li>a list of strings, which is being converted into a string array</li>
* <li>an array of strings, which is returned without conversion</li>
* </ul>
*/
public static String[] asStringArray(Object pValue) {
if (pValue == null) {
return null;
}
if (pValue instanceof String) {
return new String[]{(String) pValue};
}
if (pValue instanceof String[]) {
return (String[]) pValue;
}
if (pValue instanceof List) {
final List<?> l = (List<?>) pValue;
return l.toArray(new String[l.size()]);
}
throw new IllegalStateException("Invalid parameter class: " + pValue.getClass().getName());
}
/**
* <p>Converts the given object into a string enumeration. The object may be either of:
* <ul>
* <li>a string, which is returned as an enumeration with one element</li>
* <li>a list of strings, which is being converted into a string enumeration</li>
* <li>an array of strings, which is being converted into a string enumeration</li>
* </ul>
*/
public static Enumeration<String> asStringEnum(final Object pValue) {
if (pValue == null) {
return null;
}
if (pValue instanceof String) {
return new Enumeration<String>(){
private Object value = pValue;
public boolean hasMoreElements() {
return value != null;
}
public String nextElement() {
if (value == null) {
throw new NoSuchElementException();
}
final String s = (String) value;
value = null;
return s;
}
};
}
if (pValue instanceof String[]) {
final String[] values = (String[]) pValue;
return new Enumeration<String>() {
private int offset;
public boolean hasMoreElements() {
return offset < values.length;
}
public String nextElement() {
if (offset >= values.length) {
throw new NoSuchElementException();
}
return values[offset++];
}
};
}
if (pValue instanceof List) {
@SuppressWarnings("unchecked")
final List<String> stringList = (List<String>) pValue;
return Collections.enumeration(stringList);
}
throw new IllegalStateException("Invalid parameter class: " + pValue.getClass().getName());
}
/**
* Converts the given map into a string array map: The map values
* are string arrays.
*/
public static Map<String, String[]> asMap(final Map<String, Object> pMap) {
Map<String, String[]> result = new HashMap<String, String[]>(pMap.size());
for (Map.Entry<String, Object> entry : pMap.entrySet()) {
final String[] value = asStringArray(entry.getValue());
result.put(entry.getKey(), value);
}
return Collections.unmodifiableMap(result);
}
/**
* Adds a value to the given map.
*/
protected void addMapValue(Map<String, Object> pMap, String pName, String pValue) {
Object o = pMap.get(pName);
if (o == null) {
o = pValue;
} else if (o instanceof String) {
final List<Object> list = new ArrayList<Object>();
list.add(o);
list.add(pValue);
o = list;
} else if (o instanceof List) {
@SuppressWarnings("unchecked")
final List<String> stringList = (List<String>) o;
stringList.add(pValue);
} else if (o instanceof String[]) {
final List<String> list = new ArrayList<String>();
final String[] arr = (String[]) o;
for (String str : arr) {
list.add(str);
}
list.add(pValue);
o = list;
} else {
throw new IllegalStateException("Invalid object type: " + o.getClass().getName());
}
pMap.put(pName, o);
}
/**
* Lower cases the given name.
*/
protected String convertName(String pName) {
return pName.toLowerCase();
}
/**
* Returns the requested value.
*/
public String getValue(String pName) {
return asString(map.get(convertName(pName)));
}
/**
* Returns the requested values as a string array.
*/
public String[] getValues(String pName) {
return asStringArray(map.get(convertName(pName)));
}
/**
* Returns the requested values as an enumeration.
*/
public Enumeration<String> getValueEnum(String pName) {
return asStringEnum(map.get(convertName(pName)));
}
/**
* Returns the set of registered names as an enumeration.
* @see #getNameArray()
*/
public Enumeration<String> getNames() {
return Collections.enumeration(map.keySet());
}
/**
* Returns an unmodifiable map of name/value pairs. The map keys
* are the lower cased parameter/header names. The map values are
* string arrays.
*/
public Map<String, String[]> getMap() {
return asMap(map);
}
/**
* Adds a new name/value pair.
*/
public void addValue(String pName, String pValue) {
addMapValue(map, convertName(pName), pValue);
}
/**
* Returns the set of registered names.
* @see #getNames()
*/
public String[] getNameArray() {
final Collection<String> c = map.keySet();
return c.toArray(new String[c.size()]);
}
}