net.sf.jasperreports.engine.util.JRQueryParser 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.util;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import net.sf.jasperreports.engine.DefaultJasperReportsContext;
import net.sf.jasperreports.engine.JRPropertiesUtil;
import net.sf.jasperreports.engine.JRQueryChunk;
import net.sf.jasperreports.engine.JRRuntimeException;
/**
* Report query parser.
*
* @author Lucian Chirita ([email protected])
*/
public class JRQueryParser
{
public static final String EXCEPTION_MESSAGE_KEY_TOKEN_SEPARATORS_NOT_CONFIGURED = "util.query.token.separators.not.configured";
private static final JRQueryParser singleton = new JRQueryParser();
/**
* Returns a query parser instance.
*
* @return a query parser instance
*/
public static JRQueryParser instance()
{
return singleton;
}
/**
* Parses a report query.
*
* @param text the query text
* @param chunkHandler a handler that will be asked to handle parsed query chunks
*/
public void parse(String text, JRQueryChunkHandler chunkHandler)
{
if (text != null)
{
StringBuilder textChunk = new StringBuilder();
StringTokenizer tkzer = new StringTokenizer(text, "$", true);
boolean wasDelim = false;
while (tkzer.hasMoreTokens())
{
String token = tkzer.nextToken();
if (token.equals("$"))
{
if (wasDelim)
{
textChunk.append("$");
}
wasDelim = true;
}
else
{
if ( token.startsWith("P{") && wasDelim )
{
int end = token.indexOf('}');
if (end > 0)
{
if (textChunk.length() > 0)
{
chunkHandler.handleTextChunk(textChunk.toString());
}
String parameterChunk = token.substring(2, end);
chunkHandler.handleParameterChunk(parameterChunk);
textChunk = new StringBuilder(token.substring(end + 1));
}
else
{
if (wasDelim)
{
textChunk.append("$");
}
textChunk.append(token);
}
}
else if ( token.startsWith("P!{") && wasDelim )
{
int end = token.indexOf('}');
if (end > 0)
{
if (textChunk.length() > 0)
{
chunkHandler.handleTextChunk(textChunk.toString());
}
String parameterClauseChunk = token.substring(3, end);
chunkHandler.handleParameterClauseChunk(parameterClauseChunk);
textChunk = new StringBuilder(token.substring(end + 1));
}
else
{
if (wasDelim)
{
textChunk.append("$");
}
textChunk.append(token);
}
}
else if ( token.startsWith("X{") && wasDelim )
{
int end = token.indexOf('}');
if (end > 0)
{
if (textChunk.length() > 0)
{
chunkHandler.handleTextChunk(textChunk.toString());
}
String clauseChunk = token.substring(2, end);
parseClause(chunkHandler, clauseChunk);
textChunk = new StringBuilder(token.substring(end + 1));
}
else
{
if (wasDelim)
{
textChunk.append("$");
}
textChunk.append(token);
}
}
else
{
if (wasDelim)
{
textChunk.append("$");
}
textChunk.append(token);
}
wasDelim = false;
}
}
if (wasDelim)
{
textChunk.append("$");
}
if (textChunk.length() > 0)
{
chunkHandler.handleTextChunk(textChunk.toString());
}
}
}
protected void parseClause(JRQueryChunkHandler chunkHandler, String clauseChunk)
{
List tokens = new ArrayList();
boolean wasClauseToken = false;
char separator = determineClauseTokenSeparator(clauseChunk);
String separatorString = String.valueOf(separator);
StringTokenizer tokenizer = new StringTokenizer(clauseChunk, separatorString, true);
while (tokenizer.hasMoreTokens())
{
String token = tokenizer.nextToken();
if (token.equals(separatorString))
{
if (!wasClauseToken)
{
tokens.add("");
}
wasClauseToken = false;
}
else
{
tokens.add(token);
wasClauseToken = true;
}
}
if (!wasClauseToken)
{
tokens.add("");
}
String[] tokensArray = tokens.toArray(new String[tokens.size()]);
chunkHandler.handleClauseChunk(tokensArray, separator);
}
protected char determineClauseTokenSeparator(String clauseChunk)
{
String allSeparators = getTokenSeparators();
if (allSeparators == null || allSeparators.length() == 0)
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_TOKEN_SEPARATORS_NOT_CONFIGURED,
(Object[])null);
}
int firstSepIdx = 0;//if none of the separators are found in the text, return the first separator
int clauseLenght = clauseChunk.length();
for (int idx = 0; idx < clauseLenght; ++idx)
{
int sepIdx = allSeparators.indexOf(clauseChunk.charAt(idx));
if (sepIdx >= 0)
{
firstSepIdx = sepIdx;
break;
}
}
return allSeparators.charAt(firstSepIdx);
}
protected String getTokenSeparators()
{
return JRPropertiesUtil.getInstance(DefaultJasperReportsContext.getInstance()).getProperty(JRQueryChunk.PROPERTY_CHUNK_TOKEN_SEPARATOR);
}
/**
* (Re)creates the query text from a list of chunks.
*
* @param chunks the chunks
* @return the recreated query text
*/
public String asText(JRQueryChunk[] chunks)
{
String text = "";
if (chunks != null && chunks.length > 0)
{
StringBuilder sb = new StringBuilder();
for(int i = 0; i < chunks.length; i++)
{
JRQueryChunk queryChunk = chunks[i];
switch(queryChunk.getType())
{
case JRQueryChunk.TYPE_PARAMETER :
{
sb.append("$P{");
sb.append( queryChunk.getText() );
sb.append("}");
break;
}
case JRQueryChunk.TYPE_PARAMETER_CLAUSE :
{
sb.append("$P!{");
sb.append( queryChunk.getText() );
sb.append("}");
break;
}
case JRQueryChunk.TYPE_CLAUSE_TOKENS :
{
sb.append("$X{");
sb.append(queryChunk.getText());
sb.append("}");
break;
}
case JRQueryChunk.TYPE_TEXT :
default :
{
sb.append( queryChunk.getText() );
break;
}
}
}
text = sb.toString();
}
return text;
}
/**
* (Re)constructs a query clause chunk from the chunk tokens.
*
* @param tokens the chunk tokens
* @return the reconstructed query clause chunk
* @see JRQueryChunk#TYPE_CLAUSE_TOKENS
* @deprecated Replaced by {@link #asClauseText(String[], Character)}.
*/
public String asClauseText(String[] tokens)
{
return asClauseText(tokens, null);
}
/**
* (Re)constructs a query clause chunk from the chunk tokens.
*
* @param tokens the chunk tokens
* @param separator the chunk tokens separator character
* @return the reconstructed query clause chunk
* @see JRQueryChunk#TYPE_CLAUSE_TOKENS
*/
public String asClauseText(String[] tokens, Character separator)
{
if (separator == null)
{
separator = defaultTokenSeparator();
}
StringBuilder sb = new StringBuilder();
if (tokens != null && tokens.length > 0)
{
for (int i = 0; i < tokens.length; i++)
{
if (i > 0)
{
sb.append(separator);
}
String token = tokens[i];
if (token != null)
{
sb.append(token);
}
}
}
return sb.toString();
}
protected char defaultTokenSeparator()
{
String tokenSeparators = getTokenSeparators();
return tokenSeparators == null || tokenSeparators.isEmpty()
? ',' // would not normally happen, determineClauseTokenSeparator throws exception
: tokenSeparators.charAt(0);
}
}