Bringing Umple's APIs to the metamode and runtime #962

Open
vahdat-ab opened this Issue Jan 21, 2017 · 17 comments

Projects

None yet

3 participants

@vahdat-ab
Member

Umple generates a hand full of useful APIs for attributes and association. Currently, those methods are generated by UmpleTL. It means they are not available in the runtime model of Umple systems. This limits us regarding many analysis we can do at the runtime and causes to have duplication in UmpleTL's template files. Furthermore, This will be a great base for the future extensions such as using Language Server Protocol.
One of the concerns is how to deal with the executable body of these methods. I think we can create those APIs (their signature at the modeling level) and then tag them as auto-generated. Then code generated will know how to deal with that.
This idea can be extended in an advance form to state machines.

More info about those APIs can be found here

@vahdat-ab
Member

Another concern might be the size of the model at the runtime. I think this can be dealt later with some optimization. It might not be even an issue with the current advance in technology.

@TimLethbridge
Member

Sounds interesting, but I think explaining what you mean by example would be important. Give an example trivial umple model with two classes, an association and an attribute, and describe the effect of what you would like to see

@vahdat-ab
Member

This is in the direction relationship with issue #462

@katcavers katcavers was assigned by vahdat-ab Jan 30, 2017
@vahdat-ab
Member

Consider the following example,

class A{
  Integer x;
  0..1 -- * B;
}
class B{ 
}

Umple generates API for the attribute x and also the association 0..1 -- * B; The list of APIs for different elements are listed here
These APIs are generated by the different code generators (Java, PHP, etc). It means if a modeling element wants to check a method called void getX() in the class A, the list of methods for the class A will not show it. In these cases, the developer of that element starts to hack the code. The person implements another function which reacts like the one exists in the code generators and produce the list of auto-generated methods (sometimes, it's just a manual list). This brings lots of boiling code. Furthermore, it's hard to update to date all those manual codes with their own hard-coded names. This becomes much worse for cases that we do lots of post checking to make sure the model is valid.
For example, to check if there is no conflict between used-defined methods and auto-generated methods.
By having those methods at the metamodel level, we guarantee that the regular methods such as getAllMethods will always show the right number of methods. Then, a normal iteration on this list can satisfy many post-checkings.
Another example,

class A{
  Integer x;
}
trait T{
  Integer getX();
  void setX();
  void pMethod(){
  //***
  }
}

This example points out that the client of T must have two methods called getX and setX. When the algorithm tries to check the list of methods of the class A, there are not such methods. The algorithm needs to go through a complicated process to figure out if there are some auto-generated methods or not.

I believe this a great step for reducing dependency on code generators and have more concrete metamodel. If Umple wants one day in the future to have its own binary code, so there won't be any issue regarding the APIs.
It also brings many benefits for having a smart compiler at the IDE level (a future roadmap). For example, if users press ctrl+space, they will see those auto-generated methods as methods they can call for a specific class

@katcavers
Contributor

@vahdat-ab I have started trying to orient myself with some of the compiler code, and I want to make sure I am on the right track. I found the method analyzeAttribute in UmpleInternalParser_CodeClass.ump. Is this the correct point to identify attributes to add API methods for?

@vahdat-ab
Member

@katcavers yes. this is the place Analyzer analyzes the abstract syntax tree

@katcavers
Contributor

@vahdat-ab
I found I was getting a whole bunch of errors when I build because duplicate methods are being generated. This makes sense, as my change adds a get method for any attribute to the model, and the generator generates the API methods as well as adds any methods existing in the model; so two get methods with the same name are being added for each attribute.

I remember saying that we wanted the generation of the API methods to remain in the generators. So, I have added an additional type, fAutoAPI, to the Source enum of the Method class and set the get method's source to this. Then, I check in the Java generator class_MethodDeclaration.ump and if the source of the method is fAutoAPI I skip generating this method. Is this the right approach?

@vahdat-ab
Member

To me, it looks ok. I wonder if you detected for what reason fAuto is used? I thin it's there for this purpose.
The way I was thinking is this:
At the code generation level, the generator detects an auto-generated method, and then it generates the method along with the necessary implementation.

@vahdat-ab
Member

let's go in the way you describe. If we want to do any modification later it will be at the code generation level. You just make sure you do all required checkings at then modeling level.

@katcavers
Contributor

Sounds good.I think eventually implementing the auto-generated methods to be generated by the generators makes sense. This would just be a huge change to the code generation side, so it is easier to do this step first.

@katcavers
Contributor

I am having an issue with my changes and the Ruby generator. Many of the test cases are failing because empty lines are being inserted. I believe it may be due to the fact that we skip over autogenerated API methods, but somehow a new line is still inserted. For example, I have attached two files; the expected vs actual Ruby code.
The only difference is there are two extra empty lines at the end of the actual output.
actual.txt
expected.txt

@katcavers
Contributor

@vahdat-ab I also have two more questions.

First, in our initial discussion for this project, we talked about constructors. Would you be able to expand again on whether I should be creating/modifying constructors when an attribute is encountered in the model?
Second, you also mentioned I should make a method that could remove these autogenerated methods from the model. Would this be a method that removes all the API methods, or a method that could take for example an attribute as a parameter, and delete the API methods for only that attribute?

@vahdat-ab
Member
vahdat-ab commented Feb 24, 2017 edited

@ahmedvc ----> The issue Resolved

but somehow a new line is still inserted. For example, I have attached two files; the expected vs actual Ruby code.

I wonder if you can comment on this? How can we remove those empty lines generated because of passing some conditions?

@vahdat-ab
Member

First, in our initial discussion for this project, we talked about constructors. Would you be able to expand again on whether I should be creating/modifying constructors when an attribute is encountered in the model?

yes. This is a critical issue. You should create a constructor and feed its parameters.

Would this be a method that removes all the API methods, or a method that could take for example an attribute as a parameter, and delete the API methods for only that attribute?

The method should have a parameter such as an attribute or association and then remove related auto-generated APIs. You can also implement a method that removes all of them. This is going to be easy because there is a property that specifies which methods are auto-generated.

@katcavers
Contributor

I think I actually just figured out why it's happening. Before, there were no methods in the model for this specific case. But now there are, as I am adding get and set API methods at the model level. In the generator, a check is done on the class being processed is done; if the class has methods, it then iterates through all the methods and at the end appends to the string builder two new lines. For this case, the if statement used to prove false, but now it is true because of the API methods I add at the model level. So even though no code is generated for these methods, those two new lines are added.

@katcavers
Contributor

Thanks Vahdat, I will continue working on these.

@vahdat-ab
Member

@katcavers great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment