You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by mp...@apache.org on 2005/08/21 01:49:06 UTC

svn commit: r234135 - in /cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms: event/ formmodel/ formmodel/library/

Author: mpfingsthorn
Date: Sat Aug 20 16:48:27 2005
New Revision: 234135

URL: http://svn.apache.org/viewcvs?rev=234135&view=rev
Log:
Some code cleanup and extra definition completeness
check call path for partial definitions (needed for
inheritance later)

Added:
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractContainerDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/IncompletenessException.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/Library.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryException.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryManager.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryManagerImpl.java
Modified:
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/event/WidgetEventMulticaster.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractContainerDefinition.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractDatatypeWidgetDefinition.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractDatatypeWidgetDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinition.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinition.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/ButtonDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/CaptchaDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/ClassDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FieldDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FormDefinition.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FormDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/GroupDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MessagesDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MultiValueFieldDefinition.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MultiValueFieldDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/NewDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/RepeaterDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/StructDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UnionDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UploadDefinition.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UploadDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinition.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinitionBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinitionList.java

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/event/WidgetEventMulticaster.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/event/WidgetEventMulticaster.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/event/WidgetEventMulticaster.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/event/WidgetEventMulticaster.java Sat Aug 20 16:48:27 2005
@@ -25,6 +25,8 @@
  * Convenience class to handle all widget event listeners. See
  * <code>java.awt.AWTEventMulticaster</code> for more information on its use.
  * 
+ * Daisy-chains event listeners in a linked-list manner.
+ * 
  * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
  * @version $Id: WidgetEventMulticaster.java 190962 2005-06-16 17:17:00Z sylvain $
  */

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractContainerDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractContainerDefinition.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractContainerDefinition.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractContainerDefinition.java Sat Aug 20 16:48:27 2005
@@ -16,6 +16,7 @@
 package org.apache.cocoon.forms.formmodel;
 
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -37,6 +38,23 @@
 
     public void createWidgets(Widget parent) {
         definitions.createWidgets(parent);
+    }
+    
+    /**
+     * checks completeness of this definition
+     */
+    public void checkCompleteness() throws IncompletenessException {
+    	super.checkCompleteness();
+    	
+    	if(this.definitions.size()==0)
+    		throw new IncompletenessException(this.getClass().getName()+" requires at least one child widget!",this);
+    	
+    	// now check children's completeness
+    	List defs = definitions.getWidgetDefinitions();
+    	Iterator it = defs.iterator();
+    	while(it.hasNext()) {
+    		((WidgetDefinition)it.next()).checkCompleteness();
+    	}
     }
 
     public void addWidgetDefinition(WidgetDefinition definition) throws Exception, DuplicateIdException {

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractContainerDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractContainerDefinitionBuilder.java?rev=234135&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractContainerDefinitionBuilder.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractContainerDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -0,0 +1,26 @@
+package org.apache.cocoon.forms.formmodel;
+
+import org.apache.cocoon.forms.Constants;
+import org.apache.cocoon.forms.util.DomHelper;
+import org.w3c.dom.Element;
+
+
+
+public abstract class AbstractContainerDefinitionBuilder extends
+		AbstractWidgetDefinitionBuilder {
+
+	protected void setupContainer(Element element, String widgetsElementName, AbstractContainerDefinition definition) throws Exception {
+        
+		Element widgetsElement = DomHelper.getChildElement(element, Constants.DEFINITION_NS, widgetsElementName, true);
+        // All child elements of the widgets element are widgets
+        Element[] widgetElements = DomHelper.getChildElements(widgetsElement, Constants.DEFINITION_NS);
+        if(widgetElements!=null)
+        for (int i = 0; i < widgetElements.length; i++) {
+            Element widgetElement = widgetElements[i];
+            WidgetDefinition widgetDefinition = buildAnotherWidgetDefinition(widgetElement);
+            definition.addWidgetDefinition(widgetDefinition);
+        }
+        
+    }
+
+}

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractDatatypeWidgetDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractDatatypeWidgetDefinition.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractDatatypeWidgetDefinition.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractDatatypeWidgetDefinition.java Sat Aug 20 16:48:27 2005
@@ -42,6 +42,18 @@
         checkMutable();
         this.manager = manager;
     }
+    
+    /**
+     * checks 
+     * @return
+     */
+    public void checkCompleteness() throws IncompletenessException {
+    	super.checkCompleteness();
+    	
+    	if(this.datatype==null)
+    		throw new IncompletenessException("A datatype element is required!",this);
+    	
+    }
 
     public Datatype getDatatype() {
         return datatype;

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractDatatypeWidgetDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractDatatypeWidgetDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractDatatypeWidgetDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractDatatypeWidgetDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -49,29 +49,28 @@
         
         //---- parse "datatype"
         Element datatypeElement = DomHelper.getChildElement(widgetElement, Constants.DEFINITION_NS, "datatype");
-        if (datatypeElement == null) {
-            throw new Exception("A nested datatype element is required for the widget " 
-                                + widgetElement.getTagName() + " at " + DomHelper.getLocation(widgetElement));
-        }
-
-        Datatype datatype = datatypeManager.createDatatype(datatypeElement, false);
-        
-        //---- parse "initial-value"
-        Object initialValue = null;
-        Element initialValueElement = DomHelper.getChildElement(widgetElement, Constants.DEFINITION_NS, "initial-value", false);
-        if (initialValueElement != null) {
-            String localeValue = DomHelper.getAttribute(initialValueElement, "locale", null);
-            Locale locale = localeValue == null ? null : I18nUtils.parseLocale(localeValue);
-            String value = DomHelper.getElementText(initialValueElement);
-            ConversionResult result = datatype.convertFromString(value, locale);
-            if (!result.isSuccessful()) {
-                throw new Exception("Cannot parse initial value '" + value + "' at " +
-                        DomHelper.getLocation(initialValueElement));
+        if (datatypeElement != null) {
+        	Datatype datatype = datatypeManager.createDatatype(datatypeElement, false);
+        	
+        	// ---- parse "initial-value"
+            Object initialValue = null;
+            Element initialValueElement = DomHelper.getChildElement(widgetElement, Constants.DEFINITION_NS, "initial-value", false);
+            if (initialValueElement != null) {
+                String localeValue = DomHelper.getAttribute(initialValueElement, "locale", null);
+                Locale locale = localeValue == null ? null : I18nUtils.parseLocale(localeValue);
+                String value = DomHelper.getElementText(initialValueElement);
+                ConversionResult result = datatype.convertFromString(value, locale);
+                if (!result.isSuccessful()) {
+                    throw new Exception("Cannot parse initial value '" + value + "' at " +
+                            DomHelper.getLocation(initialValueElement));
+                }
+                initialValue = result.getResult();
             }
-            initialValue = result.getResult();
+            
+            definition.setDatatype(datatype, initialValue);
         }
         
-        definition.setDatatype(datatype, initialValue);
+        
         
         //---- parse "selection-list"
         // FIXME: pass the manager to the definition as a side effect. Should be removed

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinition.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinition.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinition.java Sat Aug 20 16:48:27 2005
@@ -41,13 +41,13 @@
 
     //TODO consider final on these
     private String location = null;
-    private String id;
+    private String id = null;
     /** the definition is mutable when being built */
     private boolean mutable = true;
     /** The initial map of attributes (can be null) */
-    private Map attributes;
-    private Map displayData;
-    private List validators;
+    private Map attributes = null;
+    private Map displayData = null;
+    private List validators = null;
     private WidgetState state = WidgetState.ACTIVE;
 
     protected CreateListener createListener;
@@ -64,6 +64,19 @@
     }
     
     /**
+     * Checks if this definition is complete or not.
+     */
+    public void checkCompleteness() throws IncompletenessException
+    {
+    	// FormDefinition is the only one allowed not to have an ID
+    	if( (id==null || "".equals(id) && !(this instanceof FormDefinition) ))
+    		throw new IncompletenessException("Widget found without an ID! "+this,this);
+    	
+    	
+    	// TODO: don't know what else to check now
+    }
+    
+    /**
      * Locks this definition so that it becomes immutable.
      */
     public void makeImmutable() {
@@ -125,7 +138,22 @@
 
     protected void setAttributes(Map attributes) {
         checkMutable();
-        this.attributes = attributes;   
+        //this.attributes = attributes;
+        if(this.attributes==null) {
+        	this.attributes = attributes;
+        	return;
+        }
+        if(attributes==null)
+        	return;
+        
+        // merge attribute lists
+        Iterator entries = attributes.entrySet().iterator();
+        while(entries.hasNext()) {
+        	Map.Entry entry = (Map.Entry)entries.next();
+        	Object key = entry.getKey();
+        	Object value = entry.getValue();
+        	this.attributes.put(key,value);
+        }
     }
     
     public Object getAttribute(String name) {
@@ -137,6 +165,7 @@
 
     protected void addCreateListener(CreateListener listener) {
         checkMutable();
+        // Event listener daisy-chain
         this.createListener = WidgetEventMulticaster.add(this.createListener, listener);
     }
     
@@ -169,7 +198,24 @@
      */
     public void setDisplayData(Map displayData) {
         checkMutable();
-        this.displayData = displayData;
+        //this.displayData = displayData;
+        
+        if(this.displayData==null) {
+        	this.displayData = displayData;
+        	return;
+        }
+        if(displayData==null)
+        	return;
+        
+        // merge displayData lists
+        Iterator entries = displayData.entrySet().iterator();
+        while(entries.hasNext()) {
+        	Map.Entry entry = (Map.Entry)entries.next();
+        	Object key = entry.getKey();
+        	Object value = entry.getValue();
+        	if(value!=null || !this.displayData.containsKey(key))
+        		this.displayData.put(key,value);
+        }
     }
 
     public void addValidator(WidgetValidator validator) {

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -34,6 +34,7 @@
 import org.apache.cocoon.forms.event.WidgetListener;
 import org.apache.cocoon.forms.event.WidgetListenerBuilder;
 import org.apache.cocoon.forms.expression.ExpressionManager;
+import org.apache.cocoon.forms.formmodel.library.Library;
 import org.apache.cocoon.forms.util.DomHelper;
 import org.apache.cocoon.forms.validation.WidgetValidatorBuilder;
 import org.apache.excalibur.xml.sax.XMLizable;
@@ -54,6 +55,15 @@
     protected DatatypeManager datatypeManager;
     protected ExpressionManager expressionManager;
     protected ServiceManager serviceManager;
+    
+    protected Library library = null;
+    
+    public WidgetDefinition buildWidgetDefinition(Element widgetElement, Library localLibrary) throws Exception {
+    	this.library =  localLibrary;
+    	WidgetDefinition def = buildWidgetDefinition(widgetElement);
+    	this.library = null;
+    	return def;
+    }
 
     public void service(ServiceManager serviceManager) throws ServiceException {
         this.serviceManager = serviceManager;
@@ -73,7 +83,7 @@
     private void setCommonProperties(Element widgetElement, AbstractWidgetDefinition widgetDefinition) throws Exception {
         // location
         widgetDefinition.setLocation(DomHelper.getLocation(widgetElement));
-
+        
         // id
         if (widgetDefinition instanceof FormDefinition) {
             // FormDefinition is the *only* kind of widget that has an optional id

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinition.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinition.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinition.java Sat Aug 20 16:48:27 2005
@@ -21,8 +21,10 @@
 import org.outerj.expression.Expression;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
 /**
  * The {@link WidgetDefinition} part of a AggregateField widget, see {@link AggregateField} for more information.
@@ -58,6 +60,11 @@
      * a group (paren) from the regular expression and corresponding field id.
      */
     private List splitMappings = new ArrayList();
+    
+    /**
+     * Set containing widgets mapped to groups to find out if a specific widget has been mapped already
+     */
+    private Set mappedFields = new HashSet();
 
     /**
      *
@@ -69,6 +76,32 @@
         checkMutable();
         container.addWidgetDefinition(widgetDefinition);
     }
+    
+    /**
+     * checks completeness of this definition
+     */
+    public void checkCompleteness() throws IncompletenessException {
+    	super.checkCompleteness();
+    	
+    	if(this.container.size()==0)
+    		throw new IncompletenessException("AggregateField doesn't have any child widgets!",this);
+    	
+    	if(this.combineExpr==null)
+    		throw new IncompletenessException("AggregateField requires a combine expression!",this);
+    	
+    	if(this.splitPattern==null)
+    		throw new IncompletenessException("AggregateField requires a split regular expression!",this);
+    	
+    	if(this.splitMappings.size()==0)
+    		throw new IncompletenessException("AggregateField requires at least one group to field mapping!",this);
+    	
+    	// now check children's completeness
+    	List defs = container.getWidgetDefinitions();
+    	Iterator it = defs.iterator();
+    	while(it.hasNext()) {
+    		((WidgetDefinition)it.next()).checkCompleteness();
+    	}
+    }
 
     public boolean hasWidget(String id) {
         return container.hasWidget(id);
@@ -108,6 +141,12 @@
 
     protected void addSplitMapping(int group, String fieldId) {
         checkMutable();
+        
+        if(mappedFields.contains(fieldId))
+        	throw new RuntimeException("Field '"+fieldId+"' is already mapped to another group!");
+        
+        mappedFields.add(fieldId);
+        
         splitMappings.add(new SplitMapping(group, fieldId));
     }
 

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -15,8 +15,6 @@
  */
 package org.apache.cocoon.forms.formmodel;
 
-import java.util.HashSet;
-
 import org.apache.cocoon.forms.Constants;
 import org.apache.cocoon.forms.util.DomHelper;
 import org.apache.excalibur.xml.sax.XMLizable;
@@ -51,37 +49,42 @@
         for (int i = 0; i < fieldElements.length; i++) {
             FieldDefinition fieldDefinition = (FieldDefinition)buildAnotherWidgetDefinition(fieldElements[i]);
             definition.addWidgetDefinition(fieldDefinition);
+            System.out.println("Aggregate: addWidget: "+fieldDefinition.getId());
         }
 
         // compile splitpattern
         Element splitElement = DomHelper.getChildElement(widgetElement, Constants.DEFINITION_NS, "split", true);
-        String patternString = DomHelper.getAttribute(splitElement, "pattern");
-        Perl5Compiler compiler = new Perl5Compiler();
-        Pattern pattern = null;
-        try {
-            pattern = compiler.compile(patternString, Perl5Compiler.READ_ONLY_MASK);
-        } catch (MalformedPatternException e) {
-            throw new Exception("Invalid regular expression at " + DomHelper.getLocation(splitElement) + ": " + e.getMessage());
+        if(splitElement!=null) {
+	        String patternString = DomHelper.getAttribute(splitElement, "pattern");
+	        Perl5Compiler compiler = new Perl5Compiler();
+	        Pattern pattern = null;
+	        try {
+	            pattern = compiler.compile(patternString, Perl5Compiler.READ_ONLY_MASK);
+	        } catch (MalformedPatternException e) {
+	            throw new Exception("Invalid regular expression at " + DomHelper.getLocation(splitElement) + ": " + e.getMessage());
+	        }
+	        definition.setSplitPattern(pattern, patternString);
+	        System.out.println("Aggregate: setSplitPattern("+patternString+")");
         }
-        definition.setSplitPattern(pattern, patternString);
 
         // read split mappings
         Element[] mapElements = DomHelper.getChildElements(splitElement, Constants.DEFINITION_NS, "map");
-        HashSet encounteredFieldMappings = new HashSet();
         for (int i = 0; i < mapElements.length; i++) {
             int group = DomHelper.getAttributeAsInteger(mapElements[i], "group");
             String field = DomHelper.getAttribute(mapElements[i], "field");
             // check that this field exists
             if (!definition.hasWidget(field)) {
-                throw new Exception("Unkwon widget id \"" + field + "\", at " +
+                throw new Exception("Unknown widget id \"" + field + "\", at " +
                                     DomHelper.getLocation(mapElements[i]));
             }
-            if (encounteredFieldMappings.contains(field)) {
-                throw new Exception("Two groups are mapped to the same widget id \"" + field + "\", at " +
-                                    DomHelper.getLocation(mapElements[i]));
+            
+            try {
+            	definition.addSplitMapping(group, field);
+            	System.out.println("Aggregate: addSplitMapping("+group+","+field+")");
+            } catch(RuntimeException e) {
+            	throw new Exception("Two groups are mapped to the same widget id \"" + field + "\", at " +
+                        DomHelper.getLocation(mapElements[i]));
             }
-            encounteredFieldMappings.add(field);
-            definition.addSplitMapping(group, field);
         }
 
         // read split fail message (if any)
@@ -93,19 +96,21 @@
 
         // compile combine expression
         Element combineElement = DomHelper.getChildElement(widgetElement, Constants.DEFINITION_NS, "combine", true);
-        String combineExprString = DomHelper.getAttribute(combineElement, "expression");
-        Expression combineExpr = null;
-        try {
-            combineExpr = expressionManager.parse(combineExprString);
-        } catch (Exception e) {
-            throw new Exception("Problem with combine expression defined at " +
-                                DomHelper.getLocation(combineElement) + ": " + e.getMessage());
-        }
-        Class clazz = definition.getDatatype().getTypeClass();
-        if (combineExpr.getResultType() != null && !clazz.isAssignableFrom(combineExpr.getResultType())) {
-            throw new Exception("The result of the combine expression should be " + clazz.getName() + ", at " +
-                                DomHelper.getLocation(combineElement));
+        if(combineElement!=null) {
+        	String combineExprString = DomHelper.getAttribute(combineElement, "expression");
+            Expression combineExpr = null;
+            try {
+                combineExpr = expressionManager.parse(combineExprString);
+            } catch (Exception e) {
+                throw new Exception("Problem with combine expression defined at " +
+                                    DomHelper.getLocation(combineElement) + ": " + e.getMessage());
+            }
+            Class clazz = definition.getDatatype().getTypeClass();
+            if (combineExpr.getResultType() != null && !clazz.isAssignableFrom(combineExpr.getResultType())) {
+                throw new Exception("The result of the combine expression should be " + clazz.getName() + ", at " +
+                                    DomHelper.getLocation(combineElement));
+            }
+            definition.setCombineExpression(combineExpr);
         }
-        definition.setCombineExpression(combineExpr);
     }
 }

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -32,7 +32,7 @@
         
         BooleanFieldDefinition definition = new BooleanFieldDefinition();
         
-        super.setupDefinition(widgetElement, definition);
+        setupDefinition(widgetElement, definition);
         setDisplayData(widgetElement, definition);
         Iterator iter = buildEventListeners(widgetElement, "on-value-changed", ValueChangedListener.class).iterator();
         while (iter.hasNext()) {

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/ButtonDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/ButtonDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/ButtonDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/ButtonDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -16,6 +16,7 @@
 package org.apache.cocoon.forms.formmodel;
 
 import org.w3c.dom.Element;
+import org.apache.cocoon.forms.formmodel.library.Library;
 import org.apache.cocoon.forms.util.DomHelper;
 
 /**
@@ -25,6 +26,11 @@
  * @version $Id: ButtonDefinitionBuilder.java 56582 2004-11-04 10:16:22Z sylvain $
  */
 public class ButtonDefinitionBuilder implements WidgetDefinitionBuilder {
+	
+	public WidgetDefinition buildWidgetDefinition(Element widgetElement, Library lib) throws Exception {
+		throw new Exception("The button widget has been renamed to action. Please update your form definition files. Found at " + DomHelper.getLocation(widgetElement));
+	}
+	
     public WidgetDefinition buildWidgetDefinition(Element widgetElement) throws Exception {
         throw new Exception("The button widget has been renamed to action. Please update your form definition files. Found at " + DomHelper.getLocation(widgetElement));
     }

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/CaptchaDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/CaptchaDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/CaptchaDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/CaptchaDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -28,7 +28,7 @@
  * @see http://www.captcha.net/
  * @version $Id: CaptchaDefinitionBuilder.java 171293 2005-05-22 08:55:42Z sylvain $
  */
-public class CaptchaDefinitionBuilder extends AbstractDatatypeWidgetDefinitionBuilder implements Contextualizable, ThreadSafe {
+public class CaptchaDefinitionBuilder extends FieldDefinitionBuilder implements Contextualizable, ThreadSafe {
     
     private Context avalonContext;
     
@@ -46,12 +46,9 @@
     protected void setupDefinition(Element widgetElement, FieldDefinition definition) throws Exception {
         super.setupDefinition(widgetElement, definition);
         
-        // parse "@required"
-        boolean required = DomHelper.getAttributeAsBoolean(widgetElement, "required", false);
-        definition.setRequired(required);
-        
         // parse "@length"
         int length = DomHelper.getAttributeAsInteger(widgetElement, "length", 7);
-        ((CaptchaFieldDefinition) definition).setLength(length);
+        if(widgetElement.getAttribute("length")!=null)
+        	((CaptchaFieldDefinition) definition).setLength(length);
     }
 }

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/ClassDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/ClassDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/ClassDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/ClassDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -15,8 +15,6 @@
  */
 package org.apache.cocoon.forms.formmodel;
 
-import org.apache.cocoon.forms.Constants;
-import org.apache.cocoon.forms.util.DomHelper;
 import org.w3c.dom.Element;
 
 /**
@@ -24,7 +22,7 @@
  *
  * @version $Id: ClassDefinitionBuilder.java 155211 2005-02-24 17:05:51Z sylvain $
  */
-public final class ClassDefinitionBuilder extends AbstractWidgetDefinitionBuilder {
+public final class ClassDefinitionBuilder extends AbstractContainerDefinitionBuilder {
 
     public WidgetDefinition buildWidgetDefinition(Element element) throws Exception {
         ClassDefinition definition = new ClassDefinition();
@@ -32,14 +30,7 @@
         super.setupDefinition(element, definition);
         setDisplayData(element, definition);
 
-        Element widgetsElement = DomHelper.getChildElement(element, Constants.DEFINITION_NS, "widgets", true);
-        // All child elements of the widgets element are widgets
-        Element[] widgetElements = DomHelper.getChildElements(widgetsElement, Constants.DEFINITION_NS);
-        for (int i = 0; i < widgetElements.length; i++) {
-            Element widgetElement = widgetElements[i];
-            WidgetDefinition widgetDefinition = buildAnotherWidgetDefinition(widgetElement);
-            definition.addWidgetDefinition(widgetDefinition);
-        }
+        setupContainer(element,"widgets",definition);
 
         definition.makeImmutable();
         return definition;

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FieldDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FieldDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FieldDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FieldDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -37,6 +37,7 @@
         
         // parse "@required"
         boolean required = DomHelper.getAttributeAsBoolean(widgetElement, "required", false);
-        definition.setRequired(required);
+        if(widgetElement.getAttribute("required")!=null)
+        	definition.setRequired(required);
     }
 }

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FormDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FormDefinition.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FormDefinition.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FormDefinition.java Sat Aug 20 16:48:27 2005
@@ -38,6 +38,19 @@
         List parents = new ArrayList();
         parents.add(this);
         resolve(parents, this);
+        
+        // TODO: test if this actually gets called!
+        checkCompleteness();
+    }
+    
+    /**
+     * provide a sensible default ID for the form
+     */
+    public String getId() {
+    	if(super.getId()==null)
+    		return "Toplevel Form Widget";
+    	else
+    		return super.getId();
     }
 
     public Widget createInstance() {

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FormDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FormDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FormDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/FormDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -15,8 +15,6 @@
  */
 package org.apache.cocoon.forms.formmodel;
 
-import org.apache.cocoon.forms.Constants;
-import org.apache.cocoon.forms.util.DomHelper;
 import org.w3c.dom.Element;
 
 /**
@@ -24,7 +22,7 @@
  * 
  * @version $Id: FormDefinitionBuilder.java 155211 2005-02-24 17:05:51Z sylvain $
  */
-public final class FormDefinitionBuilder extends AbstractWidgetDefinitionBuilder {
+public final class FormDefinitionBuilder extends AbstractContainerDefinitionBuilder {
 
     public WidgetDefinition buildWidgetDefinition(Element formElement) throws Exception {
         FormDefinition formDefinition = new FormDefinition();
@@ -32,14 +30,7 @@
         super.setupDefinition(formElement, formDefinition);
         setDisplayData(formElement, formDefinition);
 
-        Element widgetsElement = DomHelper.getChildElement(formElement, Constants.DEFINITION_NS, "widgets", true);
-        // All child elements of the widgets element are widgets
-        Element[] widgetElements = DomHelper.getChildElements(widgetsElement, Constants.DEFINITION_NS);
-        for (int i = 0; i < widgetElements.length; i++) {
-            Element widgetElement = widgetElements[i];
-            WidgetDefinition widgetDefinition = buildAnotherWidgetDefinition(widgetElement);
-            formDefinition.addWidgetDefinition(widgetDefinition);
-        }
+        setupContainer(formElement,"widgets",formDefinition);
 
         formDefinition.resolve();
 

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/GroupDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/GroupDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/GroupDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/GroupDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -16,15 +16,13 @@
 package org.apache.cocoon.forms.formmodel;
 
 import org.w3c.dom.Element;
-import org.apache.cocoon.forms.Constants;
-import org.apache.cocoon.forms.util.DomHelper;
 
 /**
  * Builds {GroupDefinition}s.
  *
  * @version $Id: GroupDefinitionBuilder.java 155211 2005-02-24 17:05:51Z sylvain $
  */
-public final class GroupDefinitionBuilder extends AbstractWidgetDefinitionBuilder {
+public final class GroupDefinitionBuilder extends AbstractContainerDefinitionBuilder {
 
     public WidgetDefinition buildWidgetDefinition(Element element) throws Exception {
         GroupDefinition definition = new GroupDefinition();
@@ -32,15 +30,8 @@
         super.setupDefinition(element, definition);
         setDisplayData(element, definition);
 
-        Element widgetsElement = DomHelper.getChildElement(element, Constants.DEFINITION_NS, "widgets", true);
-        // All child elements of the widgets element are widgets
-        Element[] widgetElements = DomHelper.getChildElements(widgetsElement, Constants.DEFINITION_NS);
-        for (int i = 0; i < widgetElements.length; i++) {
-            Element widgetElement = widgetElements[i];
-            WidgetDefinition widgetDefinition = buildAnotherWidgetDefinition(widgetElement);
-            definition.addWidgetDefinition(widgetDefinition);
-        }
-
+        setupContainer(element,"widgets",definition);
+        
         definition.makeImmutable();
         return definition;
     }

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/IncompletenessException.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/IncompletenessException.java?rev=234135&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/IncompletenessException.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/IncompletenessException.java Sat Aug 20 16:48:27 2005
@@ -0,0 +1,27 @@
+package org.apache.cocoon.forms.formmodel;
+
+import org.apache.avalon.framework.CascadingException;
+
+public class IncompletenessException extends CascadingException {
+
+	private WidgetDefinition causingDefinition = null;
+
+	public IncompletenessException(String message, WidgetDefinition incomplete) {
+        super(message);
+        causingDefinition = incomplete;
+    }
+
+    public IncompletenessException(String message, WidgetDefinition incomplete , Exception e) {
+        super(message, e);
+        causingDefinition = incomplete;
+    }
+    
+    public String toString() {
+    	String msg = super.toString();
+    	
+    	if(causingDefinition!=null)
+    		msg += " (Caused by widget '"+causingDefinition.getId()+"', last modified at "+causingDefinition.getLocation()+")";
+    	
+    	return msg;
+    }
+}

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MessagesDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MessagesDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MessagesDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MessagesDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -25,7 +25,7 @@
 public final class MessagesDefinitionBuilder extends AbstractWidgetDefinitionBuilder {
     public WidgetDefinition buildWidgetDefinition(Element widgetElement) throws Exception {
         MessagesDefinition messagesDefinition = new MessagesDefinition();
-        super.setupDefinition(widgetElement, messagesDefinition);
+        setupDefinition(widgetElement, messagesDefinition);
         setDisplayData(widgetElement, messagesDefinition);
         messagesDefinition.makeImmutable();
         return messagesDefinition;

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MultiValueFieldDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MultiValueFieldDefinition.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MultiValueFieldDefinition.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MultiValueFieldDefinition.java Sat Aug 20 16:48:27 2005
@@ -15,6 +15,7 @@
  */
 package org.apache.cocoon.forms.formmodel;
 
+
 /**
  * The {@link WidgetDefinition} part of a MultiValueField widget, see {@link MultiValueField} for more information.
  * 
@@ -24,6 +25,16 @@
     public Widget createInstance() {
         MultiValueField field =  new MultiValueField(this);
         return field;
+    }
+    
+    /**
+     * checks completeness of this definition
+     */
+    public void checkCompleteness() throws IncompletenessException {
+    	super.checkCompleteness();
+    	
+    	if (getSelectionList() == null)
+            throw new IncompletenessException("Error: multivaluefield always require a selectionlist!", this);
     }
     
 	public void setRequired(boolean required) {

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MultiValueFieldDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MultiValueFieldDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MultiValueFieldDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/MultiValueFieldDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -15,7 +15,6 @@
  */
 package org.apache.cocoon.forms.formmodel;
 
-import org.apache.cocoon.forms.util.DomHelper;
 import org.w3c.dom.Element;
 
 /**
@@ -28,9 +27,6 @@
     public WidgetDefinition buildWidgetDefinition(Element widgetElement) throws Exception {
         MultiValueFieldDefinition definition = new MultiValueFieldDefinition();
         setupDefinition(widgetElement, definition);
-        if (definition.getSelectionList() == null)
-            throw new Exception("Error: multivaluefield always require a selectionlist at " +
-                    DomHelper.getLocation(widgetElement));
         definition.makeImmutable();
         return definition;
     }

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/NewDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/NewDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/NewDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/NewDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -26,7 +26,7 @@
 
     public WidgetDefinition buildWidgetDefinition(Element element) throws Exception {
         NewDefinition definition = new NewDefinition();
-        super.setupDefinition(element, definition);
+        setupDefinition(element, definition);
         definition.makeImmutable();
         return definition;
     }

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/RepeaterDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/RepeaterDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/RepeaterDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/RepeaterDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -15,7 +15,6 @@
  */
 package org.apache.cocoon.forms.formmodel;
 
-import org.apache.cocoon.forms.Constants;
 import org.apache.cocoon.forms.util.DomHelper;
 import org.w3c.dom.Element;
 
@@ -24,7 +23,7 @@
  * 
  * @version $Id: RepeaterDefinitionBuilder.java 155211 2005-02-24 17:05:51Z sylvain $
  */
-public final class RepeaterDefinitionBuilder extends AbstractWidgetDefinitionBuilder {
+public final class RepeaterDefinitionBuilder extends AbstractContainerDefinitionBuilder {
 
     public WidgetDefinition buildWidgetDefinition(Element repeaterElement) throws Exception {
         
@@ -34,13 +33,7 @@
         super.setupDefinition(repeaterElement, repeaterDefinition);
         setDisplayData(repeaterElement, repeaterDefinition);
 
-        Element widgetsElement = DomHelper.getChildElement(repeaterElement, Constants.DEFINITION_NS, "widgets", true);
-        // All child elements of the widgets element are widgets
-        Element[] widgetElements = DomHelper.getChildElements(widgetsElement, Constants.DEFINITION_NS);
-        for (int i = 0; i < widgetElements.length; i++) {
-            WidgetDefinition widgetDefinition = buildAnotherWidgetDefinition(widgetElements[i]);
-            repeaterDefinition.addWidgetDefinition(widgetDefinition);
-        }
+        setupContainer(repeaterElement,"widgets",repeaterDefinition);
 
         repeaterDefinition.makeImmutable();
         return repeaterDefinition;

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/StructDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/StructDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/StructDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/StructDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -26,21 +26,14 @@
  * @deprecated replaced by {@link GroupDefinitionBuilder}
  * @version $Id: StructDefinitionBuilder.java 219043 2005-07-14 14:44:06Z cziegeler $
  */
-public class StructDefinitionBuilder extends AbstractWidgetDefinitionBuilder {
+public class StructDefinitionBuilder extends AbstractContainerDefinitionBuilder {
 
     public WidgetDefinition buildWidgetDefinition(Element element) throws Exception {
         StructDefinition definition = new StructDefinition();
         super.setupDefinition(element, definition);
         setDisplayData(element, definition);
 
-        Element widgetsElement = DomHelper.getChildElement(element, Constants.DEFINITION_NS, "widgets", true);
-        // All child elements of the widgets element are widgets
-        Element[] widgetElements = DomHelper.getChildElements(widgetsElement, Constants.DEFINITION_NS);
-        for (int i = 0; i < widgetElements.length; i++) {
-            Element widgetElement = widgetElements[i];
-            WidgetDefinition widgetDefinition = buildAnotherWidgetDefinition(widgetElement);
-            definition.addWidgetDefinition(widgetDefinition);
-        }
+        setupContainer(element,"widgets",definition);
 
         definition.makeImmutable();
         Deprecation.logger.info("Use of 'fd:struct' is deprecated. Use 'fd:group' instead, at " + definition.getLocation());

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UnionDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UnionDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UnionDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UnionDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -15,7 +15,6 @@
  */
 package org.apache.cocoon.forms.formmodel;
 
-import org.apache.cocoon.forms.Constants;
 import org.apache.cocoon.forms.util.DomHelper;
 import org.w3c.dom.Element;
 
@@ -24,7 +23,7 @@
  *
  * @version $Id: UnionDefinitionBuilder.java 155211 2005-02-24 17:05:51Z sylvain $
  */
-public final class UnionDefinitionBuilder extends AbstractWidgetDefinitionBuilder {
+public final class UnionDefinitionBuilder extends AbstractContainerDefinitionBuilder {
 
     public WidgetDefinition buildWidgetDefinition(Element element) throws Exception {
         UnionDefinition definition = new UnionDefinition();
@@ -32,14 +31,7 @@
         definition.setCaseWidgetId(DomHelper.getAttribute(element, "case", ""));
         setDisplayData(element, definition);
 
-        Element widgetsElement = DomHelper.getChildElement(element, Constants.DEFINITION_NS, "widgets", true);
-        // All child elements of the widgets element are widgets
-        Element[] widgetElements = DomHelper.getChildElements(widgetsElement, Constants.DEFINITION_NS);
-        for (int i = 0; i < widgetElements.length; i++) {
-            Element widgetElement = widgetElements[i];
-            WidgetDefinition widgetDefinition = buildAnotherWidgetDefinition(widgetElement);
-            definition.addWidgetDefinition(widgetDefinition);
-        }
+        setupContainer(element,"widgets",definition);
 
         definition.makeImmutable();
         return definition;

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UploadDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UploadDefinition.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UploadDefinition.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UploadDefinition.java Sat Aug 20 16:48:27 2005
@@ -26,9 +26,30 @@
     private boolean required;
     private String mimeTypes;
     
+    public UploadDefinition() {
+    	this.mimeTypes = null;
+    	this.required = false;
+    }
+    
     public UploadDefinition(boolean required, String mimeTypes) {
         this.required = required;
         this.mimeTypes = mimeTypes;
+    }
+    
+    public void addMimeTypes(String types) {
+    	if(types != null) {
+    		if(mimeTypes == null)
+    			mimeTypes = types;
+    		else {
+    			if(mimeTypes.length()>0)
+            		mimeTypes += ", ";
+            	mimeTypes += types;
+    		}
+    	}
+    }
+    
+    public void setRequired(boolean required) {
+    	this.required = required;
     }
 
     public Widget createInstance() {

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UploadDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UploadDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UploadDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/UploadDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -31,10 +31,15 @@
         String mimeTypes = DomHelper.getAttribute(widgetElement, "mime-types", null);
         boolean required = DomHelper.getAttributeAsBoolean(widgetElement, "required", false);
         
-        UploadDefinition uploadDefinition = new UploadDefinition(required, mimeTypes);
+        UploadDefinition uploadDefinition = new UploadDefinition();
         super.setupDefinition(widgetElement, uploadDefinition);
 
         setDisplayData(widgetElement, uploadDefinition);
+        
+        if(widgetElement.getAttribute("required")!=null)
+        	uploadDefinition.setRequired(required);
+        
+        uploadDefinition.addMimeTypes(mimeTypes);
 
         uploadDefinition.makeImmutable();
         return uploadDefinition;

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinition.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinition.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinition.java Sat Aug 20 16:48:27 2005
@@ -66,6 +66,13 @@
     boolean validate(Widget widget);
 
     /**
+     * Checks whether this definition is complete since we are allowed to have partial
+     * definitions in libraries. Definitions need to be complete _before_ a call to
+     * createInstance() though.
+     */
+    void checkCompleteness() throws IncompletenessException;
+    
+    /**
      * Creates and returns a widget based on this widget definition.
      */
     Widget createInstance();

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinitionBuilder.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinitionBuilder.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinitionBuilder.java Sat Aug 20 16:48:27 2005
@@ -15,6 +15,7 @@
  */
 package org.apache.cocoon.forms.formmodel;
 
+import org.apache.cocoon.forms.formmodel.library.Library;
 import org.w3c.dom.Element;
 
 /**
@@ -32,4 +33,5 @@
 
     WidgetDefinition buildWidgetDefinition(Element widgetElement) throws Exception;
 
+    WidgetDefinition buildWidgetDefinition(Element widgetElement, Library localLibrary) throws Exception;
 }

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinitionList.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinitionList.java?rev=234135&r1=234134&r2=234135&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinitionList.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/WidgetDefinitionList.java Sat Aug 20 16:48:27 2005
@@ -44,6 +44,10 @@
         this.containerDefinition = definition;
         resolving = false;
     }
+    
+    public int size() {
+    	return widgetDefinitions.size();
+    }
 
     public void addWidgetDefinition(WidgetDefinition widgetDefinition) throws DuplicateIdException {
         String id = widgetDefinition.getId();

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/Library.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/Library.java?rev=234135&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/Library.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/Library.java Sat Aug 20 16:48:27 2005
@@ -0,0 +1,157 @@
+/*
+ * 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.formmodel.library;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.avalon.framework.CascadingException;
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.ServiceSelector;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.cocoon.forms.Constants;
+import org.apache.cocoon.forms.formmodel.WidgetDefinition;
+import org.apache.cocoon.forms.formmodel.WidgetDefinitionBuilder;
+import org.apache.cocoon.forms.util.DomHelper;
+
+import org.w3c.dom.Element;
+
+/**
+ * @author Max Pfingsthorn (mpfingsthorn@hippo.nl)
+ *
+ */
+public class Library implements Serviceable, Disposable {
+
+	public static final String SEPARATOR = ":";
+	
+	protected ServiceManager serviceManager= null;
+	
+	// managed instances
+	protected ServiceSelector widgetDefinitionBuilderSelector;
+	
+	// own references
+	protected LibraryManager manager = null;
+	
+	// own instances
+	protected Map definitions = new HashMap();
+	protected Map inclusions = new HashMap();
+	
+	public Library(LibraryManager lm) {
+		manager = lm;
+	}
+	
+	public void service(ServiceManager manager) throws ServiceException{
+		this.serviceManager = manager;
+		this.widgetDefinitionBuilderSelector = (ServiceSelector) serviceManager.lookup(WidgetDefinitionBuilder.class.getName() + "Selector");
+	}
+	
+	public void dispose() {
+		this.serviceManager.release(this.widgetDefinitionBuilderSelector);
+	}
+	
+	public boolean dependenciesHaveChanged() throws Exception {
+		
+		Iterator it = this.inclusions.values().iterator();
+		while(it.hasNext()) {
+			String source = (String)it.next();
+			if(!this.manager.libraryInCache(source))
+				return true;
+		}
+		
+		return false;
+	}
+	
+	/**
+	 * "registers" a 
+	 * 
+	 * @param key the key 
+	 * @param librarysource the source of the library to be know as "key"
+	 * @return true if there was no such key used before, false otherwise
+	 */
+	public boolean includeAs(String key, String librarysource)
+		throws LibraryException 
+	{
+		try {
+			// library keys may not contain ":"!
+			if( (!inclusions.containsKey(key) || key.indexOf(SEPARATOR)>-1) 
+					&& manager.getLibrary(librarysource)!=null) {
+				inclusions.put(key,librarysource);
+				return true;
+			}
+			return false;
+		} catch(Exception e) {
+			throw new LibraryException("Could not include library '"+librarysource+"'",e);
+		}
+		
+	}
+	
+	public WidgetDefinition getDefinition(String key)
+		throws LibraryException
+	{
+		
+		String librarykey = null;
+		String definitionkey = key;
+		
+		if(key.indexOf(":")>-1) {
+			String[] parts = key.split(SEPARATOR);
+			librarykey = parts[0];
+			definitionkey = parts[1];
+			for(int i=2; i<parts.length; i++) {
+				definitionkey += SEPARATOR+parts[i];
+			}
+		}
+		
+		if(librarykey!=null) {
+			if(inclusions.containsKey(librarykey)) {
+				try {
+					return manager.getLibrary((String)inclusions.get(librarykey)).getDefinition(definitionkey);
+				} catch(Exception e) {
+					throw new LibraryException("Couldn't get Library key='"+librarykey+"' source='"+inclusions.get(librarykey)+"",e);
+				}
+			} else {
+				throw new LibraryException("Library '"+librarykey+"' does not exist! (lookup: '"+key+"')");
+			}
+		} else {
+			return (WidgetDefinition)definitions.get(definitionkey);
+		}
+	}
+	
+	public void buildLibrary(Element libraryElement) throws Exception {
+		Element widgetsElement = DomHelper.getChildElement(libraryElement, Constants.DEFINITION_NS, "widgets", true);
+        // All child elements of the widgets element are widgets
+        Element[] widgetElements = DomHelper.getChildElements(widgetsElement, Constants.DEFINITION_NS);
+        for (int i = 0; i < widgetElements.length; i++) {
+            Element widgetElement = widgetElements[i];
+            WidgetDefinition widgetDefinition = buildWidgetDefinition(widgetElement);
+            definitions.put(widgetDefinition.getId(),widgetDefinition);
+        }
+	}
+	
+	protected WidgetDefinition buildWidgetDefinition(Element widgetDefinition) throws Exception {
+        String widgetName = widgetDefinition.getLocalName();
+        WidgetDefinitionBuilder builder = null;
+        try {
+            builder = (WidgetDefinitionBuilder)widgetDefinitionBuilderSelector.select(widgetName);
+        } catch (ServiceException e) {
+            throw new CascadingException("Unknown kind of widget '" + widgetName + "' at " +
+                                         DomHelper.getLocation(widgetDefinition), e);
+        }
+        return builder.buildWidgetDefinition(widgetDefinition,this);
+    }
+}

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryException.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryException.java?rev=234135&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryException.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryException.java Sat Aug 20 16:48:27 2005
@@ -0,0 +1,34 @@
+/*
+ * 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.formmodel.library;
+
+import org.apache.avalon.framework.CascadingException;
+
+/**
+ * This exception is thrown when something specific to the library system goes wrong.
+ * 
+ * @author Max Pfingsthorn (m.pfingsthorn@hippo.nl)
+ * 
+ */
+public class LibraryException extends CascadingException {
+    public LibraryException(String message) {
+        super(message);
+    }
+
+    public LibraryException(String message, Exception e) {
+        super(message, e);
+    }
+}

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryManager.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryManager.java?rev=234135&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryManager.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryManager.java Sat Aug 20 16:48:27 2005
@@ -0,0 +1,36 @@
+/*
+ * 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.formmodel.library;
+
+import org.apache.cocoon.forms.datatype.DatatypeManager;
+
+
+/**
+ * The work interface for the LibraryManager, the class that
+ * manages all used library definitions so they can be shared between
+ * forms.
+ * 
+ * @author Max Pfingsthorn (mpfingsthorn@hippo.nl)
+ *
+ */
+public interface LibraryManager {
+
+	String ROLE = DatatypeManager.class.getName();
+	
+	Library getLibrary(String librarysource) throws Exception;
+	
+	boolean libraryInCache(String librarysource) throws Exception;
+}

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryManagerImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryManagerImpl.java?rev=234135&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryManagerImpl.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/LibraryManagerImpl.java Sat Aug 20 16:48:27 2005
@@ -0,0 +1,164 @@
+/*
+ * 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.formmodel.library;
+
+import org.apache.avalon.framework.CascadingException;
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.activity.Initializable;
+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.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.forms.CacheManager;
+import org.apache.cocoon.forms.util.DomHelper;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+/**
+ * @author Max Pfingsthorn (mpfingsthorn@hippo.nl)
+ *
+ */
+public class LibraryManagerImpl extends AbstractLogEnabled implements LibraryManager, ThreadSafe, Serviceable,
+Configurable, Initializable, Disposable {
+
+	protected static final String PREFIX = "CocoonFormLibrary:";
+	
+	private ServiceManager serviceManager;
+    private Configuration configuration;
+    private CacheManager cacheManager;
+
+    public void configure(Configuration configuration) throws ConfigurationException {
+        this.configuration = configuration;
+    }
+
+    public void service(ServiceManager serviceManager) throws ServiceException {
+        this.serviceManager = serviceManager;
+        this.cacheManager = (CacheManager)serviceManager.lookup(CacheManager.ROLE);
+    }
+    
+    public void initialize() throws Exception {
+        // read config to "preload" libraries
+    }
+    
+    public boolean libraryInCache(String librarysource) throws Exception {
+    	SourceResolver sourceResolver = null;
+        Source source = null;
+        
+        if(getLogger().isDebugEnabled())
+        	getLogger().debug("Checking if library is in cache: '"+librarysource+"'");
+
+        Library lib = null;
+        boolean result = false;
+        
+        try {
+            sourceResolver = (SourceResolver)serviceManager.lookup(SourceResolver.ROLE);
+            source = sourceResolver.resolveURI(librarysource);
+            
+            lib = (Library)this.cacheManager.get(source, PREFIX);
+            
+            if( lib != null && lib.dependenciesHaveChanged() )
+            	result = false;
+            else if( lib == null )
+            	result = false;
+            else
+            	result = true;
+        } catch(Exception e) {
+        	if(getLogger().isErrorEnabled())
+            	getLogger().error("Problem getting library '"+librarysource+"'!",e);
+        	throw e;
+        } finally {
+            if (source != null)
+                sourceResolver.release(source);
+            if (sourceResolver != null)
+            	serviceManager.release(sourceResolver);
+        }
+
+        if(getLogger().isDebugEnabled()) {
+        	if(result)
+        		getLogger().debug("Library IS in cache : '"+librarysource+"'");
+        	else
+        		getLogger().debug("Library IS NOT in cache : '"+librarysource+"'");
+        }
+        
+        return result;
+    }
+    
+	public Library getLibrary(String librarysource) throws Exception {
+		SourceResolver sourceResolver = null;
+        Source source = null;
+        Document libraryDocument = null;
+
+        Library lib = null;
+        
+        if(getLogger().isDebugEnabled())
+        	getLogger().debug("Getting library instance: '"+librarysource+"'");
+        
+        try {
+            sourceResolver = (SourceResolver)serviceManager.lookup(SourceResolver.ROLE);
+            source = sourceResolver.resolveURI(librarysource);
+            
+            lib = (Library)this.cacheManager.get(source, PREFIX);
+            
+            if( lib != null && lib.dependenciesHaveChanged() ) {
+            	if(getLogger().isDebugEnabled())
+                	getLogger().debug("Library dependencies changed, invalidating!");
+            	
+            	lib = null;
+            }
+            
+            if( lib == null ) {
+            	if(getLogger().isDebugEnabled())
+                	getLogger().debug("Library not in cache, creating!");
+            	
+            	try {
+                    InputSource inputSource = new InputSource(source.getInputStream());
+                    inputSource.setSystemId(source.getURI());
+                    libraryDocument = DomHelper.parse(inputSource, this.serviceManager);
+                    
+                    lib = new Library(this);
+                    lib.service(this.serviceManager);
+                    lib.buildLibrary(libraryDocument.getDocumentElement());
+                    
+                    this.cacheManager.set(lib,source,PREFIX);
+                    
+                } catch (Exception e) {
+                    throw new CascadingException("Could not parse form definition from " +
+                                                 source.getURI(), e);
+                }
+            }
+        } finally {
+            if (source != null)
+                sourceResolver.release(source);
+            if (sourceResolver != null)
+            	serviceManager.release(sourceResolver);
+        }
+
+        return lib;
+	}
+
+	public void dispose() {
+		this.serviceManager.release(this.cacheManager);
+	    this.cacheManager = null;
+	    this.serviceManager = null;
+	}
+	
+}