PS: I think I know where the confusion lies. You consider maps just another kind of Java object you attempt to treat like you would treat other objects - by examining their member fields and methods, constructors, etc.
I was under the impression that instances of java.util.Maps would be treated specially by your engine, i.e., as a collection of properties. I concluded that since in the MVEL dialect you allow the use of the [] operator in a LHS. It seemed the straightforward thing to do, given the conceptual equivalency of beans and (fixed-keyset) maps. Maybe I should rephrase my question then. How do I work with facts for which the set of properties is not known when I compile the Java portions of the program in which I'm embedding my Drools rules? - Godmar On Wed, Feb 20, 2008 at 12:53 PM, Godmar Back <[EMAIL PROTECTED]> wrote: > On Feb 20, 2008 12:30 PM, Edson Tirelli <[EMAIL PROTECTED]> wrote: > > > > Godmar, > > > > Shadow Facts are a necessary evil in current version. Basically what > they > > do is keep the working memory consistent in face of attribute changes on > the > > facts, that may happen both internally and externally to the working > memory. > > Our implementation to shadow facts is a lazy proxy that caches the > > values until a safe point to synchronize the actual attribute value with > the > > one seen by the engine. > > > > So, the question is: given an object: > > > > (Map) fact > > > > How can we create an identical copy of it (shadow), if there is no > > "clone" operation? > > Can you explain why you require the use of "clone()"? > > Cloning a map is otherwise easy - it's also referred to as a "shallow > copy" -- HashMap's HashMap(Map) constructor will do it. > > http://java.sun.com/j2se/1.4.2/docs/api/java/util/HashMap.html#HashMap(java.util.Map) > I know you know that, so explain what necessitates the use of clone(). > > > > More than that, the shadow must be a subclass of it. > > java.util.HashMap is a subclass of Map. > > > > > > Most Collection and Map implementations have a single parameter > > constructor that allows us to do: > > > > > > proxy = (ShadowProxy) this.shadowClass.getConstructor( new Class[]{cls} > > ).newInstance( new Object[]{fact} ); > > > > But the SingletonMap you were using does not accept that constructor. > > So, one way is to explicit check if the fact is a SingletonMap and handle > it > > accordingly, but that is a specific class hack... is there any general > > solution we can use? > > > > Forget about the SingletonMap. That was just one of the many things I > tried and failed. > > Fundamentally, I would like Drools to process facts that were obtained > from real-world sources, and these facts have properties I do not know > in advance. Therefore, I cannot use beans (or using beans would be > highly inconvenient since it will require changes to Java code > whenever I'm referring to a new property, something I'd rather avoid.) > > - Godmar > > > > > > > []s > > Edson > > > > 2008/2/20, Godmar Back <[EMAIL PROTECTED]>: > > > I don't really understand what you mean by "shadow". What is the > > > purpose of such shadowing. Mark's email implies that it has to do with > > > concurrency protection; it's not clear what that means. > > > > > > In my view, whatever purpose you pursue with "shadowing", it does not > > > justify treating beans and maps differently. > > > > > > Your example of class Person shows that. If a person has two > > > attributes, name and age, then this is equivalent to a map with two > > > keys 'name' and 'age'. > > > > > > Here's the mapping: > > > > > > p.getName() corresponds to m["name"] > > > p.getAge() corresponds to m["age"] > > > > > > and setName/setAge accordingly. > > > > > > Mathematically, a bean is an associative array with a fixed set of > > > keys (called "properties") that map to values. For all practical > > > purposes, that is the same as a map. There's no reason to treat them > > > differently. Wherever you'd do "getXXX()" with a bean you'd do > > > .get("XXX") with a map. > > > > > > - Godmar > > > > > > On Feb 20, 2008 11:25 AM, Edson Tirelli <[EMAIL PROTECTED]> wrote: > > > > > > > > Ok, let me show one example. Imagine the class Person, with 2 > > attributes > > > > (name and age) and the corresponding getter/setters. > > > > What are the data for that fact that must be shadowed? easy answer: > > just > > > > shadow all getXXX() methods (getName and getAge). > > > > > > > > Now, take a Map. What is the data that must be shadowed? > > > > > > > > So, we do our best to work with facts that don't follow the javabean > > > > spec, but collections and maps are a complicated beast. Again, if you > > have > > > > suggestions on how to improve the current support we provide for them, > > > > please share with us. > > > > > > > > []s > > > > Edson > > > > > > > > 2008/2/20, Godmar Back <[EMAIL PROTECTED]>: > > > > > > > > > On Feb 20, 2008 9:23 AM, Edson Tirelli <[EMAIL PROTECTED]> wrote: > > > > > > > > > > > > Godmar, > > > > > > > > > > > > Short answer: collection/maps objects are not javabeans. > > > > > > > > > > > > > > > > Explain why this is a problem. > > > > > > > > > > What is it about JavaBeans that your algorithm relies upon? Is it > the > > > > > fact that the set of properties remains fixed and can be determined > at > > > > > (fact) insertion time via reflection? > > > > > > > > > > Otherwise, I do not see any conceptual difference between a map and a > > > > bean. > > > > > If that is the difference, then please allow maps with an immutable > > key > > > > set. > > > > > > > > > > - Godmar > > > > > > > > > > > > > > > > Long answer: collection/maps must be shadowed to ensure > > consistency > > > > > > during execution, but how can we shadow the data if it is not > > exposed in > > > > a > > > > > > default, spec manner, as in javabeans? The algorithm we have in > > place > > > > right > > > > > > now is bellow. As you can see, it is a weak algo, but was the best > I > > > > could > > > > > > come up at that time. If you have any suggestions on how to improve > > > > that, I > > > > > > appreciate. > > > > > > > > > > > > public Object getShadow(final Object fact) throws > > > > RuntimeDroolsException > > > > > > { > > > > > > ShadowProxy proxy = null; > > > > > > if ( isShadowEnabled() ) { > > > > > > try { > > > > > > if ( Collection.class.isAssignableFrom( > > this.shadowClass > > > > ) > > > > > > || Map.class.isAssignableFrom( this.shadowClass ) ) { > > > > > > // if it is a collection, try to instantiate > > using > > > > > > constructor > > > > > > try { > > > > > > proxy = (ShadowProxy) > > > > > > this.shadowClass.getConstructor( new Class[]{cls} ).newInstance( > new > > > > > > Object[]{fact} ); > > > > > > } catch ( Exception e ) { > > > > > > // not possible to instantiate using > > constructor > > > > > > } > > > > > > } > > > > > > if ( proxy == null ) { > > > > > > if ( this.instantiator == null ) { > > > > > > this.setInstantiator(); > > > > > > } > > > > > > proxy = (ShadowProxy) > > > > this.instantiator.newInstance(); > > > > > > } > > > > > > > > > > > > proxy.setShadowedObject( fact ); > > > > > > } catch ( final Exception e ) { > > > > > > System.out.println( "shadow: " +proxy.getClass() + > > ":" + > > > > > > fact.getClass() ); > > > > > > throw new RuntimeDroolsException( "Error creating > > shadow > > > > > > fact for object: " + fact, > > > > > > e ); > > > > > > } > > > > > > } > > > > > > return proxy; > > > > > > > > > > > > > > > > > > } > > > > > > > > > > > > []s > > > > > > Edson > > > > > > > > > > > > 2008/2/19, Godmar Back <[EMAIL PROTECTED]>: > > > > > > > As a general comment, the examples for which I find Drools > failing > > are > > > > > > > not the actual examples for which my application is failing. It's > > just > > > > > > > the smallest test case I was able to eliminate. > > > > > > > > > > > > > > I'm now a bit concerned about your comment that Maps and > > Collections > > > > > > > aren't well-defined as Facts. I am planning to make extensive use > > of > > > > > > > them (that's also why I'd prefer to use the MVEL dialect, because > > in > > > > > > > Java I cannot do this without creating Bean wrappers.) > > > > > > > > > > > > > > Could you elaborate what makes the semantics not "well-defined". > > > > > > > > > > > > > > I'm specifically concerned with immutable maps (such as the one > > that > > > > > > > would have been returned by Collections.singletonMap), and with > > > > > > > collections of maps (such as those obtained via a "from"..." > > clause). > > > > > > > I need to insert immutable maps as facts; I understand that the > > items > > > > > > > returned by "from" aren't inserted as facts. > > > > > > > > > > > > > > - Godmar > > > > > > > > > > > > > > On Feb 19, 2008 3:11 PM, Edson Tirelli <[EMAIL PROTECTED]> wrote: > > > > > > > > > > > > > > > > Drools tries to create the ShadowProxy. The reason is that > it > > > > does > > > > > > not > > > > > > > > know about the implementation... it just knows it is a Map and > > as > > > > so, it > > > > > > > > must be shadowed. Problem is that SingletonMap is either final > > or > > > > does > > > > > > not > > > > > > > > have a default constructor. > > > > > > > > My recommendation, besides opening a JIRA for this, is > avoid > > > > > > inserting > > > > > > > > collections/maps directly as facts. The semantic for such facts > > is > > > > not > > > > > > > > clearly defined and it may cause undesired behavior. > > > > > > > > > > > > > > > > []s > > > > > > > > Edson > > > > > > > > > > > > > > > > 2008/2/19, Godmar Back <[EMAIL PROTECTED]>: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Hi, > > > > > > > > > > > > > > > > > > usings Drools 4.0.4 and MVEL 1.4, this simple rule: > > > > > > > > > --- > > > > > > > > > package test; > > > > > > > > > > > > > > > > > > import java.util.Collections; > > > > > > > > > > > > > > > > > > dialect "mvel" > > > > > > > > > > > > > > > > > > rule "Rule #1" > > > > > > > > > when > > > > > > > > > then > > > > > > > > > insert(Collections.singletonMap("content", "hello")); > > > > > > > > > end > > > > > > > > > -- > > > > > > > > > > > > > > > > > > produces: > > > > > > > > > java.lang.IllegalAccessError: class > > > > > > > > > > > org.drools.shadow.java.util.Collections$SingletonMapShadowProxy > > > > cannot > > > > > > > > > access its superclass java.util.Collections$SingletonMap > > > > > > > > > at java.lang.ClassLoader.defineClass1(Native Method) > > > > > > > > > at > > java.lang.ClassLoader.defineClass(ClassLoader.java:620) > > > > > > > > > at > > > > > > > > > > > > > > > > > > > > > org.drools.rule.MapBackedClassLoader.fastFindClass(MapBackedClassLoader.java:60) > > > > > > > > > at > > > > > > > > > > > > > > > > > > > > > org.drools.rule.MapBackedClassLoader.loadClass(MapBackedClassLoader.java:79) > > > > > > > > > at > > java.lang.ClassLoader.loadClass(ClassLoader.java:251) > > > > > > > > > at > > > > > > > > > > > > > > > > > > > > > org.drools.reteoo.Rete$ClassObjectTypeConf.loadOrGenerateProxy(Rete.java:547) > > > > > > > > > at > > > > > > > > > > > > > > > > > > > > > org.drools.reteoo.Rete$ClassObjectTypeConf.defineShadowProxyData(Rete.java:494) > > > > > > > > > at > > > > > > > > > org.drools.reteoo.Rete$ClassObjectTypeConf.<init>(Rete.java:461) > > > > > > > > > at org.drools.reteoo.Rete.assertObject(Rete.java:152) > > > > > > > > > at > > > > > > > > > > > > org.drools.reteoo.ReteooRuleBase.assertObject(ReteooRuleBase.java:192) > > > > > > > > > at > > > > > > > > > > > > > > > > > > > > org.drools.reteoo.ReteooWorkingMemory.doInsert(ReteooWorkingMemory.java:71) > > > > > > > > > at > > > > > > > > > > > > > > > > > > > > > org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:909) > > > > > > > > > at > > > > > > > > > > > > > > > > > > > > > org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:881) > > > > > > > > > at > > > > > > > > > > > > > > > > > > > > > org.drools.base.DefaultKnowledgeHelper.insert(DefaultKnowledgeHelper.java:67) > > > > > > > > > at > > > > > > > > > > > > > > > > > > > > > org.drools.base.DefaultKnowledgeHelper.insert(DefaultKnowledgeHelper.java:61) > > > > > > > > > > > > > > > > > > > > > > > > > > > It's not clear to me why Drools creates Proxies for such > > classes > > > > as > > > > > > > > > java.util.Collections, or does MVEL do it? > > > > > > > > > > > > > > > > > > - Godmar > > > > > > > > > _______________________________________________ > > > > > > > > > rules-users mailing list > > > > > > > > > rules-users@lists.jboss.org > > > > > > > > > https://lists.jboss.org/mailman/listinfo/rules-users > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > > > Edson Tirelli > > > > > > > > JBoss Drools Core Development > > > > > > > > Office: +55 11 3529-6000 > > > > > > > > Mobile: +55 11 9287-5646 > > > > > > > > JBoss, a division of Red Hat @ www.jboss.com > > > > > > > > _______________________________________________ > > > > > > > > rules-users mailing list > > > > > > > > rules-users@lists.jboss.org > > > > > > > > https://lists.jboss.org/mailman/listinfo/rules-users > > > > > > > > > > > > > > > > > > > > > > > _______________________________________________ > > > > > > > rules-users mailing list > > > > > > > rules-users@lists.jboss.org > > > > > > > https://lists.jboss.org/mailman/listinfo/rules-users > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > Edson Tirelli > > > > > > JBoss Drools Core Development > > > > > > Office: +55 11 3529-6000 > > > > > > Mobile: +55 11 9287-5646 > > > > > > JBoss, a division of Red Hat @ www.jboss.com > > > > > > _______________________________________________ > > > > > > rules-users mailing list > > > > > > rules-users@lists.jboss.org > > > > > > https://lists.jboss.org/mailman/listinfo/rules-users > > > > > > > > > > > > > > > > > _______________________________________________ > > > > > rules-users mailing list > > > > > rules-users@lists.jboss.org > > > > > https://lists.jboss.org/mailman/listinfo/rules-users > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > Edson Tirelli > > > > JBoss Drools Core Development > > > > Office: +55 11 3529-6000 > > > > Mobile: +55 11 9287-5646 > > > > JBoss, a division of Red Hat @ www.jboss.com > > > > _______________________________________________ > > > > rules-users mailing list > > > > rules-users@lists.jboss.org > > > > https://lists.jboss.org/mailman/listinfo/rules-users > > > > > > > > > > > _______________________________________________ > > > rules-users mailing list > > > rules-users@lists.jboss.org > > > https://lists.jboss.org/mailman/listinfo/rules-users > > > > > > > > > > > -- > > Edson Tirelli > > JBoss Drools Core Development > > Office: +55 11 3529-6000 > > Mobile: +55 11 9287-5646 > > JBoss, a division of Red Hat @ www.jboss.com > > _______________________________________________ > > rules-users mailing list > > rules-users@lists.jboss.org > > https://lists.jboss.org/mailman/listinfo/rules-users > > > > > _______________________________________________ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users