package jalview.ws; import java.util.*; import javax.swing.*; import jalview.analysis.*; import jalview.bin.*; import jalview.datamodel.*; import jalview.datamodel.Alignment; import jalview.gui.*; import vamsas.objects.simple.MsaResult; /** *

* Title: *

* *

* Description: *

* *

* Copyright: Copyright (c) 2004 *

* *

* Company: Dundee University *

* * @author not attributable * @version 1.0 */ class MsaWSThread extends Thread implements WSClientI { jalview.gui.AlignFrame alignFrame; WebserviceInfo wsInfo = null; String WebServiceName = null; String OutputHeader; AlignmentView input; boolean submitGaps = false; // pass sequences including gaps to alignment // service boolean preserveOrder = true; // and always store and recover sequence // order class MsaWSJob { int jobnum = 0; // WebServiceInfo pane for this job String jobId; // ws job ticket vamsas.objects.simple.MsaResult result = null; vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple. SequenceSet(); /** * MsaWSJob * * @param jobNum * int * @param jobId * String */ public MsaWSJob(int jobNum, SequenceI[] inSeqs) { this.jobnum = jobNum; if (!prepareInput(inSeqs, 2)) { submitted = true; subjobComplete = true; result = new MsaResult(); result.setFinished(true); result.setStatus("Job never ran - input returned to user."); } } int allowedServerExceptions = 3; // thread dies if too many // exceptions. boolean submitted = false; boolean subjobComplete = false; Hashtable SeqNames = new Hashtable(); Vector emptySeqs = new Vector(); /** * prepare input sequences for MsaWS service * @param seqs jalview sequences to be prepared * @param minlen minimum number of residues required for this MsaWS service * @return true if seqs contains sequences to be submitted to service. */ private boolean prepareInput(SequenceI[] seqs, int minlen) { int nseqs = 0; if (minlen < 0) { throw new Error("Implementation error: minlen must be zero or more."); } for (int i = 0; i < seqs.length; i++) { if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1) { nseqs++; } } boolean valid = nseqs > 1; // need at least two seqs vamsas.objects.simple.Sequence[] seqarray = (valid) ? new vamsas.objects.simple.Sequence[nseqs] : null; for (int i = 0, n = 0; i < seqs.length; i++) { String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same // for // any // subjob SeqNames.put(newname, jalview.analysis.SeqsetUtils .SeqCharacterHash(seqs[i])); if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1) { seqarray[n] = new vamsas.objects.simple.Sequence(); seqarray[n].setId(newname); seqarray[n++].setSeq( (submitGaps) ? seqs[i].getSequence() : AlignSeq.extractGaps( jalview.util.Comparison.GapChars, seqs[i] .getSequence())); } else { String empty = null; if (seqs[i].getEnd() >= seqs[i].getStart()) { empty = (submitGaps) ? seqs[i].getSequence() : AlignSeq.extractGaps( jalview.util.Comparison.GapChars, seqs[i] .getSequence()); } emptySeqs.add(new String[] {newname, empty}); } } this.seqs = new vamsas.objects.simple.SequenceSet(); this.seqs.setSeqs(seqarray); return valid; } /** * * @return true if getAlignment will return a valid alignment result. */ public boolean hasResults() { if (subjobComplete && result != null && result.isFinished() && result.getMsa() != null && result.getMsa().getSeqs() != null) { return true; } return false; } public Object[] getAlignment() { if (result != null && result.isFinished()) { SequenceI[] alseqs = null; char alseq_gapchar = '-'; int alseq_l = 0; if (result.getMsa() != null) { alseqs = getVamsasAlignment(result.getMsa()); alseq_gapchar = result.getMsa().getGapchar().charAt(0); alseq_l = alseqs.length; } if (emptySeqs.size() > 0) { SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()]; // get width int i, w = 0; if (alseq_l > 0) { for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++) { if (w < alseqs[i].getLength()) { w = alseqs[i].getLength(); } t_alseqs[i] = alseqs[i]; alseqs[i] = null; } } // check that aligned width is at least as wide as emptySeqs width. int ow = w, nw = w; for (i = 0, w = emptySeqs.size(); i < w; i++) { String[] es = (String[]) emptySeqs.get(i); if (es != null && es[1] != null) { int sw = es[1].length(); if (nw < sw) { nw = sw; } } } // make a gapped string. StringBuffer insbuff = new StringBuffer(w); for (i = 0; i < nw; i++) { insbuff.append(alseq_gapchar); } if (ow < nw) { for (i = 0; i < alseq_l; i++) { int sw = t_alseqs[i].getLength(); if (nw > sw) { // pad at end alseqs[i].setSequence(t_alseqs[i].getSequence() + insbuff.substring(0, sw - nw)); } } } for (i = 0, w = emptySeqs.size(); i < w; i++) { String[] es = (String[]) emptySeqs.get(i); if (es[1] == null) { t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0], insbuff.toString(), 1, 0); } else { if (es[1].length() < nw) { t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0], es[1] + insbuff.substring(0, nw - es[1].length()), 1, 1 + es[1].length()); } else { t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0], es[1]); } } } alseqs = t_alseqs; } AlignmentOrder msaorder = new AlignmentOrder(alseqs); // always recover the order - makes parseResult()'s life easier. jalview.analysis.AlignmentSorter.recoverOrder(alseqs); // account for any missing sequences jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs); return new Object[] { alseqs, msaorder}; } return null; } boolean cancelled = false; /** * mark subjob as cancelled and set result object appropriatly */ void cancel() { cancelled=true; subjobComplete = true; result = null; } } MsaWSJob jobs[] = null; String alTitle; // name which will be used to form new alignment window. boolean jobComplete = false; Alignment dataset; // dataset to which the new alignment will be // associated. ext.vamsas.MuscleWS server = null; String WsUrl = null; /** * set basic options for this (group) of Msa jobs * * @param subgaps * boolean * @param presorder * boolean */ MsaWSThread(ext.vamsas.MuscleWS server, String wsUrl, WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame, AlignmentView alview, String wsname, boolean subgaps, boolean presorder) { this.server = server; this.WsUrl = wsUrl; this.wsInfo = wsinfo; this.WebServiceName = wsname; this.input = alview; this.submitGaps = subgaps; this.preserveOrder = presorder; this.alignFrame = alFrame; } /** * create one or more Msa jobs to align visible seuqences in _msa * * @param title * String * @param _msa * AlignmentView * @param subgaps * boolean * @param presorder * boolean * @param seqset * Alignment */ MsaWSThread(ext.vamsas.MuscleWS server, String wsUrl, WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame, String wsname, String title, AlignmentView _msa, boolean subgaps, boolean presorder, Alignment seqset) { this(server, wsUrl, wsinfo, alFrame, _msa, wsname, subgaps, presorder); OutputHeader = wsInfo.getProgressText(); alTitle = title; dataset = seqset; SeqCigar[] msa = _msa.getSequences(); int[] contigs = _msa.getContigs(); int njobs = 1; if (contigs != null && contigs.length > 0) { int start = 0; njobs = 0; int width = _msa.getWidth(); for (int contig = 0; contig < contigs.length; contig += 3) { if ( (contigs[contig + 1] - start) > 0) { njobs++; } width += contigs[contig + 2]; // end up with full region width (including hidden regions) start = contigs[contig + 1] + contigs[contig + 2]; } if (start < width) { njobs++; } jobs = new MsaWSJob[njobs]; start = 0; int j = 0; for (int contig = 0; contig < contigs.length; contig += 3) { if (contigs[contig + 1] - start > 0) { SequenceI mseq[] = new SequenceI[msa.length]; for (int s = 0; s < mseq.length; s++) { mseq[s] = msa[s].getSeq('-').getSubSequence(start, contigs[contig + 1]); } if (j != 0) { jobs[j] = new MsaWSJob(wsinfo.addJobPane(), mseq); } else { jobs[j] = new MsaWSJob(0, mseq); } wsinfo.setProgressName("region " + jobs[j].jobnum, jobs[j].jobnum); wsinfo.setProgressText(jobs[j].jobnum, OutputHeader); j++; } start = contigs[contig + 1] + contigs[contig + 2]; } if (start < width) { SequenceI mseq[] = new SequenceI[msa.length]; for (int s = 0; s < mseq.length; s++) { mseq[s] = msa[s].getSeq('-').getSubSequence(start, width + 1); } if (j != 0) { jobs[j] = new MsaWSJob(wsinfo.addJobPane(), mseq); } else { jobs[j] = new MsaWSJob(0, mseq); } wsinfo.setProgressName("region " + jobs[j].jobnum, jobs[j].jobnum); wsinfo.setProgressText(jobs[j].jobnum, OutputHeader); j++; } } else { SequenceI mseq[] = new SequenceI[msa.length]; for (int s = 0; s < mseq.length; s++) { mseq[s] = msa[s].getSeq('-'); } jobs = new MsaWSJob[1]; wsinfo.setProgressText(OutputHeader); // ensures default text jobs[0] = new MsaWSJob(0, mseq); } } public boolean isCancellable() { return true; } public void cancelJob() { if (!jobComplete && jobs != null) { boolean cancelled = true; for (int job = 0; job < jobs.length; job++) { if (jobs[job].submitted && !jobs[job].subjobComplete) { String cancelledMessage = ""; try { vamsas.objects.simple.WsJobId cancelledJob = server .cancel(jobs[job].jobId); if (cancelledJob.getStatus() == 2) { // CANCELLED_JOB cancelledMessage = "Job cancelled."; jobs[job].cancel(); wsInfo.setStatus(jobs[job].jobnum, WebserviceInfo.STATE_CANCELLED_OK); } else if (cancelledJob.getStatus() == 3) { // VALID UNSTOPPABLE JOB cancelledMessage += "Server cannot cancel this job. just close the window.\n"; cancelled = false; // wsInfo.setStatus(jobs[job].jobnum, // WebserviceInfo.STATE_RUNNING); } if (cancelledJob.getJobId() != null) { cancelledMessage += ("[" + cancelledJob.getJobId() + "]"); } cancelledMessage += "\n"; } catch (Exception exc) { cancelledMessage += ("\nProblems cancelling the job : Exception received...\n" + exc + "\n"); Cache.log.warn("Exception whilst cancelling "+jobs[job].jobId,exc); } wsInfo.setProgressText(jobs[job].jobnum, OutputHeader + cancelledMessage + "\n"); } } if (cancelled) { wsInfo.setStatus(WebserviceInfo.STATE_CANCELLED_OK); jobComplete = true; } this.interrupt(); // kick thread to update job states. } else { if (!jobComplete) { wsInfo .setProgressText(OutputHeader + "Server cannot cancel this job because it has not been submitted properly. just close the window.\n"); } } } class JobStateSummary { int running = 0; int queuing = 0; int finished = 0; int error = 0; int serror = 0; int cancelled=0; int results=0; void updateJobPanelState(WebserviceInfo wsInfo, MsaWSJob j) { if (j.result != null) { String progheader = ""; // Parse state of job[j] if (j.result.isRunning()) { running++; wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_RUNNING); } else if (j.result.isQueued()) { queuing++; wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_QUEUING); } else if (j.result.isFinished()) { finished++; j.subjobComplete = true; if (j.hasResults()) results++; wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_OK); } else if (j.result.isFailed()) { progheader += "Job failed.\n"; j.subjobComplete = true; wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR); error++; } else if (j.result.isServerError()) { serror++; j.subjobComplete = true; wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR); } else if (j.result.isBroken() || j.result.isFailed()) { error++; j.subjobComplete = true; wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR); } // and pass on any sub-job messages to the user wsInfo.setProgressText(j.jobnum, OutputHeader); wsInfo.appendProgressText(j.jobnum, progheader); if (j.result.getStatus() != null) { wsInfo.appendProgressText(j.jobnum, j.result.getStatus()); } } else { if (j.submitted && j.subjobComplete) { if (j.allowedServerExceptions == 0) { serror++; } else if (j.result == null) { error++; } } } } } public void run() { JobStateSummary jstate=null; while (!jobComplete) { jstate = new JobStateSummary(); for (int j = 0; j < jobs.length; j++) { if (!jobs[j].submitted && jobs[j].seqs.getSeqs() != null) { StartJob(jobs[j]); } if (jobs[j].submitted && !jobs[j].subjobComplete) { try { if ( (jobs[j].result = server.getResult(jobs[j].jobId)) == null) { throw (new Exception( "Timed out when communicating with server\nTry again later.\n")); } jalview.bin.Cache.log.debug("Job " + j + " Result state " + jobs[j].result.getState() + "(ServerError=" + jobs[j].result.isServerError() + ")"); } catch (Exception ex) { // Deal with Transaction exceptions wsInfo.appendProgressText(jobs[j].jobnum, "\n" + WebServiceName + " Server exception!\n" + ex.getMessage()); Cache.log.warn(WebServiceName + " job(" + jobs[j].jobnum + ") Server exception: " + ex.getMessage()); if (jobs[j].allowedServerExceptions > 0) { jobs[j].allowedServerExceptions--; Cache.log.debug("Sleeping after a server exception."); try { Thread.sleep(5000); } catch (InterruptedException ex1) { } } else { Cache.log.warn("Dropping job " + j + " " + jobs[j].jobId); jobs[j].subjobComplete = true; wsInfo.setStatus(jobs[j].jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR); } } catch (OutOfMemoryError er) { jobComplete = true; jobs[j].subjobComplete = true; jobs[j].result = null; // may contain out of date result object wsInfo.setStatus(jobs[j].jobnum, WebserviceInfo.STATE_STOPPED_ERROR); JOptionPane .showInternalMessageDialog( Desktop.desktop, "Out of memory handling result for job !!" + "\nSee help files for increasing Java Virtual Machine memory.", "Out of memory", JOptionPane.WARNING_MESSAGE); Cache.log.error("Out of memory when retrieving Job " + j + " id:" + WsUrl + "/" + jobs[j].jobId, er); System.gc(); } } jstate.updateJobPanelState(wsInfo, jobs[j]); } // Decide on overall state based on collected jobs[] states if (jstate.running > 0) { wsInfo.setStatus(WebserviceInfo.STATE_RUNNING); } else if (jstate.queuing > 0) { wsInfo.setStatus(WebserviceInfo.STATE_QUEUING); } else { jobComplete = true; if (jstate.finished > 0) { wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK); } else if (jstate.error > 0) { wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); } else if (jstate.serror > 0) { wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); } } if (!jobComplete) { try { Thread.sleep(5000); } catch (InterruptedException e) { Cache.log.debug("Interrupted sleep waiting for next job poll.", e); } // System.out.println("I'm alive "+alTitle); } } if (jobComplete) { parseResult(); // tidy up and make results available to user } } void StartJob(MsaWSJob j) { if (j.submitted) { if (Cache.log.isDebugEnabled()) { Cache.log.debug("Tried to submit an already submitted job " + j.jobId); } return; } if (j.seqs.getSeqs() == null) { // special case - selection consisted entirely of empty sequences... j.submitted = true; j.result = new MsaResult(); j.result.setFinished(true); j.result.setStatus("Empty Alignment Job"); j.result.setMsa(null); } try { vamsas.objects.simple.WsJobId jobsubmit = server.align(j.seqs); if ( (jobsubmit != null) && (jobsubmit.getStatus() == 1)) { j.jobId = jobsubmit.getJobId(); j.submitted = true; j.subjobComplete = false; // System.out.println(WsURL + " Job Id '" + jobId + "'"); } else { if (jobsubmit == null) { throw new Exception( "Server at " + WsUrl + " returned null object, it probably cannot be contacted. Try again later ?"); } throw new Exception(jobsubmit.getJobId()); } } catch (Exception e) { // TODO: JBPNote catch timeout or other fault types explicitly // For unexpected errors System.err .println(WebServiceName + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n" + "When contacting Server:" + WsUrl + "\n" + e.toString() + "\n"); j.allowedServerExceptions = 0; wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR); wsInfo .appendProgressText( j.jobnum, "Failed to submit sequences for alignment.\n" + "It is most likely that there is a problem with the server.\n" + "Just close the window\n"); // e.printStackTrace(); // TODO: JBPNote DEBUG } } private jalview.datamodel.Sequence[] getVamsasAlignment( vamsas.objects.simple.Alignment valign) { vamsas.objects.simple.Sequence[] seqs = valign.getSeqs().getSeqs(); jalview.datamodel.Sequence[] msa = new jalview.datamodel.Sequence[seqs. length]; for (int i = 0, j = seqs.length; i < j; i++) { msa[i] = new jalview.datamodel.Sequence(seqs[i].getId(), seqs[i] .getSeq()); } return msa; } void parseResult() { int results = 0; // number of result sets received JobStateSummary finalState = new JobStateSummary(); try { for (int j = 0; j < jobs.length; j++) { finalState.updateJobPanelState(wsInfo, jobs[j]); if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults()) { results++; vamsas.objects.simple.Alignment valign = jobs[j].result.getMsa(); if (valign != null) { wsInfo.appendProgressText(jobs[j].jobnum, "\nAlignment Object Method Notes\n"); String[] lines = valign.getMethod(); for (int line = 0; line < lines.length; line++) { wsInfo.appendProgressText(jobs[j].jobnum, lines[line] + "\n"); } // JBPNote The returned files from a webservice could be // hidden behind icons in the monitor window that, // when clicked, pop up their corresponding data } } } } catch (Exception ex) { Cache.log.error("Unexpected exception when processing results for " + alTitle, ex); wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); } if (results > 0) { wsInfo.showResultsNewFrame .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed( java.awt.event.ActionEvent evt) { displayResults(true); } }); wsInfo.mergeResults .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed( java.awt.event.ActionEvent evt) { displayResults(false); } }); wsInfo.setResultsReady(); } } void displayResults(boolean newFrame) { // view input or result data for each block // warn user if a block is input rather than aligned data ? int contigs[] = input.getContigs(); SeqCigar[] seqs = input.getSequences(); SequenceI[] alignment = new SequenceI[seqs.length]; ColumnSelection columnselection = new ColumnSelection(); Vector alorders = new Vector(); if (contigs != null && contigs.length > 0) { int start = 0; int nwidth = 0; int owidth = input.getWidth(); int j = 0; for (int contig = 0; contig < contigs.length; contig += 3) { owidth += contigs[contig + 2]; // recover final column width if (contigs[contig + 1] - start > 0) { int width = 0; // subalignment width if (jobs[j].hasResults()) { Object[] subalg = jobs[j++].getAlignment(); alorders.add(subalg[1]); SequenceI mseq[] = (SequenceI[]) subalg[0]; width = mseq[0].getLength(); for (int s = 0; s < mseq.length; s++) { if (alignment[s] == null) { alignment[s] = mseq[s]; } else { alignment[s].setSequence(alignment[s].getSequence() + mseq[s].getSequence()); if (mseq[s].getStart() <= mseq[s].getEnd()) { alignment[s].setEnd(mseq[s].getEnd()); } ( (AlignmentOrder) subalg[1]).updateSequence(mseq[s], alignment[s]); } } } else { // recover input data or place gaps if (true) { // recover input data for (int s = 0; s < seqs.length; s++) { SequenceI oseq = seqs[s].getSeq('-').getSubSequence(start, contigs[contig + 1]); if (width < oseq.getLength()) { width = oseq.getLength(); } if (alignment[s] == null) { alignment[s] = oseq; } else { alignment[s].setSequence(alignment[s].getSequence() + oseq.getSequence()); if (oseq.getEnd() >= oseq.getStart()) { alignment[s].setEnd(oseq.getEnd()); } } } } j++; } nwidth += width; } // advance to begining of visible region start = contigs[contig + 1] + contigs[contig + 2]; // add hidden segment to right of next region for (int s = 0; s < seqs.length; s++) { SequenceI hseq = seqs[s].getSeq('-').getSubSequence(contigs[contig + 1], start); if (alignment[s] == null) { alignment[s] = hseq; } else { alignment[s].setSequence(alignment[s].getSequence() + hseq.getSequence()); if (hseq.getEnd() >= hseq.getStart()) { alignment[s].setEnd(hseq.getEnd()); } } } // mark hidden segment as hidden in the new alignment columnselection.hideColumns(nwidth, nwidth + contigs[contig + 2] - 1); nwidth += contigs[contig + 2]; } // Do final job - if it exists if (j < jobs.length) { int width = 0; if (jobs[j].hasResults()) { Object[] subalg = jobs[j].getAlignment(); alorders.add(subalg[1]); SequenceI mseq[] = (SequenceI[]) subalg[0]; width = mseq[0].getLength(); for (int s = 0; s < mseq.length; s++) { if (alignment[s] == null) { alignment[s] = mseq[s]; } else { alignment[s].setSequence(alignment[s].getSequence() + mseq[s].getSequence()); if (mseq[s].getEnd() >= mseq[s].getStart()) { alignment[s].setEnd(mseq[s].getEnd()); } ( (AlignmentOrder) subalg[1]).updateSequence(mseq[s], alignment[s]); } } } else { if (start < owidth) { // recover input data or place gaps if (true) { // recover input data for (int s = 0; s < seqs.length; s++) { SequenceI oseq = seqs[s].getSeq('-').getSubSequence(start, owidth + 1); if (width < oseq.getLength()) { width = oseq.getLength(); } if (alignment[s] == null) { alignment[s] = oseq; } else { alignment[s].setSequence(alignment[s].getSequence() + oseq.getSequence()); if (oseq.getEnd() >= oseq.getStart()) { alignment[s].setEnd(oseq.getEnd()); } } } nwidth += width; } else { // place gaps. throw new Error("Padding not yet implemented."); } } } } } else { if (jobs[0].hasResults()) { Object[] alg = jobs[0].getAlignment(); alignment = (SequenceI[]) alg[0]; alorders.add(alg[1]); } else { alignment = SeqCigar.createAlignmentSequences(seqs, '-', columnselection, null); } } Alignment al = new Alignment(alignment); if (dataset != null) { al.setDataset(dataset); } if (newFrame) { // TODO: JBPNote Should also rename the query sequence // sometime... AlignFrame af = new AlignFrame(al, columnselection); // >>>This is a fix for the moment, until a better solution is // found!!<<< af.getFeatureRenderer().transferSettings( alignFrame.getFeatureRenderer()); if (alorders.size() > 0) { if (alorders.size() == 1) { af.addSortByOrderMenuItem(WebServiceName + " Ordering", (AlignmentOrder) alorders.get(0)); } else { // construct a non-redundant ordering set Vector names = new Vector(); for (int i = 0, l = alorders.size(); i < l; i++) { String orderName = new String("Region " + i); int j = i + 1; int r = l; while (j < l) { if ( ( (AlignmentOrder) alorders.get(i)).equals( ( ( AlignmentOrder) alorders.get(j)))) { alorders.remove(j); l--; orderName += "," + j; } else { j++; } } if (i == 0 && j == 1) { names.add(new String("")); } else { names.add(orderName); } } for (int i = 0, l = alorders.size(); i < l; i++) { af.addSortByOrderMenuItem(WebServiceName + ( (String) names.get(i)) + " Ordering", (AlignmentOrder) alorders.get(i)); } } } Desktop.addInternalFrame(af, alTitle, AlignFrame.NEW_WINDOW_WIDTH, AlignFrame.NEW_WINDOW_HEIGHT); } else { System.out.println("MERGE WITH OLD FRAME"); } } }