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.Inquirable;
23 import com.intendico.data.Query;
24 import com.intendico.data.Rule;
25 import com.intendico.data.Store;
26 import com.intendico.gorite.addon.Reflector;
27 import java.util.Collection;
28 import java.util.Hashtable;
29 import java.util.Iterator;
30 import java.util.Vector;
33 * A Capability is a container of {@link Goal} hierarchies, which are
34 * accessible by their names, and understood to represent alternative
35 * ways in which that named goal may be achieved. It provides lookup
36 * context for {@link BDIGoal} goals.
38 * <p> A Capability may also contain {@link Rule} objects, which are
39 * added by the {@link #addRule} method. The {@link Rule} objects are
40 * collated into the owning {@link Performer} {@link
41 * Performer#rule_set rule_set} to be applied as part of the goal
44 public class Capability {
47 * The goals of this capability, clustered by name.
49 private Hashtable/*<String,Vector<Goal>>*/ goals =
50 new Hashtable/*<String,Vector<Goal>>*/();
53 * The table of inqueriable belief structures of this capability,
54 * primarily understood qua the {@link Inquirable} interface. This
55 * table is initially built at construction time by {@link
56 * #putInquirable(Inquirable)} calls, and by elevating
57 * inqueriables of sub capabilities that are added to this
58 * capability. Eventually, there is also a {@link
59 * #shareInquirables} invocation, which accepts incoming
60 * inqueriables, and the distributes this {@link Inquirable}
61 * collection downwards to sub capabilities. In general, all
62 * capabilities form the same name-to-store mapping throughout a
63 * performer, except where name conflicts arise.
65 private Hashtable/*<String,Inquirable>*/ inquirables =
66 new Hashtable/*<String,Inquirable>*/();
69 * The inner capabilities of this capability.
71 private Vector/*<Capability>*/ inner;
74 * The {@link Rule} objects of this capability.
76 private Vector/*<Rule>*/ rules;
79 * The performer that has this capability.
84 * This interface is implemented by the deferred text form
85 * entities (rules or reflectors).
87 public interface Deferred {
89 * The method by which this entity installs itself.
91 public void install();
95 * The collection of deferred entities. This is set to null by the
96 * first {@link #shareInquirables(Collection)} call.
98 private Vector/*<Deferred>*/ deferred = new Vector/*<Deferred>*/();
101 * Utility method to install a Deferred object subsequent to the
102 * first invokation of {@link #shareInquirables(Collection)}
104 public void add(Deferred entity) {
105 if ( deferred == null ) {
108 deferred.add( entity );
113 * Constructs a vector of all goals under the given name, by
114 * considering the local table and recursively from inner
117 public Vector/*<Goal>*/ lookup(String name) {
118 Vector/*<Goal>*/ g = new Vector/*<Goal>*/();
119 if ( goals.get( name ) != null )
120 g.addAll( (Vector/*<Goal>*/) goals.get( name ) );
121 if ( inner != null ) {
122 for ( Iterator/*<Capability>*/ e =
123 inner.iterator(); e.hasNext(); ) {
124 g.addAll( ((Capability)e.next()).lookup( name ) );
131 * Add a goal to this capability.
133 public void addGoal(Goal g) {
134 Vector/*<Goal>*/ v = (Vector/*<Goal>*/) goals.get( g.getGoalName() );
136 v = new Vector/*<Goal>*/();
137 goals.put( g.getGoalName(), v );
143 * Add a plan to this capability.
145 public void addPlan(Plan g) {
150 * Add an inner capability. All {@link #inquirables} of the added
151 * capability are added to the {@link #inquirables} of this
152 * capability, unless their name starts with underscore, or an
153 * equally named {@link Inquirable} is already defined.
155 * <p> Note that a capability tree built by adding children before
156 * grand children yield a different, less complete elevation of
157 * inquirables than if the grand children are added to the
160 * <p> When adding a capability late (i.e., after the first
161 * shareInquirables invocation, or more precisely when {@link
162 * #deferred} is null), then {@link #shareInquirables} is invoked;
163 * it's only invoked on the added capability unless an inquirable
164 * was gained, in which case {@link #shareInquirables} is invoked
165 * on this capability, for distributing the gained inquirables
166 * over the whole capability sub tree.
168 * @see #shareInquirables(Collection)
170 public void addCapability(Capability c) {
172 inner = new Vector/*<Capability>*/();
173 if ( ! inner.contains( c ) )
175 if ( performer != null ) {
176 c.setPerformer( performer );
178 boolean extended = false;
179 for ( Iterator/*<Inquirable>*/ si = c.inquirables.values().iterator();
181 Inquirable inquirable = (Inquirable) si.next();
182 String name = inquirable.getName();
183 if ( ( ! name.startsWith( "_" ) ) &&
184 inquirables.get( name ) == null ) {
185 putInquirable( inquirable );
189 if ( deferred == null ) {
191 shareInquirables( null );
193 c.shareInquirables( inquirables.values() );
199 * Creates a new {@link Rule} object with given antecedent and
200 * consequent {@link Query} objects.
202 public void addRule(Query a,Query c) {
204 rules = new Vector/*<Rule>*/();
205 Rule r = new Rule( a, c );
207 if ( performer != null ) {
208 if ( Goal.isTracing() )
209 System.err.println( "** Installing " + r + " for " + performer );
210 performer.rule_set.add( r );
215 * Utility method to lookup a given goal name.
217 public boolean hasGoal(String name) {
218 if ( goals.get( name ) != null )
222 for ( Iterator/*<Capability>*/ ci = inner.iterator(); ci.hasNext(); ) {
223 if ( ((Capability) ci.next()).hasGoal( name ) )
230 * Tells whether or not this capability provides some method or
231 * methods for all named goals.
233 public boolean hasGoals(String [] gs) {
236 for ( int i = 0; i < gs.length; i++ ) {
237 if ( ! hasGoal( gs[i] ) )
244 * Returns an Inquirable qua Store, or null if it's not a Store.
246 public Store getStore(String name) {
247 Object x = inquirables.get( name );
248 if ( x instanceof Store )
254 * Returns the Inquirable as mapped, or null if not found.
256 public Inquirable getInquirable(String name) {
257 return (Inquirable) inquirables.get( name );
261 * Registers an {@link Inquirable} to be mapped. A Capability
262 * extension should register all locally created inquirables.
264 public void putInquirable(Inquirable inquirable) {
265 inquirables.put( inquirable.getName(), inquirable );
269 * Registers an {@link Inquirable} under an alias. A Capability
270 * extension should register all locally created inquirables.
272 public void putInquirable(String name,Inquirable inquirable) {
273 inquirables.put( name, inquirable );
277 * This method extends the inquirables collection with the given
278 * collection, then propagates its map downwards to sub
279 * capabilities. Finally all {@link Deferred} entities held in
280 * {@link #deferred} are installed, before setting {@link
281 * #deferred} to null.
283 * <p> Note that a {@link Performer} (which is a Capability) will
284 * invoke this once the first time it is added to the {@link
285 * Executor default executor}. A multi {@link Executor} model may
286 * need additional, explicit initial calls to this method in order
287 * to establish complete inquirables sharing.
289 * @see #addCapability(Capability)
291 public void shareInquirables(Collection/*<Inquirable>*/ shared) {
292 if ( Goal.isTracing() ) {
293 System.err.println( "** Sharing inquirables in " + this );
295 // Install incoming inquirables unless defined locally
296 if ( shared != null ) {
297 for ( Iterator/*<Inquirable>*/ si =
298 shared.iterator(); si.hasNext(); ) {
299 Inquirable inquirable = (Inquirable) si.next();
300 if ( inquirables.get( inquirable.getName() ) == null ) {
301 putInquirable( inquirable );
305 // Propagate all local inquirables to inner capabilities
306 if ( inner != null ) {
307 shared = inquirables.values();
308 for ( Iterator/*<Capability>*/ i = inner.iterator();
310 Capability c = (Capability) i.next();
311 c.shareInquirables( shared );
314 // Install deferred entities
315 if ( deferred != null ) {
316 for ( Iterator/*<Deferred>*/ di = deferred.iterator();
318 ((Deferred) di.next()).install();
325 * Sets the performer for this capability, and propagates it to
326 * all inner capabilities.
328 public void setPerformer(Performer p) {
329 if ( performer != null ) {
330 if ( performer != p ) {
331 // The capability is moved
332 throw new Error( "Invalid GORITE model" );
337 if ( rules != null ) {
338 for ( Iterator/*<Rule>*/ i = rules.iterator(); i.hasNext(); ) {
339 Rule r = (Rule) i.next();
340 performer.rule_set.add( r );
343 if ( inner != null ) {
344 for ( Iterator/*<Capability>*/ i =
345 inner.iterator(); i.hasNext(); ) {
346 Capability c = (Capability) i.next();
354 * Overridable method where to add Capability initialisation
355 * code. This method is invoked when the performer is set up, and
356 * all inner capabilites are initialized. This base implementation
357 * does not do anything.
359 public void initialize() {
363 * Returns the performer that has this capability.
365 public Performer getPerformer() {
370 * Utility method that creates the goal of establishing a
373 public Goal deploy(String name) {
374 return new Goal( "deploy " + name ) {
375 public States execute(Data d) {
376 String ttn = getGoalName().substring( 7 );
377 Team t = (Team) performer;
378 Team.TaskTeam tt = t.getTaskTeam( ttn );
380 throw new Error( "Missing task team '" + ttn +
381 "' in team '" + t.getName() + "'" );
382 if ( tt.establish( d ) )
383 return States.PASSED;
384 return States.FAILED;
390 * Adds a {@link Reflector} to this capability. The actual
391 * addition is deferred until after the inquirables are shared, at
392 * which time the (@link Performer} is known.
394 public void addReflector(
395 final String goal,final String todo,final Query query) {
396 add( new Deferred() {
398 * Installs this as a proper {@link Reflector}.
400 public void install() {
401 Reflector r = new Reflector( getPerformer(), goal, todo );
408 * Returns the {@link #inquirables} collection.
410 public Hashtable/*<String,Inquirable>*/ getInquirables() {
415 * Return the goals table.
417 public Hashtable/*<String,Vector<Goal>>*/ getGoals() {
422 * Return the inner capabilities, if any.
424 public Vector/*<Capability>*/ getInner() {