|
|||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
Rule.java | 57.1% | 62.7% | 96.7% | 71.2% |
|
1 | package org.drools.rule; | |
2 | ||
3 | /* | |
4 | * $Id: Rule.java,v 1.56.2.2 2005/05/08 00:57:36 mproctor Exp $ | |
5 | * | |
6 | * Copyright 2001-2003 (C) The Werken Company. All Rights Reserved. | |
7 | * | |
8 | * Redistribution and use of this software and associated documentation | |
9 | * ("Software"), with or without modification, are permitted provided that the | |
10 | * following conditions are met: | |
11 | * | |
12 | * 1. Redistributions of source code must retain copyright statements and | |
13 | * notices. Redistributions must also contain a copy of this document. | |
14 | * | |
15 | * 2. Redistributions in binary form must reproduce the above copyright notice, | |
16 | * this list of conditions and the following disclaimer in the documentation | |
17 | * and/or other materials provided with the distribution. | |
18 | * | |
19 | * 3. The name "drools" must not be used to endorse or promote products derived | |
20 | * from this Software without prior written permission of The Werken Company. | |
21 | * For written permission, please contact bob@werken.com. | |
22 | * | |
23 | * 4. Products derived from this Software may not be called "drools" nor may | |
24 | * "drools" appear in their names without prior written permission of The Werken | |
25 | * Company. "drools" is a trademark of The Werken Company. | |
26 | * | |
27 | * 5. Due credit should be given to The Werken Company. (http://werken.com/) | |
28 | * | |
29 | * THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS ``AS IS'' | |
30 | * AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
31 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE WERKEN COMPANY OR ITS CONTRIBUTORS BE | |
33 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
34 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
35 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
36 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
37 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
38 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
39 | * POSSIBILITY OF SUCH DAMAGE. | |
40 | * | |
41 | */ | |
42 | ||
43 | import java.io.Serializable; | |
44 | import java.util.ArrayList; | |
45 | import java.util.Collections; | |
46 | import java.util.HashSet; | |
47 | import java.util.Iterator; | |
48 | import java.util.List; | |
49 | import java.util.Map; | |
50 | import java.util.Set; | |
51 | ||
52 | import org.drools.spi.Condition; | |
53 | import org.drools.spi.Consequence; | |
54 | import org.drools.spi.Duration; | |
55 | import org.drools.spi.ImportEntry; | |
56 | import org.drools.spi.Importer; | |
57 | import org.drools.spi.ObjectType; | |
58 | ||
59 | /** | |
60 | * A <code>Rule</code> contains a set of <code>Condition</code>s and a | |
61 | * <code>Consequence</code>. | |
62 | * <p> | |
63 | * The <code>Condition</code>s describe the circumstances that | |
64 | * representrepresent a match for this rule. The <code>Consequence</code> gets | |
65 | * fired when the Conditions match. | |
66 | * | |
67 | * @see Condition | |
68 | * @see Consequence | |
69 | * @author <a href="mailto:bob@eng.werken.com"> bob mcwhirter </a> | |
70 | * @author <a href="mailto:simon@redhillconsulting.com.au"> Simon Harris </a> | |
71 | * @author <a href="mailto:mproctor@codehaus.org"> mark pro </a> | |
72 | */ | |
73 | public class Rule | |
74 | implements | |
75 | Serializable | |
76 | { | |
77 | /** */ | |
78 | // ------------------------------------------------------------ | |
79 | // Instance members | |
80 | // ------------------------------------------------------------ | |
81 | /** The parent ruleSet */ | |
82 | private RuleSet ruleSet; | |
83 | ||
84 | /** Name of the rule. */ | |
85 | private final String name; | |
86 | ||
87 | /** Documentation. */ | |
88 | private String documentation; | |
89 | ||
90 | /** Salience value. */ | |
91 | private int salience; | |
92 | ||
93 | /** Formal parameter declarations. */ | |
94 | private final List parameterDeclarations = new ArrayList( ); | |
95 | ||
96 | /** Conditions. */ | |
97 | private final List conditions = new ArrayList( ); | |
98 | ||
99 | /** Consequence. */ | |
100 | private Consequence consequence; | |
101 | ||
102 | /** Truthness duration. */ | |
103 | private Duration duration; | |
104 | ||
105 | /** Load order in RuleSet */ | |
106 | private long loadOrder; | |
107 | ||
108 | /** is the consequence of the rule currently being executed? */ | |
109 | private boolean noLoop; | |
110 | ||
111 | /** A map valid Application names and types */ | |
112 | private Map applicationData; | |
113 | ||
114 | /** The Importer to use, as specified by the RuleSet */ | |
115 | private Importer importer; | |
116 | ||
117 | // ------------------------------------------------------------ | |
118 | // Constructors | |
119 | // ------------------------------------------------------------ | |
120 | ||
121 | /** | |
122 | * Construct a | |
123 | * <code>Rule<code> with the given name for the specified ruleSet parent | |
124 | * | |
125 | * @param name | |
126 | * The name of this rule. | |
127 | */ | |
128 | 372 | public Rule(String name, |
129 | RuleSet ruleSet) | |
130 | { | |
131 | 372 | this.name = name; |
132 | 372 | this.ruleSet = ruleSet; |
133 | 372 | this.applicationData = Collections.EMPTY_MAP; |
134 | } | |
135 | ||
136 | /** | |
137 | * Construct a <code>Rule</code> for the given name with null for the | |
138 | * parent <code>RuleSet</code> | |
139 | * <code>Rule</code>s will nearly always | |
140 | * want to be in a RuleSet. This is more of a convenience constructor for | |
141 | * the times you dont, ie during unit testing. | |
142 | * | |
143 | * @param name | |
144 | * The name of this rule. | |
145 | */ | |
146 | 261 | public Rule(String name) |
147 | { | |
148 | 261 | this( name, |
149 | null ); | |
150 | } | |
151 | ||
152 | /** | |
153 | * Set the documentation. | |
154 | * | |
155 | * @param documentation - | |
156 | * The documentation. | |
157 | */ | |
158 | 18 | public void setDocumentation(String documentation) |
159 | { | |
160 | 18 | this.documentation = documentation; |
161 | } | |
162 | ||
163 | /** | |
164 | * Retrieve the documentation. | |
165 | * | |
166 | * @return The documentation or <code>null</code> if none. | |
167 | */ | |
168 | 15 | public String getDocumentation() |
169 | { | |
170 | 15 | return this.documentation; |
171 | } | |
172 | ||
173 | /** | |
174 | * Set the truthness duration. This causes a delay before the firing of the | |
175 | * <code>Consequence</code> if the rule is still true at the end of the | |
176 | * duration. | |
177 | * | |
178 | * <p> | |
179 | * This is merely a convenience method for calling | |
180 | * {@link #setDuration(Duration)}with a <code>FixedDuration</code>. | |
181 | * </p> | |
182 | * | |
183 | * @see #setDuration(Duration) | |
184 | * @see FixedDuration | |
185 | * | |
186 | * @param seconds - | |
187 | * The number of seconds the rule must hold true in order to fire. | |
188 | */ | |
189 | 1 | public void setDuration(long seconds) |
190 | { | |
191 | 1 | this.duration = new FixedDuration( seconds ); |
192 | } | |
193 | ||
194 | /** | |
195 | * Set the truthness duration object. This causes a delay before the firing of the | |
196 | * <code>Consequence</code> if the rule is still true at the end of the | |
197 | * duration. | |
198 | * | |
199 | * @param duration | |
200 | * The truth duration object. | |
201 | */ | |
202 | 3 | public void setDuration(Duration duration) |
203 | { | |
204 | 3 | this.duration = duration; |
205 | } | |
206 | ||
207 | /** | |
208 | * Retrieve the truthness duration object. | |
209 | * | |
210 | * @return The truthness duration object. | |
211 | */ | |
212 | 6160 | public Duration getDuration() |
213 | { | |
214 | 6160 | return this.duration; |
215 | } | |
216 | ||
217 | /** | |
218 | * Determine if this rule is internally consistent and valid. | |
219 | * | |
220 | * No exception is thrown. | |
221 | * <p> | |
222 | * A <code>Rule</code> must include at least one parameter declaration and | |
223 | * one condition. | |
224 | * </p> | |
225 | * | |
226 | * @return <code>true</code> if this rule is valid, else | |
227 | * <code>false</code>. | |
228 | */ | |
229 | 1 | public boolean isValid() |
230 | { | |
231 | 1 | return !(getParameterDeclarations( ).isEmpty( ) || getConditions( ).isEmpty( ) ) && getConsequence( ) != null; |
232 | } | |
233 | ||
234 | /** | |
235 | * Check the validity of this rule, and throw exceptions if it fails | |
236 | * validity tests. | |
237 | * | |
238 | * <p> | |
239 | * Possibly exceptions include: | |
240 | * </p> | |
241 | * | |
242 | * <pre> | |
243 | * NoParameterDeclarationException | |
244 | * NoConsequenceException | |
245 | * </pre> | |
246 | * | |
247 | * <p> | |
248 | * A <code>Rule</code> must include at least one parameter declaration and | |
249 | * one condition. | |
250 | * </p> | |
251 | * | |
252 | * @throws InvalidRuleException | |
253 | * if this rule is in any way invalid. | |
254 | */ | |
255 | 96 | public void checkValidity() throws InvalidRuleException |
256 | { | |
257 | 96 | if ( getParameterDeclarations( ).isEmpty( ) ) |
258 | { | |
259 | 1 | throw new NoParameterDeclarationException( this ); |
260 | } | |
261 | 95 | if ( getConsequence( ) == null ) |
262 | { | |
263 | 0 | throw new NoConsequenceException( this ); |
264 | } | |
265 | } | |
266 | ||
267 | 528 | public RuleSet getRuleSet() |
268 | { | |
269 | 528 | return this.ruleSet; |
270 | } | |
271 | ||
272 | /** | |
273 | * Retrieve the name of this rule. | |
274 | * | |
275 | * @return The name of this rule. | |
276 | */ | |
277 | 183 | public String getName() |
278 | { | |
279 | 183 | return this.name; |
280 | } | |
281 | ||
282 | /** | |
283 | * Retrieve the <code>Rule</code> salience. | |
284 | * | |
285 | * @return The salience. | |
286 | */ | |
287 | 101959 | public int getSalience() |
288 | { | |
289 | 101959 | return this.salience; |
290 | } | |
291 | ||
292 | /** | |
293 | * Set the <code>Rule<code> salience. | |
294 | * | |
295 | * @param salience The salience. | |
296 | */ | |
297 | 78 | public void setSalience(int salience) |
298 | { | |
299 | 78 | this.salience = salience; |
300 | } | |
301 | ||
302 | 5866 | public boolean getNoLoop() |
303 | { | |
304 | 5866 | return this.noLoop; |
305 | } | |
306 | ||
307 | 8 | public void setNoLoop(boolean noLoop) |
308 | { | |
309 | 8 | this.noLoop = noLoop; |
310 | } | |
311 | ||
312 | /** | |
313 | * Add a <i>root fact object </i> parameter <code>Declaration</code> for | |
314 | * this <code>Rule</code>. | |
315 | * | |
316 | * @param identifier | |
317 | * The identifier. | |
318 | * @param objectType | |
319 | * The type. | |
320 | * @return The declaration. | |
321 | */ | |
322 | 249 | public Declaration addParameterDeclaration(String identifier, |
323 | ObjectType objectType) throws InvalidRuleException | |
324 | { | |
325 | 249 | if ( getParameterDeclaration( identifier ) != null ) |
326 | { | |
327 | 0 | throw new InvalidRuleException( this ); |
328 | } | |
329 | ||
330 | 249 | Declaration declaration = new Declaration( identifier, |
331 | objectType, | |
332 | this.parameterDeclarations.size( ) ); | |
333 | ||
334 | 249 | this.parameterDeclarations.add( declaration ); |
335 | ||
336 | 249 | return declaration; |
337 | } | |
338 | ||
339 | /** | |
340 | * Retrieve a parameter <code>Declaration</code> by identifier. | |
341 | * | |
342 | * @param identifier | |
343 | * The identifier. | |
344 | * | |
345 | * @return The declaration or <code>null</code> if no declaration matches | |
346 | * the <code>identifier</code>. | |
347 | */ | |
348 | 273 | public Declaration getParameterDeclaration(String identifier) |
349 | { | |
350 | 273 | Declaration eachDecl; |
351 | ||
352 | 273 | Iterator declIter = this.parameterDeclarations.iterator( ); |
353 | 273 | while ( declIter.hasNext( ) ) |
354 | { | |
355 | 154 | eachDecl = (Declaration) declIter.next( ); |
356 | ||
357 | 154 | if ( eachDecl.getIdentifier( ).equals( identifier ) ) |
358 | { | |
359 | 11 | return eachDecl; |
360 | } | |
361 | } | |
362 | ||
363 | 262 | return null; |
364 | } | |
365 | ||
366 | /** | |
367 | * Retrieve the set of all <i>root fact object </i> parameter | |
368 | * <code>Declarations</code>. | |
369 | * | |
370 | * @return The Set of <code>Declarations</code> in order which specify the | |
371 | * <i>root fact objects</i>. | |
372 | */ | |
373 | 459 | public List getParameterDeclarations() |
374 | { | |
375 | 459 | return Collections.unmodifiableList( this.parameterDeclarations ); |
376 | } | |
377 | ||
378 | /** | |
379 | * Add a <code>Condition</code> to this rule. | |
380 | * | |
381 | * @param condition | |
382 | * The <code>Condition</code> to add. | |
383 | */ | |
384 | 252 | public void addCondition(Condition condition) |
385 | { | |
386 | 252 | this.conditions.add( condition ); |
387 | } | |
388 | ||
389 | /** | |
390 | * Retrieve the <code>List</code> of <code>Conditions</code> for this | |
391 | * rule. | |
392 | * | |
393 | * @return The <code>List</code> of <code>Conditions</code>. | |
394 | */ | |
395 | 91 | public List getConditions() |
396 | { | |
397 | 91 | return Collections.unmodifiableList( this.conditions ); |
398 | } | |
399 | ||
400 | 37244 | public int getConditionSize() |
401 | { | |
402 | 37244 | return this.conditions.size( ); |
403 | } | |
404 | ||
405 | /** | |
406 | * Set the <code>Consequence</code> that is associated with the successful | |
407 | * match of this rule. | |
408 | * | |
409 | * @param consequence | |
410 | * The <code>Consequence</code> to attach to this <code>Rule</code>. | |
411 | */ | |
412 | 118 | public void setConsequence(Consequence consequence) |
413 | { | |
414 | 118 | this.consequence = consequence; |
415 | } | |
416 | ||
417 | /** | |
418 | * Retrieve the <code>Consequence</code> associated with this | |
419 | * <code>Rule</code>. | |
420 | * | |
421 | * @return The <code>Consequence</code>. | |
422 | */ | |
423 | 486 | public Consequence getConsequence() |
424 | { | |
425 | 486 | return this.consequence; |
426 | } | |
427 | ||
428 | 37228 | public long getLoadOrder() |
429 | { | |
430 | 37228 | return loadOrder; |
431 | } | |
432 | ||
433 | 149 | void setLoadOrder(long loadOrder) |
434 | { | |
435 | 149 | this.loadOrder = loadOrder; |
436 | } | |
437 | ||
438 | 442 | public Importer getImporter() |
439 | { | |
440 | 442 | return this.importer; |
441 | } | |
442 | ||
443 | 277 | public void setImporter(Importer importer) |
444 | { | |
445 | 277 | this.importer = importer; |
446 | } | |
447 | ||
448 | 87 | public void setApplicationData(Map applicationData) |
449 | { | |
450 | 87 | this.applicationData = applicationData; |
451 | } | |
452 | ||
453 | 209 | public Map getApplicationData() |
454 | { | |
455 | 209 | return this.applicationData; |
456 | } | |
457 | ||
458 | 0 | public String dump(String indent) |
459 | { | |
460 | 0 | StringBuffer buffer = new StringBuffer( ); |
461 | 0 | buffer.append( indent ).append( "Rule\n" ); |
462 | 0 | buffer.append( indent ).append( "----\n" ); |
463 | 0 | buffer.append( indent ).append( "name: " ); |
464 | 0 | buffer.append( this.name ); |
465 | 0 | buffer.append( "\n" ); |
466 | 0 | buffer.append( indent ).append( "salience: " ); |
467 | 0 | buffer.append( this.salience ); |
468 | 0 | buffer.append( "\n" ); |
469 | 0 | buffer.append( indent ).append( "load order: " ); |
470 | 0 | buffer.append( this.loadOrder ); |
471 | 0 | buffer.append( "\n" ); |
472 | 0 | buffer.append( indent ).append( "duration: " ); |
473 | 0 | buffer.append( this.duration ); |
474 | 0 | buffer.append( "\n" ); |
475 | ||
476 | 0 | for ( Iterator i = this.parameterDeclarations.iterator( ); i.hasNext( ); ) |
477 | { | |
478 | 0 | buffer.append( indent ).append( i.next( ) ); |
479 | } | |
480 | ||
481 | 0 | for ( Iterator i = this.conditions.iterator( ); i.hasNext( ); ) |
482 | { | |
483 | 0 | buffer.append( indent ).append( "condition:\n" ).append( indent ).append( i.next( ) ).append( '\n' ); |
484 | } | |
485 | ||
486 | 0 | buffer.append( indent ).append( "consequence:\n" ); |
487 | 0 | buffer.append( indent ).append( this.consequence ); |
488 | 0 | buffer.append( "\n" ); |
489 | 0 | return buffer.toString( ); |
490 | } | |
491 | } |
|