![]() |
Using local name with Merl |
Post Reply
|
| Author | |
MerlUser
Member
Joined: 13.Jul.2010 Location: Germany Posts: 3 |
Quote Reply
Topic: Using local name with MerlPosted: 13.Jul.2010 at 18:17 |
|
How can i access the "local name" of a property? With the following code, I was able to make a list of properties with the type-name and its value, but in my case there are more than one property of the same type (but with different local names):
foreach .() {
'<' type%var do :() { ' ' type%var '="' id%xml '"' } ' />' newline } Here is an example output:
<state typeA="a" typeB="b" typeA="c" />
In XML-files it is not allowed to define different attributes with the same name. The local names of the properties in the metaedit object have already different names. So i want to use these local names of the metaedit object properties, but how can I use these local names from merl?
|
|
![]() |
|
stevek
MetaCase
Joined: 11.Mar.2008 Posts: 160 |
Quote Reply
Posted: 16.Jul.2010 at 02:20 |
|
It looks like you're trying to write a generic generator, i.e. one that can be used for any metamodel. They are actually rather hard, because you need reflection capabilities to read the metamodel information. A normal generator only needs to read the model information, and the generator itself contains direct references to particular types, local names etc.
If you really want your model transformed in a watertight way into XML, I'd suggest you look instead at MetaEdit+'s XML export. That already takes care of the many XML challenges such as object references, circularity, illegal characters etc. that you will face after overcoming this hurdle. It should be easy enough to massage the XML export format into the format you want, e.g. with XSLT. On the other hand, if this was just a quick example to play around with MERL, I'd suggest you look at a different task. For a generator to add value, it has to understand the different semantics of each piece of information in the models, rather than just treating them all the same. For instance, normally one property will go to make up the name of a file, another to become a function name, still another will become part of a condition. Each property will thus be named explicitly in the generator, rather than iterating over all of them with "do :()". If you really want the local names, MERL doesn't have direct access to them: it's designed to operate on models, not metamodels. You can however get them by saving the metamodel into text with: internal 'document:into: "' type '" metamodels' execute and reading that into a variable with: variable 'metamodel' write filename 'metamodels' sep type sep 'metamodel.txt' read close You can then iterate over the lines of that variable with "do $metamodel" - you'll have to do a little processing, but you can look at the "Reverse engineer Java" generator in UML's Class Diagram for hints. Of course, if you're only going to do this for one metamodel, there's no need to write a metaprogram that could do it for all metamodels. Just stick direct references to the local names into the generator: it's almost certainly faster in the long run, and also gives you a measure of indirection to cope with name changes in the future (e.g. if you want to keep the same XML schema but make the user-visible names in the modeling tool more user-friendly). do .State { '<state name="' :Name%xml '" description="' :Description%xml '/>' newline } Note how that is already simpler than what you have above, and easier to read. I'm a big fan of meta solutions, but even I have to admit that in some cases a simple solution, even one with some apparent duplication, may be best! |
|
![]() |
|
MerlUser
Member
Joined: 13.Jul.2010 Location: Germany Posts: 3 |
Quote Reply
Posted: 19.Jul.2010 at 13:26 |
|
Thanks a lot for your detailed reply.
Yes, I would like to write a generic generator, because my meta-model contains a specific relation on which several different objects are connected. It would be nice to iterate over these objects and its properties in a generic way to write all the data to a XML file. It would be very nice to have access also to the local name. The interpreter of merl is already able to iterate over all properties and gives access to "type" and "value". I am thinking of a key word like "localname" for having access to the local name of a property. In my opinion it would be easy for you to add this to the merl-language, isn't it? |
|
![]() |
|
stevek
MetaCase
Joined: 11.Mar.2008 Posts: 160 |
Quote Reply
Posted: 22.Jul.2010 at 14:52 |
|
It actually wouldn't be trivial to add local name: inside do :(), the elements we are iterating over are properties. A property doesn't know its local name, because the same property can be shared between several objects, maybe of different types or in different slots, each with its own local name.
While we can work around that, adding "localName" opens up a large number of other new commands that would then be needed, e.g. to find the datatype of the property type to know whether to recurse again with do :() over a contained object or collection; to find the supertype of the current type; to find the kind of List widget a property type uses and its legal values etc. Essentially, MERL is a language for navigating models, and doesn't have commands to navigate metamodels. Adding those commands would increase the size of MERL by at least 50% - and the topic next to yours in the forum shows that some people already need to take a big breath before getting started.
Of course, we recognise the desire to write meta-programs in MERL, and indeed we use that freely in some areas (e.g. subreport '_' type run). While there is a little duplication involved in writing local names explicitly in generators, as well as in the metamodel, that's only for one person - the metamodeler - and not for all the modelers. Unless you have hundreds of types with dozens of properties each, that shouldn't be too bad.
BTW Maybe one solution for you, if all you need is uniqueness of attribute names, would be to add a number to the end of the name:
$ix='0'
do :() { ... type%var $++ix ...}
|
|
![]() |
|
MerlUser
Member
Joined: 13.Jul.2010 Location: Germany Posts: 3 |
Quote Reply
Posted: 26.Jul.2010 at 14:59 |
|
The last example you give is not the best solution, but it works for my problem.
Now I changed the most type names of the properties to the local name. Only in cases where are more than one properties with the same type, I add extra code like this: do :() { if type<>'exceptionType' then ' ' type%var '="' id%xml '"' endif } ' exceptionOne="' :exceptionOne%xml '"' ' exceptionTwo="' :exceptionTwo%xml '"' |
|
![]() |
|
stevek
MetaCase
Joined: 11.Mar.2008 Posts: 160 |
Quote Reply
Posted: 26.Jul.2010 at 15:15 |
|
Great! That's a nice combination of a meta-solution with pragmatism.
Pragmatism is definitely needed when working with XML. It looks simple, but actually the full rules are a nightmare, so trying to write code on day 1 that fulfills all the rules is a lost cause. E.g. how many remember that the name of an attribute cannot start with the letters "xml" in any combination of cases, but it can start with a colon?
|
|
![]() |
|
Post Reply
|
| Forum Jump | Forum Permissions ![]() You cannot post new topics in this forum You cannot reply to topics in this forum You cannot delete your posts in this forum You cannot edit your posts in this forum You cannot create polls in this forum You cannot vote in polls in this forum |