Acceleo: using custom UML Profile as metamodal, and its stereotypes in templates? - acceleo

I'm new to Acceleo. I use IBM RSA (8.5.1). I created a custom UML Profile (with a few stereotypes extending default metaclasses, it's pretty usual). The UML profile is a .epx file. In addition, I created a simple model on which I applied my custom UML Profile, and "tagged" a few classes with my custom stereotypes.
My questions (sorry if it is trivial, but I didn't find a straight answer...):
Can I use my custom UML Profile as metamodel in Acceleo? Simply saying, instead of writing in my module file the following:
[module main('http://www.eclipse.org/uml2/3.0.0/UML')] (this one works okay)
can I write something like this:
[module main('platform:/resource/MyProfileProject/MyProfile.epx')]?
If I try this, I get an error message: "The metamodel couldn't be resolved".
I tried to convert my UML Profile from .epx format to .xmi and to .uml. None of those work.
If this can be made working somehow, can I use my custom stereotypes as type qualifiers in Acceleo templates (in "for" cycles, etc.)?
Any help is appreciated. Thank you in advance.
Marcell

I don't think you can.
As far as I know, you're supposed to use services to retrieve the profile data from your UML elements (stereotypes and so on), but the metamodel remains UML and this cannot be changed for Acceleo.
You can iterate over UML elements on lists of elements filtered according to their stereotype information though.

It can be done. I'm adding an example to show how to do it, since it took me quite some time to retrieve the profile stereotypes. I'm adding it for a future reference (to whoever may need it).
[comment encoding = UTF-8 /]
[module generate('http://www.eclipse.org/uml2/4.0.0/UML')]
[template public generateElement(p : Class)]
[comment #main /]
[file (p.name.concat('.php'), false)]
[if (hasStereotype(p, 'Soa Logic Profile::bOperation'))]
code for bOperation stereotype
[/if]
[if (hasStereotype(p, 'UML Standard Profile::entity'))]
code for entity stereotype
[/if]
[p._package.member.getApplicableStereotypes().qualifiedName/]
[hasStereotype(p, 'Soa Logic Profile::bOperation')/]
[/file]
[/template]
Notice that in the code above, the qualified name Soa Logic Profile::bOperation corresponds to the stereotype bOperation defined in the Soa Logic Profile. entity is a stereotype defined in the UML Standard Profile. Both Soa Logic Profile::bOperation and UML Standard Profile::entity are qualified names.
Note: You only need to use the UML-metamodel, this model (the .uml file) already has information about the applied profile. This can be checked by inspecting the .uml file. Also, as far as I understand, the *.profile.uml files do have to be in the same folder as the .uml model file.
Greetings from Paraguay!

Related

Interface attributes not automatically replicated to class in UML class diagram in Visual Studio

In Visual Studio, I've created a UML class diagram with a class that realises an interface containing an attribute and an operation as thus:
The operation is automatically replicated to the class, but not the attribute. The MSDN guidelines indicate this behaviour:
When you create a realization connector, the operations of the interface are automatically replicated in the realizing class. If you add new operations to an interface, they are replicated in its realizing classes.
However, this seems counterintuitive to their statement just beforehand, namely:
Realization means that a class implements the attributes and operations specified by the interface.
I'm sure there must be a good technical reason for this (some OO concept like polymorphism or abstraction), but I can't think why it discerns between attributes and operations in this way.
Can anyone give me some insight into this, and perhaps what I should do to get round it (do I add the attributes to the class manually in UML?), as it's resulting in generated code that doesn't compile?
While I don't know for sure, I'd imagine it is because in C# interfaces cannot contain fields, only methods. Having attributes on an Interface therefore doesn't make sense.
Interfaces can contain properties, but these just get compiled to PropType get_PropName() and void set_PropName(PropType value). (Fun fact, trying to declare those methods yourself will generate a compiler error.)
Unfortunately, there is not a nice "out of the box" way of defining properties in UML class diagrams, as they are a language specific feature. I think you have to define a custom stereotype and the templates to generate the code accordingly - faff.

Cannot Access SysML stereotypes and their properties in Acceleo

I am developing a M2T generator in Acceleo (in Eclipse). The model is basically a UML model with SysML profile created in Papyrus. It includes Blocks and FlowPorts. I have to access these stereotypes but it seems that I cannot retrieve any SysML object even though they appear in list (code suggestion). Actually I have to access ‘Direction’ property of FlowPort associated with Port. I have already tried suggestions and answers from various forums (including https://www.eclipse.org/forums/index.php/t/452587/) but in vain.
The code is given below. I have created java services as suggested by https://www.eclipse.org/forums/index.php?t=msg&th=1060450&goto=1693765& but port.hasStereotype(‘FlowPort’) always return false. I have also tried ‘SysML::PortAndFlows::FlowPort’ instead of ‘FlowPort’. I use Acceleo 3.6.2 on Eclipse Mars.
...
[template public generateElement(model : Model)]
[comment #main/]
[file ('created.txt', false, 'UTF-8')]
[for(port: Port | model.eAllContents(Port))]
[if(port.hasStereotype('FlowPort'))]
OK
[else]
NOT OK
[/if]
[/for]
[/file]
[/template]
I include following metamodels in the Module at the time of creating the module:
http://www.eclipse.org/uml2/5.0.0/UML
http://www.eclipse.org/papyrus/0.7.0/SysML
http://www.eclipse.org/papyrus/0.7.0/SysML/Blocks
http://www.eclipse.org/papyrus/0.7.0/SysML/Constraints
http://www.eclipse.org/papyrus/0.7.0/SysML/PortAndFlows
http://www.eclipse.org/emf/2002/Ecore
Also, I do register required packages including following in registerPackages() of Generate.java as suggested by the link just mentioned above.
// UML2 profiles
URI uri = URI.createURI("platform:/plugin/org.eclipse.uml2.uml.resources");
uriMap.put(URI.createURI(UMLResource.LIBRARIES_PATHMAP), uri.appendSegment("libraries").appendSegment(""));
uriMap.put(URI.createURI(UMLResource.METAMODELS_PATHMAP), uri.appendSegment("metamodels").appendSegment(""));
uriMap.put(URI.createURI(UMLResource.PROFILES_PATHMAP), uri.appendSegment("profiles").appendSegment(""));
// SysML profiles
uri = URI.createURI("platform:/plugin/org.eclipse.papyrus.sysml");
uriMap.put(URI.createURI(SysmlResource.LIBRARIES_PATHMAP), uri.appendSegment("librairies").appendSegment(""));
uriMap.put(URI.createURI("pathmap://SysML_PROFILES/"), uri.appendSegment("SysML.profile.uml").appendSegment(""));
uriMap.put(URI.createURI("pathmap://SysML_PROFILES/"), uri.appendSegment("model").appendSegment(""));
Any sort of help is appreciated.
I had an identical problem, but with UML/MARTE rather than SysML.
I bet that port.getAppliedStereotypes() always returns the empty list, no matter what (even if of course, port is stereotyped). I also tried everything you did, unsuccessfully, including double-checking if there was a #generated NOT in the javadoc of the registerPackages method (to it being re-generated each time).
I fixed the issue whit a little workaround. I assume that you (like I did) use as input for the transformation the model.uml file generated by Papyrus. This might actually be the cause of the problem, even though I don't see an alternative. If you open that file with a text editor, you'll find that the <FlowPort> tags are outside the <uml:Model> tag. This means that, for reasons that I still fail to understand, the stereotype() methods cannot "see" the stereotypes and always return null, or empty lists. This is possibly because they fail to match the stereotype base_NamedElement to the xmi:id inside the <uml:Model> tag.
On the other hand, if you define a template which takes as input a FlowPort (rather than a Model) you will be able to get your stereotyped element and all of its properties.
[template public generateElement(aFlowPort: FlowPort)]
[comment #main /]
[comment here you can access to the aFlowPort fields]
[/template]
Among others, you can also access the base_NamedElement property of the stereotype (i.e., the Port that is stereotyped FlowPort in your model), and you can use the qualifiedName property of the base element to map back the stereotype to the Port in your Model. In practice, this means that you have to link the stereotypes to their stereotyped entities by hand.
Clunky and annoying, but still gets the job done until somebody comes with a less "workaroundy" solution.

Entity Framework: Why do the templates no longer generate ".designer.cs" source files

The default type generation in Entity Framework 3.5/4.0 emits each of the types in "Xxxx.designer.cs" source files (where "Xxxx" is the name of the type being generated). This then allowed for the developer to generate his own "Xxxx.cs" source files where further implementation could take place, or attributes could be added to Metadata classes etc.
The more recent T4 templates that have been made available (POCO, Self Tracking etc.), including the default type generation in VS2012, all genrate "Xxxx.cs" themselves without the ".designer" suffix.
I know that it is easy enough to override the behaviour of the T4 templates to emit the ".designer" within the file names, but am I missing something here where we are actually being discouraged to extend these classes through the partial definitions?
In a recent project where I generated Self Tracking Entities, I found that I had to rename the emitted files so that I could extend the definitions with Metadata class attributes as well as overrides of .Equals(object) and .GetHashcode() (otherwise EF could not detect duplicates properly) for example.
Is there something that I have missed where we are now expected to leave the emitted partial classes as they are or is this merely an oversight and are most of you also having to rename source files being emitted?
Code generation strategy has changed in VS2012. Before the code that was generated was using EntityObject based entities and a context class derived from the ObjectContext class. VS2012 by default generates POCO entities and DbContext dervied context. If you still want ObjectContext based context and EntityObject based entities you need to:
Right-click on the designer surface and select properties
Change the "Code Generation Strategy" from "None" to "Default"
Remove .tt files from your solution to avoid having both contexts and duplicate entities.

Basic Entity Framework Questions

I have an existing database, which I have been happily accessing using LINQtoSQL. Armed with Sanderson's MVC3 book I thought I'd have a crack at EF4.3, but am really fighting to get even basic functionality working.
Working with SQL 2008, VS2010, the folder architecture appears to be:
ABC.Domain.Abstract
ABC.Domain.Concrete
ABC.Domain.Concrete.ORM
ABC.Domain.Entities
Per examples, repository interfaces are abstract, actual repositories are concrete. Creating EDMX from the existing database puts that in the ORM folder and the Entities holds the classes I designed as part of the domain. So far so good.
However! I have not once persuaded the deceptively simple EfDbContext : DbContext class, with method to work...
public DbSet<ABC.Domain.Entities.Person> Person { get { return _context.Persons; }}
It complains about missing keys, that Person is not a entity class, that it cannot find the conceptual model, and so on.
Considering I have a basic connectionstring in the web.config, why is not creating a model on the fly to do simple matching?
Should the ORM folder exist, or should it simply be Concrete? (I have a .SQL subfolder for LINQtoSQL concret so it suits me to have .ORM but if it's a flaw, let's fix it).
Should I have my homespun entities AND the automatically produced ones or just one set?
The automatic ones inherit from EntityObject, mine are just POCO or POCO with complexTypes, but do not inherit from anything.
What ties the home designed Domain.Entities.Person type to the Persons property of the Context?
Sanderson's book implies that the matching is implicit if properties are identical, which they are, but that does not do it.
The app.config has an EF flavoured connection string in it, the web.config has a normal connection string in it. Which should I be using - assuming web.config at the moment - so do I delete app.config?
Your help is appreciated. Long time spent, no progress for some days now.
What ties the home designed Domain.Entities.Person type to the Persons
property of the Context?
You seem to have a misunderstanding here. Your domain entities are the entities for the database. There aren't two sets. If you actually want to have two sets of object classes (for whatever reason) you must write any mapping between the two manually. EF only knows about the classes which are part of the entity model.
You should also - if you are using EF 4.3 - apply the DbContext Generator T4 template to the EDMX file. Do not work with EntityObject derived entities! It is not supported with DbContext. The generator will build a set of POCO classes and prepare a derived DbContext. This set of POCO classes are the entities the DbContext will only know about and they should be your only set of domain entities.
The created DbContext will contain simple DbSet properties with automatic getters and setters...
public DbSet<Person> People { get; set; }
...and the Person class will be created as POCO as well.
Download the entity framework power tools:
http://visualstudiogallery.msdn.microsoft.com/72a60b14-1581-4b9b-89f2-846072eff19d
Right click in your project to 'reverse engineer an existing database' it will create the code classes for you. No need to use EDMX ,and this method will create the DbContext derived class for you
There are many questions here and you won't get an answer, but I'll stick my 5 pence for what it's worth.
Sanderson's MVC3 book
Your problems are not to do with MVC3, they are to do with Entity Framework and data persistence layer.
ABC.Domain.Abstract ABC.Domain.Concrete ABC.Domain.Concrete.ORM
ABC.Domain.Entities
Can you say why this is separated in such a way? I would argue and say that ABC.Domain should contain your POCOs independent of your persistence layer (EF) and your presentation layer (MVC). Your list implies that your domain contains ORM and your data access entities. I'm not arguing here, what I'm trying to say, is that you need to understand what you really need.
At the end of a day, I'm certain that a simple example would suffice with ABC.DataAccess, ABC.Domain and ABC.Site.
Do you understand why repositories are abstract and concrete? If you don't, then leave out interfaces and see whether you can improve it with interfaces later.
Person is not a entity class, that it cannot find the conceptual
model, and so on.
Now, there are multiple ways you can get EF to persist data for you. You can use code first, where, as the name implies, you will write code first, and EF will generate database, relations and all the relevant constraints for you.
You can use database first, where EF will generate relevant class and data access related objects from your database. This is less preferable method for me, as it relies heavily upon your database structure.
You can use model first, where you will design your class in EDMX designer and it will then generate relevant SQL for you.
All of these might sound like a bit of black box, but for what you are trying to achieve all of them will work. EDMX is a good way to learn and there are many step by step tutorials on ASP.Net.
but if it's a flaw, let's fix it).
You will have to fix and refactor yourself, there is no other way to improve in my honest opinion. I can give you a different folder/namespace structure, but there will always be a "better" one.
Should I have my homespun entities AND the automatically produced ones
or just one set?
Now this depends on the model that you have chosen. Database first, code first, code only and whatever else is there. If you are following domain driven development, then you will have to work with classes, that represent your business logic and that are not tied up to your data persistence layer or presentation layers, therefore POCO is a way forward.
What ties the home designed Domain.Entities.Person type to the Persons
Now this again depends on the model that you are using.
The app.config and web.config
When you are running your web application, the connection string from web application will be used. Please correct me if I'm wrong.
Your help is appreciated. Long time spent, no progress for some days
now.
General advise, leave MVC alone for the time being. Get it to work in a console application and make sure you feel comfortable with options offered in EF. Good luck :)
The solution to why nothing worked code-first...
...turned out to be a reference to System.Data.EntityClient in the connection string, which ought to have read System.Data.SqlClient.
Without this provider entry being correct, it was unable to work code-first.
Finding which connectionString it was using was a case of deliberately mis-spelling a keyword in the connections there were to choose from - they all were named correctly - but were in app.config, and 2 places in the web.config. With a distinct naming error, when the application threw an error trying to create the domain model, it was easy to identify which connection string my derived DbContext class was using. Correcting the ProviderName made all the difference.
Code-first is now working just fine, with seeded values on model changes.

Visual Studio code generation - how to deal with developers editing class files

So thanks to the Visualization and Modeling Feature Pack , I can build a uml model diagram and generate a bunch of classes.
But what now? Presumably, my developers will add code to those classes. Useful code, valuable code, and as the templates themselves indicate:
// Changes to this file will be lost if the code is regenerated.
So what is the best solution here? Can I make the modeling project reflect changes to the actual classes? Should I generate partial classes? Modify the default templates to read class files and not auto-generate anything that has been modified? Should I tell developers not to edit model files under pain of....well, pain?
Thanks for the tips.
As far as I know, this is really the key reason for partial classes in the first place. The custom code goes in one file, the auto-generated in another.
You could also create classes derived from the generated ones, and put any changes in there. I also agree with above poster that partial classes could be the way to go.
Although the tools generate basic skeleton classes out of the box, that's really just a starting point. You can easily adapt the generator templates to create your own stuff. Different people want to generate different code from the classes - some even generate XML or SQL. And yep, in C#, partial classes are good to generate, so's to keep the hand-written code separate from the generated bits.
It's good to put lots of extension points in the generated code, where you fill in the details by hand code.
Another neat idea is "double derived": from each UML class, generate a base class and a derived class. The derived one has only constructors. The base class has any methods you generate. So your hand code can easily override generated methods where you need that.
There are several options in the tool and recommending what is best is hard without knowing your scenario. Partial classes are great for some, but not all applications. If you want your UML class to generate a partial class, you can set it's C# stereotype's property to "Partial" and it will do so, and custom code can then be added in a partial class that won't be overwritten. If you want to prevent code from being overwritten, you can do this by setting the overwrite property to False on the template binding that corresponds to the package you are working on. This lets you set your extension code to be in a package that is not overwritten, while your model mastered code is overwritten with the latest model changes. Finally, if you want your code to be the master for your model so it always reflects the latest code, then you can reverse engineer your code by using the architecture explorer to select your classes and then dragging them in to a UML diagram. So for a given gesture, either the model is the master or the code is the master. In this version, we did not implement automated merge capabilities between the two.

Resources