Commits (12)
......@@ -7,6 +7,5 @@
</classpathentry>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="lib/gson-2.9.1.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
......@@ -5,5 +5,8 @@ Bundle-SymbolicName: org.etsi.mts.tdl.json2tdl
Bundle-Version: 1.0.0.qualifier
Export-Package: org.etsi.mts.tdl.json2tdl
Require-Bundle: org.etsi.mts.tdl.common,
org.eclipse.emf.ecore
org.eclipse.emf.ecore,
org.eclipse.xtext,
org.etsi.mts.tdl.helper,
com.google.gson
Automatic-Module-Name: org.etsi.mts.tdl.json2tdl
......@@ -25,6 +25,7 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
public class JSON2TDLTranslator extends AbstractTranslator{
private static final String JSON_STRING = "JSON_String";
......@@ -46,6 +47,15 @@ public class JSON2TDLTranslator extends AbstractTranslator{
System.out.print(" "+e);
}
}
public boolean isValid(String json) {
try {
JsonParser.parseString(json);
} catch (JsonSyntaxException e) {
return false;
}
return true;
}
//inherited entry point
@Override
......@@ -62,6 +72,7 @@ public class JSON2TDLTranslator extends AbstractTranslator{
String prefix = "JSON";
getSimpleDataTypeFor(JSON_STRING);
//TODO: add validation
translate(prefix, jsonElement);
//DONE: data instances as well? -> only one data instance,
......@@ -81,6 +92,7 @@ public class JSON2TDLTranslator extends AbstractTranslator{
//TODO: add optional extends Body? needs also corresponding import
//using a wrapper may be more adequate
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
......
package org.etsi.mts.tdl.json2tdl;
import java.io.File;
import org.eclipse.emf.ecore.resource.Resource;
import org.etsi.mts.tdl.helper.TDLHelper;
public class JSONConverter {
public static String processToString(String inputPath, String outputPath) {
return processToString(inputPath, outputPath, "SOURCE_MAPPING", "TARGET_MAPPING");
}
public static String processToString(String inputPath, String outputPath, String sourceMapping, String targetMapping) {
System.out.println("Exporting: "+outputPath+ " : "+ new File(outputPath).getAbsolutePath());
JSON2TDLTranslator translator = new JSON2TDLTranslator();
String content = "Package imported {}";
try {
Resource tr = TDLHelper.create(outputPath);
translator.setTargetResource(tr);
translator.initTargetResource(translator.cleanName(new File(inputPath).getName()));
translator.translate(inputPath);
content = TDLHelper.getText(tr);
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
}
package org.etsi.mts.tdl.json2tdl;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.util.Files;
import org.etsi.mts.tdl.CollectionDataType;
import org.etsi.mts.tdl.DataElementMapping;
import org.etsi.mts.tdl.DataElementUse;
import org.etsi.mts.tdl.DataUse;
import org.etsi.mts.tdl.LiteralValueUse;
import org.etsi.mts.tdl.MappableDataElement;
import org.etsi.mts.tdl.MemberAssignment;
import org.etsi.mts.tdl.NamedElement;
import org.etsi.mts.tdl.Package;
import org.etsi.mts.tdl.Parameter;
import org.etsi.mts.tdl.ParameterBinding;
import org.etsi.mts.tdl.SimpleDataType;
import org.etsi.mts.tdl.StructuredDataInstance;
import org.etsi.mts.tdl.StructuredDataType;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class TDL2JSONTranslator {
private Map<MappableDataElement, DataElementMapping> dataMappings = new LinkedHashMap<>();
private Map<Parameter, String> parameterMappings = new LinkedHashMap<>();
public void transform(Package p) {
indexMappings(p);
List<StructuredDataInstance> instances = EcoreUtil2.getAllContentsOfType(p, StructuredDataInstance.class);
instances.forEach(this::translate);
}
public void indexMappings(Package p) {
//TODO: assuming mappings are in the same package
//TODO: differentiate mappings
dataMappings = EcoreUtil2.getAllContentsOfType(p, DataElementMapping.class).stream()
.filter(e->e.getName().endsWith("SOURCE_MAPPING"))
.collect(Collectors.toMap(e->e.getMappableDataElement(), e->e));
dataMappings.values().forEach(this::indexParameterMappings);
}
private void indexParameterMappings(DataElementMapping dem) {
dem.getParameterMapping().forEach(pm -> parameterMappings.put(pm.getParameter(), pm.getParameterURI()));
}
public String translate(StructuredDataInstance instance) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
//DONE: test out basic individual data use translation
//instance.getMemberAssignment().forEach(ma -> translate(ma.getMemberSpec()));
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
instance.getMemberAssignment().forEach(ma -> transform(ma, map));
String json = gson.toJson(map);
//TODO: other primitives not serialised?
//TODO: refine and extract
System.out.println(json);
String prefix = "examples/json/";
String filename = prefix + instance.getQualifiedName().replaceAll("::", "_") + ".json";
Files.writeStringIntoFile(filename , json);
return json;
}
public String translate(DataUse du) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(transform(du));
// System.out.println(json);
return json;
}
public Object transform(DataUse du) {
if (du.resolveDataType() instanceof StructuredDataType) {
//TODO: should it apply for function calls and others?
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
du.getArgument().forEach(pb -> transform(pb, map));
//TODO: handle data element if assigned -> structured instance supported, others?
//TODO: also others?
//TODO: handle reduction?
if (du instanceof DataElementUse) {
NamedElement de = ((DataElementUse) du).getDataElement();
if (de instanceof StructuredDataInstance) {
((StructuredDataInstance) de).getMemberAssignment().stream()
.filter(e->du.getArgument().stream()
.noneMatch(a ->a.getParameter() == e.getMember()))
.forEach(ma -> transform(ma, map));
}
}
return map;
} else if (du.resolveDataType() instanceof CollectionDataType) {
if (du instanceof DataElementUse) {
return ((DataElementUse) du).getItem().stream()
.map(this::transform)
.collect(Collectors.toList());
} else {
return null;
}
} else if (du.resolveDataType() instanceof SimpleDataType) {
if (du instanceof LiteralValueUse) {
//TODO: also intValue and boolValue
//TODO: also differentiate during JSON2TDL
LiteralValueUse lvu = ((LiteralValueUse) du);
if (lvu.getIntValue()!=null) {
return lvu.getIntValue();
} else if (lvu.getBoolValue()!=null) {
return lvu.getBoolValue();
}
return lvu.getValue();
} else {
//TODO: handle other data uses
return null;
}
} else {
//TODO: handle other data uses
return null;
}
}
private void transform(ParameterBinding pb, LinkedHashMap<String, Object> map) {
String key = pb.getParameter().getName();
//TODO: handle extensions?
String mappedKey = parameterMappings.get(pb.getParameter());
if (mappedKey != null) {
key = mappedKey;
};
map.put(key, transform(pb.getDataUse()));
}
private void transform(MemberAssignment ma, LinkedHashMap<String, Object> map) {
String key = ma.getMember().getName();
//TODO: handle extensions?
String mappedKey = parameterMappings.get(ma.getMember());
if (mappedKey != null) {
key = mappedKey;
};
map.put(key, transform(ma.getMemberSpec()));
}
}
......@@ -23,9 +23,13 @@ public class ConverterNext {
public static String processToString(String inputPath, String outputPath) {
return processToString(inputPath, outputPath, "SOURCE_MAPPING", "TARGET_MAPPING");
}
public static String processToString(String inputPath, String outputPath, String sourceMapping, String targetMapping) {
OpenAPI spec = parseSpec(inputPath);
return processToString(inputPath, outputPath, sourceMapping, targetMapping, false);
}
public static String processToString(String inputPath, String outputPath, String sourceMapping, String targetMapping, boolean inline) {
// OpenAPI spec = parseSpec(inputPath);
System.out.println("Exporting: "+outputPath+ " : "+ new File(outputPath).getAbsolutePath());
OpenAPI2TDLTranslatorNext translator = new OpenAPI2TDLTranslatorNext();
String content = "Package imported {}";
......@@ -33,7 +37,7 @@ public class ConverterNext {
Resource tr = TDLHelper.create(outputPath);
translator.setTargetResource(tr);
translator.initTargetResource(translator.cleanName(new File(inputPath).getName()));
translator.translate(inputPath, sourceMapping, targetMapping);
translator.translate(inputPath, sourceMapping, targetMapping, inline);
content = TDLHelper.getText(tr);
} catch (Exception e) {
e.printStackTrace();
......
......@@ -28,6 +28,9 @@ public class OpenAPI2TDLTranslatorNext extends AbstractTranslator {
}
public void translate(String filename, String sourceMappingTag, String targetMappingTag) throws Exception {
translate(filename, sourceMappingTag, targetMappingTag, false);
}
public void translate(String filename, String sourceMappingTag, String targetMappingTag, boolean inline) throws Exception {
// Converter.setTdlTokens(Arrays.asList(new String[] {"'name'", "'type'", "'size'", "'instance'"}));
// Converter converter = new Converter(filename);
// converter.runConversion();
......@@ -35,7 +38,7 @@ public class OpenAPI2TDLTranslatorNext extends AbstractTranslator {
//TODO: refine according to other translators
//TODO: separate validation into another component
model = parseSpec(filename);
model = parseSpec(filename, inline);
drm = getTypeFor(sourceMappingTag, tdlPackage.Literals.DATA_RESOURCE_MAPPING);
drm.setResourceURI(new File(filename).getName());
drmTarget = getTypeFor(targetMappingTag, tdlPackage.Literals.DATA_RESOURCE_MAPPING);
......@@ -138,15 +141,18 @@ public class OpenAPI2TDLTranslatorNext extends AbstractTranslator {
* @param specFilePath The path to the specification file
* @return A "raw" OpenAPI document
*/
public static OpenAPI parseSpec(String specFilePath) {
public static OpenAPI parseSpec(String specFilePath, Boolean processInline) {
OpenAPI openAPI = new OpenAPIParser().readLocation(specFilePath, null, new ParseOptions()).getOpenAPI();
// Invoke helper function to get the original swagger version.
// See https://github.com/swagger-api/swagger-parser/pull/1374
// Also see https://github.com/swagger-api/swagger-parser/issues/1369.
ModelUtils.getOpenApiVersion(openAPI, specFilePath, null);
// InlineModelResolver inlineModelResolver = new InlineModelResolver();
// inlineModelResolver.flatten(openAPI);
//DONE: make optional and expose for configuration
if (processInline) {
InlineModelResolver inlineModelResolver = new InlineModelResolver();
inlineModelResolver.flatten(openAPI);
}
return openAPI;
}
......
{
"ieee802_dot1q_bridge_bridges": {
"bridge": [
{
"name": "ne2",
"address": "10-10-10-10-10-10",
"bridge-type": "ieee802-dot1q-bridge:customer-vlan-bridge",
"component": [
{
"name": "cv0",
"id": "0",
"type": "ieee802-dot1q-bridge:c-vlan-component",
"bridge-port": [
"eth1",
"eth2",
"eth3"
],
"filtering-database": {
"vlan-registration-entry": [
{
"database-id": "1",
"vids": "200",
"entry-type": "static",
"port-map": [
{
"port-ref": "1",
"static-vlan-registration-entries": {
"vlan-transmitted": "tagged"
}
},
{
"port-ref": "3",
"static-vlan-registration-entries": {
"vlan-transmitted": "tagged"
}
}
]
},
{
"database-id": "1",
"vids": "300",
"entry-type": "static",
"port-map": [
{
"port-ref": "2",
"static-vlan-registration-entries": {
"vlan-transmitted": "untagged"
}
},
{
"port-ref": "3",
"static-vlan-registration-entries": {
"vlan-transmitted": "tagged"
}
}
]
}
]
},
"bridge-vlan": {
"vlan": [
{
"vid": "200",
"name": "E-Line 200",
"egress-ports": [
"eth1",
"eth3"
]
},
{
"vid": "300",
"name": "E-Line 300",
"untagged-ports": [
"eth2"
],
"egress-ports": [
"eth2",
"eth3"
]
}
]
}
}
]
}
]
},
"ietf_interfaces_interfaces": {
"interface": [
{
"name": "eth1",
"type": "iana-if-type:ethernetCsmacd",
"oper-status": "up",
"statistics": {
"discontinuity-time": "2022-04-06T11:00:00+02:00"
},
"ieee802-dot1q-bridge:bridge-port": {
"bridge-name": "ne2",
"component-name": "cv0",
"port-type": "ieee802-dot1q-bridge:c-vlan-bridge-port",
"pvid": "1",
"acceptable-frame": "admit-only-VLAN-tagged-frames",
"enable-ingress-filtering": "true",
"port-number": "1"
}
},
{
"name": "eth2",
"type": "iana-if-type:ethernetCsmacd",
"oper-status": "up",
"statistics": {
"discontinuity-time": "2022-04-06T11:00:00+02:00"
},
"ieee802-dot1q-bridge:bridge-port": {
"bridge-name": "ne2",
"component-name": "cv0",
"port-type": "ieee802-dot1q-bridge:c-vlan-bridge-port",
"pvid": "300",
"acceptable-frame": "admit-only-untagged-and-priority-tagged",
"enable-ingress-filtering": "true",
"port-number": "2"
}
},
{
"name": "eth3",
"type": "iana-if-type:ethernetCsmacd",
"oper-status": "up",
"statistics": {
"discontinuity-time": "2022-04-06T11:00:00+02:00"
},
"ieee802-dot1q-bridge:bridge-port": {
"bridge-name": "ne2",
"component-name": "cv0",
"port-type": "ieee802-dot1q-bridge:c-vlan-bridge-port",
"pvid": "1",
"acceptable-frame": "admit-only-VLAN-tagged-frames",
"enable-ingress-filtering": "true",
"port-number": "3"
}
}
]
}
}
\ No newline at end of file
{
"ieee802-dot1q-bridge:bridges": {
"bridge": [
{
"name": "ne2",
"address": "10-10-10-10-10-10",
"bridge-type": "ieee802-dot1q-bridge:customer-vlan-bridge",
"component": [
{
"name": "cv0",
"id": "0",
"type": "ieee802-dot1q-bridge:c-vlan-component",
"bridge-port": [
"eth1",
"eth2",
"eth3"
],
"filtering-database": {
"vlan-registration-entry": [
{
"database-id": "1",
"vids": "200",
"entry-type": "static",
"port-map": [
{
"port-ref": "1",
"static-vlan-registration-entries": {
"vlan-transmitted": "tagged"
}
},
{
"port-ref": "3",
"static-vlan-registration-entries": {
"vlan-transmitted": "tagged"
}
}
]
},
{
"database-id": "1",
"vids": "300",
"entry-type": "static",
"port-map": [
{
"port-ref": "2",
"static-vlan-registration-entries": {
"vlan-transmitted": "untagged"
}
},
{
"port-ref": "3",
"static-vlan-registration-entries": {
"vlan-transmitted": "tagged"
}
}
]
}
]
},
"bridge-vlan": {
"vlan": [
{
"vid": "200",
"name": "E-Line 200",
"egress-ports": [
"eth1",
"eth3"
]
},
{
"vid": "300",
"name": "E-Line 300",
"untagged-ports": [
"eth2"
],
"egress-ports": [
"eth2",
"eth3"
]
}
]
}
}
]
}
]
},
"ietf-interfaces:interfaces": {
"interface": [
{
"name": "eth1",
"type": "iana-if-type:ethernetCsmacd",
"oper-status": "up",
"statistics": {
"discontinuity-time": "2022-04-06T11:00:00+02:00"
},
"ieee802-dot1q-bridge:bridge-port": {
"bridge-name": "ne2",
"component-name": "cv0",
"port-type": "ieee802-dot1q-bridge:c-vlan-bridge-port",
"pvid": "1",
"acceptable-frame": "admit-only-VLAN-tagged-frames",
"enable-ingress-filtering": "true",
"port-number": "1"
}
},
{
"name": "eth2",
"type": "iana-if-type:ethernetCsmacd",
"oper-status": "up",
"statistics": {
"discontinuity-time": "2022-04-06T11:00:00+02:00"
},
"ieee802-dot1q-bridge:bridge-port": {
"bridge-name": "ne2",
"component-name": "cv0",
"port-type": "ieee802-dot1q-bridge:c-vlan-bridge-port",
"pvid": "300",
"acceptable-frame": "admit-only-untagged-and-priority-tagged",
"enable-ingress-filtering": "true",
"port-number": "2"
}
},
{
"name": "eth3",
"type": "iana-if-type:ethernetCsmacd",
"oper-status": "up",
"statistics": {
"discontinuity-time": "2022-04-06T11:00:00+02:00"
},
"ieee802-dot1q-bridge:bridge-port": {
"bridge-name": "ne2",
"component-name": "cv0",
"port-type": "ieee802-dot1q-bridge:c-vlan-bridge-port",
"pvid": "1",
"acceptable-frame": "admit-only-VLAN-tagged-frames",
"enable-ingress-filtering": "true",
"port-number": "3"
}
}
]
}
}
\ No newline at end of file
{
"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"
}
]
},
{
"title": "Instance Book 2"
},
{
"year": "2023",
"title": "Instance Book 2"
},
{
"title": "2023 override"
},
{
"title": "2023 override and extra year",
"year": "2023"
}
]
}
\ No newline at end of file
{
"title": "Instance Book 2"
}
\ 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_books_item b2 (
title = "Instance Book 2"
)
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"
)
]
),
b2 (),
b2 (
year = "2023"
),
b2 (
title = "2023 override"
),
b2 (
title = "2023 override and extra year",
year = "2023"
),
]
)
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
......@@ -17,6 +17,11 @@ Package generated_from_model_json {
JSON_authors authors,
JSON_String year
)
JSON_books_item b2 (
title = "Instance Book 2"
)
JSON_model_json JSON_instance (
authors = [
(
......@@ -54,7 +59,18 @@ Package generated_from_model_json {
name = "Alfred"
)
]
)
),
b2 (),
b2 (
year = "2023"
),
b2 (
title = "2023 override"
),
b2 (
title = "2023 override and extra year",
year = "2023"
),
]
)
Map JSON_model_json to "JSON" in SOURCE_MAPPING as JSON_SOURCE_MAPPING {
......
......@@ -20,11 +20,13 @@ Package generated_from_ExampleAPI_yaml {
Map ResourceData to "#/components/schemas/ResourceData" in SOURCE_MAPPING as ResourceData_SOURCE_MAPPING {
id -> "id",
^size -> "size",
created -> "created" }
created -> "created"
}
Map ResourceData to "ResourceData" in TARGET_MAPPING as ResourceData_TARGET_MAPPING {
id -> "id",
^size -> "size",
created -> "created" }
created -> "created"
}
Structure Subscription (
Credentials credentials
)
......@@ -32,14 +34,18 @@ Package generated_from_ExampleAPI_yaml {
string user
)
Map Subscription to "#/components/schemas/Subscription" in SOURCE_MAPPING as Subscription_SOURCE_MAPPING {
credentials -> "credentials" }
credentials -> "credentials"
}
Map Subscription to "Subscription" in TARGET_MAPPING as Subscription_TARGET_MAPPING {
credentials -> "credentials" }
credentials -> "credentials"
}
Structure AuthenticatedNotification ( )
Map AuthenticatedNotification to "#/components/schemas/AuthenticatedNotification" in SOURCE_MAPPING as AuthenticatedNotification_SOURCE_MAPPING
Map AuthenticatedNotification to "AuthenticatedNotification" in TARGET_MAPPING as AuthenticatedNotification_TARGET_MAPPING
Map Credentials to "#/components/schemas/Credentials" in SOURCE_MAPPING as Credentials_SOURCE_MAPPING {
user -> "user" }
user -> "user"
}
Map Credentials to "Credentials" in TARGET_MAPPING as Credentials_TARGET_MAPPING {
user -> "user" }
user -> "user"
}
}
\ No newline at end of file
openapi: 3.0.0
info:
title: ReqRes API
description: Fake data CRUD API
version: 1.00
servers:
- url: https://reqres.in/api
components:
schemas:
User:
type: object
properties:
id:
type: integer
email:
type: string
first_name:
type: string
last_name:
type: string
avatar:
type: string
UnknownResource:
type: object
properties:
id:
type: integer
name:
type: string
year:
type: integer
color:
type: string
pantone_value:
type: string
paths:
/{resource}:
get:
summary: Fetches a resource list
parameters:
- in: query
name: page
schema:
type: integer
- in: query
name: per_page
schema:
type: integer
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
page:
type: integer
per_page:
type: integer
total:
type: integer
total_pages:
type: integer
data:
type: array
items:
$ref: "#/components/schemas/UnknownResource"
/users:
get:
summary: Fetches a user list
parameters:
- in: query
name: page
schema:
type: integer
- in: query
name: per_page
schema:
type: integer
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
page:
type: integer
per_page:
type: integer
total:
type: integer
total_pages:
type: integer
data:
type: array
items:
$ref: "#/components/schemas/User"
/users/{id}:
get:
summary: Fetches a user
parameters:
- in: path
name: id
schema:
type: integer
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
data:
$ref: "#/components/schemas/User"
put:
summary: Updates a user
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
updatedAt:
type: string
patch:
summary: Updates a user
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
updatedAt:
type: string
delete:
summary: Deletes a user
responses:
'204':
description: Success
/{resource}/{id}:
get:
summary: Fetches an unknown resource
parameters:
- in: path
name: id
schema:
type: integer
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
data:
$ref: "#/components/schemas/UnknownResource"
put:
summary: Updates an unknown resource
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
updatedAt:
type: string
patch:
summary: Updates an unknown resource
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
updatedAt:
type: string
delete:
summary: Deletes an unknown resource
responses:
'204':
description: Success
/login:
post:
summary: Creates a session
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
username:
type: string
email:
type: string
password:
type: string
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
token:
type: string
'400':
description: Login error
content:
application/json:
schema:
type: object
properties:
error:
type: string
/register:
post:
summary: Creates a user
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
username:
type: string
email:
type: string
password:
type: string
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
id:
type: string
token:
type: string
'400':
description: Register error
content:
application/json:
schema:
type: object
properties:
error:
type: string
/logout:
post:
summary: Ends a session
responses:
'200':
description: Success
Package generated_from_reqres_yaml {
Type String
Type TODO_RESOLVE_REFERENCED
Use "reqres.yaml" as SOURCE_MAPPING
Use "generated/java" as TARGET_MAPPING
Structure User (
integer id,
string email,
string first_name,
string last_name,
string avatar
)
Type integer
Type string
Map User to "#/components/schemas/User" in SOURCE_MAPPING as User_SOURCE_MAPPING {
id -> "id",
email -> "email",
first_name -> "first_name",
last_name -> "last_name",
avatar -> "avatar"
}
Map User to "User" in TARGET_MAPPING as User_TARGET_MAPPING {
id -> "id",
email -> "email",
first_name -> "first_name",
last_name -> "last_name",
avatar -> "avatar"
}
Structure UnknownResource (
integer id,
string name,
integer year,
string color,
string pantone_value
)
Map UnknownResource to "#/components/schemas/UnknownResource" in SOURCE_MAPPING as UnknownResource_SOURCE_MAPPING {
id -> "id",
name -> "name",
year -> "year",
color -> "color",
pantone_value -> "pantone_value"
}
Map UnknownResource to "UnknownResource" in TARGET_MAPPING as UnknownResource_TARGET_MAPPING {
id -> "id",
name -> "name",
year -> "year",
color -> "color",
pantone_value -> "pantone_value"
}
Structure inline_response_200 (
integer page,
integer per_page,
integer total,
integer total_pages,
inline_response_200______item data
)
Collection inline_response_200______item of inline_response_200______itemUnknownResource
Structure inline_response_200______itemUnknownResource (
integer id,
string name,
integer year,
string color,
string pantone_value
)
Map inline_response_200 to "#/components/schemas/inline_response_200" in SOURCE_MAPPING as inline_response_200_SOURCE_MAPPING {
page -> "page",
per_page -> "per_page",
total -> "total",
total_pages -> "total_pages",
data -> "data"
}
Map inline_response_200 to "inline_response_200" in TARGET_MAPPING as inline_response_200_TARGET_MAPPING {
page -> "page",
per_page -> "per_page",
total -> "total",
total_pages -> "total_pages",
data -> "data"
}
Structure inline_response_200_1 (
integer page,
integer per_page,
integer total,
integer total_pages,
inline_response_200_1______item data
)
Collection inline_response_200_1______item of inline_response_200_1______itemUser
Structure inline_response_200_1______itemUser (
integer id,
string email,
string first_name,
string last_name,
string avatar
)
Map inline_response_200_1 to "#/components/schemas/inline_response_200_1" in SOURCE_MAPPING as inline_response_200_1_SOURCE_MAPPING {
page -> "page",
per_page -> "per_page",
total -> "total",
total_pages -> "total_pages",
data -> "data"
}
Map inline_response_200_1 to "inline_response_200_1" in TARGET_MAPPING as inline_response_200_1_TARGET_MAPPING {
page -> "page",
per_page -> "per_page",
total -> "total",
total_pages -> "total_pages",
data -> "data"
}
Structure inline_response_200_2 (
User data
)
Map inline_response_200_2 to "#/components/schemas/inline_response_200_2" in SOURCE_MAPPING as inline_response_200_2_SOURCE_MAPPING {
data -> "data"
}
Map inline_response_200_2 to "inline_response_200_2" in TARGET_MAPPING as inline_response_200_2_TARGET_MAPPING {
data -> "data"
}
Structure inline_response_200_3 (
string updatedAt
)
Map inline_response_200_3 to "#/components/schemas/inline_response_200_3" in SOURCE_MAPPING as inline_response_200_3_SOURCE_MAPPING {
updatedAt -> "updatedAt"
}
Map inline_response_200_3 to "inline_response_200_3" in TARGET_MAPPING as inline_response_200_3_TARGET_MAPPING {
updatedAt -> "updatedAt"
}
Structure inline_response_200_4 (
UnknownResource data
)
Map inline_response_200_4 to "#/components/schemas/inline_response_200_4" in SOURCE_MAPPING as inline_response_200_4_SOURCE_MAPPING {
data -> "data"
}
Map inline_response_200_4 to "inline_response_200_4" in TARGET_MAPPING as inline_response_200_4_TARGET_MAPPING {
data -> "data"
}
Structure login_body (
string username,
string email,
string password
)
Map login_body to "#/components/schemas/login_body" in SOURCE_MAPPING as login_body_SOURCE_MAPPING {
username -> "username",
email -> "email",
password -> "password"
}
Map login_body to "login_body" in TARGET_MAPPING as login_body_TARGET_MAPPING {
username -> "username",
email -> "email",
password -> "password"
}
Structure inline_response_200_5 (
string token
)
Map inline_response_200_5 to "#/components/schemas/inline_response_200_5" in SOURCE_MAPPING as inline_response_200_5_SOURCE_MAPPING {
token -> "token"
}
Map inline_response_200_5 to "inline_response_200_5" in TARGET_MAPPING as inline_response_200_5_TARGET_MAPPING {
token -> "token"
}
Structure inline_response_400 (
string error
)
Map inline_response_400 to "#/components/schemas/inline_response_400" in SOURCE_MAPPING as inline_response_400_SOURCE_MAPPING {
error -> "error"
}
Map inline_response_400 to "inline_response_400" in TARGET_MAPPING as inline_response_400_TARGET_MAPPING {
error -> "error"
}
Structure register_body (
string username,
string email,
string password
)
Map register_body to "#/components/schemas/register_body" in SOURCE_MAPPING as register_body_SOURCE_MAPPING {
username -> "username",
email -> "email",
password -> "password"
}
Map register_body to "register_body" in TARGET_MAPPING as register_body_TARGET_MAPPING {
username -> "username",
email -> "email",
password -> "password"
}
Structure inline_response_200_6 (
string id,
string token
)
Map inline_response_200_6 to "#/components/schemas/inline_response_200_6" in SOURCE_MAPPING as inline_response_200_6_SOURCE_MAPPING {
id -> "id",
token -> "token"
}
Map inline_response_200_6 to "inline_response_200_6" in TARGET_MAPPING as inline_response_200_6_TARGET_MAPPING {
id -> "id",
token -> "token"
}
}
\ No newline at end of file
......@@ -26,6 +26,7 @@ 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.json2tdl.TDL2JSONTranslator;
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;
......@@ -42,7 +43,7 @@ public class Standalone {
enum MODE {
all,
list, debug, validateOCL,
validate, translate, exportDoc,
validate, translate, exportDoc, exportJSON,
importOpenAPI, importASN1, importJSON
}
......@@ -50,7 +51,11 @@ public class Standalone {
Standalone app = new Standalone();
//TODO: expose as arguments
app.modes.add(MODE.importJSON);
// app.modes.add(MODE.importJSON);
// app.modes.add(MODE.exportJSON);
app.path = "examples/openapi/reqres.yaml";
app.modes.add(MODE.importOpenAPI);
// app.path = "examples/json/model.json";
if (app.selected(MODE.list)) {
......@@ -76,6 +81,13 @@ public class Standalone {
app.processElements(path, jsonExtension, app::importJSON);
}
if (app.selected(MODE.exportJSON)) {
String path = pathOrDefault(app.path, "examples/json/model.json-generated.tdltx");
// path = "examples/json/e-line-examples-c-vlan-bridge.json-generated.tdltx";
app.processElements(path, jsonExtension, app::exportJSON);
}
if (app.selected(MODE.exportDoc)) {
String path = pathOrDefault(app.path, "examples/validation/Example.tdltx");
app.processElements(path, app::exportDoc);
......@@ -237,6 +249,12 @@ public class Standalone {
importData(path, new JSON2TDLTranslator());
}
private void exportJSON(String path) {
Resource resource = TDLHelper.load(path);
TDL2JSONTranslator translator = new TDL2JSONTranslator();
translator.transform((Package) resource.getContents().get(0));
}
private void exportDoc(String path) {
Resource resource = TDLHelper.load(path);
Generator generator = new Generator();
......
......@@ -18,6 +18,8 @@ public class Messages extends NLS {
public static String TDLtxProjectWithOpenAPI_Description;
public static String TDLtxFileFromOpenAPI_Label;
public static String TDLtxFileFromOpenAPI_Description;
public static String TDLtxLibrary_Label;
public static String TDLtxLibrary_Description;
static {
// initialize resource bundle
......
......@@ -10,6 +10,7 @@ import org.eclipse.xtext.ui.wizard.template.IFileTemplateProvider
import org.etsi.mts.tdl.openapi2tdl.next.ConverterNext
import org.eclipse.core.runtime.preferences.InstanceScope
import org.eclipse.ui.preferences.ScopedPreferenceStore
import org.etsi.mts.tdl.ui.wizard.TemplateHelper.Libraries
/**
* Create a list with all file templates to be shown in the template new file wizard.
......@@ -18,14 +19,18 @@ import org.eclipse.ui.preferences.ScopedPreferenceStore
*/
class TDLtxFileTemplateProvider implements IFileTemplateProvider {
override getFileTemplates() {
#[new TDLtxFile, new TDLtxFileFromOpenAPI]
#[
new TDLtxFile,
new TDLtxFileFromOpenAPI,
new TDLtxLibrary
]
}
}
@FileTemplate(label="TDLtx", icon="file_template.png", description="Create a new package for TDLtx.")
final class TDLtxFile {
//TODO: make it more sensible
val packageName = combo("Package Name:", #["Example", "Sample", "Tutorial", "Pack"], "The name of the package")
val packageName = text("Package Name:", "EmptyPackage", "The name of the package")
//TODO: reuse?
override generateFiles(IFileGenerator generator) {
......@@ -41,6 +46,29 @@ final class TDLtxFile {
}
}
@FileTemplate(label="TDLtx Library", icon="file_template.png", description="Add library for TDL.")
final class TDLtxLibrary {
//TODO: make it more sensible
//TODO: name should not be asked for...
val name = text("Name:", "Standard")
val packageName = combo("Library:", #["Standard", "HTTP"], "The library to be added.")
var validated = false
override protected updateVariables() {
validated = true
super.updateVariables()
}
//TODO: reuse?
override generateFiles(IFileGenerator generator) {
//TODO: use enum values?
if (validated) {
generator.generate('''«folder»/«name».tdltx''', TemplateHelper.getLibrary(packageName.value))
}
}
}
@FileTemplate(label="Data definitions import from OpenAPI", icon="file_template.png", description="Create a new package for TDLtx from OpenAPI data definitions.")
final class TDLtxFileFromOpenAPI {
//TODO: more modern way?
......
......@@ -19,6 +19,9 @@ import java.util.List
import org.eclipse.swt.graphics.Image
import org.etsi.mts.tdl.tx.ui.internal.TxActivator
import org.etsi.mts.tdl.openapi2tdl.next.ConverterNext
import org.eclipse.ui.preferences.ScopedPreferenceStore
import org.eclipse.core.runtime.preferences.InstanceScope
import org.etsi.mts.tdl.ui.wizard.TemplateHelper.Libraries
/**
* Create a list with all project templates to be shown in the template new project wizard.
......@@ -110,13 +113,20 @@ final class TDLtxProject {
You can set a parameter to modify the content in the generated file
and a parameter to set the path the file is created in.</p><p><img href=\"project_template.png\"/></p>")
final class TDLtxProjectWithOpenAPI {
//TODO: more modern way?
//TODO: differentiate for project vs file wizard
val s = new ScopedPreferenceStore(new InstanceScope(), "org.etsi.mts.tdl.tx.ui.template.data.openapi")
val lastUsed = "LAST_USED"
//TODO: file prompt?
//TODO: remove after testing
val testFile = "/Users/philip-iii/Dev/git/etsi-labs/eg-203647-restful-api-guide/OpenAPI/ExampleAPI.yaml"
val advanced = check("Advanced:", false)
val advanced = check("Advanced:", true)
val advancedGroup = group("Properties")
val name = combo("Package Name:", #["Example", "Sample", "Tutorial", "Pack"], "The name of the package", advancedGroup)
val path = text("Path:", "tdltx_example", "The package path to place the files in", advancedGroup)
val dataDefinitionsPath = text("Data DefinitionsPath:", testFile, "The data definitions path to import from", advancedGroup)
val name = text("Main Package Name:", "Main", "The name of the main package")
// val name = combo("Package Name:", #["Example", "Sample", "Tutorial", "Pack"], "The name of the package", advancedGroup)
val path = text("Path:", "tdl", "The package path to place the files in", advancedGroup)
val dataDefinitionsPath = text("Data DefinitionsPath:", s.getString(lastUsed), "The data definitions path to import from", advancedGroup)
val sourceMapping = text("Source mapping tag:", "SOURCE_MAPPING", "The source mapping tag to be used for the data mappings", advancedGroup)
val targetMapping = text("Target mapping tag:", "TARGET_MAPPING", "The target mapping tag to be used for the data mappings", advancedGroup)
@Inject
PluginImageHelper pluginImageHelper
......@@ -125,10 +135,15 @@ final class TDLtxProjectWithOpenAPI {
name.enabled = advanced.value
path.enabled = advanced.value
dataDefinitionsPath.enabled = advanced.value
sourceMapping.enabled = advanced.value
targetMapping.enabled = advanced.value
if (!advanced.value) {
name.value = "Example"
path.value = "tdltx.example"
dataDefinitionsPath.value = testFile
name.value = "Main"
path.value = "tdl"
dataDefinitionsPath.value = s.getString(lastUsed)
sourceMapping.value = "SOURCE_MAPPING"
targetMapping.value = "TARGET_MAPPING"
}
}
......@@ -149,21 +164,30 @@ final class TDLtxProjectWithOpenAPI {
projectNatures += #[XtextProjectHelper.NATURE_ID]
builderIds += #[XtextProjectHelper.BUILDER_ID]
folders += "src"
addRequiredBundles(List.of("org.etsi.mts.tdl.tx.ui"))
// addFile('''src/«path»/Standard.tdltx''', TemplateContent.Standard)
//TODO: move libraries to a separate bundle
addFile('''src/«path»/Standard.tdltx''', TemplateHelper.getLibrary("Standard"))
//TODO: remove hardcoded import
addFile('''src/«path»/Wizardry.tdltx''', TemplateContent.Example)
//TODO: make target package name configurable? i.e. based on name
addFile('''src/«path»/imported.tdltx''',
ConverterNext.processToString(dataDefinitionsPath.value,
"src/"+path.value+"/imported.tdltx",
sourceMapping.value,
targetMapping.value
))
addFile('''src/«path»/Model.tdltx''', '''
/*
* This is an example package
*/
Package «name» {
Import all from Standard
Import all from generated_from_ExampleAPI_yaml
Import all from Wizardry
Type simple
}
''')
//TODO: add generated and import
//TODO: deal with missing workspace info
ConverterNext.process(dataDefinitionsPath.value, "/Users/philip-iii/Dev/workspaces/runtime/2021-06-M3-clean/"+projectInfo.projectName+"/src/imported.tdltx")
])
}
......