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 for (IFlagInstance flag : flags) {
76 assert flag != null;
77 new FlagInstanceJsonProperty(flag)
78 .generateProperty(properties, state);
79 }
80
81
82 if (jsonValueKeyFlag == null) {
83 generateSimpleFieldValueInstance(properties, state);
84 }
85
86 properties.generate(obj);
87
88 if (jsonValueKeyFlag == null) {
89 obj.put("additionalProperties", false);
90 } else {
91 ObjectNode additionalPropertiesTypeNode;
92
93 additionalPropertiesTypeNode = ObjectUtils.notNull(JsonNodeFactory.instance.objectNode());
94
95 IDataTypeJsonSchema schema = state.getDataTypeSchemaForDefinition(definition);
96 schema.generateSchemaOrRef(additionalPropertiesTypeNode, state);
97
98 ObjectNode additionalPropertiesNode = ObjectUtils.notNull(JsonNodeFactory.instance.objectNode());
99 ArrayNode allOf = additionalPropertiesNode.putArray("allOf");
100 allOf.add(additionalPropertiesTypeNode);
101 allOf.addObject()
102 .put("minProperties", properties.getRequired().size() + 1)
103 .put("maxProperties", properties.getProperties().size() + 1);
104
105 obj.set("additionalProperties", additionalPropertiesNode);
106 }
107 }
108 }
109
110 public void generateSimpleFieldValueInstance(
111 @NonNull PropertyCollection properties,
112 @NonNull IJsonGenerationState state) {
113
114 IFieldDefinition definition = getDefinition();
115
116 String propertyName = definition.getEffectiveJsonValueKeyName();
117
118 ObjectNode propertyObject = ObjectUtils.notNull(JsonNodeFactory.instance.objectNode());
119 IDataTypeJsonSchema schema = state.getDataTypeSchemaForDefinition(definition);
120 schema.generateSchemaOrRef(propertyObject, state);
121
122 properties.addProperty(propertyName, propertyObject);
123 properties.addRequired(propertyName);
124 }
125
126 @Override
127 public void gatherDefinitions(
128 @NonNull Map<IKey, IDefinitionJsonSchema<?>> gatheredDefinitions,
129 @NonNull IJsonGenerationState state) {
130 super.gatherDefinitions(gatheredDefinitions, state);
131
132 IFieldDefinition definition = getDefinition();
133 IDataTypeJsonSchema schema = state.getDataTypeSchemaForDefinition(definition);
134 if (schema instanceof IDefinitionJsonSchema) {
135 ((IDefinitionJsonSchema<?>) schema).gatherDefinitions(gatheredDefinitions, state);
136 }
137 }
138
139 }