Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/* Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Ludovic Apvrille
*
* ludovic.apvrille AT enst.fr
*
* This software is a computer program whose purpose is to allow the
* edition of TURTLE analysis, design and deployment diagrams, to
* allow the generation of RT-LOTOS or Java code from this diagram,
* and at last to allow the analysis of formal validation traces
* obtained from external tools, e.g. RTL from LAAS-CNRS and CADP
* from INRIA Rhone-Alpes.
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/ or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited
* liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*/
package avatartranslator;
import graph.AUTGraph;
import graph.AUTState;
import graph.AUTTransition;
import myutil.TraceManager;
import org.jfree.data.json.impl.JSONObject;
import java.util.*;
/**
* Class AvatarCompactDependencyGraph
* Creation: 27/06/2023
*
* @author Ludovic APVRILLE
* @version 1.0 27/06/2023
*/
public class AvatarCompactDependencyGraph {
private AUTGraph graph;
private int id = 0;
public AvatarCompactDependencyGraph() {
//fromStates = new HashMap<>();
}
public AUTGraph getGraph() {
return graph;
}
public void setGraph(AUTGraph _g) {
graph = _g;
}
/*public void setRefs(HashMap<AvatarElement, ArrayList<AUTState>> _toStates, HashMap<AUTState, AvatarElement> _fromStates) {
toStates = _toStates;
fromStates = _fromStates;
}*/
public AUTState getFirstStateWithReference(AvatarElement _ae) {
return graph.getFirstStateWithReference(_ae);
}
public void buildGraph(AvatarSpecification _avspec, boolean withID) {
graph = new AUTGraph();
id = 0;
ArrayList<AUTState> states = new ArrayList<>();
ArrayList<AUTTransition> transitions = new ArrayList<>();
// First build state machines, and then link them on RD / WR operators
for (AvatarBlock block : _avspec.getListOfBlocks()) {
AvatarStateMachine asm = block.getStateMachine();
if (!(asm.isBasicStateMachine())) {
AvatarStartState ass = asm.getStartState();
// Make general structure
makeCompactDependencyGraphForAvatarElement(block, ass, null, null, states, transitions, withID, null);
}
}
ArrayList<AUTState> newStates = new ArrayList<>();
HashSet<AUTState> oldStatesRemove = new HashSet<>();
HashSet<AUTState> previousRead = new HashSet<>();
// Connect everything i.e. writers to all potential readers
// For each writing state, we draw a transition to all possible corresponding readers
// Double direction if synchronous
for (AUTState state : states) {
AvatarActionOnSignal aaos = getAvatarActionOnSignalInReferences(state);
if (aaos != null) {
// Find previous of state
AUTTransition previousTr = state.inTransitions.get(0);
int previousId = previousTr.origin;
AUTState previousState = null;
for (AUTState st : states) {
if (st.id == previousId) {
previousState = st;
break;
}
}
if (previousState != null) {
AvatarSignal signal = aaos.getSignal();
boolean found = false;
AUTTransition previousDTr = null;
AUTState previousStateD = null;
if (signal.isOut()) {
// Write operation
AvatarSignal correspondingSig = _avspec.getCorrespondingSignal(signal);
//TraceManager.addDev("Corresponding signal=" + correspondingSig);
if (correspondingSig != null) {
for (AUTState stateDestination : states) {
AvatarActionOnSignal aaosD = getAvatarActionOnSignalInReferences(stateDestination);
if (aaosD != null) {
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
if (aaosD.getSignal() == correspondingSig) {
// Found relation
//TraceManager.addDev("Found relation!");
found = true;
oldStatesRemove.add(state);
// Create a new state dedicated to this relation
AUTState newState = new AUTState(id);
newState.referenceObject = state.referenceObject;
newState.info = state.info;
newStates.add(newState);
id++;
AUTTransition tr = new AUTTransition(previousId, "", newState.id);
transitions.add(tr);
previousState.addOutTransition(tr);
newState.addInTransition(tr);
tr = new AUTTransition(newState.id, "", state.id);
transitions.add(tr);
newState.addOutTransition(tr);
state.addInTransition(tr);
// We must do the same for the destination : create a state before
// Find previous of state
previousDTr = stateDestination.inTransitions.get(0);
int previousDId = previousDTr.origin;
previousStateD = null;
for (AUTState st : states) {
if (st.id == previousDId) {
previousStateD = st;
break;
}
}
if (previousStateD != null) {
oldStatesRemove.add(stateDestination);
previousRead.add(previousStateD);
AUTState newStateD = new AUTState(id);
newStateD.referenceObject = stateDestination.referenceObject;
newStateD.info = stateDestination.info;
newStates.add(newStateD);
id++;
// linking the new state to the correct states
tr = new AUTTransition(previousDId, "", newStateD.id);
transitions.add(tr);
previousStateD.addOutTransition(tr);
newStateD.addInTransition(tr);
tr = new AUTTransition(newStateD.id, "", stateDestination.id);
transitions.add(tr);
newStateD.addOutTransition(tr);
stateDestination.addInTransition(tr);
// Links between the two new states
tr = new AUTTransition(newState.id, "", newStateD.id);
transitions.add(tr);
newState.addOutTransition(tr);
newStateD.addInTransition(tr);
AvatarRelation ar = _avspec.getAvatarRelationWithSignal(correspondingSig);
if (!(ar.isAsynchronous())) {
tr = new AUTTransition(newStateD.id, "", newState.id);
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
transitions.add(tr);
newStateD.addOutTransition(tr);
newState.addInTransition(tr);
}
// We can remove the transition between the prev and the first sttae of this read
}
}
}
}
}
}
if (found) {
// We have to remove the old transition
if (state.inTransitions.size() > 0) {
TraceManager.addDev("Found: we have to remove the wrong transition tr=" + state.inTransitions.get(0).toString());
previousState.outTransitions.remove(0);
state.inTransitions.remove(0);
transitions.remove(previousTr);
} else {
TraceManager.addDev("No inTransition for state " + state.id);
}
}
}
}
}
// We remove all transitions from previous to the first next in read operations
for (AUTState state : previousRead) {
if (state.outTransitions.size() > 0) {
AUTTransition tr = state.outTransitions.get(0);
AUTState otherState = states.get(tr.destination);
state.outTransitions.remove(0);
otherState.inTransitions.remove(0);
transitions.remove(tr);
}
}
for (AUTState state : newStates) {
states.add(state);
}
for (AUTState state : oldStatesRemove) {
ArrayList<AUTTransition> newTR = new ArrayList<>();
for (AUTTransition atPrev : state.inTransitions) {
for (int i = 0; i < state.outTransitions.size(); i++) {
AUTTransition tr = new AUTTransition(atPrev.origin,
state.outTransitions.get(i).transition, state.outTransitions.get(i).destination);
newTR.add(tr);
state.outTransitions.get(i);
}
}
AUTState sTmp;
for (AUTTransition atPrev : state.outTransitions) {
transitions.remove(atPrev);
sTmp = states.get(atPrev.destination);
sTmp.removeInTransition(atPrev);
}
for (AUTTransition atPrev : state.inTransitions) {
transitions.remove(atPrev);
sTmp = states.get(atPrev.origin);
sTmp.removeOutTransition(atPrev);
}
for (AUTTransition tr : newTR) {
transitions.add(tr);
sTmp = states.get(tr.destination);
sTmp.addInTransition(tr);
sTmp = states.get(tr.origin);
sTmp.addOutTransition(tr);
}
}
for (AUTState state : oldStatesRemove) {
states.remove(state);
}
int cpt = 0;
cpt = 0;
for (AUTState state : states) {
if (cpt != state.id) {
// We now have to compact state ids
// We place the last state at index position
// We accordingly modify transitions
// Nothing to do if state index is already at last position
state.id = cpt;
for (AUTTransition atIn : state.inTransitions) {
atIn.destination = cpt;
}
for (AUTTransition atOut : state.outTransitions) {
atOut.origin = cpt;
}
}
cpt++;
}
cpt = 0;
/*for(AUTState state: states) {
TraceManager.addDev("" + cpt + ": state " + state.id + " / " + state.info + " / " + state);
cpt ++;
}*/
// Optimization: remove states representing empty transitions
ArrayList<AUTState> toBeRemoved = new ArrayList<>();
for (AUTState state : states) {
//TraceManager.addDev("Testing " + state.referenceObject.toString());
if (state.referenceObject instanceof AvatarTransition) {
AvatarTransition at = (AvatarTransition) state.referenceObject;
TraceManager.addDev("Found transition ID: " + at.getID());
if (at.isEmpty()) {
TraceManager.addDev("Found empty transition ID: " + at.getID());
if (!at.isGuarded()) {
TraceManager.addDev("Not guarded ID: " + at.getID());
if (at.getNexts().size() > 0) {
//if (state.outTransitions.size() == 1) {
// State can be removed
// We can update the transitions
// We assume that there is only one out transition
toBeRemoved.add(state);
ArrayList<AUTTransition> newTR = new ArrayList<>();
for (AUTTransition atPrev : state.inTransitions) {
for (int i = 0; i < state.outTransitions.size(); i++) {
AUTTransition tr = new AUTTransition(atPrev.origin,
state.outTransitions.get(i).transition, state.outTransitions.get(i).destination);
newTR.add(tr);
state.outTransitions.get(i);
}
}
AUTState sTmp;
for (AUTTransition atPrev : state.outTransitions) {
transitions.remove(atPrev);
sTmp = states.get(atPrev.destination);
sTmp.removeInTransition(atPrev);
}
for (AUTTransition atPrev : state.inTransitions) {
transitions.remove(atPrev);
sTmp = states.get(atPrev.origin);
sTmp.removeOutTransition(atPrev);
}
for (AUTTransition tr : newTR) {
transitions.add(tr);
sTmp = states.get(tr.destination);
sTmp.addInTransition(tr);
sTmp = states.get(tr.origin);
sTmp.addOutTransition(tr);
}
}
}
}
}
}
for (AUTState state : toBeRemoved) {
states.remove(state);
}
// We update all ids;
cpt = 0;
for (AUTState state : states) {
if (cpt != state.id) {
// We now have to compact state ids
// We place the last state at index position
// We accordingly modify transitions
// Nothing to do if state index is already at last position
state.id = cpt;
for (AUTTransition atIn : state.inTransitions) {
atIn.destination = cpt;
}
for (AUTTransition atOut : state.outTransitions) {
atOut.origin = cpt;
}
}
cpt++;
}
cpt = 0;
/*for(AUTState state: states) {
TraceManager.addDev("" + cpt + ": state " + state.id + " / " + state.info + " / " + state);
cpt ++;
}*/
// Rework Avatar Actions on Signals if multiple, synchros for the same AAOS
// Make the graph
graph = new AUTGraph(states, transitions);
}
@SuppressWarnings("unchecked")
private void addReferenceElement(AUTState _state, AvatarStateMachineElement _elt) {
ArrayList<AvatarStateMachineElement> refs = null;
if ( (_state.referenceObject == null) ) {
refs = new ArrayList<>();
_state.referenceObject = refs;
} else {
refs = (ArrayList<AvatarStateMachineElement> ) (_state.referenceObject);
@SuppressWarnings("unchecked")
private boolean hasReferenceObject(AUTState _state, AvatarStateMachineElement _elt) {
if (_state.referenceObject == null) {
return false;
}
ArrayList<AvatarStateMachineElement> refs = (ArrayList<AvatarStateMachineElement> )(_state.referenceObject);
return refs.contains(_elt);
}
@SuppressWarnings("unchecked")
private AvatarActionOnSignal getAvatarActionOnSignalInReferences(AUTState _state) {
if (_state.referenceObject == null) {
return null;
}
ArrayList<AvatarStateMachineElement> refs = (ArrayList<AvatarStateMachineElement> )(_state.referenceObject);
for(AvatarStateMachineElement elt: refs) {
if (elt instanceof AvatarActionOnSignal) {
return (AvatarActionOnSignal)elt;
}
}
return null;
}
Ludovic Apvrille
committed
@SuppressWarnings("unchecked")
private AvatarStateMachineElement getFirstReferenceObjectFromState(AUTState _state) {
if (_state.referenceObject == null) {
return null;
}
ArrayList<AvatarStateMachineElement> refs = (ArrayList<AvatarStateMachineElement> )(_state.referenceObject);
if (refs.size() > 0) {
return refs.get(0);
}
return null;
}
@SuppressWarnings("unchecked")
private AvatarStateMachineElement getLastReferenceObjectFromState(AUTState _state) {
if (_state.referenceObject == null) {
return null;
}
ArrayList<AvatarStateMachineElement> refs = (ArrayList<AvatarStateMachineElement> )(_state.referenceObject);
if (refs.size() > 0) {
return refs.get(refs.size()-1);
}
return null;
}
private AUTState makeCompactDependencyGraphForAvatarElement(AvatarBlock bl, AvatarStateMachineElement _elt,
AUTState _previousS, AvatarStateMachineElement _previousE,
ArrayList<AUTState> _states,
ArrayList<AUTTransition> _transitions, boolean withID,
AvatarTransition _previousAvatarTransition) {
if (_elt == null) {
return null;
}
// Already a state for a next?
AUTState stateN = null;
for (AUTState st : _states) {
if (hasReferenceObject(st, _elt)) {
stateN = st;
TraceManager.addDev("Found known state machine element for " + _elt.getExtendedName());
break;
}
}
//AUTState stateN = getFirstStateFor(eltN);
if (stateN != null) {
AUTTransition tr = new AUTTransition(_previousS.id, "", stateN.id);
_transitions.add(tr);
_previousS.addOutTransition(tr);
stateN.addInTransition(tr);
return stateN;
}
TraceManager.addDev("Handling sme: " + _elt.getName() + "/" + _elt.getExtendedName());
if ( (_elt instanceof AvatarTransition) && (_elt.getNext(0) instanceof AvatarActionOnSignal)) {
if (_elt.getNext(0) != null) {
return makeCompactDependencyGraphForAvatarElement(bl, _elt.getNext(0), _previousS, _elt, _states, _transitions, withID,
(AvatarTransition) _elt);
} else {
return _previousS;
}
}
if (_elt instanceof AvatarTransition) {
AvatarTransition at = (AvatarTransition) _elt;
if (at.isEmpty()) {
if (_elt.getNext(0) != null) {
return makeCompactDependencyGraphForAvatarElement(bl, _elt.getNext(0), _previousS, _elt, _states, _transitions, withID,
null);
} else {
return _previousS;
}
}
}
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
AUTState state = new AUTState(id);
_states.add(state);
if (_previousAvatarTransition != null) {
addReferenceElement(state, _previousAvatarTransition);
}
addReferenceElement(state, _elt);
if (withID) {
state.info = _elt.toStringExtendedID();
} else {
state.info = bl.getName() + " / " + _elt.getExtendedName();
}
if (_elt.referenceObject instanceof ElementWithNew) {
if (((ElementWithNew) (_elt.referenceObject)).isNew()) {
state.info += " (New)";
}
}
//putState(_elt, state);
//fromStates.put(state, _elt);
id++;
if (_previousE != null) {
AUTTransition tr = new AUTTransition(_previousS.id, "", state.id);
_transitions.add(tr);
_previousS.addOutTransition(tr);
state.addInTransition(tr);
} else {
state.isOrigin = true;
}
// Handling all nexts
//if (!(_elt instanceof AvatarActionOnSignal)) {
for (AvatarStateMachineElement eltN : _elt.getNexts()) {
makeCompactDependencyGraphForAvatarElement(bl, eltN, state, _elt, _states, _transitions, withID, null);
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
}
//}
return state;
}
@SuppressWarnings("unchecked")
public AvatarCompactDependencyGraph clone() {
AvatarCompactDependencyGraph adg = new AvatarCompactDependencyGraph();
AUTGraph g = graph.cloneMe();
adg.setGraph(g);
//HashMap<AvatarElement, ArrayList<AUTState>> newToStates = new HashMap<>();
//HashMap<AUTState, AvatarElement> newFromStates = new HashMap<>();
//adg.setRefs(newToStates, newFromStates);
// Filling states references
/*for (AvatarElement ae : toStates.keySet()) {
ArrayList<AUTState> list = toStates.get(ae);
ArrayList<AUTState> newList = new ArrayList<>();
for(AUTState oldS: list) {
// We must find the corresponding state in the new graph
AUTState newState = g.getState(oldS.id);
newList.add(newState);
newFromStates.put(newState, ae);
}
if (newList.size() > 0) {
newToStates.put(ae, newList);
}
}*/
return adg;
}
public AvatarCompactDependencyGraph reduceGraphBefore(ArrayList<AvatarElement> eltsOfInterest) {
AvatarCompactDependencyGraph result = clone();
/*TraceManager.addDev("Size of original graph: s" + graph.getNbOfStates() + " t" + graph.getNbOfTransitions());
TraceManager.addDev("Size of graph after clone: s" + result.graph.getNbOfStates() + " t" + result.graph.getNbOfTransitions());
TraceManager.addDev("old graph:\n" + graph.toStringAll() + "\n");
TraceManager.addDev("Cloned graph:\n" + result.graph.toStringAll() + "\n");*/
/*TraceManager.addDev("Size of original graph toStates:" + toStates.size());
TraceManager.addDev("Size of original graph fromStates:" + fromStates.size());
TraceManager.addDev("Size of cloned graph toStates:" + result.toStates.size());
TraceManager.addDev("Size of cloned graph fromStates:" + result.fromStates.size());*/
// For each state, we figure out whether if it is linked to go to the elt states
// or if they are after the elts.
HashSet<AUTState> beforeStates = new HashSet<>();
// We take each elt one after the other and we complete the after or before states
for (AvatarElement ae : eltsOfInterest) {
//TraceManager.addDev("Considering elt:" + ae.getName());
Object ref = ae.getReferenceObject();
if (ref != null) {
// Finding the state referencing o
AUTState stateOfInterest = null;
for (AUTState s : graph.getStates()) {
AvatarElement elt = (AvatarElement) s.referenceObject;
if (elt.getReferenceObject() == ref) {
stateOfInterest = s;
break;
}
}
if (stateOfInterest != null) {
//TraceManager.addDev("Has a state of interest: " + stateOfInterest.id);
for (AUTState state : graph.getStates()) {
if (state == stateOfInterest) {
beforeStates.add(result.graph.getState(state.id));
} else {
/*if (graph.hasPathFromTo(state.id, stateOfInterest.id)) {
beforeStates.add(result.graph.getState(state.id));
}*/
if (graph.canGoFromTo(state.id, stateOfInterest.id)) {
beforeStates.add(result.graph.getState(state.id));
}
}
}
}
}
}
TraceManager.addDev("Size of before: " + beforeStates.size());
// We now have to figure out which states have to be removed
ArrayList<AUTState> toRemoveStates = new ArrayList<>();
for (AUTState st : result.graph.getStates()) {
if (!beforeStates.contains(st)) {
toRemoveStates.add(st);
}
}
TraceManager.addDev("Size of remove: " + toRemoveStates.size());
result.graph.removeStates(toRemoveStates);
result.removeReferencesOf(toRemoveStates);
/*TraceManager.addDev("Size of graph after remove: s" + result.graph.getNbOfStates() + " t" + result.graph.getNbOfTransitions());
TraceManager.addDev("New graph:\n" +result.graph.toStringAll() + "\n");*/
// We have to update state references
return result;
}
public AvatarSpecification makeAvatarSpecification() {
AvatarSpecification newAvspec = new AvatarSpecification("from CDG", this);
// We look for start states: we create the block with attributes / signals etc.
// We take from the other avatar spec of relations
// We create all blocks
for (AUTState st : graph.getStates()) {
if (st.getNbInTransitions() == 0) {
// This is a start state
AvatarStateMachineElement asme = getFirstReferenceObjectFromState(st);
if ((asme != null) && (asme instanceof AvatarStartState)) {
AvatarStateMachineOwner asmo = asme.getOwner();
if ((asmo != null) && (asmo instanceof AvatarBlock)) {
AvatarBlock ab = (AvatarBlock) asmo;
AvatarBlock newBlock = new AvatarBlock(ab.getName(), newAvspec, this);
TraceManager.addDev("Creating new block: " + newBlock.getName() + " from block " + ab.getName());
newAvspec.addBlock(newBlock);
for (AvatarAttribute aa : ab.getAttributes()) {
AvatarAttribute newA = aa.advancedClone(newBlock);
newA.clearReferenceObject();
newA.setReferenceObject(this);
newBlock.addAttribute(newA);
TraceManager.addDev("\t Adding attribute: " + newA.getName());
}
for (AvatarMethod am : ab.getMethods()) {
AvatarMethod newAm = am.advancedClone(newBlock);
newAm.clearReferenceObject();
newAm.setReferenceObject(this);
newBlock.addMethod(newAm);
TraceManager.addDev("\t Adding method: " + newAm.getName());
}
for (AvatarSignal as : ab.getSignals()) {
AvatarSignal newAs = as.advancedClone(newBlock);
newAs.clearReferenceObject();
newAs.setReferenceObject(this);
newBlock.addSignal(newAs);
TraceManager.addDev("\t Adding signal: " + newAs.getName());
}
}
}
}
// We have to ensure the block hierarchy
for (AUTState st : graph.getStates()) {
if (st.getNbInTransitions() == 0) {
// This is a start state
AvatarStateMachineElement asme = getFirstReferenceObjectFromState(st);
if ((asme != null) && (asme instanceof AvatarStartState)) {
AvatarStateMachineOwner asmo = asme.getOwner();
if ((asmo != null) && (asmo instanceof AvatarBlock)) {
AvatarBlock ab = (AvatarBlock) asmo;
AvatarBlock father = ab.getFather();
if (father != null) {
AvatarBlock newSon = newAvspec.getBlockWithName(ab.getName());
AvatarBlock newFather = newAvspec.getBlockWithName(father.getName());
if (newSon != null && newFather != null) {
newSon.setFather(newFather);
}
}
}
}
}
}
// We make the relations between blocks
for (AUTState st : graph.getStates()) {
if (st.getNbInTransitions() == 0) {
// This is a start state
AvatarStateMachineElement asme = getFirstReferenceObjectFromState(st);
if ((asme != null) && (asme instanceof AvatarStartState)) {
AvatarStateMachineOwner asmo = asme.getOwner();
if ((asmo != null) && (asmo instanceof AvatarBlock)) {
AvatarBlock ab = (AvatarBlock) asmo;
AvatarBlock newBlock = newAvspec.getBlockWithName(ab.getName());
if (newBlock != null) {
// We add relations for which the two related blocks have been defined
AvatarSpecification oldSpec = asmo.getAvatarSpecification();
if (oldSpec != null) {
for (AvatarRelation ar: oldSpec.getRelations()) {
boolean b1 = ar.getBlock1().getName().compareTo(newBlock.getName()) == 0;
String nameOther = ar.getBlock2().getName();
//TraceManager.addDev("Looking for relation with blocks " + newBlock.getName() + " and " + nameOther);
AvatarBlock bOther = newAvspec.getBlockWithName(nameOther);
//TraceManager.addDev("Checking bOther");
if (bOther != null) {
HashMap<AvatarBlock, AvatarBlock> blMap = new HashMap<AvatarBlock, AvatarBlock>();
blMap.put(ar.getBlock1(), newBlock);
blMap.put(ar.getBlock2(), bOther);
AvatarRelation newAr = ar.advancedClone(blMap);
//TraceManager.addDev("Cloning the relation");
if (newAr != null) {
newAr.setReferenceObject(this);
//TraceManager.addDev("Non null relation");
newAvspec.addRelation(newAr);
} else {
TraceManager.addDev("Null clone");
}
// We make the state machines
for (AUTState st : graph.getStates()) {
if (st.getNbInTransitions() == 0) {
// This is a start state
AvatarStateMachineElement asme = getFirstReferenceObjectFromState(st);
if ((asme != null) && (asme instanceof AvatarStartState)) {
AvatarStateMachineOwner asmo = asme.getOwner();
if ((asmo != null) && (asmo instanceof AvatarBlock)) {
AvatarBlock ab = (AvatarBlock) asmo;
AvatarBlock newBlock = newAvspec.getBlockWithName(ab.getName());
if (newBlock != null) {
// We start from the start state to build the SMD
makeASMFromState(newBlock, st, null, null);
}
}
}
}
}
if (newAvspec.removeDuplicatedTransitions()) {
TraceManager.addDev("Useless transitions were removed");
} else {
TraceManager.addDev("No duplicate transitions");
}
return newAvspec;
public void makeASMFromState(AvatarBlock _block, AUTState _currentState, AvatarStateMachineElement _previousE, HashMap<AUTState,
AvatarStateMachineElement> elementM) {
// Handling referenced elements
AvatarStateMachineElement asme = getLastReferenceObjectFromState(_currentState);
if (asme == null) {
return;
}
AvatarStateMachine asm = _block.getStateMachine();
if (asm == null) {
return;
}
if (elementM == null) {
elementM = new HashMap<>();
}
if (_previousE != null) {
//TraceManager.addDev("Considering state " + _currentState.id + " with previous=" + _previousE.getName());
} else {
//TraceManager.addDev("Considering state " + _currentState.id + " with no previous");
}
if (_currentState.referenceObject == null) {
//TraceManager.addDev("Nb of referenced elements of this state: 0");
} else {
Object o = _currentState.referenceObject;
try {
ArrayList<AvatarStateMachineElement> refs = (ArrayList<AvatarStateMachineElement>)(_currentState.referenceObject);
for(AvatarStateMachineElement refAsme: refs) {
//TraceManager.addDev("\tref object:" + refAsme.getName() + " / " + refAsme.getClass().toString());
}
} catch (Exception e) {
TraceManager.addDev("No valid referenced object");
}
}
boolean mustLinkToPrevious = false;
AvatarStateMachineElement newE = null;
AvatarStateMachineElement newASME = elementM.get(_currentState);
if (asme instanceof AvatarStartState) {
AvatarStartState ass = new AvatarStartState(asme.getName() + ID++, this, _block);
asm.addElement(ass);
asm.setStartState(ass);
newE = ass;
} else if (asme instanceof AvatarState) {
if (newASME == null) {
AvatarState as = new AvatarState(asme.getName(), this, _block);
asm.addElement(as);
newE = as;
} else {
newE = newASME;
}
mustLinkToPrevious = true;
} else if (asme instanceof AvatarStopState) {
AvatarStopState ass = new AvatarStopState(asme.getName() + ID++, this, _block);
mustLinkToPrevious = true;
} else if (asme instanceof AvatarActionOnSignal) {
AvatarActionOnSignal aaos = ((AvatarActionOnSignal) asme).basicCloneMe(_block);
asm.addElement(aaos);
newE = aaos;
if (_previousE instanceof AvatarTransition) {
mustLinkToPrevious = true;
} else {
// Look at reference objects
AvatarStateMachineElement asmeFirst = getFirstReferenceObjectFromState(_currentState);
if (asmeFirst instanceof AvatarTransition) {
//TraceManager.addDev("Transition before aaos found in referenced objects");
AvatarTransition at = ((AvatarTransition) asmeFirst).cloneMe();
at.removeAllNexts();
at.setName("TransitionBeforeAAOS" + ID++);
at.setReferenceObject(this);
asm.addElement(at);
_previousE.addNext(at);
at.addNext(newE);
} else {
mustLinkToPrevious = true;
}
}
} else if (asme instanceof AvatarTransition) {
AvatarTransition at = ((AvatarTransition) asme).cloneMe();
at.removeAllNexts();
at.setName("TransitionInGraph" + ID++);
asme.setReferenceObject(this);
asm.addElement(at);
_previousE.addNext(at);
newE = at;
}
if (mustLinkToPrevious && _previousE != null && newE != null) {
if (_previousE instanceof AvatarTransition) {
_previousE.addNext(newE);
} else {
AvatarTransition at = new AvatarTransition(_block, "EmptyTransition" + ID++, this);
asm.addElement(at);
_previousE.addNext(at);
at.addNext(newE);
}
}
if (newE != null) {
elementM.put(_currentState, newE);
}
if ((newE != null) && (newASME == null)) {
// We have to handle the next states of currentState
for(AUTTransition tr: _currentState.outTransitions) {
if (!(tr.hasTag(AUTGraph.COMM_TAG))) {
AUTState st = graph.getState(tr.destination);
if (st != null) {
makeASMFromState(_block, st, newE, elementM);
}
public void removeReferencesOf(Collection<AUTState> _c) {
/*for (AUTState st : _c) {
fromStates.remove(st);
}
ArrayList<AvatarElement> toBeRemoved = new ArrayList<>();
for (AvatarElement ae : toStates.keySet()) {
if (_c.contains(toStates.get(ae))) {
toBeRemoved.add(ae);
}
}
for (AvatarElement ae : toBeRemoved) {
toStates.remove(ae);
}*/
}
}