1
24 package net.sf.jasperreports.export;
25
26 import java.lang.reflect.InvocationHandler;
27 import java.lang.reflect.Method;
28 import java.lang.reflect.Proxy;
29 import java.util.ArrayList;
30 import java.util.List;
31
32 import net.sf.jasperreports.engine.JRPropertiesUtil;
33 import net.sf.jasperreports.engine.JasperReportsContext;
34 import net.sf.jasperreports.engine.util.ClassUtils;
35
36
37
40 public class CompositeExporterConfigurationFactory<C extends CommonExportConfiguration>
41 {
42
45 private final JRPropertiesUtil propertiesUtil;
46 private final Class<C> configurationInterface;
47
48
51 public CompositeExporterConfigurationFactory(JasperReportsContext jasperReportsContext, Class<C> configurationInterface)
52 {
53 this.propertiesUtil = JRPropertiesUtil.getInstance(jasperReportsContext);
54 this.configurationInterface = configurationInterface;
55 }
56
57
58
61 public C getConfiguration(final C parent, final C child)
62 {
63 if (parent == null)
64 {
65 return child;
66 }
67 else
68 {
69 boolean isOverrideHints =
70 parent.isOverrideHints() == null
71 ? propertiesUtil.getBooleanProperty(ExporterConfiguration.PROPERTY_EXPORT_CONFIGURATION_OVERRIDE_REPORT_HINTS)
72 : parent.isOverrideHints();
73 return getConfiguration(parent, child, isOverrideHints);
74 }
75 }
76
77
78
81 public C getConfiguration(final C parent, final C child, boolean isOverrideHints)
82 {
83 if (parent == null)
84 {
85 return child;
86 }
87 else
88 {
89 if (isOverrideHints)
90 {
91 return getProxy(configurationInterface, new DelegateInvocationHandler(child, parent));
92 }
93 else
94 {
95 return getProxy(configurationInterface, new DelegateInvocationHandler(parent, child));
96 }
97 }
98 }
99
100
101
104 private final C getProxy(Class<?> clazz, InvocationHandler handler)
105 {
106 List<Class<?>> allInterfaces = new ArrayList<Class<?>>();
107
108 if (clazz.isInterface())
109 {
110 allInterfaces.add(clazz);
111 }
112 else
113 {
114 List<Class<?>> lcInterfaces = ClassUtils.getInterfaces(clazz);
115 allInterfaces.addAll(lcInterfaces);
116 }
117
118 @SuppressWarnings("unchecked")
119 C composite =
120 (C)Proxy.newProxyInstance(
121 ExporterConfiguration.class.getClassLoader(),
122 allInterfaces.toArray(new Class<?>[allInterfaces.size()]),
123 handler
124 );
125
126 return composite;
127 }
128
129
130
133 class DelegateInvocationHandler implements InvocationHandler
134 {
135 private final C parent;
136 private final C child;
137
138
141 public DelegateInvocationHandler(final C parent, final C child)
142 {
143 this.parent = parent;
144 this.child = child;
145 }
146
147 @Override
148 public Object invoke(
149 Object proxy,
150 Method method,
151 Object[] args
152 ) throws Throwable
153 {
154 Object value = child == null ? null : method.invoke(child, args);
155 if (value == null)
156 {
157 value = parent == null ? null : method.invoke(parent, args);
158 }
159 return value;
160 }
161 }
162 }
163