capture
[rrq/gorite.git] / com / intendico / gorite / addon / RemotePerforming.java
1 /*********************************************************************
2 Copyright 2013, Ralph Ronnquist.
3 **********************************************************************/
4
5 package com.intendico.gorite.addon;
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 remoteHCyl2 performer,
16  * i.e., one that exists in a different process. A RemotePerforming
17  * instance is created towards a remoteHCyl2 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 remoteHCyl2 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 remoteHCyl2 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      * This interface is to be implemented by the remoteHCyl2 channel
52      * management sub system.
53      */
54     public interface Connector {
55         /**
56          * This method should trigger remoteHCyl2 goal execution.  It
57          * creates a {@link Connection} object to represent the
58          * particular goal execution. Thereafter goal execution will
59          * be monitored via the {@link Connection} methods.
60          */
61         public Connection perform(
62             String goal,String head,Vector<Ref> ins,Vector<Ref> outs);
63     }
64
65     /**
66      * This interface is implemented by the connectivity sub system,
67      * to represent a particular goal execution connection.
68      */
69     public interface Connection {
70         /**
71          * This method is used repeatedly in order to discover the
72          * status of the remote goal execution.
73          */
74         public States check() throws Throwable;
75
76         /**
77          * This method will be called if the goal execution is to be
78          * cancelled form the triggering side.
79          */
80         public void cancel();
81         
82         public Vector<Ref> results();
83     }
84
85     /**
86      * Holds the remote end connector.
87      */
88     public Connector connector;
89
90     /**
91      * Constructor with a {@link Connector} implementation to be used
92      * for interacting with the remote end.
93      */
94     public RemotePerforming(Connector c) {
95         connector = c;
96     }
97     
98     public RemoteGoal create( String name,String [] i,String [] o ) {
99         return new RemoteGoal( name, i, o );
100     }
101
102     /**
103      * This class is a wrapper for goals that are to be performed by
104      * the remote side.
105      */
106     public class RemoteGoal extends Goal {
107
108         /**
109          * Keeps track of names of goal inputs.
110          */
111         public String [] ins;
112
113         /**
114          * Keeps track of goal outputs.
115          */
116         public String [] outs;
117
118         /**
119          * Constructor with goal name, input names and output names.
120          */
121         public RemoteGoal(String name,String [] i,String [] o)
122         {
123             super( name );
124             ins = i;
125             outs = o;
126         }
127
128         /**
129          * Overrides {@link Goal#instantiate} to create a {@link
130          * RemoteInstance} to manage remote goal execution.
131          */
132         public Instance instantiate(String h,Data d)
133         {
134             return new RemoteInstance( h, d );
135         }
136
137
138         public class RemoteInstance extends Instance {
139
140             public RemoteInstance(String h,Data d)
141             {
142                 super( h );
143             }
144
145             /**
146              * The identification of the remote end connection.
147              */
148             public Connection connection = null;
149
150             /**
151              * Keep track of output Ref objects
152              */
153             public Vector<Ref> output;
154
155             /**
156              * Manages remote goal execution. On first call, the
157              * remote goal is triggered, while STOPPED is returned,
158              * and on subsequent calls, the {@link Connection} is
159              * queried about completion.
160              */
161             public States action(String head,Data d) {
162
163                 if ( connection == null ) {
164                     Vector<Ref> input = Ref.create( ins );
165                     d.get( input, true );
166                     output = Ref.create( outs );
167                     connection = connector.perform(
168                         head, getGoalName(), input, output );
169                     return States.STOPPED;
170                 }
171                 try {
172                     States s = connection.check();
173                     if ( s == States.PASSED || s == States.FAILED ) { 
174                         output = connection.results();
175                         //System.err.println( output );
176                         d.set( output );
177                     }
178                     return s;
179                 } catch (Throwable t) {
180                     t.printStackTrace();
181                     cancel();
182                     return States.CANCEL;
183                 }
184             }
185
186             /**
187              * Overrides {@link Instance#cancel} to forward
188              * cancellation to the connection (if any)
189              */
190             public void cancel()
191             {
192                 if ( connection != null )
193                     connection.cancel();
194             }
195         }
196     }
197 }
198