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:
018: package org.apache.cocoon.forms.flow.java;
019:
020: import java.io.IOException;
021: import java.util.Locale;
022:
023: import javax.servlet.http.HttpServletResponse;
024:
025: import org.apache.avalon.framework.CascadingRuntimeException;
026: import org.apache.cocoon.components.flow.FlowHelper;
027: import org.apache.cocoon.components.flow.java.AbstractContinuable;
028: import org.apache.cocoon.components.flow.java.Continuation;
029: import org.apache.cocoon.components.flow.java.VarMap;
030: import org.apache.cocoon.environment.http.HttpEnvironment;
031: import org.apache.cocoon.forms.FormContext;
032: import org.apache.cocoon.forms.FormManager;
033: import org.apache.cocoon.forms.binding.Binding;
034: import org.apache.cocoon.forms.binding.BindingManager;
035: import org.apache.cocoon.forms.formmodel.Form;
036: import org.apache.cocoon.forms.formmodel.Widget;
037: import org.apache.cocoon.forms.transformation.FormsPipelineConfig;
038: import org.apache.excalibur.source.Source;
039: import org.apache.excalibur.source.SourceResolver;
040: import org.w3c.dom.Element;
041:
042: /**
043: * Implementation of the Cocoon Forms/Java Flow integration.
044: *
045: * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
046: * @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
047: * @version CVS $Id: FormInstance.java 433543 2006-08-22 06:22:54Z crossley $
048: */
049: public class FormInstance extends AbstractContinuable {
050:
051: private Form form;
052: private Binding binding;
053: private Locale locale;
054:
055: /**
056: * Create a form, given the URI of its definition file
057: */
058: public FormInstance(String uri) {
059: FormManager formMgr = null;
060: SourceResolver resolver = null;
061: Source src = null;
062: try {
063: formMgr = (FormManager) getComponent(FormManager.ROLE);
064: resolver = (SourceResolver) getComponent(SourceResolver.ROLE);
065: src = resolver.resolveURI(uri);
066: this .form = formMgr.createForm(src);
067: this .binding = null;
068: // this.validator = null;
069: // TODO : do we keep this ?
070: // this.formWidget = new Widget(this.form); could not create instance
071: } catch (Exception e) {
072: throw new CascadingRuntimeException(
073: "Could not create form instance", e);
074: } finally {
075: releaseComponent(formMgr);
076: if (src != null)
077: resolver.release(src);
078: releaseComponent(resolver);
079: }
080: }
081:
082: /**
083: * Create a form, given the URI of its definition file, the
084: * binding file.
085: */
086: public FormInstance(String definitionFile, String bindingFile) {
087: this (definitionFile);
088: createBinding(bindingFile);
089: }
090:
091: /**
092: * Create a form of an fd:form element in the form of a org.w3c.dom.Element
093: */
094: public FormInstance(Element formDefinition) {
095: FormManager formMgr = null;
096: try {
097: formMgr = (FormManager) getComponent(FormManager.ROLE);
098: this .form = formMgr.createForm(formDefinition);
099: this .binding = null;
100: } catch (Exception e) {
101: throw new CascadingRuntimeException(
102: "Could not create form instance", e);
103: } finally {
104: releaseComponent(formMgr);
105: }
106: }
107:
108: public Widget getModel() {
109: return this .form;
110: }
111:
112: /**
113: * Get a Widget (the java object) from the form.
114: * If <code>name</code> is undefined, the form widget itself is returned.
115: * Otherwise, the form's child widget of name <code>name</code> is returned.
116: */
117: public Widget getChild(String name) {
118: if (name == null) {
119: return this .form;
120: } else {
121: return this .form.getChild(name);
122: }
123: }
124:
125: public String getSubmitId() {
126:
127: Widget widget = this .form.getSubmitWidget();
128: // Can be null on "normal" submit
129: return widget == null ? null : widget.getId();
130: }
131:
132: /**
133: * Sets the point in your script that will be returned to when the form is
134: * redisplayed. If setBookmark() is not called, this is implicitly set to
135: * the beginning of showForm().
136: */
137: /* public WebContinuation setBookmark() {
138: return (this.local_.webContinuation = cocoon.createWebContinuation());
139: }*/
140:
141: /**
142: * Returns the bookmark continuation associated with this form, or undefined
143: * if setBookmark() has not been called.
144: *
145: */
146: /* public WebContinuation getBookmark() {
147: return this.local_.webContinuation;
148: } */
149:
150: public void show(String uri) {
151: show(uri, new VarMap());
152: }
153:
154: /**
155: * Manages the display of a form and its validation.
156: *
157: * This uses some additionnal propertied on the form object :
158: * - "locale" : the form locale (default locale is used if not set)
159: * - "validator" : additional validation function. This function receives
160: * the form object as parameter and should return a boolean indicating
161: * if the form handling is finished (true) or if the form should be
162: * redisplayed again (false)
163: *
164: * On return, the calling code can check some properties to know the form result :
165: * - "isValid" : true if the form was sucessfully validated
166: * - "submitId" : the id of the widget that triggered the form submit (can be null)
167: *
168: * @param uri the page uri (like in cocoon.sendPageAndWait())
169: * @param bizData some business data for the view (like in cocoon.sendPageAndWait()).
170: * The "{FormsPipelineConfig.CFORMSKEY}" and "locale" properties are added to this object.
171: */
172: public void show(String uri, Object bizData) {
173:
174: if (bizData == null)
175: bizData = new VarMap();
176: ((VarMap) bizData)
177: .add(FormsPipelineConfig.CFORMSKEY, this .form);
178:
179: if (this .locale == null)
180: this .locale = java.util.Locale.getDefault();
181: ((VarMap) bizData).add("locale", this .locale);
182:
183: // Keep the first continuation that will be created as the result of this function
184: //var result = null;
185:
186: boolean finished = false;
187:
188: do {
189: sendPageAndWait(uri, bizData);
190:
191: if (getRequest().getParameter("cocoon-ajax-continue") == null) {
192: FormContext formContext = new FormContext(getRequest(),
193: locale);
194:
195: // Prematurely add the bizData as a request attribute so that event listeners can use it
196: // (the same is done by cocoon.sendPage())
197: FlowHelper.setContextObject(this .getObjectModel(),
198: bizData);
199:
200: finished = this .form.process(formContext);
201:
202: // See /cocoon-2.1.X/src/blocks/forms/java/org/apache/cocoon/forms/flow/javascript/Form.js line 176-201
203: if (finished
204: && getRequest().getParameter("cocoon-ajax") != null) {
205: HttpServletResponse httpResponse = (HttpServletResponse) getObjectModel()
206: .get(HttpEnvironment.HTTP_RESPONSE_OBJECT);
207: sendStatus(200);
208: httpResponse.setContentType("text/xml");
209: String text = "<?xml version='1.0'?><bu:document xmlns:bu='"
210: + org.apache.cocoon.ajax.BrowserUpdateTransformer.BU_NSURI
211: + "'><bu:continue/></bu:document>";
212: httpResponse.setContentLength(text.length());
213: try {
214: httpResponse.getWriter().print(text);
215: } catch (IOException e) {
216: // Do nothing
217: }
218: Continuation.suspend();
219: }
220: } else {
221: finished = true;
222: }
223:
224: } while (!finished);
225: }
226:
227: /*
228: /**
229: * Manages the display of a form and its validation.
230: * @param uri the page uri (like in cocoon.sendPageAndWait())
231: * @param fun optional function which will be executed after pipeline
232: * processing. Useful for releasing resources needed during pipeline
233: * processing but which should not become part of the continuation
234: * @param ttl Time to live (in milliseconds) for the continuation
235: * created
236: * @return The web continuation associated with submitting this form
237: *
238: public showForm(String uri, Object fun, ttl) {
239: if (!this.getBookmark()) {
240: this.setBookmark();
241: }
242: FormContext formContext = FormsFlowHelper.getFormContext(cocoon, this.locale);
243: // this is needed by the FormTemplateTransformer:
244: //var javaWidget = this.formWidget_.unwrap();;
245: //this.formWidget_["CocoonFormsInstance"] = javaWidget;
246: getRequest().setAttribute(Packages.org.apache.cocoon.forms.transformation.CFORMSKEY, this.formWidget);
247: WebContinuation wk = sendPageAndWait(uri, this.formWidget, fun, ttl);
248: var formContext = new FormContext(cocoon.request, javaWidget.getLocale());
249: var userErrors = 0;
250: this.formWidget_.validationErrorListener = function(widget, error) {
251: if (error != null) {
252: userErrors++;
253: }
254: }
255: var finished = javaWidget.process(formContext);
256: if (this.onValidate) {
257: this.onValidate(this);
258: }
259: if (!finished || userErrors > 0) {
260: cocoon.continuation = this.local_.webContinuation;
261: this.local_.webContinuation.continuation(this.local_.webContinuation);
262: }
263: return wk;
264: }*/
265:
266: public void createBinding(String bindingURI) {
267: BindingManager bindingManager = null;
268: Source source = null;
269: SourceResolver resolver = null;
270: try {
271: bindingManager = (BindingManager) getComponent(BindingManager.ROLE);
272: resolver = (SourceResolver) getComponent(SourceResolver.ROLE);
273: source = resolver.resolveURI(bindingURI);
274: this .binding = bindingManager.createBinding(source);
275: } catch (Exception e) {
276: throw new CascadingRuntimeException(
277: "Could not create binding", e);
278: } finally {
279: if (source != null)
280: resolver.release(source);
281: releaseComponent(bindingManager);
282: releaseComponent(resolver);
283: }
284: }
285:
286: public void load(Object object) {
287: if (this .binding == null)
288: throw new Error("Binding not configured for this form.");
289:
290: try {
291: this .binding.loadFormFromModel(this .form, object);
292: } catch (Exception e) {
293: throw new CascadingRuntimeException(
294: "Could not load form from model", e);
295: }
296: }
297:
298: public void save(Object object) {
299: if (this .binding == null)
300: throw new Error("Binding not configured for this form.");
301:
302: try {
303: this .binding.saveFormToModel(this .form, object);
304: } catch (Exception e) {
305: throw new CascadingRuntimeException(
306: "Could not save form into model", e);
307: }
308: }
309:
310: public void setAttribute(String name, Object value) {
311: this .form.setAttribute(name, value);
312: }
313:
314: public Object getAttribute(String name) {
315: return this .form.getAttribute(name);
316: }
317:
318: public void removeAttribute(String name) {
319: this.form.removeAttribute(name);
320: }
321: }
|