package org.musetest.core.step;

import org.musetest.core.*;
import org.musetest.core.context.*;
import org.musetest.core.resource.*;
import org.musetest.core.steptest.*;
import org.musetest.core.values.*;

/**
 * Abstract base step implementation with some convenience methods for using value sources.
 * Also implements execute() to raise start and end events. Subclasses should override executeStep()
 * instead of execute() unless they take responsibility for raising those events.
 *
 * @author Christopher L Merrill (see LICENSE.txt for license details)
 */
public abstract class BaseStep implements MuseStep
    {
    public BaseStep(StepConfiguration configuration)
        {
        _config = configuration;
        }

    @Override
    public StepConfiguration getConfiguration()
        {
        return _config;
        }

    /**
     * Allows for future functionality to be performed before/after the actual implementation of the step.
     */
    @Override
    public StepExecutionResult execute(StepExecutionContext context) throws MuseExecutionError
        {
        return executeImplementation(context);
        }

    /**
     * Called by BaseStep.execute(). Subclasses should override this instead of execute()... or else take
     * responsibility for raising the start/end step events
     *
     * @param context The context in which the step is executed
     * @throws StepExecutionError If the step cannot be executed.
     */
    protected abstract StepExecutionResult executeImplementation(StepExecutionContext context) throws MuseExecutionError;

    /**
     * A convenience method to get a specific value source from the configuration parameter list.
     * @see BaseValueSource#getValueSource
     */
    protected MuseValueSource getValueSource(StepConfiguration config, String name, boolean required, MuseProject project) throws MuseInstantiationException
        {
        return BaseValueSource.getValueSource(config, name, required, project);
        }

    /**
     * A convenience method to resolves a value source to the desired type.
     * @see BaseValueSource#getValueSource
     */
    protected <T> T getValue(MuseValueSource source, StepExecutionContext context, boolean null_allowed, Class<T> type) throws ValueSourceResolutionError
        {
        return BaseValueSource.getValue(source, context, null_allowed, type);
        }

    /**
     * A convenience method to resolve a value source to the desired type with a default value.
     * @see BaseValueSource#getValueSource
     */
    protected <T> T getValue(MuseValueSource source, StepExecutionContext context, Class<T> type, T default_value) throws ValueSourceResolutionError
        {
        T result = BaseValueSource.getValue(source, context, true, type);
        if (result == null)
            return default_value;
        return result;
        }

    protected <T> T getVariable(StepExecutionContext context, String varname, Class<T> type) throws MuseExecutionError
        {
        Object value = context.getVariable(varname);
        if (value == null)
            throw new MuseExecutionError(String.format("Unable to get variable '%s' from the context. A %s is required.", varname, type.getSimpleName()));
        if (type.isAssignableFrom(value.getClass()))
            return (T) value;
        throw new MuseExecutionError(String.format("Variable '%s' in the context is a %s, but a %s is required.", varname, value.getClass().getSimpleName(), type.getSimpleName()));
        }

    protected <T> T getVariable(StepExecutionContext context, String varname, Class<T> type, T default_value) throws MuseExecutionError
        {
        Object value = context.getVariable(varname);
        if (value == null)
            return default_value;
        if (type.isAssignableFrom(value.getClass()))
            return (T) value;
        throw new MuseExecutionError(String.format("Variable '%s' in the context is a %s, but a %s is required.", varname, value.getClass().getSimpleName(), type.getSimpleName()));
        }

    private StepConfiguration _config;
    }



@@ -2865,95 +2865,566 @@
     
-protected %3CT%3E T getVariable(StepExecutionContext context, String varname, Class%3CT%3E type
+/**%0A     * Convenience method to get a variable from the context as a specific type. Null return is not allowed.%0A     */%0A    protected %3CT%3E T getVariable(StepExecutionContext context, String varname, Class%3CT%3E type) throws MuseExecutionError%0A        %7B%0A        return getVariable(context, varname, type, false);%0A        %7D%0A%0A    /**%0A     * Convenience method to get a variable from the context as a specific type. Null return may be allowed.%0A     */%0A    protected %3CT%3E T getVariable(StepExecutionContext context, String varname, Class%3CT%3E type, boolean null_allowed
 ) th
@@ -3529,32 +3529,105 @@
 (value == null)%0A
+            %7B%0A            if (null_allowed)%0A                return null;%0A
             thro
@@ -3757,32 +3757,46 @@
 SimpleName()));%0A
+            %7D%0A
         if (type
@@ -4050,24 +4050,152 @@
 %0A        %7D%0A%0A
+    /**%0A     * Convenience method to get a variable from the context as a specific type. Default value may be supplied.%0A     */%0A
     protecte

Add variation of BaseStep.getValue() that allows null return.