JAL-4409 Make HttpUtils.equivalentJalviewUrlString 'non-destructive'
[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,
104                   HttpUtils.equivalentJalviewUrl(associatedFile));
105         }
106       }
107       // add an --open arg to separate from other files
108       filenames.add(pos, Arg.OPEN.argString());
109     }
110   }
111
112   private static void setValidExtensions()
113   {
114     alignmentExtensions = new HashSet<>();
115     FileFormats ffs = FileFormats.getInstance();
116     List<String> validFormats = ffs.getReadableFormats();
117
118     for (String fname : validFormats)
119     {
120       FileFormatI tff = ffs.forName(fname);
121       String[] extensions = tff.getExtensions().split(",");
122       for (String ext : extensions)
123       {
124         alignmentExtensions.add(ext.toLowerCase(Locale.ROOT));
125       }
126     }
127
128     annotationsExtensions = new HashSet<>();
129     for (String ext : Cache
130             .getDefault("ARGPREPROCESSORANNOTATIONSEXTENSIONS",
131                     "annotation,annotations")
132             .split(","))
133     {
134       annotationsExtensions.add(ext);
135     }
136
137     featuresExtensions = new HashSet<>();
138     for (String ext : Cache.getDefault("ARGPREPROCESSORFEATURESEXTENSIONS",
139             "feature,features").split(","))
140     {
141       featuresExtensions.add(ext);
142     }
143
144     treeExtensions = new HashSet<>();
145     for (String ext : Cache.getDefault("ARGPREPROCESSORTREEEXTENSIONS",
146             "tree,tre,newick,nwk").split(","))
147     {
148       treeExtensions.add(ext);
149     }
150   }
151 }
152
153 class BaseInfo
154 {
155   String filename;
156
157   Map<Arg, String> associatedFiles = null;
158
159   BaseInfo(String filename)
160   {
161     this.filename = filename;
162   }
163
164   void putAssociatedFile(Arg a, String file)
165   {
166     if (associatedFiles == null)
167     {
168       associatedFiles = new HashMap<>();
169     }
170     associatedFiles.put(a, file);
171   }
172 }