/*
* 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.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;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
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 ( ( (IActionParameter) entry.getValue() ).isOutputParameter() ) {
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());
// only put output parameters
Map outParams = actionDefinition.getActionOutputDefinitions();
for ( Object outKey : outParams.keySet() ) {
ActionParameter param = (ActionParameter) outParams.get( outKey );
if ( param.isOutputParameter() ) {
currentOutputs.put( outKey, param );
}
}
// 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();
if ( !outputParam.isOutputParameter() ) {
continue;
}
// 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 ) );
}
}