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.config.registry.decoration.DefinitionDecorators.*;
37 import static java.util.stream.Collectors.toList;
38
39 import info.magnolia.config.registry.decoration.CachingDefinitionDecorator;
40 import info.magnolia.config.registry.decoration.DefinitionDecorator;
41 import info.magnolia.config.registry.validator.DefinitionValidator;
42 import info.magnolia.config.source.stub.ConfigurationSourceTypeStub;
43 import info.magnolia.module.ModuleRegistry;
44 import info.magnolia.objectfactory.Components;
45
46 import java.util.ArrayList;
47 import java.util.Collection;
48 import java.util.HashSet;
49 import java.util.List;
50 import java.util.Optional;
51 import java.util.Set;
52
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56
57
58
59
60
61 public abstract class AbstractRegistry<T> implements Registry<T> {
62
63 private static final Logger log = LoggerFactory.getLogger(AbstractRegistry.class);
64
65 private final RegistryMap<T> registryMap = new RegistryMap<>();
66
67 private final Set<DefinitionDecorator<T>> definitionDecorators = new HashSet<>();
68
69 private final Set<DefinitionValidator<T>> validators = new HashSet<>();
70
71 private final ModuleRegistry moduleRegistry;
72
73
74
75
76 @Deprecated
77 public AbstractRegistry() {
78 this(Components.getComponent(ModuleRegistry.class));
79 }
80
81 public AbstractRegistry(ModuleRegistry moduleRegistry) {
82 this.moduleRegistry = moduleRegistry;
83 }
84
85 @Override
86 public void start() {
87 throw new IllegalStateException("not implemented yet");
88 }
89
90 protected RegistryMap<T> getRegistryMap() {
91 return registryMap;
92 }
93
94 @Override
95 public void register(DefinitionProvider<T> provider) {
96 getRegistryMap().put(onRegister(provider));
97 }
98
99 @Override
100 public Set<DefinitionMetadata> unregisterAndRegister(Collection<DefinitionMetadata> registeredIds, Collection<DefinitionProvider<T>> providers) {
101 List<DefinitionProvider<T>> wrappedProviders = providers.stream()
102 .map(this::onRegister)
103 .collect(toList());
104
105 for (DefinitionMetadata definitionMetadata : registeredIds) {
106 if (providers.stream().noneMatch(provider -> provider.getMetadata().equals(definitionMetadata))) {
107 for (DefinitionDecorator<T> definitionDecorator : definitionDecorators) {
108 if (definitionDecorator.appliesTo(getRegistryMap().get(definitionMetadata))) {
109 wrappedProviders.add(new DecoratedDefinitionProviderStub<>(this, definitionDecorator));
110 break;
111 }
112 }
113 }
114 }
115 return getRegistryMap().removeAndPutAll(registeredIds, wrappedProviders);
116 }
117
118 protected DefinitionProvider<T> onRegister(DefinitionProvider<T> provider) {
119 return provider;
120 }
121
122 @Override
123 public DefinitionProvider<T> getProvider(final DefinitionMetadata id) {
124 DefinitionProvider<T> provider = getRegistryMap().get(id);
125 if (provider == null) {
126 throw new NoSuchDefinitionException(getReferenceId(id));
127 }
128 provider = provider.isValid() ? getDecoratedDefinitionProvider(provider) : provider;
129 return validate(provider);
130 }
131
132 @Override
133 public DefinitionProvider<T> getProvider(final String referenceId) {
134 DefinitionProvider<T> provider = getRegistryMap().getByStringKey(referenceId);
135 if (provider == null) {
136 throw new NoSuchDefinitionException(referenceId);
137 }
138 provider = provider.isValid() ? getDecoratedDefinitionProvider(provider) : provider;
139 return validate(provider);
140 }
141
142 protected final DefinitionProvider<T> getDecoratedDefinitionProvider(final DefinitionProvider<T> provider) {
143
144 List<DefinitionDecorator<T>> decorators = definitionDecorators.stream()
145 .filter(appliesTo(provider))
146 .sorted(moduleDependencyBasedComparator(moduleRegistry))
147 .collect(toList());
148
149
150
151 DefinitionProvider<T> decoratedProvider = provider;
152 for (final DefinitionDecorator<T> definitionDecorator : decorators) {
153 final DefinitionMetadata definitionProviderMetadata = provider.getMetadata();
154 log.debug("Decorating [{}] definition with the reference id [{}] with [{}]", definitionProviderMetadata.getType().name(), definitionProviderMetadata.getReferenceId(), definitionDecorator.toString());
155 decoratedProvider = definitionDecorator.decorate(decoratedProvider);
156 }
157 return decoratedProvider;
158 }
159
160 @Override
161 public Collection<DefinitionProvider<T>> getAllProviders() {
162 return getAllMetadata().stream()
163 .map(this::getProvider)
164 .collect(toList());
165 }
166
167 @Override
168 public Collection<DefinitionMetadata> getAllMetadata() {
169 return getRegistryMap().keySet();
170 }
171
172 @Override
173 public Collection<T> getAllDefinitions() {
174 return getAllProviders().stream()
175 .filter(DefinitionProvider::isValid)
176 .map(DefinitionProvider::get)
177 .collect(toList());
178 }
179
180 @Override
181 @Deprecated
182 public DefinitionQuery<T> query() {
183 return DefinitionQuery.build(this);
184 }
185
186 @Override
187 public void addDecorator(DefinitionDecorator<T> definitionDecorator) {
188 if (definitionDecorator.metadata().getDecoratedDefinitionReference() != null && getAllProviders().stream().noneMatch(definitionDecorator::appliesTo)) {
189 register(new DecoratedDefinitionProviderStub<>(this, definitionDecorator));
190 }
191
192 final CachingDefinitionDecorator<T> cachingDecorator = new CachingDefinitionDecorator<>(definitionDecorator);
193
194
195 definitionDecorators.remove(cachingDecorator);
196
197
198 definitionDecorators.add(cachingDecorator);
199 }
200
201 @Override
202 public void removeDecorator(DefinitionDecorator<T> definitionDecorator) {
203
204 final DefinitionDecorator<T> toRemove = definitionDecorator instanceof CachingDefinitionDecorator ? definitionDecorator : new CachingDefinitionDecorator<>(definitionDecorator);
205 definitionDecorators.remove(toRemove);
206
207
208 final Optional<DefinitionProvider<T>> decoratedStub = getAllProviders().stream().filter(provider -> definitionDecorator.appliesTo(provider) && ConfigurationSourceTypeStub.stub == provider.getMetadata().getConfigurationSourceType()).findAny();
209 if (decoratedStub.isPresent() && definitionDecorators.stream().noneMatch(decorator -> decorator.appliesTo(decoratedStub.get()))) {
210 getRegistryMap().remove(decoratedStub.get().getMetadata());
211 }
212 }
213
214 @Override
215 public String getReferenceId(DefinitionReference definitionReference) {
216
217
218
219
220
221 return newMetadataBuilder().
222 relativeLocation(definitionReference.getRelativeLocation()).
223 name(definitionReference.getName()).
224 module(definitionReference.getModule()).
225 buildReferenceId();
226 }
227
228 Set<DefinitionDecorator<T>> getDefinitionDecorators() {
229 return definitionDecorators;
230 }
231
232 public void addValidator(DefinitionValidator<T> validator) {
233 validators.add(validator);
234 }
235
236 protected DefinitionProvider<T> validate(DefinitionProvider<T> provider) {
237 return new DefinitionProviderWrapper<T>(provider) {
238 @Override
239 public Collection<Problem> getProblems() {
240 final Collection<Problem> problems = new ArrayList<>(super.getProblems());
241 validators.forEach(validator -> problems.addAll(validator.validate(provider)));
242 return problems;
243 }
244 };
245 }
246 }