0
|
1 package edu.unc.genomics;
|
|
2
|
|
3 import java.io.StringWriter;
|
|
4 import java.util.ArrayList;
|
|
5 import java.util.HashMap;
|
|
6 import java.util.Iterator;
|
|
7 import java.util.List;
|
|
8 import java.util.Map;
|
|
9
|
|
10 import org.apache.log4j.Logger;
|
|
11 import org.apache.log4j.PatternLayout;
|
|
12 import org.apache.log4j.WriterAppender;
|
|
13
|
|
14 import com.beust.jcommander.JCommander;
|
|
15 import com.beust.jcommander.ParameterDescription;
|
|
16
|
|
17 /**
|
|
18 * A Job represents an instance of a tool configured with specific arguments
|
|
19 * Attempting to run a Job with invalid arguments will throw a RuntimeException
|
|
20 * If tool execution fails, a RuntimeException will also be thrown
|
|
21 * UncheckedExceptions should be managed by setting the Job's UncheckedExceptionManager
|
|
22 * or providing a ThreadGroup / default UncheckedExceptionManager
|
|
23 *
|
|
24 * @author timpalpant
|
|
25 *
|
|
26 */
|
|
27 public class Job implements Iterable<ParameterDescription>, Runnable {
|
|
28
|
|
29 private static final Logger log = Logger.getLogger(Job.class);
|
|
30
|
|
31 private final Class<? extends CommandLineTool> tool;
|
|
32 private final CommandLineTool app;
|
|
33 private final List<ParameterDescription> parameters;
|
|
34 private final String usageText;
|
|
35 private boolean isRunning = false;
|
|
36 private StringWriter writer = new StringWriter();
|
|
37
|
|
38 /**
|
|
39 * Arguments for running this Job
|
|
40 */
|
|
41 private Map<ParameterDescription,String> args = new HashMap<>();
|
|
42
|
|
43 /**
|
|
44 * Creates a new Job model for the specified tool
|
|
45 * @param tool
|
|
46 * @throws IllegalAccessException
|
|
47 * @throws InstantiationException
|
|
48 */
|
|
49 public Job(final Class<? extends CommandLineTool> tool) throws InstantiationException, IllegalAccessException {
|
|
50 this.tool = tool;
|
|
51
|
|
52 // Attempt to instantiate the tool and extract parameter information
|
|
53 app = tool.newInstance();
|
|
54 JCommander jc = new JCommander(app);
|
|
55 jc.setProgramName(tool.getSimpleName());
|
|
56 parameters = jc.getParameters();
|
|
57 StringBuilder sbuilder = new StringBuilder();
|
|
58 jc.usage(sbuilder);
|
|
59 usageText = sbuilder.toString();
|
|
60
|
|
61 // Set default arguments
|
|
62 for (ParameterDescription param : parameters) {
|
|
63 if (param.getDefault() != null) {
|
|
64 setArgument(param, String.valueOf(param.getDefault()));
|
|
65 }
|
|
66 }
|
|
67 }
|
|
68
|
|
69 /**
|
|
70 * Copy-constructor
|
|
71 * @param job
|
|
72 */
|
|
73 public Job(final Job job) {
|
|
74 this.tool = job.tool;
|
|
75 this.app = job.app;
|
|
76 this.parameters = job.parameters;
|
|
77 this.args = job.args;
|
|
78 this.usageText = job.usageText;
|
|
79 }
|
|
80
|
|
81 @Override
|
|
82 public void run() {
|
|
83 // Load the arguments for running the tool
|
|
84 String[] args;
|
|
85 try {
|
|
86 args = getArguments();
|
|
87 } catch (JobException e) {
|
|
88 // TODO Auto-generated catch block
|
|
89 e.printStackTrace();
|
|
90 throw new CommandLineToolException("Job arguments are not valid");
|
|
91 }
|
|
92
|
|
93 // Attempt to instantiate and run the tool
|
|
94 WriterAppender appender = new WriterAppender(new PatternLayout(), writer);
|
|
95 appender.addFilter(new ThreadFilter(Thread.currentThread().getName()));
|
|
96 Logger.getRootLogger().addAppender(appender);
|
|
97 isRunning = true;
|
|
98 app.toolRunnerMain(args);
|
|
99 isRunning = false;
|
|
100 Logger.getRootLogger().removeAppender(appender);
|
|
101 }
|
|
102
|
|
103 /**
|
|
104 * Render the arguments for running an instance of this Job
|
|
105 * @return
|
|
106 * @throws JobException
|
|
107 */
|
|
108 public String[] getArguments() throws JobException {
|
|
109 if (!validateArguments()) {
|
|
110 throw new JobException("Job Arguments are not valid");
|
|
111 }
|
|
112
|
|
113 List<String> cmdArgs = new ArrayList<>();
|
|
114 for (ParameterDescription p : args.keySet()) {
|
|
115 cmdArgs.add(p.getLongestName());
|
|
116 cmdArgs.add(args.get(p));
|
|
117 }
|
|
118
|
|
119 String[] ret = new String[cmdArgs.size()];
|
|
120 return cmdArgs.toArray(ret);
|
|
121 }
|
|
122
|
|
123 public String getArgument(final ParameterDescription p) {
|
|
124 return args.get(p);
|
|
125 }
|
|
126
|
|
127 /**
|
|
128 * Set a value for the given parameter
|
|
129 * @param p
|
|
130 * @param value
|
|
131 */
|
|
132 public void setArgument(final ParameterDescription p, final String value) {
|
|
133 if (value.length() == 0) {
|
|
134 args.remove(p);
|
|
135 } else {
|
|
136 args.put(p, value);
|
|
137 }
|
|
138 }
|
|
139
|
|
140 /**
|
|
141 * Remove all set arguments for this Job
|
|
142 */
|
|
143 public void resetArguments() {
|
|
144 args.clear();
|
|
145 }
|
|
146
|
|
147 /**
|
|
148 * Is this parameter set?
|
|
149 * @param p
|
|
150 * @return
|
|
151 */
|
|
152 public boolean isSet(final ParameterDescription p) {
|
|
153 return args.containsKey(p);
|
|
154 }
|
|
155
|
|
156 /**
|
|
157 * Validate that this job has all of its parameters set
|
|
158 * and that they are all valid
|
|
159 * @return
|
|
160 */
|
|
161 public boolean validateArguments() {
|
|
162 // TODO: Better validation based on parameter type
|
|
163 boolean hasAllRequiredParams = true;
|
|
164 for (ParameterDescription param : parameters) {
|
|
165 if (param.getParameter().required() && !isSet(param)) {
|
|
166 log.debug("Job is missing required argument: " + param.getLongestName());
|
|
167 hasAllRequiredParams = false;
|
|
168 }
|
|
169 }
|
|
170
|
|
171 return hasAllRequiredParams;
|
|
172 }
|
|
173
|
|
174 public int numParameters() {
|
|
175 return parameters.size();
|
|
176 }
|
|
177
|
|
178 @Override
|
|
179 public Iterator<ParameterDescription> iterator() {
|
|
180 return parameters.iterator();
|
|
181 }
|
|
182
|
|
183 public String getName() {
|
|
184 return tool.getSimpleName();
|
|
185 }
|
|
186
|
|
187 public boolean isRunning() {
|
|
188 return isRunning;
|
|
189 }
|
|
190
|
|
191 /**
|
|
192 * @return the usageText
|
|
193 */
|
|
194 public String getUsageText() {
|
|
195 return usageText;
|
|
196 }
|
|
197
|
|
198 @Override
|
|
199 public String toString() {
|
|
200 return getName();
|
|
201 }
|
|
202
|
|
203 public String getOutput() {
|
|
204 return writer.toString();
|
|
205 }
|
|
206
|
|
207 }
|