13
13
14
14
package io .openmanufacturing .sds .aspectmodel .generator .jsonschema ;
15
15
16
+ import com .google .common .base .Strings ;
17
+ import io .openmanufacturing .sds .metamodel .IsDescribed ;
16
18
import java .math .BigDecimal ;
17
19
import java .util .HashMap ;
18
20
import java .util .LinkedList ;
19
21
import java .util .List ;
22
+ import java .util .Locale ;
20
23
import java .util .Map ;
21
24
import java .util .Optional ;
22
25
@@ -138,6 +141,7 @@ ImmutableMap.<Resource, Map<String, JsonNode>> builder()
138
141
private final Map <Resource , Map <String , JsonNode >> typeData ;
139
142
140
143
static final String JSON_SCHEMA_VERSION = "http://json-schema.org/draft-04/schema" ;
144
+ private final Locale locale ;
141
145
142
146
private enum JsonType {
143
147
NUMBER ,
@@ -188,12 +192,18 @@ private JsonNode toJsonNode() {
188
192
private final ObjectNode rootNode = factory .objectNode ();
189
193
private final Map <Base , JsonNode > hasVisited = new HashMap <>();
190
194
191
- public AspectModelJsonSchemaVisitor ( final boolean useExtendedTypes ) {
195
+ public AspectModelJsonSchemaVisitor ( final boolean useExtendedTypes , final Locale locale ) {
192
196
if ( useExtendedTypes ) {
193
197
typeData = extendedTypeData ;
194
198
} else {
195
199
typeData = openApiTypeData ;
196
200
}
201
+
202
+ this .locale = locale ;
203
+ }
204
+
205
+ public AspectModelJsonSchemaVisitor ( final boolean useExtendedTypes ) {
206
+ this ( useExtendedTypes , Locale .ENGLISH );
197
207
}
198
208
199
209
public ObjectNode getRootNode () {
@@ -206,12 +216,14 @@ public JsonNode visitBase( final Base base, final ObjectNode context ) {
206
216
}
207
217
208
218
public JsonNode visitAspectForOpenApi ( final Aspect aspect ) {
219
+ addDescription ( rootNode , aspect , locale );
209
220
return visitHasProperties ( aspect , rootNode );
210
221
}
211
222
212
223
@ Override
213
224
public JsonNode visitAspect ( final Aspect aspect , final ObjectNode context ) {
214
225
rootNode .put ( "$schema" , JSON_SCHEMA_VERSION );
226
+ addDescription ( rootNode , aspect , locale );
215
227
return visitHasProperties ( aspect , rootNode );
216
228
}
217
229
@@ -266,6 +278,7 @@ private Characteristic determineCharacteristic( final Property property ) {
266
278
@ SuppressWarnings ( "squid:S2250" )
267
279
//Amount of elements in list is in regard to amount of properties in aspect model. Even in bigger aspects this should not lead to performance issues
268
280
public JsonNode visitProperty ( final Property property , final ObjectNode context ) {
281
+ final ObjectNode propertyNode = addDescription ( factory .objectNode (), property , locale );
269
282
final Characteristic characteristic = determineCharacteristic ( property );
270
283
final String referenceNodeName ;
271
284
if ( characteristic instanceof SingleEntity ) {
@@ -278,12 +291,12 @@ public JsonNode visitProperty( final Property property, final ObjectNode context
278
291
}
279
292
280
293
if ( processedProperties .contains ( property ) ) {
281
- return factory . objectNode () .put ( "$ref" , "#/components/schemas/" + referenceNodeName );
294
+ return propertyNode .put ( "$ref" , "#/components/schemas/" + referenceNodeName );
282
295
}
283
296
processedProperties .add ( property );
284
297
final JsonNode characteristicSchema = characteristic .accept ( this , context );
285
298
setNodeInRootSchema ( characteristicSchema , referenceNodeName );
286
- return factory . objectNode () .put ( "$ref" , "#/components/schemas/" + referenceNodeName );
299
+ return propertyNode .put ( "$ref" , "#/components/schemas/" + referenceNodeName );
287
300
}
288
301
289
302
private AspectModelJsonSchemaVisitor .JsonType getSchemaTypeForAspectType ( final Resource type ) {
@@ -314,6 +327,7 @@ public JsonNode visitSortedSet( final SortedSet sortedSet, final ObjectNode cont
314
327
@ Override
315
328
public JsonNode visitCollection ( final Collection collection , final ObjectNode context ) {
316
329
final ObjectNode collectionNode = factory .objectNode ();
330
+ addDescription ( collectionNode , collection , locale );
317
331
collectionNode .put ( "type" , "array" );
318
332
final Optional <Characteristic > characteristic = collection .getElementCharacteristic ();
319
333
if ( characteristic .isPresent () ) {
@@ -338,16 +352,19 @@ public JsonNode visitCollection( final Collection collection, final ObjectNode c
338
352
@ Override
339
353
public JsonNode visitTrait ( final Trait trait , final ObjectNode context ) {
340
354
final ObjectNode propertyNode = (ObjectNode ) trait .getBaseCharacteristic ().accept ( this , context );
355
+ addDescription ( propertyNode , trait , locale );
341
356
return Stream .ofAll ( trait .getConstraints () ).foldLeft ( propertyNode , ( node , constraint ) -> ((ObjectNode ) (constraint .accept ( this , node ))) );
342
357
}
343
358
344
359
@ Override
345
360
public JsonNode visitConstraint ( final Constraint constraint , final ObjectNode context ) {
361
+ addDescription ( context , constraint , locale );
346
362
return context ;
347
363
}
348
364
349
365
@ Override
350
366
public JsonNode visitLengthConstraint ( final LengthConstraint lengthConstraint , final ObjectNode context ) {
367
+ addDescription ( context , lengthConstraint , locale );
351
368
final String itemsOrLength = "array" .equals ( context .get ( "type" ).asText () ) ? "Items" : "Length" ;
352
369
lengthConstraint .getMaxValue ().ifPresent ( maxValue -> context .put ( "max" + itemsOrLength , maxValue ) );
353
370
lengthConstraint .getMinValue ().ifPresent ( minValue -> context .put ( "min" + itemsOrLength , minValue ) );
@@ -365,12 +382,14 @@ private Try<JsonNode> getNumberNode( final Object value ) {
365
382
@ Override
366
383
public JsonNode visitRegularExpressionConstraint ( final RegularExpressionConstraint regularExpressionConstraint ,
367
384
final ObjectNode context ) {
385
+ addDescription ( context , regularExpressionConstraint , locale );
368
386
context .set ( "pattern" , factory .textNode ( regularExpressionConstraint .getValue () ) );
369
387
return context ;
370
388
}
371
389
372
390
@ Override
373
391
public JsonNode visitRangeConstraint ( final RangeConstraint rangeConstraint , final ObjectNode context ) {
392
+ addDescription ( context , rangeConstraint , locale );
374
393
rangeConstraint .getMaxValue ().map ( maxValue -> maxValue .accept ( this , context ) ).ifPresent ( value -> {
375
394
if ( value instanceof NumericNode ) {
376
395
context .set ( "maximum" , value );
@@ -401,7 +420,7 @@ public JsonNode visitEither( final Either either, final ObjectNode context ) {
401
420
properties .set ( "left" , either .getLeft ().accept ( this , properties ) );
402
421
properties .set ( "right" , either .getRight ().accept ( this , properties ) );
403
422
404
- return factory .objectNode ()
423
+ return addDescription ( factory .objectNode (), either , locale )
405
424
.put ( "additionalProperties" , false )
406
425
.<ObjectNode > set ( "properties" , properties )
407
426
.set ( "oneOf" ,
@@ -411,9 +430,12 @@ public JsonNode visitEither( final Either either, final ObjectNode context ) {
411
430
}
412
431
413
432
@ Override
414
- public JsonNode visitCharacteristic ( final Characteristic characteristic , final ObjectNode context ) {
415
- return characteristic .getDataType ().map ( type -> type .accept ( this , context ) ).orElseThrow ( () ->
416
- new DocumentGenerationException ( "Characteristic " + characteristic + " is missing a dataType" ) );
433
+ public JsonNode visitCharacteristic ( final Characteristic characteristic ,
434
+ final ObjectNode context ) {
435
+ final JsonNode dataTypeNode = characteristic .getDataType ().map ( type -> type .accept ( this , context ) )
436
+ .orElseThrow ( () -> new DocumentGenerationException ( "Characteristic " + characteristic + " is missing a dataType" ) );
437
+
438
+ return addDescription ( ( ObjectNode ) dataTypeNode , characteristic , locale );
417
439
}
418
440
419
441
private void setNodeInRootSchema ( final JsonNode node , final String name ) {
@@ -435,6 +457,7 @@ public JsonNode visitComplexType( final ComplexType complexType, final ObjectNod
435
457
final ObjectNode complexTypeNode = factory .objectNode ();
436
458
hasVisited .put ( complexType , complexTypeNode );
437
459
460
+ addDescription ( complexTypeNode , complexType , locale );
438
461
// visitHasProperties needs to be called before accept() on the supertype:
439
462
// This Entity's Properties could be extending an AbstractProperty on the supertype,
440
463
// in order to know the corresponding Characteristic this must be visited first
@@ -526,6 +549,7 @@ private JsonNode createEnumNodeWithScalarValues( final Enumeration enumeration,
526
549
final ObjectNode enumNode = type .getUrn ().equals ( RDF .langString .getURI () ) ?
527
550
factory .objectNode ().put ( "type" , "object" ) :
528
551
(ObjectNode ) type .accept ( this , context );
552
+ addDescription ( enumNode , enumeration , locale );
529
553
enumeration .getValues ().stream ()
530
554
.map ( value -> value .accept ( this , enumNode ) )
531
555
.forEach ( valuesNode ::add );
@@ -535,6 +559,7 @@ private JsonNode createEnumNodeWithScalarValues( final Enumeration enumeration,
535
559
536
560
private JsonNode createEnumNodeWithComplexValues ( final Enumeration enumeration , final BAMM bamm ) {
537
561
final ObjectNode enumNode = factory .objectNode ();
562
+ addDescription ( enumNode , enumeration , locale );
538
563
enumNode .put ( "type" , "object" );
539
564
final ArrayNode enumValueReferences = factory .arrayNode ();
540
565
enumeration .getValues ().stream ()
@@ -559,6 +584,7 @@ private JsonNode createNodeForEnumEntityInstance( final EntityInstance entityIns
559
584
final ObjectNode enumEntityInstanceNode = factory .objectNode ();
560
585
final ArrayNode required = factory .arrayNode ();
561
586
final ObjectNode properties = factory .objectNode ();
587
+ addDescription (enumEntityInstanceNode , entityInstance , locale );
562
588
enumEntityInstanceNode .put ( "type" , "object" );
563
589
564
590
final Entity entity = entityInstance .getEntityType ();
@@ -592,6 +618,7 @@ private JsonNode createNodeForEnumEntityPropertyInstance( final Property propert
592
618
}
593
619
if ( characteristic .is ( Collection .class ) ) {
594
620
final ObjectNode propertyInstanceNode = factory .objectNode ();
621
+ addDescription ( propertyInstanceNode , property , locale );
595
622
propertyInstanceNode .put ( "type" , "array" );
596
623
final ObjectNode arrayPropertyInstanceNode = factory .objectNode ();
597
624
arrayPropertyInstanceNode .set ( "type" , schemaType .toJsonNode () );
@@ -603,8 +630,19 @@ private JsonNode createNodeForEnumEntityPropertyInstance( final Property propert
603
630
return propertyInstanceNode ;
604
631
}
605
632
final ObjectNode propertyInstanceNode = factory .objectNode ();
633
+ addDescription ( propertyInstanceNode , property , locale );
606
634
propertyInstanceNode .set ( "type" , schemaType .toJsonNode () );
607
635
propertyInstanceNode .set ( "enum" , factory .arrayNode ().add ( valueForProperty .accept ( this , propertyInstanceNode ) ) );
608
636
return propertyInstanceNode ;
609
637
}
638
+
639
+ private static ObjectNode addDescription ( final ObjectNode node ,
640
+ final IsDescribed describedElement , final Locale locale ) {
641
+ final String description = describedElement .getDescription ( locale );
642
+
643
+ if ( !Strings .isNullOrEmpty ( description ) ) {
644
+ node .put ( "description" , description );
645
+ }
646
+ return node ;
647
+ }
610
648
}
0 commit comments