package org.apache.slide.projector.descriptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.slide.projector.Context;
import org.apache.slide.projector.i18n.ErrorMessage;
import org.apache.slide.projector.i18n.ParameterMessage;
import org.apache.slide.projector.value.AnyValue;
import org.apache.slide.projector.value.MapValue;
import org.apache.slide.projector.value.NullValue;
import org.apache.slide.projector.value.Value;
public class MapValueDescriptor implements ValueDescriptor {
private final static String ELEMENT_NAME = "map";
public final static String ALL = "*";
public final static MapValueDescriptor ANY = new MapValueDescriptor(new ParameterDescriptor(MapValueDescriptor.ALL, new ParameterMessage("mapEntry/any"), new AnyValueDescriptor()));
protected List entryDescriptors = new ArrayList();
public MapValueDescriptor() {
}
public MapValueDescriptor(List entryDescriptors) {
this.entryDescriptors = entryDescriptors;
}
public MapValueDescriptor(ParameterDescriptor parameterDescriptor) {
entryDescriptors.add(parameterDescriptor);
}
public MapValueDescriptor(ParameterDescriptor[] parameterDescriptors) {
for ( int i = 0; i < parameterDescriptors.length; i++ ) {
entryDescriptors.add(parameterDescriptors[i]);
}
}
public void addEntryDescriptor(ParameterDescriptor parameterDescriptor) {
entryDescriptors.add(parameterDescriptor);
}
public List getEntryDescriptors() {
return entryDescriptors;
}
public Value valueOf(Object value, Context context) throws ValueCastException {
if ( entryDescriptors.isEmpty() ) {
throw new ValueCastException(new ErrorMessage("noMapEntryDescriptorsFound"));
}
if ( value instanceof MapValue ) {
return castedMap(((MapValue)value).getMap(), context);
} else if ( value instanceof Map ) {
return castedMap((Map)value, context);
} else {
throw new ValueCastException(new ErrorMessage("uncastableMapValue", new Object[] { value }));
}
}
private MapValue castedMap(Map map, Context context) throws ValueCastException {
Map castedMap = new HashMap(map);
for ( Iterator i = entryDescriptors.iterator(); i.hasNext(); ) {
ParameterDescriptor parameterDescriptor = (ParameterDescriptor)i.next();
ValueDescriptor entryDescriptor = parameterDescriptor.getValueDescriptor();
String key = parameterDescriptor.getName();
if ( key.equals(ALL) ) {
for ( Iterator j = castedMap.entrySet().iterator(); j.hasNext(); ) {
Map.Entry entry = (Map.Entry)j.next();
Object value = entry.getValue();
if ( value instanceof AnyValue ) {
try {
castedMap.put(entry.getKey(), entryDescriptor.valueOf(((AnyValue)value).load(context), context));
} catch (Exception e) {
throw new ValueCastException(new ErrorMessage("uncastableArrayValue", new Object[] { value }));
}
} else {
castedMap.put(entry.getKey(), entryDescriptor.valueOf(value, context));
}
}
} else {
if ( !castedMap.containsKey(key) ) {
if ( !parameterDescriptor.isRequired() ) {
castedMap.put(key, parameterDescriptor.getDefaultValue());
}
} else {
Object object = castedMap.get(key);
if ( object instanceof AnyValue ) {
try {
object = ((AnyValue)object).load(context);
} catch (Exception e) {
throw new ValueCastException(new ErrorMessage("uncastableArrayValue", new Object[] { object }), e);
}
}
if ( object.equals(parameterDescriptor.getDefaultValue())) {
castedMap.put(key, object);
} else {
castedMap.put(key, entryDescriptor.valueOf(object, context));
}
}
}
}
return new MapValue(castedMap);
}
public void validate(Value value, Context context) throws ValidationException {
Map map = ((MapValue)value).getMap();
for ( Iterator i = entryDescriptors.iterator(); i.hasNext(); ) {
ParameterDescriptor parameterDescriptor = (ParameterDescriptor)i.next();
ValueDescriptor entryDescriptor = parameterDescriptor.getValueDescriptor();
String key = parameterDescriptor.getName();
if ( key.equals(ALL) ) {
for ( Iterator j = map.values().iterator(); j.hasNext(); ) {
Value entryValue = (Value)j.next();
if ( !(entryValue instanceof NullValue) ) {
entryDescriptor.validate(entryValue, context);
}
}
} else {
if ( !map.containsKey(key) ) {
if ( parameterDescriptor.isRequired() ) {
throw new ValidationException(new ErrorMessage("mapEntryMissing", new String[] { key }));
}
} else {
Value entryValue = (Value)map.get(key);
if ( !(entryValue instanceof NullValue) ) {
entryDescriptor.validate(entryValue, context);
}
}
}
}
}
}