JAL-4420 Allow preprocessing of arguments if they are all simply filenames (or URLs...
[jalview.git] / src / jalview / util / ArgParserUtils.java
1 package jalview.util;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Locale;
8 import java.util.Map;
9 import java.util.Set;
10
11 import jalview.bin.Cache;
12 import jalview.bin.argparser.Arg;
13 import jalview.io.FileFormatI;
14 import jalview.io.FileFormats;
15
16 public class ArgParserUtils
17 {
18   private static Set<String> alignmentExtensions = null;
19
20   private static Set<String> annotationsExtensions = null;
21
22   private static Set<String> featuresExtensions = null;
23
24   private static Set<String> treeExtensions = null;
25
26   public static void preProcessArgs(List<String> filenames)
27   {
28     // Running through the arguments to look for '-arg' or '--arg' should
29     // already have happened, not doing it again.
30     if (alignmentExtensions == null)
31     {
32       setValidExtensions();
33     }
34
35     Set<String> filesSet = new HashSet<>(filenames);
36
37     List<Arg> argSet = new ArrayList<>();
38     argSet.add(Arg.ANNOTATIONS);
39     argSet.add(Arg.FEATURES);
40     argSet.add(Arg.TREE);
41
42     Map<Arg, Set<String>> argExtensionsMap = new HashMap<>();
43     argExtensionsMap.put(Arg.ANNOTATIONS, annotationsExtensions);
44     argExtensionsMap.put(Arg.FEATURES, featuresExtensions);
45     argExtensionsMap.put(Arg.TREE, treeExtensions);
46
47     Map<String, BaseInfo> baseInfoMap = new HashMap<>();
48
49     // we make a copy to run through, and delete associated filenames from the
50     // original
51     final List<String> filenamesCopy = new ArrayList<>(filenames);
52     for (String filename : filenamesCopy)
53     {
54       if (filename == null)
55       {
56         continue;
57       }
58       String ext = FileUtils.getExtension(filename);
59       if (ext != null && ext.length() > 0
60               && alignmentExtensions.contains(ext))
61       {
62         BaseInfo bi = new BaseInfo(filename);
63
64         // this includes the dot at the end of the basename
65         String base = FileUtils.getBase(filename);
66
67         for (Arg arg : argSet)
68         {
69           for (String possibleExt : argExtensionsMap.get(arg))
70           {
71             String possibleFile = base + possibleExt;
72             if (filesSet.contains(possibleFile))
73             {
74               bi.putAssociatedFile(arg, possibleFile);
75               filenames.remove(possibleFile);
76               break;
77             }
78           }
79         }
80
81         baseInfoMap.put(filename, bi);
82       }
83     }
84
85     // now we go through the saved associated files and add them back in to the
86     // right places with the appropriate argument
87     for (String filename : baseInfoMap.keySet())
88     {
89       BaseInfo bi = baseInfoMap.get(filename);
90
91       int pos = filenames.indexOf(filename);
92       if (bi.associatedFiles != null)
93       {
94         for (Arg a : bi.associatedFiles.keySet())
95         {
96           String associatedFile = bi.associatedFiles.get(a);
97           if (associatedFile == null)
98           {
99             // shouldn't happen!
100             continue;
101           }
102           filenames.add(pos + 1, a.argString());
103           filenames.add(pos + 2, associatedFile);
104         }
105       }
106       // add an --open arg to separate from other files
107       filenames.add(pos, Arg.OPEN.argString());
108     }
109   }
110
111   private static void setValidExtensions()
112   {
113     alignmentExtensions = new HashSet<>();
114     FileFormats ffs = FileFormats.getInstance();
115     List<String> validFormats = ffs.getReadableFormats();
116
117     for (String fname : validFormats)
118     {
119       FileFormatI tff = ffs.forName(fname);
120       String[] extensions = tff.getExtensions().split(",");
121       for (String ext : extensions)
122       {
123         alignmentExtensions.add(ext.toLowerCase(Locale.ROOT));
124       }
125     }
126
127     annotationsExtensions = new HashSet<>();
128     for (String ext : Cache
129             .getDefault("ARGPREPROCESSORANNOTATIONSEXTENSIONS",
130                     "annotation,annotations")
131             .split(","))
132     {
133       annotationsExtensions.add(ext);
134     }
135
136     featuresExtensions = new HashSet<>();
137     for (String ext : Cache.getDefault("ARGPREPROCESSORFEATURESEXTENSIONS",
138             "feature,features").split(","))
139     {
140       featuresExtensions.add(ext);
141     }
142
143     treeExtensions = new HashSet<>();
144     for (String ext : Cache.getDefault("ARGPREPROCESSORTREEEXTENSIONS",
145             "tree,tre,newick,nwk").split(","))
146     {
147       treeExtensions.add(ext);
148     }
149   }
150 }
151
152 class BaseInfo
153 {
154   String filename;
155
156   Map<Arg, String> associatedFiles = null;
157
158   BaseInfo(String filename)
159   {
160     this.filename = filename;
161   }
162
163   void putAssociatedFile(Arg a, String file)
164   {
165     if (associatedFiles == null)
166     {
167       associatedFiles = new HashMap<>();
168     }
169     associatedFiles.put(a, file);
170   }
171 }