capture
[rrq/gorite.git] / com / intendico / gorite / addon / Perceptor.java
1 /*********************************************************************
2 Copyright 2012, Ralph Ronnquist.
3
4 This file is part of GORITE.
5
6 GORITE is free software: you can redistribute it and/or modify it
7 under the terms of the Lesser GNU General Public License as published
8 by the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 GORITE is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14 License for more details.
15
16 You should have received a copy of the Lesser GNU General Public
17 License along with GORITE.  If not, see <http://www.gnu.org/licenses/>.
18 **********************************************************************/
19
20 package com.intendico.gorite.addon;
21
22 import com.intendico.gorite.*;
23
24 /**
25  * This is a class for implementing a performer percept channel, where
26  * each percept triggers an intention for handling it, which gets
27  * added to a {@link com.intendico.gorite.Performer.TodoGroup} for
28  * eventual processing.
29  *
30  * <p> The Perceptor class is made separate from Performer so as to
31  * allow multiple, different perceptors and to simplify its use at the
32  * perception source end.
33  *
34  * <p> A "pure" event driven system would be run via the {@link
35  * Executor#run} method (rather than using a top level {@link
36  * Performer#performGoal(Goal,String,Data)} call), and have Perceptor
37  * objects to cause executions.
38  */
39 public class Perceptor {
40
41     /**
42      * Keeps track of which {@link Performer} this is a perceptor
43      * for. This is given as constructor argument, and it typically
44      * remains unchanged. Though there is no harm in changing it and
45      * thereby move the Perceptor to another Performer.
46      */
47     public Performer performer;
48
49     /**
50      * Keeps track of which {@link Goal} hierarchy to use for handling
51      * a percept. It must not be null, and is given as optional
52      * constructor argment. The default goal hierarchy is
53      *
54      * <pre>
55      *     new BDIGoal( "handle percept" )
56      * </pre>
57      *
58      * which thus allows the actual goal hierarchy be defined among
59      * the performers capabilities, with possibly many alternative
60      * handler plans depending on the kinds of percepts.
61      */
62     public Goal handler;
63
64     /**
65      * Keeps track of which {@link com.intendico.gorite.Data.Element}
66      * name to use for the percept object. The default name is
67      * "percept".
68      */
69     public String data_name = "percept";
70
71     /**
72      * Keeps track of which {@link
73      * com.intendico.gorite.Performer.TodoGroup} to use for the
74      * percept handling intentions. The default group is "percepts".
75      */
76     public String todo_group = "percepts";
77
78     /**
79      * Constructor with performer, goal and todo group name.
80      */
81     public Perceptor(Performer p,Goal g,String todo)
82     {
83         performer = p;
84         handler = g;
85         todo_group = todo;
86         g.setGoalGroup( todo );
87     }
88
89     /**
90      * Constructor with performer and goal, using default todo group.
91      */
92     public Perceptor(Performer p,Goal g)
93     {
94         performer = p;
95         handler = g;
96         g.setGoalGroup( todo_group );
97     }
98
99     /**
100      * Alternative constructor with goal name and todo group name.
101      */
102     public Perceptor(Performer p,String goal,String todo) {
103         this( p, new BDIGoal( goal ), todo );
104     }
105
106     /**
107      * Alternative constructor with performer and name of a BDI goal
108      * to be created here.
109      */
110     public Perceptor(Performer p,String goal)
111     {
112         this( p, new BDIGoal( goal ) );
113     }
114
115     /**
116      * Alternative constructor with performer only, and using the
117      * default percept handling goal <tt>"handle percept"</tt> and
118      * default todo group <tt>"percepts"</tt>.
119      */
120     public Perceptor(Performer p)
121     {
122         this( p, "handle percept" );
123     }
124
125     /**
126      * Utility method to reset the perceptor set up. The new settings
127      * apply for subsequent perceive calls.
128      */
129     public void setup(String goal,String data,String todo) {
130         handler = new BDIGoal( goal );
131         handler.setGoalGroup( todo );
132         data_name = data;
133         todo_group = todo;
134     }
135
136     /**
137      * The method to use for making the performer perceive
138      * something. The given object is set up as value of a named data
139      * element, and percept handling goal is instantiated for handling
140      * it.
141      */
142     public void perceive(Object percept)
143     {
144         perceive( percept, new Data(), handler );
145     }
146
147     /**
148      * Alternative perception method with a given a Data object.
149      */
150     public void perceive(Object percept,Data data) {
151         perceive( percept, data, handler );
152     }
153
154     /**
155      * Alternative perception method with a given a Data object and
156      * special perception goal name.
157      */
158     public void perceive(Object percept,Data data,String goal) {
159         perceive( percept, data, goal != null? new BDIGoal( goal ) : handler );
160     }
161
162     /**
163      * Alternative perception method with a given a Data object and
164      * special perception goal name.
165      */
166     public void perceive(Object percept,Data data,Goal goal) {
167
168         if ( ! "X".equals( data.thread_name ) ) {
169             // This indicates that the Data object is already used or
170             // in use, which can cause all sorts of funny things
171             throw new Error( "Schizogenic Data object!!" );
172         }
173
174         data.setValue( data_name, percept );
175         data.setValue( Goal.PERFORMER, performer );
176         
177         if ( goal == null )
178             goal = handler;
179         Goal.Instance gi = goal.instantiate( todo_group, data );
180
181         // The following set up is essential to make it appear that
182         // the goal instace has been performed. (c.f {@link
183         // Goal.Instance#perform})
184         gi.data = data;
185         gi.performer = performer;
186         data.link( gi.thread_name );
187
188         //System.err.println( "Data = " + data );
189         //System.err.println( "Data:" + data_name + " = " + percept );
190
191         try {
192             performer.execute( false, gi, todo_group);
193         } catch (Exception e) {
194             // Not good :-(
195             e.printStackTrace();
196         }
197         performer.signalExecutor();
198     }
199 }