1 | package dk.deepthought.sidious.ruleengine; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.Collection; |
5 | import java.util.List; |
6 | |
7 | import org.apache.commons.logging.Log; |
8 | import org.apache.commons.logging.LogFactory; |
9 | |
10 | import dk.deepthought.sidious.explanation.Explanation; |
11 | import dk.deepthought.sidious.explanation.ExplanationEntry; |
12 | import dk.deepthought.sidious.goalhandler.Goal; |
13 | import dk.deepthought.sidious.rules.Rule; |
14 | import dk.deepthought.sidious.supportsystem.PlanRequester; |
15 | import dk.deepthought.sidious.supportsystem.Repository; |
16 | import dk.deepthought.sidious.supportsystem.State; |
17 | import dk.deepthought.sidious.supportsystem.Step; |
18 | import dk.deepthought.sidious.supportsystem.SuperLinkID; |
19 | |
20 | public class RuleEngineImpl implements RuleEngine { |
21 | |
22 | /** |
23 | * Logger for this class |
24 | */ |
25 | private static final Log logger = LogFactory.getLog(RuleEngineImpl.class); |
26 | |
27 | /* |
28 | * (non-Javadoc) |
29 | * |
30 | * @see dk.deepthought.sidious.ruleengine.RuleEngine#evaluate(dk.deepthought.sidious.supportsystem.SuperLinkID, |
31 | * dk.deepthought.sidious.supportsystem.State, dk.deepthought.sidious.supportsystem.State) |
32 | */ |
33 | public double evaluate(SuperLinkID requesterID, State current, State next, |
34 | Step step) { |
35 | if (requesterID == null || current == null || next == null |
36 | || step == null) { |
37 | logger.error("evaluate(SuperLinkID requesterID=" + requesterID |
38 | + ", State current=" + current + ", State next=" + next |
39 | + ") - null not valid input"); |
40 | throw new IllegalArgumentException("null not valid input"); |
41 | } |
42 | PlanRequester requester = Repository.getBlackboard().getRequester( |
43 | requesterID); |
44 | double evaluation = evaluateRules(requester.getRules(), current, next, |
45 | step); |
46 | return evaluation; |
47 | } |
48 | |
49 | /** |
50 | * This method evaluates each of the input <code>rules</code> according to |
51 | * the input states (<code>current</code> and <code>next</code>), and |
52 | * returns a combined value. |
53 | * |
54 | * @param rules |
55 | * the input collection of rules |
56 | * @param current |
57 | * the current state |
58 | * @param next |
59 | * the next state |
60 | * @param step |
61 | * the step |
62 | * @return a combined evaluation, 0 if rules is empty |
63 | */ |
64 | double evaluateRules(Collection<Rule> rules, State current, State next, |
65 | Step step) { |
66 | if (rules == null || current == null || next == null || step == null) { |
67 | logger.error("evaluateRules(Collection<Rule> rules=" + rules |
68 | + ", State current=" + current + ", State next=" + next |
69 | + ") - null not valid input"); |
70 | throw new IllegalArgumentException("null not valid input"); |
71 | } |
72 | double evaluation = 0; |
73 | List<ExplanationEntry> explanations; |
74 | ExplanationEntry entry; |
75 | explanations = new ArrayList<ExplanationEntry>(); |
76 | for (Rule rule : rules) { |
77 | double desire = rule.desire(current, next, step); |
78 | evaluation += desire; |
79 | entry = new ExplanationEntry(rule.getExplanation(), desire); |
80 | explanations.add(entry); |
81 | } |
82 | step.setExplanation(new Explanation(explanations)); |
83 | if (logger.isDebugEnabled()) { |
84 | logger.debug("evaluateRules(Collection<Rule> rules=" + rules |
85 | + ", State current=" + current + ", State next=" + next |
86 | + ") - combined evaluation=" + evaluation); |
87 | } |
88 | return evaluation; |
89 | } |
90 | |
91 | /* |
92 | * (non-Javadoc) |
93 | * |
94 | * @see dk.deepthought.sidious.ruleengine.RuleEngine#extractGoals(dk.deepthought.sidious.supportsystem.SuperLinkID) |
95 | */ |
96 | public Collection<Goal> extractGoals(SuperLinkID requesterID) { |
97 | PlanRequester requester = Repository.getBlackboard().getRequester( |
98 | requesterID); |
99 | if (requester == null) { |
100 | logger.error("extractGoals(SuperLinkID requesterID=" + requesterID |
101 | + ") - requester does not exist - returning empty list"); |
102 | return new ArrayList<Goal>(); |
103 | } |
104 | Collection<Rule> rules = requester.getRules(); |
105 | Collection<Goal> returnCollection = extractGoalsFromRules(rules); |
106 | if (logger.isDebugEnabled()) { |
107 | logger.debug("extractGoals(SuperLinkID requesterID=" + requesterID |
108 | + ") - returned goals=" + returnCollection); |
109 | } |
110 | return returnCollection; |
111 | } |
112 | |
113 | /** |
114 | * Method extracts and returns all goals from the input <code>rules</code>. |
115 | * |
116 | * @param rules |
117 | * the rules the goals will be extracted from |
118 | * @return the extracted goals |
119 | */ |
120 | Collection<Goal> extractGoalsFromRules(Collection<Rule> rules) { |
121 | if (rules == null) { |
122 | logger |
123 | .error("extractGoalsFromRules(Collection<Rule> rules=null) - null not valid"); |
124 | throw new IllegalArgumentException("Null not valid"); |
125 | } |
126 | Collection<Goal> goals = new ArrayList<Goal>(); |
127 | for (Rule rule : rules) { |
128 | goals.addAll(rule.getGoals()); |
129 | } |
130 | if (logger.isDebugEnabled()) { |
131 | logger.debug("extractGoalsFromRules(Collection<Rule> rules=" |
132 | + rules + ") - return value=" + goals); |
133 | } |
134 | return goals; |
135 | } |
136 | |
137 | } |