/*
* 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 - 2008 Pentaho Corporation. All rights reserved.
*
*/
package org.pentaho.platform.engine.services.runtime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.map.ListOrderedMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.platform.api.engine.IActionParameter;
import org.pentaho.platform.api.engine.IActionSequence;
import org.pentaho.platform.api.engine.IActionSequenceResource;
import org.pentaho.platform.api.engine.IParameterManager;
import org.pentaho.platform.api.engine.IParameterProvider;
import org.pentaho.platform.api.engine.ISolutionActionDefinition;
import org.pentaho.platform.engine.services.actionsequence.ActionParameter;
import org.pentaho.platform.engine.services.actionsequence.ActionParameterSource;
import org.pentaho.platform.engine.services.messages.Messages;
public class ParameterManager implements IParameterManager {
private static final String[] EMPTY_ARRAY = new String[0];
private ListOrderedMap allParams;
private ListOrderedMap allResources;
private List<IActionParameter> waitingToDieParams;
private ListOrderedMap currentInputs;
private ListOrderedMap currentOutputs;
private ListOrderedMap currentResources;
private String[] sequenceInputNames;
private String[] sequenceResourceNames;
private static final Log logger = LogFactory.getLog(ParameterManager.class);
private Map sequenceOutputDefs;
ParameterManager() {
allParams = new ListOrderedMap();
allResources = new ListOrderedMap();
waitingToDieParams = new ArrayList<IActionParameter>();
currentInputs = new ListOrderedMap();
currentResources = new ListOrderedMap();
currentOutputs = new ListOrderedMap();
sequenceOutputDefs = new ListOrderedMap();
sequenceInputNames = ParameterManager.EMPTY_ARRAY;
}
@SuppressWarnings({"all"})
ParameterManager(final IActionSequence actionSequence) {
this();
allParams.putAll(actionSequence.getInputDefinitions());
sequenceInputNames = (String[]) actionSequence.getInputDefinitions().keySet().toArray(ParameterManager.EMPTY_ARRAY);
allResources.putAll(actionSequence.getResourceDefinitions());
sequenceResourceNames = (String[]) actionSequence.getResourceDefinitions().keySet().toArray(
ParameterManager.EMPTY_ARRAY);
sequenceOutputDefs.putAll(actionSequence.getOutputDefinitions());
}
public Map getAllParameters() {
return (allParams);
}
public IActionParameter getCurrentInput(final String inputName) {
return ((IActionParameter) currentInputs.get(inputName));
}
public IActionParameter getCurrentOutput(final String outputName) {
return ((IActionParameter) currentOutputs.get(outputName));
}
public IActionSequenceResource getCurrentResource(final String resourceName) {
return ((IActionSequenceResource) currentResources.get(resourceName));
}
public Set getCurrentInputNames() {
return currentInputs.keySet();
}
public IActionParameter getLoopParameter(final String inputName) {
return ((IActionParameter) allParams.get(inputName));
}
public Set getCurrentOutputNames() {
return currentOutputs.keySet();
}
public Set getCurrentResourceNames() {
return (currentResources.keySet());
}
protected boolean disposeParameter(final ActionParameter param) {
try {
if (param != null) {
param.dispose();
return true;
}
} catch (Throwable th) {
// Do something here
ParameterManager.logger.error(Messages.getInstance().getErrorString(
"ParameterManager.ERROR_0001_DISPOSE_ERROR", param.getName()), th); //$NON-NLS-1$
}
return false;
}
public void dispose() {
dispose(null);
}
public void dispose(final List exceptParameters) {
if (allParams != null) {
for (Iterator it = allParams.values().iterator(); it.hasNext();) {
ActionParameter param = (ActionParameter) it.next();
if ((exceptParameters == null) || !exceptParameters.contains(param.getValue())) {
disposeParameter(param);
}
}
for (Iterator it = waitingToDieParams.iterator(); it.hasNext();) {
ActionParameter param = (ActionParameter) it.next();
if ((exceptParameters == null) || !exceptParameters.contains(param.getValue())) {
disposeParameter(param);
}
}
}
}
public void resetParameters() {
dispose();
currentInputs.clear();
currentOutputs.clear();
currentResources.clear();
allParams = resetMap(sequenceInputNames, allParams);
allResources = resetMap(sequenceResourceNames, allResources);
}
private ListOrderedMap resetMap(final String[] names, final ListOrderedMap oldMap) {
ListOrderedMap newMap = new ListOrderedMap();
for (String element : names) {
newMap.put(element, oldMap.get(element));
}
return (newMap);
}
public void setCurrentParameters(final ISolutionActionDefinition actionDefinition) {
currentInputs.clear();
currentOutputs.clear();
currentResources.clear();
if (actionDefinition == null) {
currentInputs = resetMap(sequenceInputNames, allParams);
currentResources = resetMap(sequenceResourceNames, allParams);
for (Iterator it = sequenceOutputDefs.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
String outputName = (String) entry.getKey();
IActionParameter param = (IActionParameter) allParams.get(outputName);
if (param == null) {
currentOutputs.put(outputName, entry.getValue());
} else {
currentOutputs.put(outputName, param);
}
}
return;
}
String key;
Object value;
for (Iterator it = actionDefinition.getActionInputDefinitions().keySet().iterator(); it.hasNext();) {
key = (String) it.next();
value = allParams.get(actionDefinition.getMappedInputName(key));
if (value == null) {
value = actionDefinition.getActionInputDefinitions().get(key);
if (!((ActionParameter) value).hasDefaultValue()) {
value = null; // Only use if there is a default value;
}
}
if (value != null) {
currentInputs.put(key, value);
}
}
currentOutputs.putAll(actionDefinition.getActionOutputDefinitions());
// This enables the old behavior - It should eventually be removed
if (!actionDefinition.hasActionResources()) {
currentResources.putAll(allResources);
} else {
for (Iterator it = actionDefinition.getActionResourceDefinitionNames().iterator(); it.hasNext();) {
key = (String) it.next();
String key2 = actionDefinition.getMappedResourceName(key);
value = allResources.get(key2);
currentResources.put(key, value);
}
}
}
public void addToAllInputs(final String key, final IActionParameter param) {
IActionParameter old = (IActionParameter) allParams.put(key, param);
if ((old != null) && !allParams.containsValue(old)) {
waitingToDieParams.add(old); // Just in case a parameter gets over written delete it at the final dispose
}
}
public void addToCurrentInputs(final String key, final IActionParameter param) {
if (currentInputs.containsKey(key)) {
currentInputs.remove(key);
}
currentInputs.put(key, param);
}
public boolean addOutputParameters(final ISolutionActionDefinition actionDefinition) {
String key;
for (Iterator it = actionDefinition.getActionOutputDefinitions().keySet().iterator(); it.hasNext();) {
key = (String) it.next();
IActionParameter outputParam = (IActionParameter) currentOutputs.get(key);
key = actionDefinition.getMappedOutputName(key);
// If we already have a parameter with this name, set the value and reuse the definition.
IActionParameter param = (IActionParameter) allParams.get(key);
if (param != null) {
if (param != outputParam) { // This is a trap for catching temp params that didn't get deleted at the end of the last loop
param.dispose();
param.setValue(outputParam.getValue());
}
} else {
addToAllInputs(key, outputParam);
}
}
return (true);
}
/**
* Returns a mapping of output parameters and the value and destination.
*
* @param actionSequence The Action Sequence definition to use
*
* @return a map with the param name as the key and a ReturnParameter containing the data.
*/
public Map getReturnParameters() {
ListOrderedMap returnMap = new ListOrderedMap();
// Iterate for each output defined
for (Iterator it = sequenceOutputDefs.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
String outputName = (String) entry.getKey();
IActionParameter outputParam = (IActionParameter) entry.getValue();
// The output Action Parameter objects do not have values - they are just the definition
// Pull the value from allParams
IActionParameter inputParam = (IActionParameter) allParams.get(outputName);
if (inputParam == null) {
returnMap.put(outputParam.getName(), null);
} else {
for (Iterator varIt = outputParam.getVariables().iterator(); varIt.hasNext();) {
ActionParameterSource src = (ActionParameterSource) varIt.next();
returnMap.put(outputParam.getName(), new ReturnParameter(src.getSourceName(), src.getValue(), inputParam
.getValue()));
}
}
}
return (returnMap);
}
public class ReturnParameter {
public String destinationName;
public String destinationParameter;
public Object value;
public ReturnParameter(final String destinationName, final String destinationParameter, final Object value) {
this.destinationName = destinationName;
this.destinationParameter = destinationParameter;
this.value = value;
}
}
public String getActualRequestParameterName(final String fieldName) {
/*
* This method solves the problem that exists when generating an xForm
* based on the parameter definition. The parameter definition looks
* like this:
*
* <REGION type="string"> <default-value></default-value> <sources>
* <request>regn</request> </sources> </REGION>
*
* In the above definition, the parameter name is REGION, but we'll be
* looking for the variable regn in the request. Before this fix, the
* XForm would generate code that puts REGION on the request, not regn.
*
* MB
*/
// TODO - figure out the actual name used - this is just a guess - maybe store in the ActionParam
IActionParameter actionParameter = getCurrentInput(fieldName);
if (actionParameter != null) {
List vars = actionParameter.getVariables();
for (int i = 0; i < vars.size(); i++) {
ActionParameterSource source = (ActionParameterSource) (vars.get(i));
if (source.getSourceName().equals(IParameterProvider.SCOPE_REQUEST)) {
return source.getValue();
}
}
}
return fieldName;
}
public IActionParameter getInput(final String inputName) {
return ((IActionParameter) allParams.get(inputName));
}
}