package org.xins.common.types.standard;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.StringTokenizer;
import org.xins.common.Utils;
import org.xins.common.text.FormatException;
import org.xins.common.text.URLEncoding;
import org.xins.common.types.Type;
import org.xins.common.types.TypeValueException;
import org.xins.common.MandatoryArgumentChecker;
public class Properties extends Type {
public static final Properties SINGLETON = new Properties();
private final Type _nameType;
private final Type _valueType;
private Properties() {
this("_properties", null, null);
}
protected Properties(String name, Type nameType, Type valueType) {
super(name, Map.class);
_nameType = nameType == null ? Text.SINGLETON : nameType;
_valueType = valueType == null ? Text.SINGLETON : valueType;
}
public static Map<String, String> fromStringForRequired(String string)
throws IllegalArgumentException, TypeValueException {
MandatoryArgumentChecker.check("string", string);
return (Map<String, String>) SINGLETON.fromString(string);
}
public static Map<String, String> fromStringForOptional(String string)
throws TypeValueException {
return (Map<String, String>) SINGLETON.fromString(string);
}
public static String toString(Map<String, String> value) {
if (value == null) {
return null;
}
StringBuffer buffer = new StringBuffer(255);
boolean first = true;
for (Map.Entry<String, String> entry : value.entrySet()) {
if (!first) {
buffer.append('&');
} else {
first = false;
}
String propName = entry.getKey();
String propValue = entry.getValue();
buffer.append(URLEncoding.encode(propName));
buffer.append('=');
if (propValue != null) {
buffer.append(URLEncoding.encode(propValue));
}
}
return buffer.toString();
}
protected final boolean isValidValueImpl(String string) {
HashSet propertyKeys = new HashSet();
if (string == null) {
return false;
}
StringTokenizer tokenizer = new StringTokenizer(string, "&");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
int index = token.indexOf('=');
if (index < 1) {
return false;
} else if (token.length() > (index + 1) && token.indexOf('=', index + 1) >= 0) {
return false;
} else {
try {
String name = URLEncoding.decode(token.substring(0, index));
if (propertyKeys.contains(name)) {
return false;
}
propertyKeys.add(name);
String value = token.substring(index + 1);
if (value.length() < 1) {
value = null;
} else {
value = URLEncoding.decode(value);
}
if (!_nameType.isValidValue(name)) {
return false;
}
if (!_valueType.isValidValue(value)) {
return false;
}
} catch (Exception decodingException) {
throw Utils.logProgrammingError(decodingException);
}
}
}
return true;
}
protected final Object fromStringImpl(String string)
throws TypeValueException {
Map<String, String> pr = new HashMap<String, String>();
HashSet propertyKeys = new HashSet();
StringTokenizer tokenizer = new StringTokenizer(string, "&");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
int index = token.indexOf('=');
if (index < 1) {
throw new TypeValueException(SINGLETON, string, "The token \"" + token + "\" does not contain an equals sign ('=').");
} else if (token.length() > (index + 1) && token.indexOf('=', index + 1) >= 0) {
throw new TypeValueException(SINGLETON, string);
} else {
try {
String name = URLEncoding.decode(token.substring(0, index));
if (propertyKeys.contains(name)) {
throw new TypeValueException(SINGLETON, string, "The key \"" + name + "\" is already set.");
}
propertyKeys.add(name);
String value = token.substring(index + 1);
if (value.length() < 1) {
value = null;
} else {
value = URLEncoding.decode(value);
}
_nameType.checkValue(name);
_valueType.checkValue(value);
pr.put(name, value);
} catch (FormatException fe) {
throw new TypeValueException(SINGLETON, string, fe.getReason());
} catch (IllegalArgumentException iae) {
throw Utils.logProgrammingError(iae);
}
}
}
return pr;
}
public final String toString(Object value)
throws IllegalArgumentException, ClassCastException, TypeValueException {
MandatoryArgumentChecker.check("value", value);
return toString((Map<String, String>) value);
}
public String getDescription() {
return "An ampersand separated list of key value pair in the format key=value.";
}
}