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 @Deprecated
195 public DefinitionQuery<T> query() {
196 return DefinitionQuery.build(this);
197 }
198
199 @Override
200 public void addDecorator(DefinitionDecorator<T> definitionDecorator) {
201 final CachingDefinitionDecorator<T> cachingDecorator = new CachingDefinitionDecorator<>(definitionDecorator);
202
203
204 definitionDecorators.remove(cachingDecorator);
205
206
207 definitionDecorators.add(cachingDecorator);
208 }
209
210 @Override
211 public void removeDecorator(DefinitionDecorator<T> definitionDecorator) {
212
213 final DefinitionDecorator<T> toRemove = definitionDecorator instanceof CachingDefinitionDecorator ? definitionDecorator : new CachingDefinitionDecorator<>(definitionDecorator);
214 definitionDecorators.remove(toRemove);
215 }
216
217 @Override
218 public String getReferenceId(DefinitionReference definitionReference) {
219
220
221
222
223
224 return newMetadataBuilder().
225 relativeLocation(definitionReference.getRelativeLocation()).
226 name(definitionReference.getName()).
227 module(definitionReference.getModule()).
228 buildReferenceId();
229 }
230
231 }