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 info.magnolia.config.NamedDefinition;
37
38 import java.lang.reflect.Method;
39 import java.util.Collection;
40 import java.util.Set;
41
42 import com.google.common.base.Function;
43 import com.google.common.base.Predicate;
44 import com.google.common.base.Predicates;
45 import com.google.common.collect.Collections2;
46 import com.google.common.collect.Lists;
47 import com.thoughtworks.proxy.factory.CglibProxyFactory;
48 import com.thoughtworks.proxy.toys.decorate.Decorating;
49 import com.thoughtworks.proxy.toys.decorate.Decorator;
50
51
52
53
54
55
56 public abstract class AbstractRegistry<T> implements Registry<T> {
57
58 private final RegistryMap<T> registryMap = new RegistryMap<>();
59
60 private final CglibProxyFactory proxyFactory;
61
62 public AbstractRegistry() {
63 proxyFactory = new CglibProxyFactory(false);
64 }
65
66 @Override
67 public void start() {
68 throw new IllegalStateException("not implemented yet");
69 }
70
71 protected RegistryMap<T> getRegistryMap() {
72 return registryMap;
73 }
74
75 @Override
76 public void register(DefinitionProvider<T> provider) {
77 getRegistryMap().put(onRegister(provider));
78 }
79
80 @Override
81 public Set<DefinitionMetadata> unregisterAndRegister(Collection<DefinitionMetadata> registeredIds, Collection<DefinitionProvider<T>> providers) {
82 final Collection<DefinitionProvider<T>> wrappedProviders = Collections2.transform(providers, new Function<DefinitionProvider<T>, DefinitionProvider<T>>() {
83 @Override
84 public DefinitionProvider<T> apply(DefinitionProvider<T> input) {
85 return onRegister(input);
86 }
87 });
88 return getRegistryMap().removeAndPutAll(registeredIds, wrappedProviders);
89 }
90
91
92
93
94
95
96
97
98 protected DefinitionProvider<T> onRegister(DefinitionProvider<T> provider) {
99 if (provider.isValid()) {
100 final T def = provider.get();
101 final T decoratedDef;
102 if (def instanceof NamedDefinition) {
103 decoratedDef = Decorating.proxy(def).visiting(new GetNameFromMetadata<>(provider)).build(proxyFactory);
104 } else {
105 decoratedDef = def;
106 }
107
108 return new SwappedDefinitionProviderWrapper<>(provider, decoratedDef);
109 } else {
110 return provider;
111 }
112 }
113
114 @Override
115 public DefinitionProvider<T> getProvider(DefinitionMetadata id) {
116 return getRegistryMap().get(id);
117 }
118
119 @Override
120 public DefinitionProvider<T> getProvider(String referenceId) {
121 final DefinitionProvider<T> provider = getRegistryMap().getByStringKey(referenceId);
122 if (provider == null) {
123 throw new NoSuchDefinitionException(referenceId);
124 }
125 return provider;
126 }
127
128 @Override
129 public Collection<DefinitionProvider<T>> getAllProviders() {
130 return getRegistryMap().values();
131 }
132
133 @Override
134 public Collection<DefinitionMetadata> getAllMetadata() {
135 return getRegistryMap().keySet();
136 }
137
138 @Override
139 public Collection<T> getAllDefinitions() {
140 final Collection<DefinitionProvider<T>> validProviders = Collections2.filter(getAllProviders(), VALID);
141 return Lists.newArrayList(Collections2.transform(validProviders, new DefinitionProviderGet<T>()));
142 }
143
144 private final Predicate<DefinitionProvider<T>> VALID = new ValidDefinitionProvider<>();
145 private final Predicate<DefinitionProvider<T>> ALL = Predicates.alwaysTrue();
146 private final Function<DefinitionProvider<T>, T> GET = new DefinitionProviderGet<>();
147
148 private static class ValidDefinitionProvider<T> implements Predicate<DefinitionProvider<T>> {
149 @Override
150 public boolean apply(DefinitionProvider<T> input) {
151 return input.isValid();
152 }
153 }
154
155 private static class DefinitionProviderGet<T> implements Function<DefinitionProvider<T>, T> {
156 @Override
157 public T apply(DefinitionProvider<T> input) {
158 return input.get();
159 }
160 }
161
162 @Override
163 public DefinitionQuery<T> query() {
164 return new DefinitionQueryImpl<>(this);
165 }
166
167 private static class DefinitionQueryImpl<T> extends DefinitionQuery<T> {
168 private final Registry registry;
169
170 public DefinitionQueryImpl(Registry registry) {
171 this.registry = registry;
172 }
173
174 @Override
175 public Collection<DefinitionProvider<T>> findMultiple() {
176 return findMultipleOn(registry);
177 }
178
179 protected Collection<DefinitionProvider<T>> findMultipleOn(final Registry<T> registry) {
180 final Collection<DefinitionMetadata> allMetadata = registry.getAllMetadata();
181 final Collection<DefinitionMetadata> matchingMetas = Collections2.filter(allMetadata, new QueryPredicate<T>(this));
182
183 return Collections2.transform(matchingMetas, new Function<DefinitionMetadata, DefinitionProvider<T>>() {
184 @Override
185 public DefinitionProvider<T> apply(DefinitionMetadata md) {
186 return registry.getProvider(md);
187 }
188 });
189 }
190 }
191
192 private static class QueryPredicate<T> implements Predicate<DefinitionMetadata> {
193 private final DefinitionQuery query;
194
195 public QueryPredicate(DefinitionQuery query) {
196 this.query = query;
197 }
198
199 @Override
200 public boolean apply(DefinitionMetadata input) {
201 boolean match = true;
202 match &= match(query.getName(), input.getName());
203 match &= match(query.getModule(), input.getModule());
204 return match;
205 }
206
207 private boolean match(String queryParam, String actual) {
208 if (queryParam == null) {
209
210 return true;
211 }
212 return queryParam.equals(actual);
213 }
214 }
215
216 private static class GetNameFromMetadata<T> extends Decorator<T> {
217 private final DefinitionProvider<T> definitionProvider;
218
219 public GetNameFromMetadata(DefinitionProvider<T> definitionProvider) {
220 this.definitionProvider = definitionProvider;
221 }
222
223 @Override
224 public Object decorateResult(T proxy, Method method, Object[] args, Object result) {
225 if (result == null) {
226
227 if ("getName".equals(method.getName())) {
228 return definitionProvider.getMetadata().getName();
229 }
230 }
231 return result;
232 }
233 }
234
235 private static class SwappedDefinitionProviderWrapper<T> extends DefinitionProviderWrapper<T> {
236 private final T decoratedDef;
237
238 public SwappedDefinitionProviderWrapper(DefinitionProvider<T> provider, T decoratedDef) {
239 super(provider);
240 this.decoratedDef = decoratedDef;
241 }
242
243 @Override
244 public T get() {
245 return decoratedDef;
246 }
247 }
248 }