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/26 03:03:16 UTC

svn commit: r240158 - in /cocoon/gsoc/mpfingsthorn/forms: WEB-INF/xconf/ java/org/apache/cocoon/forms/binding/ java/org/apache/cocoon/forms/binding/library/ java/org/apache/cocoon/forms/formmodel/library/ samples/library/forms/ samples/library/libraries/

Author: mpfingsthorn
Date: Thu Aug 25 18:02:36 2005
New Revision: 240158

URL: http://svn.apache.org/viewcvs?rev=240158&view=rev
Log:
Binding import/library works for now for class bindings. Next is inheritance (some stuff already there) and expansion of non-class bindings from the library. See form1 binding for an example so far.

Added:
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/BindingBuilderContext.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ImportJXPathBinding.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ImportJXPathBindingBuilder.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/Library.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryException.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryManager.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryManagerImpl.java
    cocoon/gsoc/mpfingsthorn/forms/samples/library/libraries/library_form1_binding.xml   (with props)
Modified:
    cocoon/gsoc/mpfingsthorn/forms/WEB-INF/xconf/cocoon-forms.xconf
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/AbstractCustomBinding.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/Binding.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ComposedJXPathBindingBase.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingManager.java
    cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/Library.java
    cocoon/gsoc/mpfingsthorn/forms/samples/library/forms/form1_binding.xml

Modified: cocoon/gsoc/mpfingsthorn/forms/WEB-INF/xconf/cocoon-forms.xconf
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/WEB-INF/xconf/cocoon-forms.xconf?rev=240158&r1=240157&r2=240158&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/WEB-INF/xconf/cocoon-forms.xconf (original)
+++ cocoon/gsoc/mpfingsthorn/forms/WEB-INF/xconf/cocoon-forms.xconf Thu Aug 25 18:02:36 2005
@@ -25,6 +25,7 @@
 
   <forms-binding logger="forms.binding">
     <bindings>
+      <binding name="import" src="org.apache.cocoon.forms.binding.ImportJXPathBindingBuilder"/>
       <binding name="group" src="org.apache.cocoon.forms.binding.GroupJXPathBindingBuilder"/>
       <binding name="value" src="org.apache.cocoon.forms.binding.ValueJXPathBindingBuilder"/>
       <binding name="multi-value" src="org.apache.cocoon.forms.binding.MultiValueJXPathBindingBuilder"/>

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/AbstractCustomBinding.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/AbstractCustomBinding.java?rev=240158&r1=240157&r2=240158&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/AbstractCustomBinding.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/AbstractCustomBinding.java Thu Aug 25 18:02:36 2005
@@ -15,6 +15,7 @@
  */
 package org.apache.cocoon.forms.binding;
 
+import org.apache.cocoon.forms.binding.library.Library;
 import org.apache.cocoon.forms.formmodel.Widget;
 import org.apache.commons.jxpath.JXPathContext;
 
@@ -43,8 +44,14 @@
         return this.parent.getClass(id);        
     }
     //TODO: end of stuff to clean out over time
-    //below is the real usefull stuff...
+    //below is the real useful stuff...
     
+    public boolean isValid() {
+    	return false; // pessimistic
+    }
+    public Library getLocalLibrary() {
+    	return null;
+    }
     
     /**
      * Binding service method called upon loading.

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/Binding.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/Binding.java?rev=240158&r1=240157&r2=240158&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/Binding.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/Binding.java Thu Aug 25 18:02:36 2005
@@ -15,6 +15,7 @@
  */
 package org.apache.cocoon.forms.binding;
 
+import org.apache.cocoon.forms.binding.library.Library;
 import org.apache.cocoon.forms.formmodel.Widget;
 
 /**
@@ -36,6 +37,16 @@
      * Gets binding definition id.
      */
     String getId();
+    
+    /**
+     * returns the local library for this tree of bindings
+     */
+    Library getLocalLibrary();
+    
+    /**
+     * checks for deep validity of this binding tree (taking into accound included libraries)
+     */
+    boolean isValid();
 
     /**
      * Gets a binding class.

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/BindingBuilderContext.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/BindingBuilderContext.java?rev=240158&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/BindingBuilderContext.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/BindingBuilderContext.java Thu Aug 25 18:02:36 2005
@@ -0,0 +1,50 @@
+/*
+ * 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.binding;
+
+import org.apache.cocoon.forms.binding.library.Library;
+
+/**
+ * @author Max Pfingsthorn (mpfingsthorn@hippo.nl)
+ *
+ */
+public class BindingBuilderContext {
+
+	private Library localLibrary = null;
+	private Binding superBinding = null;
+	
+	public BindingBuilderContext(BindingBuilderContext other) {
+		this.localLibrary = other.localLibrary;
+		this.superBinding = other.superBinding;
+	}
+	public BindingBuilderContext() {
+		this.localLibrary = null;
+		this.superBinding = null;
+	}
+	
+	public Library getLocalLibrary() {
+		return localLibrary;
+	}
+	public void setLocalLibrary(Library lib) {
+		this.localLibrary = lib;
+	}
+	public Binding getSuperBinding() {
+		return superBinding;
+	}
+	public void setSuperBinding(Binding binding) {
+		this.superBinding = binding;
+	}
+}

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ComposedJXPathBindingBase.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ComposedJXPathBindingBase.java?rev=240158&r1=240157&r2=240158&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ComposedJXPathBindingBase.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ComposedJXPathBindingBase.java Thu Aug 25 18:02:36 2005
@@ -16,6 +16,7 @@
 package org.apache.cocoon.forms.binding;
 
 import java.util.HashMap;
+import java.util.HashSet;
 
 import org.apache.avalon.framework.logger.Logger;
 import org.apache.cocoon.forms.formmodel.Widget;
@@ -30,6 +31,31 @@
  */
 public class ComposedJXPathBindingBase extends JXPathBindingBase {
     private final JXPathBindingBase[] subBindings;
+    
+    
+    public static JXPathBindingBase[] mergeBindings(JXPathBindingBase[] one, JXPathBindingBase[] two) throws Exception {
+    	
+    	if(one == null || one.length == 0)
+    		return two;
+    	
+    	if(two == null || two.length == 0)
+    		return one;
+    	
+    	HashSet ids = new HashSet();
+    	JXPathBindingBase[] merged = new JXPathBindingBase[one.length + two.length];
+    	for(int i=0; i<one.length; i++) {
+    		merged[i] = one[i];
+    		ids.add(one[i].getId());
+    	}
+    	for(int i=0; i<two.length; i++) {
+    		
+    		if(two[i].getId()!=null && ids.contains(two[i].getId()))
+    			throw new Exception("Duplicate ID's detected!");
+    			
+    		merged[one.length +i] = two[i];
+    	}
+    	return merged;
+    }
 
     /**
      * Constructs ComposedJXPathBindingBase

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ImportJXPathBinding.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ImportJXPathBinding.java?rev=240158&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ImportJXPathBinding.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ImportJXPathBinding.java Thu Aug 25 18:02:36 2005
@@ -0,0 +1,51 @@
+/*
+ * 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.binding;
+
+import org.apache.cocoon.forms.formmodel.Widget;
+import org.apache.commons.jxpath.JXPathContext;
+
+/**
+ * Dummy class cause bindings work with stupid arrays instead of lists. Can't affort null entries there.
+ * 
+ * @author Max Pfingsthorn (mpfingsthorn@hippo.nl)
+ *
+ */
+public class ImportJXPathBinding extends JXPathBindingBase {
+
+	public ImportJXPathBinding() {
+		super(JXPathBindingBuilderBase.CommonAttributes.DEFAULT);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.apache.cocoon.forms.binding.JXPathBindingBase#doLoad(org.apache.cocoon.forms.formmodel.Widget, org.apache.commons.jxpath.JXPathContext)
+	 */
+	public void doLoad(Widget frmModel, JXPathContext jxpc)
+			throws BindingException {
+		// dont do anything
+
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.cocoon.forms.binding.JXPathBindingBase#doSave(org.apache.cocoon.forms.formmodel.Widget, org.apache.commons.jxpath.JXPathContext)
+	 */
+	public void doSave(Widget frmModel, JXPathContext jxpc)
+			throws BindingException {
+//		 dont do anything
+
+	}
+
+}

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ImportJXPathBindingBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ImportJXPathBindingBuilder.java?rev=240158&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ImportJXPathBindingBuilder.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/ImportJXPathBindingBuilder.java Thu Aug 25 18:02:36 2005
@@ -0,0 +1,53 @@
+/*
+ * 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.binding;
+
+import org.apache.cocoon.forms.binding.JXPathBindingManager.Assistant;
+import org.apache.cocoon.forms.binding.library.Library;
+import org.apache.cocoon.forms.binding.library.LibraryException;
+import org.apache.cocoon.forms.util.DomHelper;
+import org.w3c.dom.Element;
+
+/**
+ * @author Max Pfingsthorn (mpfingsthorn@hippo.nl)
+ *
+ */
+public class ImportJXPathBindingBuilder extends JXPathBindingBuilderBase {
+
+	/* (non-Javadoc)
+	 * @see org.apache.cocoon.forms.binding.JXPathBindingBuilderBase#buildBinding(org.w3c.dom.Element, org.apache.cocoon.forms.binding.JXPathBindingManager.Assistant)
+	 */
+	public JXPathBindingBase buildBinding(Element bindingElm,
+			Assistant assistant) throws BindingException {
+
+		Library lib = assistant.getContext().getLocalLibrary();
+		
+		String prefix = bindingElm.getAttribute("prefix");
+		String uri = bindingElm.getAttribute("uri");
+		
+		if(prefix==null || uri==null)
+			throw new BindingException("Import needs to specify both @uri and @prefix! (at "+DomHelper.getLocation(bindingElm)+")");
+		
+		try {
+			lib.includeAs(prefix,uri);
+		} catch(LibraryException e) {
+			throw new BindingException("Could not import library !(at "+DomHelper.getLocation(bindingElm)+")",e);
+		}
+		
+		return new ImportJXPathBinding();
+	}
+
+}

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java?rev=240158&r1=240157&r2=240158&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBase.java Thu Aug 25 18:02:36 2005
@@ -22,6 +22,10 @@
 
 import org.apache.avalon.framework.logger.LogEnabled;
 import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.cocoon.forms.binding.library.Library;
 import org.apache.cocoon.forms.formmodel.Widget;
 import org.apache.cocoon.util.jxpath.DOMFactory;
 import org.apache.commons.jxpath.JXPathContext;
@@ -42,7 +46,12 @@
      * Avalon Logger to use in all subclasses.
      */
     private Logger logger;
-
+    
+    /**
+     * the local library, if this is the top binding
+     */
+    private Library localLibrary = null;
+    
     /**
      * Object holding the values of the common objects on all Bindings.
      */
@@ -66,7 +75,37 @@
             JXPathBindingBuilderBase.CommonAttributes commonAtts) {
         this.commonAtts = commonAtts;
     }
-
+    
+    public Library getLocalLibrary() {
+    	if(parent != null) {
+    		return parent.getLocalLibrary();
+    	} else {
+    		return localLibrary;
+    	}
+    }
+    public void setLocalLibary(Library lib) {
+    	this.localLibrary = lib;
+    }
+    
+    public boolean isValid() {
+    	if(this.localLibrary!=null) {
+    		if(parent!=null)
+    			return parent.isValid();
+    		return true; // no library used
+    	} else {
+    		try {
+    			return !this.localLibrary.dependenciesHaveChanged();
+    		} catch(Exception e) {
+    			logger.error("Error checking dependencies!",e);
+    			throw new RuntimeException("Error checking dependencies!",e);
+    		}
+    	}
+    }
+    
+    public JXPathBindingBuilderBase.CommonAttributes getCommonAtts() {
+    	return this.commonAtts;
+    }
+    
     /**
      * Gets source location of this binding.
      */
@@ -89,7 +128,14 @@
     }
 
     public Binding getClass(String id) {
-        Binding classBinding = null;
+    	
+    	Binding classBinding = null;
+    	
+    	try {
+    		if(this.localLibrary!=null && (classBinding = this.localLibrary.getBinding(id))!=null)
+    			return classBinding;
+    	} catch(Exception ignore) {}
+        
         if (classes != null) {
             // Query cache for class
             classBinding = (Binding)classes.get(id);
@@ -98,11 +144,14 @@
             // Query parent for class
             if (parent != null) {
                 classBinding = parent.getClass(id);
+                // dont cache, doesn't matter and makes things complicated with libraries
+                // **************************************
                 // Cache result
-                if (classes == null) {
+                /*if (classes == null) {
                     classes = new HashMap();
                 }
-                classes.put(id, classBinding);
+                classes.put(id, classBinding);*/
+                // **************************************
             } else {
                 throw new RuntimeException("Class \"" + id + "\" not found (" + getLocation() + ")");
             }

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java?rev=240158&r1=240157&r2=240158&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingBuilderBase.java Thu Aug 25 18:02:36 2005
@@ -19,6 +19,11 @@
 
 import org.apache.avalon.framework.logger.LogEnabled;
 import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.cocoon.forms.binding.library.Library;
+import org.apache.cocoon.forms.binding.library.LibraryManager;
 import org.apache.cocoon.forms.util.DomHelper;
 import org.apache.commons.lang.BooleanUtils;
 import org.w3c.dom.Element;
@@ -50,6 +55,7 @@
             logger.debug("JXPathBindingBuilderBase got logger...");
         }
     }
+    
 
     /**
      * Makes the logger available to the subclasses.
@@ -207,5 +213,6 @@
         private static Boolean decideLeniency(String leniency) {
             return BooleanUtils.toBooleanObject(leniency);
         }
+        
     }
 }

Modified: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingManager.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingManager.java?rev=240158&r1=240157&r2=240158&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingManager.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/JXPathBindingManager.java Thu Aug 25 18:02:36 2005
@@ -15,6 +15,8 @@
  */
 package org.apache.cocoon.forms.binding;
 
+import java.util.Stack;
+
 import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.activity.Initializable;
 import org.apache.avalon.framework.configuration.Configurable;
@@ -30,6 +32,10 @@
 import org.apache.avalon.framework.thread.ThreadSafe;
 import org.apache.cocoon.components.LifecycleHelper;
 import org.apache.cocoon.forms.CacheManager;
+import org.apache.cocoon.forms.binding.library.Library;
+import org.apache.cocoon.forms.binding.library.LibraryException;
+import org.apache.cocoon.forms.binding.library.LibraryManager;
+import org.apache.cocoon.forms.binding.library.LibraryManagerImpl;
 import org.apache.cocoon.forms.datatype.DatatypeManager;
 import org.apache.cocoon.forms.util.DomHelper;
 import org.apache.cocoon.forms.util.SimpleServiceSelector;
@@ -63,6 +69,8 @@
     private CacheManager cacheManager;
 
 	private Context avalonContext;
+	
+	private LibraryManagerImpl libraryManager;
 
 	public void contextualize(Context context) throws ContextException {
 		this.avalonContext = context;
@@ -87,10 +95,22 @@
                                        this.avalonContext,
                                        this.manager,
                                        configuration.getChild("bindings"));
+        
+        libraryManager = new LibraryManagerImpl();
+        libraryManager.setAssistant(getBuilderAssistant());
+        LifecycleHelper.setupComponent(libraryManager,
+        								getLogger(),
+        								this.avalonContext,
+        								this.manager,
+        								configuration.getChild("library"));
     }
 
     public Binding createBinding(Source source) throws BindingException {
         Binding binding = (Binding) this.cacheManager.get(source, PREFIX);
+        
+        if (binding != null && !binding.isValid())
+        	binding = null; //invalidate
+        
         if (binding == null) {
             try {
                 InputSource is = new InputSource(source.getInputStream());
@@ -177,7 +197,10 @@
      */
     public class Assistant {
 
-        private JXPathBindingBuilderBase getBindingBuilder(String bindingType)
+    	private BindingBuilderContext context = new BindingBuilderContext();
+    	private Stack contextStack = new Stack();
+    	
+    	private JXPathBindingBuilderBase getBindingBuilder(String bindingType)
                 throws BindingException {
             try {
                 return (JXPathBindingBuilderBase) bindingBuilderSelector
@@ -197,7 +220,28 @@
                 Element configElm) throws BindingException {
             String bindingType = configElm.getLocalName();
             JXPathBindingBuilderBase bindingBuilder = getBindingBuilder(bindingType);
+            
+            boolean flag = false;
+            if(context.getLocalLibrary() == null) {
+            	Library lib = new Library(libraryManager);
+            	context.setLocalLibrary(lib);
+            	flag = true;
+            	System.out.println("Set local library on "+context+" to "+lib);
+            }
+            
             JXPathBindingBase childBinding = bindingBuilder.buildBinding(configElm, this);
+            
+            if(flag && childBinding != null) {
+            	childBinding.setLocalLibary(context.getLocalLibrary());
+            }
+            
+            // this might get called unnecessarily, but solves issues with the libraries
+            if(childBinding != null)
+            	childBinding.enableLogging(getLogger());
+            	
+            System.out.println("made new binding! "+configElm.getLocalName());
+            
+            
             return childBinding;
         }
 
@@ -213,7 +257,22 @@
                 if (childElements.length > 0) {
                     JXPathBindingBase[] childBindings = new JXPathBindingBase[childElements.length];
                     for (int i = 0; i < childElements.length; i++) {
+                    	
+                    	pushContext();
+                    	
+                    	if(context.getLocalLibrary()!=null && childElements[i].getAttribute("extends")!=null) {
+                    		try {
+                    			context.setSuperBinding(context.getLocalLibrary().getBinding(childElements[i].getAttribute("extends")));
+                    		} catch(LibraryException e) {
+                    			throw new RuntimeException("Error extending binding! (at "+DomHelper.getLocation(childElements[i])+")",e);
+                    		}
+                    	} else {
+                    		context.setSuperBinding(null);
+                    	}
+                    	
                         childBindings[i] = getBindingForConfigurationElement(childElements[i]);
+                        
+                        popContext();
                     }
                     return childBindings;
                 }
@@ -228,5 +287,26 @@
         public ServiceManager getServiceManager() {
             return manager;
         }
+        
+        public LibraryManager getLibraryManager() {
+        	return libraryManager;
+        }
+        
+        public BindingBuilderContext getContext() {
+        	return this.context;
+        }
+        private void pushContext() {
+        	BindingBuilderContext c = new BindingBuilderContext(context);
+        	contextStack.push(context);
+        	context = c;
+        }
+        private void popContext() {
+        	if(!contextStack.empty()) {
+        		context = (BindingBuilderContext)contextStack.pop();
+        	} else {
+        		context = new BindingBuilderContext();
+        	}
+        }
+        
     }
 }

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/Library.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/Library.java?rev=240158&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/Library.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/Library.java Thu Aug 25 18:02:36 2005
@@ -0,0 +1,189 @@
+/*
+ * 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.binding.library;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.forms.Constants;
+import org.apache.cocoon.forms.binding.Binding;
+import org.apache.cocoon.forms.binding.BindingManager;
+import org.apache.cocoon.forms.binding.JXPathBindingManager;
+import org.apache.cocoon.forms.util.DomHelper;
+
+import org.w3c.dom.Element;
+
+/**
+ * @author Max Pfingsthorn (mpfingsthorn@hippo.nl)
+ *
+ */
+public class Library {
+
+	public static final String SEPARATOR = ":";
+	
+	// own references
+	protected LibraryManager manager = null;
+	
+	// own instances
+	protected Map definitions = new HashMap();
+	protected Map inclusions = new HashMap();
+	
+	// shared object with dependencies
+	protected Object shared = new Object();
+	
+	protected JXPathBindingManager.Assistant assistant = null;
+	
+	public Library(ServiceManager sm) {
+		try {
+			manager = (LibraryManager)sm.lookup(LibraryManager.ROLE);
+		} catch(ServiceException e) {
+			throw new RuntimeException("Could not initialize Library, LibraryManager not found!",e);
+		}
+	}
+	
+	public Library(LibraryManager lm) {
+		manager = lm;
+	}
+	
+	public void setAssistant(JXPathBindingManager.Assistant assistant) {
+		this.assistant = assistant;
+	}
+	
+	public boolean dependenciesHaveChanged() throws Exception {
+		
+		Iterator it = this.inclusions.values().iterator();
+		while(it.hasNext()) {
+			Dependency dep = (Dependency)it.next();
+			if(!dep.isValid())
+				return true;
+		}
+		
+		return false;
+	}
+	
+	/**
+	 * "Registers" a library to be referenced later under a certain key or prefix.
+	 * Definitions will be accessible locally through prefixing: "prefix:definitionid"
+	 * 
+	 * @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,new Dependency(librarysource));
+				return true;
+			}
+			return false;
+		} catch(Exception e) {
+			throw new LibraryException("Could not include library '"+librarysource+"'",e);
+		}
+		
+	}
+	
+	public Binding getBinding(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(((Dependency)inclusions.get(librarykey)).sourceURI).getBinding(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 (Binding)definitions.get(definitionkey);
+		}
+	}
+	
+	public void buildLibrary(Element libraryElement) throws Exception {
+		this.assistant.getContext().setLocalLibrary(this);
+        Element[] bindingElements = DomHelper.getChildElements(libraryElement, BindingManager.NAMESPACE);
+        for (int i = 0; i < bindingElements.length; i++) {
+            Element bindingElement = bindingElements[i];
+            Binding  binding = this.assistant.getBindingForConfigurationElement(bindingElement);
+            addBinding(binding);
+        }
+	}
+	
+	public void addBinding(Binding binding) throws LibraryException {
+		if(definitions.containsKey(binding.getId()))
+			throw new LibraryException("Library already contains a binding with this ID!");
+		
+		definitions.put(binding.getId(),binding);
+		manager.debug(this+": Put binding with id: "+binding.getId());
+	}
+	
+	
+	/**
+	 * Encapsulates a uri to designate an import plus a timestamp so previously reloaded 
+	 * 
+	 * @author Max Pfingsthorn (mpfingsthorn@hippo.nl)
+	 *
+	 */
+	public class Dependency {
+		
+		private String sourceURI;
+		private Object shared;
+		
+		public Dependency(String sourceURI) throws Exception {
+			this.sourceURI = sourceURI;
+			
+			Library lib = manager.getLibrary(sourceURI);
+			this.shared = lib.shared;
+		}
+		
+		public boolean isValid() throws LibraryException {
+			try {
+				
+				if(manager.libraryInCache(sourceURI)) {
+					Library lib = manager.getLibrary(sourceURI);
+					
+					if(this.shared == lib.shared)
+						return true;
+				}
+				
+				return false;
+			} catch(Exception forward) {
+				throw new LibraryException("Exception occured while checking dependency validity!",forward);
+			}
+			
+		}
+	}
+	
+}

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryException.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryException.java?rev=240158&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryException.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryException.java Thu Aug 25 18:02:36 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.binding.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/binding/library/LibraryManager.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryManager.java?rev=240158&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryManager.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryManager.java Thu Aug 25 18:02:36 2005
@@ -0,0 +1,38 @@
+/*
+ * 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.binding.library;
+
+
+
+/**
+ * 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 = LibraryManager.class.getName();
+	
+	Library getLibrary(String librarysource) throws Exception;
+	Library getNewLibrary();
+	
+	boolean libraryInCache(String librarysource) throws Exception;
+	
+	void debug(String msg);
+}

Added: cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryManagerImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryManagerImpl.java?rev=240158&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryManagerImpl.java (added)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/binding/library/LibraryManagerImpl.java Thu Aug 25 18:02:36 2005
@@ -0,0 +1,192 @@
+/*
+ * 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.binding.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.ServiceSelector;
+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.binding.JXPathBindingManager;
+import org.apache.cocoon.forms.formmodel.WidgetDefinitionBuilder;
+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 = "CocoonFormBindingLibrary:";
+	
+	private ServiceManager serviceManager;
+    private Configuration configuration;
+    private CacheManager cacheManager;
+    
+    private JXPathBindingManager.Assistant assistant;
+
+    public void configure(Configuration configuration) throws ConfigurationException {
+        this.configuration = configuration;
+        getLogger().debug("Gotten a config: top level element: "+this.configuration);
+    }
+
+    public void service(ServiceManager serviceManager) throws ServiceException {
+        this.serviceManager = serviceManager;
+        this.cacheManager = (CacheManager)serviceManager.lookup(CacheManager.ROLE);
+    }
+    
+    public void setAssistant(JXPathBindingManager.Assistant assistant) {
+    	this.assistant = assistant;
+    }
+    
+    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;
+            	this.cacheManager.set(null,source,PREFIX); //evict?
+            }
+            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 = getNewLibrary();
+                    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 Library getNewLibrary() {
+		Library lib = new Library(this);
+		lib.setAssistant(this.assistant);
+        
+        if(getLogger().isDebugEnabled())
+        	getLogger().debug("Created new library! "+lib);
+        
+        return lib;
+	}
+
+	public void dispose() {
+		this.serviceManager.release(this.cacheManager);
+	    this.cacheManager = null;
+	    this.serviceManager = null;
+	}
+	
+	public void debug(String msg) {
+		if(getLogger().isDebugEnabled()) {
+			getLogger().debug(msg);
+		}
+	}
+	
+}

Modified: 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=240158&r1=240157&r2=240158&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/Library.java (original)
+++ cocoon/gsoc/mpfingsthorn/forms/java/org/apache/cocoon/forms/formmodel/library/Library.java Thu Aug 25 18:02:36 2005
@@ -49,9 +49,6 @@
 	protected Map definitions = new HashMap();
 	protected Map inclusions = new HashMap();
 	
-	// my uri
-	protected String source = null;
-	
 	// shared object with dependencies
 	protected Object shared = new Object();
 	
@@ -61,14 +58,6 @@
 		manager = lm;
 		context = new WidgetDefinitionBuilderContext();
 		context.setLocalLibrary(this);
-	}
-	
-	void setSource(String source) {
-		this.source = source;
-	}
-	
-	public String toString() {
-		return getClass().getName()+":"+source;
 	}
 	
 	public void setWidgetDefinitionBuilderSelector(ServiceSelector selector) {

Modified: cocoon/gsoc/mpfingsthorn/forms/samples/library/forms/form1_binding.xml
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/samples/library/forms/form1_binding.xml?rev=240158&r1=240157&r2=240158&view=diff
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/samples/library/forms/form1_binding.xml (original)
+++ cocoon/gsoc/mpfingsthorn/forms/samples/library/forms/form1_binding.xml Thu Aug 25 18:02:36 2005
@@ -19,7 +19,10 @@
   xmlns:fd="http://apache.org/cocoon/forms/1.0#definition" 
   path="/data" >
   
-  <fb:value id="field1" path="field1"/>
+  <fb:import prefix="lib" uri="libraries/library_form1_binding.xml"/>
+  
+  <fb:new id="lib:class1"/>
+  
   <fb:value id="field2" path="field2"/>
   <fb:value id="field3" path="field3"/>
   

Added: cocoon/gsoc/mpfingsthorn/forms/samples/library/libraries/library_form1_binding.xml
URL: http://svn.apache.org/viewcvs/cocoon/gsoc/mpfingsthorn/forms/samples/library/libraries/library_form1_binding.xml?rev=240158&view=auto
==============================================================================
--- cocoon/gsoc/mpfingsthorn/forms/samples/library/libraries/library_form1_binding.xml (added)
+++ cocoon/gsoc/mpfingsthorn/forms/samples/library/libraries/library_form1_binding.xml Thu Aug 25 18:02:36 2005
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<fb:library
+  xmlns:fb="http://apache.org/cocoon/forms/1.0#binding" 
+  xmlns:fd="http://apache.org/cocoon/forms/1.0#definition" 
+  >
+  
+  <fb:class id="class1">
+    <fb:value id="field1" path="field1"/>
+  </fb:class>
+  
+</fb:library>
\ No newline at end of file

Propchange: cocoon/gsoc/mpfingsthorn/forms/samples/library/libraries/library_form1_binding.xml
------------------------------------------------------------------------------
    svn:eol-style = native