1 16 package org.apache.cocoon.woody.formmodel; 17 18 import org.apache.cocoon.woody.Constants; 19 import org.apache.cocoon.woody.FormContext; 20 import org.apache.cocoon.woody.util.I18nMessage; 21 import org.apache.cocoon.woody.validation.ValidationError; 22 import org.apache.cocoon.woody.validation.ValidationErrorAware; 23 import org.apache.cocoon.woody.datatype.SelectionList; 24 import org.apache.cocoon.woody.datatype.Datatype; 25 import org.apache.cocoon.woody.event.DeferredValueChangedEvent; 26 import org.apache.cocoon.woody.event.WidgetEvent; 27 import org.apache.cocoon.woody.event.ValueChangedEvent; 28 import org.apache.cocoon.xml.AttributesImpl; 29 import org.xml.sax.ContentHandler ; 30 import org.xml.sax.SAXException ; 31 32 import java.util.Locale ; 33 34 47 public class Field extends AbstractWidget implements ValidationErrorAware, DataWidget, SelectableWidget { 48 protected SelectionList selectionList; 49 50 protected String enteredValue; 51 protected Object value; 52 53 protected boolean needsParse = true; 56 protected boolean needsValidate = true; 57 private boolean isValidating; 58 protected ValidationError validationError; 59 60 61 public Field(FieldDefinition fieldDefinition) { 62 setDefinition(fieldDefinition); 63 setLocation(fieldDefinition.getLocation()); 64 } 65 66 public final FieldDefinition getFieldDefinition() { 67 return (FieldDefinition)super.definition; 68 } 69 70 public String getId() { 71 return definition.getId(); 72 } 73 74 public Object getValue() { 75 if (this.needsParse) { 77 this.value = null; 79 if (this.enteredValue != null) { 80 this.value = getDatatype().convertFromString(this.enteredValue, getForm().getLocale()); 82 if (this.value != null) { this.needsParse = false; 84 this.needsValidate = true; 85 } else { this.validationError = new ValidationError(new I18nMessage( 87 "datatype.conversion-failed", 88 new String [] {"datatype." + getDatatype().getDescriptiveName()}, 89 new boolean[] { true }, 90 Constants.I18N_CATALOGUE 91 )); 92 this.needsValidate = false; 94 } 95 } else { 96 this.needsParse = false; 97 this.needsValidate = true; 98 } 99 } 100 101 if (isValidating) { 104 return value; 105 } 106 107 if (this.needsValidate) { 109 isValidating = true; 110 try { 111 if (super.validate(null)) { 112 if (this.value != null) { 114 this.validationError = getDatatype().validate(value, new ExpressionContextImpl(this)); 115 } else { if (getFieldDefinition().isRequired()) { 117 this.validationError = new ValidationError(new I18nMessage("general.field-required", Constants.I18N_CATALOGUE)); 118 } 119 } 120 } 121 this.needsValidate = false; 122 } finally { 123 isValidating = false; 124 } 125 } 126 return this.validationError == null ? this.value : null; 127 } 128 129 public void setValue(Object newValue) { 130 if (newValue != null && !getDatatype().getTypeClass().isAssignableFrom(newValue.getClass())) { 131 throw new RuntimeException ("Incorrect value type for \"" + getFullyQualifiedId() + 132 "\" (expected " + getDatatype().getTypeClass() + 133 ", got " + newValue.getClass() + "."); 134 } 135 Object oldValue = this.value; 136 boolean changed = ! (oldValue == null ? "" : oldValue).equals(newValue == null ? "" : newValue); 137 if (changed || newValue == null) { 140 this.value = newValue; 141 this.needsParse = false; 142 this.validationError = null; 143 this.needsValidate = true; 145 if (newValue != null) { 146 this.enteredValue = getDatatype().convertToString(newValue, getForm().getLocale()); 147 } else { 148 this.enteredValue = null; 149 } 150 if (changed) { 151 getForm().addWidgetEvent(new ValueChangedEvent(this, oldValue, newValue)); 152 } 153 } 154 } 155 156 public void readFromRequest(FormContext formContext) { 157 String newEnteredValue = formContext.getRequest().getParameter(getFullyQualifiedId()); 158 readFromRequest(newEnteredValue); 159 } 160 161 protected void readFromRequest(String newEnteredValue) { 162 if (newEnteredValue != null) { 164 newEnteredValue = newEnteredValue.trim(); 166 if (newEnteredValue.length() == 0) { 167 newEnteredValue = null; 168 } 169 } 170 171 if (!(newEnteredValue == null ? "" : newEnteredValue).equals((enteredValue == null ? "" : enteredValue))) { 174 getForm().addWidgetEvent(new DeferredValueChangedEvent(this, value)); 175 enteredValue = newEnteredValue; 176 validationError = null; 177 value = null; 178 needsParse = true; 179 } 180 181 this.needsValidate = true; 183 } 184 185 public boolean validate(FormContext formContext) { 186 getValue(); 188 return this.validationError == null; 189 } 190 191 195 public ValidationError getValidationError() { 196 return validationError; 197 } 198 199 205 public void setValidationError(ValidationError error) { 206 this.validationError = error; 207 } 208 209 public boolean isRequired() { 210 return getFieldDefinition().isRequired(); 211 } 212 213 214 private static final String FIELD_EL = "field"; 215 private static final String VALUE_EL = "value"; 216 private static final String VALIDATION_MSG_EL = "validation-message"; 217 218 public void generateSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException { 219 AttributesImpl fieldAttrs = new AttributesImpl(); 220 fieldAttrs.addCDATAAttribute("id", getFullyQualifiedId()); 221 fieldAttrs.addCDATAAttribute("required", String.valueOf(isRequired())); 222 contentHandler.startElement(Constants.WI_NS, FIELD_EL, Constants.WI_PREFIX_COLON + FIELD_EL, fieldAttrs); 223 224 if (enteredValue != null || value != null) { 225 contentHandler.startElement(Constants.WI_NS, VALUE_EL, Constants.WI_PREFIX_COLON + VALUE_EL, Constants.EMPTY_ATTRS); 226 String stringValue; 227 if (value != null) { 228 stringValue = getDatatype().convertToString(value, locale); 229 } else { 230 stringValue = enteredValue; 231 } 232 contentHandler.characters(stringValue.toCharArray(), 0, stringValue.length()); 233 contentHandler.endElement(Constants.WI_NS, VALUE_EL, Constants.WI_PREFIX_COLON + VALUE_EL); 234 } 235 236 if (validationError != null) { 238 contentHandler.startElement(Constants.WI_NS, VALIDATION_MSG_EL, Constants.WI_PREFIX_COLON + VALIDATION_MSG_EL, Constants.EMPTY_ATTRS); 239 validationError.generateSaxFragment(contentHandler); 240 contentHandler.endElement(Constants.WI_NS, VALIDATION_MSG_EL, Constants.WI_PREFIX_COLON + VALIDATION_MSG_EL); 241 } 242 243 definition.generateDisplayData(contentHandler); 245 246 if (selectionList != null) { 248 selectionList.generateSaxFragment(contentHandler, locale); 249 } else if (getFieldDefinition().getSelectionList() != null) { 250 getFieldDefinition().getSelectionList().generateSaxFragment(contentHandler, locale); 251 } 252 contentHandler.endElement(Constants.WI_NS, FIELD_EL, Constants.WI_PREFIX_COLON + FIELD_EL); 253 } 254 255 public void generateLabel(ContentHandler contentHandler) throws SAXException { 256 definition.generateLabel(contentHandler); 257 } 258 259 263 public void setSelectionList(SelectionList selectionList) { 264 if (selectionList != null && 265 selectionList.getDatatype() != null && 266 selectionList.getDatatype() != getDatatype()) { 267 throw new RuntimeException ("Tried to assign a SelectionList that is not associated with this widget's datatype."); 268 } 269 this.selectionList = selectionList; 270 } 271 272 281 public void setSelectionList(String uri) { 282 setSelectionList(getFieldDefinition().buildSelectionList(uri)); 283 } 284 285 301 public void setSelectionList(Object model, String valuePath, String labelPath) { 302 setSelectionList(getFieldDefinition().buildSelectionListFromModel(model, valuePath, labelPath)); 303 } 304 305 public Datatype getDatatype() { 306 return getFieldDefinition().getDatatype(); 307 } 308 309 public void broadcastEvent(WidgetEvent event) { 310 getFieldDefinition().fireValueChangedEvent((ValueChangedEvent)event); 311 } 312 } 313 | Popular Tags |