1 /*
2  * JasperReports - Free Java Reporting Library.
3  * Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
4  * http://www.jaspersoft.com
5  *
6  * Unless you have purchased a commercial license agreement from Jaspersoft,
7  * the following license terms apply:
8  *
9  * This program is part of JasperReports.
10  *
11  * JasperReports is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * JasperReports is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with JasperReports. If not, see <http://www.gnu.org/licenses/>.
23  */

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 /**
38  * @author Teodor Danciu (teodord@users.sourceforge.net)
39  */

40 public class CompositeExporterConfigurationFactory<C extends CommonExportConfiguration>
41 {
42     /**
43      * 
44      */

45     private final JRPropertiesUtil propertiesUtil;
46     private final Class<C> configurationInterface;
47     
48     /**
49      * 
50      */

51     public CompositeExporterConfigurationFactory(JasperReportsContext jasperReportsContext, Class<C> configurationInterface)
52     {
53         this.propertiesUtil = JRPropertiesUtil.getInstance(jasperReportsContext);
54         this.configurationInterface = configurationInterface;
55     }
56
57     
58     /**
59      * 
60      */

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     /**
79      * 
80      */

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     /**
102      * 
103      */

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     /**
131      * 
132      */

133     class DelegateInvocationHandler implements InvocationHandler
134     {
135         private final C parent;
136         private final C child;
137         
138         /**
139          * 
140          */

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