001: /*
002: * Copyright 2006 Pentaho Corporation. All rights reserved.
003: * This software was developed by Pentaho Corporation and is provided under the terms
004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
005: * this file except in compliance with the license. If you need a copy of the license,
006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
007: * BI Platform. The Initial Developer is Pentaho Corporation.
008: *
009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
011: * the license for the specific language governing your rights and limitations.
012: */
013: package org.pentaho.core.util;
014:
015: import java.util.List;
016: import java.util.Map;
017: import java.util.StringTokenizer;
018: import java.util.regex.Matcher;
019:
020: import org.apache.commons.logging.Log;
021: import org.apache.commons.logging.LogFactory;
022: import org.pentaho.commons.connection.IPentahoMetaData;
023: import org.pentaho.commons.connection.IPentahoResultSet;
024: import org.pentaho.core.runtime.IRuntimeContext;
025: import org.pentaho.core.system.PentahoMessenger;
026: import org.pentaho.messages.Messages;
027:
028: /**
029: * This is a utility class that implements the IParameterResolver and resolves parameters
030: * based on a lookup map provided.
031: *
032: * @author Will Gorman
033: *
034: * @see MDXBaseComponent
035: * @see HQLBaseComponent
036: * @see XQueryBaseComponent
037: */
038: public class MapParameterResolver extends PentahoMessenger implements
039: IParameterResolver {
040:
041: private static final long serialVersionUID = -93516661348245465L;
042:
043: Map lookupMap;
044:
045: String prefix = null;
046:
047: IRuntimeContext runtimecontext = null;
048:
049: public MapParameterResolver(Map map, String prefix,
050: IRuntimeContext runtime) {
051: lookupMap = map;
052: this .prefix = prefix;
053: runtimecontext = runtime;
054: }
055:
056: public Log getLogger() {
057: return LogFactory.getLog(MapParameterResolver.class);
058: }
059:
060: /**
061: * This method is called when TemplateUtil.applyTemplate() encounters a parameter.
062: *
063: * @param template the source string
064: * @param parameter the parameter value
065: * @param parameterMatcher the regex parameter matcher
066: * @param copyStart the start of the copy
067: * @param results the output result
068: * @return the next copystart
069: */
070: public int resolveParameter(String template, String parameter,
071: Matcher parameterMatcher, int copyStart,
072: StringBuffer results) {
073:
074: StringTokenizer tokenizer = new StringTokenizer(parameter, ":"); //$NON-NLS-1$
075: if (tokenizer.countTokens() == 2) { // Currently, the component only handles one bit of metadata
076: String parameterPrefix = tokenizer.nextToken();
077: String inputName = tokenizer.nextToken();
078:
079: if (parameterPrefix.equals(prefix)) {
080: // We know this parameter is for us.
081: // First, is this a special input
082: Object parameterValue = TemplateUtil.getSystemInput(
083: inputName, runtimecontext);
084: if ((parameterValue == null)
085: && lookupMap.containsKey(inputName)) {
086: parameterValue = lookupMap.get(inputName);
087: }
088: if (parameterValue != null) {
089: // We have a parameter value - now, it's time to create a parameter and build up the
090: // parameter string
091: int start = parameterMatcher.start();
092: int end = parameterMatcher.end();
093:
094: // We now have a valid start and end. It's time to see whether we're dealing
095: // with an array, a result set, or a scalar.
096: StringBuffer parameterBuffer = new StringBuffer();
097:
098: // find and remove the next placeholder, to be replaced by the new value
099:
100: if (parameterValue instanceof String) {
101: parameterBuffer
102: .append(((String) parameterValue)
103: .replaceAll("'", "\\'")); //$NON-NLS-1$ //$NON-NLS-2$
104: } else if (parameterValue instanceof Object[]) {
105: Object[] pObj = (Object[]) parameterValue;
106: for (int i = 0; i < pObj.length; i++) {
107: // TODO: escape quotes!
108: parameterBuffer
109: .append((parameterBuffer.length() == 0) ? "'" + pObj[i] + "'" : ",'" + pObj[i] + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
110: }
111: } else if (parameterValue instanceof IPentahoResultSet) {
112: IPentahoResultSet rs = (IPentahoResultSet) parameterValue;
113: // See if we can find a column in the metadata with the same
114: // name as the input
115: IPentahoMetaData md = rs.getMetaData();
116: int columnIdx = -1;
117: if (md.getColumnCount() == 1) {
118: columnIdx = 0;
119: } else {
120: columnIdx = md
121: .getColumnIndex(new String[] { parameter });
122: }
123: if (columnIdx < 0) {
124: error(Messages
125: .getErrorString("Template.ERROR_0005_COULD_NOT_DETERMINE_COLUMN")); //$NON-NLS-1$
126: return -1;
127: }
128: int rowCount = rs.getRowCount();
129: Object valueCell = null;
130: // TODO support non-string columns
131: for (int i = 0; i < rowCount; i++) {
132: valueCell = rs.getValueAt(i, columnIdx);
133:
134: // TODO: escape quotes!
135: parameterBuffer
136: .append((parameterBuffer.length() == 0) ? "'" + valueCell + "'" : ",'" + valueCell + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
137: }
138: } else if (parameterValue instanceof List) {
139: List pObj = (List) parameterValue;
140: for (int i = 0; i < pObj.size(); i++) {
141: parameterBuffer
142: .append((parameterBuffer.length() == 0) ? "'" + pObj.get(i) + "'" : ",'" + pObj.get(i) + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
143: }
144: } else {
145: // If we're here, we know parameterValue is not null and not a string
146: parameterBuffer.append(parameterValue
147: .toString().replaceAll("'", "\\'")); //$NON-NLS-1$ //$NON-NLS-2$
148: }
149:
150: // OK - We have a parameterBuffer and have filled out the preparedParameters
151: // list. It's time to change the SQL to insert our parameter marker and tell
152: // the caller we've done our job.
153: results
154: .append(template
155: .substring(copyStart, start));
156: copyStart = end;
157: results.append(parameterBuffer);
158: return copyStart;
159: }
160: }
161: }
162:
163: return -1; // Nothing here for us - let default behavior through
164: }
165: }
|