Package gri.gridp.tasks

Source Code of gri.gridp.tasks.GridpScriptAssistant$MissingParameterException

/*
* File: GridpScriptAssistant.java
* Author: Daniel Rogers
* Created on Mar 19, 2008
*
*/
package gri.gridp.tasks;

import gri.gridp.filematchers.AdvancedFileMatcher;
import gri.gridp.filematchers.FileMatcher;
import gri.gridp.modules.BasicParameter;
import gri.gridp.modules.Flag;
import gri.gridp.modules.Function;
import gri.gridp.modules.Output;
import gri.gridp.modules.Parameter;
import gri.gridp.scripts.ScriptParser;
import gri.gridp.scripts.UnixScriptParser;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Helper class for preparing GRIDP scripts from a given set of
* input parameters.  Converts Java objects to the appropriate
* text values for insertion into a script.  Also can evaluate
* a script using these values.  This object also will store the
* text values that are used in the script and make them available
* for recognition of output files.  Oftentimes, output will be based
* upon input and the values of the input will need to be saved
* to properly identify output files.
*
* TODO: this class could be improved.
*
* @author dan.rogers
*/
public class GridpScriptAssistant {

  Function function;
  //String os = null;
  //String shell = null;
  File workingDirectory;

  ScriptParser scriptParser;

  Map txtScriptParams;

  // ------------------------------------------------------- Constructors

  public GridpScriptAssistant(Function function, File workingDirectory) {
    this.function = function;
    this.workingDirectory = workingDirectory;
    this.scriptParser = new UnixScriptParser();

    txtScriptParams = null;
  }

  // ---------------------------------------------------------- Accessors

  public void setFunction(Function function) {
    this.function = function;
  }
  public Function getFunction()                   {return function;}

  public void setWorkingDirectory(File file) {
    this.workingDirectory = file;
  }
  public File getWorkingDirectory()               {return workingDirectory;}

  public void setScriptParser(ScriptParser parser) {
    this.scriptParser = parser;
  }
  public ScriptParser getScriptParser()           {return scriptParser;}

  /**
   * Returns the script parameters that were used for insertion into
   * the script when prepareScript() was called.
   */
  public Map getScriptParameters() {
    return txtScriptParams;
  }

  // ----------------------------------------------------- Inputs

  public String prepareScript(Map inputs) throws Exception {
    //save script params (used by FileMatcher):
    Map textParams = new HashMap();
    Map scriptParams = new HashMap();
    prepareScriptParams(inputs, textParams, scriptParams);

    this.txtScriptParams = textParams;

    //create script:
      String scriptTemplate = function.getScript().getText();
      return scriptParser.setVariables(scriptTemplate, scriptParams);
  }

  /**
   * Processes the given input parameters to prepare for script
   * execution.  The inputs are strings, booleans, and TransferableFiles.
   * We will determine the appropriate values to insert into the script
   * based on the function definition.  Parameters are handled as
   * indicated:
   *
   * Flag:
   *    A boolean value is expected in the map.
   *    A default value is used if not present (and defined).
   *    The text value the Flag has defined for this boolean is then returned
   *   
   * BasicParameter:
   *    String-type parameters expect Strings in the map.
   *    Default values are used if not present.
   *    These are returned without modification.
   *   
   *    File-type parameters expected File's.
   *    These are copied to the working directory.
   *    The path of the file will be returned for insertion into the script.
   *  
   * @param inputs Map<String,Object> of input objects
   * @param textParams Map<String,String> of text values for objects (without scriptlets evaluated)
   * @param scriptParams Map<String,String> of script values for objects (with scriptlet evaluated)
   */
  protected void prepareScriptParams(Map inputs, Map textParams, Map scriptParams) throws Exception {

    List funcParams = function.getParameters();
    Parameter param;

    for (int i=0; i<funcParams.size(); i++) {
      param = (Parameter)funcParams.get(i);

      //get param value:
        String paramName = param.getName();
        Object value = inputs.get(paramName);

        //determine text value and script value
        String textValue = getTextValue(param, value);
        String scriptValue;

        if (value == null) {
          if (!param.hasNullScriptlet())
            throw new MissingParameterException(paramName);

          textValue = "";
          scriptValue = param.getNullScriptlet();
        }
        else {

          if (param.hasScriptlet()) {
            Map scriptletParams = new HashMap(2);
            scriptletParams.put(paramName, textValue);
            //scriptletParams.put(paramName + ".value", textValue);

            scriptValue = scriptParser.setVariables(param.getScriptlet(), scriptletParams);
          }
          else
            scriptValue = textValue;

        }

        textParams.put(paramName, textValue);
        scriptParams.put(paramName, scriptValue);

    }

  }

  /**
   * Returns the text value that will be used in the GRIDP script
   * for the given parameter.  This does not evalulate any scriptlet
   * that may exist.  If a value is null we will try to obtain the
   * default value for the parameter.  Otherwise, null will be
   * returned.
   * 
   * Additional actions also occur such as storing files before
   * returning their names as values in the script.
   */
  protected String getTextValue(Parameter param, Object objValue) throws MissingParameterException, IOException {
    String textValue;

    //flag:
    if (param instanceof Flag) {
      Flag flagParam = (Flag)param;

      //obtain boolean value:
      Boolean value = (Boolean)objValue;
      if (value == null) {
        if (!flagParam.hasDefault())
          return null;

        value = flagParam.getDefault();
      }

      //translate boolean value to text we will put in script:
        textValue = flagParam.getValue(value.booleanValue());
        System.out.println("Flag text: " + textValue);
    }

    //basic parameter:
    else if (param instanceof BasicParameter)  {
      BasicParameter basicParam = (BasicParameter)param;

      if (basicParam.getParameterType().equals("file")) {
        File file = (File)objValue;
        if (file == null)
          return null;

        if (!file.getParentFile().equals(this.workingDirectory)) {
          File newFile = new File(this.workingDirectory, file.getName());
          copy(file, newFile);
          textValue = newFile.getName();
        }
        else
          textValue = file.getName();
      }
      else {
        String value = (String)objValue;
        if (value == null) {
          if (!basicParam.hasDefault())
            return null;

          value = basicParam.getDefault();
        }

        //TODO: validate against options

        textValue = value;
      }
    }

    //other (should never happen):
    else
      throw new RuntimeException("Illegal parameter class: " + param.getClass().getName());

    return textValue;
  }

  // ------------------------------------------------------ Outputs

  /**
   * Searches through the given files and creates a map of output
   * files for the outputs generated by the script.  A FileMatcher
   * is used to do this.
   */
  public Map removeOutputs(List files, FileMatcher fileMatcher) {

    //search for specified outputs (and remove):
    Map outputs = new HashMap();

    List outputDefs = function.getOutputs();
    Output outputDef;
    for (int i=0; i<outputDefs.size(); i++) {
      outputDef = (Output)outputDefs.get(i);
      fileMatcher.setPattern(outputDef.getPattern());

      if (outputDef.getType().equals("file")) {
        File matchingFile = removeMatch(files, fileMatcher);
        outputs.put(outputDef.getName(), matchingFile);
      }
      else {
        List matchingFiles = removeMatches(files, fileMatcher);
        outputs.put(outputDef.getName(), matchingFiles);
      }
    }
   
    return outputs;
  }
  /**
   * Finds the outputs generated by the script.  An AdvancedFileMatcher
   * is used to do this and required a map of parameters that it will
   * substitute into regular expressions.  These are provided as a map
   * of name->value pairs.
   */
  public Map removeOutputs(List files, Map txtScriptParams) {
    return removeOutputs(files, new AdvancedFileMatcher(txtScriptParams));
  }
  /**
   * Finds the outputs generated by the script.  The text parameters
   * generated for the script in prepareScript() are used for substitution
   * into the file patterns.  This function can only be called if
   * prepareScript() has first been called.  Otherwise use findOutputs(File[], Map)
   *
   * @throws IllegalStateException If you haven't first called prepareScript()
   */
  public Map removeOutputs(List files) {
    if (this.txtScriptParams == null)
      throw new IllegalStateException("This method cannot be invoked if prepareScript() has not been first called.  Use findOutputs(File[], Map) instead");
   
    return removeOutputs(files, this.txtScriptParams);
  }

  /**
   * Returns and removes the first file in the list the matcher finds
   * (null if none found)
   */
  protected File removeMatch(List files, FileMatcher matcher) {
    File file;
    for (int i=0; i<files.size(); i++) {
      file = (File)files.get(i);
      if (matcher.matches(file)) {
        files.remove(i);
        return file;
      }

    }
    return null;
  }
  /**
   * Returns and removes all files in the list that the matcher finds.
   * (empty list if none found)
   */
  protected List removeMatches(List files, FileMatcher matcher) {
    List matches = new ArrayList();

    File file;
    for (int i=0; i<files.size(); i++) {
      file = (File)files.get(i);
      if (matcher.matches(file)) {
        matches.add(file);
        files.remove(i);
        i--;    //step back since we just shortened list
      }
    }

    return matches;
  }

  // ---------------------------------------------------- Utility

  protected void copy(File from, File to) throws IOException {
    FileInputStream in = new FileInputStream(from);
    FileOutputStream out = new FileOutputStream(to);

    byte [] bytes = new byte[512];
    int bytesRead = 0;
    while ((bytesRead = in.read(bytes)) > 0)
      out.write(bytes, 0, bytesRead);

    out.close();
    in.close();
  }

  // --------------------------------------------- Inner Classes

  static class MissingParameterException extends Exception {
    String paramName;

    public MissingParameterException(String paramName) {
      super("Missing parameter: " + paramName + ".  No default provided.");
      this.paramName = paramName;
    }
  }

  // ------------------------------------------------------- Test

  public static void main(String [] args) {
    try {
      BasicParameter p = new BasicParameter("param");
      p.setScriptlet("-p $param");
      p.setParameterType("string");

      gri.gridp.modules.Script script = new gri.gridp.modules.Script();
      script.setText("myprogram $param");

      Function f = new Function();
      f.addParameter(p);
      f.addScript(script);

      GridpScriptAssistant assist = new GridpScriptAssistant(f, new File("."));
      Map inputs = new HashMap();
      inputs.put("param", "value");
      String s = assist.prepareScript(inputs);
      System.out.println(s);

      //System.out.println(assist.getScriptParameters().get("param"));
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }

}
TOP

Related Classes of gri.gridp.tasks.GridpScriptAssistant$MissingParameterException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.