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.ui.form.fieldtype.registry;
35
36 import info.magnolia.config.registry.AbstractRegistry;
37 import info.magnolia.config.registry.DefinitionMetadataBuilder;
38 import info.magnolia.config.registry.DefinitionProvider;
39 import info.magnolia.config.registry.DefinitionProviderBuilder;
40 import info.magnolia.config.registry.DefinitionType;
41 import info.magnolia.dynamic.MagnoliaProxy;
42 import info.magnolia.module.ModuleRegistry;
43 import info.magnolia.objectfactory.Components;
44 import info.magnolia.registry.RegistrationException;
45 import info.magnolia.ui.form.field.definition.ConfiguredFieldDefinition;
46 import info.magnolia.ui.form.field.definition.FieldDefinition;
47 import info.magnolia.ui.form.fieldtype.definition.FieldTypeDefinition;
48
49 import java.util.Optional;
50 import java.util.concurrent.ExecutionException;
51 import java.util.concurrent.TimeUnit;
52
53 import javax.inject.Inject;
54 import javax.inject.Singleton;
55
56 import com.google.common.cache.CacheBuilder;
57 import com.google.common.cache.CacheLoader;
58 import com.google.common.cache.LoadingCache;
59
60 import net.sf.cglib.proxy.Enhancer;
61
62
63
64
65 @Singleton
66 public class FieldTypeDefinitionRegistry extends AbstractRegistry<FieldTypeDefinition> {
67
68 private static final DefinitionProvider<FieldTypeDefinition> NULL_DEFINITION_PROVIDER = DefinitionProviderBuilder.<FieldTypeDefinition>newBuilder().build();
69
70 private final LoadingCache<Class, DefinitionProvider<FieldTypeDefinition>> definitionProviderCache =
71 CacheBuilder.newBuilder()
72 .maximumSize(100)
73 .refreshAfterWrite(1000, TimeUnit.MILLISECONDS)
74 .initialCapacity(100)
75 .build(new CacheLoader<Class, DefinitionProvider<FieldTypeDefinition>>() {
76 @Override
77 public DefinitionProvider<FieldTypeDefinition> load(Class key) throws Exception {
78 return resolveMostActualDefinitionProvider(key);
79 }
80 });
81
82 @Inject
83 public FieldTypeDefinitionRegistry(ModuleRegistry moduleRegistry) {
84 super(moduleRegistry);
85 }
86
87
88
89
90 @Deprecated
91 public FieldTypeDefinitionRegistry() {
92 this(Components.getComponent(ModuleRegistry.class));
93 }
94
95 public Optional<DefinitionProvider<FieldTypeDefinition>> getByDefinitionType(Class<? extends FieldDefinition> definitionClass) {
96 try {
97 return Optional.ofNullable(definitionProviderCache.get(definitionClass, () -> resolveMostActualDefinitionProvider(definitionClass)));
98 } catch (ExecutionException e) {
99 return Optional.empty();
100 }
101 }
102
103 public DefinitionProvider<FieldTypeDefinition> resolveMostActualDefinitionProvider(Class<? extends FieldDefinition> definitionClass) throws RegistrationException {
104
105
106 while (Enhancer.isEnhanced(definitionClass) || MagnoliaProxy.class.isAssignableFrom(definitionClass)) {
107 definitionClass = (Class<? extends FieldDefinition>) definitionClass.getSuperclass();
108 }
109
110 if (definitionClass.equals(ConfiguredFieldDefinition.class)) {
111
112 throw new RegistrationException("");
113 }
114
115 DefinitionProvider<FieldTypeDefinition> deprecatedFieldTypeDefinition = null;
116 DefinitionProvider<FieldTypeDefinition> nonDeprecatedFieldTypeDefinition = null;
117 for (DefinitionProvider<FieldTypeDefinition> provider : getRegistryMap().values()) {
118 provider = getDecoratedDefinitionProvider(provider);
119 final FieldTypeDefinition fieldTypeDefinition = provider.get();
120 if (definitionClass.equals(fieldTypeDefinition.getDefinitionClass())) {
121
122 if (provider.getDecorators().size() > 0) {
123 return provider;
124 }
125
126
127 if (!provider.getMetadata().getDeprecation().isPresent()) {
128 nonDeprecatedFieldTypeDefinition = provider;
129 } else {
130 deprecatedFieldTypeDefinition = provider;
131 }
132 }
133 }
134
135
136 if (nonDeprecatedFieldTypeDefinition != null) {
137 return nonDeprecatedFieldTypeDefinition;
138 }
139
140
141
142 if (deprecatedFieldTypeDefinition != null) {
143 return deprecatedFieldTypeDefinition;
144 }
145
146 throw new RegistrationException("Could not find fieldType for definition " + definitionClass.getName());
147 }
148
149 public FieldTypeDefinition getByDefinition(Class<? extends FieldDefinition> definitionClass) throws RegistrationException {
150 return getByDefinitionType(definitionClass)
151 .filter(DefinitionProvider::isValid)
152 .map(DefinitionProvider::get)
153 .orElseThrow(() -> new RegistrationException("Field type definition not found or invalid for field definition type: " + definitionClass.getName()));
154 }
155
156
157
158
159 @Deprecated
160 public FieldTypeDefinition get(String id) throws RegistrationException {
161 final FieldTypeDefinition fieldTypeDefinition;
162 try {
163 fieldTypeDefinition = getProvider(id).get();
164 } catch (NoSuchDefinitionException | InvalidDefinitionException e) {
165 throw new RegistrationException(e.getMessage(), e);
166 }
167 return fieldTypeDefinition;
168 }
169
170 @Override
171 public DefinitionType type() {
172 return DefinitionTypes.FIELD_TYPE;
173 }
174
175 @Override
176 public DefinitionMetadataBuilder newMetadataBuilder() {
177 return DefinitionMetadataBuilder.usingNameAsId();
178 }
179 }