I've defined a simple Xtext grammar which looks like this (simplified):
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
System:
'Define System'
(
'Define Components' '{' components+=Component+ '}'
)
'End'
;
Component:
'Component' name=ID 'Value' value=Double ';'
;
Double returns ecore::EDouble:
'-'? INT? '.' INT
;
The problem I like to solve is - how can I convert a simple Java Object to a valid xtext file?
To simplify my problem, lets say we create a list of components in Java:
List<Component> components = new ArrayList<Component>();
components.add(new Component("FirstComponent", 1.0));
components.add(new Component("SecondComponent", 2.0));
components.add(new Component("ThirdComponent", 3.0));
The output-file I like to create should look like this:
Define System
Define Components {
Component FirstComponent Value 1.0;
Component SecondComponent Value 2.0;
Component ThirdComponent Value 3.0;
}
End
It is important that this file is checked by the xtext grammar, so that it's valid.
I Hope you have any ideas for me. Here are some of mine, but so far I don't know how to implement them:
Idea #1:
I know how to read and write a file. In my head one solution could look like this:
I have the list in my Java code, now I like to write a file which looks like the output-file above. Afterwards I like to read this file and check for errors by the grammar. How can I do this?
Idea #2:
If I imagine I would create a xml file out of Java code using JDOM, I wish I could do the same in xtext. Just define a parent "Define System" which ends with "End" (see my output-file) and then add a child "Define Components {" which ends with "}" and then add the children to this, e.g. "Component FirstComponent Value 1.0;". I hope this isn't confusing :-)
Idea #3:
I could use a template like the following and add children between the braces "{" ... "}":
Define System
Define Components { ... }
End
Btw: I already tried Linking Xtext with StringTemplate code generator, but it is kind of another problem. Hope you have any ideas.
You can use Xtext's serialization for this. Unlike Java's default Serialization API, Xtext's implementation creates the DSL.
The code would look like so:
Injector injector = Guice.createInjector(new my.dsl.MyDslRuntimeModule());
Serializer serializer = injector.getInstance(Serializer.class);
String s = serializer.serialize(eobj);
where eobj is an instance of System.
If you have written a formatter for your DSL, the output will also look nice.
Related blog post: Implement toString with Xtext's Serializer
Xtext provides an EMF-based AST for you. This AST features classes like System and Component together with their corresponding attributes, such as the Value attribute of Component. These classes are available in the src-gen folder of your language project.
To instantiate these objects, you have to use a factory class, also available in the same package.
To serialize such an AST, it is possible to reuse standard EMF tooling by creating a resource, and saving the contents. During serialization the AST is validated.
System system = ...; //Creating the AST programmatically
ResourceSet set = new ResourceSetImpl();
Resource resource = set.createResource(URI.create...URI("filename")); //Initializing an EMF resource that represents a file
resource.getContents.add(system); //adding your AST to the file resource
resource.save();
Minor remark: if you are not developing an Eclipse plug-in, you have to initialize the Xtext tooling by calling generated «YourLanguage»StandaloneSetup.doSetup() static method.
For other programmatic validation options, you can have a look at the ParseHelper and ValidatorTester classes used by the Xtext test framework.
Related
I am working on an app that processes incoming Json's and I want to easily extract the json data and convert it to a DSL language I'v created using Xtext. My goal is to be able to later convert this data to a String that is based on my. I could probably just extract the data and manually add it to a big String variable ,but I want to do this programmatically. So ,does Xtext supports that. Is there any way to convert data to an Xtext object and later to a String (I am looking for something like json object classes)
Thanks!
If I correctly understand your question, you have already created an Xtext grammar that syntactically 'looks like' JSON.
In that case, the Xtext generated parser will be able to parse documents that follow the grammar specification (meaning they are both valid JSON and valid according to the grammar of your language).
The code that you would write looks as follows:
Package org.something.other
import com.google.inject.Injector;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.resource.XtextResourceSet;
import org.YourDSL.YourDSLStandaloneSetupGenerated;
public class ParseDocument {
public static void main(String[] args) throws IOException {
//First you use dependency injection to register the generated resource factory with EMF
Injector injector = new ourDSLStandaloneSetupGenerated().createInjectorAndDoEMFRegistration();
//Get a resource set object
XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
//Register the generated EMF package
resourceSet.getPackageRegistry().put
(YourDSLPackage.eNS_URI, YourDSLPackage.eINSTANCE);
//Create an new resource with a suitable URI
Resource resource =
resourceSet.getResource(URI.createFileURI("./test.yourdsl"), true);
//You can now programmatically query and manipulate objects according to the metamodel of you DSL
MainClass root = (MainClass)resource.getContents().get(0);
}
That being said, an Xtext parser might be complete overkill depending on what you are trying to do and something like Jackson might be a better fit.
I am trying to create a plugin to generate some java code and write back to the main source module. I was able to create a some simple pojo class using JavaPoet and write to the src/main/java.
To make this useful, it should read the code from src/maim/java folder and analyze the classes using reflection. Look for some annotation then generate some codes. Do I use the SourceTask for this case. Looked like I can only access the classes by the files. Is that possible to read the java classes as the class and using reflection analyze the class?
Since you specified what you want to do:
You'll need to implement an annotation processor. This has absolutely nothing to do with gradle, and a gradle plugin is actually the wrong way to go about this. Please look into Java Annotation Processor and come back with more questions if any come up.
With JavaForger you can read input classes and generate sourcecode based on that. It also provides an API to insert it into existing classes or create new classes based on the input file. In contrast to JavaPoet, JavaForger has a clear separation between code to be generated and settings on where and how to insert it. An example of a template for a pojo can look like this:
public class ${class.name}Data {
<#list fields as field>
private ${field.type} ${field.name};
</#list>
<#list fields as field>
public ${field.type} ${field.getter}() {
return ${field.name};
}
public void ${field.setter}(${field.type} ${field.name}) {
this.${field.name} = ${field.name};
}
</#list>
}
The example below uses a template called "myTemplate.javat" and adds some extra settings like creating the file if it does not exist and changing the path where the file will be created from */path/* to */pathToDto/*. The the path to the input class is given to read the class name and fields and more.
JavaForgerConfiguration config = JavaForgerConfiguration.builder()
.withTemplate("myTemplate.javat")
.withCreateFileIfNotExists(true)
.withMergeClassProvider(ClassProvider.fromInputClass(s -> s.replace("path", "pathToPojo")))
.build();
JavaForger.execute(config, "MyProject/path/inputFile.java");
If you are looking for a framework that allows changing the code more programatticaly you can also look at JavaParser. With this framework you can construct an abstract syntax tree from a java class and make changes to it.
I'm having trouble finding examples of how to implement partials using the Spullara Mustache java implementation. Their github page doesn't seem to have any straight forward partial examples.
In DefaultMustacheFactory I see methods for compilePartial and resolvePartialPath, but I'm not sure if I am supposed to override them or what.
I currently have this, and it works great without partials. TemplateContent contains the raw template html including mustache syntax.
public Mustache compileMustacheTemplate(String templateCode, String templateContent){
return new DefaultMustacheFactory().compile(new StringReader(templateContent),templateCode);
}
Pretty straight forward. But what if template content had {{>partialName}} inside it? I think I need to somehow specify that template content as well.
Do I need to extend DefaultMustacheFactory or possibly another class to specify the name of my partial and the content for it?
I believe I'm just missing something.
Thanks,
Matt
Assuming your template files are stored in a folder 'src/main/resources/org/example/web/' and you have one template "page.html" file referencing two other template files 'header.html' and 'footer.html'. Your template file "page.html" should look like this:
{{> src/main/resources/org/example/web/header.html}}
... some content ...
{{> src/main/resources/org/example/web/footer.html}}
I have a configuration (config.properties) something like
app.rootDir=
app.reportDir=${app.rootDir}/report
The app.rootDir is not a fixed parameter and it must be initialized by external module. I need keep the ${app.reportDir} keep dynamic reference to ${app.rootDir}.
Use pseudo code to illustrate the problem:
// Init the root dir as '/usr/app'
config.setValue('app.rootDir','/usr/app');
// I need the reportDir to be '/usr/app/report'
String reportDir = config.getValue('app.reportDir');
I can write some codes to get this feature but I'd like to know if there is any existing library do this?
I can use properties, yaml, or json as configuration file type, according to the library availability.
I've recently found out about UIMA (http://uima.apache.org/). It looks promising for simple NLP tasks, such as tokenizing, sentence splitting, part-of-speech tagging etc.
I've managed to get my hands on an already configured minimal java sample that is using OpenNLP components for its pipeline.
The code looks like this:
public void ApplyPipeline() throws IOException, InvalidXMLException,
ResourceInitializationException, AnalysisEngineProcessException {
XMLInputSource in = new XMLInputSource(
"opennlp/OpenNlpTextAnalyzer.xml");
ResourceSpecifier specifier = UIMAFramework.getXMLParser()
.parseResourceSpecifier(in);
AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(specifier);
JCas jcas = ae.newJCas();
jcas.setDocumentText("This is my text.");
ae.process(jcas);
this.doSomethingWithResults(jcas);
jcas.reset();
ae.destroy();
}
private void doSomethingWithResults(JCas jcas) {
AnnotationIndex<Annotation> idx = jcas.getAnnotationIndex();
FSIterator<Annotation> it = idx.iterator();
while (it.hasNext()) {
System.out.println(it.next().toString());
}
}
Excerpt from OpenNlpTextAnalyzer.xml:
<delegateAnalysisEngine key="SentenceDetector">
<import location="SentenceDetector.xml" />
</delegateAnalysisEngine>
<delegateAnalysisEngine key="Tokenizer">
<import location="Tokenizer.xml" />
</delegateAnalysisEngine>
The java code produces output like this:
Token
sofa: _InitialView
begin: 426
end: 435
pos: "NNP"
I'm trying to get the same information from each Annotation object that the toString() method uses. I've already looked into UIMA's source code to understand where the values are coming from. My attempts to retrieve them sort of works, but they aren't smart in any way.
I'm struggling to find easy examples that, extract information out of the JCas objects.
I'm looking for a way to get for instance all Annotations produces by my PosTagger or by the SentenceSplitter for further usage.
I guess
List<Feature> feats = it.next().getType().getFeatures();
is a start to get values, but due to UIMA owns classes for primitive types, even the source code of the toString method in the annotation class reads like a slap in the face.
Where do I find java code that uses basic UIMA stuff and where are good tutorials (except javadoc from the framework itself)?
Generate JCas wrapper classes for your annotation types (you can do this using the type system editor UIMA plugin for Eclipse that comes with UIMA). This will provide you with Java classes that you can use to access the annotations - these offer getters and setters for features.
You should have a look at uimaFIT, which provides a more convenient API including convenience methods to retrieve annotations from the JCas, e.g. select(jcas, Token.class) (where Token.class is one of the classes you generated with the type system editor).
You could find some quick-starting Groovy scripts and a collection of UIMA components on the DKPro Core page.
There is material from the UIMA#GSCL 2013 tutorial (slides and sample code) which might be useful for you. Go here and scroll down to "Tutorial".
Disclosure: I'm developer on UIMA, uimaFIT, DKPro Core and co-organizer on the UIMA#GSCL 2013 workshop.