/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.forms.flow.java;
import java.io.IOException;
import java.util.Locale;
import javax.servlet.http.HttpServletResponse;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.cocoon.components.flow.FlowHelper;
import org.apache.cocoon.components.flow.java.AbstractContinuable;
import org.apache.cocoon.components.flow.java.Continuation;
import org.apache.cocoon.components.flow.java.VarMap;
import org.apache.cocoon.environment.http.HttpEnvironment;
import org.apache.cocoon.forms.FormContext;
import org.apache.cocoon.forms.FormManager;
import org.apache.cocoon.forms.binding.Binding;
import org.apache.cocoon.forms.binding.BindingManager;
import org.apache.cocoon.forms.formmodel.Form;
import org.apache.cocoon.forms.formmodel.Widget;
import org.apache.cocoon.forms.transformation.FormsPipelineConfig;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.w3c.dom.Element;
/**
* Implementation of the Cocoon Forms/Java Flow integration.
*
* @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
* @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
* @version CVS $Id$
*/
public class FormInstance extends AbstractContinuable {
private Form form;
private Binding binding;
private Locale locale;
/**
* Create a form, given the URI of its definition file
*/
public FormInstance(String uri) {
FormManager formMgr = null;
SourceResolver resolver = null;
Source src = null;
try {
formMgr = (FormManager)getComponent(FormManager.ROLE);
resolver = (SourceResolver)getComponent(SourceResolver.ROLE);
src = resolver.resolveURI(uri);
this.form = formMgr.createForm(src);
this.binding = null;
// this.validator = null;
// TODO : do we keep this ?
// this.formWidget = new Widget(this.form); could not create instance
} catch (Exception e) {
throw new CascadingRuntimeException("Could not create form instance", e);
} finally {
releaseComponent(formMgr);
if (src != null) resolver.release(src);
releaseComponent(resolver);
}
}
/**
* Create a form, given the URI of its definition file, the
* binding file.
*/
public FormInstance(String definitionFile, String bindingFile) {
this(definitionFile);
createBinding(bindingFile);
}
/**
* Create a form of an fd:form element in the form of a org.w3c.dom.Element
*/
public FormInstance(Element formDefinition) {
FormManager formMgr = null;
try {
formMgr = (FormManager)getComponent(FormManager.ROLE);
this.form = formMgr.createForm(formDefinition);
this.binding = null;
} catch (Exception e) {
throw new CascadingRuntimeException("Could not create form instance", e);
} finally {
releaseComponent(formMgr);
}
}
public Widget getModel() {
return this.form;
}
/**
* Get a Widget (the java object) from the form.
* If <code>name</code> is undefined, the form widget itself is returned.
* Otherwise, the form's child widget of name <code>name</code> is returned.
*/
public Widget getChild(String name) {
if (name == null) {
return this.form;
} else {
return this.form.getChild(name);
}
}
public String getSubmitId() {
Widget widget = this.form.getSubmitWidget();
// Can be null on "normal" submit
return widget == null ? null : widget.getId();
}
/**
* Sets the point in your script that will be returned to when the form is
* redisplayed. If setBookmark() is not called, this is implicitly set to
* the beginning of showForm().
*/
/* public WebContinuation setBookmark() {
return (this.local_.webContinuation = cocoon.createWebContinuation());
}*/
/**
* Returns the bookmark continuation associated with this form, or undefined
* if setBookmark() has not been called.
*
*/
/* public WebContinuation getBookmark() {
return this.local_.webContinuation;
} */
public void show(String uri) {
show(uri, new VarMap());
}
/**
* Manages the display of a form and its validation.
*
* This uses some additionnal propertied on the form object :
* - "locale" : the form locale (default locale is used if not set)
* - "validator" : additional validation function. This function receives
* the form object as parameter and should return a boolean indicating
* if the form handling is finished (true) or if the form should be
* redisplayed again (false)
*
* On return, the calling code can check some properties to know the form result :
* - "isValid" : true if the form was sucessfully validated
* - "submitId" : the id of the widget that triggered the form submit (can be null)
*
* @param uri the page uri (like in cocoon.sendPageAndWait())
* @param bizData some business data for the view (like in cocoon.sendPageAndWait()).
* The "{FormsPipelineConfig.CFORMSKEY}" and "locale" properties are added to this object.
*/
public void show(String uri, Object bizData) {
if (bizData==null) bizData = new VarMap();
((VarMap)bizData).add(FormsPipelineConfig.CFORMSKEY, this.form);
if (this.locale == null)
this.locale = java.util.Locale.getDefault();
((VarMap)bizData).add("locale", this.locale);
// Keep the first continuation that will be created as the result of this function
//var result = null;
boolean finished = false;
do {
sendPageAndWait(uri, bizData);
if (getRequest().getParameter("cocoon-ajax-continue") == null) {
FormContext formContext = new FormContext(getRequest(), locale);
// Prematurely add the bizData as a request attribute so that event listeners can use it
// (the same is done by cocoon.sendPage())
FlowHelper.setContextObject(this.getObjectModel(), bizData);
finished = this.form.process(formContext);
// See /cocoon-2.1.X/src/blocks/forms/java/org/apache/cocoon/forms/flow/javascript/Form.js line 176-201
if (finished && getRequest().getParameter("cocoon-ajax") != null) {
HttpServletResponse httpResponse = (HttpServletResponse) getObjectModel().get(HttpEnvironment.HTTP_RESPONSE_OBJECT);
sendStatus(200);
httpResponse.setContentType("text/xml");
String text = "<?xml version='1.0'?><bu:document xmlns:bu='" +
org.apache.cocoon.ajax.BrowserUpdateTransformer.BU_NSURI +
"'><bu:continue/></bu:document>";
httpResponse.setContentLength(text.length());
try {
httpResponse.getWriter().print(text);
} catch (IOException e) {
// Do nothing
}
Continuation.suspend();
}
} else {
finished = true;
}
} while(!finished);
}
/*
/**
* Manages the display of a form and its validation.
* @param uri the page uri (like in cocoon.sendPageAndWait())
* @param fun optional function which will be executed after pipeline
* processing. Useful for releasing resources needed during pipeline
* processing but which should not become part of the continuation
* @param ttl Time to live (in milliseconds) for the continuation
* created
* @return The web continuation associated with submitting this form
*
public showForm(String uri, Object fun, ttl) {
if (!this.getBookmark()) {
this.setBookmark();
}
FormContext formContext = FormsFlowHelper.getFormContext(cocoon, this.locale);
// this is needed by the FormTemplateTransformer:
//var javaWidget = this.formWidget_.unwrap();;
//this.formWidget_["CocoonFormsInstance"] = javaWidget;
getRequest().setAttribute(Packages.org.apache.cocoon.forms.transformation.CFORMSKEY, this.formWidget);
WebContinuation wk = sendPageAndWait(uri, this.formWidget, fun, ttl);
var formContext = new FormContext(cocoon.request, javaWidget.getLocale());
var userErrors = 0;
this.formWidget_.validationErrorListener = function(widget, error) {
if (error != null) {
userErrors++;
}
}
var finished = javaWidget.process(formContext);
if (this.onValidate) {
this.onValidate(this);
}
if (!finished || userErrors > 0) {
cocoon.continuation = this.local_.webContinuation;
this.local_.webContinuation.continuation(this.local_.webContinuation);
}
return wk;
}*/
public void createBinding(String bindingURI) {
BindingManager bindingManager = null;
Source source = null;
SourceResolver resolver = null;
try {
bindingManager = (BindingManager)getComponent(BindingManager.ROLE);
resolver = (SourceResolver)getComponent(SourceResolver.ROLE);
source = resolver.resolveURI(bindingURI);
this.binding = bindingManager.createBinding(source);
} catch (Exception e) {
throw new CascadingRuntimeException("Could not create binding", e);
} finally {
if (source != null)
resolver.release(source);
releaseComponent(bindingManager);
releaseComponent(resolver);
}
}
public void load(Object object) {
if (this.binding == null)
throw new Error("Binding not configured for this form.");
try {
this.binding.loadFormFromModel(this.form, object);
} catch (Exception e) {
throw new CascadingRuntimeException("Could not load form from model", e);
}
}
public void save(Object object) {
if (this.binding == null)
throw new Error("Binding not configured for this form.");
try {
this.binding.saveFormToModel(this.form, object);
} catch (Exception e) {
throw new CascadingRuntimeException("Could not save form into model", e);
}
}
public void setAttribute(String name, Object value) {
this.form.setAttribute(name, value);
}
public Object getAttribute(String name) {
return this.form.getAttribute(name);
}
public void removeAttribute(String name) {
this.form.removeAttribute(name);
}
}