001: /**
002: * Copyright 2006 Webmedia Group Ltd.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: **/package org.araneaframework.uilib.form;
016:
017: import java.util.Collections;
018: import java.util.HashMap;
019: import java.util.HashSet;
020: import java.util.Iterator;
021: import java.util.Map;
022: import java.util.Set;
023: import org.araneaframework.Environment;
024: import org.araneaframework.core.Assert;
025: import org.araneaframework.core.BaseApplicationWidget;
026: import org.araneaframework.core.util.ExceptionUtil;
027: import org.araneaframework.framework.MessageContext;
028: import org.araneaframework.uilib.form.visitor.FormElementVisitor;
029: import org.araneaframework.uilib.util.ConfigurationContextUtil;
030: import org.araneaframework.uilib.util.UilibEnvironmentUtil;
031:
032: /**
033: * Represents a general form element, a node in form element hierarchy.
034: *
035: * @author Jevgeni Kabanov (ekabanov <i>at</i> araneaframework <i>dot</i> org)
036: */
037: public abstract class GenericFormElement extends BaseApplicationWidget {
038: /** @since 1.1 */
039: public static final String SEAMLESS_VALIDATION_ACTION_ID = "bgValidate";
040:
041: //*******************************************************************
042: // FIELDS
043: //*******************************************************************
044: protected Constraint constraint;
045:
046: protected Map properties;
047:
048: protected boolean converted = false;
049: protected boolean validated = false;
050: protected Boolean backgroundValidation = null;
051:
052: private Set errors;
053:
054: //*********************************************************************
055: //* PUBLIC METHODS
056: //*********************************************************************
057:
058: protected void init() throws Exception {
059: super .init();
060: if (constraint != null)
061: constraint.setEnvironment(getConstraintEnvironment());
062: }
063:
064: /**
065: * Returns all properties of the element as a map (string -> string).
066: *
067: * @return all properties as a map.
068: */
069: public Map getProperties() {
070: if (properties == null)
071: properties = new HashMap();
072: return properties;
073: }
074:
075: /**
076: * Method for setting property values.
077: *
078: * @param key name of the property to be set.
079: * @param value value for the property.
080: */
081: public void setProperty(Object key, Object value) {
082: Assert.notNullParam(key, "key");
083:
084: getProperties().put(key, value);
085: }
086:
087: /**
088: * Returns the value of the property.
089: *
090: * @param key the name of the property to get.
091: * @return the value of the property, <code>null</code> if property is not defined.
092: */
093: public Object getProperty(Object key) {
094: Assert.notNullParam(key, "key");
095:
096: return getProperties().get(key);
097: }
098:
099: /**
100: * Returns element constraint.
101: *
102: * @return element constraint.
103: */
104: public Constraint getConstraint() {
105: return constraint;
106: }
107:
108: /**
109: * Sets element constraint.
110: *
111: * @param constraint The constraint to set.
112: */
113: public void setConstraint(Constraint constraint) {
114: this .constraint = constraint;
115: if (constraint != null && isInitialized())
116: constraint.setEnvironment(getConstraintEnvironment());
117: }
118:
119: public Environment getConstraintEnvironment() {
120: return getEnvironment();
121: }
122:
123: /**
124: * Returns whether the element is valid.
125: *
126: * @return whether the element is valid.
127: */
128: public boolean isValid() {
129: return (errors == null || errors.size() == 0);
130: }
131:
132: /**
133: * Converts the element value from control to data item and validates the value.
134: *
135: * @return whether the element is valid.
136: */
137: public boolean convertAndValidate() {
138: convert();
139: return validate();
140: }
141:
142: /**
143: * Converts the value from {@link Control}s to {@link Data}.
144: */
145: public void convert() {
146: try {
147: converted = false;
148: validated = false;
149:
150: if (!isAlive())
151: return;
152:
153: clearErrors();
154:
155: convertInternal();
156:
157: converted = isValid();
158: } catch (Exception e) {
159: ExceptionUtil.uncheckException(e);
160: }
161: }
162:
163: /**
164: * Validates the element.
165: *
166: * @return whether the element is valid.
167: */
168: public boolean validate() {
169: boolean valid = false;
170: try {
171: validated = false;
172:
173: valid = validateInternal();
174:
175: validated = valid;
176: return valid;
177: } catch (Exception e) {
178: ExceptionUtil.uncheckException(e);
179: }
180:
181: return valid;
182: }
183:
184: /**
185: * Returns whether last evaluation (converting and optional validating) has succeeded.
186: * @return whether last evaluation (converting and optional validating) has succeeded.
187: */
188: public boolean isEvaluated() {
189: return converted && validated;
190: }
191:
192: /**
193: * Since 1.1 this returns an immutable Set.
194: */
195: public Set getErrors() {
196: return Collections.unmodifiableSet(getMutableErrors());
197: }
198:
199: public void addError(String error) {
200: Assert.notEmptyParam(error, "error");
201:
202: getMutableErrors().add(error);
203: }
204:
205: public void addErrors(Set errors) {
206: Assert.notNullParam(errors, "errors");
207: for (Iterator i = errors.iterator(); i.hasNext();)
208: addError((String) i.next());
209: }
210:
211: /**
212: * Clears element errors.
213: */
214: public void clearErrors() {
215: errors = null;
216: }
217:
218: public Object getValue() {
219: return null;
220: }
221:
222: /** @since 1.1 */
223: public void setBackgroundValidation(boolean b) {
224: this .backgroundValidation = Boolean.valueOf(b);
225: }
226:
227: /** @since 1.1 */
228: public boolean isBackgroundValidation() {
229: if (this .backgroundValidation == null) {
230: FormContext fctx = ((FormContext) getEnvironment()
231: .getEntry(FormContext.class));
232: if (fctx != null)
233: return fctx.isBackgroundValidation();
234: return ConfigurationContextUtil
235: .isBackgroundFormValidationEnabled(UilibEnvironmentUtil
236: .getConfigurationContext(getEnvironment()));
237: }
238: return this .backgroundValidation.booleanValue();
239: }
240:
241: //*********************************************************************
242: //* ABSTRACT METHODS
243: //*********************************************************************
244:
245: /**
246: * Marks the current value of the data item as the base state
247: * that will be used to determine whether its state has changed in
248: * {@link #isStateChanged()}.
249: */
250: public abstract void markBaseState();
251:
252: /**
253: * Restores the value of the data item from the marked base state.
254: */
255: public abstract void restoreBaseState();
256:
257: /**
258: * Returns whether data item state has changed after it was marked.
259: * @return whether data item state has changed after it was marked.
260: */
261: public abstract boolean isStateChanged();
262:
263: /**
264: * Sets wether the element is disabled.
265: * @param disabled wether the element is disabled.
266: */
267: public abstract void setDisabled(boolean disabled);
268:
269: /**
270: * Returns whether the element is disabled.
271: * @return whether the element is disabled.
272: */
273: public abstract boolean isDisabled();
274:
275: /**
276: * Accepts the visitor.
277: */
278: public abstract void accept(String id, FormElementVisitor visitor);
279:
280: //*********************************************************************
281: //* INTERNAL METHODS
282: //*********************************************************************
283:
284: /** @since 1.1 this method is protected (private before 1.1). */
285: protected MessageContext getMessageCtx() {
286: return (MessageContext) getEnvironment().requireEntry(
287: MessageContext.class);
288: }
289:
290: /**
291: * Converts the element value from control to data item
292: * @throws Exception
293: */
294: protected abstract void convertInternal() throws Exception;
295:
296: /**
297: * Validates the element.
298: *
299: * @return whether the element is valid.
300: * @throws Exception
301: */
302: protected boolean validateInternal() throws Exception {
303: if (getConstraint() != null && isValid()) {
304: getConstraint().validate();
305: addErrors(getConstraint().getErrors());
306: getConstraint().clearErrors();
307: }
308:
309: return isValid();
310: }
311:
312: /**
313: * @since 1.1
314: */
315: protected Set getMutableErrors() {
316: if (errors == null)
317: errors = new HashSet();
318: return errors;
319: }
320:
321: //*********************************************************************
322: //* VIEW MODEL
323: //*********************************************************************
324:
325: /**
326: * This class represents a form element view model.
327: *
328: * @author Jevgeni Kabanov (ekabanov <i>at</i> araneaframework <i>dot</i> org)
329: *
330: */
331: public class ViewModel extends BaseApplicationWidget.ViewModel {
332: private Map properties;
333:
334: /**
335: * Takes a outer class snapshot.
336: */
337: public ViewModel() {
338: Map m = GenericFormElement.this .properties;
339: this .properties = m == null ? m : Collections
340: .unmodifiableMap(m);
341: }
342:
343: /**
344: * Returns form element properties.
345: * @return form element properties.
346: */
347: public Map getProperties() {
348: return properties;
349: }
350: }
351: }
|