JAL-3954 Make database parameter optional using default value if not provided.
[jalview.git] / src / jalview / hmmer / rest / PhmmerRequestBuilder.java
1 package jalview.hmmer.rest;
2
3 import static java.lang.String.format;
4 import static java.util.Objects.requireNonNullElse;
5
6 import java.io.File;
7 import java.io.FileReader;
8 import java.io.IOException;
9 import java.io.Reader;
10 import java.util.Collections;
11 import java.util.List;
12 import java.util.Objects;
13
14 public class PhmmerRequestBuilder {
15   // Default values
16   private float defaultIncE = 0.01f;
17   private float defaultIncdomE = 0.03f;
18   private float defaultE = 1.0f;
19   private float defaultDomE = 1.0f;
20
21   private float defaultIncT = 25.0f;
22   private float defaultIncdomT = 22.0f;
23   private float defaultT = 7.0f;
24   private float defaultDomT = 5.0f;
25
26   private float defaultPopen = 0.02f;
27   private float defaultPextend = 0.4f;
28   private String defaultMx = "BLOSUM62";
29   private float defaultEvalue = 0.01f;
30
31   private boolean defaultNoBias = false;
32   private boolean defaultCompressedOut = false;
33   private boolean defaultAlignView = true;
34   private String defaultDatabase = "uniprotkb";
35   private int defaultNhits = 100;
36
37   // Current values
38   private Float incE = null;
39   private Float incdomE = null;
40   private Float E = null;
41   private Float domE = null;
42
43   private Float incT = null;
44   private Float incdomT = null;
45   private Float T = null;
46   private Float domT = null;
47
48   private Float popen = null;
49   private Float pextend = null;
50   private String mx = null;
51   private Float evalue = null;
52
53   private Boolean noBias = null;
54   private Boolean compressedOut = null;
55   private Boolean alignView = null;
56   private String database = null;
57   private InputSequence sequence = null;
58   private Integer nhits = null;
59
60   private final List<String> allowedMx;
61   private final List<String> allowedDatabase;
62
63   PhmmerRequestBuilder(List<String> allowedMx,
64       List<String> allowedDatabase) {
65     this.allowedMx = Collections.unmodifiableList(allowedMx);
66     this.allowedDatabase = Collections.unmodifiableList(allowedDatabase);
67   }
68
69   public List<String> getAllowedMxValues() { return allowedMx; }
70   public List<String> getAllowedDatabaseValues() { return allowedDatabase; }
71
72   private static class FileInputSequence implements InputSequence {
73     private final File file;
74
75     private FileInputSequence(File file) {
76       this.file = file;
77     }
78
79     @Override
80     public String getAsString() throws IOException {
81       Reader reader = new FileReader(file);
82       StringBuilder builder = new StringBuilder();
83       try (reader) {
84         char[] buffer = new char[1024 * 16];
85         int bytesRead;
86         while ((bytesRead = reader.read(buffer)) >= 0) {
87           builder.append(buffer, 0, bytesRead);
88         }
89       }
90       return builder.toString();
91     }
92   }
93
94   private static class StringInputSequence implements InputSequence {
95     private final String str;
96
97     private StringInputSequence(String str) {
98       this.str = str;
99     }
100
101     @Override
102     public String getAsString() throws IOException { return str; }
103   }
104
105   public float getDefaultIncE() { return defaultIncE; }
106
107   public float getDefaultIncdomE() { return defaultIncdomE; }
108
109   public float getDefaultE() { return defaultE; }
110
111   public float getDefaultDomE() { return defaultDomE; }
112
113   public float getDefaultIncT() { return defaultIncT; }
114
115   public float getDefaultIncdomT() { return defaultIncdomT; }
116
117   public float getDefaultT() { return defaultT; }
118
119   public float getDefaultDomT() { return defaultDomT; }
120
121   public float getDefaultPopen() { return defaultPopen; }
122
123   public float getDefaultPextend() { return defaultPextend; }
124
125   public String getDefaultMx() { return defaultMx; }
126
127   public float getDefaultEvalue() { return defaultEvalue; }
128
129   public boolean getDefaultNoBias() { return defaultNoBias; }
130
131   public boolean getDefaultCompressedOut() { return defaultCompressedOut; }
132
133   public boolean getDefaultAlignView() { return defaultAlignView; }
134
135   public String getDefaultDatabase() { return defaultDatabase; }
136
137   public int getDefaultNhits() { return defaultNhits; }
138
139   public PhmmerRequestBuilder incE(Float incE) {
140     if (incE != null && (incE <= 0 || incE > 10))
141       throw new IllegalArgumentException(format("incE must be greater than 0 "
142           + "and less or equal to 10, value: %f", incE));
143     this.incE = incE;
144     return this;
145   }
146
147   public PhmmerRequestBuilder incdomE(Float incdomE) {
148     if (incdomE != null && (incdomE <= 0 || incdomE > 10))
149       throw new IllegalArgumentException(format("incdomE must be greater than 0 "
150           + "and less or equal to 10, value: %f", incdomE));
151     this.incdomE = incdomE;
152     return this;
153   }
154
155   public PhmmerRequestBuilder E(Float E) {
156     if (E != null && (E <= 0 || E > 10))
157       throw new IllegalArgumentException(format("E must be greater than 0 "
158           + "and less or equal to 10, value: %f", E));
159     this.E = E;
160     return this;
161   }
162
163   public PhmmerRequestBuilder domE(Float domE) {
164     if (domE != null && (domE <= 0 || domE > 10))
165       throw new IllegalArgumentException(format("domE must be greater than 0 "
166           + "and less or equal to 10, value: %f", domE));
167     this.domE = domE;
168     return this;
169   }
170
171   public PhmmerRequestBuilder incT(Float incT) {
172     if (incT != null && incT <= 0)
173       throw new IllegalArgumentException(format("incT must be greater than 0, "
174           + "value: %f", incT));
175     this.incT = incT;
176     return this;
177   }
178
179   public PhmmerRequestBuilder incdomT(Float incdomT) {
180     if (incdomT != null && incdomT <= 0)
181       throw new IllegalArgumentException(format("incdomT must be greater than 0, "
182           + "value: %f", incdomT));
183     this.incdomT = incdomT;
184     return this;
185   }
186
187   public PhmmerRequestBuilder T(Float T) {
188     if (T != null && T <= 0 )
189       throw new IllegalArgumentException(format("T must be greater than 0, "
190           + "value: %f", T));
191     this.T = T;
192     return this;
193   }
194
195   public PhmmerRequestBuilder domT(Float domT) {
196     if (domT != null && domT <= 0)
197       throw new IllegalArgumentException(format("domT must be greater than 0, "
198           + "value: %f", domT));
199     this.domT = domT;
200     return this;
201   }
202
203   public PhmmerRequestBuilder popen(Float popen) {
204     if (popen != null && (popen < 0 || popen >= 0.5f))
205       throw new IllegalArgumentException(format("popen must be greater or "
206           + "equal to 0 and less than 0.5, value: %s", popen));
207     this.popen = popen;
208     return this;
209   }
210
211   public PhmmerRequestBuilder pextend(Float pextend) {
212     if (pextend != null && (pextend < 0 || pextend >= 1))
213       throw new IllegalArgumentException(format("pextend must be greater or "
214           + "equal to 0 and less than 1, value: %f", pextend));
215     this.pextend = pextend;
216     return this;
217   }
218
219   public PhmmerRequestBuilder mx(String mx) {
220     if (mx != null && !allowedMx.contains(mx))
221       throw new IllegalArgumentException(String.format(
222           "\"%s\" is not one of the allowed values %s",
223           mx, allowedMx.toString()));
224     this.mx = mx;
225     return this;
226   }
227
228   public PhmmerRequestBuilder noBias(Boolean noBias) {
229     this.noBias = noBias;
230     return this;
231   }
232
233   public PhmmerRequestBuilder compressedOut(Boolean compressedOut) {
234     this.compressedOut = compressedOut;
235     return this;
236   };
237
238   public PhmmerRequestBuilder alignView(Boolean alignView) {
239     this.alignView = alignView;
240     return this;
241   }
242
243   public PhmmerRequestBuilder database(String database) {
244     Objects.requireNonNull(database);
245     if (!allowedDatabase.contains(database))
246       throw new IllegalArgumentException(String.format(
247           "\"%s\" is not one of the allowed values: %s",
248           database, allowedDatabase.toString()));
249     this.database = database;
250     return this;
251   }
252
253   public PhmmerRequestBuilder evalue(Float evalue) {
254     this.evalue = evalue;
255     return this;
256   }
257
258   public PhmmerRequestBuilder sequenceString(String sequence) {
259     Objects.requireNonNull(sequence);
260     this.sequence = new StringInputSequence(sequence);
261     return this;
262   }
263
264   public PhmmerRequestBuilder sequenceFile(String path) {
265     Objects.requireNonNull(path);
266     this.sequence = new FileInputSequence(new File(path));
267     return this;
268   }
269
270   public PhmmerRequestBuilder sequenceFile(File file) {
271     Objects.requireNonNull(file);
272     this.sequence = new FileInputSequence(file);
273     return this;
274   }
275
276   public PhmmerRequestBuilder nhits(Integer nhits) {
277     this.nhits = nhits;
278     return this;
279   }
280
281   public PhmmerRequest build() {
282     if (sequence == null)
283       throw new IllegalStateException("sequence not set");
284     boolean usingEValues = incE != null || incdomE != null || E != null || domE != null;
285     boolean usingBitScores = incT != null || incdomT != null || T != null || domT != null;
286     if (usingEValues && usingBitScores)
287       throw new IllegalStateException("using both E-values and bit scores is not allowed");
288     return new PhmmerRequest(
289         valueOrDefaultIfEnabled(incE, defaultIncE, usingEValues),
290         valueOrDefaultIfEnabled(incdomE, defaultIncdomE, usingEValues),
291         valueOrDefaultIfEnabled(E, defaultE, usingEValues),
292         valueOrDefaultIfEnabled(domE, defaultDomE, usingEValues),
293         valueOrDefaultIfEnabled(incT, defaultIncT, usingBitScores),
294         valueOrDefaultIfEnabled(incdomT, defaultIncdomT, usingBitScores),
295         valueOrDefaultIfEnabled(T, defaultT, usingBitScores),
296         valueOrDefaultIfEnabled(domT, defaultDomT, usingBitScores),
297         requireNonNullElse(popen, defaultPopen),
298         requireNonNullElse(pextend, defaultPextend),
299         requireNonNullElse(mx, defaultMx),
300         requireNonNullElse(noBias, defaultNoBias),
301         requireNonNullElse(compressedOut, defaultCompressedOut),
302         requireNonNullElse(alignView, defaultAlignView),
303         requireNonNullElse(database, defaultDatabase),
304         requireNonNullElse(evalue, defaultEvalue),
305         sequence,
306         requireNonNullElse(nhits, defaultNhits));
307   }
308
309   private static <T> T valueOrDefaultIfEnabled(T obj, T defaultObj, boolean enable) {
310     return enable ? ((obj != null) ? obj : defaultObj) : null;
311   }
312 }