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
28
29
30
31
32
33
34 package info.magnolia.config.registry;
35
36 import static info.magnolia.cms.util.ExceptionUtil.exceptionToWords;
37 import static info.magnolia.config.registry.DefinitionProvider.Problem.SeverityType.SEVERE;
38 import static java.util.stream.Collectors.toList;
39
40 import info.magnolia.config.registry.DefinitionProvider.Problem;
41 import info.magnolia.config.registry.decoration.DefinitionDecorator;
42 import info.magnolia.transformer.TransformationResult;
43
44 import java.util.ArrayList;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.List;
48
49 import com.google.common.collect.ImmutableList;
50
51
52
53
54
55
56
57
58
59 public class DefinitionProviderBuilder<T> {
60 public static <T> DefinitionProviderBuilder<T> newBuilder() {
61 return new DefinitionProviderBuilder<>();
62 }
63
64 private DefinitionMetadata metadata;
65 private DefinitionRawView rawView;
66 private T definition;
67 private List<Problem> problems = new ArrayList<>();
68 private List<DefinitionDecorator<T>> decorators = Collections.emptyList();
69 private List<String> errorMessages = new ArrayList<>();
70 private long lastModified = -1;
71
72 protected DefinitionProviderBuilder() {
73 }
74
75 public DefinitionProviderBuilder<T> metadata(DefinitionMetadata metadata) {
76 this.metadata = metadata;
77 return this;
78 }
79
80 public DefinitionProviderBuilder<T> metadata(DefinitionMetadataBuilder metadata) {
81 this.metadata = metadata.build();
82 return this;
83 }
84
85 public DefinitionProviderBuilder<T> rawView(DefinitionRawView rawView) {
86 this.rawView = rawView;
87 return this;
88 }
89
90 public DefinitionProviderBuilder<T> definition(T definition) {
91 this.definition = definition;
92 return this;
93 }
94
95 public DefinitionProviderBuilder<T> addProblem(Problem problem) {
96 this.problems.add(problem);
97 return this;
98 }
99
100 public DefinitionProviderBuilder<T> decorators(List<DefinitionDecorator<T>> decorators) {
101 this.decorators = decorators;
102 return this;
103 }
104
105
106
107
108 @Deprecated
109 public DefinitionProviderBuilder<T> addErrorMessage(String errorMessage) {
110 this.errorMessages.add(errorMessage);
111 return this;
112 }
113
114 public DefinitionProviderBuilder<T> withLastModifed(long lastModified) {
115 this.lastModified = lastModified;
116 return this;
117 }
118
119 public DefinitionProvider<T> buildFromTransformationResult(TransformationResult<T> transformationResult) {
120 try {
121 transformationResult.getProblems().forEach(transformationProblem -> addProblem(
122 Problem
123 .fromTransformationProblem(transformationProblem)
124 .withType(Problem.DefaultTypes.RESOLUTION)
125 .withTitle("Source data processing problem")
126 .withDetails(transformationProblem.getMessage())
127 .build()));
128
129 definition(transformationResult.get());
130 } catch (Exception e) {
131 final String errorMessage = exceptionToWords(e);
132 addProblem(
133 Problem
134 .severe()
135 .withDetails(errorMessage)
136 .withType(Problem.DefaultTypes.RESOLUTION)
137 .withTitle("Source data processing failed with un-expected exception")
138 .build());
139 }
140
141 DefinitionProvider<T> provider = build();
142
143 if (provider.isValid() && !metadata.getType().baseClass().isInstance(provider.get())) {
144 addProblem(Problem.severe()
145 .withDetails(String.format("Resolved definition type is %s, which is not a child of the registry's base type %s. Fix definition class or move %s to proper location.", definition.getClass().getName(), metadata.getType().baseClass().getName(), metadata.getLocation()))
146 .withType(Problem.DefaultTypes.RESOLUTION)
147 .withTitle("Incompatible definition type")
148 .build());
149
150 provider = new DefinitionProviderWrapper<T>(provider) {
151 @Override
152 public boolean isValid() {
153 return false;
154 }
155 };
156 }
157 return provider;
158 }
159
160 public DefinitionProvider<T> build() {
161 return new DefinitionProviderImpl<>(
162 this.metadata,
163 this.rawView,
164 this.definition,
165 ImmutableList.<String>builder()
166 .addAll(this.errorMessages)
167 .addAll(this.problems.stream()
168 .map(problem -> problem.getTitle() + problem.getDetails())
169 .collect(toList()))
170 .build(),
171 this.problems,
172 this.lastModified > 0 ? lastModified : System.currentTimeMillis(),
173 decorators
174 );
175 }
176
177
178
179
180 static class DefinitionProviderImpl<T> implements DefinitionProvider<T> {
181 private final List<Problem> problems;
182 private final DefinitionMetadata metadata;
183 private final DefinitionRawView rawView;
184 private final T definition;
185 private final List<String> errorMessages;
186 private final boolean valid;
187 private final long lastModified;
188 private final List<DefinitionDecorator<T>> decorators;
189
190 protected DefinitionProviderImpl(DefinitionMetadata metadata, DefinitionRawView rawView, T definition, List<String> errorMessages) {
191 this(metadata, rawView, definition, errorMessages, Collections.emptyList(), System.currentTimeMillis(), Collections.emptyList());
192 }
193
194 protected DefinitionProviderImpl(DefinitionMetadata metadata, DefinitionRawView rawView, T definition, List<String> errorMessages, List<Problem> problems, long lastModified, List<DefinitionDecorator<T>> decorators) {
195 this.metadata = metadata;
196 this.rawView = rawView;
197 this.definition = definition;
198 this.errorMessages = errorMessages;
199 this.problems = problems;
200 this.lastModified = lastModified;
201 this.decorators = decorators;
202 this.valid = metadata != null &&
203 rawView != null &&
204 definition != null &&
205 this.problems.stream()
206 .noneMatch(p -> p.getSeverityType() == SEVERE);
207 }
208
209 @Override
210 public Collection<Problem> getProblems() {
211 return problems;
212 }
213
214 @Override
215 public List<DefinitionDecorator<T>> getDecorators() {
216 return decorators;
217 }
218
219 @Override
220 public DefinitionMetadata getMetadata() {
221 return metadata;
222 }
223
224 @Override
225 public DefinitionRawView getRaw() {
226 return rawView;
227 }
228
229 @Override
230 public T get() {
231 if (!valid) {
232 throw new Registry.InvalidDefinitionException(metadata.getReferenceId());
233 }
234 return definition;
235 }
236
237 @Override
238 public boolean isValid() {
239 return valid;
240 }
241
242 @Override
243 @Deprecated
244 public List<String> getErrorMessages() {
245 return errorMessages;
246 }
247
248 @Override
249 public long getLastModified() {
250 return lastModified;
251 }
252 }
253 }