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 com.google.common.collect.FluentIterable.from;
37 import static info.magnolia.config.registry.decoration.DefinitionDecorators.*;
38
39 import info.magnolia.config.registry.decoration.CachingDefinitionDecorator;
40 import info.magnolia.config.registry.decoration.DefinitionDecorator;
41 import info.magnolia.module.ModuleRegistry;
42 import info.magnolia.objectfactory.Components;
43
44 import java.util.Collection;
45 import java.util.List;
46 import java.util.Set;
47
48 import javax.annotation.Nullable;
49
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 import com.google.common.base.Function;
54 import com.google.common.base.Predicate;
55 import com.google.common.base.Predicates;
56 import com.google.common.collect.Collections2;
57 import com.google.common.collect.Lists;
58 import com.google.common.collect.Sets;
59
60
61
62
63
64
65 public abstract class AbstractRegistry<T> implements Registry<T> {
66
67 private static final Logger log = LoggerFactory.getLogger(AbstractRegistry.class);
68
69 private final RegistryMap<T> registryMap = new RegistryMap<>();
70
71 private final Set<DefinitionDecorator<T>> definitionDecorators = Sets.newHashSet();
72
73 private final ModuleRegistry moduleRegistry;
74
75
76
77
78 @Deprecated
79 public AbstractRegistry() {
80 this(Components.getComponent(ModuleRegistry.class));
81 }
82
83 public AbstractRegistry(ModuleRegistry moduleRegistry) {
84 this.moduleRegistry = moduleRegistry;
85 }
86
87 @Override
88 public void start() {
89 throw new IllegalStateException("not implemented yet");
90 }
91
92 protected RegistryMap<T> getRegistryMap() {
93 return registryMap;
94 }
95
96 @Override
97 public void register(DefinitionProvider<T> provider) {
98 getRegistryMap().put(onRegister(provider));
99 }
100
101 @Override
102 public Set<DefinitionMetadata> unregisterAndRegister(Collection<DefinitionMetadata> registeredIds, Collection<DefinitionProvider<T>> providers) {
103 final Collection<DefinitionProvider<T>> wrappedProviders = Collections2.transform(providers, new Function<DefinitionProvider<T>, DefinitionProvider<T>>() {
104 @Override
105 public DefinitionProvider<T> apply(DefinitionProvider<T> input) {
106 return onRegister(input);
107 }
108 });
109 return getRegistryMap().removeAndPutAll(registeredIds, wrappedProviders);
110 }
111
112 protected DefinitionProvider<T> onRegister(DefinitionProvider<T> provider) {
113 return provider;
114 }
115
116 @Override
117 public DefinitionProvider<T> getProvider(final DefinitionMetadata id) {
118 final DefinitionProvider<T> provider = getRegistryMap().get(id);
119 if (provider == null) {
120 throw new NoSuchDefinitionException(getReferenceId(id));
121 }
122 return getDecoratedDefinitionProvider(provider);
123 }
124
125 @Override
126 public DefinitionProvider<T> getProvider(final String referenceId) {
127 final DefinitionProvider<T> provider = getRegistryMap().getByStringKey(referenceId);
128 if (provider == null) {
129 throw new NoSuchDefinitionException(referenceId);
130 }
131 return getDecoratedDefinitionProvider(provider);
132 }
133
134 protected final DefinitionProvider<T> getDecoratedDefinitionProvider(final DefinitionProvider<T> provider) {
135
136 final List<DefinitionDecorator<T>> decorators =
137 from(this.definitionDecorators).
138 filter(appliesTo(provider)).
139 toSortedList(moduleDependencyBasedComparator(moduleRegistry));
140
141
142
143 DefinitionProvider<T> decoratedProvider = provider;
144 for (final DefinitionDecorator<T> definitionDecorator : decorators) {
145 final DefinitionMetadata definitionProviderMetadata = provider.getMetadata();
146 log.debug("Decorating [{}] definition with the reference id [{}] with [{}]", definitionProviderMetadata.getType().name(), definitionProviderMetadata.getReferenceId(), definitionDecorator.toString());
147 decoratedProvider = definitionDecorator.decorate(decoratedProvider);
148 }
149
150 return decoratedProvider;
151 }
152
153 @Override
154 public Collection<DefinitionProvider<T>> getAllProviders() {
155 return Collections2.transform(getAllMetadata(), new Function<DefinitionMetadata, DefinitionProvider<T>>() {
156 @Nullable
157 @Override
158 public DefinitionProvider<T> apply(@Nullable DefinitionMetadata input) {
159 return getProvider(input);
160 }
161 });
162 }
163
164 @Override
165 public Collection<DefinitionMetadata> getAllMetadata() {
166 return getRegistryMap().keySet();
167 }
168
169 @Override
170 public Collection<T> getAllDefinitions() {
171 final Collection<DefinitionProvider<T>> validProviders = Collections2.filter(getAllProviders(), VALID);
172 return Lists.newArrayList(Collections2.transform(validProviders, new DefinitionProviderGet<T>()));
173 }
174
175 private final Predicate<DefinitionProvider<T>> VALID = new ValidDefinitionProvider<>();
176 private final Predicate<DefinitionProvider<T>> ALL = Predicates.alwaysTrue();
177 private final Function<DefinitionProvider<T>, T> GET = new DefinitionProviderGet<>();
178
179 private static class ValidDefinitionProvider<T> implements Predicate<DefinitionProvider<T>> {
180 @Override
181 public boolean apply(DefinitionProvider<T> input) {
182 return input.isValid();
183 }
184 }
185
186 private static class DefinitionProviderGet<T> implements Function<DefinitionProvider<T>, T> {
187 @Override
188 public T apply(DefinitionProvider<T> input) {
189 return input.get();
190 }
191 }
192
193 @Override
194 public DefinitionQuery<T> query() {
195 return new DefinitionQueryImpl<>(this);
196 }
197
198 @Override
199 public void addDecorator(DefinitionDecorator<T> definitionDecorator) {
200 final CachingDefinitionDecorator<T> cachingDecorator = new CachingDefinitionDecorator<>(definitionDecorator);
201
202
203 definitionDecorators.remove(cachingDecorator);
204
205
206 definitionDecorators.add(cachingDecorator);
207 }
208
209 @Override
210 public void removeDecorator(DefinitionDecorator<T> definitionDecorator) {
211
212 final DefinitionDecorator<T> toRemove = definitionDecorator instanceof CachingDefinitionDecorator ? definitionDecorator : new CachingDefinitionDecorator<>(definitionDecorator);
213 definitionDecorators.remove(toRemove);
214 }
215
216 @Override
217 public String getReferenceId(DefinitionReference definitionReference) {
218
219
220
221
222
223 return newMetadataBuilder().
224 relativeLocation(definitionReference.getRelativeLocation()).
225 name(definitionReference.getName()).
226 module(definitionReference.getModule()).
227 buildReferenceId();
228 }
229
230 private static class DefinitionQueryImpl<T> extends DefinitionQuery<T> {
231 private final Registry registry;
232
233 public DefinitionQueryImpl(Registry registry) {
234 this.registry = registry;
235 }
236
237 @Override
238 public Collection<DefinitionProvider<T>> findMultiple() {
239 return findMultipleOn(registry);
240 }
241
242 protected Collection<DefinitionProvider<T>> findMultipleOn(final Registry<T> registry) {
243 final Collection<DefinitionMetadata> allMetadata = registry.getAllMetadata();
244 final Collection<DefinitionMetadata> matchingMetas = Collections2.filter(allMetadata, new QueryPredicate<T>(this));
245
246 return Collections2.transform(matchingMetas, new Function<DefinitionMetadata, DefinitionProvider<T>>() {
247 @Override
248 public DefinitionProvider<T> apply(DefinitionMetadata md) {
249 return registry.getProvider(md);
250 }
251 });
252 }
253 }
254
255 private static class QueryPredicate<T> implements Predicate<DefinitionMetadata> {
256 private final DefinitionQuery query;
257
258 public QueryPredicate(DefinitionQuery query) {
259 this.query = query;
260 }
261
262 @Override
263 public boolean apply(DefinitionMetadata input) {
264 boolean match = true;
265 match &= match(query.getName(), input.getName());
266 match &= match(query.getModule(), input.getModule());
267 return match;
268 }
269
270 private boolean match(String queryParam, String actual) {
271 if (queryParam == null) {
272
273 return true;
274 }
275 return queryParam.equals(actual);
276 }
277 }
278 }