Xtext: How to persist a DSL AST using XMI (or JSON)? - xtext

I'm currently trying to figure out how to "connect" an Xtext Language Server with an EMFCloud.ModelServer instance so each time a client (VS Code extension in my case) saves a custom DSL text file, the Language Server saves the AST as XMI (or JSON). So then later the model can be included in the Model Server workspace and other editors can react to changes on my model (XMI, JSON)
So far I've seen that the current Xtext LS version does nothing with the "textDocument/didSave" notifications:
#Override
public void didSave(DidSaveTextDocumentParams params) {
// nothing to do
}
I'd like to enhance my LS instance to provide logic to that method and persist the current AST to XMI/JSON.
So far I was able to see that there is a generator class which the doGenerate method is called when the save is triggered on client side. However, taking a look to the call hierarchy of that method, it seems that is called within a "code generation" process. The documentation found for this is always related to other language generation (i.e. Java or c++) and I'm not sure if this would be the right place also because it seems that the file URI is not accessible (as it is in the didSave method of the LS part)
As summary, is there a way to access the semantic model (AST) from the Language Server "didSave" operation?

Following the hints provided by Christian Dietrich, the Language Server uses a ProjectManager which is able to retrieve the XtextResource holding the semantic model for a specific model URI (i.e. the URI passed to the server from the editor). Basically:
XtextResource resource = (XtextResource) getWorkspaceManager().getProjectManager(uri).getResource(uri);
In order to get our model from the resource the following method is provided:
EList<EObject> modelObjects = resource.getContents();
At this point we can persist the semantic model via the EMF Model Server (i.e. by creating or modifying an existing model in the Model Server).

Related

Genexus Extensions SDK - Is there a built in helper to save data locally?

I Would like to know if the Genexus Extension SDK already implements something to store persistent data locally (KB Independant and per KB), something like PersistentDictionary from ManagedEsent
I know that genexus uses SQL Server to store KB Related information, is there an interface for me to extend that?
I want to save data per genexus instance (locally) and use that data to load my extension config, everytime the users executes Genexus.
We don't use PersistentDictionary. I would advice not to use it, as it's a Windows specific API, and we are trying make everything new cross platform, as part of our journey of making GeneXus BL run on other OS.
There are different options of persistence, depending on the specific details of your scenario.
If you want to store something like configuration settings for your extension, you can use the ConfigurationHelper class located in Artech.Common.Helpers. This class provides read access to the configurations defined in the GeneXus.exe.config file in the GeneXus installation folder, as well as read/write access to the Environment.config file located in %AppData%\GeneXus\GeneXus\<version>\Environment.config. Note this file depends on the current user, and is shared between different GeneXus instances of a same main version.
The ConfigurationHelper class provides operations to read and save settings of basic types string, int and bool.
const string MY_EXTENSION = "MyExtensionSettings";
const string SETTING1 = "Setting1";
const string SETTING1_DEFAULT_VALUE = "This is the default value";
const string SETTING2 = "Setting2";
const int SETTING2_DEFAULT_VALUE = 20;
string setting1Value = ConfigurationHelper.GetUserSetting(MY_EXTENSION, SETTING1, SETTING1_DEFAULT_VALUE);
int setting2Value = ConfigurationHelper.GetUserSetting(MY_EXTENSION, SETTING2, SETTING2_DEFAULT_VALUE);
// Do something and maybe change the setting values
ConfigurationHelper.SetUserSetting(MY_EXTENSION, SETTING1, setting1Value);
ConfigurationHelper.SetUserSetting(MY_EXTENSION, SETTING2, setting2Value);
If you want to store something in a file based on the current opened KB, there's no specific API that'll help you handle the persistence. You can use the properties Location and UserDirectory of the KnowledgeBase class to access the KB location or a directory for the current user under the KB location, but it's up to you the handling of the file. You'll have to decide on the file format (binary or text), file encoding in case of text files, and handle all read and write operations to that file.
We use the kb.UserDirectory path to store non-critical stuff, such as the set of objects that were opened the last time the KB was closed, or the filter values for different dialogs.
In case you'd like to store settings inside the KB, there are plenty of options.
You can add properties to existing objects, KB version or environment. Making it a property doesn't necessary mean you'll have to edit the value in the property grid, although it's usually the way to go.
You can define a new kind of entity. Entities are the basic elements that can be stored in a KB. The entity may be stored depending on the active version of the KB, or may be independent of the current version. Entities can have properties, whose serialization is handled by the property engine, and also can read and store a byte array whose format and content will be handled by you.
You can add a part to an existing object. For instance you may want to add a part to Procedure objects. In order to do this you'll have to extend KBObjectPart, define your part in a BL package, declare that the part composes objects of certain type, and provide an editor for your new part in a UI package. KBObjectPart extends Entity so the serialization of the part is similar as in the previous case. A caveat of this option is that you'll also have to handle how the part content is imported, exported, and compared.
You can add a new kind of object. Objects extend the KBObject class, which extends Entity. Objects are not obliged to have parts (for instance the Folder object doesn't have any). When choosing to provide a new kind of object you have to consider a couple of things, such as:
Do you want to be able to create new instances from the new object dialog?
Will it be shown in the folder view?
Can it be added into modules?
Can it have the same name as other objects of different types?
As a general guideline, if you choose to add a new property, add it to objects, versions, or environments, not parts. Adding properties to parts is not so good for discoverability. Also if you choose to add a new kind of object, even though it inherits from Entity which as mentioned earlier can read and store a byte array, it's preferred to don't use the byte array in KBObject and add a KBObjectPart to it instead. That way the KBObject remains as lightweight as possible, and loading the object definition from the DB remains fast, and the blob content is loaded only when truly needed.
There's no rule of thumb. Depending on the specifics of the scenario, one option may be more suited than others.

Mapping non-compatible properties from DTO to entity

I'm refactoring a web app to ensure that my entities are always initialized in a valid state. This means that I'm using DTOs for user input, and map those DTOs to my entities after validation.
However, some of the properties of the DTOs are not directly mappable to the properties of the entities. If a DTO contains a base64 encoded image and the entity requires a URL to the image file, I need to save the base64 to a file in the mapper in order to assign the URL of that file to the entity.
It could just be me, but it feels like this kind of stuff doesn't belong inside a DTO to entity mapper. Are there reasons why this might be a bad idea? What strategies are commonly used for this kind of mapping?
Seems to me that in your case you don't have a simple mapping process from DTOs to Entities because you have application logic in the process. Storing images somewhere and getting an URL/Path for that image is application specific logic, so you probably need a Service for it.
Applications usually have some kind of tasks or operations that it needs to perform and define the flow of the application. One way to define this flow is by using Commands and attach the DTO's to these Commands.
For example let's say you have a registration process so the user must enter some data and you need to create an Account Entity.
In case of web app, the frontend will have to collect user information and create and send a command to the backend. In this case you will have RegisterUserCommand. This command will contain a UserInfo DTO property, or will have properties for the user info. For example:
RegisterUserCommand {
string UserName
string FirstName;
string LastName;
Image Avatar;
}
The next thing you need is a RegisterUserCommandService or (RegisterUserCommandHandler depending on your taste and terminology used) that will process/handle the Command. You also need a StorageProvider that will provider service operations for storing and retrieving images (can be on the File System, Amazon S3, Dropbox etc.) and give you a link. Here is a sample pseudo code
RegisterUserCommandService {
Process(RegisterUserCommand cmd) {
avatarLink = storageProvider.Store(cmd.Avatar);
account = new Account(cmd.UserName, ...., avatarLink);
accountRepository.Save(account);
}
If you tell me more about your application I can provider an example for your specific case.
Here are some resources you can check:
https://cqrs.wordpress.com/documents/task-based-ui/
https://martinfowler.com/bliki/CommandOrientedInterface.html
https://weblogs.asp.net/shijuvarghese/cqrs-commands-command-handlers-and-command-dispatcher

calling system commands from rails - general design pattern

Rails newbie here, building a rails api backend application.
Here is the broad application flow
There is a single model palindrome which has a field name of string kind
In the simplest user interaction user client sends POST with string name to PalindromeController.
This string need to be passed to a system application systemapp and the app would return another string. This would need to be parsed as a JSON string and returned to the client.
Questions on how to go about the following.
where should I call the systemapp from - from model or controller ?
should the call to systemapp be wrapped in a background job ?
Call it from the model.
If it were a more complex case, you could treat the subprogram as a proper interface and write a separate class for it. This one I would probably put into lib/interfaces or even I a separate gem, as it would contain only code specific to the subprogram, not to your application.
The lackmus test for where it goes is "will or should your model ever be able to do anything at all without that subprogram". If yes, then it is a case of dependency injection and could go into the controller. If "no", then it goes into the model.
Rule of thumb: fat models, lean controllers.
Do it directly if the performance is acceptable, i.e. if there is no risk of normal user activity overwhelming the webserver. Else, you would use deferred execution, i.e. batch processing, which would entail a very much larger end result.

writing a JBehave story

This question isn't about REST, but about using the returned value from an invocation made in #When in the subsequent #Then.
I am looking at using JBehave to test some calls to a REST api. First there is a post to create the user
When I create a user with name Charles Darwin
As I understand REST, and this is what the Atom api does, the id is returned in the location header, e.g. /user/22. So then I want to assert something about the response.
Then user was created with a valid Id
I can do this by creating a member variable in the Steps class and storing the response there, and I have used this approach before, but is this the correct way?
Yes. One needs to store data that can be asserted on in your #Then methods. The simplest way to do this is to have a member variable - but that means that your #When/#Then need to be in the same Steps class. Another way to do it is to have a shared data object that all your Steps use and you can then set it in one method and get it in another. If you just want something generic, you can do a Map<String,? extends Object> as your generic data object. And then if you run with multiple threads, then wrap the data object in a ThreadLocal.
That's what I've seen - and the data object should be setup/cleared with a #BeforeScenario/#AfterScenario method.

ACL on field level in Grails

in our new software project, we have the following requirement: A webpage shall show a set of data. This data shall be editable by some users (assigned to roles, i.e. manager), and only viewable by others. The tricky part is described by an example:
A User-page consists of address data and account information. The addess data shall be editable by the user and the manager and viewable by all users, while account information shall only be viewable by the actual user and the manager.
I have read a lot of information about SpringSecurity. It provides a very good framework to gran permissions on urls and methods and even domain classes. But what I need is field level ACLs. At least, that's what I think at the moment.
So, the question is: How to solve this problem using Grails?
Thanks a lot in advance,
Regards Daniel
Spring Security (Acegi Plugin) is definitely the way to go with Grails.
There is a taglib you can use that will allow a page to be different for different roles such as the following:
<g:ifUserHasRole roles="ROLE_ADMIN">
html code for extra fields
</g:ifUserHasRole>
Me, I'd encode it on the domain class, emulating the way GORM has you annotate the domain classes (static access = [field1: "ROLE_USER", field2: "ROLE_ADMIN,ROLE_USER"] as an example). Then build a method your controller could use to redact them for a given user. That method could use the domain class's annotations to decide how to redact it. Then, metaprogram it onto each of the domain classes the way plugins do.
Similarly, write the opposite method to restrict data bindings of params into the domain class, write your own data binding utility method, then metaprogram it onto each domain class as well.
Then you can just use instance.redact(user) or instance.bindData(params, user) to do what you want, and it's practically declarative syntax.
We have a similar situation and use both the ifUserHasRole tag in the gsp to drive the appropriate presentation and the we have a filter that enforces the rules based on the action being called. For example, on user controller we would only allow the management roles to call save action, or if the user.id is the same as the session.user.id. This seemed to be the best option for our situation.
What about creating an ACL class like this:
class ACL(val entry: Entry*) {
def isAccessAllowed(subject: String, permission: String): Boolean = ...
}
class Entry(val subject: String, val permission: String*)
usage:
new ACL(
new Entry("dave", "read", "write"),
new Entry("linda", "read")
)
(This example is in Scala, because I found it more expressive in this case, but it should be easy to transfer it to Groovy.)
You would then connect an ACL object with the object to be protected.

Resources