Home » Modeling » TMF (Xtext) » Using both AbstractModelInferrer and IGenerator implementations(Is it possible to have both generators in the same Xtext project?)
|
Re: Using both AbstractModelInferrer and IGenerator implementations [message #1053826 is a reply to message #1053825] |
Tue, 07 May 2013 18:41   |
|
On 05/07/2013 08:34 PM, Leandro Marques wrote:
> I created a gammar for a language I am constructing using Xtext and I
> would like to add a code generator. At first I need to generate Java
> code so a AbstractModelInferer is most appropriate and at last I need to
> generate Xtend code so I guess a IGenerator would be more appopriate. Is
> it possible to have both generators (ModelInferer and IGenerator) in the
> same Xtext project?
>
> I tried creating both, but only the IGenerator implementation have been
> used. To use a IGenerator implementation I added a method to my
> RuntimeModule class to inject a instance of my IGenerator implementation.
>
> In addition, I would like to learn more details about the
> AbstractModelInferer but it is hard to find detailed information on how
> to use it. Is there any tutorial that could help me?
>
> Thanks in advance,
>
As far as I understand you want to use both JvmModelGenerator (which is
the default generator relying on the JvmModelInferrer which is
automatically bound when using Xbase) and an additional custom generator
to generate other things?
If so you can implement your own generator strategies in, say,
MyCustomGenerator, and then bind another generator (say MyDslGenerator)
which delegates to both JvmModelGenerator and MyCustomGenerator (both
instances must be injected).
For instance
class MyDslGenerator implements IGenerator {
@Inject JvmModelGenerator g1
@Inject MyCustomGenerator g2
generate(...) {
g1.generate(...)
g2.generate(...)
}
}
and in the runtime module you bind MyDslGenerator.
hope this helps
Lorenzo
--
Lorenzo Bettini, PhD in Computer Science, DI, Univ. Torino
HOME: http://www.lorenzobettini.it
HOME: http://www.lorenzobettini.it
TDD Book: https://leanpub.com/tdd-buildautomation-ci
Xtext Book: https://www.packtpub.com/application-development/implementing-domain-specific-languages-xtext-and-xtend-second-edition
|
|
| | | |
Re: Using both AbstractModelInferrer and IGenerator implementations [message #1057834 is a reply to message #1053834] |
Thu, 09 May 2013 08:03   |
Dirk Deyne Messages: 8 Registered: May 2013 |
Junior Member |
|
|
Leandro:
Here's how I use IGenerator & Inferrer together
... it was not that easy
- create an IOutputConfigurationProvider
public class YourOutputProvider implements IOutputConfigurationProvider {
public static final String DEFAULT = "DEFAULT_OUTPUT";
public static final String OTHER = "OTHER";
@Override
public Set<OutputConfiguration> getOutputConfigurations() {
OutputConfiguration defaultOutput = new OutputConfiguration(DEFAULT);
defaultOutput.setDescription("Default Folder");
defaultOutput.setOutputDirectory("./src-gen");
defaultOutput.setOverrideExistingResources(true);
defaultOutput.setCreateOutputDirectory(true);
defaultOutput.setCleanUpDerivedResources(true);
defaultOutput.setSetDerivedProperty(true);
OutputConfiguration otherOutput = new OutputConfiguration(OTHER);
otherOutput.setDescription("Other Folder");
otherOutput.setOutputDirectory("./src-gen/other");
otherOutput.setOverrideExistingResources(true);
otherOutput.setCreateOutputDirectory(true);
otherOutput.setCleanUpDerivedResources(true);
otherOutput.setSetDerivedProperty(true);
}
notice the properties you can set: overrideExistingResources,...
- create an Adapter
public class OutputConfigurationAdapter implements Adapter {
private String outputConfigurationName;
public OutputConfigurationAdapter(String outputConfigurationName) {
this.outputConfigurationName = outputConfigurationName;
}
public String getOutputConfigurationName() {
return outputConfigurationName;
}
@Override
public void notifyChanged(Notification notification) {
}
@Override
public Notifier getTarget() {
return null;
}
@Override
public void setTarget(Notifier newTarget) {
}
@Override
public boolean isAdapterForType(Object type) {
return false;
}
}
- create an IFileSystemAccess
public class OutputConfigurationFileSystemAccess implements IFileSystemAccess,
IFileSystemAccessExtension, IFileSystemAccessExtension2 {
protected IFileSystemAccess fsa;
protected String outputConfigurationName;
protected OutputConfigurationFileSystemAccess(IFileSystemAccess fsa,
String outputConfigurationName) {
this.fsa = fsa;
this.outputConfigurationName = outputConfigurationName;
}
@Override
public void generateFile(String fileName, CharSequence contents) {
fsa.generateFile(fileName, outputConfigurationName, contents);
}
@Override
public void generateFile(String fileName, String outputConfiguration,
CharSequence contents) {
fsa.generateFile(fileName, outputConfigurationName, contents);
}
@Override
public void deleteFile(String fileName) {
deleteFile(fileName, outputConfigurationName);
}
@Override
public void deleteFile(String fileName,
String ignoredOutputConfigurationName) {
((IFileSystemAccessExtension) fsa).deleteFile(fileName,
outputConfigurationName);
}
@Override
public URI getURI(String fileName, String outputConfiguration) {
return ((IFileSystemAccessExtension2) fsa).getURI(fileName,
outputConfigurationName);
}
@Override
public URI getURI(String fileName) {
return ((IFileSystemAccessExtension2) fsa).getURI(fileName,
outputConfigurationName);
}
}
- create your IGenerator
class YourIGenerator implements IGenerator {
override doGenerate(Resource input, IFileSystemAccess fsa) {
...
}
- create your Inferrer
class YourModelInferrer extends AbstractModelInferrer {
def dispatch void infer(Foo foo, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
var fooClass = foo.toClass(foo.name)
fooClass.eAdapters.add(new OutputConfigurationAdapter(YourOutputProvider::DEFAULT))
acceptor.accept(fooClass)
.initializeLater([
....
])
var barClass = foo.toClass(foo.name)
barClass.eAdapters.add(new OutputConfigurationAdapter(YourOutputProvider::OTHER))
acceptor.accept(fooClass)
.initializeLater([
// nothing to do here done in YourIGenerator
])
adding the different eAdapters is important here cfr YourOutputProvider::DEFAULT & YourOutputProvider::OTHER
- create an JvmModelGenerator
public class YourJvmModelGenerator extends JvmModelGenerator {
@Inject private YourGenerator generator;
@Override
public void doGenerate(Resource input, IFileSystemAccess fsa) {
EList<EObject> contents = input.getContents();
for (final EObject obj : contents) {
String outputConfiguration = null;
for (Adapter adapter : obj.eAdapters()) {
if (adapter instanceof OutputConfigurationAdapter) {
outputConfiguration = ((OutputConfigurationAdapter) adapter).getOutputConfigurationName();
break;
}
}
if (outputConfiguration == YourOutputProvider.DEFAULT) {
this.internalDoGenerate(obj, fsa); // <= GOTO INFERRER
} else if (outputConfiguration == YourOutputProvider.OTHER) {
generator.doGenerate(input, fsa); // <= GOTO IGENERATOR
}
}
}
}
here you make the switch to your Inferrer & Igenerator
- configure your RuntimeModule
@Override
public void configure(Binder binder) {
super.configure(binder);
binder.bind(IOutputConfigurationProvider.class)
.to(YourOutputProvider.class)
.in(Singleton.class);
}
@Override
public Class<? extends IGenerator> bindIGenerator() {
return OutputConfigurationAwaredGenerator.class;
}
[Updated on: Thu, 09 May 2013 08:19] Report message to a moderator
|
|
|
Re: Using both AbstractModelInferrer and IGenerator implementations [message #1057859 is a reply to message #1057834] |
Thu, 09 May 2013 11:31   |
|
Oh, I think because in your case you needed to generate differently
according to specific inferred elements (I had missed that part)... in
my case I just wanted to generate also xml besides Java code so I did
not need to specify different output configurations right in the inferrer...
On 05/09/2013 10:03 AM, Dirk Deyne wrote:
> Lorenzo: Here's how I use IGenerator & Inferrer together .. it was not
> that easy
>
> - create an IOutputConfigurationProvider
>
> public class YourOutputProvider implements IOutputConfigurationProvider {
>
> public static final String DEFAULT = "DEFAULT_OUTPUT";
> public static final String OTHER = "OTHER";
>
> @Override
> public Set<OutputConfiguration> getOutputConfigurations() {
> OutputConfiguration defaultOutput = new
> OutputConfiguration(DEFAULT);
> defaultOutput.setDescription("Default Folder");
> defaultOutput.setOutputDirectory("./src-gen");
> defaultOutput.setOverrideExistingResources(true);
> defaultOutput.setCreateOutputDirectory(true);
> defaultOutput.setCleanUpDerivedResources(true);
> defaultOutput.setSetDerivedProperty(true);
>
> OutputConfiguration otherOutput = new OutputConfiguration(OTHER);
> otherOutput.setDescription("Other Folder");
> otherOutput.setOutputDirectory("./src-gen/other");
> otherOutput.setOverrideExistingResources(true);
> otherOutput.setCreateOutputDirectory(true);
> otherOutput.setCleanUpDerivedResources(true);
> otherOutput.setSetDerivedProperty(true);
> }
>
>
> notice the properties you can set: overrideExistingResources,...
>
> - create an Adapter
>
> public class OutputConfigurationAdapter implements Adapter {
>
> private String outputConfigurationName;
>
> public OutputConfigurationAdapter(String outputConfigurationName) {
> this.outputConfigurationName = outputConfigurationName;
> }
>
> public String getOutputConfigurationName() {
> return outputConfigurationName;
> }
>
> @Override
> public void notifyChanged(Notification notification) {
> }
>
> @Override
> public Notifier getTarget() {
> return null;
> }
>
> @Override
> public void setTarget(Notifier newTarget) {
> }
>
> @Override
> public boolean isAdapterForType(Object type) {
> return false;
> }
>
> }
>
>
> - create an IFileSystemAccess
>
> public class OutputConfigurationFileSystemAccess implements
> IFileSystemAccess,
> IFileSystemAccessExtension, IFileSystemAccessExtension2 {
> protected IFileSystemAccess fsa;
> protected String outputConfigurationName;
>
> protected OutputConfigurationFileSystemAccess(IFileSystemAccess fsa,
> String outputConfigurationName) {
> this.fsa = fsa;
> this.outputConfigurationName = outputConfigurationName;
> }
>
> @Override
> public void generateFile(String fileName, CharSequence contents) {
> fsa.generateFile(fileName, outputConfigurationName, contents);
> }
>
> @Override
> public void generateFile(String fileName, String outputConfiguration,
> CharSequence contents) {
> fsa.generateFile(fileName, outputConfigurationName, contents);
> }
>
> @Override
> public void deleteFile(String fileName) {
> deleteFile(fileName, outputConfigurationName);
> }
>
> @Override
> public void deleteFile(String fileName,
> String ignoredOutputConfigurationName) {
> ((IFileSystemAccessExtension) fsa).deleteFile(fileName,
> outputConfigurationName);
> }
>
> @Override
> public URI getURI(String fileName, String outputConfiguration) {
> return ((IFileSystemAccessExtension2) fsa).getURI(fileName,
> outputConfigurationName);
> }
>
> @Override
> public URI getURI(String fileName) {
> return ((IFileSystemAccessExtension2) fsa).getURI(fileName,
> outputConfigurationName);
> }
> }
>
>
> - create your IGenerator
>
> class YourIGenerator implements IGenerator {
>
>
> override doGenerate(Resource input, IFileSystemAccess fsa) {
> ...
> }
>
>
>
> - create your Inferrer
>
> class YourModelInferrer extends AbstractModelInferrer {
>
> def dispatch void infer(Foo foo, IJvmDeclaredTypeAcceptor acceptor,
> boolean isPreIndexingPhase) {
> var fooClass = foo.toClass(foo.name)
> fooClass.eAdapters.add(new
> OutputConfigurationAdapter(YourOutputProvider::DEFAULT))
> acceptor.accept(fooClass)
> .initializeLater([ ....
> ])
>
> var barClass = foo.toClass(foo.name)
> barClass.eAdapters.add(new
> OutputConfigurationAdapter(YourOutputProvider::OTHER))
> acceptor.accept(fooClass)
> .initializeLater([ // nothing to do
> here done in YourIGenerator
> ])
>
>
> adding the different eAdapters is important here cfr
> YourOutputProvider::DEFAULT & YourOutputProvider::OTHER
>
>
>
> - create an JvmModelGenerator
>
> public class YourJvmModelGenerator extends JvmModelGenerator {
>
> @Inject private YourGenerator generator;
>
> @Override
> public void doGenerate(Resource input, IFileSystemAccess fsa) {
> EList<EObject> contents = input.getContents();
> for (final EObject obj : contents) {
> String outputConfiguration = null;
> for (Adapter adapter : obj.eAdapters()) {
> if (adapter instanceof OutputConfigurationAdapter) {
> outputConfiguration = ((OutputConfigurationAdapter)
> adapter).getOutputConfigurationName();
> break;
> }
> }
> if (outputConfiguration == YourOutputProvider.DEFAULT) {
> this.internalDoGenerate(obj, fsa); // <= GOTO INFERRER
> } else if (outputConfiguration == YourOutputProvider.OTHER) {
> generator.doGenerate(input, fsa); // <= GOTO IGENERATOR
> } }
> }
>
> }
>
> here you make the switch to your Inferrer & Igenerator
>
> - configure your RuntimeModule
>
> @Override
> public void configure(Binder binder) {
> super.configure(binder);
> binder.bind(IOutputConfigurationProvider.class)
> .to(YourOutputProvider.class)
> .in(Singleton.class);
> }
>
> @Override
> public Class<? extends IGenerator> bindIGenerator() {
> return OutputConfigurationAwaredGenerator.class;
> }
>
>
--
Lorenzo Bettini, PhD in Computer Science, DI, Univ. Torino
HOME: http://www.lorenzobettini.it
HOME: http://www.lorenzobettini.it
TDD Book: https://leanpub.com/tdd-buildautomation-ci
Xtext Book: https://www.packtpub.com/application-development/implementing-domain-specific-languages-xtext-and-xtend-second-edition
|
|
| |
Goto Forum:
Current Time: Sat Sep 23 08:55:40 GMT 2023
Powered by FUDForum. Page generated in 0.02187 seconds
|