Skip to content

Commit 8a01f57

Browse files
committed
Multiple changes in the Ecore2AsyncApi transformation:
* Update README.md file to keep it consistent. * Add annotation and support custom names for Messages and Schemas. * Add annotation and support for titles in Schemas and properties. * Add annotation and support for parameters in Channel names.
1 parent 1b6f89a commit 8a01f57

File tree

2 files changed

+113
-28
lines changed

2 files changed

+113
-28
lines changed

README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,9 @@ import java.time.LocalDateTime;
243243
import java.util.UUID;
244244

245245
import schemas.LightMeasuredPayload;
246-
import smartylighting.streetlights._1._0.event.__streetlightId_.lighting.measured.PublishLightMeasured;
247-
import smartylighting.streetlights._1._0.event.__streetlightId_.lighting.measured.PublishLightMeasured.PublishLightMeasuredParams;
248-
import smartylighting.streetlights._1._0.event.__streetlightId_.lighting.measured.SubscribeLightMeasured;
246+
import smartylighting.streetlights._1._0.event._streetlightId_.lighting.measured.PublishLightMeasured;
247+
import smartylighting.streetlights._1._0.event._streetlightId_.lighting.measured.PublishLightMeasured.PublishLightMeasuredParams;
248+
import smartylighting.streetlights._1._0.event._streetlightId_.lighting.measured.SubscribeLightMeasured;
249249

250250
public class MainExample {
251251
public static void main(String[] args) throws Exception {
@@ -299,10 +299,13 @@ public class MainExample {
299299
It is possible to generate an skeleton AsyncAPI Specification from an Ecore model. The generator will create a reusable JSON Schema for each domain class. Channels will be created out of annotated EClasses. Moreover, hosts information can also be specified via EAnnotations. Currently, the following EAnnotations are allowed:
300300

301301

302-
| Ecore Element | EAnnotation Source | Description
303-
| ------------- | ---------------------------------------------------------- | -----------
304-
| EPackage | `http://io.github.abelgomez/asyncapi/eAnnotations/Server` | List of Servers. Expect entries: `name` (Server name), `url` (Server url, including port) and `protocol` (AsyncAPI supported protocol).
305-
| EClass | `http://io.github.abelgomez/asyncapi/eAnnotations/Channel` | The EClass represents the Payload of a given Channel. Expected entries: `name` (Channel name), `description` (Channel description), `publish` (publish `operationId`) and `subscribe` (subscribe `operationId`).
302+
| Ecore Element | EAnnotation Source | Description
303+
| ------------------ | ---------------------------------------------------------- | -----------
304+
| EPackage | `http://io.github.abelgomez/asyncapi/eAnnotations/Server` | List of Servers. Expect entries: `name` (Server name), `url` (Server url, including port) and `protocol` (AsyncAPI supported protocol).
305+
| EClass | `http://io.github.abelgomez/asyncapi/eAnnotations/Channel` | The EClass represents the Payload of a given Channel. Expected entries: `name` (Channel name), `description` (Channel description), `publish` (publish `operationId`) and `subscribe` (subscribe `operationId`).
306+
| EClass | `http://io.github.abelgomez/asyncapi/eAnnotations/Message` | The EClass represents the Payload of a given Message. Expected entries: `name` (Message name).
307+
| EClass | `http://io.github.abelgomez/asyncapi/eAnnotations/Schema` | The EClass represents a Payload. Expected entries: `name` (Schema name), `title` (Friendly name of the Schema).
308+
| EStructuralFeature | `http://io.github.abelgomez/asyncapi/eAnnotations/Schema` | The EStructuralFeature is a property part of a Payload. Expected entries: `title` (Friendly name for the property).
306309

307310
This is a possible example Ecore file demonstrating these annotations:
308311

plugins/io.github.abelgomez.asyncapi/src/io/github/abelgomez/asyncapi/generator/Ecore2AsyncApi.xtend

Lines changed: 103 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ import org.eclipse.emf.ecore.util.Diagnostician
3232
import org.eclipse.emf.ecore.util.EcoreUtil
3333
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl
3434
import org.eclipse.xtext.EcoreUtil2
35+
import io.github.abelgomez.asyncapi.asyncApi.Parameter
36+
import io.github.abelgomez.asyncapi.asyncApi.NamedParameter
37+
import io.github.abelgomez.asyncapi.asyncApi.AbstractParameter
38+
import java.util.List
3539

3640
class Ecore2AsyncApi {
3741

@@ -48,6 +52,14 @@ class Ecore2AsyncApi {
4852
public static final String EANNOTATION_CHANNEL_DESCRIPTION = "description"
4953
public static final String EANNOTATION_CHANNEL_PUBLISH = "publish"
5054
public static final String EANNOTATION_CHANNEL_SUBSCRIBE = "subscribe"
55+
public static final String EANNOTATION_CHANNEL_PARAMETERS= "parameters"
56+
57+
public static final String EANNOTATION_MESSAGE = BASE_EANNOTATION_URI + "Message"
58+
public static final String EANNOTATION_MESSAGE_NAME = "name"
59+
60+
public static final String EANNOTATION_SCHEMA = BASE_EANNOTATION_URI + "Schema"
61+
public static final String EANNOTATION_SCHEMA_NAME = "name"
62+
public static final String EANNOTATION_SCHEMA_TITLE = "title"
5163

5264
static def CharSequence generate(EPackage ePackage) {
5365
return ePackage.asyncApi.generate
@@ -92,12 +104,35 @@ class Ecore2AsyncApi {
92104
static def CharSequence generate(Channel c) '''
93105
"«c.name»" : {
94106
"description" : "«c.description»"«
107+
IF !c.parameters.empty»,
108+
"parameters" : {
109+
«c.parameters.map[generate].join(",\n"
110+
ENDIF»«
95111
IF c.publish !== null»,
96112
"publish" : «c.publish.generate»«ENDIF»«
97113
IF c.subscribe !== null»,
98114
"subscribe" : «c.subscribe.generate»«ENDIF»
99115
}'''
100116
117+
static def CharSequence generate(NamedParameter np) '''
118+
"«np.name»" : «np.parameter.generate»'''
119+
120+
static def CharSequence generate(AbstractParameter abp) '''
121+
«if (abp instanceof Parameter)
122+
abp.generate
123+
else if (abp instanceof Reference)
124+
abp.generate
125+
»'''
126+
127+
static def CharSequence generate(Parameter p) '''
128+
{
129+
"schema" : «p.schema.generate»«
130+
IF p.description !== null»,
131+
"description" : "«p.description»"«ENDIF»«
132+
IF p.location !== null»,
133+
"location" : «p.location»«ENDIF»
134+
}'''
135+
101136
static def CharSequence generate(Operation o) '''
102137
{
103138
"operationId" : "«o.operationId»",
@@ -139,6 +174,8 @@ class Ecore2AsyncApi {
139174
static def CharSequence generate(Schema s) '''
140175
{
141176
"type" : "«s.type.getName»"«
177+
IF s.title !== null»,
178+
"title" : "«s.title»"«ENDIF»«
142179
IF !s.properties.empty»,
143180
"properties" : {
144181
«s.properties.map[generate].join(",\n"
@@ -201,25 +238,22 @@ class Ecore2AsyncApi {
201238
].map [
202239
val eClass = it
203240
AsyncApiFactory.eINSTANCE.createChannel => [
204-
name = EcoreUtil.getAnnotation(eClass, EANNOTATION_CHANNEL, EANNOTATION_CHANNEL_NAME)
205-
description = EcoreUtil.getAnnotation(eClass, EANNOTATION_CHANNEL, EANNOTATION_CHANNEL_DESCRIPTION)
206-
if (EcoreUtil.getAnnotation(eClass, EANNOTATION_CHANNEL,
207-
Ecore2AsyncApi.EANNOTATION_CHANNEL_PUBLISH) !== null) {
241+
name = eClass.channelName
242+
description = eClass.channelDescription
243+
parameters += eClass.channelParameters.map[namedParameter]
244+
if (eClass.channelPublishOp !== null) {
208245
publish = AsyncApiFactory.eINSTANCE.createOperation => [
209-
operationId = EcoreUtil.getAnnotation(eClass, EANNOTATION_CHANNEL,
210-
Ecore2AsyncApi.EANNOTATION_CHANNEL_PUBLISH)
246+
operationId = eClass.channelPublishOp
211247
message = AsyncApiFactory.eINSTANCE.createReference => [
212-
uri = "#/components/messages/" + eClass.name
248+
uri = "#/components/messages/" + eClass.messageName
213249
]
214250
]
215251
}
216-
if (EcoreUtil.getAnnotation(eClass, EANNOTATION_CHANNEL,
217-
Ecore2AsyncApi.EANNOTATION_CHANNEL_SUBSCRIBE) !== null) {
252+
if (eClass.channelSubscribeOp !== null) {
218253
subscribe = AsyncApiFactory.eINSTANCE.createOperation => [
219-
operationId = EcoreUtil.getAnnotation(eClass, EANNOTATION_CHANNEL,
220-
Ecore2AsyncApi.EANNOTATION_CHANNEL_SUBSCRIBE)
254+
operationId = eClass.channelSubscribeOp
221255
message = AsyncApiFactory.eINSTANCE.createReference => [
222-
uri = "#/components/messages/" + eClass.name
256+
uri = "#/components/messages/" + eClass.messageName
223257
]
224258
]
225259
}
@@ -230,19 +264,17 @@ class Ecore2AsyncApi {
230264
static def Iterable<NamedMessage> allMessages(EPackage ePackage) {
231265
return EcoreUtil2.getAllContentsOfType(ePackage, EClass).filter [
232266
EAnnotations.exists [
233-
source == EANNOTATION_CHANNEL &&
234-
(details.get(Ecore2AsyncApi.EANNOTATION_CHANNEL_PUBLISH) !==
235-
null ||
236-
details.get(
237-
Ecore2AsyncApi.EANNOTATION_CHANNEL_SUBSCRIBE) !== null
238-
)
267+
source == EANNOTATION_CHANNEL
268+
&& (details.get(EANNOTATION_CHANNEL_PUBLISH) !== null
269+
|| details.get(EANNOTATION_CHANNEL_SUBSCRIBE) !== null
270+
)
239271
]
240272
].map [
241273
val eClass = it
242274
AsyncApiFactory.eINSTANCE.createNamedMessage => [
243-
name = eClass.name
275+
name = eClass.messageName
244276
message = AsyncApiFactory.eINSTANCE.createReference => [
245-
uri = "#/components/schemas/" + eClass.name
277+
uri = "#/components/schemas/" + eClass.schemaName
246278
]
247279
]
248280
]
@@ -252,15 +284,27 @@ class Ecore2AsyncApi {
252284
return EcoreUtil2.getAllContentsOfType(ePackage, EClass).map [
253285
val eClass = it
254286
AsyncApiFactory.eINSTANCE.createNamedSchema => [
255-
name = eClass.name
287+
name = eClass.schemaName
256288
schema = AsyncApiFactory.eINSTANCE.createSchema => [
257289
type = JsonType.OBJECT
290+
title = eClass.schemaTitle
258291
properties += eClass.EAllStructuralFeatures.map[schema]
259292
]
260293
]
261294
]
262295
}
263296
297+
static def NamedParameter namedParameter(String parameterName) {
298+
return AsyncApiFactory.eINSTANCE.createNamedParameter => [
299+
name = parameterName
300+
parameter = AsyncApiFactory.eINSTANCE.createParameter => [
301+
schema = AsyncApiFactory.eINSTANCE.createSchema => [
302+
type = JsonType.STRING
303+
]
304+
]
305+
]
306+
}
307+
264308
static def NamedSchema schema(EStructuralFeature eStructuralFeature) {
265309
return AsyncApiFactory.eINSTANCE.createNamedSchema => [
266310
name = eStructuralFeature.name
@@ -274,6 +318,9 @@ class Ecore2AsyncApi {
274318
maxItems = eStructuralFeature.upperBound
275319
]
276320
}
321+
if (eStructuralFeature.schemaTitle !== null && schema instanceof Schema) {
322+
(schema as Schema).title = eStructuralFeature.schemaTitle
323+
}
277324
]
278325
}
279326
@@ -329,6 +376,41 @@ class Ecore2AsyncApi {
329376
330377
}
331378
379+
static def String channelName(EClass eClass) {
380+
return EcoreUtil.getAnnotation(eClass, EANNOTATION_CHANNEL, EANNOTATION_CHANNEL_NAME)
381+
}
382+
383+
static def String channelDescription(EClass eClass) {
384+
return EcoreUtil.getAnnotation(eClass, EANNOTATION_CHANNEL, EANNOTATION_CHANNEL_DESCRIPTION)
385+
}
386+
387+
static def List<String> channelParameters(EClass eClass) {
388+
return EcoreUtil.getAnnotation(eClass, EANNOTATION_CHANNEL, EANNOTATION_CHANNEL_PARAMETERS).split(",").map[trim]
389+
}
390+
391+
static def String channelPublishOp(EClass eClass) {
392+
return EcoreUtil.getAnnotation(eClass, EANNOTATION_CHANNEL, EANNOTATION_CHANNEL_PUBLISH)
393+
}
394+
395+
static def String channelSubscribeOp(EClass eClass) {
396+
return EcoreUtil.getAnnotation(eClass, EANNOTATION_CHANNEL, EANNOTATION_CHANNEL_SUBSCRIBE)
397+
}
398+
399+
static def String messageName(EClass eClass) {
400+
return EcoreUtil.getAnnotation(eClass, EANNOTATION_MESSAGE, EANNOTATION_MESSAGE_NAME) ?: eClass.name
401+
}
402+
403+
static def String schemaName(EClass eClass) {
404+
return EcoreUtil.getAnnotation(eClass, EANNOTATION_SCHEMA, EANNOTATION_SCHEMA_NAME) ?: eClass.name
405+
}
406+
407+
static def String schemaTitle(EClass eClass) {
408+
return EcoreUtil.getAnnotation(eClass, EANNOTATION_SCHEMA, EANNOTATION_SCHEMA_TITLE)
409+
}
410+
411+
static def String schemaTitle(EStructuralFeature eStructuralFeature) {
412+
return EcoreUtil.getAnnotation(eStructuralFeature, EANNOTATION_SCHEMA, EANNOTATION_SCHEMA_TITLE)
413+
}
332414
333415
// Utility public methods
334416
static def String diagnoseEcoreFile(IPath path) {

0 commit comments

Comments
 (0)