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.i18nsystem;
35
36 import java.lang.reflect.AnnotatedElement;
37 import java.lang.reflect.Field;
38 import java.lang.reflect.InvocationTargetException;
39 import java.lang.reflect.Method;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.Iterator;
43 import java.util.List;
44 import java.util.Set;
45
46 import javax.annotation.Nullable;
47
48 import org.apache.commons.lang.StringUtils;
49 import org.reflections.ReflectionUtils;
50
51 import com.google.common.base.Function;
52 import com.google.common.base.Predicate;
53 import com.google.common.collect.Lists;
54
55
56
57
58
59
60
61
62 public abstract class AbstractI18nKeyGenerator<T> implements I18nKeyGenerator<T> {
63
64
65
66
67
68 @Override
69 public String[] keysFor(String undecoratedResult, T object, AnnotatedElement el) {
70 final List<String> keys = new ArrayList<String>();
71 keysFor(keys, object, el);
72 if (undecoratedResult != null) {
73 keys.add(0, undecoratedResult);
74 }
75 return keys.toArray(new String[keys.size()]);
76 }
77
78 @Override
79 public String messageBundleNameFor(T object) {
80 return resolveMessageBundleNameUpwards(object);
81 }
82
83
84
85
86 protected String resolveMessageBundleNameUpwards(Object object) {
87 String bundleName = null;
88
89 try {
90 Method getI18nBasename = object.getClass().getMethod("getI18nBasename");
91 bundleName = (String) getI18nBasename.invoke(object);
92 } catch (NoSuchMethodException e) {
93
94 } catch (SecurityException e) {
95 throw new RuntimeException(e);
96 } catch (IllegalArgumentException e) {
97 throw new RuntimeException(e);
98 } catch (IllegalAccessException e) {
99 throw new RuntimeException(e);
100 } catch (InvocationTargetException e) {
101 throw new RuntimeException(e);
102 }
103
104 if (bundleName == null) {
105 Object parent = getParentViaCast(object);
106 if (parent != null) {
107 bundleName = resolveMessageBundleNameUpwards(parent);
108 }
109 }
110
111 return bundleName;
112 }
113
114 protected abstract void keysFor(List<String> keys, T object, AnnotatedElement el);
115
116
117
118
119 protected String fieldOrGetterName(AnnotatedElement el) {
120 if (el instanceof Field) {
121 return ((Field) el).getName();
122 } else if (el instanceof Method) {
123 return getterToField((Method) el);
124 } else {
125 throw new IllegalArgumentException("Can't derive i18n key suffix from " + el);
126 }
127 }
128
129
130
131
132
133 protected <P, C> P getParentViaCast(C obj) {
134 if (!I18nParentable.class.isInstance(obj)) {
135 throw new IllegalStateException("Can't reach parent of " + obj);
136 }
137 final I18nParentable<P> cast = I18nParentable.class.cast(obj);
138 return cast.getI18nContextParent();
139 }
140
141
142
143
144
145
146
147 protected <C> List<Object> getAncestors(C obj) {
148 final ArrayList<Object> ancestors = new ArrayList<Object>();
149 Object p = getParentViaCast(obj);
150 while (p != null) {
151 ancestors.add(p);
152 p = getParentViaCast(p);
153 }
154 return ancestors;
155 }
156
157
158
159
160
161
162 protected <C> Object getRoot(C obj) {
163 Object root = null;
164 Object p = getParentViaCast(obj);
165 while (p != null) {
166 root = p;
167 p = getParentViaCast(p);
168 }
169 return root;
170 }
171
172
173
174
175
176
177 protected <C> List<I18nKeyGenerator> getAncestorKeyGenerators(C obj) {
178 return Lists.transform(getAncestors(obj), new Function<Object, I18nKeyGenerator>() {
179 @Override
180 public I18nKeyGenerator apply(@Nullable Object input) {
181 return getKeyGenerator(input);
182 }
183 });
184 }
185
186
187
188
189
190
191 protected <C> I18nKeyGenerator getRootKeyGenerator(C obj) {
192 return getKeyGenerator(getRoot(obj));
193 }
194
195
196
197
198 protected <P> I18nKeyGenerator<P> getKeyGenerator(P obj) {
199 return I18nKeyGeneratorFactory.newKeyGeneratorFor(obj);
200 }
201
202
203
204
205
206
207 protected void addKey(List<String> keys, String... parts) {
208 keys.add(keyify(parts));
209 if ("label".equals(parts[parts.length - 1])) {
210 keys.add(keyify(Arrays.copyOfRange(parts, 0, parts.length - 1)));
211 }
212 }
213
214
215
216
217 protected String keyify(String... parts) {
218 return StringUtils.join(parts, '.');
219 }
220
221
222
223
224
225
226 protected String getIdOrNameForUnknownRoot(Object obj) {
227
228 final Object root = getParentViaCast(obj) != null ? getRoot(obj) : obj;
229 @SuppressWarnings("unchecked")
230 final Set<Method> methods = ReflectionUtils.getMethods(root.getClass(), new Predicate<Method>() {
231
232 @Override
233 public boolean apply(Method input) {
234 if ("getId".equals(input.getName()) || "getName".equals(input.getName())) {
235 return true;
236 }
237 return false;
238 }
239 });
240
241 try {
242 String idOrName = null;
243 Iterator<Method> iterator = methods.iterator();
244
245 while (iterator.hasNext()) {
246 idOrName = (String) iterator.next().invoke(root);
247 if (StringUtils.isNotBlank(idOrName)) {
248 return idOrName.replaceAll(":", ".").replaceAll("/", ".");
249 }
250 }
251 return null;
252
253 } catch (IllegalArgumentException e) {
254 throw new RuntimeException(e);
255 } catch (IllegalAccessException e) {
256 throw new RuntimeException(e);
257 } catch (InvocationTargetException e) {
258 throw new RuntimeException(e);
259 }
260 }
261
262
263
264
265 private String getterToField(Method method) {
266 final String methodName = method.getName();
267 if (methodName.startsWith("get")) {
268 return methodName.substring(3, 4).toLowerCase() + methodName.substring(4);
269 } else {
270 throw new IllegalArgumentException(method + " is not a getter method");
271 }
272 }
273
274 }