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;
22 import com.intendico.data.*;
23 import java.util.Vector;
26 * This is a utility class used by BDIGoal execution, to associate a
27 * particular binding context with performing a goal. It is not
28 * intended for explicit use within goal hierarchies.
30 * <p> The {@link BDIGoal} creates individual ContextualGoal objects
31 * for each applicable plan option where the plans {@link
32 * Context#context} method returns a {@link Query} that offers
33 * multiple bindings (i.e., not null, {@link Context#EMPTY} or {@link
34 * Context#FALSE}). Plan options whose {@link Context#context} method
35 * returns null are collated without the wrapping of a ContextualGoal
36 * object, and plan options whose {@link Context#context} method
37 * returns {@link Context#EMPTY} or {@link Context#FALSE} are not
40 * <p> The ContextualGoal captures the entry data settings for the
41 * variables as well as the proposed settings that defines the plan
42 * option. It then manages the set up of the proposed settings into
43 * the data prior to executing the plan body, and the restoration of
44 * these settings if the plan body execution fails. (The variable
45 * settings are not restored if the ContextualGoal execution is
50 public class ContextualGoal extends Goal implements Precedence {
53 * Holds the Data object for the calling BDIInstance that created this
56 public Data goal_data;
59 * Holds the actual {@link Ref} objects of the context
62 public Vector/*<Ref>*/ variables;
65 * Holds {@link Ref} objects with values representing this
68 public Vector/*<Ref>*/ context;
71 * The original assignments for the variables.
73 public Vector/*<Ref>*/ original;
76 * Two ContextualGoal are equal if they are of the same goal and
77 * have the same context.
79 public boolean equals(Object c) {
80 return c instanceof ContextualGoal && equals( (ContextualGoal) c );
84 * Two ContextualGoal are equal if they are of the same goal
85 * and have the same context.
87 public boolean equals(ContextualGoal c) {
88 if ( ! c.getGoalSubgoals()[0].equals( getGoalSubgoals()[0] ) )
90 if ( context == null ) {
91 return c.context == null;
93 return Ref.equals( c.context, context );
99 public ContextualGoal(Vector/*<Ref>*/ orig,Vector/*<Ref>*/ vars,
100 Goal goal,Data data) {
101 super( goal.getGoalName() );
105 if ( variables != null )
106 context = Ref.copy( variables );
107 setGoalSubgoals( new Goal[] { goal } );
111 * A wrapping for invoking precedence of the wrapped goal. If the
112 * wrapped goal provides a precedence method, then it is invoked
113 * using the cached {@link #goal_data}, transiently establishing
114 * the invocation context, which is restored upon return.
116 public int precedence(Data data) {
117 if ( ! ( getGoalSubgoals()[ 0 ] instanceof Precedence ) )
118 return Plan.DEFAULT_PRECEDENCE;
119 if ( context == null )
120 return ((Precedence) getGoalSubgoals()[ 0 ])
121 .precedence( goal_data );
122 goal_data.set( context );
123 Ref.bind( variables, context );
124 int x = ((Precedence) getGoalSubgoals()[ 0 ]).precedence( goal_data );
125 Ref.bind( variables, original );
126 goal_data.get( context, false );
131 * Return the intention instance to be executed.
133 public Instance instantiate(String head,Data d) {
134 // Assuming data == d without checking it
135 return new ContextualGoalInstance( head, d );
139 * Utility class to represent the intention
141 public class ContextualGoalInstance extends Instance {
144 * The target intention instance
146 public Instance instance;
149 * Constructor. This established the invocation context in the
150 * intention {@link Data}.
152 public ContextualGoalInstance(String h,Data d) {
154 if ( context != null ) {
156 Ref.bind( variables, context );
158 String sub = context != null? Ref.toString( context ) : "{}";
159 instance = getGoalSubgoals()[ 0 ].instantiate( h + sub, d );
163 * Control callback whereby the intention gets notified that
164 * it is cancelled. This will forward the cancellation to the
165 * currently progressing instance, if any.
167 public void cancel() {
168 if ( instance != null )
173 * Excution of this goal, which means to execute the wrapped
174 * goal. If successful, the invocation {@link Ref} objects are
175 * updated from the final {@link Data}. Execution catches
176 * LoopEndException, but not ParallelEndException, and makes
177 * it cause a failure rather then propagate up. If execution
178 * fails, the {@link Data} context is restored by removing the
181 public States action(String head,Data d)
182 throws LoopEndException, ParallelEndException {
183 States s = States.FAILED;
185 s = instance.perform( d );
186 } catch (LoopEndException e) {
188 } catch (ParallelEndException e) {
190 throw e; // Re-thrown
192 if ( variables != null ) {
193 if ( s == States.PASSED ) {
194 d.get( variables, true );
195 } else if ( s == States.FAILED ) {
196 Ref.bind( variables, original );
197 d.get( context, false );
204 } // End of class ContextualGoalInstance
207 * Textual representation of this goal.
209 public String toString() {
210 return ( context != null? context.toString() : "{}" ) +
211 getGoalSubgoals()[ 0 ].toString();