Clover icon

Coverage Report

  1. Project Clover database Wed Dec 3 2025 16:47:11 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,508
1,193
199
0.36
23.96
23
8.65

Classes

Class Line # Actions
Commands 85 551 199
0.703931270.4%
 

Contributing tests

This file is covered by 70 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  148 toggle public Commands(ArgParser argparser, boolean headless)
106    {
107  148 this(Desktop.instance, argparser, headless);
108    }
109   
 
110  148 toggle public Commands(Desktop d, ArgParser argparser, boolean h)
111    {
112  148 argParser = argparser;
113  148 headless = h;
114  148 desktop = d;
115  148 afMap = new HashMap<>();
116    }
117   
 
118  148 toggle protected boolean processArgs()
119    {
120  148 if (argParser == null)
121    {
122  0 return true;
123    }
124   
125  148 boolean theseArgsWereParsed = false;
126   
127  148 if (argParser != null && argParser.getLinkedIds() != null)
128    {
129  148 for (String id : argParser.getLinkedIds())
130    {
131  168 ArgValuesMap avm = argParser.getLinkedArgs(id);
132  168 theseArgsWereParsed = true;
133  168 boolean processLinkedOkay = processLinked(id);
134  164 theseArgsWereParsed &= processLinkedOkay;
135   
136  164 processGroovyScript(id);
137   
138    // wait around until alignFrame isn't busy
139  164 AlignFrame af = afMap.get(id);
140  626 while (af != null && af.getViewport().isCalcInProgress())
141    {
142  462 try
143    {
144  462 Thread.sleep(25);
145    } catch (Exception q)
146    {
147    }
148  462 ;
149    }
150   
151  164 theseArgsWereParsed &= processImages(id);
152   
153  164 if (processLinkedOkay)
154    {
155  164 theseArgsWereParsed &= processOutput(id);
156    }
157   
158    // close ap
159  164 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  144 String errorsRaised = errorsToString();
174  144 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  144 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  143 argsWereParsed = theseArgsWereParsed;
190  143 return argsWereParsed;
191    }
192   
 
193  13 toggle public boolean commandArgsProvided()
194    {
195  13 return commandArgsProvided;
196    }
197   
 
198  155 toggle public boolean argsWereParsed()
199    {
200  155 return argsWereParsed;
201    }
202   
 
203  168 toggle protected boolean processLinked(String id)
204    {
205  168 boolean theseArgsWereParsed = false;
206  168 ArgValuesMap avm = argParser.getLinkedArgs(id);
207  168 if (avm == null)
208    {
209  0 return true;
210    }
211   
212  168 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  168 boolean wrap = false;
217  168 boolean showSSAnnotations = false;
218  168 boolean showAnnotations = false;
219  168 boolean hideTFrows = false;
220  168 AlignFrame af = null;
221   
222  168 if (avm.containsArg(Arg.APPEND) || avm.containsArg(Arg.OPEN))
223    {
224  168 commandArgsProvided = true;
225  168 final long progress = System.currentTimeMillis();
226   
227  168 boolean first = true;
228  168 boolean progressBarSet = false;
229    // Combine the APPEND and OPEN files into one list, along with whether it
230    // was APPEND or OPEN
231  168 List<ArgValue> openAvList = new ArrayList<>();
232  168 openAvList.addAll(avm.getArgValueList(Arg.OPEN));
233  168 openAvList.addAll(avm.getArgValueList(Arg.APPEND));
234    // sort avlist based on av.getArgIndex()
235  168 Collections.sort(openAvList);
236  168 for (ArgValue av : openAvList)
237    {
238  189 Arg a = av.getArg();
239  189 SubVals sv = av.getSubVals();
240  189 String openFile0 = av.getValue();
241  189 String openFile = HttpUtils.equivalentJalviewUrl(openFile0);
242  189 if (openFile == null)
243  0 continue;
244   
245  189 theseArgsWereParsed = true;
246  189 if (first)
247    {
248  168 first = false;
249  168 if (!headless && desktop != null)
250    {
251  130 SwingUtilities.invokeLater(new Runnable()
252    {
 
253  130 toggle @Override
254    public void run()
255    {
256  130 desktop.setProgressBar(
257    MessageManager.getString(
258    "status.processing_commandline_args"),
259    progress);
260   
261    }
262    });
263  130 progressBarSet = true;
264    }
265    }
266   
267  189 if (!Platform.isJS())
268    /**
269    * ignore in JavaScript -- can't just file existence - could load it?
270    *
271    * @j2sIgnore
272    */
273    {
274  189 if (!HttpUtils.isPlausibleUri(openFile))
275    {
276  186 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  189 DataSourceType protocol = AppletFormatAdapter
286    .checkProtocol(openFile);
287   
288  189 FileFormatI format = null;
289  189 try
290    {
291  189 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  189 af = afMap.get(id);
306    // When to open a new AlignFrame
307  189 if (af == null || "true".equals(av.getSubVal("new"))
308    || a == Arg.OPEN || format == FileFormat.Jalview)
309    {
310  169 if (a == Arg.OPEN)
311    {
312  145 Jalview.testoutput(argParser, Arg.OPEN, "examples/uniref50.fa",
313    openFile);
314    }
315   
316  169 Console.debug(
317    "Opening '" + openFile + "' in new alignment frame");
318  169 FileLoader fileLoader = new FileLoader(!headless);
319  169 boolean xception = false;
320  169 try
321    {
322  169 af = fileLoader.LoadFileWaitTillLoaded(openFile, protocol,
323    format);
324  165 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  165 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  165 String colour = null;
348  165 if (avm.containsArg(Arg.COLOUR)
349    || !(format == FileFormat.Jalview))
350    {
351  165 colour = avm.getFromSubValArgOrPref(av, Arg.COLOUR, sv, null,
352    "DEFAULT_COLOUR_PROT", null);
353    }
354  165 if (colour != null)
355    {
356  16 this.colourAlignFrame(af, colour);
357    }
358   
359    // Change alignment frame title
360  165 String title = avm.getFromSubValArgOrPref(av, Arg.TITLE, sv, null,
361    null, null);
362  165 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  165 List<String> featuresfiles = avm
370    .getValuesFromSubValOrArgs(argParser, Arg.FEATURES, sv);
371  165 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  165 List<String> annotationsfiles = avm.getValuesFromSubValOrArgs(
384    argParser, Arg.ANNOTATIONS, sv);
385  165 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  165 boolean sortbytree = avm.getBoolFromSubValOrArg(Arg.SORTBYTREE,
398    sv);
399  165 if (sortbytree)
400    {
401  1 af.getViewport().setSortByTree(true);
402  1 Jalview.testoutput(argParser, Arg.SORTBYTREE);
403    }
404   
405    // Load tree from file
406  165 String treefile = avm.getValueFromSubValOrArg(av, Arg.TREE, sv);
407  165 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  165 showSSAnnotations = avm.getFromSubValArgOrPref(
426    Arg.SHOWSSANNOTATIONS, av.getSubVals(), null,
427    "STRUCT_FROM_PDB", true);
428    // Show sequence annotations?
429  165 showAnnotations = avm.getFromSubValArgOrPref(Arg.SHOWANNOTATIONS,
430    av.getSubVals(), null, "SHOW_ANNOTATIONS", true);
431    // hide the Temperature Factor row?
432  165 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  165 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  165 afMap.put(id, af);
445   
446    // is it its own structure file?
447  165 if (format.isStructureFile())
448    {
449  2 StructureSelectionManager ssm = StructureSelectionManager
450    .getStructureSelectionManager(Desktop.instance);
451  2 SequenceI seq = af.alignPanel.getAlignment().getSequenceAt(0);
452  2 ssm.computeMapping(false, new SequenceI[] { seq }, null,
453    openFile, DataSourceType.FILE, null, null, null, false);
454    }
455    }
456    else
457    {
458  20 Console.debug(
459    "Opening '" + openFile + "' in existing alignment frame");
460   
461  20 DataSourceType dst = HttpUtils.startsWithHttpOrHttps(openFile)
462    ? DataSourceType.URL
463    : DataSourceType.FILE;
464   
465  20 FileLoader fileLoader = new FileLoader(!headless);
466  20 fileLoader.LoadFile(af.getCurrentView(), openFile, dst, null,
467    false);
468    }
469   
470  185 Console.debug("Command " + Arg.APPEND + " executed successfully!");
471   
472    }
473  164 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  164 if (progressBarSet && desktop != null)
486  126 desktop.setProgressBar(null, progress);
487   
488    }
489   
490    // open the structure (from same PDB file or given PDBfile)
491  164 if (!avm.getBoolean(Arg.NOSTRUCTURE))
492    {
493  164 if (af == null)
494    {
495  0 af = afMap.get(id);
496    }
497   
498    // STRUCTURESFILES
499    // we oo through --structuresfiles first
500  164 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  164 if (avm.containsArg(Arg.STRUCTURE))
558    {
559  37 commandArgsProvided = true;
560   
561    // Settings "global" to this AVM
562  37 String ALLSTRUCTURESVIEWERID = avm
563    .getValue(Arg.ALLSTRUCTURESVIEWERID);
564   
565  37 Boolean SUPERPOSE = null;
566  37 if (avm.containsArg(Arg.SUPERPOSE))
567    {
568  6 SUPERPOSE = avm.getBoolean(Arg.SUPERPOSE);
569    }
570   
571  37 StructureViewer structureViewer = null;
572  37 for (ArgValue structureAv : avm.getArgValueList(Arg.STRUCTURE))
573    {
574  59 argParser.setStructureFilename(null);
575  59 String val = structureAv.getValue();
576  59 SubVals subVals = structureAv.getSubVals();
577  59 SequenceI seq = getSpecifiedSequence(af, avm, structureAv);
578  59 if (seq == null)
579    {
580    // Could not find sequence from subId, let's assume the first
581    // sequence in the alignframe
582  26 AlignmentI al = af.getCurrentView().getAlignment();
583  26 seq = al.getSequenceAt(0);
584    }
585   
586  59 if (seq == null)
587    {
588  0 addWarn("Could not find sequence for argument "
589    + Arg.STRUCTURE.argString() + "=" + val);
590  0 continue;
591    }
592  59 String structureLocationRef = null;
593  59 DataSourceType structureLocationType = null;
594  59 if (subVals.getContent() != null
595    && subVals.getContent().length() != 0)
596    {
597  59 structureLocationRef = subVals.getContent();
598  59 structureLocationType = AppletFormatAdapter
599    .checkProtocol(structureLocationRef);
600  59 if (DataSourceType.FILE.equals(structureLocationType))
601    {
602  56 structureLocationRef = new File(structureLocationRef)
603    .getAbsolutePath();
604    }
605  59 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  59 if (structureLocationRef == null)
637    {
638  0 addWarn("No provided structure file with '" + val + "'");
639  0 continue;
640    }
641   
642  59 if (structureLocationType == null)
643    {
644  0 addWarn("Could not determine structure fetch protocol for '"
645    + val + "'");
646  0 continue;
647    }
648   
649  59 argParser.setStructureFilename(structureLocationRef);
650   
651    // open structure view
652  59 AlignmentPanel ap = af.alignPanel;
653  59 if (headless)
654    {
655  10 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  59 String viewerid = ALLSTRUCTURESVIEWERID;
662  59 if (viewerid == null)
663    {
664  59 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  59 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  59 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  59 String tftString = avm.getFromSubValArgOrPrefWithSubstitutions(
683    argParser, Arg.TEMPFAC, ArgValuesMap.Position.AFTER,
684    structureAv, subVals, null, null, null);
685  59 boolean notempfac = avm.getFromSubValArgOrPref(Arg.NOTEMPFAC,
686    subVals, null, "ADD_TEMPFACT_ANN", false, true);
687  59 TFType tft = notempfac ? null : TFType.DEFAULT;
688  59 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  59 boolean superpose = SUPERPOSE != null ? SUPERPOSE
716    : avm.getBoolFromSubVal(Arg.SUPERPOSE, subVals,
717    Cache.getDefault(StructureChooser.AUTOSUPERIMPOSE,
718    true));
719   
720  59 String sViewerType = avm.getFromSubValArgOrPref(
721    Arg.STRUCTUREVIEWER, ArgValuesMap.Position.AFTER,
722    structureAv, subVals, null, null, "jmol");
723  59 ViewerType viewerType = ViewerType.getFromString(sViewerType);
724   
725  59 StructureViewer thisStructureViewer = null;
726  59 if (sViewerType.equals(PREVIOUSSTRUCTUREVIEWER)
727    && structureViewer != null)
728    {
729  0 thisStructureViewer = structureViewer;
730    }
731  59 else if (viewerid != null && svMap.containsKey(viewerid))
732    {
733  5 thisStructureViewer = svMap.get(viewerid);
734    }
735    // TODO use ssFromStructure
736  59 if (thisStructureViewer == null)
737    {
738   
739  54 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  54 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  59 structureViewer = thisStructureViewer;
764   
765  59 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  50 try
775    {
776  50 long tries = 1000;
777  471 while (structureViewer.isBusy() && tries > 0)
778    {
779  421 Thread.sleep(25);
780  421 if (structureViewer.isBusy())
781    {
782  371 tries--;
783  371 Console.debug(
784    "Waiting for viewer for " + structureLocationRef);
785    }
786    }
787  50 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  50 Console.debug(
801    "Successfully opened viewer for " + structureLocationRef);
802   
803  50 if (avm.containsArg(Arg.STRUCTUREIMAGE))
804    {
805  10 for (ArgValue structureImageArgValue : avm
806    .getArgValueListFromSubValOrArg(structureAv,
807    Arg.STRUCTUREIMAGE, subVals))
808    {
809  10 String structureImageFilename = argParser.makeSubstitutions(
810    structureImageArgValue.getValue(), id, true);
811  10 if (structureViewer != null && structureImageFilename != null)
812    {
813  10 SubVals structureImageSubVals = null;
814  10 structureImageSubVals = structureImageArgValue.getSubVals();
815  10 File structureImageFile = new File(structureImageFilename);
816  10 String width = avm.getValueFromSubValOrArg(
817    structureImageArgValue, Arg.WIDTH,
818    structureImageSubVals);
819  10 String height = avm.getValueFromSubValOrArg(
820    structureImageArgValue, Arg.HEIGHT,
821    structureImageSubVals);
822  10 String scale = avm.getValueFromSubValOrArg(
823    structureImageArgValue, Arg.SCALE,
824    structureImageSubVals);
825  10 String renderer = avm.getValueFromSubValOrArg(
826    structureImageArgValue, Arg.TEXTRENDERER,
827    structureImageSubVals);
828  10 String typeS = avm.getValueFromSubValOrArg(
829    structureImageArgValue, Arg.TYPE,
830    structureImageSubVals);
831  10 if (typeS == null || typeS.length() == 0)
832    {
833  10 typeS = FileUtils.getExtension(structureImageFile);
834    }
835  10 TYPE imageType;
836  10 try
837    {
838  10 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  10 BitmapImageSizing userBis = ImageMaker
847    .parseScaleWidthHeightStrings(scale, width, height);
848   
849    /////
850    // DON'T TRY TO EXPORT IF VIEWER IS UNSUPPORTED
851  10 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  10 String imageColour = avm.getValueFromSubValOrArg(
863    structureImageArgValue, Arg.IMAGECOLOUR,
864    structureImageSubVals);
865  10 ColourSchemeI originalColourScheme = this
866    .getColourScheme(af);
867  10 this.colourAlignFrame(af, imageColour);
868   
869    /////
870    // custom image background colour
871   
872  10 String bgcolourstring = avm.getValueFromSubValOrArg(
873    structureImageArgValue, Arg.BGCOLOUR,
874    structureImageSubVals);
875  10 Color bgcolour = null;
876  10 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  10 JalviewStructureDisplayI sview = structureViewer
888    .getJalviewStructureDisplay();
889   
890  10 File sessionToRestore = null;
891   
892  10 List<StructureCommandI> extraCommands = new ArrayList<>();
893   
894  10 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  10 if (bgcolour != null)
910    {
911  0 sview.getBinding().setBackgroundColour(bgcolour);
912    }
913   
914  10 sview.getBinding().executeCommands(extraCommands, false,
915    "Executing Custom Commands");
916   
917    // and export the view as an image
918  10 boolean success = this.checksBeforeWritingToFile(avm,
919    subVals, false, structureImageFilename,
920    "structure image", isError);
921   
922  10 if (!success)
923    {
924  0 continue;
925    }
926  10 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  10 try
933    {
934    // We don't expect class cast exception
935  10 AppJmol jmol = (AppJmol) sview;
936  10 jmol.makePDBImage(structureImageFile, imageType, renderer,
937    userBis);
938  10 Console.info("Exported structure image to "
939    + structureImageFile);
940   
941    // RESTORE SESSION AFTER EXPORT IF NEED BE
942  10 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  10 try
960    {
961  10 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  50 argParser.setStructureFilename(null);
973    }
974    }
975    }
976   
977  164 if (af == null)
978   
979    {
980  0 af = afMap.get(id);
981    }
982    // many of jalview's format/layout methods are only thread safe on the
983    // swingworker thread.
984    // all these methods should be on the alignViewController so it can
985    // coordinate such details
986  164 if (headless)
987    {
988  38 af.showOrHideAnnotations(showSSAnnotations, showAnnotations,
989    hideTFrows);
990    }
991    else
992    {
993  126 try
994    {
995  126 AlignFrame _af = af;
996  126 final boolean _showSSAnnotations = showSSAnnotations;
997  126 final boolean _showAnnotations = showAnnotations;
998  126 final boolean _hideTFrows = hideTFrows;
999  126 SwingUtilities.invokeAndWait(() -> {
1000  126 _af.showOrHideAnnotations(_showSSAnnotations, _showAnnotations,
1001    _hideTFrows);
1002    }
1003   
1004    );
1005    } catch (Exception x)
1006    {
1007  0 Console.warn(
1008    "Unexpected exception adjusting annotation row visibility.",
1009    x);
1010    }
1011    }
1012   
1013  164 if (wrap)
1014    {
1015  0 if (af == null)
1016    {
1017  0 af = afMap.get(id);
1018    }
1019  0 if (af != null)
1020    {
1021  0 af.setWrapFormat(wrap, true);
1022    }
1023    }
1024   
1025    /*
1026    boolean doShading = avm.getBoolean(Arg.TEMPFAC_SHADING);
1027    if (doShading)
1028    {
1029    AlignFrame af = afMap.get(id);
1030    for (AlignmentAnnotation aa : af.alignPanel.getAlignment()
1031    .findAnnotation(PDBChain.class.getName().toString()))
1032    {
1033    AnnotationColourGradient acg = new AnnotationColourGradient(aa,
1034    af.alignPanel.av.getGlobalColourScheme(), 0);
1035    acg.setSeqAssociated(true);
1036    af.changeColour(acg);
1037    Console.info("Changed colour " + acg.toString());
1038    }
1039    }
1040    */
1041   
1042  164 return theseArgsWereParsed && !isError;
1043    }
1044   
 
1045  164 toggle protected void processGroovyScript(String id)
1046    {
1047  164 ArgValuesMap avm = argParser.getLinkedArgs(id);
1048  164 AlignFrame af = afMap.get(id);
1049   
1050  164 if (avm != null && !avm.containsArg(Arg.GROOVY))
1051    {
1052    // nothing to do
1053  164 return;
1054    }
1055   
1056  0 if (af == null)
1057    {
1058  0 addWarn("Groovy script does not have an alignment window. Proceeding with caution!");
1059    }
1060   
1061  0 if (avm.containsArg(Arg.GROOVY))
1062    {
1063  0 for (ArgValue groovyAv : avm.getArgValueList(Arg.GROOVY))
1064    {
1065  0 String groovyscript = groovyAv.getValue();
1066  0 if (groovyscript != null)
1067    {
1068    // Execute the groovy script after we've done all the rendering stuff
1069    // and before any images or figures are generated.
1070  0 Console.info("Executing script " + groovyscript);
1071  0 Jalview.getInstance().executeGroovyScript(groovyscript, af);
1072    }
1073    }
1074    }
1075    }
1076   
 
1077  164 toggle protected boolean processImages(String id)
1078    {
1079  164 ArgValuesMap avm = argParser.getLinkedArgs(id);
1080  164 AlignFrame af = afMap.get(id);
1081   
1082  164 if (avm != null && !avm.containsArg(Arg.IMAGE))
1083    {
1084    // nothing to do
1085  134 return true;
1086    }
1087   
1088  30 if (af == null)
1089    {
1090  0 addWarn("Do not have an alignment window to create image from (id="
1091    + id + "). Not proceeding.");
1092  0 return false;
1093    }
1094   
1095  30 Boolean isError = Boolean.valueOf(false);
1096  30 if (avm.containsArg(Arg.IMAGE))
1097    {
1098  30 for (ArgValue imageAv : avm.getArgValueList(Arg.IMAGE))
1099    {
1100  30 String val = imageAv.getValue();
1101  30 SubVals imageSubVals = imageAv.getSubVals();
1102  30 String fileName = imageSubVals.getContent();
1103  30 File file = new File(fileName);
1104  30 String name = af.getName();
1105  30 String renderer = avm.getValueFromSubValOrArg(imageAv,
1106    Arg.TEXTRENDERER, imageSubVals);
1107  30 if (renderer == null)
1108  30 renderer = "text";
1109  30 String type = "png"; // default
1110   
1111  30 String scale = avm.getValueFromSubValOrArg(imageAv, Arg.SCALE,
1112    imageSubVals);
1113  30 String width = avm.getValueFromSubValOrArg(imageAv, Arg.WIDTH,
1114    imageSubVals);
1115  30 String height = avm.getValueFromSubValOrArg(imageAv, Arg.HEIGHT,
1116    imageSubVals);
1117  30 BitmapImageSizing userBis = ImageMaker
1118    .parseScaleWidthHeightStrings(scale, width, height);
1119   
1120  30 type = avm.getValueFromSubValOrArg(imageAv, Arg.TYPE, imageSubVals);
1121  30 if (type == null && fileName != null)
1122    {
1123  30 for (String ext : new String[] { "svg", "png", "html", "eps" })
1124    {
1125  120 if (fileName.toLowerCase(Locale.ROOT).endsWith("." + ext))
1126    {
1127  30 type = ext;
1128    }
1129    }
1130    }
1131    // for moment we disable JSON export
1132  30 Cache.setPropsAreReadOnly(true);
1133  30 Cache.setProperty("EXPORT_EMBBED_BIOJSON", "false");
1134   
1135  30 String imageColour = avm.getValueFromSubValOrArg(imageAv,
1136    Arg.IMAGECOLOUR, imageSubVals);
1137  30 ColourSchemeI originalColourScheme = this.getColourScheme(af);
1138  30 this.colourAlignFrame(af, imageColour);
1139   
1140  30 Console.info("Writing " + file);
1141   
1142  30 boolean success = checksBeforeWritingToFile(avm, imageSubVals,
1143    false, fileName, "image", isError);
1144  30 if (!success)
1145    {
1146  0 continue;
1147    }
1148   
1149  30 try
1150    {
1151  30 switch (type)
1152    {
1153   
1154  1 case "svg":
1155  1 Console.debug("Outputting type '" + type + "' to " + fileName);
1156  1 af.createSVG(file, renderer);
1157  1 break;
1158   
1159  23 case "png":
1160  23 Console.debug("Outputting type '" + type + "' to " + fileName);
1161  23 af.createPNG(file, null, userBis);
1162  23 break;
1163   
1164  1 case "html":
1165  1 Console.debug("Outputting type '" + type + "' to " + fileName);
1166  1 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1167  1 htmlSVG.exportHTML(fileName, renderer);
1168  1 break;
1169   
1170  0 case "biojs":
1171  0 Console.debug(
1172    "Outputting BioJS MSA Viwer HTML file: " + fileName);
1173  0 try
1174    {
1175  0 BioJsHTMLOutput.refreshVersionInfo(
1176    BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
1177    } catch (URISyntaxException e)
1178    {
1179  0 e.printStackTrace();
1180    }
1181  0 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
1182  0 bjs.exportHTML(fileName);
1183  0 break;
1184   
1185  5 case "eps":
1186  5 Console.debug("Outputting EPS file: " + fileName);
1187  5 af.createEPS(file, renderer);
1188  5 break;
1189   
1190  0 case "imagemap":
1191  0 Console.debug("Outputting ImageMap file: " + fileName);
1192  0 af.createImageMap(file, name);
1193  0 break;
1194   
1195  0 default:
1196  0 addWarn(Arg.IMAGE.argString() + " type '" + type
1197    + "' not known. Ignoring");
1198  0 break;
1199    }
1200    } catch (Exception ioex)
1201    {
1202  0 addError("Unexpected error during export to '" + fileName + "'",
1203    ioex);
1204  0 isError = true;
1205    }
1206   
1207  30 this.colourAlignFrame(af, originalColourScheme);
1208    }
1209    }
1210  30 return !isError;
1211    }
1212   
 
1213  164 toggle protected boolean processOutput(String id)
1214    {
1215  164 ArgValuesMap avm = argParser.getLinkedArgs(id);
1216  164 AlignFrame af = afMap.get(id);
1217   
1218  164 if (avm != null && !avm.containsArg(Arg.OUTPUT))
1219    {
1220    // nothing to do
1221  90 return true;
1222    }
1223   
1224  74 if (af == null)
1225    {
1226  0 addWarn("Do not have an alignment window (id=" + id
1227    + "). Not proceeding.");
1228  0 return false;
1229    }
1230   
1231  74 Boolean isError = Boolean.valueOf(false);
1232   
1233  74 if (avm.containsArg(Arg.OUTPUT))
1234    {
1235  74 for (ArgValue av : avm.getArgValueList(Arg.OUTPUT))
1236    {
1237  74 String val = av.getValue();
1238  74 SubVals subVals = av.getSubVals();
1239  74 String fileName = subVals.getContent();
1240  74 boolean stdout = ArgParser.STDOUTFILENAME.equals(fileName);
1241  74 File file = new File(fileName);
1242   
1243  74 String name = af.getName();
1244  74 String format = avm.getValueFromSubValOrArg(av, Arg.FORMAT,
1245    subVals);
1246  74 FileFormats ffs = FileFormats.getInstance();
1247  74 List<String> validFormats = ffs.getWritableFormats(false);
1248   
1249  74 FileFormatI ff = null;
1250  74 if (format == null && fileName != null)
1251    {
1252  71 FORMAT: for (String fname : validFormats)
1253    {
1254  365 FileFormatI tff = ffs.forName(fname);
1255  365 String[] extensions = tff.getExtensions().split(",");
1256  365 for (String ext : extensions)
1257    {
1258  655 if (fileName.toLowerCase(Locale.ROOT).endsWith("." + ext))
1259    {
1260  62 ff = tff;
1261  62 format = ff.getName();
1262  62 break FORMAT;
1263    }
1264    }
1265    }
1266    }
1267  74 if (ff == null && format != null)
1268    {
1269  3 ff = ffs.forName(format);
1270    }
1271  74 if (ff == null)
1272    {
1273  9 if (stdout)
1274    {
1275  9 ff = FileFormat.Fasta;
1276    }
1277    else
1278    {
1279  0 StringBuilder validSB = new StringBuilder();
1280  0 for (String f : validFormats)
1281    {
1282  0 if (validSB.length() > 0)
1283  0 validSB.append(", ");
1284  0 validSB.append(f);
1285  0 FileFormatI tff = ffs.forName(f);
1286  0 validSB.append(" (");
1287  0 validSB.append(tff.getExtensions());
1288  0 validSB.append(")");
1289    }
1290   
1291  0 addError("No valid format specified for "
1292    + Arg.OUTPUT.argString() + ". Valid formats are "
1293    + validSB.toString() + ".");
1294  0 continue;
1295    }
1296    }
1297   
1298  74 boolean success = checksBeforeWritingToFile(avm, subVals, true,
1299    fileName, ff.getName(), isError);
1300  74 if (!success)
1301    {
1302  0 continue;
1303    }
1304   
1305  74 boolean backups = avm.getFromSubValArgOrPref(Arg.BACKUPS, subVals,
1306  74 null, Platform.isHeadless() ? null : BackupFiles.ENABLED,
1307    !Platform.isHeadless());
1308   
1309  74 Console.info("Writing " + fileName);
1310   
1311  74 af.saveAlignment(fileName, ff, stdout, backups);
1312  74 if (af.isSaveAlignmentSuccessful())
1313    {
1314  74 Console.debug("Written alignment '" + name + "' in "
1315    + ff.getName() + " format to '" + file + "'");
1316    }
1317    else
1318    {
1319  0 addError("Error writing file '" + file + "' in " + ff.getName()
1320    + " format!");
1321  0 isError = true;
1322  0 continue;
1323    }
1324   
1325    }
1326    }
1327  74 return !isError;
1328    }
1329   
 
1330  59 toggle private SequenceI getSpecifiedSequence(AlignFrame af, ArgValuesMap avm,
1331    ArgValue av)
1332    {
1333  59 SubVals subVals = av.getSubVals();
1334  59 ArgValue idAv = avm.getClosestNextArgValueOfArg(av, Arg.SEQID, true);
1335  59 SequenceI seq = null;
1336  59 if (subVals == null && idAv == null)
1337  0 return null;
1338  59 if (af == null || af.getCurrentView() == null)
1339    {
1340  0 return null;
1341    }
1342  59 AlignmentI al = af.getCurrentView().getAlignment();
1343  59 if (al == null)
1344    {
1345  0 return null;
1346    }
1347  59 if (subVals != null)
1348    {
1349  59 if (subVals.has(Arg.SEQID.getName()))
1350    {
1351  11 seq = al.findName(subVals.get(Arg.SEQID.getName()));
1352    }
1353  48 else if (-1 < subVals.getIndex()
1354    && subVals.getIndex() < al.getSequences().size())
1355    {
1356  0 seq = al.getSequenceAt(subVals.getIndex());
1357    }
1358    }
1359  59 if (seq == null && idAv != null)
1360    {
1361  26 seq = al.findName(idAv.getValue());
1362    }
1363  59 return seq;
1364    }
1365   
 
1366  0 toggle public AlignFrame[] getAlignFrames()
1367    {
1368  0 AlignFrame[] afs = null;
1369  0 if (afMap != null)
1370    {
1371  0 afs = (AlignFrame[]) afMap.values().toArray();
1372    }
1373   
1374  0 return afs;
1375    }
1376   
 
1377  56 toggle private void colourAlignFrame(AlignFrame af, String colour)
1378    {
1379    // use string "none" to remove colour scheme
1380  56 if (colour != null && "" != colour)
1381    {
1382  16 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
1383    af.getViewport(), af.getViewport().getAlignment(), colour);
1384  16 if (cs == null && !StringUtils.equalsIgnoreCase(colour, "none"))
1385    {
1386  0 addWarn("Couldn't parse '" + colour + "' as a colourscheme.");
1387    }
1388    else
1389    {
1390  16 Jalview.testoutput(argParser, Arg.COLOUR, "zappo", colour);
1391  16 colourAlignFrame(af, cs);
1392    }
1393    }
1394    }
1395   
 
1396  56 toggle private void colourAlignFrame(AlignFrame af, ColourSchemeI cs)
1397    {
1398  56 try
1399    {
1400  56 SwingUtilities.invokeAndWait(new Runnable()
1401    {
 
1402  56 toggle @Override
1403    public void run()
1404    {
1405    // Note that cs == null removes colour scheme from af
1406  56 af.changeColour(cs);
1407    }
1408    });
1409    } catch (Exception x)
1410    {
1411  0 Console.trace("Interrupted whilst waiting for colorAlignFrame action",
1412    x);
1413   
1414    }
1415    }
1416   
 
1417  40 toggle private ColourSchemeI getColourScheme(AlignFrame af)
1418    {
1419  40 return af.getViewport().getGlobalColourScheme();
1420    }
1421   
 
1422  0 toggle private void addInfo(String errorMessage)
1423    {
1424  0 Console.info(errorMessage);
1425  0 errors.add(errorMessage);
1426    }
1427   
 
1428  0 toggle private void addWarn(String errorMessage)
1429    {
1430  0 Console.warn(errorMessage);
1431  0 errors.add(errorMessage);
1432    }
1433   
 
1434  0 toggle private void addError(String errorMessage)
1435    {
1436  0 addError(errorMessage, null);
1437    }
1438   
 
1439  0 toggle private void addError(String errorMessage, Exception e)
1440    {
1441  0 Console.error(errorMessage, e);
1442  0 errors.add(errorMessage);
1443    }
1444   
 
1445  114 toggle private boolean checksBeforeWritingToFile(ArgValuesMap avm,
1446    SubVals subVal, boolean includeBackups, String filename,
1447    String adjective, Boolean isError)
1448    {
1449  114 File file = new File(filename);
1450   
1451  114 boolean overwrite = avm.getFromSubValArgOrPref(Arg.OVERWRITE, subVal,
1452    null, "OVERWRITE_OUTPUT", false);
1453  114 boolean stdout = false;
1454  114 boolean backups = false;
1455  114 if (includeBackups)
1456    {
1457  74 stdout = ArgParser.STDOUTFILENAME.equals(filename);
1458    // backups. Use the Arg.BACKUPS or subval "backups" setting first,
1459    // otherwise if headless assume false, if not headless use the user
1460    // preference with default true.
1461  74 backups = avm.getFromSubValArgOrPref(Arg.BACKUPS, subVal, null,
1462  74 Platform.isHeadless() ? null : BackupFiles.ENABLED,
1463    !Platform.isHeadless());
1464    }
1465   
1466  114 if (file.exists() && !(overwrite || backups || stdout))
1467    {
1468  0 addWarn("Won't overwrite file '" + filename + "' without "
1469    + Arg.OVERWRITE.argString()
1470  0 + (includeBackups ? " or " + Arg.BACKUPS.argString() : "")
1471    + " set");
1472  0 return false;
1473    }
1474   
1475  114 boolean mkdirs = avm.getFromSubValArgOrPref(Arg.MKDIRS, subVal, null,
1476    "MKDIRS_OUTPUT", false);
1477   
1478  114 if (!FileUtils.checkParentDir(file, mkdirs))
1479    {
1480  0 addError("Directory '"
1481    + FileUtils.getParentDir(file).getAbsolutePath()
1482    + "' does not exist for " + adjective + " file '" + filename
1483    + "'."
1484  0 + (mkdirs ? "" : " Try using " + Arg.MKDIRS.argString()));
1485  0 isError = true;
1486  0 return false;
1487    }
1488   
1489  114 return true;
1490    }
1491   
 
1492  116 toggle public List<String> getErrors()
1493    {
1494  116 return errors;
1495    }
1496   
 
1497  144 toggle public String errorsToString()
1498    {
1499  144 StringBuilder sb = new StringBuilder();
1500  144 for (String error : errors)
1501    {
1502  0 if (sb.length() > 0)
1503  0 sb.append("\n");
1504  0 sb.append("- " + error);
1505    }
1506  144 return sb.toString();
1507    }
1508    }