001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.forms.formmodel;
018:
019: import org.apache.cocoon.forms.FormContext;
020: import org.apache.cocoon.forms.validation.WidgetValidator;
021: import org.apache.cocoon.forms.event.WidgetEvent;
022: import org.apache.cocoon.util.location.Locatable;
023: import org.apache.cocoon.util.location.Location;
024: import org.xml.sax.ContentHandler;
025: import org.xml.sax.SAXException;
026:
027: import java.util.Locale;
028:
029: /**
030: * Interface to be implemented by Widgets. In CForms, a form consists of a number
031: * of widgets. Each widget:
032: *
033: * <ul>
034: * <li>has an unique id within its parent context widget. See {@link #getId()}.</li>
035: * <li>can have a parent (see {@link #getParent()}.</li>
036: * <li>can hold a value (which can be any kind of object). See {@link #getValue()}.</li>
037: * <li>can read its value from a request object (and convert it from a string to its native type).
038: * See {@link #readFromRequest(FormContext)}.</li>
039: * <li>can validate itself. See {@link #validate()}.</li>
040: * <li>can generate an XML representation of itself.</li>
041: * </ul>
042: *
043: * <p>When a request is submitted, first the {@link #readFromRequest(FormContext)} method of all widgets
044: * will be called so that they can read their value(s). Next, the {@link #validate()} method will
045: * be called. Doing this in two steps allows the validation to compare values between widgets.
046: * See also the method {@link Form#process(FormContext)}.</p>
047: *
048: * <p>A Widget is created by calling the createInstance method on the a
049: * {@link WidgetDefinition}. A Widget holds all the data that is specific for
050: * a certain use of the widget (its value, validationerrors, ...), while the
051: * WidgetDefinition holds the data that is static accross all widgets. This
052: * keeps the Widgets small and light to create. This mechanism is similar to
053: * classes and objects in Java.
054: *
055: * @version $Id: Widget.java 449149 2006-09-23 03:58:05Z crossley $
056: */
057: public interface Widget extends Locatable {
058:
059: /**
060: * Widget-Separator used in path-like notations
061: * @see #lookupWidget(String)
062: */
063: char PATH_SEPARATOR = '/';
064:
065: /**
066: * Called after widget's environment has been setup,
067: * to allow for any contextual initalization such as
068: * looking up case widgets for union widgets.
069: */
070: void initialize();
071:
072: /**
073: * @return the source location of this widget.
074: */
075: Location getLocation();
076:
077: /**
078: * @return the name of this widget. This should never be <code>null</code>
079: * Top-level container widgets (like 'form') should return <code>""</code>
080: */
081: String getName();
082:
083: /**
084: * @return the id of this widget. This should never be <code>null</code>
085: * Top-level container widgets (like 'form') should return <code>""</code>
086: */
087: String getId();
088:
089: /**
090: * @return the parent of this widget. If this widget is the root widget,
091: * this method returns null.
092: */
093: Widget getParent();
094:
095: /**
096: * This method is called on a widget when it is added to a container.
097: * You shouldn't call this method unless youre implementing a widget yourself (in
098: * which case it should be called when a widget is added as child of your widget).
099: */
100: void setParent(Widget widget);
101:
102: /**
103: * @return the {@link Form} to which this widget belongs. The form is the top-most ancestor
104: * of the widget.
105: */
106: Form getForm();
107:
108: /**
109: * Get this widget's definition.
110: *
111: * @return the widget's definition
112: */
113: WidgetDefinition getDefinition();
114:
115: /**
116: * Get the widget's own state. Note that this state is <em>not</em> the one actually considered
117: * for handling requests and producing output. For these matters, the combined state is used.
118: *
119: * @see #getCombinedState()
120: * @return the widget's own state
121: */
122: WidgetState getState();
123:
124: /**
125: * Set the widget's own state. This may change its combined state, and those of its
126: * children, if any.
127: *
128: * @param state the new wiget state
129: */
130: void setState(WidgetState state);
131:
132: /**
133: * Get the widget's combined state, which is the strictest of its own state and parent state.
134: * This combined state is the one that will be used by the widget to know if request
135: * parameters should be considered and if some output must be produced.
136: *
137: * @see WidgetState#strictest(WidgetState, WidgetState)
138: * @return the combined state
139: */
140: WidgetState getCombinedState();
141:
142: /**
143: * @return the name prefixed with the namespace, this name should be unique
144: * accross all widgets on the form.
145: */
146: String getFullName();
147:
148: /**
149: * @return the id prefixed with the namespace, this name should be unique
150: * accross all widgets on the form.
151: */
152: String getRequestParameterName();
153:
154: /**
155: * @deprecated getWidget got removed, use lookupWidget or getChild instead.
156: * @throws UnsupportedOperationException indicating this method has been
157: * deprecated from the API, and will be removed from future releases.
158: */
159: Widget getWidget(String id);
160:
161: /**
162: * Finds a widget relative to this one based on a path-like
163: * string (/-delimted) into the widget-tree structure.
164: * This supports '../' and '/' to point to
165: * @return the found widget or <code>null</code> if allong the traversal
166: * of the path an invalid section was encountered.
167: */
168: Widget lookupWidget(String path);
169:
170: /**
171: * Lets this widget read its data from a request. At this point the Widget
172: * may try to convert the request parameter to its native datatype (if it
173: * is not a string), but it should not yet generate any validation errors.
174: */
175: void readFromRequest(FormContext formContext);
176:
177: /**
178: * Validates this widget and returns the outcome. Possible error messages are
179: * remembered by the widget itself and will be part of the XML produced by
180: * this widget in its {@link #generateSaxFragment(ContentHandler, Locale)} method.
181: *
182: * @return <code>true</code> to indicate all validations were ok,
183: * <code>false</code> otherwise
184: */
185: boolean validate();
186:
187: void addValidator(WidgetValidator validator);
188:
189: boolean removeValidator(WidgetValidator validator);
190:
191: /**
192: * Return the current validation state.
193: * This method delivers the same result as the last call to {@link #validate()}.
194: * The validation process is not started again. If the value of this widget has
195: * changed since the latest call to {@link #validate()}, the result of this method
196: * is out of date.
197: * @return The result of the last call to {@link #validate()}.
198: */
199: boolean isValid();
200:
201: /**
202: * Generates an XML representation of this widget. The startDocument and endDocument
203: * SAX events will not be called. It is assumed that the prefix for the CForms namespace
204: * mentioned in Constants.FI_PREFIX is already declared (by the caller or otherwise).
205: */
206: void generateSaxFragment(ContentHandler contentHandler,
207: Locale locale) throws SAXException;
208:
209: /**
210: * Generates SAX events for the label of this widget. The label will not be wrapped
211: * inside another element.
212: */
213: void generateLabel(ContentHandler contentHandler)
214: throws SAXException;
215:
216: /**
217: * Get the value of a widget.
218: * <p>
219: * Not all widgets do have a value (notably {@link ContainerWidget}s,
220: * but this method is provided here as a convenience to ease writing and avoiding casts.
221: *
222: * @return the value of the widget.
223: * @throws UnsupportedOperationException if this widget doesn't have a value.
224: */
225: Object getValue() throws UnsupportedOperationException;
226:
227: /**
228: * Sets the value of this widget.
229: * <p>
230: * Not all widgets do have a value (notably {@link ContainerWidget}s,
231: * but this method is provided here as a convenience to ease writing and avoiding casts.
232: *
233: * @param value the new widget's value.
234: * @throws UnsupportedOperationException if this widget doesn't have a value.
235: */
236: void setValue(Object value) throws UnsupportedOperationException;
237:
238: /**
239: * @return whether this widget is required to be filled in. As with {@link #getValue()},
240: * for some widgets this may not make sense, those should return false here.
241: */
242: boolean isRequired();
243:
244: /**
245: * Broadcast an event previously queued by this widget to its event listeners.
246: */
247: void broadcastEvent(WidgetEvent event);
248:
249: /**
250: * Retrieves an attribute on this widget.
251: *
252: * @param name of the attribute to lookup
253: * @return the found attribute or <code>null</code> if none was found with that name.
254: */
255: Object getAttribute(String name);
256:
257: /**
258: * Sets an attribute on this widget. This can be used to store custom
259: * data with each widget.
260: */
261: void setAttribute(String name, Object value);
262:
263: /**
264: * Removes the named attribute from this widget.
265: *
266: * @param name of the attribute
267: */
268: void removeAttribute(String name);
269: }
|