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