00001
00002
00003
00004 package edu.tum.cs.inference;
00005
00006 import java.lang.reflect.Method;
00007 import java.util.Collection;
00008 import java.util.HashMap;
00009 import java.util.HashSet;
00010 import java.util.Map;
00011 import java.util.Vector;
00012 import java.util.Map.Entry;
00013
00014 import edu.tum.cs.util.StringTool;
00015
00016 public class ParameterHandler {
00020 protected java.util.HashMap<String, ParameterMapping> mappings;
00021 protected Object owner;
00022 protected Vector<ParameterHandler> subhandlers;
00023 protected Vector<ParameterHandler> parenthandlers;
00024 protected Map<String,Object> submittedParams = null;
00025 protected HashSet<String> unhandledParams = new HashSet<String>();
00026
00027 public ParameterHandler(IParameterHandler owner) {
00028 mappings = new HashMap<String, ParameterMapping>();
00029 subhandlers = new Vector<ParameterHandler>();
00030 parenthandlers = new Vector<ParameterHandler>();
00031 this.owner = owner;
00032 }
00033
00040 public void add(String paramName, String setterMethodName) throws Exception {
00041 for(Method m : owner.getClass().getMethods()) {
00042 if(m.getName().equals(setterMethodName)) {
00043 Class<?>[] paramTypes = m.getParameterTypes();
00044 if(paramTypes.length != 1)
00045 continue;
00046 mappings.put(paramName, new ParameterMapping(m));
00047 return;
00048 }
00049 }
00050 throw new Exception("Could not find an appropriate setter method with 1 parameter in class " + owner.getClass().getName());
00051 }
00052
00053 public void addSubhandler(ParameterHandler h) throws Exception {
00054 if(h == null)
00055 throw new Exception("Subhandler cannot be null");
00056 subhandlers.add(h);
00057 h.parenthandlers.add(this);
00058
00059
00060 if(submittedParams != null)
00061 h.handle(submittedParams, false);
00062 }
00063
00064 public void addSubhandler(IParameterHandler h) throws Exception {
00065 addSubhandler(h.getParameterHandler());
00066 }
00067
00074 public void handle(Map<String, Object> paramMapping, boolean exceptionIfUnhandledParam) throws Exception {
00075 submittedParams = paramMapping;
00076 for(Entry<String,Object> param : paramMapping.entrySet()) {
00077 handle(param.getKey(), param.getValue());
00078 }
00079 if(exceptionIfUnhandledParam && !unhandledParams.isEmpty())
00080 throw new Exception("Parameters " + StringTool.join(", ", unhandledParams) + " unhandled! Known parameters: " + this.getHandledParameters().toString());
00081 }
00082
00083 public Collection<String> getUnhandledParams() {
00084 return unhandledParams;
00085 }
00086
00087 protected boolean handle(String paramName, Object value) throws Exception {
00088
00089 ParameterMapping m = mappings.get(paramName);
00090 boolean handled = false;
00091 if(m != null) {
00092 m.apply(value);
00093 handled = true;
00094 }
00095
00096 for(ParameterHandler h : subhandlers)
00097 if(h.handle(paramName, value))
00098 handled = true;
00099
00100 if(handled)
00101 onHandled(paramName);
00102
00103 else
00104 unhandledParams.add(paramName);
00105 return handled;
00106 }
00107
00108 protected void onHandled(String paramName) {
00109 if(unhandledParams.contains(paramName))
00110 unhandledParams.remove(paramName);
00111
00112 for(ParameterHandler h : this.parenthandlers)
00113 h.onHandled(paramName);
00114 }
00115
00120 public Vector<String> getHandledParameters() {
00121 Vector<String> ret = new Vector<String>();
00122 getHandledParameters(ret);
00123 return ret;
00124 }
00125
00126 protected void getHandledParameters(Vector<String> ret) {
00127 for(String param : mappings.keySet())
00128 ret.add(param);
00129 for(ParameterHandler h : subhandlers)
00130 h.getHandledParameters(ret);
00131 }
00132
00133 protected class ParameterMapping {
00134 protected Method setterMethod;
00135
00136 public ParameterMapping(Method setterMethod) {
00137 this.setterMethod = setterMethod;
00138 }
00139
00140 public void apply(Object value) throws Exception {
00141 Class<?> paramType = setterMethod.getParameterTypes()[0];
00142 if(value instanceof String) {
00143 String strValue = (String)value;
00144 if(paramType == Double.class || paramType == double.class) {
00145 setterMethod.invoke(owner, Double.parseDouble(strValue));
00146 return;
00147 }
00148 if(paramType == Integer.class || paramType == int.class) {
00149 setterMethod.invoke(owner, Integer.parseInt(strValue));
00150 return;
00151 }
00152 if(paramType == Boolean.class || paramType == boolean.class) {
00153 setterMethod.invoke(owner, Boolean.parseBoolean(strValue));
00154 return;
00155 }
00156 if(paramType == String.class) {
00157 setterMethod.invoke(owner, strValue);
00158 return;
00159 }
00160 throw new Exception("Don't know how to handle setter argument of type " + paramType.getCanonicalName() + " for " + setterMethod.getName() + "; allowed types are: Double, Integer, String, Boolean");
00161 }
00162 else
00163 setterMethod.invoke(owner, value);
00164 }
00165 }
00166 }