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