KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jasperreports > olap > JROlapDataSource


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.olap;
29
30 import java.io.StringReader JavaDoc;
31 import java.util.Arrays JavaDoc;
32 import java.util.HashMap JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Map JavaDoc;
36
37 import net.sf.jasperreports.engine.JRDataSource;
38 import net.sf.jasperreports.engine.JRDataset;
39 import net.sf.jasperreports.engine.JRException;
40 import net.sf.jasperreports.engine.JRField;
41 import net.sf.jasperreports.engine.JRRuntimeException;
42 import net.sf.jasperreports.olap.mapping.AxisPosition;
43 import net.sf.jasperreports.olap.mapping.DataMapping;
44 import net.sf.jasperreports.olap.mapping.Mapping;
45 import net.sf.jasperreports.olap.mapping.MappingLexer;
46 import net.sf.jasperreports.olap.mapping.MappingMetadata;
47 import net.sf.jasperreports.olap.mapping.MappingParser;
48 import net.sf.jasperreports.olap.mapping.MemberDepth;
49 import net.sf.jasperreports.olap.mapping.MemberMapping;
50 import net.sf.jasperreports.olap.mapping.MemberProperty;
51 import net.sf.jasperreports.olap.mapping.Tuple;
52 import net.sf.jasperreports.olap.mapping.TuplePosition;
53 import net.sf.jasperreports.olap.result.JROlapCell;
54 import net.sf.jasperreports.olap.result.JROlapHierarchy;
55 import net.sf.jasperreports.olap.result.JROlapHierarchyLevel;
56 import net.sf.jasperreports.olap.result.JROlapMember;
57 import net.sf.jasperreports.olap.result.JROlapMemberTuple;
58 import net.sf.jasperreports.olap.result.JROlapResult;
59 import net.sf.jasperreports.olap.result.JROlapResultAxis;
60
61 import org.apache.commons.logging.Log;
62 import org.apache.commons.logging.LogFactory;
63
64 import antlr.ANTLRException;
65
66
67 /**
68  * @author Lucian Chirita (lucianc@users.sourceforge.net)
69  * @version $Id: JROlapDataSource.java 1446 2006-10-25 09:00:05Z lucianc $
70  */

71 public class JROlapDataSource implements JRDataSource, MappingMetadata
72 {
73     private static final Log log = LogFactory.getLog(JROlapDataSource.class);
74     
75     protected final JROlapResult olapResult;
76     protected JROlapResultAxis[] axes;
77     protected final JROlapHierarchy[][] queryHierarchies;
78     protected final int hierarchiesCount;
79     
80     protected Map JavaDoc fieldMatchers;
81     protected int[][] fieldsMaxDepths;
82     protected boolean[] iteratePositions;
83     protected boolean iterate;
84
85     protected boolean dataField;
86     
87     protected Map JavaDoc fieldValues;
88     protected int[] axisPositions;
89     protected boolean first;
90     protected int[][] maxDepths;
91
92     public JROlapDataSource(JRDataset dataset, JROlapResult result)
93     {
94         this.olapResult = result;
95         axes = result.getAxes();
96         
97         queryHierarchies = new JROlapHierarchy[axes.length][];
98         fieldsMaxDepths = new int[axes.length][];
99         maxDepths = new int[axes.length][];
100         int hCount = 0;
101         for (int i = 0; i < axes.length; i++)
102         {
103             queryHierarchies[i] = axes[i].getHierarchiesOnAxis();
104             
105             hCount += queryHierarchies[i].length;
106             fieldsMaxDepths[i] = new int[queryHierarchies[i].length];
107             maxDepths[i] = new int[queryHierarchies[i].length];
108         }
109         hierarchiesCount = hCount;
110
111         axisPositions = new int[axes.length];
112
113         init(dataset);
114     }
115
116     public boolean next() throws JRException
117     {
118         boolean next;
119         boolean matchMaxLevel;
120         do
121         {
122             if (iterate)
123             {
124                 next = nextPositions();
125             }
126             else
127             {
128                 next = first;
129                 first = false;
130             }
131
132             if (!next)
133             {
134                 break;
135             }
136
137             resetMaxDepths();
138             for (Iterator JavaDoc it = fieldMatchers.entrySet().iterator(); it.hasNext();)
139             {
140                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
141                 Object JavaDoc fieldName = entry.getKey();
142                 FieldMatcher matcher = (FieldMatcher) entry.getValue();
143                 if (matcher.matches())
144                 {
145                     Object JavaDoc value = matcher.value();
146                     fieldValues.put(fieldName, value);
147                 }
148             }
149             
150             matchMaxLevel = true;
151             axes_loop:
152             for (int i = 0; i < axes.length; i++)
153             {
154                 if (iteratePositions[i])
155                 {
156                     for (int j = 0; j < fieldsMaxDepths[i].length; j++)
157                     {
158                         if (maxDepths[i][j] < fieldsMaxDepths[i][j])
159                         {
160                             matchMaxLevel = false;
161                             break axes_loop;
162                         }
163                     }
164                 }
165             }
166         }
167         while (!matchMaxLevel);
168         
169         return next;
170     }
171
172     
173     private void resetMaxDepths()
174     {
175         for (int i = 0; i < axes.length; ++i)
176         {
177             if (iteratePositions[i])
178             {
179                 for (int j = 0; j < maxDepths[i].length; j++)
180                 {
181                     maxDepths[i][j] = 0;
182                 }
183             }
184         }
185     }
186
187     protected boolean nextPositions()
188     {
189         boolean next;
190         int i = 0;
191         for (; i < axes.length; ++i)
192         {
193             if (iteratePositions[i])
194             {
195                 ++axisPositions[i];
196                 if (axisPositions[i] >= axes[i].getTupleCount())
197                 {
198                     axisPositions[i] = 0;
199                 }
200                 else
201                 {
202                     break;
203                 }
204             }
205         }
206         
207         next = i < axes.length;
208         return next;
209     }
210
211     public Object JavaDoc getFieldValue(JRField jrField) throws JRException
212     {
213         return fieldValues.get(jrField.getName());
214     }
215
216
217     private void init(JRDataset dataset)
218     {
219         iteratePositions = new boolean[axes.length];
220         
221         fieldMatchers = new HashMap JavaDoc();
222         
223         dataField = false;
224         JRField[] fields = dataset.getFields();
225         if (fields != null)
226         {
227             for (int i = 0; i < fields.length; i++)
228             {
229                 JRField field = fields[i];
230                 String JavaDoc fieldMapping = getFieldMapping(field);
231                 
232                 MappingLexer lexer = new MappingLexer(new StringReader JavaDoc(fieldMapping));
233                 MappingParser parser = new MappingParser(lexer);
234                 parser.setMappingMetadata(this);
235                 Mapping mapping;
236                 try
237                 {
238                     mapping = parser.mapping();
239                 }
240                 catch (ANTLRException e)
241                 {
242                     log.error("Error parsing field mapping", e);
243                     throw new JRRuntimeException(e);
244                 }
245                 
246                 if (mapping == null)
247                 {
248                     throw new JRRuntimeException("Invalid field mapping \"" + fieldMapping + "\".");
249                 }
250
251                 processMappingMembers(mapping);
252
253                 FieldMatcher fieldMatcher = createFieldMatcher(mapping);
254                 fieldMatchers.put(field.getName(), fieldMatcher);
255             }
256         }
257         
258         if (!dataField)
259         {
260             Arrays.fill(iteratePositions, true);
261         }
262         
263         initIterate();
264     }
265
266     private void processMappingMembers(Mapping mapping)
267     {
268         for (Iterator JavaDoc it = mapping.memberMappings(); it.hasNext();)
269         {
270             net.sf.jasperreports.olap.mapping.Member member = (net.sf.jasperreports.olap.mapping.Member) it.next();
271             processMemberInfo(member);
272         }
273     }
274
275     private FieldMatcher createFieldMatcher(Mapping mapping)
276     {
277         FieldMatcher fieldMatcher;
278         if (mapping instanceof MemberMapping)
279         {
280             fieldMatcher = new MemberFieldMatcher((MemberMapping) mapping);
281         }
282         else if (mapping instanceof DataMapping)
283         {
284             dataField = true;
285             fieldMatcher = new DataFieldMatcher((DataMapping) mapping);
286         }
287         else
288         {
289             throw new JRRuntimeException("internal error");
290         }
291         
292         return fieldMatcher;
293     }
294
295     protected String JavaDoc getFieldMapping(JRField field)
296     {
297         return field.getDescription();
298     }
299
300     private void initIterate()
301     {
302         int firstPos = 0;
303         while (firstPos < axes.length && !iteratePositions[firstPos])
304         {
305             ++firstPos;
306         }
307         
308         if (firstPos < axes.length)
309         {
310             iterate = true;
311             axisPositions[firstPos] = -1;
312         }
313         else
314         {
315             iterate = false;
316             first = true;
317         }
318         
319         fieldValues = new HashMap JavaDoc();
320     }
321
322     
323     protected void processMemberInfo(net.sf.jasperreports.olap.mapping.Member member)
324     {
325         MemberDepth memberDepth = member.getDepth();
326         if (memberDepth != null)
327         {
328             int depth = memberDepth.getDepth();
329             int axis = member.getAxis().getIdx();
330             int idx = member.getPosition().getIdx();
331             
332             if (depth > fieldsMaxDepths[axis][idx])
333             {
334                 fieldsMaxDepths[axis][idx] = depth;
335             }
336         }
337     }
338
339     
340     public int getDimensionIndex(net.sf.jasperreports.olap.mapping.Axis axis, String JavaDoc dimension)
341     {
342         JROlapHierarchy[] hierarchies = axes[axis.getIdx()].getHierarchiesOnAxis();
343         int dimensionIndex = -1;
344         for (int i = 0; i < hierarchies.length; i++)
345         {
346             JROlapHierarchy hierarchy = hierarchies[i];
347             if (hierarchy.getDimensionName().equals(dimension))
348             {
349                 dimensionIndex = i;
350             }
351         }
352         
353         if (dimensionIndex == -1)
354         {
355             throw new JRRuntimeException("Could not find dimension \"" + dimension + "\" on axis " + axis.getIdx() + ".");
356         }
357         
358         return dimensionIndex;
359     }
360
361     public int getLevelDepth(TuplePosition pos, String JavaDoc levelName)
362     {
363         JROlapHierarchy hierarchy = axes[pos.getAxis().getIdx()].getHierarchiesOnAxis()[pos.getIdx()];
364         JROlapHierarchyLevel[] levels = hierarchy.getLevels();
365         int levelIndex = -1;
366         for (int i = 0; i < levels.length; i++)
367         {
368             JROlapHierarchyLevel level = levels[i];
369             if (level != null && level.getName().equals(levelName))
370             {
371                 levelIndex = level.getDepth();
372                 break;
373             }
374         }
375         
376         if (levelIndex == -1)
377         {
378             throw new JRRuntimeException("Could not find level \"" + levelName + "\" on hierarchy " + hierarchy.getDimensionName() + ".");
379         }
380         
381         return levelIndex;
382     }
383
384     
385     protected void setMatchMemberDepth(net.sf.jasperreports.olap.mapping.Member memberInfo, JROlapMember member)
386     {
387         int memberDepth = member.getDepth();
388         int axis = memberInfo.getAxis().getIdx();
389         int pos = memberInfo.getPosition().getIdx();
390         if (maxDepths[axis][pos] < memberDepth)
391         {
392             maxDepths[axis][pos] = memberDepth;
393         }
394     }
395     
396     
397     protected abstract class FieldMatcher
398     {
399         public abstract boolean matches();
400         
401         public abstract Object JavaDoc value();
402         
403         public final JROlapMember member(net.sf.jasperreports.olap.mapping.Member memberInfo, int[] positions)
404         {
405             int axisIdx = memberInfo.getAxis().getIdx();
406             JROlapResultAxis axis = axes[axisIdx];
407             JROlapMemberTuple tuple = axis.getTuple(positions[axisIdx]);
408             JROlapMember[] members = tuple.getMembers();
409             int pos = memberInfo.getPosition().getIdx();
410             return members[pos];
411         }
412     }
413     
414     protected class MemberFieldMatcher extends FieldMatcher
415     {
416         final net.sf.jasperreports.olap.mapping.Member memberInfo;
417         final MemberProperty property;
418         JROlapMember member;
419         
420         MemberFieldMatcher(MemberMapping mapping)
421         {
422             this.memberInfo = mapping.getMember();
423             this.property = mapping.getProperty();
424         }
425         
426         public boolean matches()
427         {
428             member = member(memberInfo, axisPositions);
429             setMatchMemberDepth(memberInfo, member);
430             member = memberInfo.ancestorMatch(member);
431             return member != null;
432         }
433
434         public Object JavaDoc value()
435         {
436             Object JavaDoc value;
437             if (property != null)
438             {
439                 value = member.getPropertyValue(property.getName());
440             }
441             else if (memberInfo.getDepth() == null)
442             {
443                 value = member.getMondrianMember();
444             }
445             else
446             {
447                 value = member.getName();
448             }
449             return value;
450         }
451     }
452     
453     
454     protected class DataFieldMatcher extends FieldMatcher
455     {
456         private final boolean formatted;
457         private final int[] dataPositions;
458         private final net.sf.jasperreports.olap.mapping.Member[] members;
459         private int[] positions;
460
461         public DataFieldMatcher(DataMapping mapping)
462         {
463             this.formatted = mapping.isFormatted();
464             
465             List JavaDoc mappingPositions = mapping.getPositions();
466             if (mappingPositions == null)
467             {
468                 this.dataPositions = null;
469                 positions = axisPositions;
470             }
471             else
472             {
473                 if (mappingPositions.size() != axes.length)
474                 {
475                     throw new JRRuntimeException("Incorrect data mapping: the number of positions doesn't match the number of axes.");
476                 }
477                 
478                 this.dataPositions = new int[axes.length];
479                 int c = 0;
480                 for (Iterator JavaDoc iter = mappingPositions.iterator(); iter.hasNext(); ++c)
481                 {
482                     AxisPosition position = (AxisPosition) iter.next();
483                     int pos;
484                     if (position.isSpecified())
485                     {
486                         pos = position.getPosition();
487                     }
488                     else
489                     {
490                         pos = -1;
491                         iteratePositions[c] = true;
492                     }
493                     dataPositions[c] = pos;
494                 }
495             }
496             
497             List JavaDoc filter = mapping.getFilter();
498             if (filter == null || filter.isEmpty())
499             {
500                 this.members = null;
501             }
502             else
503             {
504                 this.members = new net.sf.jasperreports.olap.mapping.Member[filter.size()];
505                 filter.toArray(this.members);
506             }
507         }
508
509         public boolean matches()
510         {
511             if (dataPositions != null)
512             {
513                 setPositions();
514             }
515
516             boolean matches = true;
517             if (members != null)
518             {
519                 for (int i = 0; i < members.length; i++)
520                 {
521                     net.sf.jasperreports.olap.mapping.Member memberInfo = members[i];
522                     JROlapMember member = member(memberInfo, positions);
523                     setMatchMemberDepth(memberInfo, member);
524                     if (!memberInfo.matches(member))
525                     {
526                         matches = false;
527                         break;
528                     }
529                 }
530             }
531
532             return matches;
533         }
534
535         public Object JavaDoc value()
536         {
537             JROlapCell cell = olapResult.getCell(positions);
538             
539             if (cell != null && cell.isError())
540             {
541                 throw new JRRuntimeException("OLAP cell calculation returned error.");
542             }
543             
544             Object JavaDoc value;
545             if (cell == null || cell.isNull())
546             {
547                 value = null;
548             }
549             else if (formatted)
550             {
551                 value = cell.getFormattedValue();
552             }
553             else
554             {
555                 value = cell.getValue();
556             }
557             
558             return value;
559         }
560         
561         void setPositions()
562         {
563             positions = new int[axes.length];
564             for (int i = 0; i < axes.length; i++)
565             {
566                 int dataPosition = dataPositions[i];
567                 positions[i] = dataPosition == -1 ? axisPositions[i] : dataPosition;
568             }
569         }
570     }
571
572
573     public int getTuplePosition(int axisIndex, Tuple tuple)
574     {
575         if (axisIndex > axes.length)
576         {
577             throw new JRRuntimeException("OLAP result doesn't contain Axis(" + axisIndex + ").");
578         }
579         
580         String JavaDoc[] memberUniqueNames = tuple.getMemberUniqueNames();
581         JROlapResultAxis axis = axes[axisIndex];
582         int tupleCount = axis.getTupleCount();
583         
584         int pos = -1;
585         for (int i = 0; i < tupleCount; i++)
586         {
587             JROlapMemberTuple memberTuple = axis.getTuple(i);
588             JROlapMember[] resMembers = memberTuple.getMembers();
589             if (resMembers.length == memberUniqueNames.length)
590             {
591                 boolean eq = true;
592                 for (int j = 0; eq && j < resMembers.length; ++j)
593                 {
594                     if (!memberUniqueNames[j].equals(resMembers[j].getUniqueName()))
595                     {
596                         eq = false;
597                     }
598                 }
599                 
600                 if (eq)
601                 {
602                     pos = i;
603                     break;
604                 }
605             }
606         }
607         
608         if (pos == -1)
609         {
610             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
611             sb.append('(');
612             for (int i = 0; i < memberUniqueNames.length; i++)
613             {
614                 if (i > 0)
615                 {
616                     sb.append(',');
617                 }
618                 sb.append(memberUniqueNames[i]);
619             }
620             throw new JRRuntimeException("No such tuple " + sb + " on axis " + axisIndex + ".");
621         }
622         
623         return pos;
624     }
625 }
626
Popular Tags