Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 14:43:25 GMT
  2. Package jalview.bin

File Commands.java

 

Coverage histogram

../../img/srcFileCovDistChart7.png
30% of files have more coverage

Code metrics

240
551
23
1
1,507
1,193
199
0.36
23.96
23
8.65

Classes

Class Line # Actions
Commands 85 551 199
0.636363663.6%
 

Contributing tests

This file is covered by 58 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.bin;
22   
23    import java.awt.Color;
24    import java.io.File;
25    import java.io.FileNotFoundException;
26    import java.io.IOException;
27    import java.net.URISyntaxException;
28    import java.util.ArrayList;
29    import java.util.Arrays;
30    import java.util.Collections;
31    import java.util.HashMap;
32    import java.util.Iterator;
33    import java.util.List;
34    import java.util.Locale;
35    import java.util.Map;
36   
37    import javax.swing.SwingUtilities;
38   
39    import jalview.api.structures.JalviewStructureDisplayI;
40    import jalview.bin.Jalview.ExitCode;
41    import jalview.bin.argparser.Arg;
42    import jalview.bin.argparser.ArgParser;
43    import jalview.bin.argparser.ArgValue;
44    import jalview.bin.argparser.ArgValuesMap;
45    import jalview.bin.argparser.StructuresFile;
46    import jalview.bin.argparser.SubVals;
47    import jalview.datamodel.AlignmentI;
48    import jalview.datamodel.SequenceI;
49    import jalview.gui.AlignFrame;
50    import jalview.gui.AlignmentPanel;
51    import jalview.gui.AppJmol;
52    import jalview.gui.Desktop;
53    import jalview.gui.Preferences;
54    import jalview.gui.StructureChooser;
55    import jalview.gui.StructureViewer;
56    import jalview.gui.StructureViewer.ViewerType;
57    import jalview.io.AppletFormatAdapter;
58    import jalview.io.BackupFiles;
59    import jalview.io.BioJsHTMLOutput;
60    import jalview.io.DataSourceType;
61    import jalview.io.FileFormat;
62    import jalview.io.FileFormatException;
63    import jalview.io.FileFormatI;
64    import jalview.io.FileFormats;
65    import jalview.io.FileLoader;
66    import jalview.io.HtmlSvgOutput;
67    import jalview.io.IdentifyFile;
68    import jalview.io.NewickFile;
69    import jalview.io.exceptions.ImageOutputException;
70    import jalview.schemes.ColourSchemeI;
71    import jalview.schemes.ColourSchemeProperty;
72    import jalview.structure.StructureCommandI;
73    import jalview.structure.StructureImportSettings.TFType;
74    import jalview.structure.StructureSelectionManager;
75    import jalview.util.ColorUtils;
76    import jalview.util.FileUtils;
77    import jalview.util.HttpUtils;
78    import jalview.util.ImageMaker;
79    import jalview.util.ImageMaker.TYPE;
80    import jalview.util.MessageManager;
81    import jalview.util.Platform;
82    import jalview.util.StringUtils;
83    import jalview.util.imagemaker.BitmapImageSizing;
84   
 
85    public class Commands
86    {
87    Desktop desktop;
88   
89    private boolean headless;
90   
91    private ArgParser argParser;
92   
93    private Map<String, AlignFrame> afMap;
94   
95    private Map<String, StructureViewer> svMap = new HashMap<>();
96   
97    private boolean commandArgsProvided = false;
98   
99    private boolean argsWereParsed = false;
100   
101    private List<String> errors = new ArrayList<>();
102   
103    private static final String PREVIOUSSTRUCTUREVIEWER = "previous";
104   
 
105  0 toggle public Commands(ArgParser argparser, boolean headless)
106    {
107  0 this(Desktop.getInstance(), argparser, headless);
108    }
109   
 
110  137 toggle public Commands(Desktop d, ArgParser argparser, boolean h)
111    {
112  137 argParser = argparser;
113  137 headless = h;
114  137 desktop = d;
115  137 afMap = new HashMap<>();
116    }
117   
 
118  137 toggle protected boolean processArgs()
119    {
120  137 if (argParser == null)
121    {
122  0 return true;
123    }
124   
125  137 boolean theseArgsWereParsed = false;
126   
127  137 if (argParser != null && argParser.getLinkedIds() != null)
128    {
129  137 for (String id : argParser.getLinkedIds())
130    {
131  153 ArgValuesMap avm = argParser.getLinkedArgs(id);
132  153 theseArgsWereParsed = true;
133  153 boolean processLinkedOkay = processLinked(id);
134  149 theseArgsWereParsed &= processLinkedOkay;
135   
136  149 processGroovyScript(id);
137   
138    // wait around until alignFrame isn't busy
139  149 AlignFrame af = afMap.get(id);
140  416 while (af != null && af.getViewport().isCalcInProgress())
141    {
142  267 try
143    {
144  267 Thread.sleep(25);
145    } catch (Exception q)
146    {
147    }
148  267 ;
149    }
150   
151  149 theseArgsWereParsed &= processImages(id);
152   
153  149 if (processLinkedOkay)
154    {
155  149 theseArgsWereParsed &= processOutput(id);
156    }
157   
158    // close ap
159  149 if (avm.getBoolean(Arg.CLOSE))
160    {
161  60 af = afMap.get(id);
162  60 if (af != null)
163    {
164  60 af.closeMenuItem_actionPerformed(true);
165    }
166    }
167   
168    }
169   
170    }
171   
172    // report errors - if any
173  133 String errorsRaised = errorsToString();
174  133 if (errorsRaised.trim().length() > 0)
175    {
176  0 Console.warn(
177    "The following errors and warnings occurred whilst processing files:\n"
178    + errorsRaised);
179    }
180    // gui errors reported in Jalview
181   
182  133 if (argParser.getBoolean(Arg.QUIT))
183    {
184  1 Jalview.exit("Exiting due to " + Arg.QUIT.argString() + " argument.",
185    ExitCode.OK);
186  0 return true;
187    }
188    // carry on with jalview.bin.Jalview
189  132 argsWereParsed = theseArgsWereParsed;
190  132 return argsWereParsed;
191    }
192   
 
193  13 toggle public boolean commandArgsProvided()
194    {
195  13 return commandArgsProvided;
196    }
197   
 
198  144 toggle public boolean argsWereParsed()
199    {
200  144 return argsWereParsed;
201    }
202   
 
203  153 toggle protected boolean processLinked(String id)
204    {
205  153 boolean theseArgsWereParsed = false;
206  153 ArgValuesMap avm = argParser.getLinkedArgs(id);
207  153 if (avm == null)
208    {
209  0 return true;
210    }
211   
212  153 Boolean isError = Boolean.valueOf(false);
213   
214    // set wrap, showSSAnnotations, showAnnotations and hideTFrows scope here so
215    // it can be applied after structures are opened
216  153 boolean wrap = false;
217  153 boolean showSSAnnotations = false;
218  153 boolean showAnnotations = false;
219  153 boolean hideTFrows = false;
220  153 AlignFrame af = null;
221   
222  153 if (avm.containsArg(Arg.APPEND) || avm.containsArg(Arg.OPEN))
223    {
224  153 commandArgsProvided = true;
225  153 final long progress = System.currentTimeMillis();
226   
227  153 boolean first = true;
228  153 boolean progressBarSet = false;
229    // Combine the APPEND and OPEN files into one list, along with whether it
230    // was APPEND or OPEN
231  153 List<ArgValue> openAvList = new ArrayList<>();
232  153 openAvList.addAll(avm.getArgValueList(Arg.OPEN));
233  153 openAvList.addAll(avm.getArgValueList(Arg.APPEND));
234    // sort avlist based on av.getArgIndex()
235  153 Collections.sort(openAvList);
236  153 for (ArgValue av : openAvList)
237    {
238  172 Arg a = av.getArg();
239  172 SubVals sv = av.getSubVals();
240  172 String openFile0 = av.getValue();
241  172 String openFile = HttpUtils.equivalentJalviewUrl(openFile0);
242  172 if (openFile == null)
243  0 continue;
244   
245  172 theseArgsWereParsed = true;
246  172 if (first)
247    {
248  153 first = false;
249  153 if (!headless && desktop != null)
250    {
251  122 SwingUtilities.invokeLater(new Runnable()
252    {
 
253  118 toggle @Override
254    public void run()
255    {
256  118 desktop.setProgressBar(
257    MessageManager.getString(
258    "status.processing_commandline_args"),
259    progress);
260   
261    }
262    });
263  122 progressBarSet = true;
264    }
265    }
266   
267  172 if (!Platform.isJS())
268    /**
269    * ignore in JavaScript -- can't just file existence - could load it?
270    *
271    * @j2sIgnore
272    */
273    {
274  172 if (!HttpUtils.isPlausibleUri(openFile))
275    {
276  169 if (!(new File(openFile)).exists())
277    {
278  0 addError("Can't find file '" + openFile + "'");
279  0 isError = true;
280  0 continue;
281    }
282    }
283    }
284   
285  172 DataSourceType protocol = AppletFormatAdapter
286    .checkProtocol(openFile);
287   
288  172 FileFormatI format = null;
289  172 try
290    {
291  172 format = new IdentifyFile().identify(openFile, protocol);
292    } catch (FileNotFoundException e0)
293    {
294  0 addError((protocol == DataSourceType.URL ? "File at URL" : "File")
295    + " '" + openFile + "' not found");
296  0 isError = true;
297  0 continue;
298    } catch (FileFormatException e1)
299    {
300  0 addError("Unknown file format for '" + openFile + "'");
301  0 isError = true;
302  0 continue;
303    }
304   
305  172 af = afMap.get(id);
306    // When to open a new AlignFrame
307  172 if (af == null || "true".equals(av.getSubVal("new"))
308    || a == Arg.OPEN || format == FileFormat.Jalview)
309    {
310  154 if (a == Arg.OPEN)
311    {
312  130 Jalview.testoutput(argParser, Arg.OPEN, "examples/uniref50.fa",
313    openFile);
314    }
315   
316  154 Console.debug(
317    "Opening '" + openFile + "' in new alignment frame");
318  154 FileLoader fileLoader = new FileLoader(!headless);
319  154 boolean xception = false;
320  154 try
321    {
322  154 af = fileLoader.LoadFileWaitTillLoaded(openFile, protocol,
323    format);
324  154 if (!openFile.equals(openFile0))
325    {
326  0 af.setTitle(openFile0);
327    }
328    } catch (Throwable thr)
329    {
330  0 xception = true;
331  0 addError("Couldn't open '" + openFile + "' as " + format + " "
332    + thr.getLocalizedMessage()
333    + " (Enable debug for full stack trace)");
334  0 isError = true;
335  0 Console.debug("Exception when opening '" + openFile + "'", thr);
336    } finally
337    {
338  154 if (af == null && !xception)
339    {
340  0 addInfo("Ignoring '" + openFile
341    + "' - no alignment data found.");
342  0 continue;
343    }
344    }
345   
346    // colour alignment
347  154 String colour = null;
348  154 if (avm.containsArg(Arg.COLOUR)
349    || !(format == FileFormat.Jalview))
350    {
351  154 colour = avm.getFromSubValArgOrPref(av, Arg.COLOUR, sv, null,
352    "DEFAULT_COLOUR_PROT", null);
353    }
354  154 if (colour != null)
355    {
356  16 this.colourAlignFrame(af, colour);
357    }
358   
359    // Change alignment frame title
360  154 String title = avm.getFromSubValArgOrPref(av, Arg.TITLE, sv, null,
361    null, null);
362  154 if (title != null)
363    {
364  0 af.setTitle(title);
365  0 Jalview.testoutput(argParser, Arg.TITLE, "test title", title);
366    }
367   
368    // Add features
369  154 List<String> featuresfiles = avm
370    .getValuesFromSubValOrArgs(argParser, Arg.FEATURES, sv);
371  154 for (String featuresfile : featuresfiles)
372    {
373  1 if (featuresfile != null)
374    {
375  1 af.parseFeaturesFile(featuresfile,
376    AppletFormatAdapter.checkProtocol(featuresfile));
377  1 Jalview.testoutput(argParser, Arg.FEATURES,
378    "examples/testdata/plantfdx.features", featuresfile);
379    }
380    }
381   
382    // Add annotations from file
383  154 List<String> annotationsfiles = avm.getValuesFromSubValOrArgs(
384    argParser, Arg.ANNOTATIONS, sv);
385  154 for (String annotationsfile : annotationsfiles)
386    {
387  5 if (annotationsfile != null)
388    {
389  5 af.loadJalviewDataFile(annotationsfile, null, null, null);
390  5 Jalview.testoutput(argParser, Arg.ANNOTATIONS,
391    "examples/testdata/plantfdx.annotations",
392    annotationsfile);
393    }
394    }
395   
396    // Set or clear the sortbytree flag
397  154 boolean sortbytree = avm.getBoolFromSubValOrArg(Arg.SORTBYTREE,
398    sv);
399  154 if (sortbytree)
400    {
401  1 af.getViewport().setSortByTree(true);
402  1 Jalview.testoutput(argParser, Arg.SORTBYTREE);
403    }
404   
405    // Load tree from file
406  154 String treefile = avm.getValueFromSubValOrArg(av, Arg.TREE, sv);
407  154 if (treefile != null)
408    {
409  1 try
410    {
411  1 NewickFile nf = new NewickFile(treefile,
412    AppletFormatAdapter.checkProtocol(treefile));
413  1 af.getViewport().setCurrentTree(
414    af.showNewickTree(nf, treefile).getTree());
415  1 Jalview.testoutput(argParser, Arg.TREE,
416    "examples/testdata/uniref50_test_tree", treefile);
417    } catch (IOException e)
418    {
419  0 addError("Couldn't add tree " + treefile, e);
420  0 isError = true;
421    }
422    }
423   
424    // Show secondary structure annotations?
425  154 showSSAnnotations = avm.getFromSubValArgOrPref(
426    Arg.SHOWSSANNOTATIONS, av.getSubVals(), null,
427    "STRUCT_FROM_PDB", true);
428    // Show sequence annotations?
429  154 showAnnotations = avm.getFromSubValArgOrPref(Arg.SHOWANNOTATIONS,
430    av.getSubVals(), null, "SHOW_ANNOTATIONS", true);
431    // hide the Temperature Factor row?
432  154 hideTFrows = (avm.getBoolean(Arg.NOTEMPFAC));
433   
434    // showSSAnnotations, showAnnotations, hideTFrows used after opening
435    // structure
436   
437    // wrap alignment? do this last for formatting reasons
438  154 wrap = avm.getFromSubValArgOrPref(Arg.WRAP, sv, null,
439    "WRAP_ALIGNMENT", false);
440    // af.setWrapFormat(wrap) is applied after structures are opened for
441    // annotation reasons
442   
443    // store the AlignFrame for this id
444  154 afMap.put(id, af);
445   
446    // is it its own structure file?
447  154 if (format.isStructureFile())
448    {
449  0 StructureSelectionManager ssm = StructureSelectionManager
450    .getStructureSelectionManager(desktop);
451  0 SequenceI seq = af.alignPanel.getAlignment().getSequenceAt(0);
452  0 ssm.computeMapping(false, new SequenceI[] { seq }, null,
453    openFile, DataSourceType.FILE, null, null, null, false);
454    }
455    }
456    else
457    {
458  18 Console.debug(
459    "Opening '" + openFile + "' in existing alignment frame");
460   
461  18 DataSourceType dst = HttpUtils.startsWithHttpOrHttps(openFile)
462    ? DataSourceType.URL
463    : DataSourceType.FILE;
464   
465  18 FileLoader fileLoader = new FileLoader(!headless);
466  18 fileLoader.LoadFile(af.getCurrentView(), openFile, dst, null,
467    false);
468    }
469   
470  172 Console.debug("Command " + Arg.APPEND + " executed successfully!");
471   
472    }
473  153 if (first) // first=true means nothing opened
474    {
475  0 if (headless)
476    {
477  0 Jalview.exit("Could not open any files in headless mode",
478    ExitCode.NO_FILES);
479    }
480    else
481    {
482  0 Console.info("No more files to open");
483    }
484    }
485  153 if (progressBarSet && desktop != null)
486  122 desktop.setProgressBar(null, progress);
487   
488    }
489   
490    // open the structure (from same PDB file or given PDBfile)
491  153 if (!avm.getBoolean(Arg.NOSTRUCTURE))
492    {
493  153 if (af == null)
494    {
495  0 af = afMap.get(id);
496    }
497   
498    // STRUCTURESFILES
499    // we oo through --structuresfiles first
500  153 if (avm.containsArg(Arg.STRUCTURESFILE))
501    {
502  3 String defaultViewerId = "STRUCTURESFILE VIEWER ";
503  3 int viewerIdCount = 0;
504  3 for (ArgValue structuresFileAV : avm
505    .getArgValueList(Arg.STRUCTURESFILE))
506    {
507  5 viewerIdCount++;
508  5 String structuresFilename = structuresFileAV.getValue();
509  5 AlignmentI al = af.getViewport().getAlignment();
510  5 StructuresFile sf = new StructuresFile(al, structuresFilename);
511    // set a default viewer id if one isn't given
512  5 if (sf.getViewerid() == null)
513    {
514  2 sf.setViewerid(new StringBuilder(defaultViewerId)
515    .append(viewerIdCount).toString());
516    }
517   
518  5 StructureViewer thisStructureViewer = null;
519  5 if (svMap.containsKey(sf.getViewerid()))
520    {
521  0 thisStructureViewer = svMap.get(sf.getViewerid());
522    }
523   
524  5 if (thisStructureViewer == null)
525    {
526   
527    // create a new structure viewer
528  5 StructureChooser sc = new StructureChooser(sf.getSeqs(), null,
529    af.alignPanel, false, true);
530   
531  5 thisStructureViewer = sc.launchStructureViewer(null,
532    sf.getPdbEntries(), af.alignPanel, sf.getSeqs(),
533    sf.getViewerType(), sf.isSuperpose());
534  5 thisStructureViewer.showAllChains();
535   
536  5 if (sf.getViewerid() != null)
537    {
538  5 svMap.put(sf.getViewerid(), thisStructureViewer);
539    }
540    }
541    else
542    {
543   
544    // adding structure to existing structure viewer
545  0 thisStructureViewer.viewStructures(sf.getPdbEntries(),
546    sf.getSeqs(), af.alignPanel, sf.getViewerType(),
547    sf.isSuperpose());
548   
549  0 thisStructureViewer.showAllChains();
550    }
551   
552    }
553    }
554   
555    // STRUCTURES
556    // and then --structures
557  153 if (avm.containsArg(Arg.STRUCTURE))
558    {
559  22 commandArgsProvided = true;
560   
561    // Settings "global" to this AVM
562  22 String ALLSTRUCTURESVIEWERID = avm
563    .getValue(Arg.ALLSTRUCTURESVIEWERID);
564   
565  22 Boolean SUPERPOSE = null;
566  22 if (avm.containsArg(Arg.SUPERPOSE))
567    {
568  6 SUPERPOSE = avm.getBoolean(Arg.SUPERPOSE);
569    }
570   
571  22 StructureViewer structureViewer = null;
572  22 for (ArgValue structureAv : avm.getArgValueList(Arg.STRUCTURE))
573    {
574  42 argParser.setStructureFilename(null);
575  42 String val = structureAv.getValue();
576  42 SubVals subVals = structureAv.getSubVals();
577  42 SequenceI seq = getSpecifiedSequence(af, avm, structureAv);
578  42 if (seq == null)
579    {
580    // Could not find sequence from subId, let's assume the first
581    // sequence in the alignframe
582  16 AlignmentI al = af.getCurrentView().getAlignment();
583  16 seq = al.getSequenceAt(0);
584    }
585   
586  42 if (seq == null)
587    {
588  0 addWarn("Could not find sequence for argument "
589    + Arg.STRUCTURE.argString() + "=" + val);
590  0 continue;
591    }
592  42 String structureLocationRef = null;
593  42 DataSourceType structureLocationType = null;
594  42 if (subVals.getContent() != null
595    && subVals.getContent().length() != 0)
596    {
597  42 structureLocationRef = subVals.getContent();
598  42 structureLocationType = AppletFormatAdapter
599    .checkProtocol(structureLocationRef);
600  42 if (DataSourceType.FILE.equals(structureLocationType))
601    {
602  39 structureLocationRef = new File(structureLocationRef)
603    .getAbsolutePath();
604    }
605  42 if (Console.isDebugEnabled())
606    {
607  0 Console.debug("Using structure file (from argument) '"
608   
609    + structureLocationRef + "' (protocol is "
610    + structureLocationType);
611    }
612    }
613    /*
614    * JBPNote: commented out this logic until we know what is actually needed.
615    *
616    * Most likely requirement would be to open a view for an existing structure file as specified by its ID (which is its PDB ID or original URI)
617    *
618    * Code as written below assumes the first PDBEntry is the one that should be used, which isn't reliable.
619    *
620    */
621    // else if (seq.getAllPDBEntries() != null
622    // && seq.getAllPDBEntries().size() > 0)
623    // {
624    // // TODO look up structureLocationRef in PDBEntry so we can get the
625    // // actual unique file ID ...
626    // structureFile = new File(
627    // seq.getAllPDBEntries().elementAt(0).getFile());
628    // if (structureFile != null)
629    // {
630    // Console.debug("Using structure file (from sequence) '"
631    // + structureFile.getAbsolutePath() + "'");
632    // }
633    // structureLocationRef = structureFile.getAbsolutePath();
634    // }
635   
636  42 if (structureLocationRef == null)
637    {
638  0 addWarn("No provided structure file with '" + val + "'");
639  0 continue;
640    }
641   
642  42 if (structureLocationType == null)
643    {
644  0 addWarn("Could not determine structure fetch protocol for '"
645    + val + "'");
646  0 continue;
647    }
648   
649  42 argParser.setStructureFilename(structureLocationRef);
650   
651    // open structure view
652  42 AlignmentPanel ap = af.alignPanel;
653  42 if (headless)
654    {
655  2 Cache.setProperty(Preferences.STRUCTURE_DISPLAY,
656    StructureViewer.ViewerType.JMOL.toString());
657    }
658   
659    // get viewerid to either create a new structure viewer or superimpose
660    // this structure on an existing one
661  42 String viewerid = ALLSTRUCTURESVIEWERID;
662  42 if (viewerid == null)
663    {
664  42 viewerid = avm.getFromSubValArgOrPrefWithSubstitutions(
665    argParser, Arg.VIEWERID, ArgValuesMap.Position.AFTER,
666    structureAv, subVals, null, null, null);
667    }
668   
669    // get PAEMATRIX path and label from subvals or Arg.PAEMATRIX
670    // assumes protocol is same as for the structure
671  42 String paeFilepath = avm.getFromSubValArgOrPrefWithSubstitutions(
672    argParser, Arg.PAEMATRIX, ArgValuesMap.Position.AFTER,
673    structureAv, subVals, null, null, null);
674   
675    // showing annotations from structure file or not
676  42 boolean ssFromStructure = avm.getFromSubValArgOrPref(
677    Arg.SHOWSSANNOTATIONS, subVals, null, "STRUCT_FROM_PDB",
678    true);
679   
680    // get TEMPFAC type from subvals or Arg.TEMPFAC in case user Adds
681    // reference annotations
682  42 String tftString = avm.getFromSubValArgOrPrefWithSubstitutions(
683    argParser, Arg.TEMPFAC, ArgValuesMap.Position.AFTER,
684    structureAv, subVals, null, null, null);
685  42 boolean notempfac = avm.getFromSubValArgOrPref(Arg.NOTEMPFAC,
686    subVals, null, "ADD_TEMPFACT_ANN", false, true);
687  42 TFType tft = notempfac ? null : TFType.DEFAULT;
688  42 if (tftString != null && !notempfac)
689    {
690    // get kind of temperature factor annotation
691  12 try
692    {
693  12 tft = TFType.valueOf(tftString.toUpperCase(Locale.ROOT));
694  12 Console.debug("Obtained Temperature Factor type of '" + tft
695    + "' for structure '" + structureLocationRef + "'");
696    } catch (IllegalArgumentException e)
697    {
698    // Just an error message!
699  0 StringBuilder sb = new StringBuilder().append("Cannot set ")
700    .append(Arg.TEMPFAC.argString()).append(" to '")
701    .append(tft)
702    .append("', ignoring. Valid values are: ");
703  0 Iterator<TFType> it = Arrays.stream(TFType.values())
704    .iterator();
705  0 while (it.hasNext())
706    {
707  0 sb.append(it.next().toString().toLowerCase(Locale.ROOT));
708  0 if (it.hasNext())
709  0 sb.append(", ");
710    }
711  0 addWarn(sb.toString());
712    }
713    }
714   
715  42 boolean superpose = SUPERPOSE != null ? SUPERPOSE
716    : avm.getBoolFromSubVal(Arg.SUPERPOSE, subVals,
717    Cache.getDefault(StructureChooser.AUTOSUPERIMPOSE,
718    true));
719   
720  42 String sViewerType = avm.getFromSubValArgOrPref(
721    Arg.STRUCTUREVIEWER, ArgValuesMap.Position.AFTER,
722    structureAv, subVals, null, null, "jmol");
723  42 ViewerType viewerType = ViewerType.getFromString(sViewerType);
724   
725  42 StructureViewer thisStructureViewer = null;
726  42 if (sViewerType.equals(PREVIOUSSTRUCTUREVIEWER)
727    && structureViewer != null)
728    {
729  0 thisStructureViewer = structureViewer;
730    }
731  42 else if (viewerid != null && svMap.containsKey(viewerid))
732    {
733  5 thisStructureViewer = svMap.get(viewerid);
734    }
735    // TODO use ssFromStructure
736  42 if (thisStructureViewer == null)
737    {
738   
739  37 thisStructureViewer = StructureChooser
740    .openStructureForASequence(null, null, ap, seq, false,
741    structureLocationRef, structureLocationType,
742    tft, paeFilepath, false, ssFromStructure, false,
743    viewerType);
744   
745    /* For some reason this is breaking multiple structure opening */
746    // thisStructureViewer.setPermanentTitle(viewerid);
747   
748  37 if (viewerid != null)
749    {
750  5 svMap.put(viewerid, thisStructureViewer);
751    }
752    }
753    else
754    {
755   
756    // adding structure to existing structure viewer
757  5 thisStructureViewer.viewStructures(structureLocationRef,
758    structureLocationType, seq, ap, false, tft, paeFilepath,
759    false, ssFromStructure, false, superpose);
760  5 thisStructureViewer.showAllChains();
761   
762    }
763  42 structureViewer = thisStructureViewer;
764   
765  42 if (structureViewer == null)
766    {
767  9 if (!StringUtils.equalsIgnoreCase(sViewerType, "none"))
768    {
769  0 addError("Failed to import and open structure view for file '"
770    + structureLocationRef + "'.");
771    }
772  9 continue;
773    }
774  33 try
775    {
776  33 long tries = 1000;
777  349 while (structureViewer.isBusy() && tries > 0)
778    {
779  316 Thread.sleep(25);
780  316 if (structureViewer.isBusy())
781    {
782  284 tries--;
783  284 Console.debug(
784    "Waiting for viewer for " + structureLocationRef);
785    }
786    }
787  33 if (tries == 0 && structureViewer.isBusy())
788    {
789  0 addWarn("Gave up waiting for structure viewer to load file '"
790    + structureLocationRef
791    + "'. Something may have gone wrong.");
792    }
793    } catch (Exception x)
794    {
795  0 addError("Exception whilst waiting for structure viewer "
796    + structureLocationRef, x);
797  0 isError = true;
798    }
799   
800  33 Console.debug(
801    "Successfully opened viewer for " + structureLocationRef);
802   
803  33 if (avm.containsArg(Arg.STRUCTUREIMAGE))
804    {
805  0 for (ArgValue structureImageArgValue : avm
806    .getArgValueListFromSubValOrArg(structureAv,
807    Arg.STRUCTUREIMAGE, subVals))
808    {
809  0 String structureImageFilename = argParser.makeSubstitutions(
810    structureImageArgValue.getValue(), id, true);
811  0 if (structureViewer != null && structureImageFilename != null)
812    {
813  0 SubVals structureImageSubVals = null;
814  0 structureImageSubVals = structureImageArgValue.getSubVals();
815  0 File structureImageFile = new File(structureImageFilename);
816  0 String width = avm.getValueFromSubValOrArg(
817    structureImageArgValue, Arg.WIDTH,
818    structureImageSubVals);
819  0 String height = avm.getValueFromSubValOrArg(
820    structureImageArgValue, Arg.HEIGHT,
821    structureImageSubVals);
822  0 String scale = avm.getValueFromSubValOrArg(
823    structureImageArgValue, Arg.SCALE,
824    structureImageSubVals);
825  0 String renderer = avm.getValueFromSubValOrArg(
826    structureImageArgValue, Arg.TEXTRENDERER,
827    structureImageSubVals);
828  0 String typeS = avm.getValueFromSubValOrArg(
829    structureImageArgValue, Arg.TYPE,
830    structureImageSubVals);
831  0 if (typeS == null || typeS.length() == 0)
832    {
833  0 typeS = FileUtils.getExtension(structureImageFile);
834    }
835  0 TYPE imageType;
836  0 try
837    {
838  0 imageType = Enum.valueOf(TYPE.class,
839    typeS.toUpperCase(Locale.ROOT));
840    } catch (IllegalArgumentException e)
841    {
842  0 addWarn("Do not know image format '" + typeS
843    + "', using PNG");
844  0 imageType = TYPE.PNG;
845    }
846  0 BitmapImageSizing userBis = ImageMaker
847    .parseScaleWidthHeightStrings(scale, width, height);
848   
849    /////
850    // DON'T TRY TO EXPORT IF VIEWER IS UNSUPPORTED
851  0 if (viewerType != ViewerType.JMOL)
852    {
853  0 addWarn("Cannot export image for structure viewer "
854    + viewerType.name() + " yet");
855  0 continue;
856    }
857   
858    /////
859    // Apply the temporary colourscheme to the linked alignment
860    // TODO: enhance for multiple linked alignments.
861   
862  0 String imageColour = avm.getValueFromSubValOrArg(
863    structureImageArgValue, Arg.IMAGECOLOUR,
864    structureImageSubVals);
865  0 ColourSchemeI originalColourScheme = this
866    .getColourScheme(af);
867  0 this.colourAlignFrame(af, imageColour);
868   
869    /////
870    // custom image background colour
871   
872  0 String bgcolourstring = avm.getValueFromSubValOrArg(
873    structureImageArgValue, Arg.BGCOLOUR,
874    structureImageSubVals);
875  0 Color bgcolour = null;
876  0 if (bgcolourstring != null && bgcolourstring.length() > 0)
877    {
878  0 bgcolour = ColorUtils.parseColourString(bgcolourstring);
879  0 if (bgcolour == null)
880    {
881  0 Console.warn(
882    "Background colour string '" + bgcolourstring
883    + "' not recognised -- using default");
884    }
885    }
886   
887  0 JalviewStructureDisplayI sview = structureViewer
888    .getJalviewStructureDisplay();
889   
890  0 File sessionToRestore = null;
891   
892  0 List<StructureCommandI> extraCommands = new ArrayList<>();
893   
894  0 if (extraCommands.size() > 0 || bgcolour != null)
895    {
896  0 try
897    {
898  0 sessionToRestore = sview.saveSession();
899    } catch (Throwable t)
900    {
901  0 Console.warn(
902    "Unable to save temporary session file before custom structure view export operation.");
903    }
904    }
905   
906    ////
907    // Do temporary ops
908   
909  0 if (bgcolour != null)
910    {
911  0 sview.getBinding().setBackgroundColour(bgcolour);
912    }
913   
914  0 sview.getBinding().executeCommands(extraCommands, false,
915    "Executing Custom Commands");
916   
917    // and export the view as an image
918  0 boolean success = this.checksBeforeWritingToFile(avm,
919    subVals, false, structureImageFilename,
920    "structure image", isError);
921   
922  0 if (!success)
923    {
924  0 continue;
925    }
926  0 Console.debug("Rendering image to " + structureImageFile);
927    //
928    // TODO - extend StructureViewer / Binding with makePDBImage so
929    // we can do this with every viewer
930    //
931   
932  0 try
933    {
934    // We don't expect class cast exception
935  0 AppJmol jmol = (AppJmol) sview;
936  0 jmol.makePDBImage(structureImageFile, imageType, renderer,
937    userBis);
938  0 Console.info("Exported structure image to "
939    + structureImageFile);
940   
941    // RESTORE SESSION AFTER EXPORT IF NEED BE
942  0 if (sessionToRestore != null)
943    {
944  0 Console.debug(
945    "Restoring session from " + sessionToRestore);
946   
947  0 sview.getBinding().restoreSession(
948    sessionToRestore.getAbsolutePath());
949   
950    }
951    } catch (ImageOutputException ioexec)
952    {
953  0 addError(
954    "Unexpected error when restoring structure viewer session after custom view operations.");
955  0 isError = true;
956  0 continue;
957    } finally
958    {
959  0 try
960    {
961  0 this.colourAlignFrame(af, originalColourScheme);
962    } catch (Exception t)
963    {
964  0 addError(
965    "Unexpected error when restoring colourscheme to alignment after temporary change for export.",
966    t);
967    }
968    }
969    }
970    }
971    }
972  33 argParser.setStructureFilename(null);
973    }
974    }
975    }
976   
977  153 if (af == null)
978    {
979  0 af = afMap.get(id);
980    }
981    // many of jalview's format/layout methods are only thread safe on the
982    // swingworker thread.
983    // all these methods should be on the alignViewController so it can
984    // coordinate such details
985  153 if (headless)
986    {
987  31 af.showOrHideAnnotations(showSSAnnotations, showAnnotations,
988    hideTFrows);
989    }
990    else
991    {
992  122 try
993    {
994  122 AlignFrame _af = af;
995  122 final boolean _showSSAnnotations = showSSAnnotations;
996  122 final boolean _showAnnotations = showAnnotations;
997  122 final boolean _hideTFrows = hideTFrows;
998  122 SwingUtilities.invokeAndWait(() -> {
999  118 _af.showOrHideAnnotations(_showSSAnnotations, _showAnnotations,
1000    _hideTFrows);
1001    }
1002   
1003    );
1004    } catch (Exception x)
1005    {
1006  0 Console.warn(
1007    "Unexpected exception adjusting annotation row visibility.",
1008    x);
1009    }
1010    }
1011   
1012  149 if (wrap)
1013    {
1014  0 if (af == null)
1015    {
1016  0 af = afMap.get(id);
1017    }
1018  0 if (af != null)
1019    {
1020  0 af.setWrapFormat(wrap, true);
1021    }
1022    }
1023   
1024    /*
1025    boolean doShading = avm.getBoolean(Arg.TEMPFAC_SHADING);
1026    if (doShading)
1027    {
1028    AlignFrame af = afMap.get(id);
1029    for (AlignmentAnnotation aa : af.alignPanel.getAlignment()
1030    .findAnnotation(PDBChain.class.getName().toString()))
1031    {
1032    AnnotationColourGradient acg = new AnnotationColourGradient(aa,
1033    af.alignPanel.av.getGlobalColourScheme(), 0);
1034    acg.setSeqAssociated(true);
1035    af.changeColour(acg);
1036    Console.info("Changed colour " + acg.toString());
1037    }
1038    }
1039    */
1040   
1041  149 return theseArgsWereParsed && !isError;
1042    }
1043   
 
1044  149 toggle protected void processGroovyScript(String id)
1045    {
1046  149 ArgValuesMap avm = argParser.getLinkedArgs(id);
1047  149 AlignFrame af = afMap.get(id);
1048   
1049  149 if (avm != null && !avm.containsArg(Arg.GROOVY))
1050    {
1051    // nothing to do
1052  149 return;
1053    }
1054   
1055  0 if (af == null)
1056    {
1057  0 addWarn("Groovy script does not have an alignment window. Proceeding with caution!");
1058    }
1059   
1060  0 if (avm.containsArg(Arg.GROOVY))
1061    {
1062  0 for (ArgValue groovyAv : avm.getArgValueList(Arg.GROOVY))
1063    {
1064  0 String groovyscript = groovyAv.getValue();
1065  0 if (groovyscript != null)
1066    {
1067    // Execute the groovy script after we've done all the rendering stuff
1068    // and before any images or figures are generated.
1069  0 Console.info("Executing script " + groovyscript);
1070  0 Jalview.getInstance().executeGroovyScript(groovyscript, af);
1071    }
1072    }
1073    }
1074    }
1075   
 
1076  149 toggle protected boolean processImages(String id)
1077    {
1078  149 ArgValuesMap avm = argParser.getLinkedArgs(id);
1079  149 AlignFrame af = afMap.get(id);
1080   
1081  149 if (avm != null && !avm.containsArg(Arg.IMAGE))
1082    {
1083    // nothing to do
1084  126 return true;
1085    }
1086   
1087  23 if (af == null)
1088    {
1089  0 addWarn("Do not have an alignment window to create image from (id="
1090    + id + "). Not proceeding.");
1091  0 return false;
1092    }
1093   
1094  23 Boolean isError = Boolean.valueOf(false);
1095  23 if (avm.containsArg(Arg.IMAGE))
1096    {
1097  23 for (ArgValue imageAv : avm.getArgValueList(Arg.IMAGE))
1098    {
1099  23 String val = imageAv.getValue();
1100  23 SubVals imageSubVals = imageAv.getSubVals();
1101  23 String fileName = imageSubVals.getContent();
1102  23 File file = new File(fileName);
1103  23 String name = af.getName();
1104  23 String renderer = avm.getValueFromSubValOrArg(imageAv,
1105    Arg.TEXTRENDERER, imageSubVals);
1106  23 if (renderer == null)
1107  23 renderer = "text";
1108  23 String type = "png"; // default
1109   
1110  23 String scale = avm.getValueFromSubValOrArg(imageAv, Arg.SCALE,
1111    imageSubVals);
1112  23 String width = avm.getValueFromSubValOrArg(imageAv, Arg.WIDTH,
1113    imageSubVals);
1114  23 String height = avm.getValueFromSubValOrArg(imageAv, Arg.HEIGHT,
1115    imageSubVals);
1116  23 BitmapImageSizing userBis = ImageMaker
1117    .parseScaleWidthHeightStrings(scale, width, height);
1118   
1119  23 type = avm.getValueFromSubValOrArg(imageAv, Arg.TYPE, imageSubVals);
1120  23 if (type == null && fileName != null)
1121    {
1122  23 for (String ext : new String[] { "svg", "png", "html", "eps" })
1123    {
1124  92 if (fileName.toLowerCase(Locale.ROOT).endsWith("." + ext))
1125    {
1126  23 type = ext;
1127    }
1128    }
1129    }
1130    // for moment we disable JSON export
1131  23 Cache.setPropsAreReadOnly(true);
1132  23 Cache.setProperty("EXPORT_EMBBED_BIOJSON", "false");
1133   
1134  23 String imageColour = avm.getValueFromSubValOrArg(imageAv,
1135    Arg.IMAGECOLOUR, imageSubVals);
1136  23 ColourSchemeI originalColourScheme = this.getColourScheme(af);
1137  23 this.colourAlignFrame(af, imageColour);
1138   
1139  23 Console.info("Writing " + file);
1140   
1141  23 boolean success = checksBeforeWritingToFile(avm, imageSubVals,
1142    false, fileName, "image", isError);
1143  23 if (!success)
1144    {
1145  0 continue;
1146    }
1147   
1148  23 try
1149    {
1150  23 switch (type)
1151    {
1152   
1153  1 case "svg":
1154  1 Console.debug("Outputting type '" + type + "' to " + fileName);
1155  1 af.createSVG(file, renderer);
1156  1 break;
1157   
1158  16 case "png":
1159  16 Console.debug("Outputting type '" + type + "' to " + fileName);
1160  16 af.createPNG(file, null, userBis);
1161  16 break;
1162   
1163  1 case "html":
1164  1 Console.debug("Outputting type '" + type + "' to " + fileName);
1165  1 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1166  1 htmlSVG.exportHTML(fileName, renderer);
1167  1 break;
1168   
1169  0 case "biojs":
1170  0 Console.debug(
1171    "Outputting BioJS MSA Viwer HTML file: " + fileName);
1172  0 try
1173    {
1174  0 BioJsHTMLOutput.refreshVersionInfo(
1175    BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
1176    } catch (URISyntaxException e)
1177    {
1178  0 e.printStackTrace();
1179    }
1180  0 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
1181  0 bjs.exportHTML(fileName);
1182  0 break;
1183   
1184  5 case "eps":
1185  5 Console.debug("Outputting EPS file: " + fileName);
1186  5 af.createEPS(file, renderer);
1187  5 break;
1188   
1189  0 case "imagemap":
1190  0 Console.debug("Outputting ImageMap file: " + fileName);
1191  0 af.createImageMap(file, name);
1192  0 break;
1193   
1194  0 default:
1195  0 addWarn(Arg.IMAGE.argString() + " type '" + type
1196    + "' not known. Ignoring");
1197  0 break;
1198    }
1199    } catch (Exception ioex)
1200    {
1201  0 addError("Unexpected error during export to '" + fileName + "'",
1202    ioex);
1203  0 isError = true;
1204    }
1205   
1206  23 this.colourAlignFrame(af, originalColourScheme);
1207    }
1208    }
1209  23 return !isError;
1210    }
1211   
 
1212  149 toggle protected boolean processOutput(String id)
1213    {
1214  149 ArgValuesMap avm = argParser.getLinkedArgs(id);
1215  149 AlignFrame af = afMap.get(id);
1216   
1217  149 if (avm != null && !avm.containsArg(Arg.OUTPUT))
1218    {
1219    // nothing to do
1220  75 return true;
1221    }
1222   
1223  74 if (af == null)
1224    {
1225  0 addWarn("Do not have an alignment window (id=" + id
1226    + "). Not proceeding.");
1227  0 return false;
1228    }
1229   
1230  74 Boolean isError = Boolean.valueOf(false);
1231   
1232  74 if (avm.containsArg(Arg.OUTPUT))
1233    {
1234  74 for (ArgValue av : avm.getArgValueList(Arg.OUTPUT))
1235    {
1236  74 String val = av.getValue();
1237  74 SubVals subVals = av.getSubVals();
1238  74 String fileName = subVals.getContent();
1239  74 boolean stdout = ArgParser.STDOUTFILENAME.equals(fileName);
1240  74 File file = new File(fileName);
1241   
1242  74 String name = af.getName();
1243  74 String format = avm.getValueFromSubValOrArg(av, Arg.FORMAT,
1244    subVals);
1245  74 FileFormats ffs = FileFormats.getInstance();
1246  74 List<String> validFormats = ffs.getWritableFormats(false);
1247   
1248  74 FileFormatI ff = null;
1249  74 if (format == null && fileName != null)
1250    {
1251  71 FORMAT: for (String fname : validFormats)
1252    {
1253  374 FileFormatI tff = ffs.forName(fname);
1254  374 String[] extensions = tff.getExtensions().split(",");
1255  374 for (String ext : extensions)
1256    {
1257  664 if (fileName.toLowerCase(Locale.ROOT).endsWith("." + ext))
1258    {
1259  62 ff = tff;
1260  62 format = ff.getName();
1261  62 break FORMAT;
1262    }
1263    }
1264    }
1265    }
1266  74 if (ff == null && format != null)
1267    {
1268  3 ff = ffs.forName(format);
1269    }
1270  74 if (ff == null)
1271    {
1272  9 if (stdout)
1273    {
1274  9 ff = FileFormat.Fasta;
1275    }
1276    else
1277    {
1278  0 StringBuilder validSB = new StringBuilder();
1279  0 for (String f : validFormats)
1280    {
1281  0 if (validSB.length() > 0)
1282  0 validSB.append(", ");
1283  0 validSB.append(f);
1284  0 FileFormatI tff = ffs.forName(f);
1285  0 validSB.append(" (");
1286  0 validSB.append(tff.getExtensions());
1287  0 validSB.append(")");
1288    }
1289   
1290  0 addError("No valid format specified for "
1291    + Arg.OUTPUT.argString() + ". Valid formats are "
1292    + validSB.toString() + ".");
1293  0 continue;
1294    }
1295    }
1296   
1297  74 boolean success = checksBeforeWritingToFile(avm, subVals, true,
1298    fileName, ff.getName(), isError);
1299  74 if (!success)
1300    {
1301  0 continue;
1302    }
1303   
1304  74 boolean backups = avm.getFromSubValArgOrPref(Arg.BACKUPS, subVals,
1305  74 null, Platform.isHeadless() ? null : BackupFiles.ENABLED,
1306    !Platform.isHeadless());
1307   
1308  74 Console.info("Writing " + fileName);
1309   
1310  74 af.saveAlignment(fileName, ff, stdout, backups);
1311  74 if (af.isSaveAlignmentSuccessful())
1312    {
1313  74 Console.debug("Written alignment '" + name + "' in "
1314    + ff.getName() + " format to '" + file + "'");
1315    }
1316    else
1317    {
1318  0 addError("Error writing file '" + file + "' in " + ff.getName()
1319    + " format!");
1320  0 isError = true;
1321  0 continue;
1322    }
1323   
1324    }
1325    }
1326  74 return !isError;
1327    }
1328   
 
1329  42 toggle private SequenceI getSpecifiedSequence(AlignFrame af, ArgValuesMap avm,
1330    ArgValue av)
1331    {
1332  42 SubVals subVals = av.getSubVals();
1333  42 ArgValue idAv = avm.getClosestNextArgValueOfArg(av, Arg.SEQID, true);
1334  42 SequenceI seq = null;
1335  42 if (subVals == null && idAv == null)
1336  0 return null;
1337  42 if (af == null || af.getCurrentView() == null)
1338    {
1339  0 return null;
1340    }
1341  42 AlignmentI al = af.getCurrentView().getAlignment();
1342  42 if (al == null)
1343    {
1344  0 return null;
1345    }
1346  42 if (subVals != null)
1347    {
1348  42 if (subVals.has(Arg.SEQID.getName()))
1349    {
1350  11 seq = al.findName(subVals.get(Arg.SEQID.getName()));
1351    }
1352  31 else if (-1 < subVals.getIndex()
1353    && subVals.getIndex() < al.getSequences().size())
1354    {
1355  0 seq = al.getSequenceAt(subVals.getIndex());
1356    }
1357    }
1358  42 if (seq == null && idAv != null)
1359    {
1360  15 seq = al.findName(idAv.getValue());
1361    }
1362  42 return seq;
1363    }
1364   
 
1365  0 toggle public AlignFrame[] getAlignFrames()
1366    {
1367  0 AlignFrame[] afs = null;
1368  0 if (afMap != null)
1369    {
1370  0 afs = (AlignFrame[]) afMap.values().toArray();
1371    }
1372   
1373  0 return afs;
1374    }
1375   
 
1376  39 toggle private void colourAlignFrame(AlignFrame af, String colour)
1377    {
1378    // use string "none" to remove colour scheme
1379  39 if (colour != null && "" != colour)
1380    {
1381  16 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
1382    af.getViewport(), af.getViewport().getAlignment(), colour);
1383  16 if (cs == null && !StringUtils.equalsIgnoreCase(colour, "none"))
1384    {
1385  0 addWarn("Couldn't parse '" + colour + "' as a colourscheme.");
1386    }
1387    else
1388    {
1389  16 Jalview.testoutput(argParser, Arg.COLOUR, "zappo", colour);
1390  16 colourAlignFrame(af, cs);
1391    }
1392    }
1393    }
1394   
 
1395  39 toggle private void colourAlignFrame(AlignFrame af, ColourSchemeI cs)
1396    {
1397  39 try
1398    {
1399  39 SwingUtilities.invokeAndWait(new Runnable()
1400    {
 
1401  39 toggle @Override
1402    public void run()
1403    {
1404    // Note that cs == null removes colour scheme from af
1405  39 af.changeColour(cs);
1406    }
1407    });
1408    } catch (Exception x)
1409    {
1410  0 Console.trace("Interrupted whilst waiting for colorAlignFrame action",
1411    x);
1412   
1413    }
1414    }
1415   
 
1416  23 toggle private ColourSchemeI getColourScheme(AlignFrame af)
1417    {
1418  23 return af.getViewport().getGlobalColourScheme();
1419    }
1420   
 
1421  0 toggle private void addInfo(String errorMessage)
1422    {
1423  0 Console.info(errorMessage);
1424  0 errors.add(errorMessage);
1425    }
1426   
 
1427  0 toggle private void addWarn(String errorMessage)
1428    {
1429  0 Console.warn(errorMessage);
1430  0 errors.add(errorMessage);
1431    }
1432   
 
1433  0 toggle private void addError(String errorMessage)
1434    {
1435  0 addError(errorMessage, null);
1436    }
1437   
 
1438  0 toggle private void addError(String errorMessage, Exception e)
1439    {
1440  0 Console.error(errorMessage, e);
1441  0 errors.add(errorMessage);
1442    }
1443   
 
1444  97 toggle private boolean checksBeforeWritingToFile(ArgValuesMap avm,
1445    SubVals subVal, boolean includeBackups, String filename,
1446    String adjective, Boolean isError)
1447    {
1448  97 File file = new File(filename);
1449   
1450  97 boolean overwrite = avm.getFromSubValArgOrPref(Arg.OVERWRITE, subVal,
1451    null, "OVERWRITE_OUTPUT", false);
1452  97 boolean stdout = false;
1453  97 boolean backups = false;
1454  97 if (includeBackups)
1455    {
1456  74 stdout = ArgParser.STDOUTFILENAME.equals(filename);
1457    // backups. Use the Arg.BACKUPS or subval "backups" setting first,
1458    // otherwise if headless assume false, if not headless use the user
1459    // preference with default true.
1460  74 backups = avm.getFromSubValArgOrPref(Arg.BACKUPS, subVal, null,
1461  74 Platform.isHeadless() ? null : BackupFiles.ENABLED,
1462    !Platform.isHeadless());
1463    }
1464   
1465  97 if (file.exists() && !(overwrite || backups || stdout))
1466    {
1467  0 addWarn("Won't overwrite file '" + filename + "' without "
1468    + Arg.OVERWRITE.argString()
1469  0 + (includeBackups ? " or " + Arg.BACKUPS.argString() : "")
1470    + " set");
1471  0 return false;
1472    }
1473   
1474  97 boolean mkdirs = avm.getFromSubValArgOrPref(Arg.MKDIRS, subVal, null,
1475    "MKDIRS_OUTPUT", false);
1476   
1477  97 if (!FileUtils.checkParentDir(file, mkdirs))
1478    {
1479  0 addError("Directory '"
1480    + FileUtils.getParentDir(file).getAbsolutePath()
1481    + "' does not exist for " + adjective + " file '" + filename
1482    + "'."
1483  0 + (mkdirs ? "" : " Try using " + Arg.MKDIRS.argString()));
1484  0 isError = true;
1485  0 return false;
1486    }
1487   
1488  97 return true;
1489    }
1490   
 
1491  104 toggle public List<String> getErrors()
1492    {
1493  104 return errors;
1494    }
1495   
 
1496  133 toggle public String errorsToString()
1497    {
1498  133 StringBuilder sb = new StringBuilder();
1499  133 for (String error : errors)
1500    {
1501  0 if (sb.length() > 0)
1502  0 sb.append("\n");
1503  0 sb.append("- " + error);
1504    }
1505  133 return sb.toString();
1506    }
1507    }