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