All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.sf.jasperreports.olap.JROlapDataSource Maven / Gradle / Ivy
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2014 TIBCO Software Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
package net.sf.jasperreports.olap;
import java.io.StringReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import antlr.ANTLRException;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRDataset;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.olap.mapping.AxisPosition;
import net.sf.jasperreports.olap.mapping.DataMapping;
import net.sf.jasperreports.olap.mapping.Mapping;
import net.sf.jasperreports.olap.mapping.MappingLexer;
import net.sf.jasperreports.olap.mapping.MappingMetadata;
import net.sf.jasperreports.olap.mapping.MappingParser;
import net.sf.jasperreports.olap.mapping.Member;
import net.sf.jasperreports.olap.mapping.MemberDepth;
import net.sf.jasperreports.olap.mapping.MemberMapping;
import net.sf.jasperreports.olap.mapping.MemberProperty;
import net.sf.jasperreports.olap.mapping.Tuple;
import net.sf.jasperreports.olap.mapping.TuplePosition;
import net.sf.jasperreports.olap.result.JROlapCell;
import net.sf.jasperreports.olap.result.JROlapHierarchy;
import net.sf.jasperreports.olap.result.JROlapHierarchyLevel;
import net.sf.jasperreports.olap.result.JROlapMember;
import net.sf.jasperreports.olap.result.JROlapMemberTuple;
import net.sf.jasperreports.olap.result.JROlapResult;
import net.sf.jasperreports.olap.result.JROlapResultAxis;
/**
* @author Lucian Chirita ([email protected] )
*/
public class JROlapDataSource implements JRDataSource, MappingMetadata
{
private static final Log log = LogFactory.getLog(JROlapDataSource.class);
public static final String EXCEPTION_MESSAGE_KEY_OLAP_AXIS_NOT_FOUND_IN_RESULT = "data.olap.axis.not.found.in.result";
public static final String EXCEPTION_MESSAGE_KEY_OLAP_CANNOT_CONVERT_FIELD_TYPE = "data.olap.cannot.convert.field.type";
public static final String EXCEPTION_MESSAGE_KEY_OLAP_CANNOT_CONVERT_STRING_VALUE_TYPE = "data.olap.cannot.convert.string.value.type";
public static final String EXCEPTION_MESSAGE_KEY_OLAP_DIMENSION_NOT_FOUND = "data.olap.dimension.not.found";
public static final String EXCEPTION_MESSAGE_KEY_OLAP_FIELD_VALUE_NOT_RETRIEVED = "data.olap.field.value.not.retrieved";
public static final String EXCEPTION_MESSAGE_KEY_OLAP_INTERNAL_ERROR = "data.olap.internal.error";
public static final String EXCEPTION_MESSAGE_KEY_OLAP_INVALID_FIELD_MAPPING = "data.olap.invalid.field.mapping";
public static final String EXCEPTION_MESSAGE_KEY_OLAP_LEVEL_NOT_FOUND = "data.olap.level.not.found";
public static final String EXCEPTION_MESSAGE_KEY_OLAP_TUPLE_NOT_FOUND = "data.olap.tuple.not.found";
protected final JROlapResult olapResult;
protected JROlapResultAxis[] axes;
protected final JROlapHierarchy[][] queryHierarchies;
protected final int hierarchiesCount;
protected Map fieldMatchers;
protected int[][] fieldsMaxDepths;
protected boolean[] iteratePositions;
protected boolean iterate;
protected boolean dataField;
protected Map fieldValues;
protected int[] axisPositions;
protected boolean first;
protected int[][] maxDepths;
private DateFormat dateFormat = new SimpleDateFormat();
// Mpenningroth 21-Nov-2008 added to deal with empty results.
// Sometimes non empty can cause no results, but the init was
// causing an error trying to locate a mapping to a tuple (there are
// no tuples.) This deals with that situation.
private boolean noTuples;
public JROlapDataSource(JRDataset dataset, JROlapResult result)
{
this.olapResult = result;
axes = result.getAxes();
queryHierarchies = new JROlapHierarchy[axes.length][];
fieldsMaxDepths = new int[axes.length][];
maxDepths = new int[axes.length][];
int hCount = 0;
noTuples = false;
for (int i = 0; i < axes.length; i++)
{
noTuples = (noTuples || axes[i].getTupleCount() == 0);
queryHierarchies[i] = axes[i].getHierarchiesOnAxis();
hCount += queryHierarchies[i].length;
fieldsMaxDepths[i] = new int[queryHierarchies[i].length];
maxDepths[i] = new int[queryHierarchies[i].length];
}
hierarchiesCount = hCount;
axisPositions = new int[axes.length];
if (!noTuples)
{
init(dataset);
}
}
@Override
public boolean next() throws JRException
{
boolean next;
boolean matchMaxLevel;
if (noTuples)
{
return false;
}
do
{
if (iterate)
{
next = nextPositions();
}
else
{
next = first;
first = false;
}
if (!next)
{
break;
}
resetMaxDepths();
for (Iterator> it = fieldMatchers.entrySet().iterator(); it.hasNext();)
{
Map.Entry entry = it.next();
Object fieldName = entry.getKey();
FieldMatcher matcher = entry.getValue();
if (matcher.matches())
{
Object value = matcher.value();
fieldValues.put(fieldName, value);
}
}
matchMaxLevel = true;
axes_loop:
for (int i = 0; i < axes.length; i++)
{
if (iteratePositions[i])
{
for (int j = 0; j < fieldsMaxDepths[i].length; j++)
{
if (maxDepths[i][j] < fieldsMaxDepths[i][j])
{
matchMaxLevel = false;
break axes_loop;
}
}
}
}
}
while (!matchMaxLevel);
return next;
}
private void resetMaxDepths()
{
for (int i = 0; i < axes.length; ++i)
{
if (iteratePositions[i])
{
for (int j = 0; j < maxDepths[i].length; j++)
{
maxDepths[i][j] = 0;
}
}
}
}
protected boolean nextPositions()
{
boolean next;
int i = 0;
for (; i < axes.length; ++i)
{
if (iteratePositions[i])
{
++axisPositions[i];
if (axisPositions[i] >= axes[i].getTupleCount())
{
axisPositions[i] = 0;
}
else
{
break;
}
}
}
next = i < axes.length;
return next;
}
/**
* Convert the value of the data type of the Field
* @param jrField the Field whose type has to be converted
* @return value of field in the requested type
*
*/
@Override
public Object getFieldValue(JRField jrField) throws JRException {
Class valueClass = jrField.getValueClass();
Object value = fieldValues.get(jrField.getName());
try {
/*
* Everything in the result is a string, apart from Member
*/
if (valueClass.equals(mondrian.olap.Member.class)) {
if (!(value instanceof mondrian.olap.Member)) {
throw
new JRException(
EXCEPTION_MESSAGE_KEY_OLAP_CANNOT_CONVERT_FIELD_TYPE,
new Object[]{jrField.getName(), value.getClass(), valueClass.getName()});
}
return value;
}
/*
* Convert the rest from String
*/
String fieldValue = (String) value;
if (fieldValue == null)
{
return null;
}
if (Number.class.isAssignableFrom(valueClass)){
fieldValue = fieldValue.trim();
}
if (fieldValue.length() == 0){
fieldValue = "0";
}
if (valueClass.equals(String.class)) {
return fieldValue;
} else if (valueClass.equals(Boolean.class)) {
return fieldValue.equalsIgnoreCase("true") ? Boolean.TRUE : Boolean.FALSE;
} else if (valueClass.equals(Byte.class)) {
return new Byte(fieldValue);
} else if (valueClass.equals(Integer.class)) {
return Integer.valueOf(fieldValue);
} else if (valueClass.equals(Long.class)) {
return new Long(fieldValue);
} else if (valueClass.equals(Short.class)) {
return new Short(fieldValue);
} else if (valueClass.equals(Double.class)) {
return new Double(fieldValue);
} else if (valueClass.equals(Float.class)) {
return new Float(fieldValue);
} else if (valueClass.equals(java.math.BigDecimal.class)) {
return new java.math.BigDecimal(fieldValue);
} else if (valueClass.equals(java.util.Date.class)) {
return dateFormat.parse(fieldValue);
} else if (valueClass.equals(java.sql.Timestamp.class)) {
return new java.sql.Timestamp(dateFormat.parse(fieldValue).getTime());
} else if (valueClass.equals(java.sql.Time.class)) {
return new java.sql.Time(dateFormat.parse(fieldValue).getTime());
} else if (valueClass.equals(java.lang.Number.class)) {
return new Double(fieldValue);
} else {
throw
new JRException(
EXCEPTION_MESSAGE_KEY_OLAP_CANNOT_CONVERT_STRING_VALUE_TYPE,
new Object[]{jrField.getName(), fieldValue, fieldValues.get(jrField.getName()).getClass(), valueClass.getName()});
}
} catch (Exception e) {
throw
new JRException(
EXCEPTION_MESSAGE_KEY_OLAP_FIELD_VALUE_NOT_RETRIEVED,
new Object[]{jrField.getName(), valueClass.getName()},
e);
}
}
private void init(JRDataset dataset)
{
iteratePositions = new boolean[axes.length];
fieldMatchers = new HashMap();
dataField = false;
JRField[] fields = dataset.getFields();
if (fields != null)
{
for (int i = 0; i < fields.length; i++)
{
JRField field = fields[i];
String fieldMapping = getFieldMapping(field);
if (log.isDebugEnabled())
{
log.debug("Mapping field: " + field.getName() + " - description: " + fieldMapping);
}
MappingLexer lexer = new MappingLexer(new StringReader(fieldMapping));
MappingParser parser = new MappingParser(lexer);
parser.setMappingMetadata(this);
Mapping mapping;
try
{
mapping = parser.mapping();
}
catch (ANTLRException e)
{
log.error("Error parsing field mapping", e);
throw new JRRuntimeException(e);
}
if (mapping == null)
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_OLAP_INVALID_FIELD_MAPPING,
new Object[]{fieldMapping});
}
processMappingMembers(mapping);
FieldMatcher fieldMatcher = createFieldMatcher(field, mapping);
fieldMatchers.put(field.getName(), fieldMatcher);
}
}
if (!dataField)
{
Arrays.fill(iteratePositions, true);
}
initIterate();
}
private void processMappingMembers(Mapping mapping)
{
for (Iterator it = mapping.memberMappings(); it.hasNext();)
{
Member member = it.next();
processMemberInfo(member);
}
}
private FieldMatcher createFieldMatcher(JRField field, Mapping mapping)
{
FieldMatcher fieldMatcher;
if (mapping instanceof MemberMapping)
{
fieldMatcher = new MemberFieldMatcher((MemberMapping) mapping);
}
else if (mapping instanceof DataMapping)
{
dataField = true;
fieldMatcher = new DataFieldMatcher(field, (DataMapping) mapping);
}
else
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_OLAP_INTERNAL_ERROR,
(Object[])null);
}
return fieldMatcher;
}
protected String getFieldMapping(JRField field)
{
return field.getDescription();
}
private void initIterate()
{
int firstPos = 0;
while (firstPos < axes.length && !iteratePositions[firstPos])
{
++firstPos;
}
if (firstPos < axes.length)
{
iterate = true;
axisPositions[firstPos] = -1;
}
else
{
iterate = false;
first = true;
}
fieldValues = new HashMap();
}
protected void processMemberInfo(net.sf.jasperreports.olap.mapping.Member member)
{
MemberDepth memberDepth = member.getDepth();
if (memberDepth != null)
{
int depth = memberDepth.getDepth();
int axis = member.getAxis().getIdx();
int idx = member.getPosition().getIdx();
if (depth > fieldsMaxDepths[axis][idx])
{
fieldsMaxDepths[axis][idx] = depth;
}
}
}
@Override
public int getDimensionIndex(net.sf.jasperreports.olap.mapping.Axis axis, String dimension)
{
JROlapHierarchy[] hierarchies = axes[axis.getIdx()].getHierarchiesOnAxis();
int dimensionIndex = -1;
for (int i = 0; dimensionIndex == -1 && i < hierarchies.length; i++)
{
JROlapHierarchy hierarchy = hierarchies[i];
if (matchesDimensionName(hierarchy, dimension))
{
dimensionIndex = i;
}
}
if (dimensionIndex == -1)
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_OLAP_DIMENSION_NOT_FOUND,
new Object[]{dimension, axis.getIdx()});
}
return dimensionIndex;
}
protected boolean matchesDimensionName(JROlapHierarchy hierarchy, String dimensionName)
{
if (dimensionName.equals(hierarchy.getDimensionName())
|| dimensionName.equals(hierarchy.getHierarchyUniqueName()))
{
return true;
}
// MPenningroth 21-April-2009 deal with case when dimension is . form
String hierName = "[" + dimensionName + "]";
return hierName.equals(hierarchy.getHierarchyUniqueName());
}
@Override
public int getLevelDepth(TuplePosition pos, String levelName)
{
JROlapHierarchy hierarchy = axes[pos.getAxis().getIdx()].getHierarchiesOnAxis()[pos.getIdx()];
JROlapHierarchyLevel[] levels = hierarchy.getLevels();
int levelIndex = -1;
for (int i = 0; i < levels.length; i++)
{
JROlapHierarchyLevel level = levels[i];
if (level != null && level.getName().equals(levelName))
{
levelIndex = level.getDepth();
break;
}
}
if (levelIndex == -1)
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_OLAP_LEVEL_NOT_FOUND,
new Object[]{levelName, pos.getIdx(), hierarchy.getDimensionName(), pos.getAxis().getIdx()});
}
return levelIndex;
}
protected void setMatchMemberDepth(net.sf.jasperreports.olap.mapping.Member memberInfo, JROlapMember member)
{
int memberDepth = member.getDepth();
int axis = memberInfo.getAxis().getIdx();
int pos = memberInfo.getPosition().getIdx();
if (maxDepths[axis][pos] < memberDepth)
{
maxDepths[axis][pos] = memberDepth;
}
}
protected abstract class FieldMatcher
{
public abstract boolean matches();
public abstract Object value();
public final JROlapMember member(net.sf.jasperreports.olap.mapping.Member memberInfo, int[] positions)
{
int axisIdx = memberInfo.getAxis().getIdx();
JROlapResultAxis axis = axes[axisIdx];
JROlapMemberTuple tuple = axis.getTuple(positions[axisIdx]);
JROlapMember[] members = tuple.getMembers();
int pos = memberInfo.getPosition().getIdx();
return members[pos];
}
}
protected class MemberFieldMatcher extends FieldMatcher
{
final net.sf.jasperreports.olap.mapping.Member memberInfo;
final MemberProperty property;
JROlapMember member;
MemberFieldMatcher(MemberMapping mapping)
{
this.memberInfo = mapping.getMember();
this.property = mapping.getProperty();
}
@Override
public boolean matches()
{
member = member(memberInfo, axisPositions);
setMatchMemberDepth(memberInfo, member);
member = memberInfo.ancestorMatch(member);
return member != null;
}
@Override
public Object value()
{
Object value;
if (memberInfo.getDepth() == null)
{
// The actual member object of the given dimension
return member.getMember();
}
else if (property != null)
{
// member property value
value = member.getPropertyValue(property.getName());
}
else
{
// Level name
value = member.getName();
}
return value.toString();
}
}
protected class DataFieldMatcher extends FieldMatcher
{
public static final String EXCEPTION_MESSAGE_KEY_OLAP_CELL_CALCULATION_ERROR = "data.olap.cell.calculation.error";
public static final String EXCEPTION_MESSAGE_KEY_OLAP_INCORRECT_DATA_MAPPING = "data.olap.incorrect.data.mapping";
private final boolean formatted;
private final int[] dataPositions;
private final net.sf.jasperreports.olap.mapping.Member[] members;
private int[] positions;
public DataFieldMatcher(JRField field, DataMapping mapping)
{
// only using FormattedData mappings for String fields
// for other fields, FormattedData mappings are treated in the same way as Data mappings
this.formatted = mapping.isFormatted() && String.class.equals(field.getValueClass());
List mappingPositions = mapping.getPositions();
if (mappingPositions == null)
{
this.dataPositions = null;
positions = axisPositions;
}
else
{
if (mappingPositions.size() != axes.length)
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_OLAP_INCORRECT_DATA_MAPPING,
(Object[])null);
}
this.dataPositions = new int[axes.length];
int c = 0;
for (Iterator iter = mappingPositions.iterator(); iter.hasNext(); ++c)
{
AxisPosition position = iter.next();
int pos;
if (position.isSpecified())
{
pos = position.getPosition();
}
else
{
pos = -1;
iteratePositions[c] = true;
}
dataPositions[c] = pos;
}
}
List filter = mapping.getFilter();
if (filter == null || filter.isEmpty())
{
this.members = null;
}
else
{
this.members = new Member[filter.size()];
filter.toArray(this.members);
}
}
@Override
public boolean matches()
{
if (dataPositions != null)
{
setPositions();
}
boolean matches = true;
if (members != null)
{
for (int i = 0; i < members.length; i++)
{
Member memberInfo = members[i];
JROlapMember member = member(memberInfo, positions);
setMatchMemberDepth(memberInfo, member);
if (!memberInfo.matches(member))
{
matches = false;
break;
}
}
}
return matches;
}
@Override
public Object value()
{
JROlapCell cell = olapResult.getCell(positions);
if (cell != null && cell.isError())
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_OLAP_CELL_CALCULATION_ERROR,
(Object[])null);
}
Object value;
if (cell == null || cell.isNull())
{
value = null;
}
else if (formatted)
{
value = cell.getFormattedValue();
}
else
{
value = cell.getValue().toString();
}
return value;
}
void setPositions()
{
positions = new int[axes.length];
for (int i = 0; i < axes.length; i++)
{
int dataPosition = dataPositions[i];
positions[i] = dataPosition == -1 ? axisPositions[i] : dataPosition;
}
}
}
@Override
public int getTuplePosition(int axisIndex, Tuple tuple)
{
if (axisIndex > axes.length)
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_OLAP_AXIS_NOT_FOUND_IN_RESULT,
new Object[]{axisIndex});
}
String[] memberUniqueNames = tuple.getMemberUniqueNames();
JROlapResultAxis axis = axes[axisIndex];
int tupleCount = axis.getTupleCount();
int pos = -1;
for (int i = 0; i < tupleCount; i++)
{
JROlapMemberTuple memberTuple = axis.getTuple(i);
JROlapMember[] resMembers = memberTuple.getMembers();
if (resMembers.length == memberUniqueNames.length)
{
boolean eq = true;
for (int j = 0; eq && j < resMembers.length; ++j)
{
if (!memberUniqueNames[j].equals(resMembers[j].getUniqueName()))
{
eq = false;
}
}
if (eq)
{
pos = i;
break;
}
}
}
if (pos == -1)
{
StringBuilder sb = new StringBuilder();
sb.append('(');
for (int i = 0; i < memberUniqueNames.length; i++)
{
if (i > 0)
{
sb.append(',');
}
sb.append(memberUniqueNames[i]);
}
sb.append(')');
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_OLAP_TUPLE_NOT_FOUND,
new Object[]{sb, axisIndex});
}
return pos;
}
}