I'd like to have a crossreference inside the name of my Objects.
In my language I will have this:
2. Sentence
....
2.a. sentence
1. sentence
Where 2 is the name of "2. sentence"
Here I'd like that the name of "2.a. sentence" being "2.a" while "2", in "2.a", being a reference to "2. sentence".
I already tried:
(name = ([Step|StepName] '.' CHAR ))
and
(name = (step = [Step|StepName] '.' CHAR))
but I just got errors.
Now I'm looking for changing the implementation files generate by Xtext (I changed the getName() method) but didn't get the results that I want. Since the EObjects contained in "2.a" do not have "2" in then QualifiedName, just "a". If we look in "1. sentence" I would like it to has the QualifiedName "2.a.1"
For the solution of the problem you can see here:
http://www.cs.ru.nl/J.Hooman/DSL/AdvancedXtextManual.pdf
But I will explain it.
First you will creat an IQualifideNameProvider that extends the original IQualifiedNameProvider. Inside this classe you will creat how your QualifiedName should be composed. Here is how I did:
class MyDslQualifiedNameProvider extends DefaultDeclarativeQualifiedNameProvider {
#Inject
IQualifiedNameConverter converter = new
IQualifiedNameConverter.DefaultImpl();
override QualifiedName getFullyQualifiedName(EObject obj) {
if (obj instanceof HelloGreeting) {
val nodes = NodeModelUtils.findNodesForFeature(obj,
MyDslPackage.Literals.HELLO_GREETING__PERSON);
for (node : nodes) {
val text = NodeModelUtils.getTokenText(node);
if (text !== null) {
return converter.toQualifiedName(text);
}
}
}
return super.getFullyQualifiedName(obj);
}
}
This extend code will generate a QualifiedName that is the exactly text of your cross reference HELLO_GREETING_PERSON, if you want to compose you name you will need to get the names of your EObject and concatenate the strings to create the QualifiedName.
For example this is my code, that i add to compose my name:
var a = obj.eContainer();
var FN = (a as UseCase).getName() + "." + text + "." + (obj as Extension).getName();
Then you will need to change you RunTimeModulo adding:
override Class<? extends IQualifiedNameProvider>
bindIQualifiedNameProvider() {
return typeof(MyDslQualifiedNameProvider);
}
inside you class RunTimeModule.
This work for me. Theses codes are exact extract from the PDF above, I just tried to help to understand what need to be done.
Related
I have a nested JSON file, consisting of keys and values which are string only. But the structure of the JSON file is not fixed, so sometimes it could be nested 3 levels, sometimes only 2 levels.
I wonder how i could serialize this in strict mode?
"live" : {
"host" : "localhost",
"somevalue" : "nothing",
"anobject" : {
"one" : "two",
"three" : "four",
"five" : {
"six" : "seven"
}
}
}
If i would know the structure of the JSON, i simply would write my own class for it, but since the keys are not fixed, and also the nesting could be into several levels, i really wonder how i cut put such an object into a specific type.
Any help or hints appreciated
I think invariants will serve you well here. First off, it might be helpful to know that you can type a keyed tree strictly in Hack:
<?hh // strict
class KeyedTree<+Tk as arraykey, +T> {
public function __construct(
private Map<Tk, KeyedTree<Tk, T>> $descendants = Map{},
private ?T $v = null
) {}
}
(It must be a class because cyclic shape definitions are sadly not allowed)
I haven't tried it yet, but type_structures and Fred Emmott's TypeAssert look to also be of interest. If some part of your JSON blob is known to be fixed, then you could isolate the nested, uncertain part and build a tree out of it with invariants. In the limiting case where the whole blob is unknown, then you could excise the TypeAssert since there's no interesting fixed structure to assert:
use FredEmmott\TypeAssert\TypeAssert;
class JSONParser {
const type Blob = shape(
'live' => shape(
'host' => string, // fixed
'somevalue' => string, // fixed
'anobject' => KeyedTree<arraykey, mixed> // nested and uncertain
)
);
public static function parse_json(string $json_str): this::Blob {
$json = json_decode($json_str, true);
invariant(!array_key_exists('anobject', $json), 'JSON is not properly formatted.');
$json['anobject'] = self::DFS($json['anobject']);
// replace the uncertain array with a `KeyedTree`
return TypeAssert::matchesTypeStructure(
type_structure(self::class, 'Blob'),
$json
);
return $json;
}
public static function DFS(array<arraykey, mixed> $tree): KeyedTree<arraykey, mixed> {
$descendants = Map{};
foreach($tree as $k => $v) {
if(is_array($v))
$descendants[$k] = self::DFS($v);
else
$descendants[$k] = new KeyedTree(Map{}, $v); // leaf node
}
return new KeyedTree($descendants);
}
}
Down the road, you'll still have to supplement containsKey invariants on the KeyedTree, but that's the reality with unstructured data in Hack.
I am wondering if I can pass variable to be evaluated as String inside gstring evaluation.
simplest example will be some thing like
def var ='person.lName'
def value = "${var}"
println(value)
I am looking to get output the value of lastName in the person instance. As a last resort I can use reflection, but wondering there should be some thing simpler in groovy, that I am not aware of.
Can you try:
def var = Eval.me( 'new Date()' )
In place of the first line in your example.
The Eval class is documented here
edit
I am guessing (from your updated question) that you have a person variable, and then people are passing in a String like person.lName , and you want to return the lName property of that class?
Can you try something like this using GroovyShell?
// Assuming we have a Person class
class Person {
String fName
String lName
}
// And a variable 'person' stored in the binding of the script
person = new Person( fName:'tim', lName:'yates' )
// And given a command string to execute
def commandString = 'person.lName'
GroovyShell shell = new GroovyShell( binding )
def result = shell.evaluate( commandString )
Or this, using direct string parsing and property access
// Assuming we have a Person class
class Person {
String fName
String lName
}
// And a variable 'person' stored in the binding of the script
person = new Person( fName:'tim', lName:'yates' )
// And given a command string to execute
def commandString = 'person.lName'
// Split the command string into a list based on '.', and inject starting with null
def result = commandString.split( /\./ ).inject( null ) { curr, prop ->
// if curr is null, then return the property from the binding
// Otherwise try to get the given property from the curr object
curr?."$prop" ?: binding[ prop ]
}
How to add a String type field to class (i.e to all instances of that class), like grails add an id and version fields to all domain classes? If it is possible, how to specify the type of field as String / Long etc
EDIT:
The added fields are not updated in DB. how to make them persistent?
With respect to POGO, you can use ExpandoMetaClass to add/override a property/field/constructor.
class Foo{
String bar
}
//Add a field to Foo at runtime
//Type is set to String in this case
Foo.metaClass.baz = "Hello World"
//Add a method to Foo at runtime
Foo.metaClass.doSomething = {String str -> str.reverse()}
assert new Foo().baz == "Hello World"
assert new Foo().doSomething("Hello") == "olleH"
For your use case, you may be able to use normal inheritance:
abstract class Base {
// common fields
// constraints for those fields
// etc.
}
class MyDomain extends Base {
}
I found the solution Burt Beckwith offered in this question: add user define properties to a domain class and think this could be a viable option for us in some situations. In testing this, I have a domain with a Map property as described in the referenced question. Here is a simplified version (I have more non-map properties, but they are not relevant to this question):
class Space {
String spaceDescription
String spaceType
Map dynForm
String toString() {
return (!spaceType)?id:spaceType + " (" + spaceDescription + ")"
}
}
I have some instances of space saved with some arbitrary data in the dynForm Map like 'Test1':'abc' and 'Test2':'xyz'.
I am trying to query this data and have succesfully used HQL to filter doing the following:
String className = "Space"
Class clazz = grailsApplication.domainClasses.find { it.clazz.simpleName == className }.clazz
def res = clazz.executeQuery("select distinct space.id, space.spaceDescription from Space as space where space.dynForm['Test1'] = 'abc' " )
log.debug "" + res
I want to know if there is a way to select an individual item from the Map dynForm in a select statement. Somehting like this:
def res = clazz.executeQuery("select distinct space.id, elements(space.dynForm['Test1']) from Space as space where space.dynForm['Test1'] = 'abc' " )
I can select the entire map like this:
def res = clazz.executeQuery("select distinct elements(space.dynForm) from Space as space where space.dynForm['Test1'] = 'abc' " )
But I just want to get a specific instance based on the string idx.
how about to use Criteria, but i don't have any sql server so i haven't tested yet.
def results = Space.createCriteria().list {
dynForm{
like('Test1', 'abc')
}
}
Question: how can I insert a table from C# into 'LuaInterface' script scope using a C# object (preferably anonymous type)?
/// I want to do this, but it does not work
/// (complains that 'test' is userdata and not table
/// when I pass it to pairs() in the script)
//lua["test"] = new { A = 1, B = 2 };
/// another option
/// but building this string is a PITA (actual string is nested and long).
lua.DoString("test = { A = 1, B = 2 }");
// So I have to do this
lua.NewTable("test");
((LuaTable) lua["test"])["A"] = 1;
((LuaTable) lua["test"])["B"] = 2;
lua.DoString("for k,v in pairs(test) do print(k..': '..v) end");
You could fill a C# Dictionary with the keys and values you want to put inside the table. Then do what you're doing in the "I have to..." section, but inside a foreach loop.
Untested code:
var test = new Dictionary<string, int> {
{ "A", 1 },
{ "B", 2 }
};
foreach (var entry in test)
{
((LuaTable) lua]["test"])[entry.Key] = entry.Value;
}
I'd refactor this basic idea into a generic class for added flexibility.
I think if you want to serialize anonymous types into lua tables you will need to user reflection. Maybe you can try to write a lua table serializer. I think I would try to assemble my tables as string and pass it to Lua with DoString
I think the dictionary solution is good and you can use nested tables with without reflection. I tried Tuples, but they are not generic enough and eventually I fell back to the reflection idea.
I would create an extension method:
public static class LuaExt
{
public static LuaTable GetTable(this Lua lua, string tableName)
{
return lua[tableName] as LuaTable;
}
public static LuaTable CreateTable(this Lua lua, string tableName)
{
lua.NewTable(tableName);
return lua.GetTable(tableName);
}
public static LuaTable CreateTable(this Lua lua)
{
lua.NewTable("my");
return lua.GetTable("my");
}
}
Then I could write something like this:
var lua = new Lua();
var table = lua.CreateTable("test");
table["A"] = 1;
table["B"] = 1;
table["C"] = lua.CreateTable();
((LuaTable) table["C"])["A"] = 3;
table["D"] = lua.CreateTable();
((LuaTable)table["D"])["A"] = 3;
foreach (var v in table.Keys)
{
Console.WriteLine(v + ":" + table[v]);
}