[jboss-svn-commits] JBL Code SVN: r5984 - in labs/jbossrules/trunk/drools-repository/src: java/org/drools/repository java/org/drools/repository/test node_type_definitions

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Sun Aug 27 17:17:35 EDT 2006


Author: bentruitt
Date: 2006-08-27 17:17:30 -0400 (Sun, 27 Aug 2006)
New Revision: 5984

Added:
   labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/FunctionItem.java
   labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/FunctionItemTestCase.java
   labs/jbossrules/trunk/drools-repository/src/node_type_definitions/function_node_type.cnd
Modified:
   labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RuleItem.java
   labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RulePackageItem.java
   labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RulesRepository.java
   labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/VersionableItem.java
   labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/RulePackageItemTestCase.java
   labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/RulesRepositoryTestCase.java
   labs/jbossrules/trunk/drools-repository/src/node_type_definitions/rulepackage_node_type.cnd
Log:
JBRULES-398 complete.

Added: labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/FunctionItem.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/FunctionItem.java	2006-08-25 20:26:11 UTC (rev 5983)
+++ labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/FunctionItem.java	2006-08-27 21:17:30 UTC (rev 5984)
@@ -0,0 +1,476 @@
+package org.drools.repository;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Value;
+
+import org.apache.log4j.Logger;
+
+/**
+ * The FunctionItem class is used to abstract away the details of the underlying JCR repository.
+ * It is used to pass information about functions stored in the repository.
+ * 
+ * @author btruitt
+ */
+public class FunctionItem extends VersionableItem {
+    private Logger log = Logger.getLogger(FunctionItem.class);    
+    
+    /**
+     * The name of the tag property on the function node type
+     */
+    public static final String TAG_PROPERTY_NAME = "drools:tag_reference";
+    
+    /**
+     * The name of the function node type
+     */
+    public static final String FUNCTION_NODE_TYPE_NAME = "drools:function_node_type";
+    
+    /**
+     * The name of the state property on the function node type
+     */
+    public static final String STATE_PROPERTY_NAME = "drools:state_reference";                 
+    
+    /**
+     * The name of the content property on the function node type
+     */
+    public static final String CONTENT_PROPERTY_NAME = "drools:content";            
+    
+    /**
+     * The name of the function language property on the function node type
+     */
+    public static final String FUNCTION_LANGUAGE_PROPERTY_NAME = "drools:function_language";
+    
+    /**
+     * Constructs a FunctionItem object, setting its node attribute to the specified node.
+     * 
+     * @param rulesRepository the rulesRepository that instantiated this object
+     * @param node the node in the repository that this FunctionItem corresponds to
+     * @throws RulesRepositoryException 
+     */
+    public FunctionItem(RulesRepository rulesRepository, Node node) throws RulesRepositoryException {
+        super(rulesRepository, node);
+        
+        try {
+            //make sure this node is a function node       
+            if(!(this.node.getPrimaryNodeType().getName().equals(FUNCTION_NODE_TYPE_NAME) ||
+                 this.node.getPrimaryNodeType().getName().equals("nt:version"))) {
+                String message = this.node.getName() + " is not a node of type " + FUNCTION_NODE_TYPE_NAME + " nor nt:version. It is a node of type: " + this.node.getPrimaryNodeType().getName();
+                log.error(message);
+                throw new RulesRepositoryException(message);
+            }    
+        }
+        catch(Exception e) {
+            log.error("Caught exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+    
+    /**
+     * returns the content of this object's function node
+     * 
+     * @return the content of this object's function node
+     * @throws RulesRepositoryException
+     */
+    public String getContent() throws RulesRepositoryException {
+        try {                        
+            Node functionNode;
+            if(this.node.getPrimaryNodeType().getName().equals("nt:version")) {
+                functionNode = this.node.getNode("jcr:frozenNode");
+            }
+            else {
+                functionNode = this.node;
+            }
+                        
+            Property data = functionNode.getProperty(CONTENT_PROPERTY_NAME);
+            return data.getValue().getString();
+        }
+        catch(Exception e) {
+            log.error("Caught Exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }                
+    
+    /**
+     * @return the function language of this object's function node
+     * @throws RulesRepositoryException
+     */
+    public String getFunctionLanguage() throws RulesRepositoryException {
+        try {                        
+            Node functionNode;
+            if(this.node.getPrimaryNodeType().getName().equals("nt:version")) {
+                functionNode = this.node.getNode("jcr:frozenNode");
+            }
+            else {
+                functionNode = this.node;
+            }
+                        
+            Property languageProperty = functionNode.getProperty(FUNCTION_LANGUAGE_PROPERTY_NAME);
+            return languageProperty.getValue().getString();
+        }
+        catch(Exception e) {
+            log.error("Caught Exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+    
+    /**
+     * Creates a new version of this object's function node, updating th content for the
+     * function node. 
+     * 
+     * @param newContent the new content for the function
+     * @throws RulesRepositoryException
+     */
+    public void updateContent(String newContent) throws RulesRepositoryException {
+        try {
+            this.node.checkout();
+        }
+        catch(UnsupportedRepositoryOperationException e) {
+            String message = "";
+            try {
+                message = "Error: Caught UnsupportedRepositoryOperationException when attempting to checkout rule: " + this.node.getName() + ". Are you sure your JCR repository supports versioning? ";
+                log.error(message, e);
+            }
+            catch (RepositoryException e1) {
+                log.error("Caught Exception", e);
+                throw new RulesRepositoryException(e1);
+            }
+            throw new RulesRepositoryException(message, e);
+        }
+        catch(Exception e) {
+            log.error("Caught Exception", e);
+            throw new RulesRepositoryException(e);
+        }
+        
+        try {                                    
+            this.node.setProperty(CONTENT_PROPERTY_NAME, newContent);
+            
+            Calendar lastModified = Calendar.getInstance();
+            this.node.setProperty(LAST_MODIFIED_PROPERTY_NAME, lastModified);
+            
+            this.node.getSession().save();
+            
+            this.node.checkin();
+        }
+        catch(Exception e) {
+            log.error("Caught Exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }            
+    
+    /**
+     * Adds the specified tag to this object's function node. Tags are stored as nodes in a tag area of
+     * the repository. If the specified tag does not already have a corresponding node, a node is 
+     * created for it.
+     *  
+     * @param tag the tag to add to the function. functions can have multiple tags
+     * @throws RulesRepositoryException 
+     */
+    public void addTag(String tag) throws RulesRepositoryException {
+        try {
+            //make sure this object's node is the head version
+            if(this.node.getPrimaryNodeType().getName().equals("nt:version")) {
+                String message = "Error. Tags can only be added to the head version of a function node";
+                log.error(message);
+                throw new RulesRepositoryException(message);
+            }                                       
+            
+            CategoryItem tagItem = this.rulesRepository.getOrCreateCategory(tag);
+                                    
+            //now set the tag property of the node
+            Property tagReferenceProperty;
+            int i = 0;
+            Value[] newTagValues = null;
+            try {
+                tagReferenceProperty = this.node.getProperty(TAG_PROPERTY_NAME);
+                Value[] oldTagValues = tagReferenceProperty.getValues();
+                
+                //first, make sure this tag wasn't already there. while we're at it, lets copy the array
+                newTagValues = new Value[oldTagValues.length + 1];                
+                for(i=0; i<oldTagValues.length; i++) {
+                    if(oldTagValues[i].getString().equals(tag)) {
+                        log.info("tag '" + tag + "' already existed for function node: " + this.node.getName());
+                        return;
+                    }
+                    newTagValues[i] = oldTagValues[i];
+                }
+            }
+            catch(PathNotFoundException e) {
+                //the property doesn't exist yet, so create it in the finally block
+                newTagValues = new Value[1];                 
+            }
+            finally {   
+                if(newTagValues != null) {
+                    newTagValues[i] = this.node.getSession().getValueFactory().createValue(tagItem.getNode());
+                    this.node.checkout();
+                    this.node.setProperty(TAG_PROPERTY_NAME, newTagValues);
+                    this.node.getSession().save();
+                    this.node.checkin();
+                }
+                else {
+                    log.error("reached expected path of execution when adding tag '" + tag + "' to functionNode: " + this.node.getName());
+                }
+            }
+        }
+        catch(Exception e) {
+            log.error("Caught exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+
+    /**
+     * Removes the specified tag from this object's function node.
+     * 
+     * @param tag the tag to remove from the node
+     * @throws RulesRepositoryException 
+     */
+    public void removeTag(String tag) throws RulesRepositoryException {
+        //TODO: implement if the removed tag no longer has anyone referencing it, remove the tag (are we sure we want to do this, for versioning's sake?)
+        try {
+            //make sure this object's node is the head version
+            if(this.node.getPrimaryNodeType().getName().equals("nt:version")) {
+                String message = "Error. Tags can only be removed from the head version of a function node";
+                log.error(message);
+                throw new RulesRepositoryException(message);
+            }                                                   
+                                    
+            //now set the tag property of the rule
+            Property tagReferenceProperty;
+            int i = 0;
+            int j = 0;
+            Value[] newTagValues = null;
+            try {
+                tagReferenceProperty = this.node.getProperty(TAG_PROPERTY_NAME);
+                Value[] oldTagValues = tagReferenceProperty.getValues();
+                
+                //see if the tag was even there
+                boolean wasThere = false;
+                for(i=0; i<oldTagValues.length; i++) {
+                    Node tagNode = this.node.getSession().getNodeByUUID(oldTagValues[i].getString());
+                    if(tagNode.getName().equals(tag)) {                                                
+                        wasThere = true;
+                    }
+                }
+                
+                if(wasThere) {
+                    //copy the array, minus the specified tag
+                    newTagValues = new Value[oldTagValues.length + 1];                
+                    for(i=0; i<oldTagValues.length; i++) {
+                        Node tagNode = this.node.getSession().getNodeByUUID(oldTagValues[i].getString());
+                        if(!tagNode.getName().equals(tag)) {                                                         
+                            newTagValues[j] = oldTagValues[i];
+                            j++;
+                        }
+                    }
+                }
+                else {
+                    //TODO: remove the tag if it isn't used by anyone else
+                    return;
+                }
+            }
+            catch(PathNotFoundException e) {
+                //the property doesn't exist yet
+                //TODO: first remove the tag if it isn't used by anyone else
+                return;             
+            }
+            finally {   
+                if(newTagValues != null) {
+                    this.node.checkout();
+                    this.node.setProperty(TAG_PROPERTY_NAME, newTagValues);
+                    this.node.getSession().save();
+                    this.node.checkin();
+                }
+                else {
+                    log.error("reached expected path of execution when removing tag '" + tag + "' from functionNode: " + this.node.getName());
+                }
+            }
+        }
+        catch(Exception e) {
+            log.error("Caught exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+    
+    /**
+     * Gets a list of TagItem objects for this object's function node.
+     * 
+     * @return a list of TagItem objects for each tag on the node. If there are no tags, an empty list. 
+     * @throws RulesRepositoryException
+     */
+    @SuppressWarnings("unchecked")
+    public List getTags() throws RulesRepositoryException {
+        try {                            
+            Node functionNode;
+            if(this.node.getPrimaryNodeType().getName().equals("nt:version")) {
+                functionNode = this.node.getNode("jcr:frozenNode");
+            }
+            else {
+                functionNode = this.node;
+            }
+            
+            List returnList = new ArrayList();
+            try {
+                Property tagReferenceProperty = functionNode.getProperty(TAG_PROPERTY_NAME);
+                Value[] tagValues = tagReferenceProperty.getValues();                
+                for(int i=0; i<tagValues.length; i++) {
+                    Node tagNode = this.node.getSession().getNodeByUUID(tagValues[i].getString());
+                    CategoryItem tagItem = new CategoryItem(this.rulesRepository, tagNode);
+                    returnList.add(tagItem);
+                }
+            }
+            catch(PathNotFoundException e) {
+                //the property doesn't even exist yet, so just return nothing
+            }
+            return returnList;
+        }
+        catch(Exception e) {
+            log.error("Caught exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+    
+    /**
+     * Sets this object's function node's state property to refer to the specified state node
+     * 
+     * @param stateName the name of the state to set the function node to
+     * @throws RulesRepositoryException 
+     */
+    public void setState(String stateName) throws RulesRepositoryException {
+        try {
+            StateItem stateItem = this.rulesRepository.getState(stateName);
+            this.setState(stateItem);
+        }
+        catch(Exception e) {
+            log.error("Caught exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+    
+    /**
+     * Sets this object's function node's state property to refer to the specified StateItem's node
+     * 
+     * @param stateItem the StateItem encapsulating the node to refer to from this object's node's state 
+     *                  property
+     * @throws RulesRepositoryException 
+     */
+    public void setState(StateItem stateItem) throws RulesRepositoryException {
+        try {
+            //make sure this node is a function node
+            if(this.node.getPrimaryNodeType().getName().equals("nt:version")) {
+                String message = "Error. States can only be set for the head version of a function node";
+                log.error(message);
+                throw new RulesRepositoryException(message);
+            } 
+            
+            //now set the state property of the rule                              
+            this.node.checkout();
+            this.node.setProperty(STATE_PROPERTY_NAME, stateItem.getNode());
+            this.node.getSession().save();
+            this.node.checkin();        
+        }
+        catch(Exception e) {
+            log.error("Caught exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+    
+    /**
+     * Gets StateItem object corresponding to the state property of this object's node
+     * 
+     * @return a StateItem object corresponding to the state property of this object's node, or null
+     *         if the state property is not set
+     * @throws RulesRepositoryException
+     */
+    public StateItem getState() throws RulesRepositoryException {
+        try {
+            Property stateProperty = this.node.getProperty(STATE_PROPERTY_NAME);
+            Node stateNode = this.node.getSession().getNodeByUUID(stateProperty.getString());
+            return new StateItem(this.rulesRepository, stateNode);
+        }
+        catch(PathNotFoundException e) {
+            //not set
+            return null;
+        }
+        catch(Exception e) {
+            log.error("Caught exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+
+    /**
+     * Nicely formats the information contained by the node that this object encapsulates
+     */
+    public String toString() {                
+        try {
+            StringBuffer returnString = new StringBuffer();
+            returnString.append("Content of function item named '" + this.getName() + "':\n");
+            returnString.append(this.getContent() + "\n");
+            returnString.append("------\n");
+                        
+            returnString.append("Function Language: " + this.getFunctionLanguage() + "\n");
+            returnString.append("Version Name: " + this.getVersionName() + "\n");
+            returnString.append("------\n");
+            
+            returnString.append("Function state: ");
+            StateItem stateItem = this.getState();
+            if(stateItem != null) {
+                returnString.append(this.getState().getName() + "\n");
+            }
+            else {
+                returnString.append("NO STATE SET FOR THIS NODE\n");
+            }            
+            returnString.append("------\n");
+            
+            returnString.append("Categories:\n");
+            for(Iterator it=this.getTags().iterator(); it.hasNext();) {
+                CategoryItem currentTag = (CategoryItem)it.next();
+                returnString.append(currentTag.getName() + "\n");
+            }
+            returnString.append("--------------\n");
+            return returnString.toString();
+        }
+        catch(Exception e) {         
+            log.error("Caught Exception", e);
+            return null;
+        }
+    }
+        
+    public VersionableItem getPrecedingVersion() throws RulesRepositoryException {
+        try {
+            Node precedingVersionNode = this.getPrecedingVersionNode();
+            if(precedingVersionNode != null) {
+                return new FunctionItem(this.rulesRepository, precedingVersionNode);
+            }
+            else {
+                return null;
+            }
+        }        
+        catch(Exception e) {
+            log.error("Caught exception", e);
+            throw new RulesRepositoryException(e);
+        }               
+    }
+
+    public VersionableItem getSucceedingVersion() throws RulesRepositoryException {
+        try {
+            Node succeedingVersionNode = this.getSucceedingVersionNode();
+            if(succeedingVersionNode != null) {
+                return new FunctionItem(this.rulesRepository, succeedingVersionNode);
+            }
+            else {
+                return null;
+            }
+        }        
+        catch(Exception e) {
+            log.error("Caught exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }           
+}
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RuleItem.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RuleItem.java	2006-08-25 20:26:11 UTC (rev 5983)
+++ labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RuleItem.java	2006-08-27 21:17:30 UTC (rev 5984)
@@ -49,7 +49,7 @@
     public static final String LHS_PROPERTY_NAME = "drools:lhs";
     
     /**
-     * The name of the lhs property on the rule node type
+     * The name of the rhs property on the rule node type
      */
     public static final String RHS_PROPERTY_NAME = "drools:rhs";
     
@@ -63,6 +63,10 @@
      */
     public static final String DATE_EXPIRED_PROPERTY_NAME = "drools:date_expired";                        
     
+    /**
+     * The name of the rule language property on the rule node type
+     */
+    public static final String RULE_LANGUAGE_PROPERTY_NAME = "drools:rule_language";    
     
     /**
      * Constructs a RuleItem object, setting its node attribute to the specified node.
@@ -142,29 +146,6 @@
     }
         
     /**
-     * @return the date the rule node (this version) was last modified
-     * @throws RulesRepositoryException
-     */
-    public Calendar getLastModified() throws RulesRepositoryException {
-        try {                        
-            Node ruleNode;
-            if(this.node.getPrimaryNodeType().getName().equals("nt:version")) {
-                ruleNode = this.node.getNode("jcr:frozenNode");
-            }
-            else {
-                ruleNode = this.node;
-            }
-                        
-            Property lastModifiedProperty = ruleNode.getProperty("drools:last_modified");
-            return lastModifiedProperty.getDate();
-        }
-        catch(Exception e) {
-            log.error("Caught Exception", e);
-            throw new RulesRepositoryException(e);
-        }
-    }
-    
-    /**
      * @return the date the rule becomes effective
      * @throws RulesRepositoryException
      */
@@ -307,7 +288,7 @@
     }
     
     /**
-     * @return the date the rule becomes expired
+     * @return the rule language of this object's rune node
      * @throws RulesRepositoryException
      */
     public String getRuleLanguage() throws RulesRepositoryException {
@@ -320,7 +301,7 @@
                 ruleNode = this.node;
             }
                         
-            Property ruleLanguageProperty = ruleNode.getProperty("drools:rule_language");
+            Property ruleLanguageProperty = ruleNode.getProperty(RULE_LANGUAGE_PROPERTY_NAME);
             return ruleLanguageProperty.getValue().getString();
         }
         catch(Exception e) {

Modified: labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RulePackageItem.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RulePackageItem.java	2006-08-25 20:26:11 UTC (rev 5983)
+++ labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RulePackageItem.java	2006-08-27 21:17:30 UTC (rev 5984)
@@ -1,6 +1,7 @@
 package org.drools.repository;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
 import javax.jcr.Node;
@@ -39,6 +40,12 @@
     public static final String RULE_REFERENCE_PROPERTY_NAME = "drools:rule_reference";
     
     /**
+     * The name of the reference property on the rulepackage_node_type type node that objects of
+     * this type hold a reference to
+     */
+    public static final String FUNCTION_REFERENCE_PROPERTY_NAME = "drools:function_reference";    
+    
+    /**
      * The name of the rule package node type
      */
     public static final String RULE_PACKAGE_TYPE_NAME = "drools:rulepackage_node_type";   
@@ -144,8 +151,86 @@
             throw new RulesRepositoryException(e);
         }
     }
+
+    /**
+     * Adds a function to the rule package node this object represents.  The reference to the 
+     * function node will follow the head version of the specified node.
+     * 
+     * @param functionItem the functionItem corresponding to the node to add to the rule package this
+     *                 object represents
+     * @throws RulesRepositoryException
+     */
+    public void addFunction(FunctionItem functionItem) throws RulesRepositoryException {
+        this.addFunction(functionItem, true);        
+    }
     
     /**
+     * Adds a function to the rule package node this object represents.  The reference to the function
+     * will optionally follow the head version of the specified node or the specific current version.
+     * 
+     * @param functionItem the functionItem corresponding to the node to add to the rule package this 
+     *                 object represents
+     * @param followRuleHead if true, the reference to the function node will follow the head version 
+     *                       of the node, even if new versions are added. If false, will refer 
+     *                       specifically to the current version.
+     * @throws RulesRepositoryException
+     */
+    public void addFunction(FunctionItem functionItem, boolean followFunctionHead) throws RulesRepositoryException {        
+        try {
+            ValueFactory factory = this.node.getSession().getValueFactory();
+            int i = 0;
+            Value[] newValueArray = null;
+            
+            try {
+                Value[] oldValueArray = this.node.getProperty(FUNCTION_REFERENCE_PROPERTY_NAME).getValues();
+                newValueArray = new Value[oldValueArray.length + 1];                
+                
+                for(i=0; i<oldValueArray.length; i++) {
+                    newValueArray[i] = oldValueArray[i];
+                }
+            }
+            catch(PathNotFoundException e) {
+                //the property has not been created yet. do so now
+                newValueArray = new Value[1];
+            }
+            finally {
+                if(newValueArray != null) { //just here to make the compiler happy
+                    if(followFunctionHead) {                    
+                        newValueArray[i] = factory.createValue(functionItem.getNode());
+                    }
+                    else {
+                        newValueArray[i] = factory.createValue(functionItem.getNode().getBaseVersion());
+                    }
+                    this.node.checkout();
+                    this.node.setProperty(FUNCTION_REFERENCE_PROPERTY_NAME, newValueArray);                
+                    this.node.getSession().save();
+                    this.node.checkin();
+                }
+                else {
+                    throw new RulesRepositoryException("Unexpected null pointer for newValueArray");
+                }
+            }                    
+        }
+        catch(UnsupportedRepositoryOperationException e) {
+            String message = "";
+            try {
+                message = "Error: Caught UnsupportedRepositoryOperationException when attempting to get base version for function: " + functionItem.getNode().getName() + ". Are you sure your JCR repository supports versioning? ";
+                log.error(message + e);
+            }
+            catch (RepositoryException e1) {
+                log.error("Caught exception: " + e1);
+                throw new RulesRepositoryException(message, e1);
+            }
+            log.error("Caught exception: " + e);
+            throw new RulesRepositoryException(e);
+        }
+        catch(Exception e) {
+            log.error("Caught exception: " + e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+    
+    /**
      * Removes the specified rule from the rule package node this object represents.  
      * 
      * @param ruleItem the ruleItem corresponding to the node to remove from the rule package 
@@ -191,6 +276,81 @@
             throw new RulesRepositoryException(e);
         }
     }
+
+    /**
+     * Removes the specified function from the rule package node this object represents.  
+     * 
+     * @param functionItem the functionItem corresponding to the node to remove from the rule package 
+     *                 this object represents
+     * @throws RulesRepositoryException
+     */
+    public void removeFunction(FunctionItem functionItem) throws RulesRepositoryException {                
+        try {
+            Value[] oldValueArray = this.node.getProperty(FUNCTION_REFERENCE_PROPERTY_NAME).getValues();
+            Value[] newValueArray = new Value[oldValueArray.length - 1];
+            
+            boolean wasThere = false;
+            
+            int j=0;
+            for(int i=0; i<oldValueArray.length; i++) {
+                Node functionNode = this.node.getSession().getNodeByUUID(oldValueArray[i].getString());
+                FunctionItem currentFunctionItem = new FunctionItem(this.rulesRepository, functionNode);
+                if(currentFunctionItem.equals(functionItem)) {
+                    wasThere = true;
+                }
+                else {
+                    newValueArray[j] = oldValueArray[i];
+                    j++;
+                }
+            }
+                            
+            if(!wasThere) {
+                return;
+            }
+            else {
+                this.node.checkout();
+                this.node.setProperty(FUNCTION_REFERENCE_PROPERTY_NAME, newValueArray);                
+                this.node.getSession().save();
+                this.node.checkin();
+            }
+        }
+        catch(PathNotFoundException e) {
+            //the property has not been created yet. 
+            return;
+        }  
+        catch(Exception e) {
+            log.error("Caught exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+
+    /**
+     * Gets a list of FunctionItem objects for each function node in this rule package
+     * 
+     * @return the List object holding the FunctionItem objects in this rule package
+     * @throws RulesRepositoryException 
+     */
+    @SuppressWarnings("unchecked")
+    public List getFunctions() throws RulesRepositoryException {
+        try {                       
+            Value[] valueArray = this.node.getProperty(FUNCTION_REFERENCE_PROPERTY_NAME).getValues();
+            List returnList = new ArrayList();
+           
+            for(int i=0; i<valueArray.length; i++) {
+                Node functionNode = this.node.getSession().getNodeByUUID(valueArray[i].getString());
+                returnList.add(new FunctionItem(this.rulesRepository, functionNode));
+            }
+            return returnList;
+        }
+        catch(PathNotFoundException e) {
+            //the property has not been created yet. 
+            return new ArrayList();
+        }                                       
+        catch(Exception e) {
+            log.error("Caught exception: " + e);
+            throw new RulesRepositoryException(e);
+        }
+    }
     
     /**
      * Gets a list of RuleItem objects for each rule node in this rule package
@@ -198,6 +358,7 @@
      * @return the List object holding the RuleItem objects in this rule package
      * @throws RulesRepositoryException 
      */
+    @SuppressWarnings("unchecked")
     public List getRules() throws RulesRepositoryException {
         try {                       
             Value[] valueArray = this.node.getProperty(RULE_REFERENCE_PROPERTY_NAME).getValues();
@@ -220,6 +381,29 @@
     }    
     
     /**
+     * Removes all functions from the rule package
+     * 
+     * @throws RulesRepositoryException
+     */
+    public void removeAllFunctions() throws RulesRepositoryException {
+        try {
+            Property functionsProperty = this.node.getProperty(FUNCTION_REFERENCE_PROPERTY_NAME);
+            this.node.checkout();
+            functionsProperty.remove();
+            this.node.save();
+            this.node.checkin();
+        }
+        catch(PathNotFoundException e) {
+            //the property has not been created yet. 
+            return;
+        }                                       
+        catch(Exception e) {
+            log.error("Caught exception: " + e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+    
+    /**
      * Removes all rules from the rule package
      * 
      * @throws RulesRepositoryException
@@ -248,45 +432,42 @@
     public String toString() {
         try {            
             StringBuffer returnString = new StringBuffer();
-            returnString.append("These are the rules in the rule package named " + this.node.getName() + ":");
+            returnString.append("Content of the rule package named " + this.node.getName() + ":");
+            returnString.append("Contributor: " + this.getContributor() + "\n");
+            returnString.append("Description: " + this.getDescription() + "\n");
+            returnString.append("Format: " + this.getFormat() + "\n");
+            returnString.append("Last modified: " + this.getLastModified() + "\n");
+            returnString.append("Title: " + this.getTitle() + "\n");
+            returnString.append("Version Name: " + this.getVersionName() + "\n");
+            returnString.append("----\n");
             
             //iterate over the rules in this rule package and dump them
-            Property rulesProp = this.node.getProperty(RULE_REFERENCE_PROPERTY_NAME);
-            Value[] values = rulesProp.getValues();
-            for(int i=0; i<values.length; i++) {
-                Node ruleNode = this.node.getSession().getNodeByUUID(values[i].getString());
-                RuleItem ruleItem = new RuleItem(this.rulesRepository, ruleNode);
-                returnString.append(ruleItem.toString());
+            returnString.append("Rules in rule package: \n");
+            List ruleItems = this.getRules();
+            Iterator it = ruleItems.iterator();
+            while(it.hasNext()) {
+                RuleItem currentRuleItem = (RuleItem)it.next();
+                returnString.append(currentRuleItem.toString() + "\n");
             }
+            returnString.append("----\n");
+            
+            //iterate over the functions in this rule package and dump them
+            returnString.append("Functions in rule package: \n");
+            List functionItems = this.getFunctions();
+            it = functionItems.iterator();
+            while(it.hasNext()) {
+                FunctionItem currentFunctionItem = (FunctionItem)it.next();
+                returnString.append(currentFunctionItem.toString() + "\n");
+            }
+            returnString.append("--------\n");
+            
             return returnString.toString();
         }
         catch(Exception e) {
             log.error("Caught Exception", e);
             return null;
         }
-    }
-
-    /**
-     * @return a List of RulePackageItem objects encapsulating each Version node in the 
-     *         VersionHistory of this Item's node
-     * @throws RulesRepositoryException
-     */
-    public List getHistory() throws RulesRepositoryException {
-        List returnList = new ArrayList();
-        try {
-            VersionIterator it = this.node.getVersionHistory().getAllVersions();
-            while(it.hasNext()) {
-                Version currentVersion = it.nextVersion();
-                RulePackageItem item = new RulePackageItem(this.rulesRepository, currentVersion);
-                returnList.add(item);
-            }
-        }
-        catch(Exception e) {
-            log.error("Caught exception: " + e);
-            throw new RulesRepositoryException(e);
-        }
-        return returnList;
-    }
+    }    
     
     public VersionableItem getPrecedingVersion() throws RulesRepositoryException {
         try {

Modified: labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RulesRepository.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RulesRepository.java	2006-08-25 20:26:11 UTC (rev 5983)
+++ labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/RulesRepository.java	2006-08-27 21:17:30 UTC (rev 5984)
@@ -78,6 +78,11 @@
     public final static String RULE_AREA = "drools:rule_area";
     
     /**
+     * The name of the rule area of the repository
+     */
+    public final static String FUNCTION_AREA = "drools:function_area";
+    
+    /**
      * The name of the DSL area of the repository
      */
     public final static String DSL_AREA = "drools:dsl_area";
@@ -263,6 +268,15 @@
                 //This will happen in the node type is already registered, so ignore it
             }
             
+            //Setup the function node type
+            try {
+                //TODO: remove hard-coded path
+                this.registerNodeTypesFromCndFile("./src/node_type_definitions/function_node_type.cnd", ws);
+            }
+            catch(InvalidNodeTypeDefException e) {
+                //This will happen in the node type is already registered, so ignore it
+            }
+            
             // Setup the rulepackage node type
             try {
                 //TODO: remove hard-coded path
@@ -278,6 +292,9 @@
             // Setup the Rule area
             addNodeIfNew(repositoryNode, RULE_AREA, "nt:folder");
             
+            //Setup the Rule area
+            addNodeIfNew(repositoryNode, FUNCTION_AREA, "nt:folder");
+            
             // Setup the RulePackageItem area        
             addNodeIfNew(repositoryNode, RULE_PACKAGE_AREA, "nt:folder");
             
@@ -484,6 +501,98 @@
     }    
     
     /**
+     * Adds a Function node in the repository using the content specified.
+     * 
+     * @param functionName the name of the function
+     * @param content the content of the function
+     * @return a FunctionItem object encapsulating the node that gets added
+     * @throws RulesRepositoryException
+     */
+    public FunctionItem addFunction(String functionName, String content) throws RulesRepositoryException {
+        Node folderNode = this.getAreaNode(FUNCTION_AREA);        
+        
+        try {        
+            //create the node - see section 6.7.22.6 of the spec
+            Node functionNode = folderNode.addNode(functionName, FunctionItem.FUNCTION_NODE_TYPE_NAME);
+                        
+            functionNode.setProperty(FunctionItem.TITLE_PROPERTY_NAME, functionName);
+            functionNode.setProperty(FunctionItem.CONTENT_PROPERTY_NAME, content);
+            functionNode.setProperty(FunctionItem.DESCRIPTION_PROPERTY_NAME, "");
+            
+            //TODO: set contributor correctly
+            functionNode.setProperty(FunctionItem.CONTRIBUTOR_PROPERTY_NAME, "");
+            
+            functionNode.setProperty(FunctionItem.FORMAT_PROPERTY_NAME, FunctionItem.FUNCTION_FORMAT);
+            
+            Calendar lastModified = Calendar.getInstance();
+            functionNode.setProperty(FunctionItem.LAST_MODIFIED_PROPERTY_NAME, lastModified);
+            
+            session.save();
+            
+            try {
+                functionNode.checkin();
+            }
+            catch(UnsupportedRepositoryOperationException e) {
+                String message = "Error: Caught UnsupportedRepositoryOperationException when attempting to checkin node: " + functionNode.getName() + ". Are you sure your JCR repository supports versioning? ";
+                log.error(message + e);
+                throw new RulesRepositoryException(message, e);
+            }
+            
+            return new FunctionItem(this, functionNode);
+        }
+        catch(Exception e) {
+            log.error("Caught Exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+    
+    /**
+     * Adds a Function node in the repository using the content specified.
+     * 
+     * @param functionName the name of the function
+     * @param content the content of the function
+     * @param description the description of the function
+     * @return a FunctionItem object encapsulating the node that gets added
+     * @throws RulesRepositoryException
+     */
+    public FunctionItem addFunction(String functionName, String content, String description) throws RulesRepositoryException {
+        Node folderNode = this.getAreaNode(FUNCTION_AREA);        
+        
+        try {        
+            //create the node - see section 6.7.22.6 of the spec
+            Node functionNode = folderNode.addNode(functionName, FunctionItem.FUNCTION_NODE_TYPE_NAME);
+                        
+            functionNode.setProperty(FunctionItem.TITLE_PROPERTY_NAME, functionName);
+            functionNode.setProperty(FunctionItem.CONTENT_PROPERTY_NAME, content);
+            functionNode.setProperty(FunctionItem.DESCRIPTION_PROPERTY_NAME, description);
+            functionNode.setProperty(FunctionItem.FORMAT_PROPERTY_NAME, FunctionItem.FUNCTION_FORMAT);
+            
+            //TODO: set contributor correctly
+            functionNode.setProperty(FunctionItem.CONTRIBUTOR_PROPERTY_NAME, "");
+            
+            Calendar lastModified = Calendar.getInstance();
+            functionNode.setProperty(FunctionItem.LAST_MODIFIED_PROPERTY_NAME, lastModified);
+            
+            session.save();
+            
+            try {
+                functionNode.checkin();
+            }
+            catch(UnsupportedRepositoryOperationException e) {
+                String message = "Error: Caught UnsupportedRepositoryOperationException when attempting to checkin node: " + functionNode.getName() + ". Are you sure your JCR repository supports versioning? ";
+                log.error(message + e);
+                throw new RulesRepositoryException(message, e);
+            }
+            
+            return new FunctionItem(this, functionNode);
+        }
+        catch(Exception e) {
+            log.error("Caught Exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+    
+    /**
      * Adds a Rule node in the repository using the content specified, associating it with
      * the specified DSL node
      * 
@@ -505,7 +614,12 @@
             ruleNode.setProperty(RuleItem.TITLE_PROPERTY_NAME, ruleName);
             ruleNode.setProperty(RuleItem.LHS_PROPERTY_NAME, lhsContent);
             ruleNode.setProperty(RuleItem.RHS_PROPERTY_NAME, rhsContent);
+            ruleNode.setProperty(RuleItem.DESCRIPTION_PROPERTY_NAME, "");
+            ruleNode.setProperty(RuleItem.FORMAT_PROPERTY_NAME, RuleItem.RULE_FORMAT);
             
+            //TODO: set this correctly
+            ruleNode.setProperty(RuleItem.CONTRIBUTOR_PROPERTY_NAME, "");
+            
             if(followDslHead) {
                 ruleNode.setProperty(RuleItem.DSL_PROPERTY_NAME, dslItem.getNode());
             }
@@ -825,6 +939,33 @@
     }
 
     /**
+     * This will retrieve a list of FunctionItem objects - that are allocated to the 
+     * provided category.
+     * Only the latest versions of each FunctionItem will be returned (you will have 
+     * to delve into the functions' deepest darkest history yourself... mahahahaha).
+     */
+    @SuppressWarnings("unchecked")
+    public List findFunctionsByTag(String categoryTag) throws RulesRepositoryException {        
+        CategoryItem item = this.getOrCreateCategory( categoryTag );
+        List results = new ArrayList();
+        try {
+            PropertyIterator it = item.getNode().getReferences();
+            while(it.hasNext()) {
+                Property ruleLink = (Property) it.next();
+                Node parentNode = ruleLink.getParent();
+                if(parentNode.getPrimaryNodeType().getName().equals(FunctionItem.FUNCTION_NODE_TYPE_NAME) ||
+                   (parentNode.getPrimaryNodeType().getName().equals("nt:version") && 
+                    parentNode.getProperty(VersionableItem.FORMAT_PROPERTY_NAME).getString().equals(VersionableItem.FUNCTION_FORMAT))) {
+                    results.add(new FunctionItem(this, parentNode));
+                }
+            }
+            return results;
+        } catch (RepositoryException e) {            
+            throw new RulesRepositoryException(e);
+        }        
+    }
+    
+    /**
      * This will retrieve a list of RuleItem objects - that are allocated to the 
      * provided category.
      * Only the latest versions of each RuleItem will be returned (you will have 
@@ -839,7 +980,12 @@
             PropertyIterator it = item.getNode().getReferences();
             while(it.hasNext()) {
                 Property ruleLink = (Property) it.next();
-                results.add( new RuleItem(this, ruleLink.getParent()) );
+                Node parentNode = ruleLink.getParent();
+                if(parentNode.getPrimaryNodeType().getName().equals(RuleItem.RULE_NODE_TYPE_NAME) ||
+                   (parentNode.getPrimaryNodeType().getName().equals("nt:version") && 
+                    parentNode.getProperty(VersionableItem.FORMAT_PROPERTY_NAME).getString().equals(VersionableItem.RULE_FORMAT))) {
+                    results.add(new RuleItem(this, parentNode));
+                }
             }
             return results;
         } catch ( RepositoryException e ) {            

Modified: labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/VersionableItem.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/VersionableItem.java	2006-08-25 20:26:11 UTC (rev 5983)
+++ labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/VersionableItem.java	2006-08-27 21:17:30 UTC (rev 5984)
@@ -45,6 +45,7 @@
     public static final String RULE_FORMAT = "Rule";    
     public static final String DSL_FORMAT = "DSL";
     public static final String RULE_PACKAGE_FORMAT = "Rule Package";
+    public static final String FUNCTION_FORMAT = "Function";
     
     /**
      * Sets this object's node attribute to the specified node
@@ -280,6 +281,29 @@
     }       
 
     /**
+     * @return the date the function node (this version) was last modified
+     * @throws RulesRepositoryException
+     */
+    public Calendar getLastModified() throws RulesRepositoryException {
+        try {                        
+            Node theNode;
+            if(this.node.getPrimaryNodeType().getName().equals("nt:version")) {
+                theNode = this.node.getNode("jcr:frozenNode");
+            }
+            else {
+                theNode = this.node;
+            }
+                        
+            Property lastModifiedProperty = theNode.getProperty("drools:last_modified");
+            return lastModifiedProperty.getDate();
+        }
+        catch(Exception e) {
+            log.error("Caught Exception", e);
+            throw new RulesRepositoryException(e);
+        }
+    }
+        
+    /**
      * Creates a new version of this object's node, updating the description content 
      * for the node.
      * <br>

Added: labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/FunctionItemTestCase.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/FunctionItemTestCase.java	2006-08-25 20:26:11 UTC (rev 5983)
+++ labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/FunctionItemTestCase.java	2006-08-27 21:17:30 UTC (rev 5984)
@@ -0,0 +1,373 @@
+package org.drools.repository.test;
+
+import java.io.File;
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.repository.*;
+
+public class FunctionItemTestCase extends TestCase {
+    private RulesRepository rulesRepository;
+    
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.rulesRepository = new RulesRepository(true);
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        rulesRepository.logout();
+    }
+
+    public void testFunctionItem() {
+        try {            
+            //calls constructor
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            assertNotNull(functionItem1);
+            assertNotNull(functionItem1.getNode());
+            assertEquals("test function", functionItem1.getName());            
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+        
+        //try constructing with node of wrong type
+        try {
+            File dslFile1 = new File("./src/java/org/drools/repository/test/test_data/dsl1.dsl");
+            DslItem dslItem = rulesRepository.addDslFromFile(dslFile1);
+            FunctionItem functionItem = new FunctionItem(this.rulesRepository, dslItem.getNode());
+            fail("Exception not thrown for node of type: " + dslItem.getNode().getPrimaryNodeType().getName());
+        }
+        catch(RulesRepositoryException e) {
+            //this is good
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+
+    public void testGetContent() {
+        try {            
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            assertNotNull(functionItem1);
+            assertNotNull(functionItem1.getNode());
+            assertEquals("test content", functionItem1.getContent());
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+    
+    public void testUpdateContent() {
+        //TODO: maybe add some testing on the versioning stuff more - check the content of the
+        //      previous version, etc.
+        try {                        
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+                        
+            functionItem1.updateContent("new content");
+            
+            assertEquals("new content", functionItem1.getContent());
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+        
+    public void testAddTag() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            functionItem1.addTag("TestTag");
+            List tags = functionItem1.getTags();
+            assertEquals(1, tags.size());
+            assertEquals("TestTag", ((CategoryItem)tags.get(0)).getName());
+            
+            functionItem1.addTag("TestTag2");
+            tags = functionItem1.getTags();
+            assertEquals(2, tags.size());   
+                        
+            //now test retrieve by tags
+            List result = this.rulesRepository.findFunctionsByTag("TestTag");            
+            assertEquals(1, result.size());            
+            FunctionItem retItem = (FunctionItem) result.get(0);
+            assertEquals("test function", retItem.getName());            
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+
+    public void testRemoveTag() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            functionItem1.addTag("TestTag");                                    
+            functionItem1.removeTag("TestTag");
+            List tags = functionItem1.getTags();
+            assertEquals(0, tags.size());
+            
+            functionItem1.addTag("TestTag2");                                    
+            functionItem1.addTag("TestTag3");
+            functionItem1.removeTag("TestTag2");
+            tags = functionItem1.getTags();
+            assertEquals(1, tags.size());
+            assertEquals("TestTag3", ((CategoryItem)tags.get(0)).getName());            
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+
+    public void testGetTags() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+           
+            List tags = functionItem1.getTags();
+            assertNotNull(tags);
+            assertEquals(0, tags.size());
+            
+            functionItem1.addTag("TestTag");                                    
+            tags = functionItem1.getTags();
+            assertEquals(1, tags.size());
+            assertEquals("TestTag", ((CategoryItem)tags.get(0)).getName());
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+
+    public void testSetStateString() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+           
+            functionItem1.setState("TestState1");
+            assertNotNull(functionItem1.getState());
+            assertEquals("TestState1", functionItem1.getState().getName());
+            
+            functionItem1.setState("TestState2");
+            assertNotNull(functionItem1.getState());
+            assertEquals("TestState2", functionItem1.getState().getName());            
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+
+    public void testSetStateStateItem() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test content", "test content");
+           
+            StateItem stateItem1 = rulesRepository.getState("TestState1");
+            functionItem1.setState(stateItem1);            
+            assertNotNull(functionItem1.getState());
+            assertEquals(functionItem1.getState().getName(), "TestState1");
+            
+            StateItem stateItem2 = rulesRepository.getState("TestState2");
+            functionItem1.setState(stateItem2);
+            assertNotNull(functionItem1.getState());
+            assertEquals("TestState2", functionItem1.getState().getName());            
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+
+    public void testGetState() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+           
+            StateItem stateItem1 = functionItem1.getState();
+            assertNull(stateItem1);
+            
+            functionItem1.setState("TestState1");
+            assertNotNull(functionItem1.getState());
+            assertEquals("TestState1", functionItem1.getState().getName());                        
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+
+    public void testToString() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+           
+            assertNotNull(functionItem1.toString());                        
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+    
+    public void testGetLastModified() {
+        //common functionality with FunctionItem - tested there
+    }
+        
+    public void testFunctionRuleLanguage() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+           
+            //it should be initialized to 'Java'
+            assertEquals("Java", functionItem1.getFunctionLanguage());                        
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+    
+    public void testGetDescription() {
+        //common functionality with FunctionItem - tested there
+    }
+    
+    public void testGetPrecedingVersion() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            FunctionItem predecessorFunctionItem = (FunctionItem) functionItem1.getPrecedingVersion();
+            assertTrue(predecessorFunctionItem == null);            
+            
+            functionItem1.updateContent("new content");
+            
+            predecessorFunctionItem = (FunctionItem) functionItem1.getPrecedingVersion();
+            assertNotNull(predecessorFunctionItem);
+            assertEquals("test content", predecessorFunctionItem.getContent());
+            
+            functionItem1.updateContent("newer content");
+            
+            predecessorFunctionItem = (FunctionItem) functionItem1.getPrecedingVersion();
+            assertNotNull(predecessorFunctionItem);
+            assertEquals("new content", predecessorFunctionItem.getContent());
+            predecessorFunctionItem = (FunctionItem) predecessorFunctionItem.getPrecedingVersion();
+            assertNotNull(predecessorFunctionItem);
+            assertEquals("test content", predecessorFunctionItem.getContent());
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }   
+    }
+    
+    public void testGetSucceedingVersion() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            FunctionItem succeedingFunctionItem = (FunctionItem) functionItem1.getSucceedingVersion();
+            assertTrue(succeedingFunctionItem == null);            
+            
+            functionItem1.updateContent("new content");
+            
+            FunctionItem predecessorFunctionItem = (FunctionItem) functionItem1.getPrecedingVersion();
+            assertEquals("test content", predecessorFunctionItem.getContent());
+            succeedingFunctionItem = (FunctionItem) predecessorFunctionItem.getSucceedingVersion();
+            assertNotNull(succeedingFunctionItem);
+            assertEquals(functionItem1.getContent(), succeedingFunctionItem.getContent());                       
+        }        
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }   
+    } 
+    
+    public void testGetSuccessorVersionsIterator() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");                        
+            
+            Iterator iterator = functionItem1.getSuccessorVersionsIterator();            
+            assertNotNull(iterator);
+            assertFalse(iterator.hasNext());
+            
+            functionItem1.updateContent("new content");
+            
+            iterator = functionItem1.getSuccessorVersionsIterator();            
+            assertNotNull(iterator);
+            assertFalse(iterator.hasNext());
+            
+            FunctionItem predecessorFunctionItem = (FunctionItem) functionItem1.getPrecedingVersion();
+            iterator = predecessorFunctionItem.getSuccessorVersionsIterator();
+            assertNotNull(iterator);
+            assertTrue(iterator.hasNext());
+            FunctionItem nextFunctionItem = (FunctionItem) iterator.next();
+            assertEquals("new content", nextFunctionItem.getContent());
+            assertFalse(iterator.hasNext());
+            
+            functionItem1.updateContent("newer content");
+                        
+            iterator = predecessorFunctionItem.getSuccessorVersionsIterator();
+            assertNotNull(iterator);
+            assertTrue(iterator.hasNext());
+            nextFunctionItem = (FunctionItem) iterator.next();
+            assertEquals("new content", nextFunctionItem.getContent());
+            assertTrue(iterator.hasNext());
+            nextFunctionItem = (FunctionItem)iterator.next();
+            assertEquals("newer content", nextFunctionItem.getContent());
+            assertFalse(iterator.hasNext());            
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+    
+    public void testGetPredecessorVersionsIterator() {
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");                        
+            
+            Iterator iterator = functionItem1.getPredecessorVersionsIterator();            
+            assertNotNull(iterator);
+            assertFalse(iterator.hasNext());
+            
+            functionItem1.updateContent("new content");
+            
+            iterator = functionItem1.getPredecessorVersionsIterator();            
+            assertNotNull(iterator);
+            assertTrue(iterator.hasNext());
+            FunctionItem nextFunctionItem = (FunctionItem) iterator.next();
+            assertFalse(iterator.hasNext());
+            assertEquals("test content", nextFunctionItem.getContent());
+            
+            functionItem1.updateContent("newer content");
+            
+            iterator = functionItem1.getPredecessorVersionsIterator();            
+            assertNotNull(iterator);
+            assertTrue(iterator.hasNext());
+            nextFunctionItem = (FunctionItem) iterator.next();
+            assertTrue(iterator.hasNext());            
+            assertEquals("new content", nextFunctionItem.getContent());
+            nextFunctionItem = (FunctionItem) iterator.next();
+            assertFalse(iterator.hasNext());
+            assertEquals("test content", nextFunctionItem.getContent());
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+    
+    public void testGetTitle() {    
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");            
+                        
+            assertEquals("test function", functionItem1.getTitle());
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+    
+    public void testGetContributor() {
+        //can't implement this until we figure out login / JAAS stuff.
+        fail("not yet implemented");        
+    }
+    
+    public void testGetFormat() {        
+        try {
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            assertEquals("Function", functionItem1.getFormat());            
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+    }        
+}

Modified: labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/RulePackageItemTestCase.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/RulePackageItemTestCase.java	2006-08-25 20:26:11 UTC (rev 5983)
+++ labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/RulePackageItemTestCase.java	2006-08-27 21:17:30 UTC (rev 5984)
@@ -140,6 +140,117 @@
         }
     }
 
+    public void testAddFunctionFunctionItem() {
+        try {
+            RulePackageItem rulePackageItem1 = this.rulesRepository.createRulePackage("testRulePackage");
+            
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            rulePackageItem1.addFunction(functionItem1);
+            
+            List functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(1, functions.size());
+            assertEquals("test function", ((FunctionItem)functions.get(0)).getName());
+            
+            //test that it is following the head revision                        
+            functionItem1.updateContent("new content");
+            functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(1, functions.size());
+            assertEquals("test function", ((FunctionItem)functions.get(0)).getName());
+            assertEquals("new content", ((FunctionItem)functions.get(0)).getContent());
+                        
+            FunctionItem functionItem2 = this.rulesRepository.addFunction("test function 2", "test content");
+            rulePackageItem1.addFunction(functionItem2);
+            
+            functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(2, functions.size());                          
+        }
+        catch(Exception e) {
+            e.printStackTrace();
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+
+    public void testAddFunctionFunctionItemBoolean() {
+        try {
+            RulePackageItem rulePackageItem1 = this.rulesRepository.createRulePackage("testRulePackage");
+            
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            rulePackageItem1.addFunction(functionItem1, true);
+            
+            List functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(1, functions.size());
+            assertEquals("test function", ((FunctionItem)functions.get(0)).getName());
+            
+            //test that it is following the head revision                        
+            functionItem1.updateContent("new content");
+            functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(1, functions.size());
+            assertEquals("test function", ((FunctionItem)functions.get(0)).getName());
+            assertEquals("new content", ((FunctionItem)functions.get(0)).getContent());
+            
+            FunctionItem functionItem2 = this.rulesRepository.addFunction("test function 2", "test content");
+            rulePackageItem1.addFunction(functionItem2);
+            
+            functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(2, functions.size());
+            
+            //test not following the head revision
+            rulePackageItem1.removeAllFunctions();
+            FunctionItem functionItem3 = this.rulesRepository.addFunction("test function 3", "test content");
+            
+            rulePackageItem1.addFunction(functionItem3, false);
+            
+            functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(1, functions.size());
+            assertEquals("test content", ((FunctionItem)functions.get(0)).getContent());
+                                    
+            functionItem3.updateContent("new content");
+            functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(1, functions.size());
+            assertEquals("test content", ((FunctionItem)functions.get(0)).getContent());
+        }
+        catch(Exception e) {
+            e.printStackTrace();
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+
+    public void testGetFunctions() {
+        try {
+            RulePackageItem rulePackageItem1 = this.rulesRepository.createRulePackage("testRulePackage");
+                        
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            rulePackageItem1.addFunction(functionItem1);
+            
+            List functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(1, functions.size());
+            assertEquals("test function", ((FunctionItem)functions.get(0)).getName());
+                                  
+            FunctionItem functionItem2 = this.rulesRepository.addFunction("test function 2", "test content");
+            rulePackageItem1.addFunction(functionItem2);
+            
+            functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(2, functions.size());            
+        }
+        catch(Exception e) {
+            e.printStackTrace();
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+    
     public void testGetRules() {
         try {
             RulePackageItem rulePackageItem1 = this.rulesRepository.createRulePackage("testRulePackage");
@@ -246,8 +357,75 @@
             e.printStackTrace();
             fail("Caught unexpected exception: " + e);
         }
+    }    
+    
+    public void testRemoveFunction() {
+        try {
+            RulePackageItem rulePackageItem1 = this.rulesRepository.createRulePackage("testRulePackage");
+            
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            rulePackageItem1.addFunction(functionItem1);
+            
+            List functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(1, functions.size());
+            assertEquals("test function", ((FunctionItem)functions.get(0)).getName());
+                                    
+            functionItem1.updateContent("new content");
+            functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(1, functions.size());
+            assertEquals("test function", ((FunctionItem)functions.get(0)).getName());
+            assertEquals("new content", ((FunctionItem)functions.get(0)).getContent());
+            
+            FunctionItem functionItem2 = this.rulesRepository.addFunction("test function 2", "test content");
+            rulePackageItem1.addFunction(functionItem2);
+            
+            //remove the function, make sure the other function in the package stays around
+            rulePackageItem1.removeFunction(functionItem1);
+            functions = rulePackageItem1.getFunctions();
+            assertEquals(1, functions.size());
+            assertEquals("test function 2", ((FunctionItem)functions.get(0)).getName());
+            
+            //remove the function that is following the head revision, make sure the package is now empty
+            rulePackageItem1.removeFunction(functionItem2);
+            functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(0, functions.size());
+                        
+        }
+        catch(Exception e) {
+            e.printStackTrace();
+            fail("Caught unexpected exception: " + e);
+        }
     }
     
+    public void testRemoveAllFunctions() {
+        try {
+            RulePackageItem rulePackageItem1 = this.rulesRepository.createRulePackage("testRulePackage");
+            
+            FunctionItem functionItem1 = this.rulesRepository.addFunction("test function", "test content");
+            
+            rulePackageItem1.addFunction(functionItem1);
+            
+            List functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(1, functions.size());
+            assertEquals("test function", ((FunctionItem)functions.get(0)).getName());
+            
+            rulePackageItem1.removeAllFunctions();
+            
+            functions = rulePackageItem1.getFunctions();
+            assertNotNull(functions);
+            assertEquals(0, functions.size());            
+        }
+        catch(Exception e) {
+            e.printStackTrace();
+            fail("Caught unexpected exception: " + e);
+        }
+    }
+    
     public void testGetPrecedingVersion() {
         //not bothering to implement this test since it is pretty much covered by the RuleItemTestCase   
     }

Modified: labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/RulesRepositoryTestCase.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/RulesRepositoryTestCase.java	2006-08-25 20:26:11 UTC (rev 5983)
+++ labs/jbossrules/trunk/drools-repository/src/java/org/drools/repository/test/RulesRepositoryTestCase.java	2006-08-27 21:17:30 UTC (rev 5984)
@@ -2,6 +2,7 @@
 
 import java.io.File;
 import java.util.Calendar;
+import java.util.Iterator;
 
 import org.drools.repository.*;
 
@@ -263,4 +264,86 @@
             }
         }
     }
+    
+    public void testAddFunctionStringString() {
+        RulesRepository rulesRepository = null;
+        try {
+            rulesRepository = new RulesRepository(true);
+                        
+            FunctionItem functionItem1 = rulesRepository.addFunction("test function", "test content");
+            
+            assertNotNull(functionItem1);
+            assertNotNull(functionItem1.getNode());
+            assertEquals("test function", functionItem1.getName());
+            assertEquals("test content", functionItem1.getContent());
+            assertEquals("", functionItem1.getDescription());
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+        finally {
+            if(rulesRepository != null) {
+                try {
+                    rulesRepository.logout();
+                }
+                catch(Exception e) {
+                    fail("Caught unexpected Exception: " + e);
+                }
+            }
+        }
+    }
+    
+    public void testAddFunctionStringStringString() {
+        RulesRepository rulesRepository = null;
+        try {
+            rulesRepository = new RulesRepository(true);
+                        
+            FunctionItem functionItem1 = rulesRepository.addFunction("test function", "test content", "test description");
+            
+            assertNotNull(functionItem1);
+            assertNotNull(functionItem1.getNode());
+            assertEquals("test function", functionItem1.getName());
+            assertEquals("test content", functionItem1.getContent());
+            assertEquals("test description", functionItem1.getDescription());
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+        finally {
+            if(rulesRepository != null) {
+                try {
+                    rulesRepository.logout();
+                }
+                catch(Exception e) {
+                    fail("Caught unexpected Exception: " + e);
+                }
+            }
+        }
+    }
+    
+    public void testListPackages() {
+        RulesRepository rulesRepository = null;
+        try {
+            RulePackageItem rulePackageItem1 = rulesRepository.createRulePackage("testRulePacakge");
+            
+            Iterator it = rulesRepository.listPackages();
+            assertTrue(it.hasNext());
+            
+            RulePackageItem pack = (RulePackageItem) it.next();
+            assertEquals("testRulePackage", pack.getName());
+        }
+        catch(Exception e) {
+            fail("Caught unexpected exception: " + e);
+        }
+        finally {
+            if(rulesRepository != null) {
+                try {
+                    rulesRepository.logout();
+                }
+                catch(Exception e) {
+                    fail("Caught unexpected Exception: " + e);
+                }
+            }
+        }
+    }
 }

Added: labs/jbossrules/trunk/drools-repository/src/node_type_definitions/function_node_type.cnd
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/node_type_definitions/function_node_type.cnd	2006-08-25 20:26:11 UTC (rev 5983)
+++ labs/jbossrules/trunk/drools-repository/src/node_type_definitions/function_node_type.cnd	2006-08-27 21:17:30 UTC (rev 5984)
@@ -0,0 +1,31 @@
+/*  The node type definition for the function node type.  
+    See http://jackrabbit.apache.org/doc/nodetype/cnd.html for an explanation
+*/
+
+// The namespace declaration
+<drools = 'http://www.jboss.org/drools-repository/1.0'>
+<nt='http://www.jcp.org/jcr/nt/1.0'>
+<mix='http://www.jcp.org/jcr/mix/1.0'>
+
+// Node type name
+[drools:function_node_type]
+
+// Supertypes
+> 'drools:versionable_node_type'
+
+// Properties:
+- drools:content (string)
+  mandatory
+  
+- drools:function_language (string)
+  = 'Java'
+  mandatory autocreated
+
+- drools:tag_reference (reference)
+  multiple 
+  copy
+  < 'drools:tag_node_type'
+
+- drools:state_reference (reference)
+  copy
+  < 'drools:state_node_type'
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-repository/src/node_type_definitions/rulepackage_node_type.cnd
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/node_type_definitions/rulepackage_node_type.cnd	2006-08-25 20:26:11 UTC (rev 5983)
+++ labs/jbossrules/trunk/drools-repository/src/node_type_definitions/rulepackage_node_type.cnd	2006-08-27 21:17:30 UTC (rev 5984)
@@ -16,4 +16,9 @@
 - drools:rule_reference (reference)
   multiple
   copy
-  < 'drools:rule_node_type','nt:version'
\ No newline at end of file
+  < 'drools:rule_node_type','nt:version'
+  
+- drools:function_reference (reference)
+  multiple
+  copy
+  < 'drools:function_node_type','nt:version'
\ No newline at end of file




More information about the jboss-svn-commits mailing list