KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > reasoner > rulesys > impl > RETEClauseFilter


1 /******************************************************************
2  * File: RETEClauseFilter.java
3  * Created by: Dave Reynolds
4  * Created on: 09-Jun-2003
5  *
6  * (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
7  * [See end of file]
8  * $Id: RETEClauseFilter.java,v 1.8 2005/02/21 12:17:57 andy_seaborne Exp $
9  *****************************************************************/

10 package com.hp.hpl.jena.reasoner.rulesys.impl;
11
12 import com.hp.hpl.jena.graph.*;
13 import com.hp.hpl.jena.graph.impl.LiteralLabel;
14 import com.hp.hpl.jena.reasoner.rulesys.*;
15 import com.hp.hpl.jena.reasoner.*;
16
17 import java.util.*;
18
19 /**
20  * Checks a triple against the grounded matches and intra-triple matches
21  * for a single rule clause. If the match passes it creates a binding
22  * environment token and passes it on the the RETE network itself. The checks
23  * and bindings are implemented using a simple byte-coded interpreter.
24  *
25  * @author <a HREF="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
26  * @version $Revision: 1.8 $ on $Date: 2005/02/21 12:17:57 $
27  */

28 public class RETEClauseFilter implements RETESourceNode {
29     
30     /** Contains the set of byte-coded instructions and argument pointers */
31     protected byte[] instructions;
32     
33     /** Contains the object arguments referenced from the instructions array */
34     protected Object JavaDoc[] args;
35     
36     /** The network node to receive any created tokens */
37     protected RETESinkNode continuation;
38     
39     /** Instruction code: Check triple entry (arg1) against literal value (arg2). */
40     public static final byte TESTValue = 0x01;
41     
42     /** Instruction code: Check literal value is a functor of name arg1 */
43     public static final byte TESTFunctorName = 0x02;
44     
45     /** Instruction code: Cross match two triple entries (arg1, arg2) */
46     public static final byte TESTIntraMatch = 0x03;
47     
48     /** Instruction code: Create a result environment of length arg1. */
49     public static final byte CREATEToken = 0x04;
50     
51     /** Instruction code: Bind a node (arg1) to a place in the rules token (arg2). */
52     public static final byte BIND = 0x05;
53     
54     /** Instruction code: Final entry - dispatch to the network. */
55     public static final byte END = 0x06;
56     
57     /** Argument addressing code: triple subject */
58     public static final byte ADDRSubject = 0x10;
59     
60     /** Argument addressing code: triple predicate */
61     public static final byte ADDRPredicate = 0x20;
62     
63     /** Argument addressing code: triple object as a whole */
64     public static final byte ADDRObject = 0x30;
65     
66     /** Argument addressing code: triple object functor node, offset in
67      * low nibble, only usable after a successful TestFunctorName. */

68     public static final byte ADDRFunctorNode = 0x40;
69         
70     /**
71      * Contructor.
72      * @param instructions the set of byte-coded instructions and argument pointers.
73      * @param args the object arguments referenced from the instructions array.
74      */

75     public RETEClauseFilter(byte[] instructions, Object JavaDoc[] args) {
76         this.instructions = instructions;
77         this.args = args;
78     }
79     
80     /**
81      * Create a filter node from a rule clause.
82      * Clause complexity is limited to less than 50 args in a Functor.
83      * @param clause the rule clause
84      * @param envLength the size of binding environment that should be created on successful matches
85      * @param varList a list to which all clause variables will be appended
86      */

87     public static RETEClauseFilter compile(TriplePattern clause, int envLength, List varList) {
88         byte[] instructions = new byte[300];
89         byte[] bindInstructions = new byte[100];
90         ArrayList args = new ArrayList();
91         int pc = 0;
92         int bpc = 0;
93         
94         // Pass 0 - prepare env creation statement
95
bindInstructions[bpc++] = CREATEToken;
96         bindInstructions[bpc++] = (byte)envLength;
97         
98         // Pass 1 - check literal values
99
Node n = clause.getSubject();
100         if ( !n.isVariable() ) {
101             instructions[pc++] = TESTValue;
102             instructions[pc++] = ADDRSubject;
103             instructions[pc++] = (byte)args.size();
104             args.add( n );
105         } else {
106             bindInstructions[bpc++] = BIND;
107             bindInstructions[bpc++] = ADDRSubject;
108             bindInstructions[bpc++] = (byte)((Node_RuleVariable)n).getIndex();
109             varList.add(n);
110         }
111         n = clause.getPredicate();
112         if ( !n.isVariable() ) {
113             instructions[pc++] = TESTValue;
114             instructions[pc++] = ADDRPredicate;
115             instructions[pc++] = (byte)args.size();
116             args.add( clause.getPredicate() );
117         } else {
118             bindInstructions[bpc++] = BIND;
119             bindInstructions[bpc++] = ADDRPredicate;
120             bindInstructions[bpc++] = (byte)((Node_RuleVariable)n).getIndex();
121             varList.add(n);
122         }
123         n = clause.getObject();
124         if ( !n.isVariable() ) {
125             if (Functor.isFunctor(n)) {
126                 // Pass 2 - check functor
127
Functor f = (Functor)n.getLiteral().getValue();
128                 instructions[pc++] = TESTFunctorName;
129                 instructions[pc++] = (byte)args.size();
130                 args.add(f.getName());
131                 Node[] fargs = f.getArgs();
132                 for (int i = 0; i < fargs.length; i++) {
133                     Node fn = fargs[i];
134                     byte addr = (byte) (ADDRFunctorNode | (0x0f & i));
135                     if ( !fn.isVariable() ) {
136                         instructions[pc++] = TESTValue;
137                         instructions[pc++] = addr;
138                         instructions[pc++] = (byte)args.size();
139                         args.add( fn );
140                     } else {
141                         bindInstructions[bpc++] = BIND;
142                         bindInstructions[bpc++] = addr;
143                         bindInstructions[bpc++] = (byte)((Node_RuleVariable)fn).getIndex();
144                         varList.add(fn);
145                     }
146                 }
147             } else {
148                 instructions[pc++] = TESTValue;
149                 instructions[pc++] = ADDRObject;
150                 instructions[pc++] = (byte)args.size();
151                 args.add( n );
152             }
153         } else {
154             bindInstructions[bpc++] = BIND;
155             bindInstructions[bpc++] = ADDRObject;
156             bindInstructions[bpc++] = (byte)((Node_RuleVariable)n).getIndex();
157             varList.add(n);
158         }
159         bindInstructions[bpc++] = END;
160         
161         // Pass 4 - Pack instructions
162
byte[] packed = new byte[pc + bpc];
163         System.arraycopy(instructions, 0, packed, 0, pc);
164         System.arraycopy(bindInstructions, 0, packed, pc, bpc);
165         Object JavaDoc[] packedArgs = args.toArray();
166         
167         return new RETEClauseFilter(packed, packedArgs);
168     }
169     
170     /**
171      * Set the continuation node for this node.
172      */

173     public void setContinuation(RETESinkNode continuation) {
174         this.continuation = continuation;
175     }
176
177     /**
178      * Insert or remove a triple into the network.
179      * @param triple the triple to process.
180      * @param isAdd true if the triple is being added to the working set.
181      */

182     public void fire(Triple triple, boolean isAdd) {
183         
184         Functor lastFunctor = null; // bound by TESTFunctorName
185
BindingVector env = null; // bound by CREATEToken
186
Node n = null; // Temp workspace
187

188         for (int pc = 0; pc < instructions.length; ) {
189             switch(instructions[pc++]) {
190                 
191             case TESTValue:
192                 // Check triple entry (arg1) against literal value (arg2)
193
if (! getTripleValue(triple, instructions[pc++], lastFunctor)
194                                 .sameValueAs(args[instructions[pc++]])) return;
195                 break;
196                 
197             case TESTFunctorName:
198                 // Check literal value is a functor of name arg1.
199
// Side effect: leaves a loop variable pointing to functor
200
// for possible later functor argument accesses
201
n = triple.getObject();
202                 if ( !n.isLiteral() ) return;
203                 LiteralLabel ll = n.getLiteral();
204                 if ( ll.getDatatype() != Functor.FunctorDatatype.theFunctorDatatype) return;
205                 lastFunctor = (Functor)ll.getValue();
206                 if ( !lastFunctor.getName().equals(args[instructions[pc++]]) ) return;
207                 break;
208                 
209             case CREATEToken:
210                 // Create a result environment of length arg1
211
env = new BindingVector(new Node[instructions[pc++]]);
212                 break;
213                 
214             case BIND:
215                 // Bind a node (arg1) to a place in the rules token (arg2)
216
n = getTripleValue(triple, instructions[pc++], lastFunctor);
217                 if ( !env.bind(instructions[pc++], n) ) return;
218                 break;
219                 
220             case END:
221                 // Success, fire the continuation
222
continuation.fire(env, isAdd);
223             }
224         }
225
226     }
227     
228     /**
229      * Helperful function. Return the node from the argument triple
230      * corresponding to the byte code address.
231      */

232     private Node getTripleValue(Triple triple, byte address, Functor lastFunctor) {
233         switch (address & 0xf0) {
234         case ADDRSubject:
235             return triple.getSubject();
236         case ADDRPredicate:
237             return triple.getPredicate();
238         case ADDRObject:
239             return triple.getObject();
240         case ADDRFunctorNode:
241             return lastFunctor.getArgs()[address & 0x0f];
242         }
243         return null;
244     }
245     
246     /**
247      * Clone this node in the network.
248      * @param netCopy a map from RETENode to cloned instance
249      * @param context the new context to which the network is being ported
250      */

251     public RETENode clone(Map netCopy, RETERuleContext context) {
252         RETEClauseFilter clone = (RETEClauseFilter)netCopy.get(this);
253         if (clone == null) {
254             clone = new RETEClauseFilter(instructions, args);
255             clone.setContinuation((RETESinkNode)continuation.clone(netCopy, context));
256             netCopy.put(this, clone);
257         }
258         return clone;
259     }
260     
261 }
262
263
264
265 /*
266     (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
267     All rights reserved.
268
269     Redistribution and use in source and binary forms, with or without
270     modification, are permitted provided that the following conditions
271     are met:
272
273     1. Redistributions of source code must retain the above copyright
274        notice, this list of conditions and the following disclaimer.
275
276     2. Redistributions in binary form must reproduce the above copyright
277        notice, this list of conditions and the following disclaimer in the
278        documentation and/or other materials provided with the distribution.
279
280     3. The name of the author may not be used to endorse or promote products
281        derived from this software without specific prior written permission.
282
283     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
284     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
285     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
286     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
287     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
288     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
289     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
290     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
291     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
292     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
293 */
Popular Tags