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.components.list;
25
26 import net.sf.jasperreports.engine.JRDatasetRun;
27 import net.sf.jasperreports.engine.JRElement;
28 import net.sf.jasperreports.engine.JRExpressionCollector;
29 import net.sf.jasperreports.engine.base.JRBaseObjectFactory;
30 import net.sf.jasperreports.engine.component.Component;
31 import net.sf.jasperreports.engine.component.ComponentCompiler;
32 import net.sf.jasperreports.engine.design.JRVerifier;
33 import net.sf.jasperreports.engine.type.PrintOrderEnum;
34
35 /**
36  * Compile-time handler of {@link ListComponent list component} instances.
37  * 
38  * @author Lucian Chirita (lucianc@users.sourceforge.net)
39  */

40 public class ListComponentCompiler implements ComponentCompiler
41 {
42
43     @Override
44     public void collectExpressions(Component component,
45             JRExpressionCollector collector)
46     {
47         ListComponent listComponent = (ListComponent) component;
48         JRDatasetRun datasetRun = listComponent.getDatasetRun();
49         collector.collect(datasetRun);
50         
51         JRExpressionCollector datasetCollector = collector.getDatasetCollector(
52                 datasetRun.getDatasetName());
53         JRElement[] elements = listComponent.getContents().getElements();
54         if (elements != null)
55         {
56             for (int i = 0; i < elements.length; i++)
57             {
58                 elements[i].collectExpressions(datasetCollector);
59             }
60         }
61     }
62
63     @Override
64     public Component toCompiledComponent(Component component,
65             JRBaseObjectFactory baseFactory)
66     {
67         ListComponent listComponent = (ListComponent) component;
68         StandardListComponent compiledComponent = new StandardListComponent(
69                 listComponent, baseFactory);
70         return compiledComponent;
71     }
72
73     @Override
74     public void verify(Component component, JRVerifier verifier)
75     {
76         ListComponent listComponent = (ListComponent) component;
77
78         JRDatasetRun datasetRun = listComponent.getDatasetRun();
79         if (datasetRun == null)
80         {
81             verifier.addBrokenRule("No list subdataset run set", listComponent);
82         }
83         else
84         {
85             verifier.verifyDatasetRun(datasetRun);
86         }
87         
88         ListContents listContents = listComponent.getContents();
89         
90         if (listContents == null)
91         {
92             verifier.addBrokenRule("No list contents set", listComponent);
93         }
94         else
95         {
96             PrintOrderEnum listPrintOrder = listComponent.getPrintOrderValue() == null ? PrintOrderEnum.VERTICAL : listComponent.getPrintOrderValue();
97             
98             Boolean listIgnoreWidth = listComponent.getIgnoreWidth();
99             boolean ignoreWidth = listIgnoreWidth != null && listIgnoreWidth;
100             
101             if (listContents.getHeight() < 0)
102             {
103                 verifier.addBrokenRule("List contents height must be positive.", listContents);
104             }
105             
106             int elementWidth = verifier.getCurrentComponentElement().getWidth();
107             Integer width = listContents.getWidth();
108             int contentsWidth;
109             if (width == null)
110             {
111                 contentsWidth = elementWidth;
112                 
113                 if (listPrintOrder == PrintOrderEnum.HORIZONTAL)
114                 {
115                     verifier.addBrokenRule("List contents width must be set for horizontal lists"
116                             listContents);
117                 }
118             }
119             else
120             {
121                 contentsWidth = width;
122                 
123                 if (width <= 0)
124                 {
125                     verifier.addBrokenRule("List contents width must be positive.", listContents);
126                 }
127                 
128                 if (!ignoreWidth && listPrintOrder == PrintOrderEnum.HORIZONTAL 
129                         && width > elementWidth)
130                 {
131                     verifier.addBrokenRule(
132                             "List contents width is larger than the list element width"
133                             listComponent);
134                 }
135             }
136             
137             String subdataset = datasetRun == null ? null : datasetRun.getDatasetName();
138             if (subdataset != null)
139             {
140                 verifier.pushSubdatasetContext(subdataset);
141             }
142             try
143             {
144                 verifyContents(verifier, listContents, contentsWidth);
145             }
146             finally
147             {
148                 if (subdataset != null)
149                 {
150                     verifier.popSubdatasetContext();
151                 }
152             }            
153         }
154     }
155
156     protected void verifyContents(JRVerifier verifier, ListContents listContents, int contentsWidth)
157     {
158         JRElement[] elements = listContents.getElements();
159         if (elements != null)
160         {
161             for (int i = 0; i < elements.length; i++)
162             {
163                 JRElement element = elements[i];
164                 
165                 verifier.verifyElement(element);
166                 
167                 if (element.getX() < 0 || element.getY() < 0)
168                 {
169                     verifier.addBrokenRule("Element must be placed at positive coordinates."
170                             element);
171                 }
172                 
173                 if (element.getY() + element.getHeight() > listContents.getHeight())
174                 {
175                     verifier.addBrokenRule("Element reaches outside list contents height: y = " 
176                             + element.getY() + ", height = " + element.getHeight() 
177                             + ", list contents height = " + listContents.getHeight() + ".", element);
178                 }
179                 
180                 if (element.getX() + element.getWidth() > contentsWidth)
181                 {
182                     verifier.addBrokenRule("Element reaches outside list contents width: x = " 
183                             + element.getX() + ", width = " + element.getWidth() 
184                             + ", list contents width = " + contentsWidth + ".", element);
185                 }
186             }
187         }
188     }
189
190 }
191