[jboss-svn-commits] JBL Code SVN: r30813 - in labs/jbossrules/trunk: drools-api/src/main/java/org/drools/agent and 11 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Dec 24 12:54:15 EST 2009


Author: eaa
Date: 2009-12-24 12:54:14 -0500 (Thu, 24 Dec 2009)
New Revision: 30813

Added:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/ResourceDiffProducer.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/BinaryResourceDiffProducerImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/DefaultResourceDiffProducerImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/ResourceDiffResult.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/changeset/DefinitionHandler.java
Removed:
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/agent/KnowledgeAgentRemoveRuleChangeSetTest.java
Modified:
   labs/jbossrules/trunk/drools-api/src/main/java/org/drools/ChangeSet.java
   labs/jbossrules/trunk/drools-api/src/main/java/org/drools/KnowledgeBase.java
   labs/jbossrules/trunk/drools-api/src/main/java/org/drools/agent/KnowledgeAgentFactory.java
   labs/jbossrules/trunk/drools-api/src/main/java/org/drools/definition/KnowledgePackage.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/java/JavaDialect.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/agent/KnowledgeAgentIncrementalChangeSetTest.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/KnowledgeAgentImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/definitions/impl/KnowledgePackageImp.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/KnowledgeBaseImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/io/impl/ChangeSetImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Function.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/ChangeSetSemanticModule.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/changeset/RemoveHandler.java
Log:
JBRULES-2082: support for delete/modify in changesets
	- The agent now support adding/modifying/removing entire resources. For modified resources (when newInstance=false), a silly diff is made: all the definitions are marked as changed. A better implementation of this diff will allow to modify in the kbase just the rules that have changed.   	
	

Modified: labs/jbossrules/trunk/drools-api/src/main/java/org/drools/ChangeSet.java
===================================================================
--- labs/jbossrules/trunk/drools-api/src/main/java/org/drools/ChangeSet.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-api/src/main/java/org/drools/ChangeSet.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -82,8 +82,11 @@
      */
     public Collection<Resource> getResourcesModified();
 
-    Map<Resource, String> getKnowledgeDefinitionsRemoved();
+    /**
+     * Returns a collection containing the full names (package+name) of the kdefinitions to be removed.
+     * @return
+     */
+    Collection<String> getKnowledgeDefinitionsRemoved();
 
-    void setKnowledgeDefinitionsRemoved(Map<Resource, String> knowledgeDefinitionsRemoved);
 
 }

Modified: labs/jbossrules/trunk/drools-api/src/main/java/org/drools/KnowledgeBase.java
===================================================================
--- labs/jbossrules/trunk/drools-api/src/main/java/org/drools/KnowledgeBase.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-api/src/main/java/org/drools/KnowledgeBase.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -91,6 +91,14 @@
                     String ruleName);
     
     /**
+     * Remove a function from the specified package.
+     * @param packageName
+     * @param ruleName
+     */
+    void removeFunction(String packageName,
+                    String ruleName);
+
+    /**
      * Returns the FactType identified by the given package and type names.
      * 
      * @param packageName the name of the package the fact belongs to.

Modified: labs/jbossrules/trunk/drools-api/src/main/java/org/drools/agent/KnowledgeAgentFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-api/src/main/java/org/drools/agent/KnowledgeAgentFactory.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-api/src/main/java/org/drools/agent/KnowledgeAgentFactory.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -27,7 +27,7 @@
  * KnowledgeBase kbase = kagent.getKnowledgeBase();    
  * </pre>
  * 
- * <p>If you wish to change to change the polling time of the scanner, this can be done with the ResourceChangeScannerService on the ResourceFactory</p>
+ * <p>If you wish to change the polling time of the scanner, this can be done with the ResourceChangeScannerService on the ResourceFactory</p>
  * <pre>
  * // Set the interval on the ResourceChangeScannerService if the default of 60s is not desirable.
  * ResourceChangeScannerConfiguration sconf = ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfiguration();
@@ -53,10 +53,9 @@
  * </pre>
  * 
  * <p>
- * You'll notice the property "drools.agent.newInstance", which defaults to true, currently this cannot be set to false. This property when
+ * You'll notice the property "drools.agent.newInstance", which defaults to true. This property when
  * true means the KnowledgeBase will be rebuilt as a new instance when changes are detected and that new instance will be available when
- * kagent.getKnowledgeBase() is next called. We hope to add incremental KnowledgeBase support in the future, when a "false" value will be supported
- * for this property.
+ * kagent.getKnowledgeBase() is next called. 
  * </p>
  * 
  * <p>
@@ -85,14 +84,32 @@
  * For example -Ddrools.resource.urlcache=/home/rulecaches
  *
  * </p>
+ *
+ * <p>
+ * The default implementation of KnowledgeAgent returned by this factory is
+ * "org.drools.agent.impl.KnowledgeAgentProviderImpl". You can change it using
+ *  the system property {@link #PROVIDER_CLASS_NAME_PROPERTY_NAME} to point to a diverse
+ * implementation of "org.drools.agent.KnowledgeAgentProvider".
+ * </p>
  * 
  * @see org.drools.agent.KnowledgeAgent
- * @see org.drools.agent.KnowledgeAgentConfiguration
+ * @see org.drools.agent.KnowledgeAgent
  * 
  */
 public class KnowledgeAgentFactory {
+
+    public static final String PROVIDER_CLASS_NAME_PROPERTY_NAME = "drools.agent.factory.provider";
+    /**
+     * The provider class name. The default provider is org.drools.agent.impl.KnowledgeAgentProviderImpl.
+     * If you need a different provider you can use the system property
+     * {@link #PROVIDER_CLASS_NAME_PROPERTY_NAME}  to point to a diverse implementation of
+     * "org.drools.agent.KnowledgeAgentProvider"
+     */
+    private static String providerClassName = "org.drools.agent.impl.KnowledgeAgentProviderImpl";
+
     private static KnowledgeAgentProvider provider;
 
+
     public static KnowledgeAgentConfiguration newKnowledgeAgentConfiguration() {
         return getKnowledgeAgentProvider().newKnowledgeAgentConfiguration();
     }
@@ -140,11 +157,13 @@
 
     private static void loadProvider() {
         try {
-            // we didn't find anything in properties so lets try and us reflection
-            Class<KnowledgeAgentProvider> cls = (Class<KnowledgeAgentProvider>) Class.forName( "org.drools.agent.impl.KnowledgeAgentProviderImpl" );
+            //loads the provider class
+            providerClassName = System.getProperty(KnowledgeAgentFactory.PROVIDER_CLASS_NAME_PROPERTY_NAME, providerClassName);
+
+            Class<KnowledgeAgentProvider> cls = (Class<KnowledgeAgentProvider>) Class.forName(providerClassName);
             setKnowledgeAgentProvider( cls.newInstance() );
         } catch ( Exception e ) {
-            throw new ProviderInitializationException( "Provider org.drools.agent.KnowledgeAgentProvider could not be set." );
+            throw new ProviderInitializationException( "Provider "+providerClassName+" could not be set." );
         }
     }
 }

Modified: labs/jbossrules/trunk/drools-api/src/main/java/org/drools/definition/KnowledgePackage.java
===================================================================
--- labs/jbossrules/trunk/drools-api/src/main/java/org/drools/definition/KnowledgePackage.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-api/src/main/java/org/drools/definition/KnowledgePackage.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -34,4 +34,5 @@
      */
     Collection<Process> getProcesses();
 
+
 }

Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/java/JavaDialect.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/java/JavaDialect.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/java/JavaDialect.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -582,7 +582,7 @@
 
         this.pkg.addStaticImport( functionClassName + "." + functionDescr.getName() );
 
-        Function function = new Function( functionDescr.getName(),
+        Function function = new Function( functionDescr.getNamespace(), functionDescr.getName(),
                                           this.ID );
         if ( resource != null && ((InternalResource) resource).hasURL() ) {
             function.setResource( resource );

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/agent/KnowledgeAgentIncrementalChangeSetTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/agent/KnowledgeAgentIncrementalChangeSetTest.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/agent/KnowledgeAgentIncrementalChangeSetTest.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -1005,6 +1005,216 @@
         kagent.monitorResourceChangeEvents(false);
     }
 
+
+    public void completeTest() throws Exception {
+        String header = "";
+        header += "package org.drools.test\n";
+        header += "global java.util.List list\n\n";
+
+        String rule1 = this.createCommonRule("rule1");
+        String rule1V2 = this.createCommonRule("rule1", "2");
+        String rule1V3 = this.createCommonRule("rule1", "3");
+        String rule2 = this.createCommonRule("rule2");
+        String rule3 = this.createCommonRule("rule3");
+        String rule3V2 = this.createCommonRule("rule3","2");
+        String rule4 = this.createCommonRule("rule4");
+
+
+        File f1 = fileManager.newFile("rule1.drl");
+        Writer output = new BufferedWriter(new FileWriter(f1));
+        output.write(header);
+        output.write(rule1);
+        output.write(rule2);
+        output.close();
+
+        File f2 = fileManager.newFile("rule2.drl");
+        output = new BufferedWriter(new FileWriter(f2));
+        output.write(header);
+        output.write(rule3);
+        output.close();
+
+        File f3 = fileManager.newFile("rule3.drl");
+        output = new BufferedWriter(new FileWriter(f3));
+        output.write(header);
+        output.write(rule1V2);
+        output.close();
+
+        String xml = "";
+        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
+        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
+        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
+        xml += "    <add> ";
+        xml += "        <resource source='http://localhost:9000/rule1.drl' type='DRL' />";
+        xml += "        <resource source='http://localhost:9000/rule2.drl' type='DRL' />";
+        xml += "    </add> ";
+        xml += "</change-set>";
+        File fxml = fileManager.newFile("changeset.xml");
+        output = new BufferedWriter(new FileWriter(fxml));
+        output.write(xml);
+        output.close();
+
+        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+        KnowledgeAgent kagent = this.createKAgent(kbase);
+
+        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
+
+        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
+
+        List<String> list = new ArrayList<String>();
+        ksession.setGlobal("list", list);
+        ksession.fireAllRules();
+        ksession.dispose();
+
+        assertEquals(3, list.size());
+        assertTrue(list.contains("rule1"));
+        assertTrue(list.contains("rule2"));
+        assertTrue(list.contains("rule3"));
+
+        list.clear();
+
+        xml = "";
+        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
+        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
+        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
+        xml += "    <add> ";
+        xml += "        <resource source='http://localhost:9000/rule3.drl' type='DRL' />";
+        xml += "    </add> ";
+        xml += "</change-set>";
+
+        fxml = fileManager.newFile("changeset.xml");
+        output = new BufferedWriter(new FileWriter(fxml));
+        output.write(xml);
+        output.close();
+
+        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
+
+        ksession = kbase.newStatefulKnowledgeSession();
+        list = new ArrayList<String>();
+        ksession.setGlobal("list", list);
+        ksession.fireAllRules();
+        ksession.dispose();
+
+        assertEquals(3, list.size());
+        assertTrue(list.contains("rule1-V2"));
+        assertTrue(list.contains("rule2"));
+        assertTrue(list.contains("rule3"));
+
+
+        // have to sleep here as linux lastModified does not do milliseconds
+        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
+        Thread.sleep(2000);
+
+        output = new BufferedWriter(new FileWriter(f2));
+        output.write(header);
+        output.write(rule3);
+        output.write(rule4);
+        output.close();
+        Thread.sleep(3000);
+
+        ksession = kbase.newStatefulKnowledgeSession();
+        list = new ArrayList<String>();
+        ksession.setGlobal("list", list);
+        ksession.fireAllRules();
+        ksession.dispose();
+
+        assertEquals(4, list.size());
+        assertTrue(list.contains("rule1-V2"));
+        assertTrue(list.contains("rule2"));
+        assertTrue(list.contains("rule3"));
+        assertTrue(list.contains("rule4"));
+
+
+        // have to sleep here as linux lastModified does not do milliseconds
+        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
+        Thread.sleep(2000);
+
+        //removes rule1 from rules3.drl and add a new definition for rule3 in that file
+        output = new BufferedWriter(new FileWriter(f3));
+        output.write(header);
+        output.write(rule3V2);
+        output.close();
+        Thread.sleep(3000);
+
+        ksession = kbase.newStatefulKnowledgeSession();
+        list = new ArrayList<String>();
+        ksession.setGlobal("list", list);
+        ksession.fireAllRules();
+        ksession.dispose();
+
+        assertEquals(3, list.size());
+        assertTrue(list.contains("rule2"));
+        assertTrue(list.contains("rule3-V2"));
+        assertTrue(list.contains("rule4"));
+
+        // have to sleep here as linux lastModified does not do milliseconds
+        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
+        Thread.sleep(2000);
+
+        //removes rule3 from rules3.drl
+        output = new BufferedWriter(new FileWriter(f3));
+        output.write(header);
+        output.close();
+        Thread.sleep(3000);
+
+        ksession = kbase.newStatefulKnowledgeSession();
+        list = new ArrayList<String>();
+        ksession.setGlobal("list", list);
+        ksession.fireAllRules();
+        ksession.dispose();
+
+        assertEquals(2, list.size());
+        assertTrue(list.contains("rule2"));
+        assertTrue(list.contains("rule4"));
+
+        // have to sleep here as linux lastModified does not do milliseconds
+        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
+        Thread.sleep(2000);
+
+        //removes rule3 from rules3.drl
+        f3.delete();
+        Thread.sleep(3000);
+
+        ksession = kbase.newStatefulKnowledgeSession();
+        list = new ArrayList<String>();
+        ksession.setGlobal("list", list);
+        ksession.fireAllRules();
+        ksession.dispose();
+
+        assertEquals(2, list.size());
+        assertTrue(list.contains("rule2"));
+        assertTrue(list.contains("rule4"));
+
+
+        // have to sleep here as linux lastModified does not do milliseconds
+        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
+        Thread.sleep(2000);
+
+        //adds rules1-V3 definition to rules2.drl
+        output = new BufferedWriter(new FileWriter(f2));
+        output.write(header);
+        output.write(rule1V3);
+        output.write(rule3);
+        output.write(rule4);
+        output.close();
+        Thread.sleep(3000);
+
+        ksession = kbase.newStatefulKnowledgeSession();
+        list = new ArrayList<String>();
+        ksession.setGlobal("list", list);
+        ksession.fireAllRules();
+        ksession.dispose();
+
+        assertEquals(4, list.size());
+        assertTrue(list.contains("rule1-V3"));
+        assertTrue(list.contains("rule2"));
+        //rule3 reapears because rules2.drl was reporcessed
+        assertTrue(list.contains("rule3"));
+        assertTrue(list.contains("rule4"));
+
+        kagent.monitorResourceChangeEvents(false);
+
+    }
+
      
 
     private static void writePackage(Object pkg, File p1file)
@@ -1017,6 +1227,101 @@
         }
     }
 
+
+    private KnowledgeAgent createKAgent(KnowledgeBase kbase) {
+        ResourceChangeScannerConfiguration sconf = ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfiguration();
+        sconf.setProperty("drools.resource.scanner.interval", "2");
+        ResourceFactory.getResourceChangeScannerService().configure(sconf);
+
+        //System.setProperty(KnowledgeAgentFactory.PROVIDER_CLASS_NAME_PROPERTY_NAME, "org.drools.agent.impl.KnowledgeAgentProviderImpl");
+
+        KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
+        aconf.setProperty("drools.agent.scanDirectories", "true");
+        aconf.setProperty("drools.agent.scanResources", "true");
+        // Testing incremental build here
+        aconf.setProperty("drools.agent.newInstance", "false");
+
+
+
+        KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent(
+                "test agent", kbase, aconf);
+
+        assertEquals("test agent", kagent.getName());
+
+        return kagent;
+    }
+
+    private String createCommonRule(String ruleName) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("rule ");
+        sb.append(ruleName);
+        sb.append("\n");
+        sb.append("when\n");
+        sb.append("then\n");
+        sb.append("list.add( drools.getRule().getName() );\n");
+        sb.append("end\n");
+
+        return sb.toString();
+    }
+
+    private String createCommonDSLRRule(String ruleName) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("rule ");
+        sb.append(ruleName);
+        sb.append("\n");
+        sb.append("when\n");
+        sb.append("There is a String\n");
+        sb.append("then\n");
+        sb.append("add rule's name to list;\n");
+        sb.append("end\n");
+
+        return sb.toString();
+    }
+
+    private String createCommonRule(String ruleName, String version) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("rule ");
+        sb.append(ruleName);
+        sb.append("\n");
+        sb.append("when\n");
+        sb.append("then\n");
+        sb.append("list.add( drools.getRule().getName()+\"-V" + version + "\");\n");
+        sb.append("end\n");
+
+        return sb.toString();
+    }
+
+    private String createCommonDSL() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[condition][]There is a String = String()\n");
+        sb.append("[consequence][]add rule's name to list = list.add( drools.getRule().getName() );\n");
+        return sb.toString();
+    }
+
+    private String createDummyFunction(String functionName) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("function void  ");
+        sb.append(functionName);
+        sb.append("(){\n");
+        sb.append(" System.out.println(\"Function executed\");\n");
+        sb.append("}\n");
+
+        return sb.toString();
+    }
+
+    private String createCommonFunction(String functionName, String valueToAdd) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("function void  ");
+        sb.append(functionName);
+        sb.append("(java.util.List myList,String source){\n");
+        sb.append(" myList.add(\"");
+        sb.append(valueToAdd);
+        sb.append(" from \"+source);\n");
+        sb.append("}\n");
+
+        return sb.toString();
+    }
+
     public static class ResultHandlerImpl implements ResultHandler {
 
         Object object;

Deleted: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/agent/KnowledgeAgentRemoveRuleChangeSetTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/agent/KnowledgeAgentRemoveRuleChangeSetTest.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/agent/KnowledgeAgentRemoveRuleChangeSetTest.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -1,365 +0,0 @@
-package org.drools.agent;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import junit.framework.TestCase;
-
-import org.drools.KnowledgeBase;
-import org.drools.KnowledgeBaseFactory;
-import org.drools.io.Resource;
-import org.drools.io.ResourceChangeScannerConfiguration;
-import org.drools.io.ResourceFactory;
-import org.drools.io.impl.ChangeSetImpl;
-import org.drools.io.impl.ResourceChangeNotifierImpl;
-import org.drools.io.impl.ResourceChangeScannerImpl;
-import org.drools.runtime.StatefulKnowledgeSession;
-import org.drools.runtime.pipeline.ResultHandler;
-import org.drools.util.DroolsStreamUtils;
-import org.drools.util.FileManager;
-import org.mortbay.jetty.Server;
-import org.mortbay.jetty.handler.ResourceHandler;
-
-public class KnowledgeAgentRemoveRuleChangeSetTest extends TestCase {
-
-    FileManager fileManager;
-    private Server server;
-
-    @Override
-    protected void setUp() throws Exception {
-        fileManager = new FileManager();
-        fileManager.setUp();
-        ((ResourceChangeScannerImpl) ResourceFactory.getResourceChangeScannerService()).reset();
-        ResourceFactory.getResourceChangeNotifierService().start();
-        ResourceFactory.getResourceChangeScannerService().start();
-
-        this.server = new Server(9000);
-        ResourceHandler resourceHandler = new ResourceHandler();
-        resourceHandler.setResourceBase(fileManager.getRootDirectory().getPath());
-        System.out.println("root : " + fileManager.getRootDirectory().getPath());
-
-        server.setHandler(resourceHandler);
-
-        server.start();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        fileManager.tearDown();
-        ResourceFactory.getResourceChangeNotifierService().stop();
-        ResourceFactory.getResourceChangeScannerService().stop();
-        ((ResourceChangeNotifierImpl) ResourceFactory.getResourceChangeNotifierService()).reset();
-        ((ResourceChangeScannerImpl) ResourceFactory.getResourceChangeScannerService()).reset();
-
-        server.stop();
-    }
-
-    public void testModifyFileUrlIncremental() throws Exception {
-
-        String header = "";
-        header += "package org.drools.test\n";
-        header += "global java.util.List list\n\n";
-
-        String rule1 = this.createCommonRule("rule1");
-        String rule2 = this.createCommonRule("rule2");
-        String rule3 = this.createCommonRule("rule3");
-        String rule4 = this.createCommonRule("rule4");
-
-        String function1 = this.createDummyFunction("function1");
-
-        String query1 = "";
-        query1 += "query \"all the Strings\"\n";
-        //query1 += "query \"rule1\"\n";
-        query1 += "     str : String()\n";
-        query1 += "end\n";
-
-        String type1 = "";
-        type1 += "declare Address\n";
-        type1 += "  number : int\n";
-        type1 += "  streetName : String\n";
-        type1 += "  city : String\n";
-        type1 += "end\n";
-
-
-        File f1 = fileManager.newFile("rule1.drl");
-        Writer output = new BufferedWriter(new FileWriter(f1));
-        output.write(header);
-        output.write(type1);
-        output.write(query1);
-        output.write(function1);
-        output.write(rule1);
-        output.write(rule2);
-        output.close();
-
-        File f2 = fileManager.newFile("rule2.drl");
-        output = new BufferedWriter(new FileWriter(f2));
-        output.write(header);
-        output.write(rule3);
-        output.close();
-
-        String xml = "";
-        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
-        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
-        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
-        xml += "    <add> ";
-        xml += "        <resource source='http://localhost:9000/rule1.drl' type='DRL' />";
-        xml += "        <resource source='http://localhost:9000/rule2.drl' type='DRL' />";
-        xml += "    </add> ";
-        xml += "</change-set>";
-        File fxml = fileManager.newFile("changeset.xml");
-        output = new BufferedWriter(new FileWriter(fxml));
-        output.write(xml);
-        output.close();
-
-        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
-        KnowledgeAgent kagent = this.createKAgent(kbase);
-        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
-
-        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
-        List<String> list = new ArrayList<String>();
-        ksession.setGlobal("list", list);
-        ksession.fireAllRules();
-        ksession.dispose();
-
-        assertEquals(3, list.size());
-        assertTrue(list.contains("rule1"));
-        assertTrue(list.contains("rule2"));
-        assertTrue(list.contains("rule3"));
-
-        list.clear();
-
-        // have to sleep here as linux lastModified does not do milliseconds
-        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
-        Thread.sleep(2000);
-
-
-        output = new BufferedWriter(new FileWriter(f1));
-        output.write(header);
-        output.write(rule2);
-        output.write(rule4);
-        output.close();
-        Thread.sleep(3000);
-
-        // Use the same session for incremental build test
-        ksession = kbase.newStatefulKnowledgeSession();
-        list = new ArrayList<String>();
-        ksession.setGlobal("list", list);
-        ksession.fireAllRules();
-        ksession.dispose();
-
-        assertEquals(3, list.size());
-
-        assertTrue(list.contains("rule3"));
-        assertTrue(list.contains("rule2"));
-        assertTrue(list.contains("rule4"));
-        kagent.monitorResourceChangeEvents(false);
-    }
-
-    public void testRemoveRuleChangeSet() throws Exception {
-
-        String header = "";
-        header += "package org.drools.test\n";
-        header += "global java.util.List list\n\n";
-
-        String rule1 = this.createCommonRule("rule1");
-        String rule2 = this.createCommonRule("rule2");
-        String rule3 = this.createCommonRule("rule3");
-
-        String function1 = this.createDummyFunction("function1");
-
-        File f1 = fileManager.newFile("rule1.drl");
-        Writer output = new BufferedWriter(new FileWriter(f1));
-        output.write(header);
-        output.write(function1);
-        output.write(rule1);
-        output.write(rule2);
-        output.close();
-
-        File f2 = fileManager.newFile("rule2.drl");
-        output = new BufferedWriter(new FileWriter(f2));
-        output.write(header);
-        output.write(rule3);
-        output.close();
-
-        String xml = "";
-        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
-        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
-        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
-        xml += "    <add> ";
-        xml += "        <resource source='http://localhost:9000/rule1.drl' type='DRL' />";
-        xml += "        <resource source='http://localhost:9000/rule2.drl' type='DRL' />";
-        xml += "    </add> ";
-        xml += "</change-set>";
-        final File fxml = fileManager.newFile("changeset.xml");
-        output = new BufferedWriter(new FileWriter(fxml));
-        output.write(xml);
-        output.close();
-
-        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
-        KnowledgeAgent kagent = this.createKAgent(kbase);
-        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
-
-        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
-        List<String> list = new ArrayList<String>();
-        ksession.setGlobal("list", list);
-        ksession.fireAllRules();
-        ksession.dispose();
-
-        assertEquals(3, list.size());
-        assertTrue(list.contains("rule1"));
-        assertTrue(list.contains("rule2"));
-        assertTrue(list.contains("rule3"));
-
-        list.clear();
-
-        //Creates a new changeSet that will delete Rule1 from kbase
-        ChangeSetImpl cs = new ChangeSetImpl();
-        cs.setKnowledgeDefinitionsRemoved(new HashMap<Resource, String>() {
-
-            {
-                Resource r = ResourceFactory.newUrlResource("http://localhost:9000/rule1.drl");
-                this.put(r, "rule1");
-            }
-        });
-
-        kagent.applyChangeSet(cs);
-
-
-        ksession = kbase.newStatefulKnowledgeSession();
-        list = new ArrayList<String>();
-        ksession.setGlobal("list", list);
-        ksession.fireAllRules();
-        ksession.dispose();
-
-        assertEquals(2, list.size());
-
-        assertTrue(list.contains("rule2"));
-        assertTrue(list.contains("rule3"));
-
-
-
-        //Creates a new changeSet that will try to delete Rule3 from rule1.drl.
-        //Because Rule3 is defined in rule2.drl, this shouldn't remove any rule.
-        cs = new ChangeSetImpl();
-        cs.setKnowledgeDefinitionsRemoved(new HashMap<Resource, String>() {
-
-            {
-                Resource r = ResourceFactory.newUrlResource("http://localhost:9000/rule1.drl");
-                this.put(r, "rule3");
-            }
-        });
-
-        kagent.applyChangeSet(cs);
-
-
-        ksession = kbase.newStatefulKnowledgeSession();
-        list = new ArrayList<String>();
-        ksession.setGlobal("list", list);
-        ksession.fireAllRules();
-        ksession.dispose();
-
-        assertEquals(2, list.size());
-
-        assertTrue(list.contains("rule2"));
-        assertTrue(list.contains("rule3"));
-
-
-        //Finally, remove Rule3
-        cs = new ChangeSetImpl();
-        cs.setKnowledgeDefinitionsRemoved(new HashMap<Resource, String>() {
-
-            {
-                Resource r = ResourceFactory.newUrlResource("http://localhost:9000/rule2.drl");
-                this.put(r, "rule3");
-            }
-        });
-
-        kagent.applyChangeSet(cs);
-
-
-        ksession = kbase.newStatefulKnowledgeSession();
-        list = new ArrayList<String>();
-        ksession.setGlobal("list", list);
-        ksession.fireAllRules();
-        ksession.dispose();
-
-        assertEquals(1, list.size());
-
-        assertTrue(list.contains("rule2"));
-
-    }
-    
-
-    private KnowledgeAgent createKAgent(KnowledgeBase kbase){
-        ResourceChangeScannerConfiguration sconf = ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfiguration();
-        sconf.setProperty("drools.resource.scanner.interval", "2");
-        ResourceFactory.getResourceChangeScannerService().configure(sconf);
-
-        KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
-        aconf.setProperty("drools.agent.scanDirectories", "true");
-        aconf.setProperty("drools.agent.scanResources", "true");
-        // Testing incremental build here
-        aconf.setProperty("drools.agent.newInstance", "false");
-        KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent(
-                "test agent", kbase, aconf);
-
-        assertEquals("test agent", kagent.getName());
-
-        return kagent;
-    }
-
-    private String createCommonRule(String ruleName) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("rule ");
-        sb.append(ruleName);
-        sb.append("\n");
-        sb.append("when\n");
-        sb.append("then\n");
-        sb.append("list.add( drools.getRule().getName() );\n");
-        sb.append("end\n");
-
-        return sb.toString();
-    }
-
-    private String createDummyFunction(String functionName) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("function void  ");
-        sb.append(functionName);
-        sb.append("(){\n");
-        sb.append(" System.out.println(\"Function executed\");\n");
-        sb.append("}\n");
-
-        return sb.toString();
-    }
-
-    private static void writePackage(Object pkg, File p1file)
-            throws IOException, FileNotFoundException {
-        FileOutputStream out = new FileOutputStream(p1file);
-        try {
-            DroolsStreamUtils.streamOut(out, pkg);
-        } finally {
-            out.close();
-        }
-    }
-
-    public static class ResultHandlerImpl implements ResultHandler {
-
-        Object object;
-
-        public void handleResult(Object object) {
-            this.object = object;
-        }
-
-        public Object getObject() {
-            return this.object;
-        }
-    }
-}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/ResourceDiffProducer.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/ResourceDiffProducer.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/ResourceDiffProducer.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -0,0 +1,31 @@
+/*
+ *  Copyright 2009 esteban.
+ * 
+ *  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.
+ *  under the License.
+ */
+
+package org.drools.agent;
+
+import java.util.Set;
+import org.drools.definition.KnowledgeDefinition;
+import org.drools.definitions.impl.KnowledgePackageImp;
+import org.drools.agent.impl.ResourceDiffResult;
+
+/**
+ *
+ * @author esteban
+ */
+public interface ResourceDiffProducer {
+    ResourceDiffResult diff(Set<KnowledgeDefinition> originalDefinitions, KnowledgePackageImp pkg);
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/BinaryResourceDiffProducerImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/BinaryResourceDiffProducerImpl.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/BinaryResourceDiffProducerImpl.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2009 JBoss Inc
+ *
+ * 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.drools.agent.impl;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.drools.definition.KnowledgeDefinition;
+import org.drools.definitions.impl.KnowledgePackageImp;
+import org.drools.agent.ResourceDiffProducer;
+import org.drools.rule.Rule;
+import org.drools.util.ReflectiveVisitor;
+
+/**
+ *
+ * @author esteban.aliverti at gmail.com
+ */
+public class BinaryResourceDiffProducerImpl extends ReflectiveVisitor implements ResourceDiffProducer {
+
+    private KnowledgePackageImp newPkg;
+
+    public ResourceDiffResult diff(Set<KnowledgeDefinition> originalDefinitions, KnowledgePackageImp pkg) {
+
+        this.newPkg = pkg;
+        
+        Set<KnowledgeDefinition> removed = new HashSet<KnowledgeDefinition>();
+
+
+        for (KnowledgeDefinition knowledgeDefinition : originalDefinitions) {
+            this.visit(knowledgeDefinition);
+        }
+
+
+        //return the whole new package as new
+        return new ResourceDiffResult(pkg, originalDefinitions);
+    }
+
+    
+    public void visitRule(final Rule rule){
+        //ok, so I got an old rule: is it modified in the new pkg? is it even present on it?
+        //newPkg.
+
+    }
+
+
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/DefaultResourceDiffProducerImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/DefaultResourceDiffProducerImpl.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/DefaultResourceDiffProducerImpl.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -0,0 +1,51 @@
+/*
+ *  Copyright 2009 esteban.
+ * 
+ *  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.
+ *  under the License.
+ */
+
+package org.drools.agent.impl;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.drools.RuntimeDroolsException;
+import org.drools.builder.KnowledgeBuilder;
+import org.drools.builder.KnowledgeBuilderFactory;
+import org.drools.definition.KnowledgeDefinition;
+import org.drools.definitions.impl.KnowledgePackageImp;
+import org.drools.agent.ResourceDiffProducer;
+
+/**
+ *
+ * @author esteban.aliverti at gmail.com
+ */
+public class DefaultResourceDiffProducerImpl implements ResourceDiffProducer {
+
+    public ResourceDiffResult diff(Set<KnowledgeDefinition> originalDefinitions, KnowledgePackageImp pkg) {
+
+        Set<KnowledgeDefinition> removed = new HashSet<KnowledgeDefinition>();
+
+        //put all the original definitions as removed
+        for (KnowledgeDefinition knowledgeDefinition : originalDefinitions) {
+            removed.add(knowledgeDefinition);
+        }
+
+        //return the whole new package as new
+        return new ResourceDiffResult(pkg, removed);
+
+
+    }
+
+
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/KnowledgeAgentImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/KnowledgeAgentImpl.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/KnowledgeAgentImpl.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -3,9 +3,9 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -36,9 +36,9 @@
 import org.drools.io.ResourceFactory;
 import org.drools.io.impl.ClassPathResource;
 import org.drools.io.impl.ResourceChangeNotifierImpl;
+import org.drools.agent.ResourceDiffProducer;
 import org.drools.rule.Function;
 import org.drools.rule.Package;
-import org.drools.rule.Query;
 import org.drools.rule.Rule;
 import org.drools.rule.TypeDeclaration;
 import org.drools.runtime.KnowledgeSessionConfiguration;
@@ -60,7 +60,6 @@
         ResourceChangeListener {
 
     private String name;
-    private ResourceMap resourcesMap;
     private Set<Resource> resourceDirectories;
     private KnowledgeBase kbase;
     private ResourceChangeNotifierImpl notifier;
@@ -71,6 +70,7 @@
     private Thread thread;
     private ChangeSetNotificationDetector changeSetNotificationDetector;
     private SemanticModules semanticModules;
+    private final RegisteredResourceMap registeredResources = new RegisteredResourceMap();
 
     /**
      * Default constructor for KnowledgeAgentImpl
@@ -83,7 +83,6 @@
             KnowledgeAgentConfiguration configuration) {
         this.name = name;
         this.kbase = kbase;
-        this.resourcesMap = new ResourceMap(this);
         this.resourceDirectories = new HashSet<Resource>();
         // this.listener = listener;
         this.listener = SystemEventListenerFactory.getSystemEventListener();
@@ -111,8 +110,9 @@
 
         monitorResourceChangeEvents(monitor);
 
-        buildResourceMapping();
 
+        autoBuildResourceMapping();
+
         this.listener.info("KnowledgeAgent created, with configuration:\nmonitorChangeSetEvents="
                 + monitor
                 + " scanResources="
@@ -131,7 +131,7 @@
     }
 
     public void applyChangeSet(ChangeSet changeSet) {
-        synchronized (this.resourcesMap) {
+        synchronized (this.registeredResources) {
             this.listener.info("KnowledgeAgent applying ChangeSet");
 
             ChangeSetState changeSetState = new ChangeSetState();
@@ -144,7 +144,7 @@
             // Rebuild or do an update to the KnowledgeBase
             buildKnowledgeBase(changeSetState);
             // Rebuild the resource mapping
-            buildResourceMapping();
+            //buildResourceMapping();
         }
     }
 
@@ -155,7 +155,7 @@
 
     public void processChangeSet(ChangeSet changeSet,
             ChangeSetState changeSetState) {
-        synchronized (this.resourcesMap) {
+        synchronized (this.registeredResources) {
             /*
              * Process the added resources from a ChangeSet by subscribing to
              * the notifier and inserting a new ResourceMapping.
@@ -181,18 +181,18 @@
                         }
 
                         ((InternalResource) child).setResourceType(((InternalResource) resource).getResourceType());
-                        if (this.resourcesMap.addResourceMapping(child, true)
+
+                        this.addDefinitionMapping(child, null, true);
+                        if (this.addResourceMapping(child, true)
                                 && changeSetState.incrementalBuild) {
                             changeSetState.addedResources.add(child);
                         }
                     }
                 } else {
-                    if (this.resourcesMap.addResourceMapping(resource, true)
+                    if (this.addResourceMapping(resource, true)
                             && changeSetState.incrementalBuild) {
-                        // parse the reource using DlrParser. save the packageDescr into a Map<Resource,PackageDescr
                         changeSetState.addedResources.add(resource);
 
-
                     }
                 }
             }
@@ -215,10 +215,11 @@
                     this.notifier.unsubscribeResourceChangeListener(this,
                             resource);
                 } else {
-                    ResourceMapEntry removedEntry = this.resourcesMap.removeResourceMapping(resource, true);
 
-                    if (removedEntry != null && changeSetState.incrementalBuild) {
-                        changeSetState.removedResourceMappings.add(removedEntry);
+                    Set<KnowledgeDefinition> definitions = this.removeResourceMapping(resource, true);
+
+                    if (definitions != null && changeSetState.incrementalBuild) {
+                        changeSetState.removedResourceMappings.put(resource, definitions);
                     }
                 }
             }
@@ -249,7 +250,7 @@
                             continue;
                         }
 
-                        if (this.resourcesMap.addResourceMapping(child, true)) {
+                        if (this.addResourceMapping(child, true)) {
                             ((InternalResource) child).setResourceType(((InternalResource) resource).getResourceType());
                             if (changeSetState.incrementalBuild) {
                                 changeSetState.addedResources.add(child);
@@ -257,45 +258,28 @@
                         }
                     }
                 } else {
-                    ResourceMapEntry modifiedMapping = this.resourcesMap.removeResourceMapping(resource, false);
-                    if (modifiedMapping == null) {
+
+                    boolean isResourceMapped = this.registeredResources.isResourceMapped(resource);
+
+                    if (!isResourceMapped) {
                         this.listener.warning("KnowledgeAgent subscribing to new resource="
                                 + resource
                                 + ", though it was marked as modified.");
-                        this.resourcesMap.addResourceMapping(resource, true);
+                        this.addResourceMapping(resource, true);
                         if (changeSetState.incrementalBuild) {
                             changeSetState.addedResources.add(resource);
                         }
                     } else {
-                        /*
-                         * Put a new one, but no need to subscribe or update
-                         * since this will be done in the buildResourceMapping
-                         * later
-                         */
-                        this.resourcesMap.addResourceMapping(resource, false);
                         if (changeSetState.incrementalBuild) {
-                            changeSetState.modifiedResourceMappings.add(modifiedMapping);
-                        }
-                    }
-                }
-            }
 
+                            Set<KnowledgeDefinition> definitions = this.removeResourceMapping(resource, true);
 
-            //Removes each knowledgeDefinition marked as deleted from resourceMap.
-            //The deletion from kbase will be performed after by buildKnowledgeBase()
-            for (Resource resource : changeSet.getKnowledgeDefinitionsRemoved().keySet()) {
+                            changeSetState.modifiedResourceMappings.put(resource, definitions);
 
-                KnowledgeDefinition removedDefinition = this.resourcesMap.removeResourceMappingEntry(resource, changeSet.getKnowledgeDefinitionsRemoved().get(resource));
-
-                if (removedDefinition == null) {
-                    this.listener.warning("Knowledge definition "
-                            + changeSet.getKnowledgeDefinitionsRemoved().get(resource)
-                            + " couldn't be removed from "
-                            + resource);
-                } else{
-                    //set the removedDefinition into the changeSetState so it
-                    //can be removed from kbase by buildKnowledgeBase().
-                    changeSetState.removedKnowledgeDefinitions.put(resource, removedDefinition);
+                            //adds a new empty mapping that will be filled in buildResourceMapping()
+                            this.addResourceMapping(resource, false);
+                        }
+                    }
                 }
             }
 
@@ -346,78 +330,112 @@
     public static class ChangeSetState {
 
         List<Resource> addedResources = new ArrayList<Resource>();
-        List<ResourceMapEntry> removedResourceMappings = new ArrayList<ResourceMapEntry>();
-        List<ResourceMapEntry> modifiedResourceMappings = new ArrayList<ResourceMapEntry>();
-        Map<Resource, KnowledgeDefinition> removedKnowledgeDefinitions = new HashMap<Resource, KnowledgeDefinition>();
+        /**
+         * Map of removed definitions. The Set of kdefinitions is the original
+         * definitions of the resource (before the deletion).
+         */
+        Map<Resource, Set<KnowledgeDefinition>> removedResourceMappings = new HashMap<Resource, Set<KnowledgeDefinition>>();
+        /**
+         * Map of modified definitions. The Set of kdefinitions is the original
+         * definitions of the resource (before the modification).
+         */
+        Map<Resource, Set<KnowledgeDefinition>> modifiedResourceMappings = new HashMap<Resource, Set<KnowledgeDefinition>>();
+        /**
+         *Map of created Packages. The agent will create this packages when
+         * processing added and modified resources
+         */
+        Map<Resource, KnowledgePackage> createdPackages = new LinkedHashMap<Resource, KnowledgePackage>();
         boolean scanDirectories;
         boolean incrementalBuild;
     }
 
+    private void buildResourceMapping(Package pkg, Resource resource) {
+        if (resource == null) {
+            this.listener.warning("KnowledgeAgent: trying to build a resource map for a null resource!");
+            return;
+        }
+        this.buildResourceMapping(pkg, resource, false);
+    }
+
+    private void buildResourceMapping(Package pkg, Resource resource, boolean autoDiscoverResource) {
+
+        synchronized (this.registeredResources) {
+            if (!autoDiscoverResource && resource == null) {
+                this.listener.warning("KnowledgeAgent: Impossible to map to a null resource! Use autoDiscoverResource = true ");
+                return;
+            }
+
+            if (autoDiscoverResource && resource != null) {
+                this.listener.warning("KnowledgeAgent: building resource map with resource set and autoDiscoverResource=true. Resource value wil be overwritten!");
+            }
+
+            for (Rule rule : pkg.getRules()) {
+                if (resource != null && !((InternalResource) resource).hasURL()) {
+                    this.listener.debug("KnowledgeAgent no resource mapped for rule="
+                            + rule);
+                }
+                if (autoDiscoverResource) {
+                    resource = rule.getResource();
+                }
+
+                this.addDefinitionMapping(resource, rule, true);
+            }
+
+            for (Process process : pkg.getRuleFlows().values()) {
+                if (resource != null && !((InternalResource) resource).hasURL()) {
+                    this.listener.debug("KnowledgeAgent no resource mapped for rule="
+                            + process);
+                }
+                if (autoDiscoverResource) {
+                    resource = ((org.drools.process.core.Process) process).getResource();
+                }
+
+                this.addDefinitionMapping(resource, process, true);
+            }
+
+            for (TypeDeclaration typeDeclaration : pkg.getTypeDeclarations().values()) {
+                if (resource != null && !((InternalResource) resource).hasURL()) {
+                    this.listener.debug("KnowledgeAgent no resource mapped for rule="
+                            + typeDeclaration);
+                }
+                if (autoDiscoverResource) {
+                    resource = typeDeclaration.getResource();
+                }
+
+                this.addDefinitionMapping(resource, typeDeclaration, true);
+            }
+
+            for (Function function : pkg.getFunctions().values()) {
+                if (resource != null && !((InternalResource) resource).hasURL()) {
+                    this.listener.debug("KnowledgeAgent no resource mapped for rule="
+                            + function);
+                }
+                if (autoDiscoverResource) {
+                    resource = function.getResource();
+                }
+                this.addDefinitionMapping(resource, function, true);
+            }
+        }
+    }
+
     /**
      * This indexes the rules, flows, type declarations, etc against their
      * respective URLs if they have any, to allow more fine grained removal and
      * not just removing of an entire package
      */
-    public void buildResourceMapping() {
+    public void autoBuildResourceMapping() {
         this.listener.debug("KnowledgeAgent building resource map");
-        synchronized (this.resourcesMap) {
+        synchronized (this.registeredResources) {
             RuleBase rbase = ((KnowledgeBaseImpl) this.kbase).ruleBase;
-            /*
-             * Iterate each package for the different types of
-             * KnowledgeDefinitions we want to track
-             */
-            for (Package pkg : rbase.getPackages()) {
-                for (Rule rule : pkg.getRules()) {
-                    Resource resource = rule.getResource();
-                    if (resource == null
-                            || !((InternalResource) resource).hasURL()) {
-                        this.listener.debug("KnowledgeAgent no resource mapped for rule="
-                                + rule);
-                        continue;
-                    }
-                    this.resourcesMap.putResourceMappingEntry(resource, rule);
-                }
 
-                for (Process process : pkg.getRuleFlows().values()) {
-                    Resource resource = ((org.drools.process.core.Process) process).getResource();
-                    if (resource == null
-                            || !((InternalResource) resource).hasURL()) {
-                        this.listener.debug("KnowledgeAgent no resource mapped for process="
-                                + process);
-                        continue;
-                    }
-                    this.resourcesMap.putResourceMappingEntry(resource, process);
-                }
-
-                for (TypeDeclaration typeDeclaration : pkg.getTypeDeclarations().values()) {
-                    Resource resource = typeDeclaration.getResource();
-                    if (resource == null
-                            || !((InternalResource) resource).hasURL()) {
-                        this.listener.debug("KnowledgeAgent no resource mapped for typeDeclaration="
-                                + typeDeclaration);
-                        continue;
-                    }
-                    this.resourcesMap.putResourceMappingEntry(resource,
-                            typeDeclaration);
-                }
-
-                for (Function function : pkg.getFunctions().values()) {
-                    Resource resource = function.getResource();
-                    if (resource == null
-                            || !((InternalResource) resource).hasURL()) {
-                        this.listener.debug("KnowledgeAgent no resource mapped for function="
-                                + function);
-                        continue;
-                    }
-                    this.resourcesMap.putResourceMappingEntry(resource,
-                            function);
-                }
+            for (Package pkg : rbase.getPackages()) {
+                this.buildResourceMapping(pkg, null, true);
             }
         }
     }
 
     public KnowledgeBase getKnowledgeBase() {
-        synchronized (this.resourcesMap) {
+        synchronized (this.registeredResources) {
             return this.kbase;
         }
     }
@@ -453,7 +471,7 @@
      */
     public void buildKnowledgeBase(ChangeSetState changeSetState) {
         this.listener.debug("KnowledgeAgent rebuilding KnowledgeBase using ChangeSet");
-        synchronized (this.resourcesMap) {
+        synchronized (this.registeredResources) {
 
             /*
              * Do the following only if we are building a new instance,
@@ -479,6 +497,57 @@
         this.listener.debug("KnowledgeAgent finished rebuilding KnowledgeBase using ChangeSet");
     }
 
+    private KnowledgePackageImp createPackageFromResource(Resource resource) {
+        return this.createPackageFromResource(resource, null);
+    }
+
+    private KnowledgePackageImp createPackageFromResource(Resource resource,KnowledgeBuilder kbuilder) {
+
+        if (kbuilder == null){
+            kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+        }
+
+        if (((InternalResource) resource).getResourceType() != ResourceType.PKG) {
+            kbuilder.add(resource, ((InternalResource) resource).getResourceType());
+            if (kbuilder.hasErrors()) {
+                this.listener.warning(
+                        "KnowledgeAgent has KnowledgeBuilder errors ", kbuilder.getErrors());
+            }
+            if (kbuilder.getKnowledgePackages().iterator().hasNext()){
+                return (KnowledgePackageImp) kbuilder.getKnowledgePackages().iterator().next();
+            }
+            return null;
+        } else {
+            // .pks are handled as a special case.
+            InputStream is = null;
+            KnowledgePackageImp kpkg = null;
+            try {
+                is = resource.getInputStream();
+                Object object = DroolsStreamUtils.streamIn(is);
+                if (object instanceof KnowledgePackageImp) {
+                    kpkg = ((KnowledgePackageImp) object);
+                } else {
+                    kpkg = new KnowledgePackageImp((Package) object);
+                }
+                for (Rule rule : kpkg.pkg.getRules()) {
+                    rule.setResource(resource);
+                }
+
+            } catch (Exception ex) {
+                this.listener.exception(new RuntimeException("KnowledgeAgent exception while trying to deserialize KnowledgeDefinitionsPackage  ", ex));
+            } finally {
+                try {
+                    if (is != null) {
+                        is.close();
+                    }
+                } catch (IOException e) {
+                    this.listener.exception(new RuntimeException("KnowledgeAgent exception while trying to close KnowledgeDefinitionsPackage  ", e));
+                }
+            }
+            return kpkg;
+        }
+    }
+
     /**
      * This method is meant to rebuild the entire KnowledgeBase. Cached
      * references outside of this Agent will no longer be valid to the current
@@ -503,7 +572,10 @@
             this.kbase = KnowledgeBaseFactory.newKnowledgeBase();
         }
 
-        addResourcesToKnowledgeBase(resourcesMap.getAllResources());
+        changeSetState.addedResources.clear();
+        changeSetState.addedResources.addAll(this.registeredResources.getAllResources());
+        addResourcesToKnowledgeBase(changeSetState);
+        //autoBuildResourceMapping();
 
         this.listener.info("KnowledgeAgent new KnowledgeBase now built and in use");
     }
@@ -520,7 +592,7 @@
             this.listener.warning("KnowledgeAgent incremental build of KnowledgeBase when newInstance is true");
         }
         // Incrementally rebuild the resources
-        synchronized (this.resourcesMap) {
+        synchronized (this.registeredResources) {
             this.listener.info("KnowledgeAgent performing an incremental build of the ChangeSet");
 
             // Create the knowledge base if one does not exist
@@ -530,30 +602,53 @@
 
             // Remove all rules from the resources removed and also those
             // modified
-            for (ResourceMapEntry resourceMapEntry : changeSetState.removedResourceMappings) {
-                for (KnowledgeDefinition kd : resourceMapEntry.getKnowledgeDefinitions()) {
+            for (Map.Entry<Resource, Set<KnowledgeDefinition>> entry : changeSetState.removedResourceMappings.entrySet()) {
+                for (KnowledgeDefinition kd : entry.getValue()) {
                     removeKnowledgeDefinitionFromBase(kd);
                 }
             }
 
-            for (ResourceMapEntry resourceMapEntry : changeSetState.modifiedResourceMappings) {
-                for (KnowledgeDefinition kd : resourceMapEntry.getKnowledgeDefinitions()) {
+
+
+
+            for (Map.Entry<Resource, Set<KnowledgeDefinition>> entry : changeSetState.modifiedResourceMappings.entrySet()) {
+
+                KnowledgePackageImp kpkg = createPackageFromResource(entry.getKey());
+
+                if (kpkg == null){
+                    continue;
+                }
+
+
+                ResourceDiffProducer rdp = new DefaultResourceDiffProducerImpl();
+                //ResourceDiffProducer rdp = new BinaryResourceDiffProducerImpl();
+
+                ResourceDiffResult diff = rdp.diff(entry.getValue(), kpkg);
+
+                for (KnowledgeDefinition kd : diff.getRemovedDefinitions()) {
                     removeKnowledgeDefinitionFromBase(kd);
                 }
-                changeSetState.addedResources.add(resourceMapEntry.getResource());
+
+                changeSetState.createdPackages.put(entry.getKey(), diff.getPkg());
+
             }
 
             /*
-             * Adds both the newly added resources and the modified resources
+             * Compile the newly added resources
              */
-            addResourcesToKnowledgeBase(changeSetState.addedResources);
+            for (Resource resource : changeSetState.addedResources) {
+                ///compile the new resource
+                KnowledgePackageImp kpkg = createPackageFromResource(resource);
+                if (kpkg == null){
+                    continue;
+                }
+                changeSetState.createdPackages.put(resource, kpkg);
+            }
+            //the added resources were already processed and converted to createdPackages.
+            changeSetState.addedResources.clear();
 
+            addResourcesToKnowledgeBase(changeSetState);
 
-            //Remove the individual knowledgeDefinitions marked as deleted by the
-            //changeset
-            for (Resource resource : changeSetState.removedKnowledgeDefinitions.keySet()) {
-                removeKnowledgeDefinitionFromBase(changeSetState.removedKnowledgeDefinitions.get(resource));
-            }
         }
         this.listener.info("KnowledgeAgent incremental build of KnowledgeBase finished and in use");
     }
@@ -563,22 +658,26 @@
      * @param kd
      */
     private void removeKnowledgeDefinitionFromBase(KnowledgeDefinition kd) {
-        if (kd instanceof Query) {
-            // @TODO Queries. The way JavaDialectRuntimeData removes rules
-            // doesn't apply to Queries (Even when Query is a subclass of Rule).
-        } else if (kd instanceof Rule) {
-            Rule rule = (Rule) kd;
-            this.listener.debug("KnowledgeAgent removing Rule=" + rule
-                    + " from package=" + rule.getPackageName());
-            this.kbase.removeRule(rule.getPackageName(), rule.getName());
-        } else if (kd instanceof Process) {
-            Process process = (Process) kd;
-            this.listener.debug("KnowledgeAgent removing Process=" + process);
-            this.kbase.removeProcess(process.getId());
-        } else if (kd instanceof TypeDeclaration) {
-            // @TODO Handle Type Declarations... is there a way to remove this?
-        } else if (kd instanceof Function) {
-            // @TODO functions and type declarations
+        try {
+            if (kd instanceof Rule) {
+                Rule rule = (Rule) kd;
+                this.listener.debug("KnowledgeAgent removing Rule=" + rule
+                        + " from package=" + rule.getPackageName());
+                this.kbase.removeRule(rule.getPackageName(), rule.getName());
+            } else if (kd instanceof Process) {
+                Process process = (Process) kd;
+                this.listener.debug("KnowledgeAgent removing Process=" + process);
+                this.kbase.removeProcess(process.getId());
+            } else if (kd instanceof TypeDeclaration) {
+                // @TODO Handle Type Declarations... is there a way to remove this?
+            } else if (kd instanceof Function) {
+                Function function = (Function) kd;
+                this.kbase.removeFunction(function.getNamespace(), function.getName());
+            }
+        } catch (IllegalArgumentException e) {
+            //it could be possible that a definition does not longer exists
+            //in the kbase.
+            this.listener.warning(e.getMessage());
         }
     }
 
@@ -588,63 +687,42 @@
      *
      * @param resources
      */
-    private void addResourcesToKnowledgeBase(Collection<Resource> resources) {
+    private void addResourcesToKnowledgeBase(ChangeSetState changeSetState) {
 
-        KnowledgeBuilder kbuilder = null;
+        KnowledgeBuilder kbuilder =  KnowledgeBuilderFactory.newKnowledgeBuilder();;
         List<Package> packages = new ArrayList<Package>();
-        for (Resource resource : resources) {
-            /*
-             * If it's not a PKG, clearly we need the knowledge builder, so
-             * build it
-             */
-            if (((InternalResource) resource).getResourceType() != ResourceType.PKG) {
-                this.listener.debug("KnowledgeAgent building resource="
-                        + resource);
-                if (kbuilder == null) {
-                    kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
-                }
-                kbuilder.add(resource, ((InternalResource) resource).getResourceType());
-            } else {
-                // For PKG (.pks) just add them
-                this.listener.debug("KnowledgeAgent obtaining pkg resource="
-                        + resource);
 
-                InputStream is = null;
-                try {
-                    // .pks are handled as a special case.
-                    is = resource.getInputStream();
-                    Object object = DroolsStreamUtils.streamIn(is);
-                    Package pkg = null;
-                    if (object instanceof KnowledgePackage) {
-                        pkg = ((KnowledgePackageImp) object).pkg;
+        for (Resource resource : changeSetState.addedResources) {
+            KnowledgePackageImp createdPackage = this.createPackageFromResource(resource, kbuilder);
+            changeSetState.createdPackages.put(resource, createdPackage);
 
-                    } else {
-                        pkg = (Package) object;
-                    }
-                    for (Rule rule : pkg.getRules()) {
-                        rule.setResource(resource);
-                    }
+        }
 
-                    packages.add(pkg);
-                } catch (Exception e) {
-                    this.listener.exception(new RuntimeException(
-                            "KnowledgeAgent exception while trying to deserialize KnowledgeDefinitionsPackage  ",
-                            e));
-                } finally {
-                    try {
-                        if (is != null) {
-                            is.close();
-                        }
-                    } catch (IOException e) {
-                        this.listener.exception(new RuntimeException(
-                                "KnowledgeAgent exception while trying to close KnowledgeDefinitionsPackage  ",
-                                e));
-                    }
+
+        for (Map.Entry<Resource, KnowledgePackage> entry : changeSetState.createdPackages.entrySet()) {
+            // For PKG (.pks) just add them
+            Resource resource = entry.getKey();
+            this.listener.debug("KnowledgeAgent obtaining pkg resource="
+                    + resource);
+
+            try {
+                // .pks are handled as a special case.
+                Package pkg = ((KnowledgePackageImp) entry.getValue()).pkg;
+                for (Rule rule : pkg.getRules()) {
+                    rule.setResource(resource);
                 }
+                packages.add(pkg);
+
+                this.buildResourceMapping(pkg, resource);
+            } catch (Exception e) {
+                this.listener.exception(new RuntimeException(
+                        "KnowledgeAgent exception while trying to deserialize KnowledgeDefinitionsPackage  ",
+                        e));
             }
         }
 
-        if (kbuilder != null) {
+        if (kbuilder
+                != null) {
             // Log any errors we come across
             if (kbuilder.hasErrors()) {
                 this.listener.warning(
@@ -671,6 +749,10 @@
      */
     public String getName() {
         return this.name;
+
+
+
+
     }
 
     /**
@@ -695,6 +777,84 @@
     }
 
     /**
+     *
+     * @param resource
+     * @param notify
+     * @return
+     */
+    public boolean addResourceMapping(Resource resource, boolean notify) {
+        boolean newMapping = this.registeredResources.createNewResourceEntry(resource);
+
+        if (notify && newMapping) {
+            this.listener.debug("KnowledgeAgent notifier subscribing to resource="
+                    + resource);
+            this.notifier.subscribeResourceChangeListener(this,
+                    resource);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Add an resource/definition entry to registeredResources. Optionaly it
+     * adds a listener to the resource added.
+     * @param resource
+     * @param definition
+     * @param notify
+     * @return if the resource/definition didn't exist in registeredResources.
+     */
+    public boolean addDefinitionMapping(Resource resource, KnowledgeDefinition definition, boolean notify) {
+
+        if (resource == null) {
+            listener.warning("KnowledgeAgent: impossible to add a map for a null resource! skiping.");
+            return false;
+        }
+
+        this.listener.debug("KnowledgeAgent mapping resource="
+                + resource + " to KnowledgeDefinition=" + definition);
+
+        boolean isNewResource = this.registeredResources.isResourceMapped(resource);
+
+        boolean isNewDefinition = true;
+
+        if (definition != null) {
+            isNewDefinition = this.registeredResources.putDefinition(resource, definition);
+        }
+
+        if (notify && isNewResource) {
+            this.listener.debug("KnowledgeAgent notifier subscribing to resource="
+                    + resource);
+
+            this.notifier.subscribeResourceChangeListener(this,
+                    resource);
+        }
+
+        return isNewDefinition;
+    }
+
+    public Set<KnowledgeDefinition> removeResourceMapping(Resource resource,
+            boolean unsubscribe) {
+        this.listener.debug("KnowledgeAgent removing mappings for resource="
+                + resource + " with unsubscribe=" + unsubscribe);
+        Set<KnowledgeDefinition> definitions = this.registeredResources.removeDefinitions(resource);
+
+
+
+
+        if (definitions != null) {
+            if (unsubscribe) {
+                this.listener.debug("KnowledgeAgent notifier unsubscribing to resource="
+                        + resource);
+
+                this.notifier.unsubscribeResourceChangeListener(
+                        this, resource);
+            }
+        }
+        return definitions;
+
+    }
+
+    /**
      * A class to monitor and handle ChangeSets fired by the
      * ResourceChangeNotifier on a separate service (or process).
      *
@@ -743,252 +903,63 @@
         }
     }
 
-    /**
-     * Maps a set of KnowledgeDefinitions to the resource that created them so
-     * we can perform incremental building of a KnowledgeBase.
-     *
-     * @author Mark Proctor
-     */
-    public static class ResourceMapEntry {
+    private static class RegisteredResourceMap {
 
-        private final Resource resource;
-        private Set<KnowledgeDefinition> knowledgeDefinitions;
+        private Map<Resource, Set<KnowledgeDefinition>> map = new HashMap<Resource, Set<KnowledgeDefinition>>();
 
-        public ResourceMapEntry(Resource resource) {
-            this.resource = resource;
-            this.knowledgeDefinitions = new HashSet<KnowledgeDefinition>();
-        }
-
-        public Resource getResource() {
-            return resource;
-        }
-
-        public Set<KnowledgeDefinition> getKnowledgeDefinitions() {
-            return knowledgeDefinitions;
-        }
-    }
-
-    /**
-     * A Bidirectional map of Resources to KnowledgeDefinitions.This allows you
-     * to go both ways due to a KnowledgeDefinition being able to be overwritten
-     * by multiple resources, and we only want to track the Resource responsible
-     * as tagged by the KnowledgeBase for creating that resource.
-     *
-     * @author Sam Romano
-     */
-    public static class ResourceMap {
-
-        private final KnowledgeAgentImpl agent;
-        private Map<Resource, ResourceMapEntry> resourceMappings;
-        private Map<KnowledgeDefinition, Resource> knowledgeDefinitionMappings;
-
-        public ResourceMap(KnowledgeAgentImpl agent) {
-            this.agent = agent;
-            this.resourceMappings = new HashMap<Resource, ResourceMapEntry>();
-            this.knowledgeDefinitionMappings = new HashMap<KnowledgeDefinition, Resource>();
-        }
-
         /**
+         * Creates a new entry for resource with an empty Set<KnowledgeDefinition>.
+         * If the map already contains an entry for the resource, then nothing
+         * is changed.
          * @param resource
-         *            The resource to add to the Map
-         * @param notify
-         *            True if you want to notify the listener, false otherwise.
-         * @return True if it was added, false otherwise.
+         * @return true if the resource was not previously mapped.
          */
-        public boolean addResourceMapping(Resource resource, boolean notify) {
-            ResourceMapEntry rsrcMapping = this.resourceMappings.get(resource);
-            if (rsrcMapping == null) {
-                rsrcMapping = new ResourceMapEntry(resource);
-                this.resourceMappings.put(resource, rsrcMapping);
-                if (notify) {
-                    this.agent.listener.debug("KnowledgeAgent notifier subscribing to resource="
-                            + resource);
-
-                    this.agent.notifier.subscribeResourceChangeListener(agent,
-                            resource);
-                }
+        public boolean createNewResourceEntry(Resource resource) {
+            if (!this.isResourceMapped(resource)) {
+                this.map.put(resource, new HashSet<KnowledgeDefinition>());
                 return true;
             }
             return false;
         }
 
-        /**
-         * Returns the old ResourceMapping mapped to the Resource. If it finds a
-         * resource mapping, it will unsubscribe from the
-         * ResourceChangeListener.
-         *
-         * @param resource
-         * @param unsubscribe
-         *            True if you want to unsubscribe on a successful removal,
-         *            false otherwise... normally false on attempting to remove
-         *            entries for Modifications
-         * @return The old resourceMapping with the KnowledgeDefinitions that it
-         *         use to have
-         */
-        public ResourceMapEntry removeResourceMapping(Resource resource,
-                boolean unsubscribe) {
-            this.agent.listener.debug("KnowledgeAgent removing mappings for resource="
-                    + resource + " with unsubscribe=" + unsubscribe);
-            ResourceMapEntry rsrcMapping = this.resourceMappings.remove(resource);
-            if (rsrcMapping != null) {
-                if (unsubscribe) {
-                    this.agent.listener.debug("KnowledgeAgent notifier unsubscribing to resource="
-                            + resource);
-                    this.agent.notifier.unsubscribeResourceChangeListener(
-                            agent, resource);
-                }
+        public boolean putDefinition(Resource resource, KnowledgeDefinition definition) {
+            Set<KnowledgeDefinition> defList = map.get(resource);
+            if (defList == null) {
+                defList = new HashSet<KnowledgeDefinition>();
+                this.map.put(resource, defList);
+            }
 
-                for (KnowledgeDefinition kd : rsrcMapping.knowledgeDefinitions) {
-                    this.knowledgeDefinitionMappings.remove(kd);
-                }
+            //support for lazy loading
+            if (definition != null) {
+                boolean isNew = defList.add(definition);
+                return isNew;
             }
-            return rsrcMapping;
+
+            return false;
         }
 
-        public Set<Resource> getAllResources() {
-            return this.resourceMappings.keySet();
+        public Set<KnowledgeDefinition> removeDefinitions(Resource resource) {
+            return this.map.remove(resource);
         }
 
-        /**
-         * Maps a resource to the knowledge Definition, and vice versa for
-         * bidirectional mapping and integrity. If the resource is not mapped at
-         * all, this will subscribe the agent specified to this ResourceMap to
-         * listen for those changes.
-         *
-         * @param resource
-         * @param kd
-         * @return The old resource the KnowledgeDefinition use to be mapped to
-         *         if it was
-         */
-        public Resource putResourceMappingEntry(Resource resource,
-                KnowledgeDefinition kd) {
-            ResourceMapEntry rsrcMapping = this.resourceMappings.get(resource);
-            if (rsrcMapping == null) {
-                addResourceMapping(resource, true);
-                rsrcMapping = this.resourceMappings.get(resource);
-            }
-            /*
-             * If adding this returns true, then we need to map it the other
-             * way, otherwise don't bother with the bidirectional logic and
-             * waste time - essentially we know we mapped it before.
-             */
-            if (rsrcMapping.knowledgeDefinitions.add(kd)) {
-                this.agent.listener.debug("KnowledgeAgent mapping resource="
-                        + resource + " to KnowledgeDefinition=" + kd);
-
-                Resource oldRsrc = this.knowledgeDefinitionMappings.put(kd,
-                        resource);
-                /*
-                 * If an oldRsrc exists, make sure we remove the kd from that
-                 * mapping - but dont unsubscribe from it as the resource is
-                 * still being compiled in the KnowledgeBase, we need to know of
-                 * its updates
-                 */
-                ResourceMapEntry oldRsrcMapping = this.resourceMappings.get(oldRsrc);
-                if (oldRsrcMapping != null) {
-                    this.agent.listener.debug("KnowledgeAgent removing reference from resource="
-                            + oldRsrc + " to KnowledgeDefinition=" + kd);
-                    oldRsrcMapping.getKnowledgeDefinitions().remove(kd);
-                }
-
-                return oldRsrc;
-            }
-            return null;
+        public Set<KnowledgeDefinition> getDefinitions(Resource resource) {
+            return this.getDefinitions(resource, false);
         }
 
-        public boolean removeResourceMappingEntry(Resource resource,
-                KnowledgeDefinition kd) {
-            ResourceMapEntry rsrcMapping = this.resourceMappings.get(resource);
-            if (rsrcMapping != null) {
-                /*
-                 * If the above didn't remove the kd, then we don't do the
-                 * bidirectional removal
-                 */
-                if (rsrcMapping.getKnowledgeDefinitions().remove(kd)) {
-                    this.knowledgeDefinitionMappings.remove(kd);
-                    return true;
-                }
+        public Set<KnowledgeDefinition> getDefinitions(Resource resource, boolean returnEmptyIfNull) {
+            Set<KnowledgeDefinition> definitions = this.map.get(resource);
+            if (returnEmptyIfNull && definitions == null) {
+                definitions = new HashSet<KnowledgeDefinition>();
             }
-            return false;
+            return definitions;
         }
 
-        /**
-         * Removes a resource's knowledge definition from the maps given its name.
-         * To find the right knowledge definition, this method uses
-         * {@link #getKnowledgeDefinitionByName(org.drools.io.Resource, java.lang.String).
-         *
-         * <b>Author:<b> Esteban Aliverti.
-         *
-         * @param resource the resource where the kdefinition will be seached.
-         * @param knowledgeDefinitionName the name of the kdefinition.
-         * @return The removed kdefinition if it was found and succesfully
-         * removed. Oterwise, null.
-         */
-        public KnowledgeDefinition removeResourceMappingEntry(Resource resource,
-                String knowledgeDefinitionName) {
-
-            ResourceMapEntry rsrcMapping = this.resourceMappings.get(resource);
-
-
-            if (rsrcMapping != null) {
-                KnowledgeDefinition foundDefinition = this.getKnowledgeDefinitionByName(resource, knowledgeDefinitionName);
-                if (rsrcMapping.getKnowledgeDefinitions().remove(foundDefinition)) {
-                    this.knowledgeDefinitionMappings.remove(foundDefinition);
-                    return foundDefinition;
-                }
-            }
-
-
-            return null;
+        public boolean isResourceMapped(Resource resource) {
+            return this.map.containsKey(resource);
         }
 
-        /**
-         * Return a knowledgeDeinition of a resource fiven its name. If
-         * the resource doesn't have a kdefinition with he specified name, null
-         * is returned.
-         * If the resouce has more than one kdefinition with the given name
-         * (according to some tests I made, functions and queries could have
-         * the same name), the first kdefinition found is returned. The search
-         * order is Rule/Query, Function, TypeDeclaration.
-         *
-         * <b>Author:<b> Esteban Aliverti.
-         *
-         * @param resource the resource where the kdefinition will be seached.
-         * @param knowledgeDefinitionName the name of the kdefinition.
-         * @return the kdefinition with the given name, or null if it doesn't exist.
-         *
-         */
-        private KnowledgeDefinition getKnowledgeDefinitionByName(Resource resource, String knowledgeDefinitionName) {
-
-            KnowledgeDefinition foundDefinition = null;
-
-            ResourceMapEntry rsrcMapping = this.resourceMappings.get(resource);
-            if (rsrcMapping != null) {
-
-
-                for (KnowledgeDefinition kd : rsrcMapping.knowledgeDefinitions) {
-
-                    String currentKDefinitionName = "";
-
-                    if (kd instanceof Rule) {
-                        //rules and queries
-                        currentKDefinitionName = ((Rule) kd).getName();
-                    } else if (kd instanceof Function) {
-                        currentKDefinitionName = ((Function) kd).getName();
-                    } else if (kd instanceof TypeDeclaration) {
-                        currentKDefinitionName = ((TypeDeclaration) kd).getTypeName();
-                    }
-
-                    if (currentKDefinitionName.equals(knowledgeDefinitionName)) {
-                        foundDefinition = kd;
-                        break;
-                    }
-
-                }
-
-            }
-
-            return foundDefinition;
+        public Set<Resource> getAllResources() {
+            return this.map.keySet();
         }
     }
 
@@ -1004,6 +975,8 @@
         if (this.changeSetNotificationDetector != null) {
             this.changeSetNotificationDetector.monitor = false;
 
+
+
         }
     }
 }

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/ResourceDiffResult.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/ResourceDiffResult.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/ResourceDiffResult.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -0,0 +1,45 @@
+/*
+ *  Copyright 2009 esteban.
+ * 
+ *  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.
+ *  under the License.
+ */
+
+package org.drools.agent.impl;
+
+import java.util.Set;
+import org.drools.definition.KnowledgeDefinition;
+import org.drools.definition.KnowledgePackage;
+
+/**
+ *
+ * @author esteban.aliverti at gmail.com
+ */
+public class ResourceDiffResult {
+    private KnowledgePackage pkg;
+    private Set<KnowledgeDefinition> removedDefinitions;
+
+    public ResourceDiffResult(KnowledgePackage pkg, Set<KnowledgeDefinition> removedDefinitions) {
+        this.pkg = pkg;
+        this.removedDefinitions = removedDefinitions;
+    }
+
+    public KnowledgePackage getPkg() {
+        return pkg;
+    }
+
+    public Set<KnowledgeDefinition> getRemovedDefinitions() {
+        return removedDefinitions;
+    }
+
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/definitions/impl/KnowledgePackageImp.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/definitions/impl/KnowledgePackageImp.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/definitions/impl/KnowledgePackageImp.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -59,4 +59,6 @@
     public void writeExternal(ObjectOutput out) throws IOException {
         this.pkg.writeExternal( out );
     }
+
+
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/KnowledgeBaseImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/KnowledgeBaseImpl.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/KnowledgeBaseImpl.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -172,6 +172,12 @@
                                   ruleName );
     }
 
+    public void removeFunction(String packageName,
+                           String ruleName) {
+        this.ruleBase.removeFunction( packageName,
+                                  ruleName );
+    }
+
     public void removeProcess(String processId) {
         this.ruleBase.removeProcess( processId );
     }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/io/impl/ChangeSetImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/io/impl/ChangeSetImpl.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/io/impl/ChangeSetImpl.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -2,11 +2,8 @@
 
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
 
 import org.drools.ChangeSet;
-import org.drools.definition.KnowledgeDefinition;
 import org.drools.io.Resource;
 
 public class ChangeSetImpl implements ChangeSet {
@@ -16,7 +13,7 @@
 
     //Map of removed kdefinitions. The key is the resource and the string is
     //the knowledgeDefinition's name.
-    private Map<Resource,String>  knowledgeDefinitionsRemoved = new HashMap<Resource, String>();
+    private Collection<String>  knowledgeDefinitionsRemoved = Collections.<String>emptyList();
     
     public ChangeSetImpl() {
         
@@ -46,11 +43,11 @@
         this.resourcesModified = resourcesModified;
     }
 
-    public Map<Resource, String> getKnowledgeDefinitionsRemoved() {
+    public Collection<String> getKnowledgeDefinitionsRemoved() {
         return knowledgeDefinitionsRemoved;
     }
 
-    public void setKnowledgeDefinitionsRemoved(Map<Resource, String> knowledgeDefinitionsRemoved) {
+    public void setKnowledgeDefinitionsRemoved(Collection<String> knowledgeDefinitionsRemoved) {
         this.knowledgeDefinitionsRemoved = knowledgeDefinitionsRemoved;
     }
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Function.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Function.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Function.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -10,6 +10,7 @@
 
 public class Function implements  KnowledgeDefinition, Dialectable, Externalizable {
     private String name;
+    private String namespace;
     private String dialect;
     private Resource resource;
 
@@ -17,8 +18,9 @@
 
     }
 
-    public Function(String name,
+    public Function(String namespace, String name,
                     String dialect) {
+        this.namespace = namespace;
         this.name = name;
         this.dialect = dialect;
     }
@@ -39,6 +41,16 @@
         this.resource = resource;
     }
 
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    
+
     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
         name    = (String)in.readObject();
         dialect = (String)in.readObject();

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -33,6 +33,7 @@
 import org.drools.base.ClassFieldAccessorStore;
 import org.drools.common.DroolsObjectInputStream;
 import org.drools.common.DroolsObjectOutputStream;
+import org.drools.definition.KnowledgeDefinition;
 import org.drools.definition.process.Process;
 import org.drools.definition.type.FactType;
 import org.drools.facttemplates.FactTemplate;
@@ -555,4 +556,5 @@
         this.classFieldAccessorStore.setClassFieldAccessorCache( classFieldAccessorCache );
     }
 
+
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/ChangeSetSemanticModule.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/ChangeSetSemanticModule.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/ChangeSetSemanticModule.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -6,6 +6,7 @@
 import org.drools.xml.changeset.AddHandler;
 import org.drools.xml.changeset.ChangeSetHandler;
 import org.drools.xml.changeset.DecisionTableConfigurationHandler;
+import org.drools.xml.changeset.DefinitionHandler;
 import org.drools.xml.changeset.ModifyHandler;
 import org.drools.xml.changeset.RemoveHandler;
 import org.drools.xml.changeset.ResourceHandler;
@@ -29,6 +30,9 @@
         
         addHandler( "resource",
                     new ResourceHandler() );  
+
+        addHandler( "definition",
+                    new DefinitionHandler() );
         
         addHandler( "decisiontable-conf",
                     new DecisionTableConfigurationHandler() );             

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/changeset/DefinitionHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/changeset/DefinitionHandler.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/changeset/DefinitionHandler.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -0,0 +1,92 @@
+package org.drools.xml.changeset;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+import org.drools.xml.BaseAbstractHandler;
+import org.drools.xml.ExtensibleXmlParser;
+import org.drools.xml.Handler;
+import org.w3c.dom.Element;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+public class DefinitionHandler extends BaseAbstractHandler
+    implements
+    Handler {
+
+
+    public class DefinitionHandlerData {
+        private String packageName;
+        private String name;
+
+        public DefinitionHandlerData(String packageName, String name) {
+            this.packageName = packageName;
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getPackageName() {
+            return packageName;
+        }
+
+        
+    }
+
+    public DefinitionHandler() {
+        if ( (this.validParents == null) && (this.validPeers == null) ) {
+            this.validParents = new HashSet(1);
+            this.validParents.add( Collection.class );
+
+            this.validPeers = new HashSet(2);
+            this.validPeers.add( null );
+            this.validPeers.add( DefinitionHandler.DefinitionHandlerData.class );
+
+            this.allowNesting = true;
+        }        
+    }    
+    
+    public Object start(String uri,
+                        String localName,
+                        Attributes attrs,
+                        ExtensibleXmlParser parser) throws SAXException {
+        parser.startElementBuilder( localName,
+                                    attrs );      
+        
+        
+        String packageName = attrs.getValue( "package" );
+        String name = attrs.getValue( "name" );
+        
+        emptyAttributeCheck( localName,
+                             "package",
+                             packageName,
+                             parser );
+        
+        emptyAttributeCheck( localName,
+                             "name",
+                             name,
+                             parser );        
+        DefinitionHandler.DefinitionHandlerData data = new DefinitionHandlerData(packageName, name);
+        
+        return data;
+    }
+
+    public Object end(String uri,
+                      String localName,
+                      ExtensibleXmlParser parser) throws SAXException {
+        final Element element = parser.endElementBuilder();
+        
+        final Collection collection = (Collection) parser.getParent();
+        final DefinitionHandlerData data = ( DefinitionHandlerData ) parser.getCurrent();
+        collection.add( data );
+        return data;
+    }
+
+    
+    public Class< ? > generateNodeFor() {
+        return DefinitionHandler.DefinitionHandlerData.class;
+    }
+
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/changeset/RemoveHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/changeset/RemoveHandler.java	2009-12-24 16:09:54 UTC (rev 30812)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/xml/changeset/RemoveHandler.java	2009-12-24 17:54:14 UTC (rev 30813)
@@ -1,18 +1,12 @@
 package org.drools.xml.changeset;
 
-import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 
 import org.drools.ChangeSet;
-import org.drools.builder.ResourceType;
 import org.drools.io.Resource;
 import org.drools.io.impl.ChangeSetImpl;
-import org.drools.io.impl.ClassPathResource;
-import org.drools.io.impl.KnowledgeResource;
-import org.drools.io.impl.UrlResource;
-import org.drools.util.StringUtils;
 import org.drools.xml.BaseAbstractHandler;
 import org.drools.xml.ExtensibleXmlParser;
 import org.drools.xml.Handler;
@@ -55,9 +49,32 @@
         final Element element = parser.endElementBuilder();
         
         final ChangeSetImpl changeSet = (ChangeSetImpl) parser.getParent();
-        final Collection removed = ( Collection ) parser.getCurrent();
-        changeSet.setResourcesRemoved( removed );
-        return removed;
+        
+        Collection<Resource> removedResources = new ArrayList<Resource>();
+        Collection<String> removedDefinitions = new ArrayList<String>();
+
+        for (Object object : ( Collection ) parser.getCurrent()) {
+            if (object instanceof DefinitionHandler.DefinitionHandlerData){
+                DefinitionHandler.DefinitionHandlerData data = (DefinitionHandler.DefinitionHandlerData)object;
+
+                String fullName = data.getPackageName();
+
+                if (fullName == null || fullName.equals("")){
+                    fullName = data.getName();
+                }else{
+                    fullName += "."+data.getName();
+                }
+
+                removedDefinitions.add(fullName);
+
+            }else if (object instanceof Resource){
+                removedResources.add((Resource)object);
+            }
+        }
+
+        changeSet.setResourcesRemoved( removedResources );
+        changeSet.setKnowledgeDefinitionsRemoved( removedDefinitions );
+        return ( Collection ) parser.getCurrent();
     }
 
     



More information about the jboss-svn-commits mailing list