1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package gov.nist.secauto.metaschema.schemagen;
28
29 import gov.nist.secauto.metaschema.core.configuration.IConfiguration;
30 import gov.nist.secauto.metaschema.core.metapath.MetapathExpression;
31 import gov.nist.secauto.metaschema.core.model.IDefinition;
32 import gov.nist.secauto.metaschema.core.model.IModule;
33 import gov.nist.secauto.metaschema.core.model.INamedInstance;
34 import gov.nist.secauto.metaschema.core.model.IValuedDefinition;
35 import gov.nist.secauto.metaschema.core.model.constraint.IAllowedValue;
36 import gov.nist.secauto.metaschema.core.model.constraint.IAllowedValuesConstraint;
37 import gov.nist.secauto.metaschema.core.util.CollectionUtil;
38 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
39 import gov.nist.secauto.metaschema.schemagen.datatype.IDatatypeManager;
40
41 import java.util.ArrayList;
42 import java.util.LinkedList;
43 import java.util.List;
44 import java.util.Locale;
45
46 import edu.umd.cs.findbugs.annotations.NonNull;
47 import edu.umd.cs.findbugs.annotations.Nullable;
48
49 public abstract class AbstractGenerationState<WRITER, DATATYPE_MANAGER extends IDatatypeManager>
50 implements IGenerationState<WRITER> {
51 @NonNull
52 private final IModule module;
53 @NonNull
54 private final WRITER writer;
55 @NonNull
56 private final DATATYPE_MANAGER datatypeManager;
57 @NonNull
58 private final IInlineStrategy inlineStrategy;
59
60 @NonNull
61 private final ModuleIndex moduleIndex;
62
63 public AbstractGenerationState(
64 @NonNull IModule module,
65 @NonNull WRITER writer,
66 @NonNull IConfiguration<SchemaGenerationFeature<?>> configuration,
67 @NonNull DATATYPE_MANAGER datatypeManager) {
68 this.module = module;
69 this.writer = writer;
70 this.datatypeManager = datatypeManager;
71 this.inlineStrategy = IInlineStrategy.newInlineStrategy(configuration);
72 this.moduleIndex = ModuleIndex.indexDefinitions(module);
73 }
74
75 @Override
76 public IModule getModule() {
77 return module;
78 }
79
80 @Override
81 public WRITER getWriter() {
82 return writer;
83 }
84
85 @NonNull
86 protected DATATYPE_MANAGER getDatatypeManager() {
87 return datatypeManager;
88 }
89
90 @NonNull
91 public ModuleIndex getMetaschemaIndex() {
92 return moduleIndex;
93 }
94
95 @Override
96 public boolean isInline(@NonNull IDefinition definition) {
97 return inlineStrategy.isInline(definition, getMetaschemaIndex());
98 }
99
100
101
102
103
104
105
106
107
108 @NonNull
109 protected static AllowedValueCollection getContextIndependentEnumeratedValues(
110 @NonNull IValuedDefinition definition) {
111 List<IAllowedValue> values = new LinkedList<>();
112 boolean closed = false;
113 for (IAllowedValuesConstraint constraint : definition.getAllowedValuesConstraints()) {
114 if (!constraint.isAllowedOther()) {
115 closed = true;
116 }
117
118 if (!MetapathExpression.CONTEXT_NODE.equals(constraint.getTarget())) {
119 values = CollectionUtil.emptyList();
120 break;
121 }
122
123 values.addAll(constraint.getAllowedValues().values());
124 }
125 return new AllowedValueCollection(closed, values);
126 }
127
128
129
130
131
132
133
134
135
136
137
138 private CharSequence getTypeContext(
139 @NonNull IDefinition definition,
140 @NonNull IModule childModule) {
141 StringBuilder builder = new StringBuilder();
142 if (definition.isInline()) {
143 INamedInstance inlineInstance = definition.getInlineInstance();
144 IDefinition parentDefinition = inlineInstance.getContainingDefinition();
145
146 builder
147 .append(getTypeContext(parentDefinition, childModule))
148 .append(toCamelCase(inlineInstance.getEffectiveName()));
149 } else {
150 builder.append(toCamelCase(definition.getEffectiveName()));
151 }
152 return builder;
153 }
154
155 @NonNull
156 public String getTypeNameForDefinition(@NonNull IDefinition definition, @Nullable String suffix) {
157 StringBuilder builder = new StringBuilder()
158 .append(toCamelCase(definition.getModelType().name()))
159 .append(toCamelCase(definition.getContainingModule().getShortName()));
160
161 if (isInline(definition)) {
162 builder.append(toCamelCase(definition.getEffectiveName()));
163 } else {
164
165 builder.append(getTypeContext(definition, definition.getContainingModule()));
166 }
167 if (suffix != null && !suffix.isBlank()) {
168 builder.append(toCamelCase(suffix));
169 }
170 builder.append("Type");
171
172 return ObjectUtils.notNull(builder.toString());
173 }
174
175 @NonNull
176 protected static CharSequence toCamelCase(String text) {
177 StringBuilder builder = new StringBuilder();
178 for (String segment : text.split("\\p{Punct}")) {
179 if (segment.length() > 0) {
180 builder.append(segment.substring(0, 1).toUpperCase(Locale.ROOT));
181 }
182 if (segment.length() > 1) {
183 builder.append(segment.substring(1).toLowerCase(Locale.ROOT));
184 }
185 }
186 return builder;
187 }
188
189 public static class AllowedValueCollection {
190 private final boolean closed;
191 @NonNull
192 private final List<IAllowedValue> values;
193
194 public AllowedValueCollection(boolean closed, @NonNull List<IAllowedValue> values) {
195 this.closed = closed;
196 this.values = CollectionUtil.unmodifiableList(new ArrayList<>(values));
197 }
198
199 public boolean isClosed() {
200 return closed;
201 }
202
203 @NonNull
204 public List<IAllowedValue> getValues() {
205 return values;
206 }
207 }
208 }