You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2004/06/15 09:33:44 UTC

cvs commit: cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/util SimpleServiceSelector.java

sylvain     2004/06/15 00:33:44

  Modified:    src/blocks/forms/java/org/apache/cocoon/forms
                        DefaultFormManager.java
               src/blocks/forms/java/org/apache/cocoon/forms/binding
                        ComposedJXPathBindingBase.java
                        JXPathBindingManager.java
                        JavaScriptJXPathBinding.java
                        JavaScriptJXPathBindingBuilder.java
                        SimpleRepeaterJXPathBinding.java
               src/blocks/forms/java/org/apache/cocoon/forms/event
                        WidgetEventMulticaster.java
               src/blocks/forms/java/org/apache/cocoon/forms/event/impl
                        JavaScriptWidgetListener.java
                        JavaScriptWidgetListenerBuilder.java
               src/blocks/forms/java/org/apache/cocoon/forms/flow/javascript
                        Form.js
               src/blocks/forms/java/org/apache/cocoon/forms/formmodel
                        AbstractWidgetDefinition.java
                        AbstractWidgetDefinitionBuilder.java
                        FieldDefinition.java FieldDefinitionBuilder.java
               src/blocks/forms/java/org/apache/cocoon/forms/util
                        SimpleServiceSelector.java
  Added:       src/blocks/forms/java/org/apache/cocoon/forms/event
                        CreateEvent.java CreateListener.java
  Log:
  - remove dependencies on EnvironmentHelper (now compatible with 2.1.5 and 2.2-dev)
  - add <child-binding> to JS binding (useful for container widgets)
  - early prototype of CreateEvent (needs much more work)
  - fix NPE in SimpleRepeater
  
  Revision  Changes    Path
  1.6       +18 -3     cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/DefaultFormManager.java
  
  Index: DefaultFormManager.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/DefaultFormManager.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- DefaultFormManager.java	1 Jun 2004 10:51:28 -0000	1.5
  +++ DefaultFormManager.java	15 Jun 2004 07:33:43 -0000	1.6
  @@ -22,6 +22,9 @@
   import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
  +import org.apache.avalon.framework.context.Context;
  +import org.apache.avalon.framework.context.ContextException;
  +import org.apache.avalon.framework.context.Contextualizable;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.avalon.framework.service.ServiceException;
   import org.apache.avalon.framework.service.ServiceManager;
  @@ -46,7 +49,7 @@
    */
   public class DefaultFormManager 
     extends AbstractLogEnabled 
  -  implements FormManager, ThreadSafe, Serviceable, Disposable, Configurable, Component, Initializable {
  +  implements FormManager, Contextualizable, ThreadSafe, Serviceable, Disposable, Configurable, Component, Initializable {
         
       protected static final String PREFIX = "CocoonForm:";
       protected ServiceManager manager;
  @@ -54,7 +57,18 @@
       protected SimpleServiceSelector widgetDefinitionBuilderSelector;
       protected CacheManager cacheManager;
   
  -    public void service(ServiceManager serviceManager) throws ServiceException {
  +    private Context avalonContext;
  +    public void contextualize(Context context) throws ContextException {
  +		this.avalonContext = context;
  +	}
  +    
  +    /** Temporary internal method, don't rely on it's existence! Needed to access the context from flowscript. */
  +    // FIXME (SW). Extending the FOM is needed.
  +    public Context getAvalonContext() {
  +    		return this.avalonContext;
  +    }
  +
  +	public void service(ServiceManager serviceManager) throws ServiceException {
           this.manager = serviceManager;
           this.cacheManager = (CacheManager)serviceManager.lookup(CacheManager.ROLE);
       }
  @@ -190,4 +204,5 @@
           this.manager = null;
           this.cacheManager = null;
       }
  +
   }
  
  
  
  1.3       +2 -2      cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/ComposedJXPathBindingBase.java
  
  Index: ComposedJXPathBindingBase.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/ComposedJXPathBindingBase.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ComposedJXPathBindingBase.java	11 Mar 2004 02:56:32 -0000	1.2
  +++ ComposedJXPathBindingBase.java	15 Jun 2004 07:33:43 -0000	1.3
  @@ -36,7 +36,7 @@
        *
        * @param childBindings sets the array of childBindings
        */
  -    protected ComposedJXPathBindingBase(JXPathBindingBuilderBase.CommonAttributes commonAtts, JXPathBindingBase[] childBindings) {
  +    public ComposedJXPathBindingBase(JXPathBindingBuilderBase.CommonAttributes commonAtts, JXPathBindingBase[] childBindings) {
           super(commonAtts);
           this.subBindings = childBindings;
           if (this.subBindings != null) {
  
  
  
  1.4       +20 -5     cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingManager.java
  
  Index: JXPathBindingManager.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/JXPathBindingManager.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- JXPathBindingManager.java	1 Jun 2004 10:51:28 -0000	1.3
  +++ JXPathBindingManager.java	15 Jun 2004 07:33:43 -0000	1.4
  @@ -20,11 +20,15 @@
   import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
  +import org.apache.avalon.framework.context.Context;
  +import org.apache.avalon.framework.context.ContextException;
  +import org.apache.avalon.framework.context.Contextualizable;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.avalon.framework.service.ServiceException;
   import org.apache.avalon.framework.service.ServiceManager;
   import org.apache.avalon.framework.service.Serviceable;
   import org.apache.avalon.framework.thread.ThreadSafe;
  +import org.apache.cocoon.components.LifecycleHelper;
   import org.apache.cocoon.forms.CacheManager;
   import org.apache.cocoon.forms.datatype.DatatypeManager;
   import org.apache.cocoon.forms.util.DomHelper;
  @@ -43,7 +47,7 @@
    * @version CVS $Id$
    */
   public class JXPathBindingManager extends AbstractLogEnabled implements
  -        BindingManager, Serviceable, Disposable, Initializable, Configurable,
  +        BindingManager, Contextualizable, Serviceable, Disposable, Initializable, Configurable,
           ThreadSafe {
   
       private static final String PREFIX = "CocoonFormBinding:";
  @@ -58,7 +62,13 @@
   
       private CacheManager cacheManager;
   
  -    public void service(ServiceManager serviceManager) throws ServiceException {
  +	private Context avalonContext;
  +
  +	public void contextualize(Context context) throws ContextException {
  +		this.avalonContext = context;
  +	}
  +
  +	public void service(ServiceManager serviceManager) throws ServiceException {
           this.serviceManager = serviceManager;
           this.datatypeManager = (DatatypeManager) serviceManager
                   .lookup(DatatypeManager.ROLE);
  @@ -74,8 +84,13 @@
       public void initialize() throws Exception {
           bindingBuilderSelector = new SimpleServiceSelector("binding",
                   JXPathBindingBuilderBase.class);
  -        bindingBuilderSelector.enableLogging(getLogger());
  -        bindingBuilderSelector.configure(configuration.getChild("bindings"));
  +        LifecycleHelper.setupComponent(
  +        		bindingBuilderSelector,
  +			getLogger(),
  +			this.avalonContext,
  +			this.serviceManager,
  +			null, // RoleManager,
  +			configuration.getChild("bindings"));
       }
   
       public Binding createBinding(Source source) throws BindingException {
  
  
  
  1.7       +46 -24    cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/JavaScriptJXPathBinding.java
  
  Index: JavaScriptJXPathBinding.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/JavaScriptJXPathBinding.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- JavaScriptJXPathBinding.java	25 May 2004 07:28:24 -0000	1.6
  +++ JavaScriptJXPathBinding.java	15 Jun 2004 07:33:43 -0000	1.7
  @@ -16,15 +16,21 @@
   package org.apache.cocoon.forms.binding;
   
   import java.util.HashMap;
  +import java.util.Iterator;
   import java.util.Map;
   
   import org.apache.avalon.framework.CascadingRuntimeException;
  +import org.apache.avalon.framework.context.Context;
  +import org.apache.cocoon.components.ContextHelper;
  +import org.apache.cocoon.components.flow.javascript.ScriptableMap;
   import org.apache.cocoon.environment.internal.EnvironmentHelper;
   import org.apache.cocoon.forms.formmodel.Widget;
   import org.apache.cocoon.forms.util.JavaScriptHelper;
   import org.apache.commons.jxpath.JXPathContext;
   import org.apache.commons.jxpath.Pointer;
  +import org.mozilla.javascript.Function;
   import org.mozilla.javascript.Script;
  +import org.mozilla.javascript.Scriptable;
   
   /**
    *
  @@ -33,19 +39,32 @@
    */
   public class JavaScriptJXPathBinding extends JXPathBindingBase {
   
  +	private final Context avalonContext;
       private final String id;
       private final String path;
  -    private final Script loadScript;
  -    private final Script saveScript;
  +    private final Function loadScript;
  +    private final Function saveScript;
  +    private final Scriptable childBindings;
  +    
  +    final static String[] LOAD_PARAMS = { "widget", "jxpathPointer", "jxpathContext", "childBindings" };
  +    final static String[] SAVE_PARAMS = { "widget", "jxpathPointer", "jxpathContext", "childBindings" };
   
       public JavaScriptJXPathBinding(
  -            JXPathBindingBuilderBase.CommonAttributes commonAtts, String id,
  -            String path, Script loadScript, Script saveScript) {
  +    		    Context context, JXPathBindingBuilderBase.CommonAttributes commonAtts, String id,
  +            String path, Function loadScript, Function saveScript, Map childBindings) {
           super(commonAtts);
           this.id = id;
           this.path = path;
           this.loadScript = loadScript;
           this.saveScript = saveScript;
  +        this.avalonContext = context;
  +        
  +        // Set parent on child bindings
  +        for(Iterator iter = childBindings.values().iterator(); iter.hasNext(); ) {
  +        		((Binding)iter.next()).setParent(this);
  +        }
  +        
  +        this.childBindings = new ScriptableMap(childBindings);
       }
   
       public void doLoad(Widget frmModel, JXPathContext jctx) {
  @@ -55,19 +74,22 @@
               // Move to widget context
               Pointer pointer = jctx.getPointer(this.path);
       
  -            // FIXME: remove this ugly hack and get the request from the
  -            // Avalon context once binding builder are real components
  -            Map objectModel = EnvironmentHelper.getCurrentEnvironment().getObjectModel();
  +            Map objectModel = ContextHelper.getObjectModel(this.avalonContext);
   
               try {
  -                Map values = new HashMap(3);
  -                values.put("widget", widget);
  -                values.put("jxpathPointer", pointer);
  -                if (pointer.getNode() != null) {
  -                    values.put("jxpathContext", jctx.getRelativeContext(pointer));
  -                }
  +//                Map values = new HashMap(3);
  +//                values.put("widget", widget);
  +//                values.put("jxpathPointer", pointer);
  +//                if (pointer.getNode() != null) {
  +//                    values.put("jxpathContext", jctx.getRelativeContext(pointer));
  +//                }
  +//                values.put("childBindings", this.childBindings);
  +                
  +                JXPathContext newCtx = pointer.getNode() == null ? null :
  +                	    jctx.getRelativeContext(pointer);
   
  -                JavaScriptHelper.execScript(this.loadScript, values, objectModel);
  +                JavaScriptHelper.callFunction(this.loadScript, frmModel,
  +                		new Object[] {widget, pointer, newCtx, this.childBindings}, objectModel);
       
               } catch(RuntimeException re) {
                   // rethrow
  @@ -90,16 +112,16 @@
               Pointer pointer = jctx.createPath(this.path);
               JXPathContext widgetCtx = jctx.getRelativeContext(pointer);
               try {
  -                // FIXME: remove this ugly hack and get the request from the Avalon context once
  -                // binding builder are real components
  -                Map objectModel = EnvironmentHelper.getCurrentEnvironment().getObjectModel();
  -
  -                Map values = new HashMap();
  -                values.put("widget", widget);
  -                values.put("jxpathContext", widgetCtx);
  -                values.put("jxpathPointer", pointer);
  +                Map objectModel = ContextHelper.getObjectModel(this.avalonContext);
  +
  +//                Map values = new HashMap();
  +//                values.put("widget", widget);
  +//                values.put("jxpathContext", widgetCtx);
  +//                values.put("jxpathPointer", pointer);
  +//                values.put("childBindings", this.childBindings);
   
  -                JavaScriptHelper.execScript(this.saveScript, values, objectModel);
  +                JavaScriptHelper.callFunction(this.saveScript, frmModel,
  +                		new Object[] {widget, pointer, widgetCtx, this.childBindings}, objectModel);
   
               } catch(RuntimeException re) {
                   // rethrow
  
  
  
  1.3       +64 -9     cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/JavaScriptJXPathBindingBuilder.java
  
  Index: JavaScriptJXPathBindingBuilder.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/JavaScriptJXPathBindingBuilder.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- JavaScriptJXPathBindingBuilder.java	24 Mar 2004 01:32:45 -0000	1.2
  +++ JavaScriptJXPathBindingBuilder.java	15 Jun 2004 07:33:43 -0000	1.3
  @@ -15,28 +15,42 @@
    */
   package org.apache.cocoon.forms.binding;
   
  +import java.util.Collections;
  +import java.util.HashMap;
  +import java.util.Map;
  +
  +import org.apache.avalon.framework.context.Context;
  +import org.apache.avalon.framework.context.ContextException;
  +import org.apache.avalon.framework.context.Contextualizable;
   import org.apache.cocoon.forms.binding.JXPathBindingManager.Assistant;
   import org.apache.cocoon.forms.util.DomHelper;
   import org.apache.cocoon.forms.util.JavaScriptHelper;
  +import org.mozilla.javascript.Function;
   import org.mozilla.javascript.Script;
   import org.w3c.dom.Element;
   
   /**
    * Builds a {@link Binding} based on two JavaScript snippets, respectively for loading and saving the form.
  + * This binding also optionally accepts named child bindings, which are useful when the bound widget is a container.
    * <p>
  - * The syntax for this binding is as follows :
  + * The syntax for this binding is as follows:
    * <pre>
    *   &lt;fb:javascript id="foo" path="@foo"&gt;
    *     &lt;fb:load-form&gt;
    *       var appValue = jxpathPointer.getValue();
    *       var formValue = doLoadConversion(appValue);
    *       widget.setValue(formValue);
  + *       childBindings["foo"].loadFormFromModel(widget, jxpathContext);
    *     &lt;/fb:load-form&gt;
    *     &lt;fb:save-form&gt;
    *       var formValue = widget.getValue();
    *       var appValue = doSaveConversion(formValue);
    *       jxpathPointer.setValue(appValue);
  + *       childBindings["foo"].saveFormToModel(widget, jxpathContext);
    *     &lt;/fb:save-form&gt;
  + *     &lt;fb:child-binding name="foo"&gt;
  + *       &lt;fb:value id="bar" path="baz"/&gt;
  + *     &lt;/fb:child-binding&gt;
    *   &lt;/fb:javascript&gt;
    * </pre>
    * This example is rather trivial and could be replaced by a simple &lt;fb:value&gt;, but
  @@ -54,37 +68,78 @@
    * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
    * @version CVS $Id$
    */
  -public class JavaScriptJXPathBindingBuilder extends JXPathBindingBuilderBase {
  +public class JavaScriptJXPathBindingBuilder extends JXPathBindingBuilderBase implements Contextualizable {
   
  -    public JXPathBindingBase buildBinding(Element element, Assistant assistant) throws BindingException {
  +	private Context avalonContext;
  +	
  +	public void contextualize(Context context) throws ContextException {
  +		this.avalonContext = context;
  +	}
  +
  +	public JXPathBindingBase buildBinding(Element element, Assistant assistant) throws BindingException {
           try {
               CommonAttributes commonAtts = JXPathBindingBuilderBase.getCommonAttributes(element);
   
               String id = DomHelper.getAttribute(element, "id");
               String path = DomHelper.getAttribute(element, "path");
   
  -            Script loadScript = null;
  +            // Build load script
  +            Function loadScript = null;
               if (commonAtts.loadEnabled) {
                   Element loadElem = DomHelper.getChildElement(element, BindingManager.NAMESPACE, "load-form");
                   if (loadElem == null) {
                       throw new BindingException("Element \"load-form\" is missing (" +
                           DomHelper.getLocation(element) + ")");
                   }
  -                loadScript = JavaScriptHelper.buildScript(loadElem);
  +                loadScript = JavaScriptHelper.buildFunction(loadElem, JavaScriptJXPathBinding.LOAD_PARAMS);
               }
   
  -            Script saveScript = null;
  +            	// Build save script
  +            Function saveScript = null;
               if (commonAtts.saveEnabled) {
                   Element saveElem = DomHelper.getChildElement(element, BindingManager.NAMESPACE, "save-form");
                   if (saveElem == null) {
                       throw new BindingException("Element \"save-form\" is missing (" +
                           DomHelper.getLocation(element) + ")");
                   }
  -                saveScript = JavaScriptHelper.buildScript(saveElem);
  +                saveScript = JavaScriptHelper.buildFunction(saveElem, JavaScriptJXPathBinding.SAVE_PARAMS);
  +            }
  +            
  +            // Build child bindings
  +            Map childBindings;
  +            Element[] children = DomHelper.getChildElements(element, BindingManager.NAMESPACE, "child-binding");
  +            if (children.length == 0) {
  +            		childBindings = Collections.EMPTY_MAP;
  +            } else {
  +            		childBindings = new HashMap();
  +            		for (int i = 0; i < children.length; i++) {
  +            			Element child = children[i];
  +            			
  +            			// Get the binding name and check its uniqueness
  +            			String name = DomHelper.getAttribute(child, "name");
  +            			if (childBindings.containsKey(name)) {
  +            				throw new BindingException("Duplicate name '" + name + "' at " + DomHelper.getLocation(child));
  +            			}
  +            			
  +            			// Build the child binding
  +            			JXPathBindingBase[] bindings = assistant.makeChildBindings(child);
  +            			if (bindings == null) {
  +            				bindings = new JXPathBindingBase[0];
  +            			}
  +            			
  +            			ComposedJXPathBindingBase composedBinding = new ComposedJXPathBindingBase(commonAtts, bindings);
  +            			composedBinding.enableLogging(getLogger());
  +            			childBindings.put(name, composedBinding);
  +            		}
               }
   
  -            return new JavaScriptJXPathBinding(commonAtts, id, path, loadScript, saveScript);
  +            JXPathBindingBase result = new JavaScriptJXPathBinding(this.avalonContext, commonAtts, id, path, loadScript, saveScript,
  +            		Collections.unmodifiableMap(childBindings));
  +            result.enableLogging(getLogger());
  +            return result;
   
  +        } catch(BindingException be) {
  +        	    throw be;
           } catch(Exception e) {
               throw new BindingException("Cannot build binding at " + DomHelper.getLocation(element), e);
           }
  
  
  
  1.4       +2 -1      cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/SimpleRepeaterJXPathBinding.java
  
  Index: SimpleRepeaterJXPathBinding.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/SimpleRepeaterJXPathBinding.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SimpleRepeaterJXPathBinding.java	23 Apr 2004 11:42:58 -0000	1.3
  +++ SimpleRepeaterJXPathBinding.java	15 Jun 2004 07:33:43 -0000	1.4
  @@ -52,6 +52,7 @@
           this.repeaterPath = repeaterPath;
           this.rowPath = rowPath;
           this.rowBinding = rowBinding;
  +        this.rowBinding.setParent(this);
           this.clearOnLoad = clearOnLoad;
           this.deleteIfEmpty = deleteIfEmpty;
       }
  
  
  
  1.2       +27 -6     cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/event/WidgetEventMulticaster.java
  
  Index: WidgetEventMulticaster.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/event/WidgetEventMulticaster.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- WidgetEventMulticaster.java	9 Mar 2004 10:33:45 -0000	1.1
  +++ WidgetEventMulticaster.java	15 Jun 2004 07:33:43 -0000	1.2
  @@ -32,6 +32,23 @@
           super(a, b);
       }
       
  +    //-- Create ---------------------------------------------------------------
  +    
  +    public static CreateListener add(CreateListener a, CreateListener b) {
  +        return (CreateListener)addInternal(a, b);
  +    }
  +    
  +    public static CreateListener remove(CreateListener l, CreateListener oldl) {
  +        return (CreateListener)removeInternal(l, oldl);
  +    }
  +    
  +    public void widgetCreated(CreateEvent e) {
  +        ((CreateListener)a).widgetCreated(e);
  +        ((CreateListener)b).widgetCreated(e);
  +    }
  +
  +    //-- Action ---------------------------------------------------------------
  +
       public static ActionListener add(ActionListener a, ActionListener b) {
           return (ActionListener)addInternal(a, b);
       }
  @@ -45,6 +62,8 @@
           ((ActionListener)b).actionPerformed(e);
       }
   
  +    //-- ValueChanged ---------------------------------------------------------
  +
       public static ValueChangedListener add(ValueChangedListener a, ValueChangedListener b) {
           return (ValueChangedListener)addInternal(a, b);
       }
  @@ -53,6 +72,13 @@
           return (ValueChangedListener)removeInternal(l, oldl);
       }
       
  +    public void valueChanged(ValueChangedEvent e) {
  +        ((ValueChangedListener)a).valueChanged(e);
  +        ((ValueChangedListener)b).valueChanged(e);
  +    }
  +    
  +    //-- ProcessingPhase ------------------------------------------------------
  +
       public void phaseEnded(ProcessingPhaseEvent e) {
           ((ProcessingPhaseListener)a).phaseEnded(e);
           ((ProcessingPhaseListener)b).phaseEnded(e);
  @@ -64,11 +90,6 @@
       
       public static ProcessingPhaseListener remove(ProcessingPhaseListener l, ProcessingPhaseListener oldl) {
           return (ProcessingPhaseListener)removeInternal(l, oldl);
  -    }
  -    
  -    public void valueChanged(ValueChangedEvent e) {
  -        ((ValueChangedListener)a).valueChanged(e);
  -        ((ValueChangedListener)b).valueChanged(e);
       }
       
       /**
  
  
  
  1.1                  cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/event/CreateEvent.java
  
  Index: CreateEvent.java
  ===================================================================
  /*
   * Copyright 1999-2004 The Apache Software Foundation.
   * 
   * Licensed 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.event;
  
  import org.apache.cocoon.forms.formmodel.Widget;
  
  /**
   * <b>Early prototype of a create event. Don't use it now as the plumbing is not yet ready! (SW)</b>
   * An event raised when a widget is created, once it has been fully set up. For
   * container widgets, this occurs after child widgets, if any, have been created.
   * 
   * @version CVS $Id: CreateEvent.java,v 1.1 2004/06/15 07:33:43 sylvain Exp $
   */
  public class CreateEvent extends WidgetEvent {
      
      public CreateEvent(Widget source) {
          super(source);
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/event/CreateListener.java
  
  Index: CreateListener.java
  ===================================================================
  /*
   * Copyright 1999-2004 The Apache Software Foundation.
   * 
   * Licensed 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.event;
  
  /**
   * Listeners for {@link CreateEvent}s
   * 
   * @version CVS $Id: CreateListener.java,v 1.1 2004/06/15 07:33:43 sylvain Exp $
   */
  
  public interface CreateListener extends WidgetListener {
      void widgetCreated(CreateEvent event);
  }
  
  
  
  1.5       +14 -1     cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/event/impl/JavaScriptWidgetListener.java
  
  Index: JavaScriptWidgetListener.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/event/impl/JavaScriptWidgetListener.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- JavaScriptWidgetListener.java	27 Apr 2004 12:02:13 -0000	1.4
  +++ JavaScriptWidgetListener.java	15 Jun 2004 07:33:43 -0000	1.5
  @@ -24,6 +24,8 @@
   import org.apache.cocoon.components.flow.FlowHelper;
   import org.apache.cocoon.forms.event.ActionEvent;
   import org.apache.cocoon.forms.event.ActionListener;
  +import org.apache.cocoon.forms.event.CreateEvent;
  +import org.apache.cocoon.forms.event.CreateListener;
   import org.apache.cocoon.forms.event.ValueChangedEvent;
   import org.apache.cocoon.forms.event.ValueChangedListener;
   import org.apache.cocoon.forms.event.WidgetEvent;
  @@ -91,6 +93,17 @@
           }
   
           public void valueChanged(ValueChangedEvent event) {
  +            super.callScript(event);
  +        }
  +    }
  +    
  +    public static class JSCreateListener extends JavaScriptWidgetListener implements CreateListener {
  +
  +        public JSCreateListener(Script script, Context context) {
  +            super(script, context);
  +        }
  +
  +        public void widgetCreated(CreateEvent event) {
               super.callScript(event);
           }
       }
  
  
  
  1.3       +6 -3      cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/event/impl/JavaScriptWidgetListenerBuilder.java
  
  Index: JavaScriptWidgetListenerBuilder.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/event/impl/JavaScriptWidgetListenerBuilder.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- JavaScriptWidgetListenerBuilder.java	27 Apr 2004 12:02:13 -0000	1.2
  +++ JavaScriptWidgetListenerBuilder.java	15 Jun 2004 07:33:43 -0000	1.3
  @@ -16,6 +16,7 @@
   package org.apache.cocoon.forms.event.impl;
   
   import org.apache.cocoon.forms.event.ActionListener;
  +import org.apache.cocoon.forms.event.CreateListener;
   import org.apache.cocoon.forms.event.ValueChangedListener;
   import org.apache.cocoon.forms.event.WidgetListener;
   import org.apache.cocoon.forms.event.WidgetListenerBuilder;
  @@ -32,10 +33,10 @@
    * <p>
    * The syntax for this listener is as follows :
    * <pre>
  - *   &lt;javascript&gt;
  + *   &lt;fd:javascript&gt;
    *     var widget = event.sourceWidget;
    *     sourceWidget.setValue("Yeah");
  - *   &lt;/javascript&gt;
  + *   &lt;/fd:javascript&gt;
    * </pre>
    * As shown above, the event that fired this listener is published as the <code>event</code>
    * variable.
  @@ -57,6 +58,8 @@
   
           if (listenerClass == ActionListener.class) {
               return new JavaScriptWidgetListener.JSActionListener(script, context);
  +        } else if (listenerClass == CreateListener.class) {
  +            return new JavaScriptWidgetListener.JSCreateListener(script, context);
           } else if (listenerClass == ValueChangedListener.class) {
               return new JavaScriptWidgetListener.JSValueChangedListener(script, context);
           } else {
  
  
  
  1.18      +5 -3      cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/flow/javascript/Form.js
  
  Index: Form.js
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/flow/javascript/Form.js,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- Form.js	9 Jun 2004 13:50:43 -0000	1.17
  +++ Form.js	15 Jun 2004 07:33:44 -0000	1.18
  @@ -39,6 +39,8 @@
           this.form = formMgr.createForm(src);
           this.binding = null;
           this.eventHandler = null;
  +        // FIXME : hack needed because FOM doesn't provide access to the context
  +        this.avalonContext = formMgr.getAvalonContext();
           // TODO : do we keep this ?
           this.formWidget = new Widget(this.form);
   
  @@ -121,8 +123,8 @@
   
           // Prematurely add the bizData as in the object model so that event listeners can use it
           // (the same is done by cocoon.sendPage())
  -        // FIXME: hack because object model isn't available in flowscript.
  -        var objectModel = org.apache.cocoon.environment.internal.EnvironmentHelper.getCurrentEnvironment().getObjectModel();
  +        // FIXME : hack needed because FOM doesn't provide access to the object model
  +        var objectModel = org.apache.cocoon.components.ContextHelper.getObjectModel(this.avalonContext);
           org.apache.cocoon.components.flow.FlowHelper.setContextObject(objectModel, bizData);
   
           finished = this.form.process(formContext);
  
  
  
  1.7       +16 -1     cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinition.java
  
  Index: AbstractWidgetDefinition.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinition.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- AbstractWidgetDefinition.java	29 Apr 2004 08:46:19 -0000	1.6
  +++ AbstractWidgetDefinition.java	15 Jun 2004 07:33:44 -0000	1.7
  @@ -21,6 +21,9 @@
   import java.util.Map;
   
   import org.apache.cocoon.forms.Constants;
  +import org.apache.cocoon.forms.event.CreateEvent;
  +import org.apache.cocoon.forms.event.CreateListener;
  +import org.apache.cocoon.forms.event.WidgetEventMulticaster;
   import org.apache.cocoon.forms.validation.WidgetValidator;
   import org.apache.cocoon.xml.XMLUtils;
   import org.apache.excalibur.xml.sax.XMLizable;
  @@ -41,6 +44,8 @@
       private String id;
       private Map displayData;
       private List validators;
  +    
  +    protected CreateListener createListener;
   
       public FormDefinition getFormDefinition() {
           if (this.formDefinition == null) {
  @@ -82,6 +87,16 @@
   
       protected void setId(String id) {
           this.id = id;
  +    }
  +    
  +    protected void addCreateListener(CreateListener listener) {
  +    		this.createListener = WidgetEventMulticaster.add(this.createListener, listener);
  +    }
  +    
  +    public void fireCreateEvent(CreateEvent event) {
  +        if (this.createListener != null) {
  +        	    this.createListener.widgetCreated(event);
  +        }
       }
   
       public void generateLabel(ContentHandler contentHandler) throws SAXException {
  
  
  
  1.4       +11 -1     cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinitionBuilder.java
  
  Index: AbstractWidgetDefinitionBuilder.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinitionBuilder.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- AbstractWidgetDefinitionBuilder.java	27 Apr 2004 12:02:13 -0000	1.3
  +++ AbstractWidgetDefinitionBuilder.java	15 Jun 2004 07:33:44 -0000	1.4
  @@ -18,6 +18,7 @@
   import java.util.ArrayList;
   import java.util.Collections;
   import java.util.HashMap;
  +import java.util.Iterator;
   import java.util.List;
   import java.util.Map;
   
  @@ -29,6 +30,8 @@
   import org.apache.avalon.framework.service.Serviceable;
   import org.apache.cocoon.forms.Constants;
   import org.apache.cocoon.forms.datatype.DatatypeManager;
  +import org.apache.cocoon.forms.event.CreateListener;
  +import org.apache.cocoon.forms.event.ValueChangedListener;
   import org.apache.cocoon.forms.event.WidgetListener;
   import org.apache.cocoon.forms.event.WidgetListenerBuilder;
   import org.apache.cocoon.forms.expression.ExpressionManager;
  @@ -151,6 +154,13 @@
                       widgetValidatorBuilderSelector.release(builder);
                   }
               }
  +        }
  +    }
  +    
  +    protected void setCreateListeners(Element widgetElement, AbstractWidgetDefinition widgetDefinition) throws Exception {
  +        Iterator iter = buildEventListeners(widgetElement, "on-create", CreateListener.class).iterator();
  +        while (iter.hasNext()) {
  +            widgetDefinition.addCreateListener((CreateListener)iter.next());
           }
       }
   
  
  
  
  1.2       +6 -1      cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/FieldDefinition.java
  
  Index: FieldDefinition.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/FieldDefinition.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- FieldDefinition.java	9 Mar 2004 10:33:50 -0000	1.1
  +++ FieldDefinition.java	15 Jun 2004 07:33:44 -0000	1.2
  @@ -15,6 +15,8 @@
    */
   package org.apache.cocoon.forms.formmodel;
   
  +import org.apache.cocoon.forms.event.CreateEvent;
  +
   /**
    * The {@link WidgetDefinition} part of a Field widget, see {@link Field} for more information.
    * 
  @@ -25,6 +27,9 @@
   
       public Widget createInstance() {
           Field field = new Field(this);
  +        if (this.createListener != null) {
  +            this.createListener.widgetCreated(new CreateEvent(field));
  +        }
           return field;
       }
   
  
  
  
  1.4       +2 -1      cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/FieldDefinitionBuilder.java
  
  Index: FieldDefinitionBuilder.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/FieldDefinitionBuilder.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- FieldDefinitionBuilder.java	17 Mar 2004 15:37:58 -0000	1.3
  +++ FieldDefinitionBuilder.java	15 Jun 2004 07:33:44 -0000	1.4
  @@ -59,6 +59,7 @@
   
           setDisplayData(widgetElement, fieldDefinition);
           setValidators(widgetElement, fieldDefinition);
  +        setCreateListeners(widgetElement, fieldDefinition);
   
           boolean required = DomHelper.getAttributeAsBoolean(widgetElement, "required", false);
           fieldDefinition.setRequired(required);
  
  
  
  1.3       +8 -3      cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/util/SimpleServiceSelector.java
  
  Index: SimpleServiceSelector.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/util/SimpleServiceSelector.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SimpleServiceSelector.java	15 Apr 2004 18:09:03 -0000	1.2
  +++ SimpleServiceSelector.java	15 Jun 2004 07:33:44 -0000	1.3
  @@ -79,8 +79,13 @@
               Object component = null;
               try {
                   component = clazz.newInstance();
  -                LifecycleHelper lifecycleHelper = new LifecycleHelper(getLogger(), context, serviceManager, null, componentConfs[i]);
  -                lifecycleHelper.setupComponent(component);
  +                LifecycleHelper.setupComponent(
  +                		component,
  +					getLogger(),
  +					context,
  +					serviceManager,
  +					null, // RoleManager
  +					componentConfs[i]);
               } catch (Exception e) {
                   throw new ConfigurationException("Error creating " + hintShortHand + " declared at " + componentConfs[i].getLocation(), e);
               }