Change the way to deal with Limits to simplify wrapper writing and enable couping...
[jabaws.git] / engine / compbio / engine / client / SkeletalExecutable.java
index dbdb4f5..b289f6c 100644 (file)
@@ -27,246 +27,251 @@ import org.apache.log4j.Logger;
 \r
 import compbio.engine.client.CommandBuilder.Parameter;\r
 import compbio.engine.conf.PropertyHelperManager;\r
+import compbio.metadata.Limit;\r
+import compbio.metadata.LimitsManager;\r
 import compbio.util.PropertyHelper;\r
 import compbio.util.Util;\r
 \r
 public abstract class SkeletalExecutable<T> implements Executable<T> {\r
 \r
-    protected static final PropertyHelper ph = PropertyHelperManager\r
-           .getPropertyHelper();\r
+       protected static final PropertyHelper ph = PropertyHelperManager\r
+                       .getPropertyHelper();\r
 \r
-    private static Logger log = Logger.getLogger(SkeletalExecutable.class);\r
+       private static Logger log = Logger.getLogger(SkeletalExecutable.class);\r
 \r
-    protected String inputFile = "input.txt";\r
-    protected String outputFile = "output.txt";\r
-    protected String errorFile = "error.txt";\r
+       // Cache for Limits information\r
+       private LimitsManager<T> limits;\r
 \r
-    private boolean isInputSet = false;\r
-    private boolean isOutputSet = false;\r
-    private boolean isErrorSet = false;\r
+       protected String inputFile = "input.txt";\r
+       protected String outputFile = "output.txt";\r
+       protected String errorFile = "error.txt";\r
 \r
-    /**\r
-     * This has to allow duplicate parameters as different options may have the\r
-     * same value e.g. Muscle -weight1 clustalw -weight2 clustalw\r
-     */\r
-    protected CommandBuilder<T> cbuilder;\r
+       private boolean isInputSet = false;\r
+       private boolean isOutputSet = false;\r
+       private boolean isErrorSet = false;\r
 \r
-    public SkeletalExecutable() {\r
-       cbuilder = new CommandBuilder<T>(" ");\r
-    }\r
+       /**\r
+        * This has to allow duplicate parameters as different options may have the\r
+        * same value e.g. Muscle -weight1 clustalw -weight2 clustalw\r
+        */\r
+       protected CommandBuilder<T> cbuilder;\r
+\r
+       public SkeletalExecutable() {\r
+               cbuilder = new CommandBuilder<T>(" ");\r
+       }\r
 \r
-    public SkeletalExecutable(String parameterKeyValueDelimiter) {\r
-       assert parameterKeyValueDelimiter != null;\r
-       cbuilder = new CommandBuilder<T>(parameterKeyValueDelimiter);\r
-    }\r
+       public SkeletalExecutable(String parameterKeyValueDelimiter) {\r
+               assert parameterKeyValueDelimiter != null;\r
+               cbuilder = new CommandBuilder<T>(parameterKeyValueDelimiter);\r
+       }\r
 \r
-    public SkeletalExecutable<T> setInput(String inFile) {\r
-       if (compbio.util.Util.isEmpty(inFile)) {\r
-           throw new IllegalArgumentException("Input file must not be NULL");\r
+       public SkeletalExecutable<T> setInput(String inFile) {\r
+               if (compbio.util.Util.isEmpty(inFile)) {\r
+                       throw new IllegalArgumentException("Input file must not be NULL");\r
+               }\r
+               this.inputFile = inFile;\r
+               this.isInputSet = true;\r
+               return this;\r
        }\r
-       this.inputFile = inFile;\r
-       this.isInputSet = true;\r
-       return this;\r
-    }\r
-\r
-    public SkeletalExecutable<T> setOutput(String outFile) {\r
-       if (compbio.util.Util.isEmpty(outFile)\r
-               || PathValidator.isAbsolutePath(outFile)) {\r
-           throw new IllegalArgumentException(\r
-                   "Output file must not be NULL and Absolute path could not be used! Please provide the filename only. Value provided: "\r
-                           + outFile);\r
+\r
+       public SkeletalExecutable<T> setOutput(String outFile) {\r
+               if (compbio.util.Util.isEmpty(outFile)\r
+                               || PathValidator.isAbsolutePath(outFile)) {\r
+                       throw new IllegalArgumentException(\r
+                                       "Output file must not be NULL and Absolute path could not be used! Please provide the filename only. Value provided: "\r
+                                                       + outFile);\r
+               }\r
+               this.outputFile = outFile;\r
+               this.isOutputSet = true;\r
+               return this;\r
        }\r
-       this.outputFile = outFile;\r
-       this.isOutputSet = true;\r
-       return this;\r
-    }\r
-\r
-    public SkeletalExecutable<T> setError(String errFile) {\r
-       if (compbio.util.Util.isEmpty(errFile)\r
-               || PathValidator.isAbsolutePath(errFile)) {\r
-           throw new IllegalArgumentException(\r
-                   "Error file must not be NULL and Absolute path could not be used! Please provide the filename only. Value provided: "\r
-                           + errFile);\r
+\r
+       public SkeletalExecutable<T> setError(String errFile) {\r
+               if (compbio.util.Util.isEmpty(errFile)\r
+                               || PathValidator.isAbsolutePath(errFile)) {\r
+                       throw new IllegalArgumentException(\r
+                                       "Error file must not be NULL and Absolute path could not be used! Please provide the filename only. Value provided: "\r
+                                                       + errFile);\r
+               }\r
+               this.errorFile = errFile;\r
+               this.isErrorSet = true;\r
+               return this;\r
+       }\r
+\r
+       @Override\r
+       public CommandBuilder<T> getParameters(ExecProvider provider) {\r
+               /*\r
+                * Prevent modification of the parameters unintentionally. This is\r
+                * important to preserve executable parameters intact as engine could\r
+                * add things into the array as it see fit. For instance\r
+                * ExecutableWrapper (part of local engines) add command line as the\r
+                * first element of an array.\r
+                */\r
+               paramValueUpdater();\r
+               return cbuilder;\r
+       }\r
+\r
+       @Override\r
+       public Executable<T> addParameters(List<String> parameters) {\r
+               cbuilder.addParams(parameters);\r
+               return this;\r
+       }\r
+\r
+       public Executable<T> setParameter(String parameter) {\r
+               cbuilder.setParam(parameter);\r
+               return this;\r
        }\r
-       this.errorFile = errFile;\r
-       this.isErrorSet = true;\r
-       return this;\r
-    }\r
-\r
-    @Override\r
-    public CommandBuilder<T> getParameters(ExecProvider provider) {\r
-       /*\r
-        * Prevent modification of the parameters unintentionally. This is\r
-        * important to preserve executable parameters intact as engine could\r
-        * add things into the array as it see fit. For instance\r
-        * ExecutableWrapper (part of local engines) add command line as the\r
-        * first element of an array.\r
+\r
+       /**\r
+        * This is a generic method of changing values of the parameters with\r
+        * properties\r
+        * \r
+        * This method iterates via commands for an executable finding matches from\r
+        * the Executable.properties file and replacing values in CommandBuilder\r
+        * with a combination of value from CommandBuilder to merge path from\r
+        * properties\r
         */\r
-       paramValueUpdater();\r
-       return cbuilder;\r
-    }\r
-\r
-    @Override\r
-    public Executable<T> addParameters(List<String> parameters) {\r
-       cbuilder.addParams(parameters);\r
-       return this;\r
-    }\r
-\r
-    public Executable<T> setParameter(String parameter) {\r
-       cbuilder.setParam(parameter);\r
-       return this;\r
-    }\r
-\r
-    /**\r
-     * This is a generic method of changing values of the parameters with\r
-     * properties\r
-     * \r
-     * This method iterates via commands for an executable finding matches from\r
-     * the Executable.properties file and replacing values in CommandBuilder\r
-     * with a combination of value from CommandBuilder to merge path from\r
-     * properties\r
-     */\r
-    void paramValueUpdater() {\r
-       for (Parameter command : cbuilder.getCommandList()) {\r
-           if (command.value == null) {\r
-               continue;\r
-           }\r
-           String propertyPath = compbio.engine.client.Util.getExecProperty(\r
-                   command.name + ".path", getType());\r
-           if (Util.isEmpty(propertyPath)) {\r
-               continue;\r
-           }\r
-           if (new File(command.value).isAbsolute()) {\r
-               // Matrix can be found so no actions necessary\r
-               // This method has been called already and the matrix name\r
-               // is modified to contain full path // no further actions is\r
-               // necessary\r
-               continue;\r
-           }\r
-           String absMatrixPath = compbio.engine.client.Util\r
-                   .convertToAbsolute(propertyPath);\r
-           command.value = absMatrixPath + File.separator + command.value;\r
-           cbuilder.setParam(command);\r
+       void paramValueUpdater() {\r
+               for (Parameter command : cbuilder.getCommandList()) {\r
+                       if (command.value == null) {\r
+                               continue;\r
+                       }\r
+                       String propertyPath = compbio.engine.client.Util.getExecProperty(\r
+                                       command.name + ".path", getType());\r
+                       if (Util.isEmpty(propertyPath)) {\r
+                               continue;\r
+                       }\r
+                       if (new File(command.value).isAbsolute()) {\r
+                               // Matrix can be found so no actions necessary\r
+                               // This method has been called already and the matrix name\r
+                               // is modified to contain full path // no further actions is\r
+                               // necessary\r
+                               continue;\r
+                       }\r
+                       String absMatrixPath = compbio.engine.client.Util\r
+                                       .convertToAbsolute(propertyPath);\r
+                       command.value = absMatrixPath + File.separator + command.value;\r
+                       cbuilder.setParam(command);\r
+               }\r
        }\r
-    }\r
-\r
-    /**\r
-     * This method cannot really tell whether the files has actually been\r
-     * created or not. It must be overridden as required.\r
-     * \r
-     * @see compbio.engine.client.Executable#getCreatedFiles()\r
-     */\r
-    @Override\r
-    public List<String> getCreatedFiles() {\r
-       return Arrays.asList(getOutput(), getError());\r
-    }\r
-\r
-    @Override\r
-    public String getInput() {\r
-       return inputFile;\r
-    }\r
-\r
-    protected boolean isInputSet() {\r
-       return isInputSet;\r
-    }\r
-\r
-    protected boolean isOutputSet() {\r
-       return isOutputSet;\r
-    }\r
-\r
-    protected boolean isErrorSet() {\r
-       return isErrorSet;\r
-    }\r
-\r
-    @Override\r
-    public String getOutput() {\r
-       return outputFile;\r
-    }\r
-\r
-    @Override\r
-    public String getError() {\r
-       return errorFile;\r
-    }\r
-\r
-    @Override\r
-    public String toString() {\r
-       String value = "Input: " + this.getInput() + "\n";\r
-       value += "Output: " + this.getOutput() + "\n";\r
-       value += "Error: " + this.getError() + "\n";\r
-       value += "Class: " + this.getClass() + "\n";\r
-       value += "Params: " + cbuilder + "\n";\r
-       return value;\r
-    }\r
-\r
-    @Override\r
-    public Executable<?> loadRunConfiguration(RunConfiguration rconfig) {\r
-       if (!compbio.util.Util.isEmpty(rconfig.getOutput())) {\r
-           setOutput(rconfig.getOutput());\r
+\r
+       /**\r
+        * This method cannot really tell whether the files has actually been\r
+        * created or not. It must be overridden as required.\r
+        * \r
+        * @see compbio.engine.client.Executable#getCreatedFiles()\r
+        */\r
+       @Override\r
+       public List<String> getCreatedFiles() {\r
+               return Arrays.asList(getOutput(), getError());\r
        }\r
-       if (!compbio.util.Util.isEmpty(rconfig.getError())) {\r
-           setError(rconfig.getError());\r
+\r
+       @Override\r
+       public String getInput() {\r
+               return inputFile;\r
        }\r
-       if (!compbio.util.Util.isEmpty(rconfig.getInput())) {\r
-           setInput(rconfig.getInput());\r
+\r
+       protected boolean isInputSet() {\r
+               return isInputSet;\r
        }\r
-       this.cbuilder = (CommandBuilder<T>) rconfig.getParameters();\r
-       return this;\r
-    }\r
-\r
-    @Override\r
-    public boolean equals(Object obj) {\r
-       if (obj == null) {\r
-           return false;\r
+\r
+       protected boolean isOutputSet() {\r
+               return isOutputSet;\r
        }\r
-       if (!(obj instanceof SkeletalExecutable<?>)) {\r
-           return false;\r
+\r
+       protected boolean isErrorSet() {\r
+               return isErrorSet;\r
        }\r
-       SkeletalExecutable<?> exec = (SkeletalExecutable<?>) obj;\r
-       if (!Util.isEmpty(this.inputFile) && !Util.isEmpty(exec.inputFile)) {\r
-           if (!this.inputFile.equals(exec.inputFile)) {\r
-               return false;\r
-           }\r
+\r
+       @Override\r
+       public String getOutput() {\r
+               return outputFile;\r
        }\r
-       if (!Util.isEmpty(this.outputFile) && !Util.isEmpty(exec.outputFile)) {\r
-           if (!this.outputFile.equals(exec.outputFile)) {\r
-               return false;\r
-           }\r
+\r
+       @Override\r
+       public String getError() {\r
+               return errorFile;\r
        }\r
-       if (!Util.isEmpty(this.errorFile) && !Util.isEmpty(exec.errorFile)) {\r
-           if (!this.errorFile.equals(exec.errorFile)) {\r
-               return false;\r
-           }\r
+\r
+       @Override\r
+       public String toString() {\r
+               String value = "Input: " + this.getInput() + "\n";\r
+               value += "Output: " + this.getOutput() + "\n";\r
+               value += "Error: " + this.getError() + "\n";\r
+               value += "Class: " + this.getClass() + "\n";\r
+               value += "Params: " + cbuilder + "\n";\r
+               return value;\r
        }\r
-       if (!this.cbuilder.equals(exec.cbuilder)) {\r
-           return false;\r
+\r
+       @Override\r
+       public Executable<?> loadRunConfiguration(RunConfiguration rconfig) {\r
+               if (!compbio.util.Util.isEmpty(rconfig.getOutput())) {\r
+                       setOutput(rconfig.getOutput());\r
+               }\r
+               if (!compbio.util.Util.isEmpty(rconfig.getError())) {\r
+                       setError(rconfig.getError());\r
+               }\r
+               if (!compbio.util.Util.isEmpty(rconfig.getInput())) {\r
+                       setInput(rconfig.getInput());\r
+               }\r
+               this.cbuilder = (CommandBuilder<T>) rconfig.getParameters();\r
+               return this;\r
+       }\r
+\r
+       @Override\r
+       public boolean equals(Object obj) {\r
+               if (obj == null) {\r
+                       return false;\r
+               }\r
+               if (!(obj instanceof SkeletalExecutable<?>)) {\r
+                       return false;\r
+               }\r
+               SkeletalExecutable<?> exec = (SkeletalExecutable<?>) obj;\r
+               if (!Util.isEmpty(this.inputFile) && !Util.isEmpty(exec.inputFile)) {\r
+                       if (!this.inputFile.equals(exec.inputFile)) {\r
+                               return false;\r
+                       }\r
+               }\r
+               if (!Util.isEmpty(this.outputFile) && !Util.isEmpty(exec.outputFile)) {\r
+                       if (!this.outputFile.equals(exec.outputFile)) {\r
+                               return false;\r
+                       }\r
+               }\r
+               if (!Util.isEmpty(this.errorFile) && !Util.isEmpty(exec.errorFile)) {\r
+                       if (!this.errorFile.equals(exec.errorFile)) {\r
+                               return false;\r
+                       }\r
+               }\r
+               if (!this.cbuilder.equals(exec.cbuilder)) {\r
+                       return false;\r
+               }\r
+               return true;\r
+       }\r
+\r
+       @Override\r
+       public int hashCode() {\r
+               int code = inputFile.hashCode();\r
+               code += outputFile.hashCode();\r
+               code += errorFile.hashCode();\r
+               code *= this.cbuilder.hashCode();\r
+               return code;\r
+       }\r
+\r
+       public String getClusterSettings() {\r
+               String settings = ph.getProperty(getType().getSimpleName()\r
+                               .toLowerCase() + ".cluster.settings");\r
+               return settings == null ? "" : settings;\r
        }\r
-       return true;\r
-    }\r
-\r
-    @Override\r
-    public int hashCode() {\r
-       int code = inputFile.hashCode();\r
-       code += outputFile.hashCode();\r
-       code += errorFile.hashCode();\r
-       code *= this.cbuilder.hashCode();\r
-       return code;\r
-    }\r
-\r
-    public String getClusterSettings() {\r
-       String settings = ph.getProperty(getType().getSimpleName()\r
-               .toLowerCase()\r
-               + ".cluster.settings");\r
-       return settings == null ? "" : settings;\r
-    }\r
-\r
-    /**\r
+\r
+       /**\r
         * \r
         * @return number of cpus to use on the cluster or 0 if the value is\r
         *         undefined\r
         */\r
        public static int getClusterCpuNum(Class<? extends Executable<?>> type) {\r
                int cpus = 0;\r
-               String cpuNum = ph.getProperty(type.getSimpleName().toLowerCase()+ ".cluster.cpunum");\r
+               String cpuNum = ph.getProperty(type.getSimpleName().toLowerCase()\r
+                               + ".cluster.cpunum");\r
                if (compbio.util.Util.isEmpty(cpuNum)) {\r
                        return 0;\r
                }\r
@@ -274,20 +279,55 @@ public abstract class SkeletalExecutable<T> implements Executable<T> {
                        cpus = Integer.parseInt(cpuNum);\r
                } catch (NumberFormatException e) {\r
                        // safe to ignore\r
-                       log\r
-                       .debug("Number of cpus to use for cluster execution is defined but could not be parsed as integer! Given value is: "\r
+                       log.debug("Number of cpus to use for cluster execution is defined but could not be parsed as integer! Given value is: "\r
                                        + cpuNum);\r
                        return 0;\r
                }\r
                if (cpus < 1 || cpus > 100) {\r
                        throw new InvalidParameterException(\r
                                        "Number of cpu for cluster execution must be within 1 and 100! "\r
-                                       + "Look at the value of 'tcoffee.cluster.cpunum' property. Given value is "\r
-                                       + cpus);\r
+                                                       + "Look at the value of 'tcoffee.cluster.cpunum' property. Given value is "\r
+                                                       + cpus);\r
                }\r
                return cpus;\r
        }\r
 \r
-    public abstract Class<? extends Executable<?>> getType();\r
+       @Override\r
+       public Limit<T> getLimit(String presetName) {\r
+\r
+               if (limits == null) {\r
+                       limits = getLimits();\r
+               }\r
+\r
+               Limit<T> limit = null;\r
+               if (limits != null) {\r
+                       // this returns default limit if preset is undefined!\r
+                       limit = limits.getLimitByName(presetName);\r
+               }\r
+               // If limit is not defined for a particular preset, then return default\r
+               // limit\r
+               if (limit == null) {\r
+                       log.debug("Limit for the preset " + presetName\r
+                                       + " is not found. Using default");\r
+                       limit = limits.getDefaultLimit();\r
+               }\r
+               return limit;\r
+       }\r
+\r
+       @Override\r
+       public LimitsManager<T> getLimits() {\r
+               synchronized (SkeletalExecutable.class) {\r
+                       if (limits == null) {\r
+                               limits = compbio.runner.Util.getLimits(this.getType());\r
+                       }\r
+               }\r
+               return limits;\r
+       }\r
+\r
+       /**\r
+        * \r
+        * @return subclasses must return their type\r
+        */\r
+       public abstract Class<Executable<T>> getType();\r
 \r
 }\r