--- /dev/null
+package jalview.ws2.actions.alignment;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import jalview.analysis.AlignSeq;
+import jalview.analysis.SeqsetUtils;
+import jalview.analysis.SeqsetUtils.SequenceInfo;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.util.Comparison;
+import jalview.ws2.actions.BaseJob;
+import jalview.ws2.api.WebServiceJobHandle;
+
+/**
+ * A wrapper class that extends basic job container with data specific to
+ * alignment services. It stores input and empty sequences (with uniquified
+ * names) along the original sequence information. {@link AlignmentJob} objects
+ * are created by {@link AlignmentTask} during a preparation stage.
+ *
+ * @author mmwarowny
+ *
+ */
+class AlignmentJob extends BaseJob
+{
+ private final List<SequenceI> emptySeqs;
+
+ private final Map<String, SequenceInfo> names;
+
+ private AlignmentI alignmentResult;
+
+ AlignmentJob(List<SequenceI> inputSeqs, List<SequenceI> emptySeqs,
+ Map<String, SequenceInfo> names)
+ {
+ super(Collections.unmodifiableList(inputSeqs));
+ this.emptySeqs = Collections.unmodifiableList(emptySeqs);
+ this.names = Collections.unmodifiableMap(names);
+ }
+
+ public static AlignmentJob create(SequenceI[] seqs, int minlen, boolean keepGaps)
+ {
+ int nseqs = 0;
+ for (int i = 0; i < seqs.length; i++)
+ {
+ if (seqs[i].getEnd() - seqs[i].getStart() >= minlen)
+ nseqs++;
+ }
+ boolean valid = nseqs > 1; // need at least two sequences
+ Map<String, SequenceInfo> names = new LinkedHashMap<>();
+ List<SequenceI> inputSeqs = new ArrayList<>();
+ List<SequenceI> emptySeqs = new ArrayList<>();
+ for (int i = 0; i < seqs.length; i++)
+ {
+ SequenceI seq = seqs[i];
+ String newName = SeqsetUtils.unique_name(i);
+ names.put(newName, SeqsetUtils.SeqCharacterHash(seq));
+ if (valid && seq.getEnd() - seq.getStart() >= minlen)
+ {
+ // make new input sequence
+ String seqString = seq.getSequenceAsString();
+ if (!keepGaps)
+ seqString = AlignSeq.extractGaps(Comparison.GapChars, seqString);
+ inputSeqs.add(new Sequence(newName, seqString));
+ }
+ else
+ {
+ String seqString = "";
+ if (seq.getEnd() >= seq.getStart()) // true if gaps only
+ {
+ seqString = seq.getSequenceAsString();
+ if (!keepGaps)
+ seqString = AlignSeq.extractGaps(Comparison.GapChars, seqString);
+ }
+ emptySeqs.add(new Sequence(newName, seqString));
+ }
+ }
+ return new AlignmentJob(inputSeqs, emptySeqs, names);
+ }
+
+ @Override
+ public boolean isInputValid()
+ {
+ return inputSeqs.size() >= 2;
+ }
+
+ List<SequenceI> getEmptySequences()
+ {
+ return emptySeqs;
+ }
+
+ Map<String, SequenceInfo> getNames()
+ {
+ return names;
+ }
+
+ boolean hasResult()
+ {
+ return alignmentResult != null;
+ }
+
+ AlignmentI getAlignmentResult()
+ {
+ return alignmentResult;
+ }
+
+ void setAlignmentResult(AlignmentI alignment)
+ {
+ this.alignmentResult = alignment;
+ }
+}