Custom Persistence -Write and Read Model

Hi,

I have read through custom persistence sample persistence example and was able to implement my custom persistence to load models from database. However I am facing some problem.

I want to load  some models from database when a new model is created, which I accomplished by
Code
public SModelData createEmpty(SModelReference reference, StreamDataSource source) { 
  SModel sModel = new SModel(reference); 
  string name = reference.getModelName(); 
  info "Model Name" + name; 
  if (reference.getModelId() instanceof SModelId.RelativePathSModelId) { 
    name = FileUtil.getNameWithoutExtension(((SModelId.RelativePathSModelId) reference.getModelId()).getFileName()); 
  } 
  SNode entity = CustomConvertor.createDBObject("STUDENT"); 
  SNode workset = CustomConvertor.createDBObject("TEACHERS"); 
  sModel.addLanguage(PersistenceFacade.getInstance().createModuleReference("a47aa9ed-b3e0-4756-896f-9425cf4c8ec5(com.org.dsl.language)")); 
  sModel.addRootNode(entity); 
  sModel.addRootNode(workset); 
  return sModel; 
     
}
prettyPrint();

With above code if any model is created 2 db models are loaded and added to model.

Now I want to persist this model as default persistence in MPS, that I dont want to persist in any custom format so whenever the Model is loaded/ read Model it loads from default persistence format , How do I achieve this  as I need to add some default logic to below writeModel method
public void writeModel(SModelData data, StreamDataSource source) throws IOException, ModelSaveException { 
  info "-------------------------in Write Model-------------------------"; 
     }
prettyPrint();


Also when i tried to save the content somehow in xml format, then below code in load method always loads model as temp
@NotNull() 
@Override 
public SModel load(@NotNull() DataSource dataSource, @NotNull() Map<String, String> options) throws IOException { 
  if (!((dataSource instanceof StreamDataSource))) { throw new UnsupportedDataSourceException(dataSource); } 
  String moduleRef = options.get(ModelFactory.OPTION_MODULEREF); 
  String relPath = options.get(ModelFactory.OPTION_RELPATH); 
  String modelName = options.get(ModelFactory.OPTION_MODELNAME); 
  boolean contentOnly = "true".equals(options.get(ModelFactory.OPTION_CONTENT_ONLY)); 
  SModelReference ref; 
  if (relPath == null || moduleRef == null || modelName == null) { 
    if (!(contentOnly)) { 
      if (dataSource instanceof FileDataSource) { 
        LOG.error("cannot load " + dataSource.getLocation() + ": relPath = " + relPath, new Throwable()); 
      } 
      throw new IOException("cannot load xml model from " + dataSource.getLocation()); 
    } 
    ref = PersistenceFacade.getInstance().createModelReference(null, SModelId.generate(), "temp"); 
  } else { 
    SModelId id = PersistenceFacade.getInstance().createModelId("path:" + relPath); 
    SModuleReference mref = PersistenceFacade.getInstance().createModuleReference(moduleRef); 
    if (mref == null) { 
      // TODO fix 
      return null; 
    } 
    ref = PersistenceFacade.getInstance().createModelReference(mref, id, modelName); 
  } 
  return new CustomPersistenceSModel(ref, (StreamDataSource) dataSource, this); 
}


prettyPrint();

FYI , the above code is from  sample xml persistence project and  reloading of model doesnot work as refpath is returned as null.
Thanks

Kunal
10 comments
Hi!

It looks like you are trying to use custom persistence in order to import model content from data base to MPS. Is it true?

MPS custom persistence was designed in order to provide you with the possibility to load (edit) and save models into the proprietary formats (including data base in general). We suppose that by writing your custom DB persistence you will provide MPS with possibility to access DB information directly.

In order to load data from DB and then save it into standard MPS model you have to create import action - either connecting to DB and loading content/saving it as MPS model or accessing DB content through the custom persistence you will create and re-saving it as a separate (new) MPS default model.

HTH.
0
Hi Alex,

Thanks for your reply. I am trying to import model content from Database so that it is editable via MPS IDE. I have created a grammar to represent the content to IDE. I want users to open Model from MPS IDE , edit and save back to DB.

I did not understand this part In order to load data from DB and then save it into standard MPS model you have to create import action

Can you please elaborate on what is import action or share any link/samples/examples.

Thanks
0
An import action would be a node of the ActionDeclaration concept that the user could invoke from the menu. The action would connect to the db, load the data (model) and insert it into your MPS model, so you have your model persisted outside of the db. Then you'd no longer need the db.

From what you say, however, this is not the scenario that you are looking for. Since you want to load and save models from/to a database repeatedly, you'll need to provide a db-persistence.

What puzzled us was your mention "Now I want to persist this model as default persistence in MPS,...", which we do not understand why you'd want to do that.
0
Hi!

If you are going to expose DB content for the MPS user to allow editing it and saving back to DB on MPS "save" action then you have to implement model persistence reading model from the DB and saving it back. I don't understand why you asked about:
Now I want to persist this model as default persistence in MPS


Such models should not be persisted as default MPS persistence at all...

By import action I mean custom action reading DB content and saving it as an MPS model. (see documentation about MPS actions: https://confluence.jetbrains.com/display/MPSD32/Plugin#Plugin-Actionsandactiongroups)

Generally speaking, in order to edit "external" data in MPs you can follow one of two possible scenarios:
1) implement custom model persistence working directly with your data storage (DB, for example) so MPS will load model from the data storage on opening project and save data back to the data storage on any modifications made in MPS

2) import (copy) data into default MPS model, edit a copy of it locally within the MPS project and upload it back to the data storage on calling specific action.

With first approach you have to deal with custom model persistence and even custom model roots in some cases because custom model loaded from the external data storage can be not necessary represented by any local file, custom model root can be not necessary represented by any local folder..

With second approach you don't need any custom persistence code - you can just write java code connecting to the data storage, loading data from there, converting it to the MPS SNodes and saving into specified model. The way back is similar - custom action have to get all the data from the model and save it back to the data storage. You ave to handle possible merge conflicts within this action.
0
Hi Alex/Vaclav,
Thanks for the detailed explanation. I am following 1st approach of creating a custom persistence and loading the model from DB to MPS by mapping mps nodes to DB tables.

After loading the models in MPS , If i change anything in the editor , I see writeModel() method is called. Is there any way to detect which node was added/modified in the writeModel Method, since we have almost 200 nodes in the model and each time writeModel() is called , we don't want to persist all the data back to DB.Below is blank implementation of writeModel() API.
public void writeModel(SModelData model, StreamDataSource source) throws IOException, ModelSaveException { 
  info "---in Write Model----"; 
  info "Source Stream" + source.getLocation(); 
  for (SNode rootNode : model.getRootNodes()) { 
     
      
    } 
  } 
  
prettyPrint();

Any suggestions?
0
Hi!
You could use SNodeChangeListener from openapi to track what node are being added/removed to/from the model just in time. Or, you could compute delta right before saving the model to DB.
0
Great.. I was able to add Module and Model Listener as Project Component via plugin.
Thanks
Kunal
0
Hello Kunal!
I'm also elaborating a similar use case.
Have you overridden only the XmlModelPersistence File or the complete implementation of the plugin?
Would it be possible to provide a trivial example?

Thanks in advance!

Regards
msch95
0
Hi,
You need to first use the complete plugin to understand the components.
You can see plugin.xml file which is important to load the classes. Now with this you can start modifying the XmlPersistence class and add your own logic for save.I will share a sample example soon if you really need that.

Thanks
0
That would be great and help me a lot!

Thanks Kunal
msch95
0

Please sign in to leave a comment.