View Javadoc
1   package org.apache.maven.plugin.cxx.utils;
2   
3   /*
4    * Copyright (C) 2011-2016, Neticoa SAS France - Tous droits réservés.
5    * Author(s) : Franck Bonin, Neticoa SAS France
6    *
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   *
19   */
20  
21  /**
22   * 
23   * @author fbonin
24   * 
25   */
26  public abstract class Automate implements ActionExecutor
27  {
28      private static class Transition
29      {
30          /**
31           * Etat suivant
32           */
33          private int nextState = -1;
34          
35          /**
36           * Action à effectuée
37           */
38          private Action transitionAction = null;
39  
40          /**
41           * @param pINextState
42           * @param pIAction
43           */
44          public Transition( final int pINextState, final Action pIAction )
45          {
46              nextState = pINextState;
47              transitionAction = pIAction;
48          }
49  
50          /**
51           * tell if transition exists
52           * 
53           * @return true if transition exist
54           */
55          public boolean isPossible()
56          {
57              return ( transitionAction != null ) && ! transitionAction.equals( impossible );
58          }
59  
60          /**
61           * 
62           * @param pIExecutor
63           * @param pIAutomate
64           * @param pIParam
65           * @throws AutomateException
66           */
67          public void passThrough( final ActionExecutor pIExecutor, final Automate pIAutomate,
68                          final Object pIParam ) throws AutomateException
69          {
70              transitionAction.action( pIExecutor, pIParam );
71              pIAutomate.changeState( nextState, pIParam );
72          }
73      };
74  
75      private static boolean classInititialized = false;
76      private static Action empty = new Action()
77      {
78          public void action( final ActionExecutor pIExecutor, final Object pIParam )
79          {
80              // System.out.println(" Information : empty() action called for executor "
81              // + aiExecutor.getName());
82          }
83  
84          public String getName()
85          {
86              return "empty";
87          }
88      };
89      private static Action impossible = new Action()
90      {
91          public void action( final ActionExecutor aiExecutor, final Object aiParam ) throws AutomateException
92          {
93              throw new AutomateException( "action 'impossible(Object aiParam)' was called for executor "
94                   + aiExecutor.getName() );
95          }
96  
97          public String getName()
98          {
99              return "impossible";
100         }
101     };
102     
103     /**
104      * 
105      */
106     private static int labelCount = 0;
107     private static Transition model[][] = null;
108     private static Action stateActions[] = null;
109     
110     /**
111      * 
112      */
113     private static int stateCount = 0;
114 
115     /**
116      * TODO
117      * 
118      * @param aiStateCount
119      * @param aiLabelCount
120      * @throws AutomateException
121      */
122     protected static void initializeAutomate( final int aiStateCount, final int aiLabelCount ) throws AutomateException
123     {
124         stateCount = aiStateCount;
125         labelCount = aiLabelCount;
126         if ( ( 0 >= stateCount ) || ( 0 >= labelCount ) )
127         {
128             throw new AutomateException(
129                  "You must provide a positive value for stateCount and labelCount when calling initializeAutomate()" );
130         }
131         model = new Transition[stateCount][labelCount];
132         stateActions = new Action[stateCount];
133         for ( int e = 0; e < stateCount; e++ )
134         {
135             stateActions[e] = empty;
136             for ( int t = 0; t < labelCount; t++ )
137             {
138                 model[e][t] = new Transition( e, impossible );
139             }
140         }
141         classInititialized = true;
142     }
143 
144     /**
145      * 
146      * @param aiState
147      * @param aiStateAction
148      */
149     protected static void setState( final int aiState, final Action aiStateAction )
150     {
151         setState( aiState, aiStateAction, -1, null );
152     } 
153     
154     /**
155      * @param aiState
156      * @param aiStateAction
157      * @param aiDefaultTargetState
158      * @param aiDefaultAction
159      */
160     protected static void setState( final int aiState, final Action aiStateAction,
161        final int aiDefaultTargetState, final Action aiDefaultAction )
162     {
163         if ( null != aiStateAction )
164         {
165             stateActions[aiState] = aiStateAction;
166         }
167         for ( int t = 0; t < labelCount; t++ )
168         {
169             // we focus on unhandled transitions
170             if ( null == model[aiState][t].transitionAction || impossible == model[aiState][t].transitionAction )
171             {
172                 if ( null != aiDefaultAction )
173                 {
174                     model[aiState][t].transitionAction = aiDefaultAction;
175                 }
176                 if ( aiDefaultTargetState >= 0 )
177                 {
178                     model[aiState][t].nextState = aiDefaultTargetState;
179                 }
180             }
181         }
182     }
183 
184     /**
185      * setTransition wire your automate
186      * 
187      * @param aiState
188      * @param aiLabel
189      * @param aiNextState
190      * @param aiAction
191      */
192     protected static void setTransition( final int aiState, final int aiLabel, final int aiNextState,
193                 final Action aiAction )
194     {
195         model[aiState][aiLabel] = new Transition( aiNextState, aiAction );
196     }
197 
198     /**
199      * Etat courant
200      */
201     private int currentState = -1;
202     
203     /**
204      * 
205      */
206     private ActionExecutor executor = null;
207     
208     /**
209      * Objet initialisé
210      */
211     private boolean objectInitialized = false;
212     
213 
214     protected Automate( final ActionExecutor aiExecutor, final int aiCurrentState,
215                 final Object aioParam ) throws AutomateException
216     {
217         initializer( aiExecutor, aiCurrentState, aioParam );
218     }
219 
220     protected Automate( final int aiCurrentState, final Object aioParam )
221                 throws AutomateException 
222     {
223         initializer( this, aiCurrentState, aioParam );
224     }
225 
226     private void changeState( final int aiNextState, final Object aiParam ) throws AutomateException
227     {
228         if ( ! objectInitialized || ( currentState != aiNextState ) )
229         {
230             currentState = aiNextState;
231             notifyCurrentStateChanged();
232             objectInitialized = true;
233             stateActions[currentState].action( executor, aiParam ); // <=> // this.stateActions[currentState](aiParam);
234         }
235     }
236 
237     /**
238      * event function top inform automate from label to try
239      * 
240      * @param aiLabel
241      *            label to try
242      * @param aiParam
243      *            associated data that transition action will receive
244      *            (and next state action too)
245      * @throws AutomateException
246      */
247     public void event( final int aiLabel, final Object aiParam ) throws AutomateException
248     {
249         model[currentState][aiLabel].passThrough( executor, this, aiParam );
250     }
251 
252     /**
253      * @return currentState
254      */
255     public int getCurrentState()
256     {
257         return currentState;
258     }
259     
260     protected void initializer( final int aiCurrentState, final Object aiParam )
261         throws AutomateException
262     {
263         initializer( this, aiCurrentState, aiParam );
264     }
265 
266     protected void initializer( final ActionExecutor aiExecutor, final int aiCurrentState, final Object aiParam )
267         throws AutomateException
268     {
269         //System.out.println("Automate.initializer : " + classInititialized + "," + aiCurrentState
270         //    + "," + isInFinalState() );
271         if ( classInititialized && ( currentState == -1 || isInFinalState() ) )
272         {
273             executor = aiExecutor;
274             changeState( aiCurrentState, aiParam );
275         } 
276         else
277         {
278             throw new AutomateException(
279                 "public static void initializeAutomate() must be called before trying to instantiate an Automate" );
280         }
281     }
282 
283     /**
284      * 
285      */
286     protected abstract boolean isInFinalState();
287 
288     /**
289      * according to current state, tell if transition exists useful to
290      * activate/unactivate GUI components
291      * 
292      * @param aiLabel transition label
293      * 
294      * @return true if transition exist
295      */
296     public boolean isPossible( final int aiLabel )
297     {
298         return model[currentState][aiLabel].isPossible();
299     }
300 
301     /**
302      * 
303      */
304     protected abstract void notifyCurrentStateChanged();
305 };