+ trees.add(new ArrayList<NewickFile>());
+ }
+ }
+ }
+ }
+ }
+ // Now aggregate and present results from this frame of alignment data.
+ int nvertsep = 0, nvertseps = 1;
+ if (vsepjobs)
+ {
+ // Jobs relate to different rows of input alignment.
+ // Jobs are subdivided by rows before columns,
+ // so there will now be a number of subjobs according tohsep for each
+ // vertsep
+ // TODO: get vertical separation intervals for each job and set
+ // nvertseps
+ // TODO: merge data from each group/sequence onto whole
+ // alignment
+ }
+ /**
+ * index into rest jobs subdivided vertically
+ */
+ int vrestjob = 0;
+ // Destination alignments for all result data.
+ ArrayList<SequenceGroup> visgrps = new ArrayList<SequenceGroup>();
+ Hashtable<String, SequenceGroup> groupNames = new Hashtable<String, SequenceGroup>();
+ ArrayList<AlignmentAnnotation> visAlAn = null;
+ for (nvertsep = 0; nvertsep < nvertseps; nvertsep++)
+ {
+ // TODO: set scope w.r.t. original alignment view for vertical
+ // separation.
+ {
+ // results for a job exclude hidden columns of input data, so map
+ // back on to all visible regions
+ /**
+ * rest job result we are working with
+ */
+ int nrj = vrestjob;
+
+ RestJob rj = (RestJob) jobs[nrj];
+ int contigs[] = input.getVisibleContigs();
+ AlignmentI destAl = null;
+ jalview.datamodel.HiddenColumns destHCs = null;
+ // Resolve destAl for this data.
+ if (als == 0 && rj.isInputContextModified())
+ {
+ // special case: transfer features, annotation, groups, etc,
+ // from input
+ // context to align panel derived from input data
+ if (destAls.size() > als)
+ {
+ destAl = destAls.get(als);
+ }
+ else
+ {
+ if (!restClient.isAlignmentModified() && merge)
+ {
+ destAl = restClient.av.getAlignment();
+ destHCs = restClient.av.getAlignment().getHiddenColumns();
+ resultDest
+ .add(restClient.isShowResultsInNewView() ? AddDataTo.newView
+ : AddDataTo.currentView);
+ destPanels.add(restClient.recoverAlignPanelForView());
+ }
+ else
+ {
+ newAlignment = true;
+ // recreate the input alignment data
+ Object[] idat = input
+ .getAlignmentAndHiddenColumns(gapCharacter);
+ destAl = new Alignment((SequenceI[]) idat[0]);
+ destHCs = (HiddenColumns) idat[1];
+ resultDest.add(AddDataTo.newAlignment);
+ // but do not add to the alignment panel list - since we need to
+ // create a whole new alignFrame set.
+ }
+ destAls.add(destAl);
+ destColsel.add(destHCs);
+ }
+ }
+ else
+ {
+ // alignment(s) returned by service is to be re-integrated and
+ // displayed
+ if (destAls.size() > als)
+ {
+ if (!vsepjobs)
+ {
+ // TODO: decide if multiple multiple alignments returned by
+ // non-vseparable services are allowed.
+ Cache.log
+ .warn("dealing with multiple alignment products returned by non-vertically separable service.");
+ }
+ // recover reference to last alignment created for this rest frame
+ // ready for extension
+ destAl = destAls.get(als);
+ destHCs = destColsel.get(als);
+ }
+ else
+ {
+ Object[] newview;
+
+ if (!hsepjobs)
+ {
+ // single alignment for any job that gets mapped back on to
+ // input data. Reconstruct by interleaving parts of returned
+ // alignment with hidden parts of input data.
+ SequenceI[][] nsq = splitSeqsOnVisibleContigs(rseqs[nrj],
+ contigs, gapCharacter);
+ AlignmentOrder alo[] = new AlignmentOrder[nsq.length];
+ for (int no = 0; no < alo.length; no++)
+ {
+ alo[no] = new AlignmentOrder(orders[nrj].getOrder());
+ }
+ newview = input.getUpdatedView(nsq, orders, gapCharacter);
+ }
+ else
+ {
+ // each job maps to a single visible contig, and all need to be
+ // stitched back together.
+ // reconstruct using sub-region based MSA alignment construction
+ // mechanism
+ newview = input.getUpdatedView(rseqs, orders, gapCharacter);
+ }
+ destAl = new Alignment((SequenceI[]) newview[0]);
+ destHCs = (HiddenColumns) newview[1];
+ newAlignment = true;
+ // TODO create alignment from result data with propagated
+ // references.
+ destAls.add(destAl);
+ destColsel.add(destHCs);
+ resultDest.add(AddDataTo.newAlignment);
+ throw new Error(
+ MessageManager
+ .getString("error.implementation_error")
+ + "TODO: ");
+ }
+ }
+ /**
+ * save initial job in this set in case alignment is h-separable
+ */
+ int initnrj = nrj;
+ // Now add in groups
+ for (int ncnt = 0; ncnt < contigs.length; ncnt += 2)
+ {
+ if (!hsepjobs)
+ {
+ // single alignment for any job that gets mapped back on to input
+ // data.
+ }
+ else
+ {
+ // each job maps to a single visible contig, and all need to be
+ // stitched back together.
+ if (ncnt > 0)
+ {
+ nrj++;
+ }
+ // TODO: apply options for group merging and annotation merging.
+ // If merging not supported, then either clear hashtables now or
+ // use them to rename the new annotation/groups for each contig if
+ // a conflict occurs.
+ }
+ if (sgrp[nrj] != null)
+ {
+ for (SequenceGroup sg : sgrp[nrj])
+ {
+ boolean recovered = false;
+ SequenceGroup exsg = null;
+ if (sg.getName() != null)
+ {
+ exsg = groupNames.get(sg.getName());
+ }
+ if (exsg == null)
+ {
+ exsg = new SequenceGroup(sg);
+ groupNames.put(exsg.getName(), exsg);
+ visgrps.add(exsg);
+ exsg.setStartRes(sg.getStartRes() + contigs[ncnt]);
+ exsg.setEndRes(sg.getEndRes() + contigs[ncnt]);
+ }
+ else
+ {
+ recovered = true;
+ }
+ // now replace any references from the result set with
+ // corresponding refs from alignment input set.
+
+ // TODO: cope with recovering hidden sequences from
+ // resultContext
+ {
+ for (SequenceI oseq : sg.getSequences(null))
+ {
+ SequenceI nseq = getNewSeq(oseq, rseqs[nrj],
+ ordermap[nrj], destAl);
+ if (nseq != null)
+ {
+ if (!recovered)
+ {
+ exsg.deleteSequence(oseq, false);
+ }
+ exsg.addSequence(nseq, false);
+ }
+ else
+ {
+ Cache.log
+ .warn("Couldn't resolve original sequence for new sequence.");
+ }
+ }
+ if (sg.hasSeqrep())
+ {
+ if (exsg.getSeqrep() == sg.getSeqrep())
+ {
+ // lift over sequence rep reference too
+ SequenceI oseq = sg.getSeqrep();
+ SequenceI nseq = getNewSeq(oseq, rseqs[nrj],
+ ordermap[nrj], destAl);
+ if (nseq != null)
+ {
+ exsg.setSeqrep(nseq);
+ }
+ }
+ }
+ }
+ if (recovered)