/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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 General Public License for more details.
*
*
* Copyright 2006 - 2013 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.platform.engine.services.runtime;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.commons.connection.IPentahoMetaData;
import org.pentaho.commons.connection.IPentahoResultSet;
import org.pentaho.platform.api.engine.IParameterResolver;
import org.pentaho.platform.api.engine.IRuntimeContext;
import org.pentaho.platform.engine.services.PentahoMessenger;
import org.pentaho.platform.engine.services.messages.Messages;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
/**
* This is a utility class that implements the IParameterResolver and resolves parameters based on a lookup map
* provided.
*
* @author Will Gorman
*
* @see MDXBaseComponent
* @see HQLBaseComponent
* @see XQueryBaseComponent
*/
public class MapParameterResolver extends PentahoMessenger implements IParameterResolver {
private static final long serialVersionUID = -93516661348245465L;
Map lookupMap;
String prefix = null;
IRuntimeContext runtimecontext = null;
public MapParameterResolver( final Map map, final String prefix, final IRuntimeContext runtime ) {
lookupMap = map;
this.prefix = prefix;
runtimecontext = runtime;
}
@Override
public Log getLogger() {
return LogFactory.getLog( MapParameterResolver.class );
}
/**
* This method is called when TemplateUtil.applyTemplate() encounters a parameter.
*
* @param template
* the source string
* @param parameter
* the parameter value
* @param parameterMatcher
* the regex parameter matcher
* @param copyStart
* the start of the copy
* @param results
* the output result
* @return the next copystart
*/
public int resolveParameter( final String template, final String parameter, final Matcher parameterMatcher,
int copyStart, final StringBuffer results ) {
StringTokenizer tokenizer = new StringTokenizer( parameter, ":" ); //$NON-NLS-1$
if ( tokenizer.countTokens() == 2 ) { // Currently, the component only handles one bit of metadata
String parameterPrefix = tokenizer.nextToken();
String inputName = tokenizer.nextToken();
if ( parameterPrefix.equals( prefix ) ) {
// We know this parameter is for us.
// First, is this a special input
Object parameterValue = TemplateUtil.getSystemInput( inputName, runtimecontext );
if ( ( parameterValue == null ) && lookupMap.containsKey( inputName ) ) {
parameterValue = lookupMap.get( inputName );
}
if ( parameterValue != null ) {
// We have a parameter value - now, it's time to create a parameter and build up the
// parameter string
int start = parameterMatcher.start();
int end = parameterMatcher.end();
// We now have a valid start and end. It's time to see whether we're dealing
// with an array, a result set, or a scalar.
StringBuffer parameterBuffer = new StringBuffer();
// find and remove the next placeholder, to be replaced by the new value
if ( parameterValue instanceof String ) {
parameterBuffer.append( ( (String) parameterValue ).replaceAll( "'", "\\'" ) ); //$NON-NLS-1$ //$NON-NLS-2$
} else if ( parameterValue instanceof Object[] ) {
Object[] pObj = (Object[]) parameterValue;
for ( Object element : pObj ) {
// TODO: escape quotes!
parameterBuffer.append( ( parameterBuffer.length() == 0 ) ? "'" + element + "'" : ",'" + element + "'" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
} else if ( parameterValue instanceof IPentahoResultSet ) {
IPentahoResultSet rs = (IPentahoResultSet) parameterValue;
// See if we can find a column in the metadata with the same
// name as the input
IPentahoMetaData md = rs.getMetaData();
int columnIdx = -1;
if ( md.getColumnCount() == 1 ) {
columnIdx = 0;
} else {
columnIdx = md.getColumnIndex( new String[] { parameter } );
}
if ( columnIdx < 0 ) {
error( Messages.getInstance().getErrorString( "Template.ERROR_0005_COULD_NOT_DETERMINE_COLUMN" ) ); //$NON-NLS-1$
return -1;
}
int rowCount = rs.getRowCount();
Object valueCell = null;
// TODO support non-string columns
for ( int i = 0; i < rowCount; i++ ) {
valueCell = rs.getValueAt( i, columnIdx );
// TODO: escape quotes!
parameterBuffer.append( ( parameterBuffer.length() == 0 )
? "'" + valueCell + "'" : ",'" + valueCell + "'" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
} else if ( parameterValue instanceof List ) {
List pObj = (List) parameterValue;
for ( int i = 0; i < pObj.size(); i++ ) {
parameterBuffer.append( ( parameterBuffer.length() == 0 )
? "'" + pObj.get( i ) + "'" : ",'" + pObj.get( i ) + "'" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
} else {
// If we're here, we know parameterValue is not null and not a string
parameterBuffer.append( parameterValue.toString().replaceAll( "'", "\\'" ) ); //$NON-NLS-1$ //$NON-NLS-2$
}
// OK - We have a parameterBuffer and have filled out the preparedParameters
// list. It's time to change the SQL to insert our parameter marker and tell
// the caller we've done our job.
results.append( template.substring( copyStart, start ) );
copyStart = end;
results.append( parameterBuffer );
return copyStart;
}
}
}
return -1; // Nothing here for us - let default behavior through
}
}