Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Creating Serializer for different DSL
Creating Serializer for different DSL [message #1817248] Tue, 19 November 2019 09:15 Go to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
Hi,

I have 2 DSLs, A and B. (A models business entities, B models database tables).

B elements link to A elements but not the other way around. However, when compiling A elements, B elements should be created.

My approach:
- 1. the A generator creates B elements in memory
- 2. then, the B elements should be serialized (I wrote a custom formatter)

My problem: When I try to serialize the B elements (so step 1 is done), the serializer crashes with the message
java.lang.NullPointerException: Invalid context: A_element returns B_element


I suppose, the wrong serializer is used (which makes sense, cause the Generator is run from the A context, which does not know B, as such the A Injector ist used).

Any idea how I could tackle this problem? Is there a way to create a B-serializer from within the A DSL?

For my Unit-Test, I wrote a special InjectorProvider in order to use both language contexts', something like this:

class MultiDslInjectorProvider extends ADslInjectorProvider {

	override protected internalCreateInjector() {
		new ADslStandaloneSetup().createInjectorAndDoEMFRegistration
		return new BDslStandaloneSetup().createInjectorAndDoEMFRegistration
	}

}


Maybe I have to use an injector like this in my non-test code as well?

Bests,
Konrad
Re: Creating Serializer for different DSL [message #1817249 is a reply to message #1817248] Tue, 19 November 2019 09:16 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14666
Registered: July 2009
Senior Member
hi,

you can use IGlobalServiceProvider to obtain stuff from another DSL


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Creating Serializer for different DSL [message #1817258 is a reply to message #1817249] Tue, 19 November 2019 13:18 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
Thank you, this works fine. :)

However, I now face a more fundamental problem in my approach:

In order to build my B instances, I ...
1. compile an EMF B model out of my A model. The B elements are linkes with each other.
2. then I serialize the B elements using the default serializer.

This works fine in my unit tests without Eclipse support (so outside the .ui-projects).

However, in Eclipse, I receiver errors when the Serializer tries to serialize cross-references from one B element to another, which might not have been serialized, yet. The problem is, that the referenced object cannot be found in the scope and thus cannot be serialized.

Do you have any hints how I could tackle this problem? I do not fully understand why this happens with Eclipse Support (although I understand that the underlying containers / classpath concept is different), but not when running in standalone, i.e., test.

Any help would be appreciated.

Re: Creating Serializer for different DSL [message #1817259 is a reply to message #1817258] Tue, 19 November 2019 13:27 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14666
Registered: July 2009
Senior Member
you should create your resourceset with

- IResourceSetProvider

and initialize it with

- LiveScopeResourceSetInitializer

also make sure all relevant resoures are added to the resourceset if they are dirty


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Creating Serializer for different DSL [message #1817261 is a reply to message #1817259] Tue, 19 November 2019 13:36 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
Wow, thanks for your quick reply. Although I do not fully understand:

Right now I add the generated B elements to the resource set provided by the A Builder in doGenerate (i.e., ADslGenerator.doGenerate). This resource set already contains all A elements, to which I need to reference, too. Is this the wrong approach?

Do you mean I should NOT add the B elements to this resource set, but instead to a new one which I initialize with the LiveScopeResourceSetInitializer. Do I understand you correctly?

Then, I should add all resources from the resourceSet provided by the builder (the set that contains all the A elements) to the new resource set?
Re: Creating Serializer for different DSL [message #1817269 is a reply to message #1817261] Tue, 19 November 2019 16:05 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14666
Registered: July 2009
Senior Member
the resources that need to see each other should have proper uris and be in the same resourceset

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Creating Serializer for different DSL [message #1817273 is a reply to message #1817269] Tue, 19 November 2019 17:34 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
Yeah, I already checked that. The freshly generated B elements are all present in the rset, with entries like this:
uri='platform:/resource/myProject/tdm/gen/<package>/myBfile.bdsl', org.eclipse.xtext.linking.lazy.LazyLinkingResource@6e85bd12


However, they are not found in the global scope I create for those.

Deeper debugging shows, that a ContainerState is used which refers to an inner JavaProjectsState, as I use the library approach promoted in your book (i.e., the project is a java project and my plugin also provides a libary of well-known B-items).

I guess, from the URI I created for the "virtual" (i.e., not yet serialized) resources, in particular the part
platform:/resource/myProject/tdm/gen/
the global scope assumes, that the resources must be contained in the JavaProjectState, which then looks into the mentioned folder, only to find nothing. So the scope does not contain those items.

Is my assumption right? How should the URIs of such "virtual", i.e., not yet generated, resources look like to make them visible under Eclipse?

Best regards!
Re: Creating Serializer for different DSL [message #1817274 is a reply to message #1817273] Tue, 19 November 2019 17:49 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14666
Registered: July 2009
Senior Member
how do you create and populate the resourceset?
what is the message you get?

LiveScopeResourceSetInitializer
should take case that the resourcset and not the index only is considered


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Tue, 19 November 2019 17:58]

Report message to a moderator

Re: Creating Serializer for different DSL [message #1817275 is a reply to message #1817274] Tue, 19 November 2019 18:03 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
- I first get an rset which contains all A items
- from these, I create new B items
- for each of these B items, I create a new resource and add it to the rset mentioned above. The code looks as follows:

		private def createFile(ResourceSet rset, BItem item) {
			val itemPath = item.expectedPath
			val res = rset.createResource(URI.createURI("platform:/resource/myProject/tdm/gen/"+itemPath))
			res.contents.add(doc)
	
			return res
		}


The error message is as follows:
1    [Worker-0: Building workspace] ERROR org.eclipse.xtext.builder.BuilderParticipant  - Error during compilation of 'platform:/resource/myProject/AItems/<path>.adsl'.
java.lang.RuntimeException: No EObjectDescription could be found in Scope BItem1.ref for BItem2'<package>'.members[0]->BItem3'<name>'
Semantic Object: BItem2'<package>'.members[0]->BItem3'<name>'.connections[0]->BItem1
URI: platform:/resource/myProject/tdm/gen/<path>/<filename>.bdsl
EStructuralFeature: bmetamodel::BItem1.ref
	at org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic$ExceptionThrowingAcceptor.accept(ISerializationDiagnostic.java:131)
	at org.eclipse.xtext.serializer.tokens.CrossReferenceSerializer.getCrossReferenceNameFromScope(CrossReferenceSerializer.java:138)
	at org.eclipse.xtext.serializer.tokens.CrossReferenceSerializer.serializeCrossRef(CrossReferenceSerializer.java:111)
	at org.eclipse.xtext.serializer.acceptor.SequenceFeeder.getToken(SequenceFeeder.java:482)
	at org.eclipse.xtext.serializer.acceptor.SequenceFeeder.accept(SequenceFeeder.java:245)

[Updated on: Tue, 19 November 2019 18:05]

Report message to a moderator

Re: Creating Serializer for different DSL [message #1817276 is a reply to message #1817275] Tue, 19 November 2019 18:09 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
Regarding LiveScopeResourceSetInitializer: Under Eclipse (not standalone) I create a new rset instead of using the provided one directly, as you suggested. The code looks as follows (the method convert is called witch the original A-resourceSet as a parameter).

The method takes the resources from the unconverted rset and pushes them to the converted one. Then the converted one is returned.



	@Inject
	LiveScopeResourceSetInitializer rsetInitializer
	
	@Inject
	IResourceSetProvider rsetProv

	override convert(ResourceSet rset) {
		
		val firstRes = rset.resources.head
		val proj = getIProject(firstRes);
		
		if (proj === null)
			return null;
			
		val rslt = rsetProv.get(proj)
		
		rsetInitializer.initialize(rset)
		
		val temp = newArrayList
		for (r : rset.resources) {
			temp.add(r)
		}
		for (r : temp) {
			rslt.resources.add(r)
		}
		
		
		return rslt
	}
Re: Creating Serializer for different DSL [message #1817278 is a reply to message #1817276] Tue, 19 November 2019 18:34 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14666
Registered: July 2009
Senior Member
i assume you have to load the original resource a second time into the new resource set
unfortunatly i dont have the time to build up an example

i also dont know how you did the libary thing.
there is JavaProjectResourceSetInitializer too


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Tue, 19 November 2019 18:41]

Report message to a moderator

Re: Creating Serializer for different DSL [message #1817280 is a reply to message #1817278] Tue, 19 November 2019 18:53 Go to previous message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
Hi,

thank you, I fixed the problem. You were right, the LiveScopeResourceSetInitializer did the trick. The only remaining problem was that I had a typo in my code, you can see it in my post above. Instead of

		rsetInitializer.initialize(rset)


it should of course be

		rsetInitializer.initialize(rslt)


I found it when checking whether or not the LIVE_SCOPE flag was actually set.

Thank you so much for pointing me towards this flag, I would've never found this solution on my own. :)

Best regards,
Konrad
Previous Topic:Pointers request for string-based microformat in DSL
Next Topic:How to recompile other files when a file validates without error?
Goto Forum:
  


Current Time: Fri Apr 26 16:38:43 GMT 2024

Powered by FUDForum. Page generated in 0.03876 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top