Coverage Report - org.melati.poem.Setting
 
Classes in this File Line Coverage Branch Coverage Complexity
Setting
91%
71/78
96%
25/26
3
 
 1  
 /*
 2  
  * $Source$
 3  
  * $Revision$
 4  
  *
 5  
  * Copyright (C) 2000 William Chesters
 6  
  *
 7  
  * Part of Melati (http://melati.org), a framework for the rapid
 8  
  * development of clean, maintainable web applications.
 9  
  *
 10  
  * Melati is free software; Permission is granted to copy, distribute
 11  
  * and/or modify this software under the terms either:
 12  
  *
 13  
  * a) the GNU General Public License as published by the Free Software
 14  
  *    Foundation; either version 2 of the License, or (at your option)
 15  
  *    any later version,
 16  
  *
 17  
  *    or
 18  
  *
 19  
  * b) any version of the Melati Software License, as published
 20  
  *    at http://melati.org
 21  
  *
 22  
  * You should have received a copy of the GNU General Public License and
 23  
  * the Melati Software License along with this program;
 24  
  * if not, write to the Free Software Foundation, Inc.,
 25  
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
 26  
  * GNU General Public License and visit http://melati.org to obtain the
 27  
  * Melati Software License.
 28  
  *
 29  
  * Feel free to contact the Developers of Melati (http://melati.org),
 30  
  * if you would like to work out a different arrangement than the options
 31  
  * outlined here.  It is our intention to allow Melati to be used by as
 32  
  * wide an audience as possible.
 33  
  *
 34  
  * This program is distributed in the hope that it will be useful,
 35  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 36  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 37  
  * GNU General Public License for more details.
 38  
  *
 39  
  * Contact details for copyright holder:
 40  
  *
 41  
  *     William Chesters <williamc At paneris.org>
 42  
  *     http://paneris.org/~williamc
 43  
  *     Obrechtstraat 114, 2517VX Den Haag, The Netherlands
 44  
  */
 45  
 
 46  
 package org.melati.poem;
 47  
 
 48  
 import org.melati.poem.generated.SettingBase;
 49  
 
 50  
 /**
 51  
  * A setting, analageous to a Property.
 52  
  * <p>
 53  
  * NOTE While the underlying value is held as a String 
 54  
  * that is converted to any type.
 55  
  * 
 56  
  * <p>
 57  
  * 
 58  
  * Melati POEM generated, modified definition of  
 59  
  * a <code>Persistent</code> <code>Setting</code> object.
 60  
  * 
 61  
  * <p> 
 62  
  * Description: 
 63  
  *   A configurable setting for the application. 
 64  
  * </p>
 65  
  * 
 66  
  * <table> 
 67  
  * <caption>
 68  
  * Field summary for SQL table <code>Setting</code>
 69  
  * </caption>
 70  
  * <tr><th>Name</th><th>Type</th><th>Description</th></tr>
 71  
  * <tr><td> id </td><td> Integer </td><td> The Table Row Object ID </td></tr> 
 72  
  * <tr><td> name </td><td> String </td><td> A code name for this setting 
 73  
  * </td></tr> 
 74  
  * <tr><td> value </td><td> String </td><td> The value of this setting 
 75  
  * </td></tr> 
 76  
  * </table> 
 77  
  * 
 78  
  * See org.melati.poem.prepro.TableDef#generateMainJava 
 79  
  * @author WilliamC@paneris.org
 80  
  */
 81  
 
 82  
 public class Setting extends SettingBase {
 83  
  /**
 84  
   * Constructor 
 85  
   * for a <code>Persistent</code> <code>Setting</code> object.
 86  
   * <p>
 87  
   * Description: 
 88  
   *   A configurable setting for the application. 
 89  
   * </p>
 90  
   * 
 91  
   * See org.melati.poem.prepro.TableDef#generateMainJava 
 92  
   */
 93  36
   public Setting() { }
 94  
 
 95  
   // programmer's domain-specific code here
 96  
 
 97  23
   private FieldAttributes<?> valueAttributes = null;
 98  23
   private Object raw = null;
 99  23
   private Object cooked = null;
 100  
 
 101  
   /**
 102  
    * Constructor with reasonable defaults for a String setting
 103  
    * Use SettingTable.create to persist this.
 104  
    * @param typefactory The type factory integer code
 105  
    * @param name the name of the setting
 106  
    * @param value the string value
 107  
    * @param displayname the name to display
 108  
    * @param description the description to display
 109  
    */
 110  
   public Setting(Integer typefactory, String name, String value,
 111  5
                  String displayname, String description) {
 112  5
     setTypefactory_unsafe(typefactory);
 113  5
     setName_unsafe(name);
 114  5
     setValue_unsafe(value);
 115  5
     setDisplayname_unsafe(displayname);
 116  5
     setDescription_unsafe(description);
 117  5
     setUsereditable_unsafe(Boolean.TRUE);
 118  5
     setNullable_unsafe(Boolean.TRUE);
 119  5
     setSize_unsafe(new Integer(-1));
 120  5
     setWidth_unsafe(new Integer(20));
 121  5
     setHeight_unsafe(new Integer(1));
 122  5
     setPrecision_unsafe(new Integer(22));
 123  5
     setScale_unsafe(new Integer(2));
 124  5
   }
 125  
 
 126  
  /**
 127  
   * Thrown when a {@link Setting} value fails validation.
 128  
   */
 129  
   public static class SettingValidationException extends PoemException {
 130  
     private static final long serialVersionUID = 1L;
 131  
 
 132  
     /** The name of the requested setting. */
 133  
     public String name;
 134  
 
 135  
     /** Constructor. */
 136  
     public SettingValidationException(String name, Exception problem) {
 137  
       super(problem);
 138  
       this.name = name;
 139  
     }
 140  
 
 141  
     /** @return The detail message. */
 142  
     public String getMessage() {
 143  
       return "A problem arose updating the value of the `" + name +
 144  
       "' setting:\n" + subException.getMessage();
 145  
     }
 146  
   }
 147  
 
 148  
   /**
 149  
    * Check that value is of correct type before setting. 
 150  
    * {@inheritDoc}
 151  
    * @see org.melati.poem.generated.SettingBase#setValue(java.lang.String)
 152  
    */
 153  
   public void setValue(String value) {
 154  
     Object rawLocal;
 155  
     try {
 156  4
       rawLocal = getType().rawOfString(value);
 157  1
     } catch (Exception e) {
 158  1
       throw new SettingValidationException(getName_unsafe(), e);
 159  3
     }
 160  
 
 161  3
     super.setValue(value);
 162  3
     this.raw = rawLocal;
 163  3
     cooked = null;
 164  3
   }
 165  
 
 166  
   /**
 167  
    * Set from a raw value; checking that the value is of the correct type first.
 168  
    * @param raw the raw to set
 169  
    */
 170  
   public void setRaw(Object raw) {
 171  
     String string;
 172  
     Object newRaw;
 173  
     try {
 174  31
       string = getType().stringOfRaw(raw);
 175  1
     } catch (Exception e) {
 176  1
       throw new SettingValidationException(getName_unsafe(), e);
 177  30
     }
 178  
     try {
 179  30
       newRaw = getType().rawOfString(string);
 180  2
     } catch (Exception e) {
 181  2
       throw new SettingValidationException(getName_unsafe(), e);
 182  28
     }
 183  28
     super.setValue(newRaw == null ? null : string);
 184  28
     this.raw = newRaw;
 185  28
     cooked = null;
 186  28
   }
 187  
 
 188  
   /**
 189  
    * @return the raw value
 190  
    */
 191  
   public Object getRaw() {
 192  24
     if (raw == null)
 193  
       try {
 194  9
         raw = getType().rawOfString(getValue());
 195  0
       } catch (Exception e) {
 196  0
         throw new SettingValidationException(getName_unsafe(), e);
 197  9
       }
 198  
 
 199  24
     return raw;
 200  
   }
 201  
 
 202  
   /**
 203  
    * @return the cooked, ie typed, Object
 204  
    */
 205  
   public Object getCooked() {
 206  23
     if (cooked == null)
 207  19
       cooked = getType().cookedOfRaw(getRaw());
 208  23
     return cooked;
 209  
   }
 210  
 
 211  
  /**
 212  
   * Thrown when a {@link Setting}'s type does not match the type required. 
 213  
   */
 214  
   public static class 
 215  
       SettingTypeMismatchException extends AppBugPoemException {
 216  
     private static final long serialVersionUID = 1L;
 217  
 
 218  
     /** Name of the setting. */
 219  
     public String name;
 220  
     /** The factory used. */
 221  
     public PoemTypeFactory type;
 222  
     /** Required type. */
 223  
     public String reqType;
 224  
 
 225  
     /** Constructor. */
 226  
     public SettingTypeMismatchException(String name, PoemTypeFactory type,
 227  
                                         String reqType) {
 228  
       this.name = name;
 229  
       this.type = type;
 230  
       this.reqType = reqType;
 231  
     }
 232  
 
 233  
     /** @return The detail message. */
 234  
     public String getMessage() {
 235  
       return "The setting `" + name + "' has type `" + type + "' but " +
 236  
       "the application asked for a value of type " + reqType;
 237  
     }
 238  
   }
 239  
 
 240  
   /**
 241  
    * @return value as an Integer
 242  
    */
 243  
   public Integer getIntegerCooked() {
 244  3
     Object cookedLocal = getCooked();
 245  3
     if (cookedLocal == null && getNullable().booleanValue())
 246  1
       return null;
 247  2
     else if (cookedLocal instanceof Integer)
 248  1
       return (Integer)cookedLocal;
 249  
     else
 250  1
       throw new SettingTypeMismatchException(getName_unsafe(),
 251  1
                                              getTypefactory(), "Integer");
 252  
   }
 253  
 
 254  
   /**
 255  
    * @return value as a String
 256  
    */
 257  
   public String getStringCooked() {
 258  3
     Object cookedLocal = getCooked();
 259  3
     if (cookedLocal == null && getNullable().booleanValue())
 260  1
       return null;
 261  2
     else if (cookedLocal instanceof String)
 262  1
       return (String)cookedLocal;
 263  
     else
 264  1
       throw new SettingTypeMismatchException(getName_unsafe(),
 265  1
                                              getTypefactory(), "String");
 266  
   }
 267  
 
 268  
   /**
 269  
    * @return value as a Boolean
 270  
    */
 271  
   public Boolean getBooleanCooked() {
 272  3
     Object cookedLocal = getCooked();
 273  3
     if (cookedLocal == null && getNullable().booleanValue())
 274  1
       return null;
 275  2
     else if (cookedLocal instanceof Boolean)
 276  1
       return (Boolean)cookedLocal;
 277  
     else
 278  1
       throw new SettingTypeMismatchException(getName_unsafe(),
 279  1
                                              getTypefactory(), "Boolean");
 280  
   }
 281  
 
 282  
   /**
 283  
    * @return the attributes set in this Setting as the attributes for the 
 284  
    * value field
 285  
    */
 286  
   @SuppressWarnings("rawtypes")
 287  
   private FieldAttributes valueFieldAttributes() {
 288  4
     if (valueAttributes == null)
 289  4
       valueAttributes =
 290  4
           fieldAttributesRenamedAs(getSettingTable().getValueColumn());
 291  
 
 292  4
     return valueAttributes;
 293  
   }
 294  
 
 295  
   /**
 296  
    * Override the normal field attributes for the Value field, 
 297  
    * use the attribute values set in this setting.
 298  
    * @see org.melati.poem.generated.SettingBase#getValueField()
 299  
    */
 300  
   @SuppressWarnings({ "rawtypes", "unchecked" })
 301  
   public Field getValueField() {
 302  
     try {
 303  4
       return new Field<String>(getRaw(), valueFieldAttributes());
 304  0
     } catch (AccessPoemException accessException) {
 305  0
       return new Field<Exception>(accessException, valueFieldAttributes());
 306  
     }
 307  
   }
 308  
 
 309  
   /**
 310  
    * Slight overkill, force recreation of value field attributes even 
 311  
    * if it is the value that has been changed.
 312  
    *   
 313  
    * {@inheritDoc}
 314  
    * @see org.melati.poem.ValueInfo#postEdit(boolean)
 315  
    */
 316  
   public void postEdit(boolean creating) {
 317  0
     super.postEdit(creating);
 318  0
     valueAttributes  = null;
 319  0
   }
 320  
   
 321  
 }