JAL-4353 Preserve the user given 'linkedId' with ArgValue, to help with deciding...
[jalview.git] / src / jalview / bin / argparser / ArgValues.java
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.argparser;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.stream.Collectors;
28
29 import jalview.bin.Console;
30 import jalview.bin.argparser.Arg.Opt;
31 import jalview.bin.argparser.Arg.Type;
32
33 public class ArgValues
34 {
35   public static final String ID = "id";
36
37   private Arg arg;
38
39   private int argCount = 0;
40
41   private boolean boolValue = false;
42
43   private boolean negated = false;
44
45   private boolean setByWildcard = false;
46
47   private String givenLinkedId = null;
48
49   private int boolIndex = -1;
50
51   private List<Integer> argsIndexes;
52
53   private List<ArgValue> argValueList;
54
55   private Map<String, ArgValue> idMap = new HashMap<>();
56
57   private ArgValuesMap avm;
58
59   /*
60    * Type type is only really used by --help-type
61    */
62   private Type type = null;
63
64   protected ArgValues(Arg a, ArgValuesMap avm)
65   {
66     this.arg = a;
67     this.argValueList = new ArrayList<ArgValue>();
68     this.boolValue = arg.getDefaultBoolValue();
69     this.avm = avm;
70   }
71
72   protected boolean setByWildcard()
73   {
74     return setByWildcard;
75   }
76
77   protected void setSetByWildcard(boolean b)
78   {
79     setByWildcard = b;
80   }
81
82   public Arg arg()
83   {
84     return arg;
85   }
86
87   protected void setType(Type t)
88   {
89     if (this.arg().hasOption(Opt.HASTYPE))
90       this.type = t;
91   }
92
93   public Type getType()
94   {
95     return type;
96   }
97
98   protected int getCount()
99   {
100     return argCount;
101   }
102
103   protected void incrementCount()
104   {
105     argCount++;
106   }
107
108   protected void setNegated(boolean b, boolean beingSetByWildcard)
109   {
110     // don't overwrite a wildcard set boolean with a non-wildcard set boolean
111     if (boolIndex >= 0 && !this.setByWildcard && beingSetByWildcard)
112       return;
113     this.negated = b;
114   }
115
116   protected boolean isNegated()
117   {
118     return this.negated;
119   }
120
121   protected void setBoolean(Type t, boolean b, int i,
122           boolean beingSetByWildcard, String givenLinkedId)
123   {
124     this.setType(t);
125     // don't overwrite a wildcard set boolean with a non-wildcard set boolean
126     if (boolIndex >= 0 && !this.setByWildcard && beingSetByWildcard)
127       return;
128     this.boolValue = b;
129     this.boolIndex = i;
130     this.setSetByWildcard(beingSetByWildcard);
131     this.givenLinkedId = givenLinkedId;
132   }
133
134   protected boolean getBoolean()
135   {
136     return this.boolValue;
137   }
138
139   @Override
140   public String toString()
141   {
142     if (argValueList == null)
143       return null;
144     StringBuilder sb = new StringBuilder();
145     sb.append(arg.toLongString());
146     if (arg.hasOption(Opt.BOOLEAN) || arg.hasOption(Opt.UNARY))
147       sb.append("Boolean: ").append(boolValue).append("; Default: ")
148               .append(arg.getDefaultBoolValue()).append("; Negated: ")
149               .append(negated).append("\n");
150     if (arg.hasOption(Opt.STRING))
151     {
152       sb.append("Values:");
153       sb.append("'")
154               .append(String
155                       .join("',\n  '",
156                               argValueList.stream().map(av -> av.getValue())
157                                       .collect(Collectors.toList())))
158               .append("'");
159       sb.append("\n");
160     }
161     sb.append("Count: ").append(argCount).append("\n");
162     return sb.toString();
163   }
164
165   protected void addValue(Type type, String val, int argIndex,
166           boolean wildcard, String givenLinkedId)
167   {
168     addArgValue(new ArgValue(arg(), type, val, argIndex, wildcard,
169             givenLinkedId, avm.getLinkedId()), wildcard);
170   }
171
172   protected void addValue(SubVals sv, Type type, String content,
173           int argIndex, boolean wildcard, String givenLinkedId)
174   {
175     addArgValue(new ArgValue(arg(), sv, type, content, argIndex, wildcard,
176             givenLinkedId, avm.getLinkedId()), wildcard);
177   }
178
179   protected void addArgValue(ArgValue av, boolean beingSetByWildcard)
180   {
181     // allow a non-wildcard value to overwrite a wildcard set single value
182     boolean overwrite = !arg.hasOption(Opt.MULTIVALUE) && setByWildcard
183             && !beingSetByWildcard;
184     if ((!arg.hasOption(Opt.MULTIVALUE) && argValueList.size() > 0)
185             && !overwrite)
186       return;
187     if (arg.hasOption(Opt.NODUPLICATEVALUES)
188             && this.containsValue(av.getValue()))
189       return;
190     // new or overwrite if single valued
191     if (argValueList == null || overwrite)
192     {
193       argValueList = new ArrayList<ArgValue>();
194     }
195     SubVals sv = new SubVals(av.getValue());
196     if (sv.has(ID))
197     {
198       String id = sv.get(ID);
199       av.setId(id);
200       idMap.put(id, av);
201     }
202     argValueList.add(av);
203     this.setSetByWildcard(beingSetByWildcard);
204   }
205
206   protected boolean hasValue(String val)
207   {
208     return argValueList.contains(val);
209   }
210
211   protected ArgValue getArgValue()
212   {
213     if (arg.hasOption(Opt.MULTIVALUE))
214       Console.warn("Requesting single value for multi value argument");
215     return argValueList.size() > 0 ? argValueList.get(0) : null;
216   }
217
218   protected List<ArgValue> getArgValueList()
219   {
220     return argValueList;
221   }
222
223   protected boolean hasId(String id)
224   {
225     return idMap.containsKey(id);
226   }
227
228   protected ArgValue getId(String id)
229   {
230     return idMap.get(id);
231   }
232
233   private boolean containsValue(String v)
234   {
235     if (argValueList == null)
236       return false;
237     for (ArgValue av : argValueList)
238     {
239       String val = av.getValue();
240       if (v == null && val == null)
241         return true;
242       if (v == null)
243         continue;
244       if (v.equals(val))
245         return true;
246     }
247     return false;
248   }
249
250   public boolean setByWildcardLinkedId()
251   {
252     // looking for deliberately user set wildcard
253     return this.setByWildcard && this.givenLinkedId != null;
254   }
255
256 }