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.proxytoys;
35
36 import info.magnolia.i18nsystem.I18nKeyGenerator;
37 import info.magnolia.i18nsystem.I18nKeyGeneratorFactory;
38 import info.magnolia.i18nsystem.I18nParentable;
39 import info.magnolia.i18nsystem.I18nText;
40 import info.magnolia.i18nsystem.I18nable;
41 import info.magnolia.i18nsystem.I18nizer;
42 import info.magnolia.i18nsystem.LocaleProvider;
43 import info.magnolia.i18nsystem.TranslationService;
44
45 import javax.inject.Inject;
46
47 import com.thoughtworks.proxy.ProxyFactory;
48 import com.thoughtworks.proxy.factory.CglibProxyFactory;
49 import com.thoughtworks.proxy.toys.decorate.Decorating;
50 import com.thoughtworks.proxy.toys.decorate.Decorator;
51 import com.thoughtworks.proxy.toys.dispatch.Dispatching;
52
53 import net.sf.cglib.proxy.Enhancer;
54
55
56
57
58
59
60
61 @Deprecated
62 public class ProxytoysI18nizer implements I18nizer {
63 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ProxytoysI18nizer.class);
64
65 private final TranslationService translationService;
66 private final LocaleProvider localeProvider;
67 private final ProxyFactory proxyFactory;
68
69 @Inject
70 public ProxytoysI18nizer(TranslationService translationService, LocaleProvider localeProvider) {
71 this.translationService = translationService;
72 this.localeProvider = localeProvider;
73 this.proxyFactory = new CglibProxyFactory(false);
74 }
75
76 @Override
77 public <C> C decorate(C obj) {
78 if (obj == null) {
79 return null;
80 }
81
82 if (isProxied(obj.getClass()) && obj instanceof I18nParentable) {
83 throw new IllegalStateException(obj + " has already been enhanced by " + getClass().getSimpleName());
84 }
85
86 return decorateChild(obj, null);
87 }
88
89 protected <P, C> C decorateChild(C child, P parent) {
90 log.debug("About to decorate {} (parent: {})", child, parent);
91 if (child == null) {
92 return null;
93 }
94 if (child instanceof I18nParentable) {
95 log.debug(" - {} is already an instance of I18nParentable - probably because we're in a list. Assuming it's also already decorated with i18n.", child);
96 return child;
97 }
98
99
100 Class<C> originalClass = (Class<C>) child.getClass();
101 while (isProxied(originalClass)) {
102
103 originalClass = (Class<C>) originalClass.getSuperclass();
104 }
105 final C parentedChild = injectParentableInterface(originalClass, child, parent);
106
107 final C i18nd = decorateI18nTextMethods(parentedChild, originalClass, I18nParentable.class);
108 return interceptGetters(i18nd, originalClass);
109 }
110
111 protected <T, P> T injectParentableInterface(Class<? extends T> ct, T object, P parent) {
112 final I18nParentableImpl<P> parentable = new I18nParentableImpl<P>(parent);
113 return Dispatching.proxy(ct, I18nParentable.class)
114 .with(object, parentable)
115 .build(proxyFactory);
116 }
117
118 protected <T> T decorateI18nTextMethods(T obj, Class<T> proxyPrimaryType, Class... proxyMoreTypes) {
119 final I18nKeyGenerator<T> keyGen = I18nKeyGeneratorFactory.newKeyGeneratorFor(obj);
120 final I18nTextMethodDecorator<T> decorator = newI18nTextMethodDecorator(keyGen);
121
122 return decorateI18nTextMethods(obj, proxyPrimaryType, proxyMoreTypes, decorator);
123 }
124
125 protected <T> I18nTextMethodDecorator<T> newI18nTextMethodDecorator(I18nKeyGenerator<T> keyGen) {
126 return new I18nTextMethodDecorator<T>(translationService, localeProvider, keyGen);
127 }
128
129 protected <T> T decorateI18nTextMethods(T obj, Class<T> proxyPrimaryType, Class[] proxyMoreTypes, Decorator<T> decorator) {
130 return Decorating.proxy(proxyPrimaryType, proxyMoreTypes)
131 .with(obj)
132 .visiting(new FilteringMethodDecorator<T>(decorator, new MethodsAnnotatedWith(I18nText.class)))
133 .build(proxyFactory);
134 }
135
136 protected <T> T interceptGetters(T o, Class<T> originalClass) {
137 final T proxy = Decorating.proxy(originalClass, new Class[] { I18nParentable.class })
138 .with(o)
139 .visiting(new FilteringMethodDecorator<T>(new ChildDecorator<T>(this), new ReturnsAnnotatedTypeArgument(I18nable.class)))
140 .build(proxyFactory);
141 log.debug("Proxied {} (and returning {})", o, proxy);
142 return proxy;
143 }
144
145 protected boolean isProxied(Class<?> aClass) {
146
147 return proxyFactory.isProxyClass(aClass) || Enhancer.isEnhanced(aClass);
148 }
149
150 }