net.sf.jasperreports.engine.data.JsonQLDataSource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jasperreports Show documentation
Show all versions of jasperreports Show documentation
Free Java Reporting Library
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2019 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.engine.data;
import java.io.File;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.fasterxml.jackson.databind.JsonNode;
import net.sf.jasperreports.annotations.properties.Property;
import net.sf.jasperreports.annotations.properties.PropertyScope;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;
import net.sf.jasperreports.engine.JRPropertiesUtil;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.engine.json.JRJsonNode;
import net.sf.jasperreports.engine.query.JsonQLQueryExecuterFactory;
import net.sf.jasperreports.engine.util.JsonUtil;
import net.sf.jasperreports.engine.util.json.DefaultJsonQLExecuter;
import net.sf.jasperreports.engine.util.json.JsonQLExecuter;
import net.sf.jasperreports.properties.PropertyConstants;
import net.sf.jasperreports.repo.RepositoryContext;
import net.sf.jasperreports.repo.SimpleRepositoryContext;
/**
* @author Narcis Marcu ([email protected])
*/
public class JsonQLDataSource extends JRAbstractTextDataSource implements JsonData, RandomAccessDataSource {
private static final Log log = LogFactory.getLog(JsonQLDataSource.class);
public static final String EXCEPTION_MESSAGE_KEY_NO_DATA = "data.json.no.data";
public static final String EXCEPTION_MESSAGE_KEY_JSON_FIELD_VALUE_NOT_RETRIEVED = "data.json.field.value.not.retrieved";
/**
* Property specifying the JSONQL expression for the dataset field.
*/
@Property (
category = PropertyConstants.CATEGORY_DATA_SOURCE,
scopes = {PropertyScope.FIELD},
scopeQualifications = {JsonQLQueryExecuterFactory.JSONQL_QUERY_EXECUTER_NAME},
sinceVersion = PropertyConstants.VERSION_6_3_1
)
public static final String PROPERTY_FIELD_EXPRESSION = JRPropertiesUtil.PROPERTY_PREFIX + "jsonql.field.expression";
private JRJsonNode root;
private String selectExpression;
private JRJsonNode currentJsonNode;
private List nodes;
private int currentNodeIndex = - 1;
private JsonQLExecuter jsonQLExecuter;
private Map fieldExpressions = new HashMap<>();
public JsonQLDataSource(File file, String selectExpression) throws JRException {
this(JsonUtil.parseJson(file), selectExpression);
}
public JsonQLDataSource(File file) throws JRException {
this(file, null);
}
public JsonQLDataSource(InputStream jsonInputStream, String selectExpression) throws JRException {
this(JsonUtil.parseJson(jsonInputStream), selectExpression);
}
public JsonQLDataSource(InputStream jsonInputStream) throws JRException {
this(jsonInputStream, null);
}
public JsonQLDataSource(JasperReportsContext jasperReportsContext, String jsonSource, String selectExpression) throws JRException {
this(SimpleRepositoryContext.of(jasperReportsContext), jsonSource, selectExpression);
}
public JsonQLDataSource(RepositoryContext repositoryContext, String jsonSource, String selectExpression) throws JRException {
this(JsonUtil.parseJson(repositoryContext, jsonSource), selectExpression);
}
protected JsonQLDataSource(JsonNode jacksonJsonTree, String selectExpression) throws JRException {
this(new JRJsonNode(null, jacksonJsonTree), selectExpression);
}
protected JsonQLDataSource(JRJsonNode root, String selectExpression) throws JRException {
this.root = root;
this.selectExpression = selectExpression;
this.jsonQLExecuter = new DefaultJsonQLExecuter();
if (log.isDebugEnabled()) {
log.debug("The JsonQL expression is: " + selectExpression);
}
moveFirst();
}
@Override
public void moveFirst() throws JRException {
if (root.getDataNode() == null || root.getDataNode().isMissingNode()) {
throw new JRException(EXCEPTION_MESSAGE_KEY_NO_DATA, (Object[]) null);
}
currentJsonNode = null;
nodes = jsonQLExecuter.selectNodes(root, selectExpression);
currentNodeIndex = -1;
}
@Override
public boolean next() throws JRException {
if (nodes != null && currentNodeIndex < nodes.size() - 1) {
currentJsonNode = nodes.get(++currentNodeIndex);
return true;
}
return false;
}
@Override
public int recordCount() {
return nodes == null ? 0 : nodes.size();
}
@Override
public int currentIndex() {
return currentNodeIndex;
}
@Override
public void moveToRecord(int index) throws NoRecordAtIndexException {
if (nodes != null && index >= 0 && index < nodes.size()) {
currentNodeIndex = index;
currentJsonNode = nodes.get(index);
} else {
throw new NoRecordAtIndexException(index);
}
}
@Override
public Object getFieldValue(JRField jrField) throws JRException {
if(currentJsonNode == null) {
return null;
}
String expression;
if (fieldExpressions.containsKey(jrField.getName())) {
expression = fieldExpressions.get(jrField.getName());
} else {
expression = getFieldExpression(jrField);
fieldExpressions.put(jrField.getName(), expression);
}
if (expression == null || expression.length() == 0) {
return null;
}
JRJsonNode selectedNode = jsonQLExecuter.selectNode(currentJsonNode, root, expression);
if (selectedNode != null) {
return getConvertedValue(selectedNode, jrField);
}
return null;
}
@Override
public JsonQLDataSource subDataSource() throws JRException {
return subDataSource(null);
}
@Override
public JsonQLDataSource subDataSource(String selectExpression) throws JRException {
if(currentJsonNode == null) {
throw new JRException(EXCEPTION_MESSAGE_KEY_NO_DATA, (Object[])null);
}
JsonQLDataSource subDataSource = new JsonQLDataSource(currentJsonNode, selectExpression);
subDataSource.setTextAttributes(this);
return subDataSource;
}
protected Object getConvertedValue(JRJsonNode node, JRField jrField) throws JRException {
JsonNode dataNode = node.getDataNode();
Class valueClass = jrField.getValueClass();
if (log.isDebugEnabled()) {
log.debug("attempting to convert: " + dataNode + " to class: " + valueClass);
}
if (Object.class.equals(valueClass)) {
return dataNode;
}
Object result = null;
if (!dataNode.isNull()) {
try {
if (Boolean.class.equals(valueClass) && dataNode.isBoolean()) {
result = dataNode.booleanValue();
} else if (BigDecimal.class.equals(valueClass) && dataNode.isBigDecimal()) {
result = dataNode.decimalValue();
} else if (BigInteger.class.equals(valueClass) && dataNode.isBigInteger()) {
result = dataNode.bigIntegerValue();
} else if (Double.class.equals(valueClass) && dataNode.isDouble()) {
result = dataNode.doubleValue();
} else if (Integer.class.equals(valueClass) && dataNode.isInt()) {
result = dataNode.intValue();
} else if (Number.class.isAssignableFrom(valueClass) && dataNode.isNumber()) {
result = convertNumber(dataNode.numberValue(), valueClass);
} else {
result = convertStringValue(dataNode.asText(), valueClass);
}
if (result == null) {
throw new JRException(EXCEPTION_MESSAGE_KEY_CANNOT_CONVERT_FIELD_TYPE,
new Object[]{jrField.getName(), valueClass.getName()});
}
} catch (Exception e) {
throw new JRException(EXCEPTION_MESSAGE_KEY_JSON_FIELD_VALUE_NOT_RETRIEVED,
new Object[]{jrField.getName(), valueClass.getName()}, e);
}
}
return result;
}
protected String getFieldExpression(JRField field) {
String fieldExpression = null;
if (field.hasProperties()) {
fieldExpression = field.getPropertiesMap().getProperty(PROPERTY_FIELD_EXPRESSION);
}
if (fieldExpression == null) {
fieldExpression = field.getDescription();
if (fieldExpression == null || fieldExpression.length() == 0) {
fieldExpression = field.getName();
}
}
return fieldExpression;
}
}