Newer
Older
/* 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;
/**
* AvatarLibraryFunction is used to represent a library function that can be further used in state machine diagrams.
* <p>
* A library function is defined by:
* <ul>
* <li>a name</li>
* <li>a set of {@link AvatarAttribute} representing the parameters of the function,</li>
* <li>a set of {@link AvatarAttribute} for local usage,</li>
* <li>a set of {@link AvatarSignal} that are used to communicate,</li>
* <li>a set of {@link AvatarAttribute} that will contain the return values of the function and</li>
* <li>an {@link AvatarStateMachine} that describes the content of the function.</li>
* </ul>
*
* @version 1.0 04.07.2016
* @author Florian LUGOU
public class AvatarLibraryFunction extends AvatarElement implements AvatarTranslator, AvatarStateMachineOwner {
/**
* The list of parameters of the function. Their values should never be reaffected.
*
* <p>Note that these are only placeholders and should not be used outside this class.</p>
*/
/**
* The list of variables local to the function.
*
* <p>Note that these are only placeholders and should not be used outside this class.</p>
*/
/**
* The list of signals used by the function.
*
* <p>Note that these are only placeholders and should not be used outside this class.</p>
*/
/**
* The list of attribute that will hold the return values of the function. These shouldn't be elements of {@link AvatarLibraryFunction#attributes} or {@link AvatarLibraryFunction#parameters}.
*
* <p>Note that these are only placeholders and should not be used outside this class.</p>
*/
/**
* The list of methods that can be used by the function.
*
*/
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
* The state machine describing the behaviour of the function.
*/
private AvatarStateMachine asm;
/**
* The specification that this library function is part of.
*/
private AvatarSpecification avspec;
/**
* Counter of invocations of this library function.
*/
private int counter;
/**
* Basic constructor of the function function.
*
* @param name
* The name that identifies this function.
* @param avspec
* The specification this function is part of.
* @param referenceObject
* The graphical element that this function is related to.
*/
public AvatarLibraryFunction (String name, AvatarSpecification avspec, Object referenceObject) {
super(name, referenceObject);
this.avspec = avspec;
this.parameters = new LinkedList<AvatarAttribute> ();
this.signals = new LinkedList<AvatarSignal> ();
this.returnAttributes = new LinkedList<AvatarAttribute> ();
this.attributes = new LinkedList<AvatarAttribute> ();
this.methods = new LinkedList<AvatarMethod> ();
this.asm = new AvatarStateMachine (this, "statemachineoffunction__" + name, referenceObject);
this.counter = 0;
}
/**
* @return : a unique counter for library function call.
*/
public int getCounter()
{
return this.counter++;
}
/**
* Set counter for this library function.
* @param counter : counter to set
*/
public void setCounter(int counter)
{
this.counter = counter;
}
@Override
public AvatarSpecification getAvatarSpecification () {
return this.avspec;
}
/**
* Return the list of parameters of the function.
*
* @return The list of parameters.
*/
return this.parameters;
}
/**
* Add a parameter for this function.
*
* @param attr The parameter to add.
*/
public void addParameter (AvatarAttribute attr) {
this.parameters.add (attr);
}
/**
* Return the list of signals.
*
* @return The list of signals.
*/
return this.signals;
}
/**
* Add a signal.
*
* @param signal The signal to add.
*/
public void addSignal (AvatarSignal signal) {
this.signals.add (signal);
}
@Override
public AvatarSignal getAvatarSignalWithName (String signalName) {
for (AvatarSignal signal: this.signals)
if (signal.getName ().equals (signalName))
return signal;
return null;
}
/**
* Return the list of return values.
*
* @return The list of return values.
*/
return this.returnAttributes;
}
/**
* Add a return value.
*
* @param returnAttribute
* The return value to add.
*/
public void addReturnAttribute (AvatarAttribute returnAttribute) {
this.returnAttributes.add (returnAttribute);
}
/**
* Return the list of attributes local to the function.
*
* @return The list of local attributes.
*/
return this.attributes;
}
@Override
public List<AvatarAttribute> getAttributes () {
List<AvatarAttribute> result = new LinkedList<AvatarAttribute> ();
for (AvatarAttribute attr: this.attributes)
result.add (attr);
for (AvatarAttribute attr: this.returnAttributes)
result.add (attr);
for (AvatarAttribute attr: this.parameters)
result.add (attr);
return result;
}
@Override
public void addAttribute (AvatarAttribute attribute) {
this.attributes.add (attribute);
}
/**
* Return the list of methods.
*
* @return The list of methods used by this function.
*/
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
return this.methods;
}
@Override
public AvatarMethod getAvatarMethodWithName (String methodName) {
for (AvatarMethod method: this.methods)
if (method.getName ().equals (methodName))
return method;
return null;
}
/**
* Add a method.
*
* @param method
* The method to add to this function.
*/
public void addMethod (AvatarMethod method) {
this.methods.add (method);
}
@Override
public AvatarStateMachine getStateMachine () {
return this.asm;
}
@Override
public AvatarAttribute getAvatarAttributeWithName (String name) {
for (AvatarAttribute attr: this.parameters)
if (attr.getName ().equals (name))
return attr;
for (AvatarAttribute attr: this.attributes)
if (attr.getName ().equals (name))
return attr;
for (AvatarAttribute attr: this.returnAttributes)
if (attr.getName ().equals (name))
return attr;
return null;
}
public AvatarAttribute getOriginalAvatarAttributeWithName(String attributeName) {
return getAvatarAttributeWithName(attributeName);
}
/**
* Add all of the temporary attributes used by the function to the block.
*
* @param block
* The block to which the attributes should be added.
* @param mapping
* A mapping from placeholders to attributes of the block.
*/
public void addAttributesToBlock (AvatarBlock block, Map<AvatarAttribute, AvatarAttribute> mapping) {
for (AvatarAttribute attribute: this.attributes) {
// TODO: We should use different attributes for different library function call
String name = this.name + "__" + attribute.getName ();
AvatarAttribute attr = block.getAvatarAttributeWithName (name);
if (attr == null) {
attr = new AvatarAttribute (name, attribute.getType (), block, block.getReferenceObject ());
if (attribute.getInitialValue() != null) {
attr.setInitialValue(attribute.getInitialValue());
}
block.addAttribute (attr);
}
mapping.put (attribute, attr);
}
}
/**
* Add mappings from parameters and return values placeholders to "real" attributes.
*
* @param mapping
* A mapping from placeholders to attributes of the block.
* @param parameters
* A list of the attributes that were passed as parameters.
* @param returnAttributes
* A list of the attributes that should receive return values.
*/
public void addAttributesToMapping( Map<AvatarAttribute, AvatarAttribute> mapping, List<AvatarAttribute> parameters, List<AvatarAttribute> returnAttributes) {
Iterator<AvatarAttribute> placeholders = this.parameters.iterator ();
for (AvatarAttribute attr: parameters)
mapping.put (placeholders.next (), attr);
placeholders = this.returnAttributes.iterator ();
for (AvatarAttribute attr: returnAttributes)
mapping.put (placeholders.next (), attr);
}
/**
* Add mappings from signals placeholders to "real" signals.
*
* @param mapping
* A mapping from placeholders to signals of the block.
* @param signals
* A list of the attributes that were passed as parameters.
*/
public void addSignalsToMapping( Map<AvatarSignal, AvatarSignal> mapping, List<AvatarSignal> signals) {
Iterator<AvatarSignal> placeholders = this.signals.iterator ();
for (AvatarSignal signal: signals)
mapping.put (placeholders.next (), signal);
}
/**
* Inner class used to pass arguments for the translation process.
*/
private class TranslatorArgument {
/**
* A mapping from placeholders to attributes of the block.
*/
public Map<AvatarAttribute, AvatarAttribute> placeholdersMapping;
/**
* A mapping from placeholders to signals of the block.
*/
/**
* The previous element of the state machine being created.
*/
public AvatarStateMachineElement previousElement;
/**
* The last element of the state machine being created.
*/
public AvatarStateMachineElement lastElement;
/**
* A mapping from placeholder state machine elements to "real" elements.
*/
public Map<AvatarStateMachineElement, AvatarStateMachineElement> elementsMapping;
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
424
425
426
427
/**
* The block the function call belongs to.
*/
public AvatarBlock block;
/**
* The reference object associated to the function call being translated.
*/
public Object referenceObject;
/**
* The counter for the library function call.
*/
public int counter;
/**
* Basic constructor.
*
* @param placeholdersMapping
* A mapping from placeholders to attributes of the block.
* @param signalsMapping
* A mapping from placeholders to signals of the block.
* @param previousElement
* The previous element of the state machine being created.
* @param lastElement
* The last element of the state machine being created.
* @param elementsMapping
* A mapping from placeholder state machine elements to <i>real</i> elements.
* @param block
* The block the function call belongs to.
* @param referenceObject
* The reference object associated to the function call being translated.
* @param counter
* The counter for the library function call.
*/
public TranslatorArgument( Map<AvatarAttribute, AvatarAttribute> placeholdersMapping, Map<AvatarSignal, AvatarSignal> signalsMapping, AvatarStateMachineElement previousElement, AvatarStateMachineElement lastElement, Map<AvatarStateMachineElement, AvatarStateMachineElement> elementsMapping, AvatarBlock block, Object referenceObject, int counter) {
this.placeholdersMapping = placeholdersMapping;
this.signalsMapping = signalsMapping;
this.previousElement = previousElement;
this.lastElement = lastElement;
this.elementsMapping = elementsMapping;
this.block = block;
this.referenceObject = referenceObject;
this.counter = counter;
}
}
/**
* Translate the state machine described by this function in the context of a particular block.
*
* @param placeholdersMapping
* A mapping from placeholders to attributes of the block.
* @param signalsMapping
* A mapping from placeholders to signals of the block.
* @param firstElement
* The first element of the state machine to be created.
* @param block
* The block the function call belongs to.
* @param referenceObject
* The reference object associated to the function call being translated.
* @param counter
* The counter of this library function
*
* @return The last element of the state machine created.
*/
public AvatarState translateASMWithMapping( Map<AvatarAttribute, AvatarAttribute> placeholdersMapping, Map<AvatarSignal, AvatarSignal> signalsMapping,
AvatarStateMachineElement firstElement, AvatarBlock block, Object referenceObject, int counter) {
/* Create the last state */
AvatarState lastState = new AvatarState ("exit_" + this.name + "_" + counter, referenceObject, block);
block.getStateMachine().addElement(lastState);
/* Create the argument object that will be passed to translation functions */
Object arg = new TranslatorArgument (
placeholdersMapping,
signalsMapping,
firstElement,
lastState,
new LinkedHashMap<AvatarStateMachineElement, AvatarStateMachineElement> (),
block,
referenceObject,
counter);
/* Translate the state machine, starting from the first state */
this.asm.getStartState ().translate (this, arg);
return lastState;
}
/**
* Translate elements that follow the current state.
*
* @param asme
* The newly created element.
* @param placeholder
* The state machine element that has just be translated.
* @param arg
* The object containing the arguments to pass to the translation functions.
*/
private void translateNext (AvatarStateMachineElement asme, AvatarStateMachineElement placeholder, TranslatorArgument arg) {
//TraceManager.addDev("TRANSLATION of:" + asme.getExtendedName());
arg.previousElement.addNext (asme);
arg.elementsMapping.put (placeholder, asme);
// Must be added to the state machine as well?
arg.block.getStateMachine().addElement(asme);
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
/* If there is no next element, consider this as an end state */
if (placeholder.nbOfNexts () == 0) {
asme.addNext (arg.lastElement);
return;
}
/* Loop through the next elements */
for (AvatarStateMachineElement next: placeholder.getNexts ()) {
AvatarStateMachineElement existingNext = arg.elementsMapping.get (next);
/* Check if next element has already been translated */
if (existingNext != null)
asme.addNext (existingNext);
else {
arg.previousElement = asme;
next.translate (this, arg);
}
}
}
@Override
public void translateTimerOperator (AvatarTimerOperator _asme, Object _arg) {
TranslatorArgument arg = (TranslatorArgument) _arg;
AvatarTimerOperator asme;
if (_asme instanceof AvatarSetTimer) {
// TODO: isn't the name used for the timer ?
asme = new AvatarSetTimer (this.name + "_" + arg.counter + "__" + _asme.getName (), arg.referenceObject, _asme.getOwner());
// TODO: should probably replace attributes too, right ?
((AvatarSetTimer) asme).setTimerValue (((AvatarSetTimer) _asme).getTimerValue ());
} else if (_asme instanceof AvatarResetTimer)
asme = new AvatarResetTimer (this.name + "_" + arg.counter + "__" + _asme.getName (), arg.referenceObject, _asme.getOwner());
else if (_asme instanceof AvatarExpireTimer)
asme = new AvatarExpireTimer (this.name + "_" + arg.counter + "__" + _asme.getName (), arg.referenceObject, _asme.getOwner());
else
/* !!! should not happen */
return;
asme.setTimer (arg.placeholdersMapping.get (_asme.getTimer ()));
this.translateNext (asme, _asme, arg);
}
@Override
public void translateActionOnSignal (AvatarActionOnSignal _asme, Object _arg) {
TranslatorArgument arg = (TranslatorArgument) _arg;
AvatarActionOnSignal asme = new AvatarActionOnSignal (this.name + "_" + arg.counter + "__" + _asme.getName (),
arg.signalsMapping.get (_asme.getSignal ()), arg.referenceObject, _asme.getOwner());
for (String s: _asme.getValues ()) {
AvatarAttribute attr = this.getAvatarAttributeWithName (s);
if (attr == null)
asme.addValue (s);
else
asme.addValue (arg.placeholdersMapping.get (attr).getName ());
}
this.translateNext (asme, _asme, arg);
}
@Override
public void translateTransition (AvatarTransition _asme, Object _arg) {
TranslatorArgument arg = (TranslatorArgument) _arg;
//printCorrespondance(_arg);
AvatarTransition asme = new AvatarTransition (arg.block, this.name + "_" + arg.counter + "__" + _asme.getName (), arg.referenceObject);
AvatarGuard guard = _asme.getGuard ().clone ();
guard.replaceAttributes (arg.placeholdersMapping);
asme.setGuard (guard, _asme.getOriginalGuard());
//TraceManager.addDev("minD:" + _asme.getMinDelay() + " in block " + arg.block.getName());
String minD = replaceAttributesInExpr(_asme.getMinDelay(), _arg);
//TraceManager.addDev("minD:" + minD);
//TraceManager.addDev("maxD:" + _asme.getMaxDelay() + " in block " + arg.block.getName());
String maxD = replaceAttributesInExpr(_asme.getMaxDelay(), _arg);
//TraceManager.addDev("maxD:" + maxD);
asme.setDelays(minD, maxD, _asme.getOriginalMinDelay(), _asme.getOriginalMaxDelay());
asme.setComputes (replaceAttributesInExpr(_asme.getMinCompute (), _arg),
replaceAttributesInExpr(_asme.getMaxCompute (), _arg));
for (AvatarAction _action: _asme.getActions ()) {
AvatarAction action = _action.clone ();
//TraceManager.addDev("\n*** Action BEFORE replace:" + action.toString() + " " + action.getClass().getCanonicalName());
action.replaceAttributes (arg.placeholdersMapping);
//TraceManager.addDev("Action AFTER replace:" + action.getName() + "\n");
asme.addAction (action, _asme.getOriginalAction(cpt));
cpt ++;
}
this.translateNext (asme, _asme, arg);
}
@Override
public void translateStartState (AvatarStartState _asme, Object _arg) {
TranslatorArgument arg = (TranslatorArgument) _arg;
_asme.getNext (0).translate (this, arg);
}
@Override
public void translateState (AvatarState _asme, Object _arg) {
TranslatorArgument arg = (TranslatorArgument) _arg;
/* Mark state as non checkable as it is up to now impossible to display the
* reachability of state in a function for a particular invocation of this
* function.
*/
AvatarState asme = new AvatarState (this.name + "_" + arg.counter + "__" + _asme.getName (), arg.referenceObject, _asme.getOwner(), false,
false);
asme.setHidden (true);
asme.addEntryCode (_asme.getEntryCode ());
this.translateNext (asme, _asme, arg);
}
@Override
public void translateRandom (AvatarRandom _asme, Object _arg) {
TranslatorArgument arg = (TranslatorArgument) _arg;
AvatarRandom asme = new AvatarRandom (this.name + "_" + arg.counter + "__" + _asme.getName (), arg.referenceObject, _asme.getOwner());
asme.setValues (replaceAttributesInExpr(_asme.getMinValue (), _arg), replaceAttributesInExpr(_asme.getMaxValue (), _arg));
asme.setFunctionId (_asme.getFunctionId ());

Ludovic Apvrille
committed
asme.setExtraAttribute1(_asme.getExtraAttribute1());
asme.setExtraAttribute2(_asme.getExtraAttribute2());
asme.setVariable (arg.placeholdersMapping.get (this.getAvatarAttributeWithName (_asme.getVariable ())).getName ());
this.translateNext (asme, _asme, arg);
}
@Override
public void translateEmpty (AvatarEmpty _asme, Object _arg) {
TranslatorArgument arg = (TranslatorArgument) _arg;
this.translateNext (_asme, _asme, arg);
}
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
@Override
public void translateStopState (AvatarStopState _asme, Object _arg) {
TranslatorArgument arg = (TranslatorArgument) _arg;
arg.previousElement.addNext (arg.lastElement);
}
@Override
public void translateLibraryFunctionCall (AvatarLibraryFunctionCall _asme, Object _arg) {
TranslatorArgument arg = (TranslatorArgument) _arg;
AvatarLibraryFunctionCall asme = new AvatarLibraryFunctionCall (this.name + "_" + arg.counter + "__" + _asme.getName (), _asme.getLibraryFunction (), arg.referenceObject);
for (AvatarAttribute attr: _asme.getParameters ())
asme.addParameter (arg.placeholdersMapping.get (attr));
for (AvatarSignal signal: _asme.getSignals ())
asme.addSignal (arg.signalsMapping.get (signal));
for (AvatarAttribute attr: _asme.getReturnAttributes ())
asme.addReturnAttribute (arg.placeholdersMapping.get (attr));
this.translateNext (asme, _asme, arg);
}
@Override
public AvatarLibraryFunction advancedClone(AvatarSpecification avspec) {
AvatarLibraryFunction result = new AvatarLibraryFunction(this.name, avspec, this.referenceObject);
this.cloneLinkToReferenceObjects (result);
result.setCounter(this.counter);
for (AvatarAttribute aa: this.parameters)
result.addParameter(aa.advancedClone(result));
for (AvatarSignal sig: this.signals)
result.addSignal(sig.advancedClone(result));
for (AvatarAttribute aa: this.returnAttributes)
result.addReturnAttribute(aa.advancedClone(result));
for (AvatarAttribute aa: this.attributes)
result.addAttribute(aa.advancedClone(result));
for (AvatarMethod met: this.methods)
result.addMethod(met.advancedClone(result));
this.asm.advancedClone(result.getStateMachine(), result);
return result;
}
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
private String replaceAttributesInExpr(String expr, Object _arg) {
if (expr == null) {
return null;
}
expr = expr.trim();
if (expr.length() == 0) {
return expr;
}
TranslatorArgument arg = (TranslatorArgument) _arg;
AvatarTerm term = AvatarTerm.createFromString(arg.block, expr);
if (term == null) {
TraceManager.addDev("NULL term in /" + expr + "/ of block /" + arg.block.getName() + "/");
}
if (term instanceof AvatarAttribute) {
AvatarAttribute ret = arg.placeholdersMapping.get(term);
if (ret == null) {
for(AvatarAttribute atbis: arg.placeholdersMapping.keySet()) {
if (atbis.getName().equals(term.getName())) {
ret = arg.placeholdersMapping.get(atbis);
break;
}
}
if (ret == null) {
TraceManager.addDev("NULL correspondance");
return expr;
}
}
TraceManager.addDev("Ok correspondance");
return ret.getName();
}
term.replaceAttributes(arg.placeholdersMapping);
return term.toString();
}
private void printCorrespondance(Object _arg) {
TranslatorArgument arg = (TranslatorArgument) _arg;
for(AvatarAttribute elt1: arg.placeholdersMapping.keySet()) {
AvatarAttribute elt2 = arg.placeholdersMapping.get(elt1);
TraceManager.addDev("Correspondance " + elt1 + " --> " + elt2);
}
}