1
2
3
4
5
6 package gov.nist.secauto.metaschema.schemagen.json.impl;
7
8 import gov.nist.secauto.metaschema.core.model.IDefinition;
9 import gov.nist.secauto.metaschema.core.model.IFlagInstance;
10 import gov.nist.secauto.metaschema.core.model.IModelDefinition;
11 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
12 import gov.nist.secauto.metaschema.schemagen.IGenerationState;
13 import gov.nist.secauto.metaschema.schemagen.json.IDefinitionJsonSchema;
14 import gov.nist.secauto.metaschema.schemagen.json.IJsonGenerationState;
15
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Objects;
19 import java.util.stream.Collectors;
20 import java.util.stream.Stream;
21
22 import edu.umd.cs.findbugs.annotations.NonNull;
23 import edu.umd.cs.findbugs.annotations.Nullable;
24 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
25
26 public abstract class AbstractModelDefinitionJsonSchema<D extends IModelDefinition>
27 extends AbstractDefinitionJsonSchema<D> {
28 @Nullable
29 private final String jsonKeyFlagName;
30 @Nullable
31 private final String discriminatorProperty;
32 @Nullable
33 private final String discriminatorValue;
34 @NonNull
35 private final List<FlagInstanceJsonProperty> flagProperties;
36 @NonNull
37 private final IKey key;
38
39 @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Use of final fields")
40 protected AbstractModelDefinitionJsonSchema(
41 @NonNull D definition,
42 @Nullable String jsonKeyFlagName,
43 @Nullable String discriminatorProperty,
44 @Nullable String discriminatorValue) {
45 super(definition);
46 this.jsonKeyFlagName = jsonKeyFlagName;
47 this.discriminatorProperty = discriminatorProperty;
48 this.discriminatorValue = discriminatorValue;
49 this.key = IKey.of(definition, jsonKeyFlagName, discriminatorProperty, discriminatorValue);
50
51 Stream<? extends IFlagInstance> flagStream = definition.getFlagInstances().stream();
52
53
54 if (jsonKeyFlagName != null) {
55 IFlagInstance jsonKeyFlag = definition.getFlagInstanceByName(
56 definition.getContainingModule().toFlagQName(jsonKeyFlagName));
57 if (jsonKeyFlag == null) {
58 throw new IllegalArgumentException(
59 String.format("The referenced json-key flag-name '%s' does not exist on definition '%s'.",
60 jsonKeyFlagName,
61 definition.getName()));
62 }
63 flagStream = flagStream.filter(instance -> !jsonKeyFlag.equals(instance));
64 }
65
66 this.flagProperties = ObjectUtils.notNull(flagStream
67 .map(instance -> new FlagInstanceJsonProperty(ObjectUtils.requireNonNull(instance)))
68 .collect(Collectors.toUnmodifiableList()));
69 }
70
71 @Override
72 public IKey getKey() {
73 return key;
74 }
75
76 protected String getJsonKeyFlagName() {
77 return jsonKeyFlagName;
78 }
79
80 protected String getDiscriminatorProperty() {
81 return discriminatorProperty;
82 }
83
84 protected String getDiscriminatorValue() {
85 return discriminatorValue;
86 }
87
88 @Override
89 protected String generateDefinitionName(IJsonGenerationState state) {
90 IModelDefinition definition = getDefinition();
91 StringBuilder builder = new StringBuilder();
92 if (jsonKeyFlagName != null) {
93 builder
94 .append(IGenerationState.toCamelCase(jsonKeyFlagName))
95 .append("JsonKey");
96 }
97
98 if (discriminatorProperty != null || discriminatorValue != null) {
99 builder
100 .append(IGenerationState.toCamelCase(ObjectUtils.requireNonNull(discriminatorProperty)))
101 .append(IGenerationState.toCamelCase(ObjectUtils.requireNonNull(discriminatorValue)))
102 .append("Choice");
103 }
104 return state.getTypeNameForDefinition(
105 definition,
106 builder.toString());
107 }
108
109 protected List<FlagInstanceJsonProperty> getFlagProperties() {
110 return flagProperties;
111 }
112
113 @Override
114 public void gatherDefinitions(
115 @NonNull Map<IKey, IDefinitionJsonSchema<?>> gatheredDefinitions,
116 @NonNull IJsonGenerationState state) {
117 super.gatherDefinitions(gatheredDefinitions, state);
118
119 for (FlagInstanceJsonProperty property : getFlagProperties()) {
120 property.gatherDefinitions(gatheredDefinitions, state);
121 }
122 }
123
124 public static class ComplexKey implements IKey {
125 @NonNull
126 private final IDefinition definition;
127 @Nullable
128 private final String jsonKeyFlagName;
129 @Nullable
130 private final String discriminatorProperty;
131 @Nullable
132 private final String discriminatorValue;
133
134 public ComplexKey(
135 @NonNull IDefinition definition,
136 @Nullable String jsonKeyFlagName,
137 @Nullable String discriminatorProperty,
138 @Nullable String discriminatorValue) {
139 this.definition = definition;
140 this.jsonKeyFlagName = jsonKeyFlagName;
141 this.discriminatorProperty = discriminatorProperty;
142 this.discriminatorValue = discriminatorValue;
143 }
144
145 @Override
146 @NonNull
147 public IDefinition getDefinition() {
148 return definition;
149 }
150
151 @Override
152 @Nullable
153 public String getJsonKeyFlagName() {
154 return jsonKeyFlagName;
155 }
156
157 @Override
158 public String getDiscriminatorProperty() {
159 return discriminatorProperty;
160 }
161
162 @Override
163 public String getDiscriminatorValue() {
164 return discriminatorValue;
165 }
166
167 @Override
168 public int hashCode() {
169 return Objects.hash(definition, jsonKeyFlagName, discriminatorProperty, discriminatorValue);
170 }
171
172 @SuppressWarnings("PMD.OnlyOneReturn")
173 @Override
174 public boolean equals(Object obj) {
175 if (this == obj) {
176 return true;
177 }
178 if (!(obj instanceof IKey)) {
179 return false;
180 }
181 IKey other = (IKey) obj;
182 return Objects.equals(definition, other.getDefinition())
183 && Objects.equals(jsonKeyFlagName, other.getJsonKeyFlagName())
184 && Objects.equals(discriminatorProperty, other.getDiscriminatorProperty())
185 && Objects.equals(discriminatorValue, other.getDiscriminatorValue());
186 }
187 }
188 }