[rules-dev] "not contains" doesn't work on inner fields

Taras Svirskyi stware at gmail.com
Tue Jan 12 10:50:17 EST 2010


Hi,
  I don't know exactly is it a bug or am I doing something wrong.
  Consider following example.
  There are nodes that are connected into directed graph. Each node has 
special collection of attributes. Under some conditions attributes 
should be propagated along the edges in the graph.

  Lets model this with following code.

/******* propagation rules **********************/
package com.test.collection;

rule "move child"
when
	c : Child()
	s : CNode( children contains c)		
	l : Link( src == s,
		  t : target && target.children not contains c )
then
	System.out.println("adding "+c+" from "+s+" to "+t);
	t.addChild(c);
	update(t);
end


/** Child.java (represent special attributes of a node) *******/
package com.test.collection;

public class Child {
	private String name;	
	public Child(String name){
		this.name = name;
	}
	public String getName() {
		return name;
	}
	@Override
	public String toString() {
		return "child("+name+")";
	}	
}

/********* CNode.java - nodes of a graph *************/
package com.test.collection;

import java.util.HashSet;
import java.util.Set;

public class CNode {
	private Set<Child> children;

	public CNode() {
		this.children = new HashSet<Child>();
	}

	public Set<Child> getChildren() {
		return children;
	}
	
	public void addChild(Child ch){
		children.add(ch);		
	}

	@Override
	public String toString() {
		return "Node{children="+children+"}";
	}
}

/**** Link.java - edges of a graph *******/
package com.test.collection;

public class Link {
	private CNode src;
	private CNode target;
	
	public Link(CNode src, CNode target) {
		this.src = src;
		this.target = target;
	}

	public CNode getSrc() {
		return src;
	}

	public CNode getTarget() {
		return target;
	}
}

/********************* populate session with facts **********/
Child c0 = new Child("x");
Child c1 = new Child("y");
Child c2 = new Child("z");
			
CNode src = new CNode();
src.addChild(c0);
src.addChild(c1);
			
CNode target = new CNode();
target.addChild(c0);
			
Link link = new Link(src,target);
			
// populate with facts
ksession.insert(c0);
ksession.insert(c1);
ksession.insert(c2);
ksession.insert(link);
ksession.insert(src);
ksession.insert(target);

/****************************************************************/
So with all that code listed below I've got following output from rules:
--
adding child(x) from Node{children=[child(x), child(y)]} to 
Node{children=[child(x)]}
--
That means that 'not contains' operator actually works as 'contains' 
one. Still when I changed it to older operator 'excludes' everything 
goes right printing out.
---
adding child(y) from Node{children=[child(y), child(x)]} to 
Node{children=[child(x)]}
---

I've noticed that rewriting rule in form of simple statements also fix 
issue.

rule "move child"
when
	c : Child()
	s : CNode( children contains c)
	t : CNode( children not contains c )
	l : Link( src == s, target == t)
then
	System.out.println("adding "+c+" from "+s+" to "+t);
	t.addChild(c);
	update(t);
end

So the question is it a bug or a feature? :)

regards,
Taras


More information about the rules-dev mailing list