1 /*********************************************************************
2 Copyright 2012, Ralph Ronnquist.
4 This file is part of GORITE.
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.
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.
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 **********************************************************************/
20 package com.intendico.gorite;
23 * The Action class is a utility base class for implementation of task
24 * goals that operate on a common entity. The created action object
25 * becomes a factory for goals that refer back to it, and that end up
26 * invoking the Action's {@link #execute} method as way of achieving
29 * <p> Generally, an action is a named definition of a function
30 * performed on data. It would occur in a process model in terms of a
31 * task goal, which is recognised as a usage point of the action,
32 * linking it to particular input and output data. The same action may
33 * be used elsewhere, with other data names.
35 * <p> Task goals referring to the same action object will invoke the
36 * same {@link #execute} method.
40 * public class MachineControlAdapter {
41 * Action open_lid = new Action( "open lid" ) {
42 * public boolean execute(
43 * boolean reentry,Data.Element [] ins,Data.Element [] * outs ) {
44 * .. code to perform the "open lid" action
47 * Action status = new Action( "check status" ) {
48 * public boolean execute(
49 * boolean reentry,Data.Element [] ins,Data.Element [] * outs ) {
50 * .. code to perform the "check status" action
53 * public Capability actions() {
54 * return new Capability() {{
55 * open_lid.create( new String [] { "angle" }, null );
56 * on_off.create( null, new String [] { "status" } );
62 * The example code illustrates a "machine adapter" with two actions:
63 * to "open lid" to a certain "angle", and to "check status" giving a
64 * "status". The "machine adapter" includes an "actions()" method that
65 * creates a control capability of two goals for invoking the actions.
70 * The name of the action. This is also the name of the goal for
71 * the action created via the {@link #create} method.
76 * Nominates the {@link Performer.TodoGroup} to use for performing
82 * Constructor without group.
84 public Action(String n) {
91 public Action(String n,String g) {
97 * This is a utility class to represent the appearance of the
98 * action within a goal hierarchy. Each such apprearance involves
99 * its own data connections, which are contained within the Usage
100 * class. When this task goal is executed, it firstly ensures that
101 * all input data is available, or otherwise delays the execution
102 * until they are available. Thereafter it ensures that some
103 * output data needs to be produces, before invoking the action's
104 * exectution. If all output data is already produced, the task
105 * goal execution succeeds immediately without the actual action
108 public class Usage extends Goal {
111 * The names of data elements that are inputs to the goal; the
112 * performance of a goal will be postponed until all inputs
113 * are available, although maybe not ready.
115 public String [] inputs;
118 * The names of data elements that are outputs from the
119 * action. The task goal for an action considers these: if
120 * they are all ready and available when the goal is
121 * performed, then the action execution is skipped, and the
122 * goal terminates successfully. However, an action without
123 * outputs is always executed.
125 public String [] outputs;
130 public Usage(String [] ins,String [] outs) {
131 super( Action.this.name );
134 group = getGoalGroup();
138 * Creates and returns an instance object for achieving
141 public Instance instantiate(String head,Data d) {
142 return new Invoke( head, d );
146 * The Invoke class represents the intention to performa Usage
149 public class Invoke extends Instance {
154 public Invoke(String head,Data d) {
159 * Tracking of first or sub sequence perform calls.
161 public boolean reentry = false;
164 * The execution of an action involves an initial step of
165 * establishing the data connections. This will postpone the
166 * actual action execution until all input data is
167 * available. It will also skip the action execution if all
168 * outputs are already marked ready. It is the responsibility
169 * of the actual action execution to mark outputs as ready.
171 public States action(String head,Data d) {
172 Data.Element [] ins = null;
173 Data.Element [] outs = null;
175 // Synchronise with existence and readiness of inputs.
176 if ( inputs != null ) {
177 ins = new Data.Element [ inputs.length ];
178 for ( int i = 0; i < inputs.length; i++ ) {
179 ins[ i ] = d.find( inputs[ i ] );
180 if ( ins[ i ] == null )
181 return States.BLOCKED;
182 if ( ! ins[ i ].ready )
183 return States.BLOCKED;
187 if ( outputs != null ) {
188 outs = new Data.Element [ outputs.length ];
189 for ( int i = 0; i < outputs.length; i++ ) {
190 outs[ i ] = d.create( outputs[ i ] );
194 // Invoke action implementation
195 Goal.States s = Action.this.execute( reentry, ins, outs );
198 if ( s == Goal.States.PASSED ) {
199 // Mark all outputs as ready.
200 if ( outs != null ) {
201 for ( int i = 0; i < outs.length; i++ ) {
202 outs[ i ].markReady();
211 * Makes a string representation of a string array.
213 public String toString(String [] data)
215 StringBuffer s = new StringBuffer( "[ " );
216 if ( data != null ) {
218 for ( int i = 0; i < data.length; i++ ) {
220 s.append( nameString( data[i] ) );
229 * Makes a textual representation of this action's goal.
231 public String toString(String counter) {
232 StringBuffer s = new StringBuffer( super.toString( counter ) );
233 s.append( toString( inputs ) );
235 s.append( toString( outputs ) );
242 * A factory method that makes a "usage object" for this action,
243 * representing its usage in a goal sentence. When performed,
244 * the action's execute method is invoked with the actual in and out
245 * Data.Element objects.
247 public Goal create(String [] ins,String [] outs)
249 return new Usage( ins, outs );
253 * The generic action performance method. Should be overridden by
254 * extension class for action implementation.
256 public Goal.States execute(
257 boolean reentry,Data.Element [] ins,Data.Element [] outs) {
259 StringBuffer s = new StringBuffer( "Action " );
260 s.append( Goal.nameString( name ) );
263 if ( ins != null && ins.length > 0 ) {
264 for ( int i=0; i < ins.length; i++ ) {
267 s.append( ins[i].toString() );
270 s.append( "] >> [" );
272 if ( outs != null && outs.length > 0 ) {
273 for ( int i=0; i < outs.length; i++ ) {
276 s.append( outs[i].toString() );
280 System.err.println( s.toString() );
281 return Goal.States.PASSED;
285 * Returns the {@link #group} attribute.
287 public String getTodoGroup() {
292 * Assigns the {@link #group} attribute.
294 public void setTodoGroup(String v) {