KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jasperreports > crosstabs > design > JRDesignCrosstab


1 /*
2  * ============================================================================
3  * GNU Lesser General Public License
4  * ============================================================================
5  *
6  * JasperReports - Free Java report-generating library.
7  * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  *
23  * JasperSoft Corporation
24  * 303 Second Street, Suite 450 North
25  * San Francisco, CA 94107
26  * http://www.jaspersoft.com
27  */

28 package net.sf.jasperreports.crosstabs.design;
29
30 import java.beans.PropertyChangeEvent JavaDoc;
31 import java.beans.PropertyChangeListener JavaDoc;
32 import java.io.IOException JavaDoc;
33 import java.io.Serializable JavaDoc;
34 import java.net.URLStreamHandlerFactory JavaDoc;
35 import java.util.ArrayList JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.List JavaDoc;
39 import java.util.ListIterator JavaDoc;
40 import java.util.Locale JavaDoc;
41 import java.util.Map JavaDoc;
42 import java.util.ResourceBundle JavaDoc;
43 import java.util.TimeZone JavaDoc;
44
45 import net.sf.jasperreports.crosstabs.JRCellContents;
46 import net.sf.jasperreports.crosstabs.JRCrosstab;
47 import net.sf.jasperreports.crosstabs.JRCrosstabBucket;
48 import net.sf.jasperreports.crosstabs.JRCrosstabCell;
49 import net.sf.jasperreports.crosstabs.JRCrosstabColumnGroup;
50 import net.sf.jasperreports.crosstabs.JRCrosstabDataset;
51 import net.sf.jasperreports.crosstabs.JRCrosstabGroup;
52 import net.sf.jasperreports.crosstabs.JRCrosstabMeasure;
53 import net.sf.jasperreports.crosstabs.JRCrosstabParameter;
54 import net.sf.jasperreports.crosstabs.JRCrosstabRowGroup;
55 import net.sf.jasperreports.crosstabs.base.JRBaseCrosstab;
56 import net.sf.jasperreports.engine.JRAbstractObjectFactory;
57 import net.sf.jasperreports.engine.JRChild;
58 import net.sf.jasperreports.engine.JRConstants;
59 import net.sf.jasperreports.engine.JRDefaultStyleProvider;
60 import net.sf.jasperreports.engine.JRElement;
61 import net.sf.jasperreports.engine.JRException;
62 import net.sf.jasperreports.engine.JRExpression;
63 import net.sf.jasperreports.engine.JRExpressionCollector;
64 import net.sf.jasperreports.engine.JRParameter;
65 import net.sf.jasperreports.engine.JRVariable;
66 import net.sf.jasperreports.engine.design.JRDesignElement;
67 import net.sf.jasperreports.engine.design.JRDesignVariable;
68 import net.sf.jasperreports.engine.util.FormatFactory;
69 import net.sf.jasperreports.engine.util.JRStyleResolver;
70 import net.sf.jasperreports.engine.xml.JRXmlWriter;
71
72 import org.apache.commons.collections.SequencedHashMap;
73
74 /**
75  * Design-time {@link net.sf.jasperreports.crosstabs.JRCrosstab crosstab} implementation.
76  *
77  * @author Lucian Chirita (lucianc@users.sourceforge.net)
78  * @version $Id: JRDesignCrosstab.java 1485 2006-11-14 20:23:17 +0200 (Tue, 14 Nov 2006) teodord $
79  */

80 public class JRDesignCrosstab extends JRDesignElement implements JRCrosstab
81 {
82     private static final long serialVersionUID = JRConstants.SERIAL_VERSION_UID;
83
84     protected List JavaDoc parametersList;
85     protected Map JavaDoc parametersMap;
86     protected Map JavaDoc variablesList;
87     protected JRExpression parametersMapExpression;
88     protected JRDesignCrosstabDataset dataset;
89     protected List JavaDoc rowGroups;
90     protected List JavaDoc columnGroups;
91     protected List JavaDoc measures;
92     protected Map JavaDoc rowGroupsMap;
93     protected Map JavaDoc columnGroupsMap;
94     protected Map JavaDoc measuresMap;
95     protected int columnBreakOffset = DEFAULT_COLUMN_BREAK_OFFSET;
96     protected boolean repeatColumnHeaders = true;
97     protected boolean repeatRowHeaders = true;
98     protected List JavaDoc cellsList;
99     protected Map JavaDoc cellsMap;
100     protected JRDesignCrosstabCell[][] crossCells;
101     protected JRDesignCellContents whenNoDataCell;
102     protected JRDesignCellContents headerCell;
103     
104     
105     private class MeasureClassChangeListener implements PropertyChangeListener JavaDoc, Serializable JavaDoc
106     {
107         private static final long serialVersionUID = JRConstants.SERIAL_VERSION_UID;
108
109         public void propertyChange(PropertyChangeEvent JavaDoc evt)
110         {
111             measureClassChanged((JRDesignCrosstabMeasure) evt.getSource(), (String JavaDoc) evt.getNewValue());
112         }
113     }
114
115     private PropertyChangeListener JavaDoc measureClassChangeListener = new MeasureClassChangeListener();
116     
117     private static final Object JavaDoc[] BUILT_IN_PARAMETERS = new Object JavaDoc[] {
118         JRParameter.REPORT_PARAMETERS_MAP, java.util.Map JavaDoc.class,
119         JRParameter.REPORT_LOCALE, Locale JavaDoc.class,
120         JRParameter.REPORT_RESOURCE_BUNDLE, ResourceBundle JavaDoc.class,
121         JRParameter.REPORT_TIME_ZONE, TimeZone JavaDoc.class,
122         JRParameter.REPORT_FORMAT_FACTORY, FormatFactory.class,
123         JRParameter.REPORT_CLASS_LOADER, ClassLoader JavaDoc.class,
124         JRParameter.REPORT_URL_HANDLER_FACTORY, URLStreamHandlerFactory JavaDoc.class};
125     
126     private static final Object JavaDoc[] BUILT_IN_VARIABLES = new Object JavaDoc[] {
127         JRCrosstab.VARIABLE_ROW_COUNT, Integer JavaDoc.class,
128         JRCrosstab.VARIABLE_COLUMN_COUNT, Integer JavaDoc.class};
129
130     
131     /**
132      * Creates a new crosstab.
133      *
134      * @param defaultStyleProvider default style provider
135      */

136     public JRDesignCrosstab(JRDefaultStyleProvider defaultStyleProvider)
137     {
138         super(defaultStyleProvider);
139         
140         parametersList = new ArrayList JavaDoc();
141         parametersMap = new HashMap JavaDoc();
142         
143         rowGroupsMap = new HashMap JavaDoc();
144         rowGroups = new ArrayList JavaDoc();
145         columnGroupsMap = new HashMap JavaDoc();
146         columnGroups = new ArrayList JavaDoc();
147         measuresMap = new HashMap JavaDoc();
148         measures = new ArrayList JavaDoc();
149         
150         cellsMap = new HashMap JavaDoc();
151         cellsList = new ArrayList JavaDoc();
152         
153         addBuiltinParameters();
154         
155         variablesList = new SequencedHashMap();
156         addBuiltinVariables();
157         
158         dataset = new JRDesignCrosstabDataset();
159     }
160
161     private void addBuiltinParameters()
162     {
163         for (int i = 0; i < BUILT_IN_PARAMETERS.length; i++)
164         {
165             JRDesignCrosstabParameter parameter = new JRDesignCrosstabParameter();
166             parameter.setName((String JavaDoc) BUILT_IN_PARAMETERS[i++]);
167             parameter.setValueClass((Class JavaDoc) BUILT_IN_PARAMETERS[i]);
168             parameter.setSystemDefined(true);
169             try
170             {
171                 addParameter(parameter);
172             }
173             catch (JRException e)
174             {
175                 // never reached
176
}
177         }
178     }
179
180     private void addBuiltinVariables()
181     {
182         for (int i = 0; i < BUILT_IN_VARIABLES.length; ++i)
183         {
184             JRDesignVariable variable = new JRDesignVariable();
185             variable.setName((String JavaDoc) BUILT_IN_VARIABLES[i]);
186             variable.setValueClass((Class JavaDoc) BUILT_IN_VARIABLES[++i]);
187             variable.setCalculation(JRVariable.CALCULATION_SYSTEM);
188             variable.setSystemDefined(true);
189             addVariable(variable);
190         }
191     }
192     
193     /**
194      * Creates a new crosstab.
195      */

196     public JRDesignCrosstab()
197     {
198         this(null);
199     }
200     
201     
202     /**
203      * The ID of the crosstab is only generated at compile time.
204      */

205     public int getId()
206     {
207         return 0;
208     }
209
210     public JRCrosstabDataset getDataset()
211     {
212         return dataset;
213     }
214
215     
216     /**
217      * Returns the crosstab dataset object to be used for report designing.
218      *
219      * @return the crosstab dataset design object
220      */

221     public JRDesignCrosstabDataset getDesignDataset()
222     {
223         return dataset;
224     }
225
226     public JRCrosstabRowGroup[] getRowGroups()
227     {
228         JRCrosstabRowGroup[] groups = new JRCrosstabRowGroup[rowGroups.size()];
229         rowGroups.toArray(groups);
230         return groups;
231     }
232
233     public JRCrosstabColumnGroup[] getColumnGroups()
234     {
235         JRCrosstabColumnGroup[] groups = new JRCrosstabColumnGroup[columnGroups.size()];
236         columnGroups.toArray(groups);
237         return groups;
238     }
239
240     public JRCrosstabMeasure[] getMeasures()
241     {
242         JRCrosstabMeasure[] measureArray = new JRCrosstabMeasure[measures.size()];
243         measures.toArray(measureArray);
244         return measureArray;
245     }
246
247     public void collectExpressions(JRExpressionCollector collector)
248     {
249         collector.collect(this);
250     }
251
252     public JRChild getCopy(JRAbstractObjectFactory factory)
253     {
254         return factory.getCrosstab(this);
255     }
256
257     public void writeXml(JRXmlWriter writer) throws IOException JavaDoc
258     {
259         writer.writeCrosstab(this);
260     }
261     
262     
263     /**
264      * Sets the crosstab input dataset.
265      *
266      * @param dataset the dataset
267      * @see JRCrosstab#getDataset()
268      */

269     public void setDataset(JRDesignCrosstabDataset dataset)
270     {
271         this.dataset = dataset;
272     }
273     
274     
275     /**
276      * Adds a row group.
277      * <p>
278      * This group will be a sub group of the last row group, if any.
279      *
280      * @param group the group
281      * @throws JRException
282      * @see JRCrosstab#getRowGroups()
283      */

284     public void addRowGroup(JRDesignCrosstabRowGroup group) throws JRException
285     {
286         String JavaDoc groupName = group.getName();
287         if (rowGroupsMap.containsKey(groupName) ||
288                 columnGroupsMap.containsKey(groupName) ||
289                 measuresMap.containsKey(groupName))
290         {
291             throw new JRException("A group or measure having the same name already exists in the crosstab.");
292         }
293         
294         rowGroupsMap.put(groupName, new Integer JavaDoc(rowGroups.size()));
295         rowGroups.add(group);
296         
297         addRowGroupVars(group);
298     }
299
300     
301     protected void addRowGroupVars(JRDesignCrosstabRowGroup rowGroup)
302     {
303         addVariable(rowGroup.getVariable());
304         
305         for (Iterator JavaDoc measureIt = measures.iterator(); measureIt.hasNext();)
306         {
307             JRCrosstabMeasure measure = (JRCrosstabMeasure) measureIt.next();
308             addTotalVar(measure, rowGroup, null);
309             
310             for (Iterator JavaDoc colIt = columnGroups.iterator(); colIt.hasNext();)
311             {
312                 JRCrosstabColumnGroup colGroup = (JRCrosstabColumnGroup) colIt.next();
313                 addTotalVar(measure, rowGroup, colGroup);
314             }
315         }
316     }
317     
318     
319     /**
320      * Adds a column group.
321      * <p>
322      * This group will be a sub group of the last column group, if any.
323      *
324      * @param group the group
325      * @throws JRException
326      * @see JRCrosstab#getColumnGroups()
327      */

328     public void addColumnGroup(JRDesignCrosstabColumnGroup group) throws JRException
329     {
330         String JavaDoc groupName = group.getName();
331         if (rowGroupsMap.containsKey(groupName) ||
332                 columnGroupsMap.containsKey(groupName) ||
333                 measuresMap.containsKey(groupName))
334         {
335             throw new JRException("A group or measure having the same name already exists in the crosstab.");
336         }
337         
338         columnGroupsMap.put(groupName, new Integer JavaDoc(columnGroups.size()));
339         columnGroups.add(group);
340         
341         addColGroupVars(group);
342     }
343     
344     
345     protected void addColGroupVars(JRDesignCrosstabColumnGroup colGroup)
346     {
347         addVariable(colGroup.getVariable());
348         
349         for (Iterator JavaDoc measureIt = measures.iterator(); measureIt.hasNext();)
350         {
351             JRCrosstabMeasure measure = (JRCrosstabMeasure) measureIt.next();
352             addTotalVar(measure, null, colGroup);
353
354             for (Iterator JavaDoc rowIt = rowGroups.iterator(); rowIt.hasNext();)
355             {
356                 JRCrosstabRowGroup rowGroup = (JRCrosstabRowGroup) rowIt.next();
357                 addTotalVar(measure, rowGroup, colGroup);
358             }
359         }
360     }
361
362     /**
363      * Adds a measure to the crosstab.
364      *
365      * @param measure the measure
366      * @throws JRException
367      * @see JRCrosstab#getMeasures()
368      */

369     public void addMeasure(JRDesignCrosstabMeasure measure) throws JRException
370     {
371         String JavaDoc measureName = measure.getName();
372         if (rowGroupsMap.containsKey(measureName) ||
373                 columnGroupsMap.containsKey(measureName) ||
374                 measuresMap.containsKey(measureName))
375         {
376             throw new JRException("A group or measure having the same name already exists in the crosstab.");
377         }
378         
379         measure.addPropertyChangeListener(JRDesignCrosstabMeasure.PROPERTY_VALUE_CLASS, measureClassChangeListener);
380         
381         measuresMap.put(measureName, new Integer JavaDoc(measures.size()));
382         measures.add(measure);
383         
384         addMeasureVars(measure);
385     }
386
387     protected void addMeasureVars(JRDesignCrosstabMeasure measure)
388     {
389         addVariable(measure.getVariable());
390         
391         for (Iterator JavaDoc colIt = columnGroups.iterator(); colIt.hasNext();)
392         {
393             JRCrosstabColumnGroup colGroup = (JRCrosstabColumnGroup) colIt.next();
394             addTotalVar(measure, null, colGroup);
395         }
396         
397         for (Iterator JavaDoc rowIt = rowGroups.iterator(); rowIt.hasNext();)
398         {
399             JRCrosstabRowGroup rowGroup = (JRCrosstabRowGroup) rowIt.next();
400             addTotalVar(measure, rowGroup, null);
401             
402             for (Iterator JavaDoc colIt = columnGroups.iterator(); colIt.hasNext();)
403             {
404                 JRCrosstabColumnGroup colGroup = (JRCrosstabColumnGroup) colIt.next();
405                 addTotalVar(measure, rowGroup, colGroup);
406             }
407         }
408     }
409
410
411     protected void addTotalVar(JRCrosstabMeasure measure, JRCrosstabRowGroup rowGroup, JRCrosstabColumnGroup colGroup)
412     {
413         JRDesignVariable var = new JRDesignVariable();
414         var.setCalculation(JRVariable.CALCULATION_SYSTEM);
415         var.setSystemDefined(true);
416         var.setName(getTotalVariableName(measure, rowGroup, colGroup));
417         var.setValueClassName(measure.getValueClassName());
418         addVariable(var);
419     }
420
421
422     protected void removeTotalVar(JRCrosstabMeasure measure, JRCrosstabRowGroup rowGroup, JRCrosstabColumnGroup colGroup)
423     {
424         String JavaDoc varName = getTotalVariableName(measure, rowGroup, colGroup);
425         removeVariable(varName);
426     }
427
428     
429     public static String JavaDoc getTotalVariableName(JRCrosstabMeasure measure, JRCrosstabRowGroup rowGroup, JRCrosstabColumnGroup colGroup)
430     {
431         StringBuffer JavaDoc name = new StringBuffer JavaDoc();
432         name.append(measure.getName());
433         if (rowGroup != null)
434         {
435             name.append('_');
436             name.append(rowGroup.getName());
437         }
438         if (colGroup != null)
439         {
440             name.append('_');
441             name.append(colGroup.getName());
442         }
443         name.append("_ALL");
444         return name.toString();
445     }
446
447
448     /**
449      * Removes a row group.
450      *
451      * @param groupName the group name
452      * @return the removed group
453      */

454     public JRCrosstabRowGroup removeRowGroup(String JavaDoc groupName)
455     {
456         JRCrosstabRowGroup removed = null;
457         
458         Integer JavaDoc idx = (Integer JavaDoc) rowGroupsMap.remove(groupName);
459         if (idx != null)
460         {
461             removed = (JRCrosstabRowGroup) rowGroups.remove(idx.intValue());
462             
463             for (ListIterator JavaDoc it = rowGroups.listIterator(idx.intValue()); it.hasNext();)
464             {
465                 JRCrosstabRowGroup group = (JRCrosstabRowGroup) it.next();
466                 rowGroupsMap.put(group.getName(), new Integer JavaDoc(it.previousIndex()));
467             }
468             
469             for (Iterator JavaDoc it = cellsList.iterator(); it.hasNext();)
470             {
471                 JRCrosstabCell cell = (JRCrosstabCell) it.next();
472                 String JavaDoc rowTotalGroup = cell.getRowTotalGroup();
473                 if (rowTotalGroup != null && rowTotalGroup.equals(groupName))
474                 {
475                     it.remove();
476                     cellsMap.remove(new Pair(rowTotalGroup, cell.getColumnTotalGroup()));
477                 }
478             }
479             
480             removeRowGroupVars(removed);
481         }
482         
483         return removed;
484     }
485
486     protected void removeRowGroupVars(JRCrosstabRowGroup rowGroup)
487     {
488         removeVariable(rowGroup.getVariable());
489         
490         for (Iterator JavaDoc measureIt = measures.iterator(); measureIt.hasNext();)
491         {
492             JRCrosstabMeasure measure = (JRCrosstabMeasure) measureIt.next();
493             removeTotalVar(measure, rowGroup, null);
494             
495             for (Iterator JavaDoc colIt = columnGroups.iterator(); colIt.hasNext();)
496             {
497                 JRCrosstabColumnGroup colGroup = (JRCrosstabColumnGroup) colIt.next();
498                 removeTotalVar(measure, rowGroup, colGroup);
499             }
500         }
501     }
502
503
504     /**
505      * Removes a row group.
506      *
507      * @param group the group to be removed
508      * @return the removed group
509      */

510     public JRCrosstabRowGroup removeRowGroup(JRCrosstabRowGroup group)
511     {
512         return removeRowGroup(group.getName());
513     }
514     
515     
516     /**
517      * Removes a column group.
518      *
519      * @param groupName the group name
520      * @return the removed group
521      */

522     public JRCrosstabColumnGroup removeColumnGroup(String JavaDoc groupName)
523     {
524         JRCrosstabColumnGroup removed = null;
525         
526         Integer JavaDoc idx = (Integer JavaDoc) columnGroupsMap.remove(groupName);
527         if (idx != null)
528         {
529             removed = (JRCrosstabColumnGroup) columnGroups.remove(idx.intValue());
530             
531             for (ListIterator JavaDoc it = columnGroups.listIterator(idx.intValue()); it.hasNext();)
532             {
533                 JRCrosstabColumnGroup group = (JRCrosstabColumnGroup) it.next();
534                 columnGroupsMap.put(group.getName(), new Integer JavaDoc(it.previousIndex()));
535             }
536             
537             for (Iterator JavaDoc it = cellsList.iterator(); it.hasNext();)
538             {
539                 JRCrosstabCell cell = (JRCrosstabCell) it.next();
540                 String JavaDoc columnTotalGroup = cell.getColumnTotalGroup();
541                 if (columnTotalGroup != null && columnTotalGroup.equals(groupName))
542                 {
543                     it.remove();
544                     cellsMap.remove(new Pair(cell.getRowTotalGroup(), columnTotalGroup));
545                 }
546             }
547             
548             removeColGroupVars(removed);
549         }
550         
551         return removed;
552     }
553
554     
555     protected void removeColGroupVars(JRCrosstabColumnGroup colGroup)
556     {
557         removeVariable(colGroup.getVariable());
558         
559         for (Iterator JavaDoc measureIt = measures.iterator(); measureIt.hasNext();)
560         {
561             JRCrosstabMeasure measure = (JRCrosstabMeasure) measureIt.next();
562             removeTotalVar(measure, null, colGroup);
563
564             for (Iterator JavaDoc rowIt = rowGroups.iterator(); rowIt.hasNext();)
565             {
566                 JRCrosstabRowGroup rowGroup = (JRCrosstabRowGroup) rowIt.next();
567                 removeTotalVar(measure, rowGroup, colGroup);
568             }
569         }
570     }
571     
572     
573     /**
574      * Removes a column group.
575      *
576      * @param group the group
577      * @return the removed group
578      */

579     public JRCrosstabColumnGroup removeColumnGroup(JRCrosstabColumnGroup group)
580     {
581         return removeColumnGroup(group.getName());
582     }
583     
584     
585     /**
586      * Removes a measure.
587      *
588      * @param measureName the measure name
589      * @return the removed measure
590      */

591     public JRCrosstabMeasure removeMeasure(String JavaDoc measureName)
592     {
593         JRDesignCrosstabMeasure removed = null;
594         
595         Integer JavaDoc idx = (Integer JavaDoc) measuresMap.remove(measureName);
596         if (idx != null)
597         {
598             removed = (JRDesignCrosstabMeasure) measures.remove(idx.intValue());
599             
600             for (ListIterator JavaDoc it = measures.listIterator(idx.intValue()); it.hasNext();)
601             {
602                 JRCrosstabMeasure group = (JRCrosstabMeasure) it.next();
603                 measuresMap.put(group.getName(), new Integer JavaDoc(it.previousIndex()));
604             }
605             
606             removeMeasureVars(removed);
607             
608             removed.removePropertyChangeListener(JRDesignCrosstabMeasure.PROPERTY_VALUE_CLASS, measureClassChangeListener);
609         }
610         
611         return removed;
612     }
613
614     protected void removeMeasureVars(JRDesignCrosstabMeasure measure)
615     {
616         removeVariable(measure.getVariable());
617         
618         for (Iterator JavaDoc colIt = columnGroups.iterator(); colIt.hasNext();)
619         {
620             JRCrosstabColumnGroup colGroup = (JRCrosstabColumnGroup) colIt.next();
621             removeTotalVar(measure, null, colGroup);
622         }
623         
624         for (Iterator JavaDoc rowIt = rowGroups.iterator(); rowIt.hasNext();)
625         {
626             JRCrosstabRowGroup rowGroup = (JRCrosstabRowGroup) rowIt.next();
627             removeTotalVar(measure, rowGroup, null);
628             
629             for (Iterator JavaDoc colIt = columnGroups.iterator(); colIt.hasNext();)
630             {
631                 JRCrosstabColumnGroup colGroup = (JRCrosstabColumnGroup) colIt.next();
632                 removeTotalVar(measure, rowGroup, colGroup);
633             }
634         }
635     }
636     
637     
638     /**
639      * Removes a measure.
640      *
641      * @param measure the measure
642      * @return the removed measure
643      */

644     public JRCrosstabMeasure removeMeasure(JRCrosstabMeasure measure)
645     {
646         return removeMeasure(measure.getName());
647     }
648
649     public boolean isRepeatColumnHeaders()
650     {
651         return repeatColumnHeaders;
652     }
653
654     
655     /**
656      * Sets the repeat column headers flag.
657      *
658      * @param repeatColumnHeaders whether to repeat the column headers on row breaks
659      * @see JRCrosstab#isRepeatColumnHeaders()
660      */

661     public void setRepeatColumnHeaders(boolean repeatColumnHeaders)
662     {
663         this.repeatColumnHeaders = repeatColumnHeaders;
664     }
665
666     public boolean isRepeatRowHeaders()
667     {
668         return repeatRowHeaders;
669     }
670
671     
672     /**
673      * Sets the repeat row headers flag.
674      *
675      * @param repeatRowHeaders whether to repeat the row headers on column breaks
676      * @see JRCrosstab#isRepeatRowHeaders()
677      */

678     public void setRepeatRowHeaders(boolean repeatRowHeaders)
679     {
680         this.repeatRowHeaders = repeatRowHeaders;
681     }
682
683     public JRCrosstabCell[][] getCells()
684     {
685         return crossCells;
686     }
687
688     
689     /**
690      * Returns the data cells list.
691      *
692      * @return the data cells list
693      * @see #addCell(JRDesignCrosstabCell)
694      */

695     public List JavaDoc getCellsList()
696     {
697         return cellsList;
698     }
699     
700     
701     /**
702      * Adds a data cell to the crosstab.
703      *
704      * @param cell the cell
705      * @throws JRException
706      * @see JRCrosstab#getCells()
707      */

708     public void addCell(JRDesignCrosstabCell cell) throws JRException
709     {
710         String JavaDoc rowTotalGroup = cell.getRowTotalGroup();
711         if (rowTotalGroup != null && !rowGroupsMap.containsKey(rowTotalGroup))
712         {
713             throw new JRException("Row group " + rowTotalGroup + " does not exist.");
714         }
715         
716         String JavaDoc columnTotalGroup = cell.getColumnTotalGroup();
717         if (columnTotalGroup != null && !columnGroupsMap.containsKey(columnTotalGroup))
718         {
719             throw new JRException("Row group " + columnTotalGroup + " does not exist.");
720         }
721         
722         Object JavaDoc cellKey = new Pair(rowTotalGroup, columnTotalGroup);
723         if (cellsMap.containsKey(cellKey))
724         {
725             throw new JRException("Duplicate cell in crosstab.");
726         }
727         
728         cellsMap.put(cellKey, cell);
729         cellsList.add(cell);
730     }
731     
732     
733     /**
734      * Removes a data cell.
735      *
736      * @param rowTotalGroup the cell's total row group
737      * @param columnTotalGroup the cell's total column group
738      * @return the removed cell
739      */

740     public JRCrosstabCell removeCell(String JavaDoc rowTotalGroup, String JavaDoc columnTotalGroup)
741     {
742         Object JavaDoc cellKey = new Pair(rowTotalGroup, columnTotalGroup);
743         
744         JRCrosstabCell cell = (JRCrosstabCell) cellsMap.remove(cellKey);
745         if (cell != null)
746         {
747             cellsList.remove(cell);
748         }
749         
750         return cell;
751     }
752     
753     
754     /**
755      * Removes a data cell.
756      *
757      * @param cell the cell to be removed
758      * @return the removed cell
759      */

760     public JRCrosstabCell removeCell(JRCrosstabCell cell)
761     {
762         Object JavaDoc cellKey = new Pair(cell.getRowTotalGroup(), cell.getColumnTotalGroup());
763         JRCrosstabCell removedCell = (JRCrosstabCell) cellsMap.remove(cellKey);
764         if (removedCell != null)
765         {
766             cellsList.remove(removedCell);
767         }
768         
769         return removedCell;
770     }
771     
772     private static class Pair implements Serializable JavaDoc
773     {
774         private static final long serialVersionUID = 1L;
775         
776         final Object JavaDoc o1;
777         final Object JavaDoc o2;
778         
779         Pair(Object JavaDoc o1, Object JavaDoc o2)
780         {
781             this.o1 = o1;
782             this.o2 = o2;
783         }
784         
785         public boolean equals(Object JavaDoc o)
786         {
787             if (o == this)
788             {
789                 return true;
790             }
791             
792             if (o == null || !(o instanceof Pair))
793             {
794                 return false;
795             }
796             
797             Pair p = (Pair) o;
798             
799             return (p.o1 == null ? o1 == null : (o1 != null && p.o1.equals(o1))) &&
800                 (p.o2 == null ? o2 == null : (o2 != null && p.o2.equals(o2)));
801         }
802         
803         public int hashCode()
804         {
805             int hash = o1 == null ? 0 : o1.hashCode();
806             
807             hash *= 31;
808             
809             hash += o2 == null ? 0 : o2.hashCode();
810             
811             return hash;
812         }
813     }
814
815     public JRCrosstabParameter[] getParameters()
816     {
817         JRCrosstabParameter[] parameters = new JRCrosstabParameter[parametersList.size()];
818         parametersList.toArray(parameters);
819         return parameters;
820     }
821     
822     
823     /**
824      * Returns the paremeters list.
825      *
826      * @return the paremeters list
827      */

828     public List JavaDoc getParametersList()
829     {
830         return parametersList;
831     }
832     
833     
834     /**
835      * Returns the parameters indexed by names.
836      *
837      * @return the parameters indexed by names
838      */

839     public Map JavaDoc getParametersMap()
840     {
841         return parametersMap;
842     }
843
844     public JRExpression getParametersMapExpression()
845     {
846         return parametersMapExpression;
847     }
848     
849     
850     /**
851      * Adds a parameter to the crosstab.
852      *
853      * @param parameter the parameter
854      * @throws JRException
855      * @see JRCrosstab#getMeasures()
856      */

857     public void addParameter(JRCrosstabParameter parameter) throws JRException
858     {
859         if (parametersMap.containsKey(parameter.getName()))
860         {
861             if (parametersMap.containsKey(parameter.getName()))
862             {
863                 throw new JRException("Duplicate declaration of parameter : " + parameter.getName());
864             }
865         }
866         
867         parametersMap.put(parameter.getName(), parameter);
868         parametersList.add(parameter);
869     }
870     
871     
872     /**
873      * Removes a parameter.
874      *
875      * @param parameterName the name of the parameter to be removed
876      * @return the removed parameter
877      */

878     public JRCrosstabParameter removeParameter(String JavaDoc parameterName)
879     {
880         JRCrosstabParameter param = (JRCrosstabParameter) parametersMap.remove(parameterName);
881         
882         if (param != null)
883         {
884             parametersList.remove(param);
885         }
886         
887         return param;
888     }
889     
890     
891     /**
892      * Removes a parameter.
893      *
894      * @param parameter the parameter to be removed
895      * @return the removed parameter
896      */

897     public JRCrosstabParameter removeParameter(JRCrosstabParameter parameter)
898     {
899         return removeParameter(parameter.getName());
900     }
901     
902     
903     /**
904      * Sets the parameters map expression.
905      *
906      * @param expression the parameters map expression
907      * @see JRCrosstab#getParametersMapExpression()
908      */

909     public void setParametersMapExpression(JRExpression expression)
910     {
911         this.parametersMapExpression = expression;
912     }
913     
914     
915     /**
916      * Returns the variables of this crosstab indexed by name.
917      *
918      * @return the variables of this crosstab indexed by name
919      */

920     public Map JavaDoc getVariablesMap()
921     {
922         JRVariable[] variables = getVariables();
923         Map JavaDoc variablesMap = new HashMap JavaDoc();
924         
925         for (int i = 0; i < variables.length; i++)
926         {
927             variablesMap.put(variables[i].getName(), variables[i]);
928         }
929         
930         return variablesMap;
931     }
932     
933     
934     /**
935      * Returns the list of variables created for this crosstab.
936      *
937      * @return the list of variables created for this crosstab
938      * @see JRCrosstabGroup#getVariable()
939      * @see JRCrosstabMeasure#getVariable()
940      * @see JRCrosstab#VARIABLE_ROW_COUNT
941      * @see JRCrosstab#VARIABLE_COLUMN_COUNT
942      */

943     public JRVariable[] getVariables()
944     {
945         JRVariable[] variables = new JRVariable[variablesList.size()];
946         variablesList.values().toArray(variables);
947         return variables;
948     }
949     
950
951     public int getColumnBreakOffset()
952     {
953         return columnBreakOffset;
954     }
955
956     
957     /**
958      * Sets the column break offset.
959      *
960      * @param columnBreakOffset the offset
961      * @see JRCrosstab#getColumnBreakOffset()
962      */

963     public void setColumnBreakOffset(int columnBreakOffset)
964     {
965         this.columnBreakOffset = columnBreakOffset;
966     }
967
968     
969     /**
970      * Performs all the calculations required for report compilation.
971      */

972     public void preprocess()
973     {
974         setGroupVariablesClass(rowGroups);
975         setGroupVariablesClass(columnGroups);
976         
977         calculateSizes();
978     }
979
980     
981     protected void setGroupVariablesClass(List JavaDoc groups)
982     {
983         for (Iterator JavaDoc it = groups.iterator(); it.hasNext();)
984         {
985             JRDesignCrosstabGroup group = (JRDesignCrosstabGroup) it.next();
986             JRCrosstabBucket bucket = group.getBucket();
987             if (bucket != null)
988             {
989                 JRExpression expression = bucket.getExpression();
990                 if (expression != null)
991                 {
992                     group.designVariable.setValueClassName(expression.getValueClassName());
993                 }
994             }
995         }
996     }
997
998     protected void calculateSizes()
999     {
1000        setWhenNoDataCellSize();
1001        
1002        createCellMatrix();
1003        
1004        int rowHeadersWidth = calculateRowHeadersSizes();
1005        int colHeadersHeight = calculateColumnHeadersSizes();
1006        
1007        if (headerCell != null)
1008        {
1009            headerCell.setWidth(rowHeadersWidth);
1010            headerCell.setHeight(colHeadersHeight);
1011        }
1012    }
1013
1014    protected void setWhenNoDataCellSize()
1015    {
1016        if (whenNoDataCell != null)
1017        {
1018            whenNoDataCell.setWidth(getWidth());
1019            whenNoDataCell.setHeight(getHeight());
1020        }
1021    }
1022
1023    protected void createCellMatrix()
1024    {
1025        crossCells = new JRDesignCrosstabCell[rowGroups.size() + 1][columnGroups.size() + 1];
1026        for (Iterator JavaDoc it = cellsList.iterator(); it.hasNext();)
1027        {
1028            JRDesignCrosstabCell crosstabCell = (JRDesignCrosstabCell) it.next();
1029            JRDesignCellContents contents = (JRDesignCellContents) crosstabCell.getContents();
1030            
1031            String JavaDoc rowTotalGroup = crosstabCell.getRowTotalGroup();
1032            int rowGroupIndex = rowTotalGroup == null ? rowGroupIndex = rowGroups.size() : ((Integer JavaDoc) rowGroupsMap.get(rowTotalGroup)).intValue();
1033            
1034            Integer JavaDoc cellWidth = crosstabCell.getWidth();
1035            if (cellWidth != null)
1036            {
1037                contents.setWidth(cellWidth.intValue());
1038            }
1039
1040            String JavaDoc columnTotalGroup = crosstabCell.getColumnTotalGroup();
1041            int columnGroupIndex = columnTotalGroup == null ? columnGroupIndex = columnGroups.size() : ((Integer JavaDoc) columnGroupsMap.get(columnTotalGroup)).intValue();
1042            Integer JavaDoc cellHeight = crosstabCell.getHeight();
1043            if (cellHeight != null)
1044            {
1045                contents.setHeight(cellHeight.intValue());
1046            }
1047
1048            crossCells[rowGroupIndex][columnGroupIndex] = crosstabCell;
1049        }
1050        
1051        inheritCells();
1052    }
1053
1054    protected JRDesignCrosstabRowGroup getRowGroup(int rowGroupIndex)
1055    {
1056        return (JRDesignCrosstabRowGroup) rowGroups.get(rowGroupIndex);
1057    }
1058
1059    protected JRDesignCrosstabColumnGroup getColumnGroup(int columnGroupIndex)
1060    {
1061        return (JRDesignCrosstabColumnGroup) columnGroups.get(columnGroupIndex);
1062    }
1063
1064    protected void inheritCells()
1065    {
1066        for (int i = rowGroups.size(); i >= 0 ; --i)
1067        {
1068            for (int j = columnGroups.size(); j >= 0 ; --j)
1069            {
1070                boolean used = (i == rowGroups.size() || getRowGroup(i).hasTotal()) &&
1071                    (j == columnGroups.size() || getColumnGroup(j).hasTotal());
1072                
1073                if (used)
1074                {
1075                    if (crossCells[i][j] == null)
1076                    {
1077                        inheritCell(i, j);
1078                        
1079                        if (crossCells[i][j] == null)
1080                        {
1081                            crossCells[i][j] = emptyCell(i, j);
1082                            inheritCellSize(i, j);
1083                        }
1084                    }
1085                    else
1086                    {
1087                        inheritCellSize(i, j);
1088                    }
1089                }
1090                else
1091                {
1092                    crossCells[i][j] = null;
1093                }
1094            }
1095        }
1096    }
1097
1098    private JRDesignCrosstabCell emptyCell(int i, int j)
1099    {
1100        JRDesignCrosstabCell emptyCell = new JRDesignCrosstabCell();
1101        if (i < rowGroups.size())
1102        {
1103            emptyCell.setRowTotalGroup(((JRCrosstabRowGroup) rowGroups.get(i)).getName());
1104        }
1105        if (j < columnGroups.size())
1106        {
1107            emptyCell.setColumnTotalGroup(((JRCrosstabColumnGroup) columnGroups.get(j)).getName());
1108        }
1109        return emptyCell;
1110    }
1111
1112    protected void inheritCellSize(int i, int j)
1113    {
1114        JRDesignCrosstabCell cell = crossCells[i][j];
1115        
1116        JRDesignCellContents contents = (JRDesignCellContents) cell.getContents();
1117        
1118        if (contents.getWidth() == JRCellContents.NOT_CALCULATED)
1119        {
1120            if (i < rowGroups.size())
1121            {
1122                JRDesignCrosstabCell rowCell = crossCells[rowGroups.size()][j];
1123                if (rowCell != null)
1124                {
1125                    contents.setWidth(rowCell.getContents().getWidth());
1126                }
1127            }
1128            else
1129            {
1130                for (int k = j + 1; k <= columnGroups.size(); ++k)
1131                {
1132                    if (crossCells[i][k] != null)
1133                    {
1134                        contents.setWidth(crossCells[i][k].getContents().getWidth());
1135                        break;
1136                    }
1137                }
1138            }
1139        }
1140        
1141        if (contents.getHeight() == JRCellContents.NOT_CALCULATED)
1142        {
1143            if (j < columnGroups.size())
1144            {
1145                JRDesignCrosstabCell colCell = crossCells[i][columnGroups.size()];
1146                if (colCell != null)
1147                {
1148                    contents.setHeight(colCell.getContents().getHeight());
1149                }
1150            }
1151            else
1152            {
1153                for (int k = i + 1; k <= rowGroups.size(); ++k)
1154                {
1155                    if (crossCells[k][j] != null)
1156                    {
1157                        contents.setHeight(crossCells[k][j].getContents().getHeight());
1158                    }
1159                }
1160            }
1161        }
1162    }
1163
1164    
1165    protected void inheritCell(int i, int j)
1166    {
1167        JRDesignCrosstabCell inheritedCell = null;
1168        
1169        if (j < columnGroups.size())
1170        {
1171            JRDesignCrosstabCell colCell = crossCells[rowGroups.size()][j];
1172            JRDesignCellContents colContents = colCell == null ? null : (JRDesignCellContents) colCell.getContents();
1173            for (int k = j + 1; inheritedCell == null && k <= columnGroups.size(); ++k)
1174            {
1175                JRDesignCrosstabCell cell = crossCells[i][k];
1176                if (cell != null)
1177                {
1178                    JRDesignCellContents contents = (JRDesignCellContents) cell.getContents();
1179                    if (colContents == null || contents.getWidth() == colContents.getWidth())
1180                    {
1181                        inheritedCell = cell;
1182                    }
1183                }
1184            }
1185        }
1186        
1187        if (inheritedCell == null && i < rowGroups.size())
1188        {
1189            JRDesignCrosstabCell rowCell = crossCells[i][columnGroups.size()];
1190            JRDesignCellContents rowContents = rowCell == null ? null : (JRDesignCellContents) rowCell.getContents();
1191            for (int k = i + 1; inheritedCell == null && k <= rowGroups.size(); ++k)
1192            {
1193                JRDesignCrosstabCell cell = crossCells[k][j];
1194                if (cell != null)
1195                {
1196                    JRDesignCellContents contents = (JRDesignCellContents) cell.getContents();
1197                    if (rowContents == null || contents.getHeight() == rowContents.getHeight())
1198                    {
1199                        inheritedCell = cell;
1200                    }
1201                }
1202            }
1203        }
1204        
1205        crossCells[i][j] = inheritedCell;
1206    }
1207
1208    protected int calculateRowHeadersSizes()
1209    {
1210        int widthSum = 0;
1211        for (int i = rowGroups.size() - 1, heightSum = 0; i >= 0; --i)
1212        {
1213            JRDesignCrosstabRowGroup group = (JRDesignCrosstabRowGroup) rowGroups.get(i);
1214
1215            widthSum += group.getWidth();
1216            
1217            JRDesignCrosstabCell cell = crossCells[i + 1][columnGroups.size()];
1218            if (cell != null)
1219            {
1220                heightSum += cell.getContents().getHeight();
1221            }
1222
1223            JRDesignCellContents header = (JRDesignCellContents) group.getHeader();
1224            header.setHeight(heightSum);
1225            header.setWidth(group.getWidth());
1226
1227            if (group.hasTotal())
1228            {
1229                JRDesignCellContents totalHeader = (JRDesignCellContents) group.getTotalHeader();
1230                totalHeader.setWidth(widthSum);
1231                JRDesignCrosstabCell totalCell = crossCells[i][columnGroups.size()];
1232                if (totalCell != null)
1233                {
1234                    totalHeader.setHeight(totalCell.getContents().getHeight());
1235                }
1236            }
1237        }
1238        return widthSum;
1239    }
1240
1241    protected int calculateColumnHeadersSizes()
1242    {
1243        int heightSum = 0;
1244        for (int i = columnGroups.size() - 1, widthSum = 0; i >= 0; --i)
1245        {
1246            JRDesignCrosstabColumnGroup group = (JRDesignCrosstabColumnGroup) columnGroups.get(i);
1247
1248            heightSum += group.getHeight();
1249            JRDesignCrosstabCell cell = crossCells[rowGroups.size()][i + 1];
1250            if (cell != null)
1251            {
1252                widthSum += cell.getContents().getWidth();
1253            }
1254
1255            JRDesignCellContents header = (JRDesignCellContents) group.getHeader();
1256            header.setHeight(group.getHeight());
1257            header.setWidth(widthSum);
1258
1259            if (group.hasTotal())
1260            {
1261                JRDesignCellContents totalHeader = (JRDesignCellContents) group.getTotalHeader();
1262                totalHeader.setHeight(heightSum);
1263                JRDesignCrosstabCell totalCell = crossCells[rowGroups.size()][i];
1264                if (totalCell != null)
1265                {
1266                    totalHeader.setWidth(totalCell.getContents().getWidth());
1267                }
1268            }
1269        }
1270        return heightSum;
1271    }
1272
1273    public JRCellContents getWhenNoDataCell()
1274    {
1275        return whenNoDataCell;
1276    }
1277
1278    
1279    /**
1280     * Sets the "No data" cell.
1281     *
1282     * @param whenNoDataCell the cell
1283     * @see JRCrosstab#getWhenNoDataCell()
1284     */

1285    public void setWhenNoDataCell(JRDesignCellContents whenNoDataCell)
1286    {
1287        this.whenNoDataCell = whenNoDataCell;
1288    }
1289
1290    
1291    public JRElement getElementByKey(String JavaDoc elementKey)
1292    {
1293        return JRBaseCrosstab.getElementByKey(this, elementKey);
1294    }
1295    
1296    
1297    public byte getMode()
1298    {
1299        return JRStyleResolver.getMode(this, MODE_TRANSPARENT);
1300    }
1301
1302    public JRCellContents getHeaderCell()
1303    {
1304        return headerCell;
1305    }
1306    
1307    
1308    /**
1309     * Sets the crosstab header cell (this cell will be rendered at the upper-left corder of the crosstab).
1310     *
1311     * @param headerCell the cell
1312     * @see JRCrosstab#getHeaderCell()
1313     */

1314    public void setHeaderCell(JRDesignCellContents headerCell)
1315    {
1316        this.headerCell = headerCell;
1317    }
1318
1319    
1320    protected void measureClassChanged(JRDesignCrosstabMeasure measure, String JavaDoc valueClassName)
1321    {
1322        for (Iterator JavaDoc colIt = columnGroups.iterator(); colIt.hasNext();)
1323        {
1324            JRCrosstabColumnGroup colGroup = (JRCrosstabColumnGroup) colIt.next();
1325            setTotalVarClass(measure, null, colGroup, valueClassName);
1326        }
1327        
1328        for (Iterator JavaDoc rowIt = rowGroups.iterator(); rowIt.hasNext();)
1329        {
1330            JRCrosstabRowGroup rowGroup = (JRCrosstabRowGroup) rowIt.next();
1331            setTotalVarClass(measure, rowGroup, null, valueClassName);
1332            
1333            for (Iterator JavaDoc colIt = columnGroups.iterator(); colIt.hasNext();)
1334            {
1335                JRCrosstabColumnGroup colGroup = (JRCrosstabColumnGroup) colIt.next();
1336                setTotalVarClass(measure, rowGroup, colGroup, valueClassName);
1337            }
1338        }
1339    }
1340    
1341    protected void setTotalVarClass(JRCrosstabMeasure measure, JRCrosstabRowGroup rowGroup, JRCrosstabColumnGroup colGroup, String JavaDoc valueClassName)
1342    {
1343        JRDesignVariable variable = getVariable(getTotalVariableName(measure, rowGroup, colGroup));
1344        variable.setValueClassName(valueClassName);
1345    }
1346
1347    private void addVariable(JRVariable variable)
1348    {
1349        variablesList.put(variable.getName(), variable);
1350    }
1351
1352    private void removeVariable(JRVariable variable)
1353    {
1354        removeVariable(variable.getName());
1355    }
1356
1357    private void removeVariable(String JavaDoc varName)
1358    {
1359        variablesList.remove(varName);
1360    }
1361    
1362    private JRDesignVariable getVariable(String JavaDoc varName)
1363    {
1364        return (JRDesignVariable) variablesList.get(varName);
1365    }
1366}
1367
Popular Tags