View Javadoc
1 package org.apache.turbine.services.intake.model; 2 3 /* ==================================================================== 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2001 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, 22 * if any, must include the following acknowledgment: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.apache.org/)." 25 * Alternately, this acknowledgment may appear in the software itself, 26 * if and wherever such third-party acknowledgments normally appear. 27 * 28 * 4. The names "Apache" and "Apache Software Foundation" and 29 * "Apache Turbine" must not be used to endorse or promote products 30 * derived from this software without prior written permission. For 31 * written permission, please contact apache@apache.org. 32 * 33 * 5. Products derived from this software may not be called "Apache", 34 * "Apache Turbine", nor may "Apache" appear in their name, without 35 * prior written permission of the Apache Software Foundation. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.apache.org/>;. 55 */ 56 57 import java.lang.reflect.Method; 58 import org.apache.turbine.om.Retrievable; 59 import org.apache.turbine.services.intake.TurbineIntake; 60 import org.apache.turbine.services.intake.validator.InitableByConstraintMap; 61 import org.apache.turbine.services.intake.validator.ValidationException; 62 import org.apache.turbine.services.intake.validator.Validator; 63 import org.apache.turbine.services.intake.xmlmodel.Rule; 64 import org.apache.turbine.services.intake.xmlmodel.XmlField; 65 import org.apache.turbine.util.Log; 66 import org.apache.turbine.util.ParameterParser; 67 import org.apache.turbine.util.RunData; 68 import org.apache.turbine.util.TurbineException; 69 70 /*** 71 * Base class for Intake generated input processing classes. 72 * 73 * @author <a href="mailto:jmcnally@collab.net>;John McNally</a> 74 * @version $Id: Field.java,v 1.3 2002/07/11 16:53:27 mpoeschl Exp $ 75 */ 76 public abstract class Field 77 { 78 private static final String EMPTY = ""; 79 private static final String VALUE_IF_ABSENT_KEY = "_vifa_"; 80 81 // the following are set from the xml file and are permanent (final) 82 protected final String name; 83 protected final String key; 84 protected String displayName; 85 protected final String mapToObject; 86 protected Validator validator; 87 protected final Method getter; 88 protected final Method setter; 89 protected final String ifRequiredMessage; 90 protected final boolean isMultiValued; 91 protected final Group group; 92 protected boolean alwaysRequired; 93 protected Object onError; 94 protected Object defaultValue; 95 96 // these are reset when the Field is returned to the pool 97 protected boolean set_flag; 98 protected boolean valid_flag; 99 protected boolean required; 100 protected boolean initialized; 101 protected String message; 102 protected Retrievable retrievable; 103 104 private Object validValue; 105 private Object testValue; 106 private Object[] valArray; // for reflection 107 108 /*** The object containing the request data */ 109 protected RunData data; 110 111 /*** 112 * Constructs a field based on data in the xml specification 113 * and assigns it to a Group. 114 * 115 * @param field a <code>XmlField</code> value 116 * @param group a <code>Group</code> value 117 * @exception Exception if an error occurs 118 */ 119 public Field(XmlField field, Group group) 120 throws Exception 121 { 122 this.group = group; 123 key = field.getKey(); 124 name = field.getName(); 125 displayName = field.getDisplayName(); 126 isMultiValued = field.isMultiValued(); 127 setDefaultValue(field.getDefaultValue()); 128 String className = field.getValidator(); 129 if ( className == null && field.getRules().size() > 0 ) 130 { 131 className = getDefaultValidator(); 132 } 133 else if ( className != null && className.indexOf('.') == -1 ) 134 { 135 className = "org.apache.turbine.services.intake.validator." 136 + className; 137 } 138 139 if ( className != null ) 140 { 141 validator = (Validator)Class.forName(className).newInstance(); 142 // this should always be true for now 143 // (until bean property initialization is implemented) 144 if ( validator instanceof InitableByConstraintMap ) 145 { 146 ((InitableByConstraintMap)validator).init(field.getRuleMap()); 147 } 148 149 } 150 151 // field may have been declared as always required in the xml spec 152 Rule reqRule = (Rule)field.getRuleMap().get("required"); 153 if ( reqRule != null ) 154 { 155 alwaysRequired = new Boolean(reqRule.getValue()).booleanValue(); 156 } 157 158 mapToObject = field.getMapToObject(); 159 String propName = field.getMapToProperty(); 160 Method tmpGetter = null; 161 Method tmpSetter = null; 162 if ( mapToObject != null && mapToObject.length() != 0) 163 { 164 tmpGetter = TurbineIntake.getFieldGetter(mapToObject, propName); 165 tmpSetter = TurbineIntake.getFieldSetter(mapToObject, propName); 166 } 167 getter = tmpGetter; 168 setter = tmpSetter; 169 ifRequiredMessage = field.getIfRequiredMessage(); 170 171 valArray = new Object[1]; 172 } 173 174 175 /*** 176 * Method called when this field (the group it belongs to) is 177 * pulled from the pool. The request data is searched to determine 178 * if a value has been supplied for this field. if so, the value 179 * is validated. 180 * 181 * @param data a <code>RunData</code> value 182 * @return a <code>Field</code> value 183 * @exception TurbineException if an error occurs 184 */ 185 public Field init(RunData data) 186 throws TurbineException 187 { 188 this.data = data; 189 valid_flag = true; 190 191 ParameterParser pp = data.getParameters(); 192 if ( pp.containsKey(getKey()) && pp.getString(getKey()) != null ) 193 { 194 set_flag = true; 195 if (validate(pp)) 196 { 197 // iv.reconcileNotValid(pp); 198 } 199 } 200 else if ( pp.containsKey(getValueIfAbsent()) && 201 pp.getString(getValueIfAbsent()) != null ) 202 { 203 pp.add(getKey(), pp.getString(getValueIfAbsent())); 204 set_flag = true; 205 validate(pp); 206 } 207 208 initialized = true; 209 return this; 210 } 211 212 /*** 213 * Method called when this field or the group it belongs to is 214 * pulled from the pool. The retrievable object can provide 215 * a default value for the field, or using setProperty the field's 216 * value can be transferred to the retrievable. 217 * 218 * @param obj a <code>Retrievable</code> value 219 * @return a <code>Field</code> value 220 */ 221 public Field init(Retrievable obj) 222 { 223 if ( !initialized ) 224 { 225 valid_flag = true; 226 } 227 retrievable = obj; 228 return this; 229 } 230 231 232 protected String getDefaultValidator() 233 { 234 return "org.apache.turbine.services.intake.validator.DefaultValidator"; 235 } 236 237 public Validator getValidator() 238 { 239 return validator; 240 } 241 242 /*** 243 * Flag to determine whether the field has been declared as required. 244 * @return value of required. 245 */ 246 public boolean isRequired() 247 { 248 return alwaysRequired || required; 249 } 250 251 /*** 252 * Set whether this field is required to have a value. 253 * @param v Value to assign to required. 254 */ 255 public void setRequired(boolean v) 256 { 257 setRequired(v, ifRequiredMessage); 258 } 259 260 /*** 261 * Set the value of required. 262 * 263 * @param v a <code>boolean</code> value 264 * @param message, override the value from intake.xml 265 */ 266 public void setRequired(boolean v, String message) 267 { 268 this.required = v; 269 if (v && !set_flag) 270 { 271 valid_flag=false; 272 this.message = message; 273 } 274 } 275 276 /*** 277 * Removes references to this group and its fields from the 278 * query parameters 279 */ 280 public void removeFromRequest() 281 { 282 data.getParameters().remove(getKey()); 283 } 284 285 286 /*** 287 * Disposes the object after use. The method is called 288 * when the Group is returned to its pool. 289 * if overridden, super.dispose() should be called. 290 */ 291 public void dispose() 292 { 293 data = null; 294 initialized = false; 295 set_flag = false; 296 valid_flag = false; 297 required = false; 298 message = null; 299 retrievable = null; 300 301 validValue = null; 302 testValue = null; 303 valArray[0] = null; 304 } 305 306 /*** 307 * Get the key used to identify the field. 308 * @return the query data key. 309 */ 310 public String getKey() 311 { 312 if ( group == null ) 313 { 314 return key; 315 } 316 else 317 { 318 return group.getObjectKey() + key; 319 } 320 } 321 322 /*** 323 * Use in a hidden field assign a default value in the event the 324 * field is absent from the query parameters. Used to track checkboxes, 325 * since they only show up if checked. 326 */ 327 public String getValueIfAbsent() 328 { 329 return getKey() + VALUE_IF_ABSENT_KEY; 330 } 331 332 /*** 333 * Flag set to true, if the test value met the constraints. 334 * Is also true, in the case the test value was not set, 335 * unless this field has been marked as required. 336 * 337 * @return a <code>boolean</code> value 338 */ 339 public boolean isValid() 340 { 341 return valid_flag; 342 } 343 344 /*** 345 * Flag set to true, if the test value has been set to 346 * anything other than an empty value. 347 * 348 * @return a <code>boolean</code> value 349 */ 350 public boolean isSet() 351 { 352 return set_flag; 353 } 354 355 /*** 356 * Get the display name of the field. Useful for building 357 * data entry forms. Returns name of field if no display 358 * name has been assigned to the field by xml input file 359 * 360 * @return a <code>String</code> value 361 */ 362 public String getDisplayName() 363 { 364 return (displayName == null) ? name : displayName; 365 } 366 367 /*** 368 * Set the display name of the field. Display names are 369 * used in building data entry forms and serve as a 370 * user friendly description of the data contained in 371 * the field. 372 */ 373 public void setDisplayName(String newDisplayName) 374 { 375 displayName = newDisplayName; 376 } 377 378 /*** 379 * Get any error message resulting from invalid input. 380 * 381 * @return a <code>String</code> value 382 */ 383 public String getMessage() 384 { 385 if ( message == null ) 386 { 387 return EMPTY; 388 } 389 return message; 390 } 391 392 /*** 393 * Sets an error message. The field is also marked as invalid. 394 */ 395 public void setMessage(String message) 396 { 397 this.message = message; 398 valid_flag = false; 399 } 400 401 /*** 402 * Compares request data with constraints and sets the valid flag. 403 */ 404 protected boolean validate(ParameterParser pp) 405 // throws TurbineException 406 { 407 if ( isMultiValued ) 408 { 409 String[] ss = pp.getStrings(getKey()); 410 // this definition of not set might need refined. But 411 // not sure the situation will arise. 412 if ( ss.length == 0 || (ss.length == 1 && ss[0].length() == 0) ) 413 { 414 set_flag = false; 415 } 416 417 if ( validator != null ) 418 { 419 for (int i=0; i<ss.length; i++) 420 { 421 try 422 { 423 validator.assertValidity(ss[i]); 424 } 425 catch (ValidationException ve) 426 { 427 setMessage(ve.getMessage()); 428 } 429 } 430 } 431 432 if ( set_flag && valid_flag ) 433 { 434 doSetValue(pp); 435 } 436 437 } 438 else 439 { 440 String s = pp.getString(getKey()); 441 if ( s.length() == 0 ) 442 { 443 set_flag = false; 444 } 445 446 if ( validator != null ) 447 { 448 try 449 { 450 validator.assertValidity(s); 451 452 if ( set_flag ) 453 { 454 doSetValue(pp); 455 } 456 } 457 catch (ValidationException ve) 458 { 459 setMessage(ve.getMessage()); 460 } 461 } 462 else if ( set_flag ) 463 { 464 doSetValue(pp); 465 } 466 } 467 468 return valid_flag; 469 } 470 471 /*** 472 * Compares request data with constraints and sets the valid flag. 473 * To be implemented in subclasses 474 */ 475 protected abstract void doSetValue(ParameterParser pp); 476 477 /*** 478 * Set the default Value 479 */ 480 protected abstract void setDefaultValue(String prop); 481 482 483 /*** 484 * Set the value used as a default, in the event the field 485 * has not been set yet. 486 * 487 * @param obj an <code>Object</code> value 488 */ 489 void setInitialValue(Object obj) 490 { 491 validValue = obj; 492 } 493 494 /*** 495 * Get the value used as a default. If the initial value has 496 * not been set and a <code>Retrievable</code> object has 497 * been associated with this field, the objects property will 498 * be used as the initial value. 499 * 500 * @return an <code>Object</code> value 501 * @exception Exception if an error occurs 502 */ 503 public Object getInitialValue() 504 throws Exception 505 { 506 if ( validValue == null) 507 { 508 if ( retrievable != null ) 509 { 510 getProperty(retrievable); 511 } 512 else 513 { 514 getDefault(); 515 } 516 } 517 return validValue; 518 } 519 520 /*** 521 * Set the value input by a user that will be validated. 522 * 523 * @param obj an <code>Object</code> value 524 */ 525 void setTestValue(Object obj) 526 { 527 testValue = obj; 528 } 529 530 /*** 531 * Get the value input by a user that will be validated. 532 * 533 * @return an <code>Object</code> value 534 */ 535 public Object getTestValue() 536 { 537 return testValue; 538 } 539 540 /*** 541 * Get the value of the field. if a test value has been set, it 542 * will be returned as is, unless it is so badly formed that the 543 * validation could not parse it. In most cases the test value 544 * is returned even though invalid, so that it can be returned to 545 * the user to make modifications. if the test value is not set 546 * the initial value is returned. 547 * 548 * @return an <code>Object</code> value 549 */ 550 public Object getValue() 551 { 552 Object val = null; 553 try 554 { 555 val = getInitialValue(); 556 } 557 catch (Exception e) 558 { 559 Log.error(e); 560 } 561 562 if ( getTestValue() != null ) 563 { 564 val = getTestValue(); 565 } 566 567 if ( val == null ) 568 { 569 val = onError; 570 } 571 return val; 572 } 573 574 /*** 575 * Calls toString() on the object returned by getValue(), 576 * unless null; and then it returns "", the empty String. 577 * 578 * @return a <code>String</code> value 579 */ 580 public String toString() 581 { 582 if ( getValue() != null ) 583 { 584 return getValue().toString(); 585 } 586 else 587 { 588 return EMPTY; 589 } 590 } 591 592 /*** 593 * Loads the valid value from a bean 594 */ 595 public void getProperty(Object obj) 596 throws Exception 597 { 598 validValue = getter.invoke(obj, null); 599 } 600 601 /*** 602 * Loads the default value from the object 603 */ 604 605 public void getDefault() 606 { 607 validValue = getDefaultValue(); 608 } 609 610 /*** 611 * Calls a setter method on obj, if this field has been set. 612 * @exception throws a TurbineException if called and the input 613 * was not valid. 614 */ 615 public void setProperty(Object obj) 616 // public void setProperty($appData.BasePackage$field.MapToObject obj) 617 throws TurbineException 618 { 619 if (!isValid()) 620 { 621 throw new TurbineException( 622 "Attempted to assign an invalid input."); 623 } 624 if (isSet()) 625 { 626 try 627 { 628 valArray[0] = getTestValue(); 629 setter.invoke(obj, valArray); 630 } 631 catch ( Exception e) 632 { 633 throw new TurbineException("An exception prevented the" + 634 " setting property "+name+" of " + obj + " to " + 635 valArray[0], e); 636 } 637 } 638 } 639 640 /*** 641 * Get the default Value 642 */ 643 public Object getDefaultValue() 644 { 645 return defaultValue; 646 } 647 }

This page was automatically generated by Maven