1
2
3
4
5
6 package gov.nist.secauto.metaschema.schemagen.json.impl;
7
8 import com.fasterxml.jackson.databind.node.ArrayNode;
9 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
10 import com.fasterxml.jackson.databind.node.ObjectNode;
11
12 import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
13 import gov.nist.secauto.metaschema.core.model.IFlagInstance;
14 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
15 import gov.nist.secauto.metaschema.schemagen.FlagInstanceFilter;
16 import gov.nist.secauto.metaschema.schemagen.json.IDataTypeJsonSchema;
17 import gov.nist.secauto.metaschema.schemagen.json.IDefinitionJsonSchema;
18 import gov.nist.secauto.metaschema.schemagen.json.IJsonGenerationState;
19 import gov.nist.secauto.metaschema.schemagen.json.impl.IJsonProperty.PropertyCollection;
20
21 import java.io.IOException;
22 import java.util.Collection;
23 import java.util.Map;
24
25 import edu.umd.cs.findbugs.annotations.NonNull;
26 import edu.umd.cs.findbugs.annotations.Nullable;
27
28 public class FieldDefinitionJsonSchema
29 extends AbstractModelDefinitionJsonSchema<IFieldDefinition> {
30
31 public FieldDefinitionJsonSchema(
32 @NonNull IFieldDefinition definition,
33 @Nullable String jsonKeyFlagName,
34 @Nullable String discriminatorProperty,
35 @Nullable String discriminatorValue,
36 @NonNull IJsonGenerationState state) {
37 super(definition, jsonKeyFlagName, discriminatorProperty, discriminatorValue);
38
39 state.getDataTypeSchemaForDefinition(definition);
40 }
41
42 @SuppressWarnings("PMD.CognitiveComplexity")
43 @Override
44 protected void generateBody(
45 IJsonGenerationState state,
46 ObjectNode obj) throws IOException {
47 IFieldDefinition definition = getDefinition();
48
49 Collection<? extends IFlagInstance> flags = definition.getFlagInstances();
50 String discriminatorProperty = getDiscriminatorProperty();
51 IFlagInstance jsonKeyFlag = definition.getJsonKey();
52 if (discriminatorProperty == null
53 && (flags.isEmpty() || jsonKeyFlag != null && flags.size() == 1)) {
54
55
56 IDataTypeJsonSchema schema = state.getDataTypeSchemaForDefinition(definition);
57 schema.generateSchemaOrRef(obj, state);
58 } else {
59 obj.put("type", "object");
60
61
62 IFlagInstance jsonValueKeyFlag = definition.getJsonValueKeyFlagInstance();
63 flags = FlagInstanceFilter.filterFlags(flags, jsonKeyFlag, jsonValueKeyFlag);
64
65 PropertyCollection properties = new PropertyCollection();
66
67
68 if (discriminatorProperty != null) {
69 ObjectNode discriminatorObj = state.getJsonNodeFactory().objectNode();
70 discriminatorObj.put("const", getDiscriminatorValue());
71 properties.addProperty(discriminatorProperty, discriminatorObj);
72 }
73
74
75 flags.forEach(flag -> {
76 assert flag != null;
77 new FlagInstanceJsonProperty(flag).generateProperty(properties, state);
78 });
79
80
81 if (jsonValueKeyFlag == null) {
82 generateSimpleFieldValueInstance(properties, state);
83 }
84
85 properties.generate(obj);
86
87 if (jsonValueKeyFlag == null) {
88 obj.put("additionalProperties", false);
89 } else {
90 ObjectNode additionalPropertiesTypeNode;
91
92 additionalPropertiesTypeNode = ObjectUtils.notNull(JsonNodeFactory.instance.objectNode());
93
94 IDataTypeJsonSchema schema = state.getDataTypeSchemaForDefinition(definition);
95 schema.generateSchemaOrRef(additionalPropertiesTypeNode, state);
96
97 ObjectNode additionalPropertiesNode = ObjectUtils.notNull(JsonNodeFactory.instance.objectNode());
98 ArrayNode allOf = additionalPropertiesNode.putArray("allOf");
99 allOf.add(additionalPropertiesTypeNode);
100 allOf.addObject()
101 .put("minProperties", properties.getRequired().size() + 1)
102 .put("maxProperties", properties.getProperties().size() + 1);
103
104 obj.set("additionalProperties", additionalPropertiesNode);
105 }
106 }
107 }
108
109 public void generateSimpleFieldValueInstance(
110 @NonNull PropertyCollection properties,
111 @NonNull IJsonGenerationState state) {
112
113 IFieldDefinition definition = getDefinition();
114
115 String propertyName = definition.getEffectiveJsonValueKeyName();
116
117 ObjectNode propertyObject = ObjectUtils.notNull(JsonNodeFactory.instance.objectNode());
118 IDataTypeJsonSchema schema = state.getDataTypeSchemaForDefinition(definition);
119 schema.generateSchemaOrRef(propertyObject, state);
120
121 properties.addProperty(propertyName, propertyObject);
122 properties.addRequired(propertyName);
123 }
124
125 @Override
126 public void gatherDefinitions(
127 @NonNull Map<IKey, IDefinitionJsonSchema<?>> gatheredDefinitions,
128 @NonNull IJsonGenerationState state) {
129 super.gatherDefinitions(gatheredDefinitions, state);
130
131 IFieldDefinition definition = getDefinition();
132 IDataTypeJsonSchema schema = state.getDataTypeSchemaForDefinition(definition);
133 if (schema instanceof IDefinitionJsonSchema) {
134 ((IDefinitionJsonSchema<?>) schema).gatherDefinitions(gatheredDefinitions, state);
135 }
136 }
137
138 }