1 16 package org.directwebremoting.convert; 17 18 import java.util.ArrayList ; 19 import java.util.HashMap ; 20 import java.util.Iterator ; 21 import java.util.List ; 22 import java.util.Map ; 23 import java.util.StringTokenizer ; 24 import java.util.TreeMap ; 25 26 import org.directwebremoting.dwrp.ParseUtil; 27 import org.directwebremoting.dwrp.ProtocolConstants; 28 import org.directwebremoting.dwrp.ObjectOutboundVariable; 29 import org.directwebremoting.extend.ConverterManager; 30 import org.directwebremoting.extend.InboundContext; 31 import org.directwebremoting.extend.InboundVariable; 32 import org.directwebremoting.extend.MarshallException; 33 import org.directwebremoting.extend.NamedConverter; 34 import org.directwebremoting.extend.OutboundContext; 35 import org.directwebremoting.extend.OutboundVariable; 36 import org.directwebremoting.extend.Property; 37 import org.directwebremoting.extend.TypeHintContext; 38 import org.directwebremoting.util.LocalUtil; 39 import org.directwebremoting.util.Logger; 40 import org.directwebremoting.util.Messages; 41 42 48 public abstract class BasicObjectConverter extends BaseV20Converter implements NamedConverter 49 { 50 53 public Object convertInbound(Class paramType, InboundVariable iv, InboundContext inctx) throws MarshallException 54 { 55 String value = iv.getValue(); 56 57 if (value.trim().equals(ProtocolConstants.INBOUND_NULL)) 59 { 60 return null; 61 } 62 63 if (!value.startsWith(ProtocolConstants.INBOUND_MAP_START)) 64 { 65 throw new MarshallException(paramType, Messages.getString("BeanConverter.FormatError", ProtocolConstants.INBOUND_MAP_START)); 66 } 67 68 if (!value.endsWith(ProtocolConstants.INBOUND_MAP_END)) 69 { 70 throw new MarshallException(paramType, Messages.getString("BeanConverter.FormatError", ProtocolConstants.INBOUND_MAP_START)); 71 } 72 73 value = value.substring(1, value.length() - 1); 74 75 try 76 { 77 Object bean; 78 if (instanceType != null) 79 { 80 bean = instanceType.newInstance(); 81 } 82 else 83 { 84 bean = paramType.newInstance(); 85 } 86 87 if (instanceType != null) 90 { 91 inctx.addConverted(iv, instanceType, bean); 92 } 93 else 94 { 95 inctx.addConverted(iv, paramType, bean); 96 } 97 98 Map properties = getPropertyMapFromObject(bean, false, true); 99 100 Map tokens = extractInboundTokens(paramType, value); 102 for (Iterator it = tokens.entrySet().iterator(); it.hasNext();) 103 { 104 Map.Entry entry = (Map.Entry ) it.next(); 105 String key = (String ) entry.getKey(); 106 String val = (String ) entry.getValue(); 107 108 Property property = (Property) properties.get(key); 109 if (property == null) 110 { 111 log.warn("Missing java bean property to match javascript property: " + key + ". For causes see debug level logs:"); 112 113 log.debug("- The javascript may be refer to a property that does not exist"); 114 log.debug("- You may be missing the correct setter: set" + Character.toTitleCase(key.charAt(0)) + key.substring(1) + "()"); 115 log.debug("- The property may be excluded using include or exclude rules."); 116 117 StringBuffer all = new StringBuffer (); 118 for (Iterator pit = properties.keySet().iterator(); pit.hasNext();) 119 { 120 all.append(pit.next()); 121 if (pit.hasNext()) 122 { 123 all.append(','); 124 } 125 } 126 log.debug("Fields exist for (" + all + ")."); 127 continue; 128 } 129 130 Class propType = property.getPropertyType(); 131 132 String [] split = ParseUtil.splitInbound(val); 133 String splitValue = split[LocalUtil.INBOUND_INDEX_VALUE]; 134 String splitType = split[LocalUtil.INBOUND_INDEX_TYPE]; 135 136 InboundVariable nested = new InboundVariable(iv.getLookup(), null, splitType, splitValue); 137 TypeHintContext incc = createTypeHintContext(inctx, property); 138 139 Object output = converterManager.convertInbound(propType, nested, inctx, incc); 140 property.setValue(bean, output); 141 } 142 143 return bean; 144 } 145 catch (MarshallException ex) 146 { 147 throw ex; 148 } 149 catch (Exception ex) 150 { 151 throw new MarshallException(paramType, ex); 152 } 153 } 154 155 165 protected abstract TypeHintContext createTypeHintContext(InboundContext inctx, Property property); 166 167 170 public OutboundVariable convertOutbound(Object data, OutboundContext outctx) throws MarshallException 171 { 172 Map ovs = new TreeMap (); 174 175 ObjectOutboundVariable ov = new ObjectOutboundVariable(outctx); 177 outctx.put(data, ov); 178 179 try 180 { 181 Map properties = getPropertyMapFromObject(data, true, false); 182 for (Iterator it = properties.entrySet().iterator(); it.hasNext();) 183 { 184 Map.Entry entry = (Map.Entry ) it.next(); 185 String name = (String ) entry.getKey(); 186 Property property = (Property) entry.getValue(); 187 188 Object value = property.getValue(data); 189 OutboundVariable nested = getConverterManager().convertOutbound(value, outctx); 190 191 ovs.put(name, nested); 192 } 193 } 194 catch (MarshallException ex) 195 { 196 throw ex; 197 } 198 catch (Exception ex) 199 { 200 throw new MarshallException(data.getClass(), ex); 201 } 202 203 ov.init(ovs, getJavascript()); 204 205 return ov; 206 } 207 208 212 public void setExclude(String excludes) 213 { 214 if (inclusions != null) 215 { 216 throw new IllegalArgumentException (Messages.getString("BeanConverter.OnlyIncludeOrExclude")); 217 } 218 219 exclusions = new ArrayList (); 220 221 String toSplit = LocalUtil.replace(excludes, ",", " "); 222 StringTokenizer st = new StringTokenizer (toSplit); 223 while (st.hasMoreTokens()) 224 { 225 String rule = st.nextToken(); 226 if (rule.startsWith("get")) 227 { 228 log.warn("Exclusions are based on property names and not method names. '" + rule + "' starts with 'get' so it looks like a method name and not a property name."); 229 } 230 231 exclusions.add(rule); 232 } 233 } 234 235 239 public void setInclude(String includes) 240 { 241 if (exclusions != null) 242 { 243 throw new IllegalArgumentException (Messages.getString("BeanConverter.OnlyIncludeOrExclude")); 244 } 245 246 inclusions = new ArrayList (); 247 248 String toSplit = LocalUtil.replace(includes, ",", " "); 249 StringTokenizer st = new StringTokenizer (toSplit); 250 while (st.hasMoreTokens()) 251 { 252 String rule = st.nextToken(); 253 if (rule.startsWith("get")) 254 { 255 log.warn("Inclusions are based on property names and not method names. '" + rule + "' starts with 'get' so it looks like a method name and not a property name."); 256 } 257 258 inclusions.add(rule); 259 } 260 } 261 262 266 public void setImplementation(String name) throws ClassNotFoundException  267 { 268 setInstanceType(LocalUtil.classForName(name)); 269 } 270 271 274 public Class getInstanceType() 275 { 276 return instanceType; 277 } 278 279 282 public void setInstanceType(Class instanceType) 283 { 284 this.instanceType = instanceType; 285 } 286 287 290 public void setConverterManager(ConverterManager converterManager) 291 { 292 this.converterManager = converterManager; 293 } 294 295 299 public ConverterManager getConverterManager() 300 { 301 return converterManager; 302 } 303 304 309 protected boolean isAllowedByIncludeExcludeRules(String property) 310 { 311 if (exclusions != null) 312 { 313 for (Iterator it = exclusions.iterator(); it.hasNext();) 315 { 316 String test = (String ) it.next(); 317 if (property.equals(test)) 318 { 319 return false; 320 } 321 } 322 323 } 328 329 if (inclusions != null) 330 { 331 for (Iterator it = inclusions.iterator(); it.hasNext();) 333 { 334 String test = (String ) it.next(); 335 if (property.equals(test)) 336 { 337 return true; 338 } 339 } 340 341 return false; 344 } 345 346 return true; 348 } 349 350 357 protected Map extractInboundTokens(Class paramType, String value) throws MarshallException 358 { 359 Map tokens = new HashMap (); 360 StringTokenizer st = new StringTokenizer (value, ProtocolConstants.INBOUND_MAP_SEPARATOR); 361 int size = st.countTokens(); 362 363 for (int i = 0; i < size; i++) 364 { 365 String token = st.nextToken(); 366 if (token.trim().length() == 0) 367 { 368 continue; 369 } 370 371 int colonpos = token.indexOf(ProtocolConstants.INBOUND_MAP_ENTRY); 372 if (colonpos == -1) 373 { 374 throw new MarshallException(paramType, Messages.getString("BeanConverter.MissingSeparator", ProtocolConstants.INBOUND_MAP_ENTRY, token)); 375 } 376 377 String key = token.substring(0, colonpos).trim(); 378 String val = token.substring(colonpos + 1).trim(); 379 tokens.put(key, val); 380 } 381 382 return tokens; 383 } 384 385 388 public String getJavascript() 389 { 390 return javascript; 391 } 392 393 396 public void setJavascript(String javascript) 397 { 398 this.javascript = javascript; 399 } 400 401 404 protected String javascript; 405 406 409 protected List exclusions = null; 410 411 414 protected List inclusions = null; 415 416 419 protected Class instanceType = null; 420 421 424 protected ConverterManager converterManager = null; 425 426 429 private static final Logger log = Logger.getLogger(BasicObjectConverter.class); 430 } 431
| Popular Tags
|