Simplify Enterprise Architect code generation - code-generation

Using Enterprise Architect (version 7.5), I'm trying to refine the code generation for C#. To make an attribute with an initial value that is a string generate properly, the only way I've been successful is with the code below. Does anyone know if a simpler way to do this? It currently seems a little bloated.
%if attType=="string" and attInitial!=""%
= "
%elseIf attInitial!=""%
=
%endIf%
%attInitial ? value%
%if attType=="string" and attInitial!=""%
"
%endIf%

%if attInitial!=""%
=
%attInitial%
%endIf%
EA's attInitial corresponds to Property.default in UML.
default : String [0..1]
A string that is evaluated to give a default value for the attribute when an object of the owning class is instantiated. -- UML 2.2 infrastructure 10.2.5, emphasis added
So according to UML, if the type of the property is string, then the value attInitial should be an expression which evaluates to a string, not the content of a string literal.
If you do want it to be a non-UML-complient extension string literal value, you have to write something a bit more complicated that what you have done above to handle escaping.

Related

Extract Types/Classnames from flat Modelica code

I was wondering if there already exists a possibility to extract from flat Modelica code all variables AND their corresponding types (classnames respectively).
For example:
Given an extract from a flattened Modelica model:
constant Integer nSurfaces = 8;
constant Integer construction1.nLayers(min = 1.0) = 2 "Number of layers of the construction";
parameter Modelica.SIunits.Length construction1.thickness[construction1.nLayers]= {0.2, 0.1} "Thickness of each construction layer";
Here, the wanted output would be something like:
nSurfaces, Integer, constant;
construction1.nLayers, Integer, constant;
construction1.thickness[construction1.nLayers], Modelica.SIunits.Length, parameter
Ideally, for construction1.thickness there would be two lines (=number of construction1.nLayers).
I know, that it is possible to get a list of used variables from the dsin.txt, which is produced while translating a model. But until now I did not find an already existing way to get the corresponding types. And I really would like to avoid writing an own parser :-).
You could try to generate the file modelDescription.xml as defined by the FMI standard. It contains a ton of information and XML should be easier to parse, e.g. python has a couple of xml parsing/reading packages.
If you are using Dymola you just set the flag Advanced.FMI.GenerateModelDescriptionInterface2 = true to generate the model description file.
The second idea could be to let the compiler/tool parse the Modelica file for you as they need to do that anyway, try searching for AST (abstract syntax tree). In Dymola, this is available through the ModelManagement library, and also through the Python interface.
Third idea could be to use one of the Modelica parsers available, e.g. have a look at:
https://github.com/lbl-srg/modelica-json
https://hackage.haskell.org/package/modelicaparser
https://github.com/xie-dongping/modparc
https://github.com/pymoca/pymoca
https://github.com/pymola/pymola/tree/master/src/pymola
Fourth, if all that did not work, you still do not have to write a full parser, you could use ANTLR, then use an existing grammar file (look for e.g. modelica.g4).

handing string to MATLAB function in Simulink

In my Simulink Model I have a MATLAB function, this_function, which uses as one parameter the name of the Simulink Model, modelname. The name is defined in an extra parameter file with all other parameters needed. Loading the parameter file loads modelname into the workspace. The problem is now, that this_function can't access modelname in the workspace and therefore the model doesn't run.
I tried to use modelname as a constant input source for this_function, which I used as a work-around previously, but Simulink doesn't accept chars/strings as signals. Furthermore does setting modelname to global not work as well.
Is there a way to keep modelname in the parameter file instead of writing it directly into this_function?
Simulink does not support strings. Like, anywhere. It really sucks and I don't know why this limitation exists - it seems like a pretty horrible design choice to me.
I've found the following workarounds for this limitation:
Dirty Casting
Let
function yourFun(num_param1, num_param2, ..., str_param);
be your MATLAB function inside the Simulink block, with str_param the parameter you want to be a string, and num_param[X] any other parameters. Then pass the string signal to the function like so:
yourFun(3, [4 5], ..., 'the_string'+0);
Note that '+0' at the end; that is shorthand for casting a string to an array of integers, corresponding to the ASCII codes of each character in the string. Then, inside the function, you could get the string back by doing the inverse:
model = char(str_param);
but usually that results in problems later on (strcmp not supported, upper/lower not supported, etc.). So, you could do string comparisons (and similar operations) in a similar fashion:
isequal(str_param, 'comparison'+0);
This has all the benefits of strings, without actually using strings.
Of course, the '+0' trick can be used inside constant blocks as well, model callbacks to convert workspace variables on preLoad, etc.
Note that support for variable size arrays must be enabled in the MATLAB function.
Fixed Option Set
Instead of passing in a string, you can pass a numeric scalar, which corresponds to a selection in a list of fixed, hardcoded options:
function yourFun(..., option)
...
switch (option)
case 1
model = 'model_idealised';
case 2
model = 'model_with_drag';
case 3
model = 'model_fullscale';
otherwise
error('Invalid option.');
end
...
end
Both alternatives are not ideal, both are contrived, and both are prone to error and/or have reusability and scalability problems. It's pretty hopeless.
Simulink should start supporting strings natively, I mean, come on.

Structures or javascript/json objects in progress ABL?

We're migrating to 11.6 and I think it's a great moment to rethink old habits and improve some concepts.
One of these things is the way we've been dealing with parameter definitions in functions and procedures.
Often times we have procedures and functions that need a lot of parameters, either inputs or outputs. Personally, for readability and maintainability reasons, I don't like to have methods with too many parameters explicitly declared.
In order to avoid this problem and still allow a large number of parameters, we've manually implemented a key-value pair approach with a single parameter.
But there are some drawbacks with this approach:
It's not possible to tell which parameters are needed just by inspecting
the method signature.
You'll always need some boilerplate code, like methods for pushing and pulling values.
So with that said, I would like to hear some others' thoughts.
Have you ever implemented something similar?
Is there something that could work as a javascript/json object in ABL?
Current implementation.
DEFINE VARIABLE param as CHARACTER NO-UNDO.
addValue('id', '1', param).
addValue('date', STRING(TODAY), param).
RUN internalProc (INPUT param).
Desired implementation
param.id = 1
param.date = TODAY
RUN internalProc (INPUT param)
Since you are mentioning 11.6, why not use a real class based object (available since 10.1A).
yourpackage\yourparameter.cls:
CLASS yourpackage.yourclass:
DEFINE PUBLIC PROPERTY date AS DATE NO-UNDO
GET.
SET.
DEFINE PUBLIC PROPERTY id AS INTEGER NO-UNDO
GET.
SET.
CONSTRUCTOR PUBLIC yourclass ():
SUPER ().
END CONSTRUCTOR.
CONSTRUCTOR PUBLIC yourclass (pid AS INTEGER, pdate AS DATE):
SUPER ().
ASSIGN THIS-OBJECT:id = pid
THIS-OBJECT:date = DATE .
END CONSTRUCTOR.
END CLASS.
and the internal procedure:
DEFINE INPUT PARAMETER poParameter AS yourpackage.yourclass NO-UNDO .
and the caller:
DEFINE VARIABLE o AS yourpackage.yourclass NO-UNDO.
o = NEW yourpackage.yourclass().
o:id = 42.
o:date = TODAY.
RUN internalProc (o) .
alternative caller:
RUN internalProc (NEW yourpackage.yourclass (1, TODAY)) .
The ABL provides full OO capabilities from 10.1A on and that can be mixed nicely with procedural code. And parameter objects (structs) is a great way to get started with a few inital classes in legacy code.

Specification and correct use of (boolean) URI matrix parameters (and making them optional when using CXF/JAXB)?

I was wondering if the "proper" use of URI/URL matrix parameters was ever defined in a specification, such as an RFC or a W3 recommendation?
In particular, I just joined a project where we use matrix parameters and a Java framework to implement a REST service. One of the matrix parameters we have for our REST service is a boolean one, much like ;sortByDate=true
What bugged me about this one is that the Java framework we use apparently insists that boolean parameters are always passed in (i.e. you cannot make them optional/omit them; probably because they are converted to Java boolean type). I think that's a bit odd...
I have to doublecheck what framework we use tomorrow (I think it is JAXB), but in the meantime I wondered if matrix parameters were defined in an official specification somewhere, and if such a specification made any mention of boolean parameters.
So far I found a hint (though no mention of boolean matrix parameters) in Appendix B 2.2 of the W3's "HTML 4.01 Specification":
We recommend that HTTP server implementors, and in particular, CGI implementors support the use of ";" in place of "&" to save authors the trouble of escaping "&" characters in this manner.
And the "Web Application Description Language" specification specifies:
Boolean matrix parameters are represented as: ';' name when value is true and are omitted from identifier when value is false
What I haven't found is "the" specification for matrix parameters. Is there any? Does it mention how boolean matrix parameters should be used? If not, is there an established best practice?
And, as a bonus question: can you omit boolean URL matrix parameters when using CXF (JAXB), or do you always have to specify them?
Cheers! :)
Update: We're using CXF (which apparently uses JAXB under the hood...)
RFC3986 describes Matrix Parameters without explicitly naming them. Quoting https://www.rfc-editor.org/rfc/rfc3986#section-3.3:
For example, the semicolon (";") and equals ("=") reserved characters are often used to delimit parameters and parameter values applicable to that segment. The comma (",") reserved character is often used for similar purposes. For example, one URI producer might use a segment such as "name;v=1.1" to indicate a reference to version 1.1 of "name", whereas another might use a segment such as "name,1.1" to indicate the same.
I hope this helps.
I think that this answer does a good job of explaining the purpose of matrix parameters:
https://stackoverflow.com/a/5602678
You can use the Boolean wrapper class to support an optional boolean value. The values true and false will be mapped to the correct boolean values.
#MatrixParam("sortByDate") Boolean sortByDate
It will be null if the param is not present. Note that JAXB doesn't apply when dealing with JAX-RS parameters.

Why does Scala choose to have the types after the variable names?

In Scala variables are declared like:
var stockPrice: Double = 100.
Where the type (Double) follows the identifier (stockPrice). Traditionally in imperative languages such as C, Java, C#, the type name precedes the identifier.
double stock_price = 100.0;
Is it purely a matter of taste, or does having the type name in the end help the compiler in any way? Go also has the same style.
Kevin's got it right. The main observation is that the "type name" syntax works great as long as types are short keywords such as int or float:
int x = 1
float d = 0.0
For the price of one you get two pieces of information: "A new definition starts here", and "here's the (result) type of the definition". But we are way past the area of simple primitive types nowadays. If you write
HashMap<Shape, Pair<String, String>> shapeInfo = makeInfo()
the most important part of what you define (the name) is buried behind the type expression. Compare with
val shapeInfo: HashMap[Shape, (String, String)] = makeInfo()
It says clearly
We define a value here, not a variable or method (val)
The name of the thing we define is shapeInfo
If you care about it, here's the type (HashMap[...])
As well as supporting type inference, this has an ergonomic benefit too.
For any given variable name + type, chances are that the name is the more important piece of information. Moving it to the left makes it more prominent, and the code more readable once you're accustomed to the style.
Other ergonomic benefits:
With val, var or def before member names, instead of their type, they all neatly line up in a column.
If you change just the type of a member, or drop it entirely in favour of inference, then a fine-grained diff tool will clearly show that the name is unaltered
Likewise, changing between a val/var/def is very clear in diffs
inference should be considered default behaviour in Scala, you only need type specifications in certain specific scenarios, even then it's mostly done for the compiler. So putting them at the very start of a declaration emphasises the wrong thing.
"name: Type" instead of "Type name" more closely matches the way most programmers will actually think about a declaration, it's more natural.
The differing C/C++ and Java conventions for pointers and arrays (i.e * being a prefix on the following name and not a suffix on the preceeding type in C/C++, or [] being a valid suffix on both names and types in Java) are still confusing to newcomers or language converts, and cause some very real errors when declaring multiple variables on a single line. Scala leaves no room for doubt and confusion here.
It's afterwards so that it can be removed for type inference:
var stockPrice: Double = 100.0
var stockPrice = 100.0
However, it is not true that imperative languages traditionally have types first. For example, Pascal doesn't.
Now, C does it, and C++, Java and C# are based on C's syntax, so naturally they do it that way too, but that has absolutely nothing to do with imperative languages.
It should be noted that even C doesn't "traditionally" define the type before the variable name, but indeed allows the declarations to be interleaved.
int foo[];
where the type for foo is declared both before and after it, lexically.
Beyond that, I'm guessing this is a distinction without a difference. The compiler developers certainly couldn't care one way or another.