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.engine.base;
25
26 import java.awt.Color;
27 import java.io.IOException;
28 import java.io.ObjectInputStream;
29 import java.io.Serializable;
30 import java.util.UUID;
31
32 import net.sf.jasperreports.engine.JRConstants;
33 import net.sf.jasperreports.engine.JRDefaultStyleProvider;
34 import net.sf.jasperreports.engine.JRElement;
35 import net.sf.jasperreports.engine.JRElementGroup;
36 import net.sf.jasperreports.engine.JRExpression;
37 import net.sf.jasperreports.engine.JRGroup;
38 import net.sf.jasperreports.engine.JRPropertiesHolder;
39 import net.sf.jasperreports.engine.JRPropertiesMap;
40 import net.sf.jasperreports.engine.JRPropertyExpression;
41 import net.sf.jasperreports.engine.JRRuntimeException;
42 import net.sf.jasperreports.engine.JRStyle;
43 import net.sf.jasperreports.engine.design.events.JRChangeEventsSupport;
44 import net.sf.jasperreports.engine.design.events.JRPropertyChangeSupport;
45 import net.sf.jasperreports.engine.type.ModeEnum;
46 import net.sf.jasperreports.engine.type.PositionTypeEnum;
47 import net.sf.jasperreports.engine.type.StretchTypeEnum;
48 import net.sf.jasperreports.engine.util.JRCloneUtils;
49 import net.sf.jasperreports.engine.util.StyleResolver;
50
51
52 /**
53  * This class provides a skeleton implementation for a report element. It mostly provides internal variables, representing
54  * the most common element properties, and their getter/setter methods. It also has a constructor for initializing
55  * these properties.
56  * @author Teodor Danciu (teodord@users.sourceforge.net)
57  */

58 public abstract class JRBaseElement implements JRElement, Serializable, JRChangeEventsSupport
59 {
60
61
62     /**
63      *
64      */

65     private static final long serialVersionUID = JRConstants.SERIAL_VERSION_UID;
66
67     public static final String PROPERTY_POSITION_TYPE = "positionType";
68
69     public static final String PROPERTY_PRINT_IN_FIRST_WHOLE_BAND = "isPrintInFirstWholeBand";
70
71     public static final String PROPERTY_PRINT_REPEATED_VALUES = "isPrintRepeatedValues";
72
73     public static final String PROPERTY_PRINT_WHEN_DETAIL_OVERFLOWS = "isPrintWhenDetailOverflows";
74
75     public static final String PROPERTY_REMOVE_LINE_WHEN_BLANK = "isRemoveLineWhenBlank";
76
77     public static final String PROPERTY_STRETCH_TYPE = "stretchType";
78
79     public static final String PROPERTY_WIDTH = "width";
80
81     public static final String PROPERTY_X = "x";
82
83     /**
84      *
85      */

86     protected UUID uuid;
87     protected String key;
88     protected PositionTypeEnum positionTypeValue;
89     protected StretchTypeEnum stretchTypeValue = StretchTypeEnum.NO_STRETCH;
90     protected boolean isPrintRepeatedValues = true;
91     protected ModeEnum modeValue;
92     protected int x;
93     protected int y;
94     protected int width;
95     protected int height;
96     protected boolean isRemoveLineWhenBlank;
97     protected boolean isPrintInFirstWholeBand;
98     protected boolean isPrintWhenDetailOverflows;
99     protected Color forecolor;
100     protected Color backcolor;
101
102     /**
103      *
104      */

105     protected JRExpression printWhenExpression;
106     protected JRGroup printWhenGroupChanges;
107     protected JRElementGroup elementGroup;
108
109     protected final JRDefaultStyleProvider defaultStyleProvider;
110     protected JRStyle parentStyle;
111     protected String parentStyleNameReference;
112
113     private JRPropertiesMap propertiesMap;
114
115     private JRPropertyExpression[] propertyExpressions;
116     
117     /**
118      *
119      */

120     protected JRBaseElement(JRDefaultStyleProvider defaultStyleProvider)
121     {
122         this.defaultStyleProvider = defaultStyleProvider;
123     }
124
125
126     /**
127      * Initializes basic properties of the element.
128      * @param element an element whose properties are copied to this element. Usually it is a
129      * {@link net.sf.jasperreports.engine.design.JRDesignElement} that must be transformed into an
130      * <tt>JRBaseElement</tt> at compile time.
131      * @param factory a factory used in the compile process
132      */

133     protected JRBaseElement(JRElement element, JRBaseObjectFactory factory)
134     {
135         factory.put(element, this);
136
137         defaultStyleProvider = factory.getDefaultStyleProvider();
138
139         parentStyle = factory.getStyle(element.getStyle());
140         parentStyleNameReference = element.getStyleNameReference();
141
142         uuid = element.getUUID();
143         key = element.getKey();
144         positionTypeValue = element.getPositionTypeValue();
145         stretchTypeValue = element.getStretchTypeValue();
146         isPrintRepeatedValues = element.isPrintRepeatedValues();
147         modeValue = element.getOwnModeValue();
148         x = element.getX();
149         y = element.getY();
150         width = element.getWidth();
151         height = element.getHeight();
152         isRemoveLineWhenBlank = element.isRemoveLineWhenBlank();
153         isPrintInFirstWholeBand = element.isPrintInFirstWholeBand();
154         isPrintWhenDetailOverflows = element.isPrintWhenDetailOverflows();
155         forecolor = element.getOwnForecolor();
156         backcolor = element.getOwnBackcolor();
157
158         printWhenExpression = factory.getExpression(element.getPrintWhenExpression());
159         printWhenGroupChanges = factory.getGroup(element.getPrintWhenGroupChanges());
160         elementGroup = (JRElementGroup)factory.getVisitResult(element.getElementGroup());
161         
162         propertiesMap = JRPropertiesMap.getPropertiesClone(element);
163         propertyExpressions = factory.getPropertyExpressions(element.getPropertyExpressions());
164     }
165
166
167     @Override
168     public JRDefaultStyleProvider getDefaultStyleProvider()
169     {
170         return defaultStyleProvider;
171     }
172
173     /**
174      *
175      */

176     protected StyleResolver getStyleResolver()
177     {
178         if (getDefaultStyleProvider() != null)
179         {
180             return getDefaultStyleProvider().getStyleResolver();
181         }
182         return StyleResolver.getInstance();
183     }
184     
185     /**
186      *
187      */

188     protected JRStyle getBaseStyle()
189     {
190         if (parentStyle != null)
191         {
192             return parentStyle;
193         }
194         if (defaultStyleProvider != null)
195         {
196             return defaultStyleProvider.getDefaultStyle();
197         }
198         return null;
199     }
200
201     @Override
202     public UUID getUUID()
203     {
204         if (uuid == null)
205         {
206             uuid = UUID.randomUUID();
207         }
208         return uuid;
209     }
210
211     @Override
212     public String getKey()
213     {
214         return key;
215     }
216
217     @Override
218     public PositionTypeEnum getPositionTypeValue()
219     {
220         return positionTypeValue;
221     }
222
223     @Override
224     public void setPositionType(PositionTypeEnum positionTypeValue)
225     {
226         PositionTypeEnum old = this.positionTypeValue;
227         this.positionTypeValue = positionTypeValue;
228         getEventSupport().firePropertyChange(PROPERTY_POSITION_TYPE, old, this.positionTypeValue);
229     }
230
231     @Override
232     public StretchTypeEnum getStretchTypeValue()
233     {
234         return stretchTypeValue;
235     }
236
237     @Override
238     public void setStretchType(StretchTypeEnum stretchTypeValue)
239     {
240         StretchTypeEnum old = this.stretchTypeValue;
241         this.stretchTypeValue = stretchTypeValue;
242         getEventSupport().firePropertyChange(PROPERTY_STRETCH_TYPE, old, this.stretchTypeValue);
243     }
244
245     @Override
246     public boolean isPrintRepeatedValues()
247     {
248         return this.isPrintRepeatedValues;
249     }
250
251     @Override
252     public void setPrintRepeatedValues(boolean isPrintRepeatedValues)
253     {
254         boolean old = this.isPrintRepeatedValues;
255         this.isPrintRepeatedValues = isPrintRepeatedValues;
256         getEventSupport().firePropertyChange(PROPERTY_PRINT_REPEATED_VALUES, old, this.isPrintRepeatedValues);
257     }
258
259     @Override
260     public ModeEnum getModeValue()
261     {
262         return getStyleResolver().getMode(this, ModeEnum.OPAQUE);
263     }
264
265     @Override
266     public ModeEnum getOwnModeValue()
267     {
268         return modeValue;
269     }
270
271     @Override
272     public void setMode(ModeEnum modeValue)
273     {
274         Object old = this.modeValue;
275         this.modeValue = modeValue;
276         getEventSupport().firePropertyChange(JRBaseStyle.PROPERTY_MODE, old, this.modeValue);
277     }
278
279     @Override
280     public int getX()
281     {
282         return this.x;
283     }
284
285     @Override
286     public void setX(int x)
287     {
288         int old = this.x;
289         this.x = x;
290         getEventSupport().firePropertyChange(PROPERTY_X, old, this.x);
291     }
292
293     @Override
294     public int getY()
295     {
296         return this.y;
297     }
298
299     @Override
300     public int getWidth()
301     {
302         return this.width;
303     }
304
305     @Override
306     public void setWidth(int width)
307     {
308         int old = this.width;
309         this.width = width;
310         getEventSupport().firePropertyChange(PROPERTY_WIDTH, old, this.width);
311     }
312
313     @Override
314     public int getHeight()
315     {
316         return this.height;
317     }
318
319     @Override
320     public boolean isRemoveLineWhenBlank()
321     {
322         return this.isRemoveLineWhenBlank;
323     }
324
325     @Override
326     public void setRemoveLineWhenBlank(boolean isRemoveLine)
327     {
328         boolean old = this.isRemoveLineWhenBlank;
329         this.isRemoveLineWhenBlank = isRemoveLine;
330         getEventSupport().firePropertyChange(PROPERTY_REMOVE_LINE_WHEN_BLANK, old, this.isRemoveLineWhenBlank);
331     }
332
333     @Override
334     public boolean isPrintInFirstWholeBand()
335     {
336         return this.isPrintInFirstWholeBand;
337     }
338
339     @Override
340     public void setPrintInFirstWholeBand(boolean isPrint)
341     {
342         boolean old = this.isPrintInFirstWholeBand;
343         this.isPrintInFirstWholeBand = isPrint;
344         getEventSupport().firePropertyChange(PROPERTY_PRINT_IN_FIRST_WHOLE_BAND, old, this.isPrintInFirstWholeBand);
345     }
346
347     @Override
348     public boolean isPrintWhenDetailOverflows()
349     {
350         return this.isPrintWhenDetailOverflows;
351     }
352
353     @Override
354     public void setPrintWhenDetailOverflows(boolean isPrint)
355     {
356         boolean old = this.isPrintWhenDetailOverflows;
357         this.isPrintWhenDetailOverflows = isPrint;
358         getEventSupport().firePropertyChange(PROPERTY_PRINT_WHEN_DETAIL_OVERFLOWS, old, this.isPrintWhenDetailOverflows);
359     }
360
361     @Override
362     public Color getForecolor()
363     {
364         return getStyleResolver().getForecolor(this);
365     }
366
367     @Override
368     public Color getOwnForecolor()
369     {
370         return forecolor;
371     }
372
373     @Override
374     public void setForecolor(Color forecolor)
375     {
376         Object old = this.forecolor;
377         this.forecolor = forecolor;
378         getEventSupport().firePropertyChange(JRBaseStyle.PROPERTY_FORECOLOR, old, this.forecolor);
379     }
380
381     @Override
382     public Color getBackcolor()
383     {
384         return getStyleResolver().getBackcolor(this);
385     }
386
387     @Override
388     public Color getOwnBackcolor()
389     {
390         return backcolor;
391     }
392
393     @Override
394     public void setBackcolor(Color backcolor)
395     {
396         Object old = this.backcolor;
397         this.backcolor = backcolor;
398         getEventSupport().firePropertyChange(JRBaseStyle.PROPERTY_BACKCOLOR, old, this.backcolor);
399     }
400
401     @Override
402     public JRExpression getPrintWhenExpression()
403     {
404         return this.printWhenExpression;
405     }
406
407     @Override
408     public JRGroup getPrintWhenGroupChanges()
409     {
410         return this.printWhenGroupChanges;
411     }
412
413     @Override
414     public JRElementGroup getElementGroup()
415     {
416         return this.elementGroup;
417     }
418
419     @Override
420     public JRStyle getStyle()
421     {
422         return parentStyle;
423     }
424
425     @Override
426     public String getStyleNameReference()
427     {
428         return parentStyleNameReference;
429     }
430     
431     private transient JRPropertyChangeSupport eventSupport;
432     
433     @Override
434     public JRPropertyChangeSupport getEventSupport()
435     {
436         synchronized (this)
437         {
438             if (eventSupport == null)
439             {
440                 eventSupport = new JRPropertyChangeSupport(this);
441             }
442         }
443         
444         return eventSupport;
445     }
446
447     @Override
448     public Object clone() 
449     {
450         JRBaseElement clone = null;
451         
452         try
453         {
454             clone = (JRBaseElement)super.clone();
455         }
456         catch (CloneNotSupportedException e)
457         {
458             throw new JRRuntimeException(e);
459         }
460
461         clone.printWhenExpression = JRCloneUtils.nullSafeClone(printWhenExpression);
462         clone.propertiesMap = JRPropertiesMap.getPropertiesClone(this);
463         clone.propertyExpressions = JRCloneUtils.cloneArray(propertyExpressions);
464         clone.eventSupport = null;
465         
466         return clone;
467     }
468
469     @Override
470     public Object clone(JRElementGroup parentGroup) 
471     {
472         JRBaseElement clone = (JRBaseElement)this.clone();
473         
474         clone.elementGroup = parentGroup;
475         
476         return clone;
477     }
478
479     @Override
480     public JRElement clone(JRElementGroup parentGroup, int y)
481     {
482         JRBaseElement clone = (JRBaseElement) clone(parentGroup);
483         clone.y = y;
484         return clone;
485     }
486
487     @Override
488     public boolean hasProperties()
489     {
490         // checking for empty properties here instead of hasProperties because
491         // table components create elements with dynamic base properties
492         return propertiesMap != null && !propertiesMap.isEmpty();
493     }
494
495     @Override
496     public JRPropertiesMap getPropertiesMap()
497     {
498         if (propertiesMap == null)
499         {
500             propertiesMap = new JRPropertiesMap();
501         }
502         return propertiesMap;
503     }
504
505     @Override
506     public JRPropertiesHolder getParentProperties()
507     {
508         return null;
509     }
510
511     @Override
512     public JRPropertyExpression[] getPropertyExpressions()
513     {
514         return propertyExpressions;
515     }
516
517     
518     /*
519      * These fields are only for serialization backward compatibility.
520      */

521     private int PSEUDO_SERIAL_VERSION_UID = JRConstants.PSEUDO_SERIAL_VERSION_UID; //NOPMD
522     /**
523      * @deprecated
524      */

525     private Byte mode;
526     /**
527      * @deprecated
528      */

529     private byte positionType;
530     /**
531      * @deprecated
532      */

533     private byte stretchType;
534     
535     @SuppressWarnings("deprecation")
536     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
537     {
538         in.defaultReadObject();
539         
540         if (PSEUDO_SERIAL_VERSION_UID < JRConstants.PSEUDO_SERIAL_VERSION_UID_3_7_2)
541         {
542             modeValue = ModeEnum.getByValue(mode);
543             positionTypeValue = PositionTypeEnum.getByValue(positionType);
544             stretchTypeValue = StretchTypeEnum.getByValue(stretchType);
545             
546             mode = null;
547         }
548     }
549
550 }
551