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 org.araneaframework.uilib.DataItemTypeViolatedException;
018: import org.araneaframework.uilib.util.Event;
019:
020: /**
021: * This class represents typed form element data. Type is used by the
022: * {@link org.araneaframework.uilib.form.converter.ConverterFactory} to find the appropriate
023: * {@link org.araneaframework.uilib.form.Converter} for converting {@link Data} held in
024: * {@link org.araneaframework.uilib.form.FormElement} to plain object type held in
025: * {@link org.araneaframework.uilib.form.Control}. Reverse converting happens much
026: * the same, both object type in {@link org.araneaframework.uilib.form.Control}
027: * and supposed {@link org.araneaframework.uilib.form.FormElement} {@link Data} are
028: * considered and appropriate {@link org.araneaframework.uilib.form.Converter}
029: * chosen.
030: *
031: * @author Jevgeni Kabanov (ekabanov <i>at</i> araneaframework <i>dot</i> org)
032: */
033: public class Data implements java.io.Serializable, FormElementAware {
034: protected String type;
035: protected Class typeClass;
036:
037: protected Object value;
038: protected Object markedBaseValue;
039:
040: protected FormElement feCtx;
041:
042: /**
043: * Creates {@link Data} of type <code>type</code>.
044: * @param type the type of {@link Data}
045: */
046: protected Data(Class typeClass, String type) {
047: this .type = type;
048: this .typeClass = typeClass;
049: }
050:
051: /**
052: * Creates {@link Data} for holding objects of given <code>Class</code>.
053: * <code>Type</code> is assumed to be simple class name of given Class.
054: * @param typeClass the <code>Class</code> of {@link Data} values.
055: */
056: public Data(Class typeClass) {
057: this .typeClass = typeClass;
058: this .type = typeClass.toString().substring(
059: typeClass.toString().lastIndexOf('.') + 1);
060: }
061:
062: /**
063: * Returns {@link Data} value.
064: * @return {@link Data} value.
065: */
066: public Object getValue() {
067: return value;
068: }
069:
070: /**
071: * Sets {@link Data} value.
072: * @param value {@link Data} value.
073: */
074: public void setValue(Object value) {
075: setDataValue(value);
076: setControlValue(value);
077: }
078:
079: /**
080: * Sets the value of this {@link Data} without modifying underlying {@link Control}.
081: * This is used on {@link FormElement} conversion—which should not affect {@link Control} values
082: * read from request.
083: *
084: * @since 1.0.12 */
085: public void setDataValue(Object value) {
086: if (value != null
087: && !(typeClass.isAssignableFrom(value.getClass())))
088: throw new DataItemTypeViolatedException(getValueType(),
089: value.getClass());
090:
091: this .value = value;
092: }
093:
094: /**
095: * Sets the value of {@link Control} that is associated with {@link FormElement} which owns this {@link Data}.
096: * @since 1.0.12 */
097: public void setControlValue(final Object value) {
098: if (feCtx != null) {
099: feCtx.addInitEvent(new Event() {
100: public void run() {
101: // TODO:this is dangerous in case Data value is set before FE is associated with Control
102: if (feCtx.getControl() != null) {
103: feCtx.getControl().setRawValue(
104: feCtx.getConverter().reverseConvert(
105: value));
106: }
107: }
108: });
109: }
110: }
111:
112: /**
113: * Returns {@link Data} type.
114: * @return {@link Data} type.
115: */
116: public String getValueType() {
117: return type;
118: }
119:
120: public String toString() {
121: return "Data: [Type = " + getValueType() + "; Value = " + value
122: + "]";
123: }
124:
125: /**
126: * Returns a new instance of this {@link Data}, value is not set.
127: * @return a new instance of current {@link Data}, value is not set.
128: */
129: public Data newData() {
130: return new Data(typeClass, type);
131: }
132:
133: /**
134: * Marks the current value of the {@link Data} as the base state
135: * that will be used to determine whether its state has changed in
136: * {@link #isStateChanged()}.
137: */
138: public void markBaseState() {
139: markedBaseValue = value;
140: }
141:
142: /**
143: * Restores the value of the {@link Data} from the marked base state.
144: */
145: public void restoreBaseState() {
146: // TODO: maybe deep copy?
147: setValue(markedBaseValue);
148: }
149:
150: /**
151: * Returns whether {@link Data} state (value) has changed after it was marked.
152: * @return whether {@link Data} state (value) has changed after it was marked.
153: */
154: public boolean isStateChanged() {
155: if (markedBaseValue == null && value == null)
156: return false;
157: else if (markedBaseValue == null || value == null)
158: return true;
159: else
160: return !markedBaseValue.equals(value);
161: }
162:
163: public void setFormElementCtx(FormElementContext feCtx) {
164: if (this .feCtx != feCtx) {
165: this .feCtx = (FormElement) feCtx;
166: setValue(getValue());
167: }
168: }
169: }
|