capture
[rrq/gorite.git] / com / intendico / gorite / addon / remote / RemotePerforming.java
1 /*********************************************************************
2 Copyright 2013, Ralph Ronnquist.
3 **********************************************************************/
4
5 package com.intendico.gorite.addon.remote;
6
7 import com.intendico.data.Ref;
8 import com.intendico.gorite.Capability;
9 import com.intendico.gorite.Data;
10 import com.intendico.gorite.Goal.States;
11 import com.intendico.gorite.Goal;
12 import java.util.Vector;
13
14 /**
15  * This capability wraps goals to be performed by a remote performer,
16  * i.e., one that exists in a different process. A RemotePerforming
17  * instance is created towards a remote performer, and then it manages
18  * goal transfer to that performer. To this end, the capability is set
19  * up with a model of the remote goal handling. This is used for
20  * filtering which goals to forward, and what to do with data to and
21  * from those goals. The following is an illustration:
22  * <pre>
23  *     addCapability( new RemotePerforming( my_remote_connector ) {{
24  *         addGoal( new RemoteGoal(
25  *            "review paper",
26  *            String [] { "submission" },
27  *            String [] { "review" },
28  *         ) );
29  *     }} );
30  * 
31  * }
32  * </pre>
33  * Note that my_remote_connector is an implementation of the {@link
34  * RemotePerforming.Connector} interface, to represent the "logical
35  * connection" to the remote performer. When performing a goal, the
36  * connector is expected to create a {@link
37  * RemotePerforming.Connection} object to represent a particular
38  * realisation of the logical connection for the particular goal
39  * execution.
40  * <p>
41  * Further, we note that RemotePerforming is a {@link Capability}, and
42  * as such, it may have other goals and sub capabilities than the
43  * {@link RemotePerforming.RemoteGoal}. Also, once a RemoteGoal is
44  * created within a RemotePerforming capability, it may in fact be added
45  * to another capability than the one it is created within. However,
46  * doing so usually causes more grief than benefits.
47  */
48 public class RemotePerforming extends Capability {
49
50     /**
51      * Holds the remote end connector.
52      */
53     public Connector connector;
54
55     /**
56      * Constructor with a {@link Connector} implementation to be used
57      * for interacting with the remote end.
58      */
59     public RemotePerforming(Connector c) {
60         connector = c;
61     }
62     
63     // added so that a remote goal could be created non-anonymously
64     public RemoteGoal create( String name,String [] i,String [] o ) {
65         return new RemoteGoal( name, i, o );
66     }
67
68     /**
69      * This class is a wrapper for goals that are to be performed by
70      * the remote side.
71      */
72     public class RemoteGoal extends Goal {
73
74         /**
75          * Keeps track of names of goal inputs.
76          */
77         public String [] ins;
78
79         /**
80          * Keeps track of goal outputs.
81          */
82         public String [] outs;
83
84         /**
85          * Constructor with goal name, input names and output names.
86          */
87         public RemoteGoal(String name,String [] i,String [] o)
88         {
89             super( name );
90             ins = i;
91             outs = o;
92         }
93
94         /**
95          * Overrides {@link Goal#instantiate} to create a {@link
96          * RemoteInstance} to manage remote goal execution.
97          */
98         public Instance instantiate(String h,Data d)
99         {
100             return new RemoteInstance( h, d );
101         }
102
103
104         public class RemoteInstance extends Instance {
105
106             public RemoteInstance(String h,Data d)
107             {
108                 super( h );
109             }
110
111             /**
112              * The identification of the remote end connection.
113              */
114             public Connection connection = null;
115
116             /**
117              * Keep track of output Ref objects
118              */
119             public Vector<Ref> output;
120
121             /**
122              * Manages remote goal execution. On first call, the
123              * remote goal is triggered, while STOPPED is returned,
124              * and on subsequent calls, the {@link Connection} is
125              * queried about completion.
126              */
127             public States action(String head,Data d) {
128
129                 if ( connection == null ) {
130                     Vector<Ref> input = Ref.create( ins );
131                     d.get( input, true );
132                     output = Ref.create( outs );
133                     connection = connector.perform(
134                         head, getGoalName(), input, output );
135                     return States.STOPPED;
136                 }
137                 try {
138                     States s = connection.check();
139                     if ( s == States.PASSED || s == States.FAILED ) { 
140                         output = connection.results();
141                         //System.err.println( output );
142                         d.set( output );
143                     }
144                     return s;
145                 } catch (Throwable t) {
146                     t.printStackTrace();
147                     cancel();
148                     return States.CANCEL;
149                 }
150             }
151
152             /**
153              * Overrides {@link Instance#cancel} to forward
154              * cancellation to the connection (if any)
155              */
156             public void cancel()
157             {
158                 if ( connection != null )
159                     connection.cancel();
160             }
161         }
162     }
163 }
164