Xtext: DSL reference to attribute - reference

For example
i have a grammar like this one:
Bundle:
'Bundle'
name= ID '{'
car+=Car+
service +=Service*
'}'
;
Car:
'Car'
name=ID
extra+=Extra*
'}'
;
Extra:
name= ID '=' type=STRING
;
Service:
'Service' att=STRING 'for' ref+=Reference*
;
Reference:
//Ref to car oder Ref to Car.Extra
;
In my model i want to create a Service like:
Service "ServiceName" for car1
Service "ServiceName" for car2 (extra1 extra2)
How can i resolve the reference to Extras of a Car?

this can be done with simple cross refs
Service:
'Service' att=STRING 'for' car=[Car] ('(' extras+=[Extra]+ ')')?
;
And a corresponding scope provider
package org.xtext.example.mydsl.scoping
import org.eclipse.emf.ecore.EReference
import org.eclipse.xtext.scoping.IScope
import org.eclipse.xtext.scoping.Scopes
import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider
import org.xtext.example.mydsl.myDsl.Service
class MyDslScopeProvider extends AbstractDeclarativeScopeProvider {
def IScope scope_Service_extras(Service ctx, EReference ref) {
return Scopes.scopeFor(ctx.car.extra)
}
}

Related

Implementing Typescript interfaces in Python

I'm looking for some advice on what's the best way of implementing a set of data value only 'interfaces' in Python that are equivalent to their typescript counterpart (we've got a project where we use both, and want to enforce a consistent interface for their communication, which would be via serialising the python into json to pull into the TS component)
The interfaces will be compositions to keep things modular and simple.
Given a set of TS interfaces defined as:
interface TestOutput {
phantom: string
testDateTime: datetime
author: string
result: boolean
report_summaryFile?: string // the '?' means this field is optional
// ... more values
series: Array<Series>
soloImages: Array<Images>
}
interface Series {
number: number
filter: string
kernel: string
// ... more values
images: Array<TestImage>
}
I was thinking of using dataclasses and doing the following:
from dataclasses import dataclass
from typing import List
import datetime
#dataclass
class TestSeries:
seriesNum: int
modality: str
description: str = ''
#dataclass
class TestOutput:
phantom: str
testDateTime: datetime.datetime
author: str
result: bool
series: List[TestSeries]
soloImages: List[Images]
report_summaryFile: str = ''
Is dataclasses the best approach for this?
pydantic is a good library.
I did something similar, but only for dataclasses - ValidatedDC:
from dataclasses import dataclass
from typing import List
from validated_dc import ValidatedDC
import json
#dataclass
class Series(ValidatedDC):
series_num: int
modality: str
description: str = ''
#dataclass
class Output(ValidatedDC):
phantom: str
date_time: str
author: str
result: bool
series: List[Series]
report_summary_file: str = ''
# For example, by API we got a JSON string:
input_json_string = '''
{
"phantom": "test_phantom",
"date_time": "2020.01.01",
"author": "Peter",
"result": true,
"series": [{
"series_num": 1,
"modality": "test_modality"
}]
}
'''
# Load the string into the dictionary:
input_data = json.loads(input_json_string)
# Then create a dataclass to check the types of values and for the
# convenience of further work with data:
output = Output(**input_data)
# Since valid data were obtained, there are no errors
assert output.get_errors() is None
# Let's say we got data with an error:
input_data['series'][0]['series_num'] = '1' # The string is not an integer!
output = Output(**input_data)
assert output.get_errors()
print(output.get_errors())
# {
# 'series': [
# InstanceValidationError(
# value_repr="{'series_num': '1', 'modal...}",
# value_type=<class 'dict'>,
# annotation=<class '__main__.Series'>, exception=None,
# errors={
# 'series_num': [
# BasicValidationError(
# value_repr='1', value_type=<class 'str'>,
# annotation=<class 'int'>, exception=None
# )
# ]
# }
# ),
# ListValidationError(
# item_index=0, item_repr="{'series_num': '1', 'modal...}",
# item_type=<class 'dict'>, annotation=<class '__main__.Series'>
# )
# ]
# }
See here for more details:
https://github.com/EvgeniyBurdin/validated_dc

Decorators plugin missing with polymer-cli

I'm using polymer-cli (v1.9.11) to serve my project while developing it :
polymer-cli serve
But when I use decorators (#customElement) in my js sources like this :
import { LitElement, html, property, customElement } from 'lit-element';
import '#polymer/iron-ajax';
import '#vaadin/vaadin-combo-box';
#customElement('my-element') // HERE
class MyElement extends PolymerElement {
static get properties() {
It raises this error when I request the file :
Error SyntaxError: This experimental syntax requires enabling one of the following parser plugin(s): 'decorators-legacy, decorators' (5:0)
at Parser.raise (/usr/lib/node_modules/polymer-cli/node_modules/babylon/lib/index.js:776:15)
at Parser.expectOnePlugin (/usr/lib/node_modules/polymer-cli/node_modules/babylon/lib/index.js:2098:18)
at Parser.parseDecorator (/usr/lib/node_modules/polymer-cli/node_modules/babylon/lib/index.js:4133:10)
at Parser.parseDecorators (/usr/lib/node_modules/polymer-cli/node_modules/babylon/lib/index.js:4115:28)
at Parser.parseStatement (/usr/lib/node_modules/polymer-cli/node_modules/babylon/lib/index.js:3959:12)
at Parser.parseBlockOrModuleBlockBody (/usr/lib/node_modules/polymer-cli/node_modules/babylon/lib/index.js:4513:23)
at Parser.parseBlockBody (/usr/lib/node_modules/polymer-cli/node_modules/babylon/lib/index.js:4500:10)
at Parser.parseTopLevel (/usr/lib/node_modules/polymer-cli/node_modules/babylon/lib/index.js:3938:10)
at Parser.parse (/usr/lib/node_modules/polymer-cli/node_modules/babylon/lib/index.js:5304:17)
at Object.parse (/usr/lib/node_modules/polymer-cli/node_modules/babylon/lib/index.js:10083:24) {
pos: 138,
loc: Position { line: 5, column: 0 },
missingPlugin: [ 'decorators-legacy', 'decorators' ]
}
So I'm wondering where I should declare one of these plugins ?

Groovy : multiple loops in template engine using GStringTemplateEngine()

This question is in continuation with earlier question I have posted before.
To enhance my templates further I need to have multiple loops in the template engines and the values need to be replaced from the HashMap Variables that were derived from a configuration file.
My HashMap looks something like this, let say envVar:
envVar = [
PROJECT:name,
env:[
[name:param1, value:value1],
[name:param2, value:value2],
[name:param3, value:value3]],
ports:[
[protocol:port1, port:1000],
[protocol:port2, port:2000]]
]
My template engine looks like this:
- env:
<< NEED TO LOOP HERE WITH env variables
- name : param1
value : value1
....
>>
project: "${PROJECT}"
......
......
......
ports:
<< NEED TO LOOP HERE WITH ports variables
- port: 1000
protocol : port1
....
>>
Code snippet is described below.
def f = new File('output.template')
def engine = new groovy.text.GStringTemplateEngine()
//....
//envVar are derived from another file
//....
def Template = engine.createTemplate(f).make(envVar)
println "${Template}"
Can someone explain me how to modify the above code snippet and templates to make sure the envVar will be replaced properly in the template engine.
You need to do an each for every variable. Your template file needs to look like this:
#cat output.template
- env:<% env.each { v -> %>
- name : ${v.name}
value : ${v.value}<% } %>
project: "${PROJECT}"
......
......
......
ports:<% ports.each { v -> %>
- port: ${v.port}
protocol: ${v.protocol}<% } %>
Then, your main script should look like this:
def f = new File('output.template')
def engine = new groovy.text.GStringTemplateEngine()
def envVar = [
PROJECT: name,
env:[
[name:'param1', value:'value1'],
[name:'param2', value:'value2'],
[name:'param3', value:'value3']
],
ports:[
[protocol:'port1', port:1000],
[protocol:'port2', port:2000]
]
]
def Template = engine.createTemplate(f).make(envVar)
println "${Template}".trim()
output:
#cat output.template
- env:
- name : param1
value : value1
- name : param2
value : value2
- name : param3
value : value3
project: "projectName"
......
......
......
ports:
- port: 1000
protocol: port1
- port: 2000
protocol: port2
to navigate through your env variable you can use the following:
envVar.env.each{
println "name : ${it.name}"
println "value : ${it.value}"
}
envVar.ports.each{
println "port : ${it.port}"
println "protocol : ${it.protocol}"
}

Failing scripts in groovy using Grab

The following groovy scripts fail using command line
#Grab("org.apache.poi:poi:3.9")
println "test"
Error:
unexpected token: println # line 2, column 1.
println "test"
^
1 error
Removing the Grab, it works!
Anything I missed?
$>groovy -v
Groovy Version: 2.1.7 JVM: 1.7.0_25 Vendor: Oracle Corporation OS: Linux
Annotations can only be applied to certain targets. See SO: Why can't I do a method call after a #Grab declaration in a Groovy script?
#Grab("org.apache.poi:poi:3.9")
dummy = null
println "test"
Alternatively you can use grab as a method call:
import static groovy.grape.Grape.grab
grab(group: "org.apache.poi", module: "poi", version: "3.9")
println "test"
For more information refer to Groovy Language Documentation > Dependency management with Grape.
File 'Grabber.groovy'
package org.taste
import groovy.grape.Grape
//List<List[]> artifacts => [[<group>,<module>,<version>,[<Maven-URL>]],..]
static def grab (List<List[]> artifacts) {
ClassLoader classLoader = new groovy.lang.GroovyClassLoader()
def eal = Grape.getEnableAutoDownload()
artifacts.each { artifact -> {
Map param = [
classLoader: classLoader,
group : artifact.get(0),
module : artifact.get(1),
version : artifact.get(2),
classifier : (artifact.size() < 4) ? null : artifact.get(3)
]
println param
Grape.grab(param)
}
}
Grape.setEnableAutoDownload(eal)
}
Usage :
package org.taste
import org.taste.Grabber
Grabber.grab([
[ "org.codehaus.groovy.modules.http-builder", "http-builder", '0.7.1'],
[ "org.postgresql", "postgresql", '42.3.1', null ],
[ "com.oracle.database.jdbc", "ojdbc8", '12.2.0.1', null]
])

changing startup MVC group in Application.groovy issue

I've created new Groffin module using IntelliJ. I was prompted for create-app command.
Creating a module was fine, and as you know, by default, when you ran an app, it shows applet with default content "Content goes here".
Next, I've added a second login MVC group in Application.groovy:
application {
title = 'Soms'
startupGroups = ['login']
// Should Griffon exit when no Griffon created frames are showing?
autoShutdown = true
// If you want some non-standard application class, apply it here
//frameClass = 'javax.swing.JFrame'
}
mvcGroups {
// MVC Group for "soms"
'soms' {
model = 'soms.SomsModel'
view = 'soms.SomsView'
controller = 'soms.SomsController'
}
// MVC Group for "login"
'login' {
model = 'soms.LoginModel'
view = 'soms.LoginView'
controller = 'soms.LoginController'
}
}
I've also created:
LoginModel.groovy (groovy class)
LoginController.groovy (groovy class)
LoginView.groovy (groovy script)
in the corresponding folders.
When I run project, it's giving errors:
Base Directory: D:\work\griffon\soms Running script
C:\Griffon-1.2.0\scripts\RunApp.groovy Resolving dependencies...
Dependencies resolved in 633ms. Environment set to development
Resolving framework plugin dependencies ... Framework plugin
dependencies resolved in 1114 ms. Resolving plugin dependencies ...
Plugin dependencies resolved in 741 ms. [griffonc] Compiling 1 source
file to d:\Users\akarasaev.griffon\1.2.0\projects\soms\classes\main
Launching application ... 2013-04-15 10:26:44,788 [main] INFO
griffon.swing.SwingApplication - Initializing all startup groups:
[login] 2013-04-15 10:26:46,311 [AWT-EventQueue-0] ERROR
org.codehaus.griffon.runtime.builder.UberBuilder - An error occurred
while building soms.LoginView#34a083f2
groovy.lang.MissingPropertyException: No such property: CENTER for
class: org.codehaus.griffon.runtime.builder.UberBuilder at
org.codehaus.griffon.runtime.builder.UberBuilder.getProperty(UberBuilder.groovy:187)
at
org.codehaus.griffon.runtime.builder.UberInterceptorMetaClass.getProperty(UberInterceptorMetaClass.groovy:210)
at soms.LoginView.run(LoginView.groovy:18) at
org.codehaus.griffon.runtime.builder.UberInterceptorMetaClass.invokeMethod(UberInterceptorMetaClass.groovy:152)
at
org.codehaus.griffon.runtime.builder.UberBuilder.build(UberBuilder.groovy:160)
at
org.codehaus.griffon.runtime.core.AbstractMVCGroup$1.run(AbstractMVCGroup.java:129)
2013-04-15 10:26:46,324 [main] ERROR
griffon.util.GriffonExceptionHandler - Uncaught Exception
groovy.lang.MissingPropertyException: No such property: CENTER for
class: org.codehaus.griffon.runtime.builder.UberBuilder at
org.codehaus.griffon.runtime.builder.UberBuilder.getProperty(UberBuilder.groovy:187)
at
org.codehaus.griffon.runtime.builder.UberInterceptorMetaClass.getProperty(UberInterceptorMetaClass.groovy:210)
at soms.LoginView.run(LoginView.groovy:18) at
org.codehaus.griffon.runtime.builder.UberInterceptorMetaClass.invokeMethod(UberInterceptorMetaClass.groovy:152)
at
org.codehaus.griffon.runtime.builder.UberBuilder.build(UberBuilder.groovy:160)
at
org.codehaus.griffon.runtime.core.AbstractMVCGroup$1.run(AbstractMVCGroup.java:129)
The same error happens when I try to run from command prompt.
Environment:
Win 7 Pro, 64-bit
IntelliJ IDEA ver 12.1
Griffon-1.2.0 JDK 1.6
LoginModel.groovy:
package soms
import groovy.beans.Bindable
import griffon.transform.PropertyListener
import static griffon.util.GriffonNameUtils.isBlank
#Bindable
#PropertyListener(enabler)
class LoginModel {
String login
String password
boolean submitEnabled
boolean resetEnabled
private enabler = { e ->
submitEnabled = !isBlank(login) && !isBlank(password)
resetEnabled = !isBlank(login) || !isBlank(password)
}
}
LoginView.groovy:
package soms
application(title: 'Login',
preferredSize: [320, 240],
pack: true,
locationByPlatform: true
)
borderLayout()
panel(constraints: CENTER, border: emptyBorder(6)) {
gridLayout(rows:3, columns:2, hgap:6, vgap:6)
label: 'login:'
textField columns: 20, text: bind(target: model, 'login', mutual: true)
label: 'password:'
textField columns: 20, text: bind(target: model, 'password', mutual: true)
}
panel(constraints: SOUTH){
gridLayout(rows:1, cols:2, hgap:6, vgap:6 )
button('reset', actionPerformed: controller.reset, enabled: bind{model.resetEnabled})
button('submit', actionPerformed: controller.reset, enabled: bind{model.submitEnabled})
}
LoginController.groovy:
package soms
class LoginController {
def model
def view
}
I found out that my LoginController.groovy was incomplete.
Now it's working and the correct LoginController.groovy as follows:
package soms
import griffon.transform.Threading
class LoginController {
def model
def view
#Threading(Threading.Policy.SKIP)
def reset = {
model.login = ''
model.password = ''
}
def submit = {
println "Login: ${model.login}"
println "Password: ${model.password}"
}
}

Resources