JAL-629 More NG arguments: --features, --annotations, --sortbytree, --tree, --groovy...
[jalview.git] / src / jalview / bin / argparser / BootstrapArgs.java
1 package jalview.bin.argparser;
2
3 import java.io.File;
4 import java.util.ArrayList;
5 import java.util.Arrays;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11
12 import jalview.bin.argparser.Arg.Opt;
13 import jalview.util.FileUtils;
14
15 public class BootstrapArgs
16 {
17   // only need one
18   private Map<Arg, List<String>> bootstrapArgMap = new HashMap<>();
19
20   private Set<File> argFiles = new HashSet<>();
21
22   public static BootstrapArgs getBootstrapArgs(String[] args)
23   {
24     List<String> argList = new ArrayList<>(Arrays.asList(args));
25     return new BootstrapArgs(argList);
26   }
27
28   public static BootstrapArgs getBootstrapArgs(List<String> args)
29   {
30     return new BootstrapArgs(args);
31   }
32
33   private BootstrapArgs(List<String> args)
34   {
35     parse(args, null);
36   }
37
38   private void parse(List<String> args, File inArgFile)
39   {
40     if (args == null)
41       return;
42     // avoid looping argFiles
43     if (inArgFile != null)
44     {
45       if (argFiles.contains(inArgFile))
46       {
47         System.err.println(
48                 "Looped argfiles detected: '" + inArgFile.getPath() + "'");
49         return;
50       }
51       argFiles.add(inArgFile);
52     }
53
54     for (int i = 0; i < args.size(); i++)
55     {
56       String arg = args.get(i);
57       String argName = null;
58       String val = null;
59       if (arg.startsWith(ArgParser.DOUBLEDASH))
60       {
61         // remove "--"
62         arg = arg.substring(ArgParser.DOUBLEDASH.length());
63         int equalPos = arg.indexOf(ArgParser.EQUALS);
64         if (equalPos > -1
65                 && ArgParser.argMap.containsKey(arg.substring(0, equalPos)))
66         {
67           argName = arg.substring(0, equalPos);
68           val = arg.substring(equalPos + 1);
69         }
70         // check for boolean prepended by "no"
71         else if (arg.startsWith(ArgParser.NEGATESTRING)
72                 && ArgParser.argMap.containsKey(
73                         arg.substring(ArgParser.NEGATESTRING.length())))
74         {
75           argName = arg.substring(ArgParser.NEGATESTRING.length());
76           val = "false";
77         }
78         else if (ArgParser.argMap.containsKey(arg))
79         {
80           argName = arg;
81           val = "true";
82         }
83
84         Arg a = ArgParser.argMap.get(argName);
85
86         if (a == null || !a.hasOption(Opt.BOOTSTRAP))
87         {
88           // not a valid bootstrap arg
89           continue;
90         }
91
92         if (a.hasOption(Opt.STRING))
93         {
94           List<String> vals = null;
95           if (equalPos == -1)
96           {
97             vals = ArgParser.getShellGlobbedFilenameValues(a, args, i + 1);
98           }
99           else
100           {
101             if (a.hasOption(Opt.GLOB))
102             {
103               vals = FileUtils.getFilenamesFromGlob(val);
104             }
105             else
106             {
107               vals = new ArrayList<>();
108               vals.add(val);
109             }
110           }
111           addAll(a, vals);
112
113           if (a == Arg.ARGFILE)
114           {
115             for (String filename : vals)
116             {
117               File argFile = new File(filename);
118               parse(ArgParser.readArgFile(argFile), argFile);
119             }
120           }
121         }
122         else
123         {
124           add(a, val);
125         }
126       }
127     }
128   }
129
130   public boolean contains(Arg a)
131   {
132     return bootstrapArgMap.containsKey(a);
133   }
134
135   public List<String> getList(Arg a)
136   {
137     return bootstrapArgMap.get(a);
138   }
139
140   private List<String> getOrCreateList(Arg a)
141   {
142     List<String> l = getList(a);
143     if (l == null)
144     {
145       l = new ArrayList<>();
146       putList(a, l);
147     }
148     return l;
149   }
150
151   private void putList(Arg a, List<String> l)
152   {
153     bootstrapArgMap.put(a, l);
154   }
155
156   /*
157    * Creates a new list if not used before,
158    * adds the value unless the existing list is non-empty
159    * and the arg is not MULTI (so first expressed value is
160    * retained).
161    */
162   private void add(Arg a, String s)
163   {
164     List<String> l = getOrCreateList(a);
165     if (a.hasOption(Opt.MULTI) || l.size() == 0)
166     {
167       l.add(s);
168     }
169   }
170
171   private void addAll(Arg a, List<String> al)
172   {
173     List<String> l = getOrCreateList(a);
174     if (a.hasOption(Opt.MULTI))
175     {
176       l.addAll(al);
177     }
178     else if (l.size() == 0 && al.size() > 0)
179     {
180       l.add(al.get(0));
181     }
182   }
183
184   /*
185    * Retrieves the first value even if MULTI.
186    * A convenience for non-MULTI args.
187    */
188   public String get(Arg a)
189   {
190     if (!bootstrapArgMap.containsKey(a))
191       return null;
192     List<String> aL = bootstrapArgMap.get(a);
193     return (aL == null || aL.size() == 0) ? null : aL.get(0);
194   }
195
196   public boolean getBoolean(Arg a, boolean d)
197   {
198     if (!bootstrapArgMap.containsKey(a))
199       return d;
200     return Boolean.parseBoolean(get(a));
201   }
202
203   public boolean getBoolean(Arg a)
204   {
205     if (!(a.hasOption(Opt.BOOLEAN) || a.hasOption(Opt.UNARY)))
206     {
207       return false;
208     }
209     if (bootstrapArgMap.containsKey(a))
210       return Boolean.parseBoolean(get(a));
211     else
212       return a.getDefaultBoolValue();
213   }
214 }