/* * The MIT License (MIT) * * Copyright (c) 2014 Thomas Morgner * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.pentaho.reporting.sdk.datasource; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Locale; import org.pentaho.reporting.engine.classic.core.DataRow; import org.pentaho.reporting.engine.classic.core.util.PropertyLookupParser; import org.pentaho.reporting.libraries.base.util.CSVTokenizer; import org.pentaho.reporting.libraries.formatting.FastMessageFormat; public class QueryParametrizer extends PropertyLookupParser { private LinkedHashMap<String,String> collectedParameter; private LinkedHashSet<String> collectedFields; private DataRow parameters; private Locale locale; private int counter; /** * Default Constructor. */ public QueryParametrizer(final DataRow parameters, final Locale locale) { if (locale == null) { throw new NullPointerException("Locale must not be null"); } if (parameters == null) { throw new NullPointerException("Parameter datarow must not be null"); } this.collectedFields = new LinkedHashSet<>(); this.collectedParameter = new LinkedHashMap<>(); this.parameters = parameters; this.locale = locale; setMarkerChar('$'); setOpeningBraceChar('{'); setClosingBraceChar('}'); } /** * Looks up the property with the given name. This replaces the name with the current index position. * * @param name the name of the property to look up. * @return the translated value. */ protected String lookupVariable(final String name) { final CSVTokenizer tokenizer = new CSVTokenizer(name, false); if (tokenizer.hasMoreTokens() == false) { // invalid reference .. return null; } counter += 1; String parameterReference = "param_" + counter; // NON-NLS final String parameterName = tokenizer.nextToken(); final Object o = parameters.get(parameterName); String subType = null; final StringBuilder b = new StringBuilder(name.length() + 4); b.append('{'); b.append("0"); while (tokenizer.hasMoreTokens()) { b.append(','); final String token = tokenizer.nextToken(); b.append(token); if (subType == null) { subType = token; } } b.append('}'); final String formatString = b.toString(); if ("string".equals(subType)) { if (o == null) { return "null"; // NON-NLS } return quote(String.valueOf(o)); } final FastMessageFormat messageFormat = new FastMessageFormat(formatString, locale); final String parameterValue = messageFormat.format(new Object[]{o}); collectedFields.add(parameterName); collectedParameter.put(parameterReference, parameterValue); return "@" + parameterReference; } public LinkedHashSet<String> getCollectedFields() { return collectedFields; } public LinkedHashMap<String, String> getCollectedParameter() { return collectedParameter; } protected static String quote(final String original) { // This solution needs improvements. Copy blocks instead of single // characters. final int length = original.length(); final StringBuilder b = new StringBuilder(length * 12 / 10); b.append('"'); for (int i = 0; i < length; i++) { final char c = original.charAt(i); if (c == '"') { b.append('"'); b.append('"'); } else { b.append(c); } } b.append('"'); return b.toString(); } }