{
"authors": [
{
"name": "Alfonso"
},
{
"name": "Alfred"
}
],
"books": [
{
"title": "Book One",
"authors": [
{
"name": "Author One"
},
{
"name": "Author Two"
}
]
},
{
"title": "Book Two",
"authors": [
{
"name": "Alfonso"
}
]
},
{
"title": "Book Three",
"year": "2022",
"authors": [
{
"name": "Alfred"
}
]
}
]
}
\ No newline at end of file
Package generated_from_model_json {
Type String
Type TODO_RESOLVE_REFERENCED
Use "model.json" as SOURCE_MAPPING
Type JSON_String
Structure JSON_model_json (
JSON_authors authors,
JSON_books books
)
Collection JSON_authors of JSON_authors_item
Structure JSON_authors_item (
JSON_String name
)
Collection JSON_books of JSON_books_item
Structure JSON_books_item (
JSON_String title,
JSON_authors authors,
JSON_String year
)
JSON_model_json JSON_instance (
authors = [
(
name = "Alfonso"
),
(
name = "Alfred"
)
],
books = [
(
title = "Book One",
authors = [
(
name = "Author One"
),
(
name = "Author Two"
)
]
),
(
title = "Book Two",
authors = [
(
name = "Alfonso"
)
]
),
(
title = "Book Three",
year = "2022",
authors = [
(
name = "Alfred"
)
]
)
]
)
Map JSON_model_json to "JSON" in SOURCE_MAPPING as JSON_SOURCE_MAPPING {
authors -> "authors",
books -> "books"
}
Map JSON_authors_item to "JSON.authors.item" in SOURCE_MAPPING as JSON_authors_item_SOURCE_MAPPING {
name -> "name"
}
Map JSON_books_item to "JSON.books.item" in SOURCE_MAPPING as JSON_books_item_SOURCE_MAPPING {
title -> "title",
authors -> "authors",
year -> "year"
}
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ import java.io.FilenameFilter;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
......@@ -24,6 +25,7 @@ import org.etsi.mts.tdl.tdlPackage;
import org.etsi.mts.tdl.asn2tdl.ASN2TDLTranslator;
import org.etsi.mts.tdl.constraints.evl.Validator;
import org.etsi.mts.tdl.helper.TDLHelper;
import org.etsi.mts.tdl.json2tdl.JSON2TDLTranslator;
import org.etsi.mts.tdl.openapi2tdl.next.OpenAPI2TDLTranslatorNext;
import org.etsi.mts.tdl.tools.to.docx.poi.Generator;
import org.etsi.mts.tdl.transform.AbstractTranslator;
......@@ -33,55 +35,93 @@ public class Standalone {
static String targetExtension = "tdltx";
static String openapiExtension = "yaml";
static String asnExtension = "asn";
static String jsonExtension = "json";
private List<MODE> modes = new ArrayList<>();
private String path = "";
enum MODE {
all,
list, debug, validateOCL,
validate, translate, exportDoc,
importOpenAPI, importASN1, importJSON
}
public static void main(String[] args) throws Exception {
Standalone app = new Standalone();
//folder
String path = "examples/basics";
//TODO: expose as arguments
app.modes.add(MODE.importJSON);
// app.path = "examples/json/model.json";
if (app.selected(MODE.list)) {
String path = pathOrDefault(app.path, "examples/basics");
app.processElements(path, app::listElements);
}
path = "examples/basics";
app.processElements(path, app::listElements);
//TODO: may fail
app.processElements(path, app::validate);
//TODO: may fail due to literal value use without data type
if (app.selected(MODE.validate)) {
String path = pathOrDefault(app.path, "examples/basics");
app.processElements(path, app::validate);
}
//TODO: may fail
// app.processElements(path, app::translate);
if (app.selected(MODE.translate)) {
String path = pathOrDefault(app.path, "examples/basics");
app.processElements(path, app::translate);
}
if (app.selected(MODE.importJSON)) {
String path = pathOrDefault(app.path, "examples/json");
app.processElements(path, jsonExtension, app::importJSON);
}
if (app.selected(MODE.exportDoc)) {
String path = pathOrDefault(app.path, "examples/validation/Example.tdltx");
app.processElements(path, app::exportDoc);
}
TDLHelper.resetResourceSet();
path = "examples/validation/Example.tdltx";
//TODO: can only be used in isolation as it interferes with OCL delegates afterwards..
// app.processElements(path, app::validateOCL);
//TODO: may fail due to literal value use without data type
// app.processElements(path, app::validate);
app.processElements(path, app::exportDoc);
TDLHelper.resetResourceSet();
path = "examples/openapi";
app.processElements(path, openapiExtension, app::importOpenAPI);
//NOTE: keep in mind weird errors if legacy OpenAPI importer is imported as well in manifest (especially if it is first)
if (app.selected(MODE.validateOCL)) {
String path = pathOrDefault(app.path, "examples/validation/Example.tdltx");
app.processElements(path, app::validateOCL);
}
TDLHelper.resetResourceSet();
path = "examples/asn1";
app.processElements(path, asnExtension, app::importASN1);
//individual file without dependencies
TDLHelper.resetResourceSet();
path = "examples/basics/Sample.tdltx";
app.processElements(path, app::listElements);
if (app.selected(MODE.importOpenAPI)) {
String path = pathOrDefault(app.path, "examples/openapi");
app.processElements(path, openapiExtension, app::importOpenAPI);
//NOTE: keep in mind weird errors if legacy OpenAPI importer is imported as well in manifest (especially if it is first)
}
//individual file with missing dependencies
TDLHelper.resetResourceSet();
path = "examples/basics/ImportSample.tdltx";
app.processElements(path, app::listElements);
//validation will fail due to unresolved items
if (app.selected(MODE.importASN1)) {
String path = pathOrDefault(app.path, "examples/asn1");
app.processElements(path, asnExtension, app::importASN1);
}
if (app.selected(MODE.debug)) {
//individual file without dependencies
app.processElements("examples/basics/Sample.tdltx", app::listElements);
//individual file with missing dependencies
app.processElements("examples/basics/ImportSample.tdltx", app::listElements);
//validation will fail due to unresolved items
}
//TODO: minimal example for TO translation
//TODO: minimal example for TTCN-3 generation
//TODO: clean up keywords automatically
}
private static String pathOrDefault(String path, String defaultPath) {
return path.isEmpty() ? defaultPath : path;
}
private boolean selected(MODE m) {
return modes.contains(MODE.all) || modes.contains(m);
}
private void processElements(String path, Consumer<String> operation) throws Exception {
TDLHelper.resetResourceSet();
processElements(path, sourceExtension, operation);
}
......@@ -193,6 +233,10 @@ public class Standalone {
importData(path, new ASN2TDLTranslator());
}
private void importJSON(String path) {
importData(path, new JSON2TDLTranslator());
}
private void exportDoc(String path) {
Resource resource = TDLHelper.load(path);
Generator generator = new Generator();
......
......@@ -1020,7 +1020,7 @@ Assignment returns tdl::Assignment:
//## ValueConverter Rules (Pseudo-terminals)
//TODO: why does this strip quotes when it is a single word?
//DONE: why does this strip quotes when it is a single word? -> added custom value converter
EString:
STRING
// | ID
......@@ -1033,7 +1033,9 @@ EString:
Identifier:
ID
ID
//implementation specific
| 'name' | 'type' //TODO: exclude other keywords to the extent possible?
;
GRIdentifier:
......@@ -1882,3 +1884,9 @@ Then:
KIdentifier:
ID | 'sends' | 'receives' | 'triggers' | 'in'
;
//TODO: document?
@Override
//terminal ID: '^'?('a'..'z'|'A'..'Z'|'_') (ALPHANUM | (('-'|':') ALPHANUM))*;
terminal ID: '^'?('a'..'z'|'A'..'Z'|'_') (ALPHANUM | (('-') ALPHANUM))*;
terminal fragment ALPHANUM: ('a'..'z'|'A'..'Z'|'_'|'0'..'9');
\ No newline at end of file
......@@ -19,6 +19,7 @@ import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.etsi.mts.tdl.Element;
import org.etsi.mts.tdl.ElementImport;
import org.etsi.mts.tdl.PackageableElement;
import org.etsi.mts.tdl.ParameterBinding;
import org.etsi.mts.tdl.ParameterMapping;
import org.etsi.mts.tdl.StructuredDataType;
import org.etsi.mts.tdl.EnumDataType;
......@@ -32,6 +33,8 @@ import org.etsi.mts.tdl.Connection;
import org.etsi.mts.tdl.Annotation;
import org.etsi.mts.tdl.Extension;
import org.etsi.mts.tdl.DataElementMapping;
import org.etsi.mts.tdl.DataElementUse;
import org.etsi.mts.tdl.DataUse;
import org.etsi.mts.tdl.TestConfiguration;
import org.etsi.mts.tdl.TestDescription;
import org.etsi.mts.tdl.Behaviour;
......@@ -240,6 +243,12 @@ public class TDLtxFormatter extends AbstractJavaFormatter {
// doc.append(m, p->p.newLine());
doc.format(m);
}
List<ISemanticRegion> close = this.textRegionExtensions.regionFor(e).ruleCallsTo(this._grammarAccess.getENDRule());
if (!close.isEmpty()) {
doc.prepend(close.get(0), p->p.newLine());
}
}
//Test Objective Only
......@@ -318,6 +327,35 @@ public class TDLtxFormatter extends AbstractJavaFormatter {
doc.format(m);
}
}
protected void format(org.etsi.mts.tdl.DataUse e, IFormattableDocument doc) {
for (ParameterBinding m : e.getArgument()) {
doc.prepend(m, p->p.newLine());
doc.surround(m, p->p.indent());
// doc.append(m, p->p.newLine());
doc.format(m);
}
if (e instanceof DataElementUse) {
for (DataUse m : ((DataElementUse) e).getItem()) {
doc.prepend(m, p->p.newLine());
doc.surround(m, p->p.indent());
// doc.append(m, p->p.newLine());
doc.format(m);
}
}
List<ISemanticRegion> closeParen = this.textRegionExtensions.regionFor(e).ruleCallsTo(this._grammarAccess.getRParenRule());
if (!closeParen.isEmpty()) {
doc.prepend(closeParen.get(0), p->p.newLine());
}
List<ISemanticRegion> closeItems = this.textRegionExtensions.regionFor(e).keywords("]");
if (!closeItems.isEmpty()) {
doc.prepend(closeItems.get(0), p->p.newLine());
}
}
protected void format(org.etsi.mts.tdl.Package _package, IFormattableDocument doc) {
// TODO: format HiddenRegions around keywords, attributes, cross references, etc.
......