JAL-629 Ensure precedence of named linked ID values over wildcard linked ID set value...
[jalview.git] / src / jalview / bin / argparser / ArgValues.java
1 package jalview.bin.argparser;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.stream.Collectors;
8
9 import jalview.bin.Console;
10 import jalview.bin.argparser.Arg.Opt;
11
12 public class ArgValues
13 {
14   public static final String ID = "id";
15
16   private Arg arg;
17
18   private int argCount = 0;
19
20   private boolean boolValue = false;
21
22   private boolean negated = false;
23
24   private boolean setByWildcard = false;
25
26   private int boolIndex = -1;
27
28   private List<Integer> argsIndexes;
29
30   private List<ArgValue> argValueList;
31
32   private Map<String, ArgValue> idMap = new HashMap<>();
33
34   protected ArgValues(Arg a)
35   {
36     this.arg = a;
37     this.argValueList = new ArrayList<ArgValue>();
38     this.boolValue = arg.getDefaultBoolValue();
39   }
40
41   protected boolean setByWildcard()
42   {
43     return setByWildcard;
44   }
45
46   protected void setSetByWildcard(boolean b)
47   {
48     setByWildcard = b;
49   }
50
51   public Arg arg()
52   {
53     return arg;
54   }
55
56   protected int getCount()
57   {
58     return argCount;
59   }
60
61   protected void incrementCount()
62   {
63     argCount++;
64   }
65
66   protected void setNegated(boolean b, boolean beingSetByWildcard)
67   {
68     // don't overwrite a wildcard set boolean with a non-wildcard set boolean
69     if (boolIndex >= 0 && !this.setByWildcard && beingSetByWildcard)
70       return;
71     this.negated = b;
72   }
73
74   protected boolean isNegated()
75   {
76     return this.negated;
77   }
78
79   protected void setBoolean(boolean b, int i, boolean beingSetByWildcard)
80   {
81     // don't overwrite a wildcard set boolean with a non-wildcard set boolean
82     if (boolIndex >= 0 && !this.setByWildcard && beingSetByWildcard)
83       return;
84     this.boolValue = b;
85     this.boolIndex = i;
86     this.setSetByWildcard(beingSetByWildcard);
87   }
88
89   protected boolean getBoolean()
90   {
91     return this.boolValue;
92   }
93
94   @Override
95   public String toString()
96   {
97     if (argValueList == null)
98       return null;
99     StringBuilder sb = new StringBuilder();
100     sb.append(arg.toLongString());
101     if (arg.hasOption(Opt.BOOLEAN) || arg.hasOption(Opt.UNARY))
102       sb.append("Boolean: ").append(boolValue).append("; Default: ")
103               .append(arg.getDefaultBoolValue()).append("; Negated: ")
104               .append(negated).append("\n");
105     if (arg.hasOption(Opt.STRING))
106     {
107       sb.append("Values:");
108       sb.append("'")
109               .append(String
110                       .join("',\n  '",
111                               argValueList.stream().map(av -> av.getValue())
112                                       .collect(Collectors.toList())))
113               .append("'");
114       sb.append("\n");
115     }
116     sb.append("Count: ").append(argCount).append("\n");
117     return sb.toString();
118   }
119
120   protected void addValue(String val, int argIndex, boolean wildcard)
121   {
122     addArgValue(new ArgValue(arg(), val, argIndex), wildcard);
123   }
124
125   protected void addValue(SubVals sv, String content, int argIndex,
126           boolean wildcard)
127   {
128     addArgValue(new ArgValue(arg(), sv, content, argIndex), wildcard);
129   }
130
131   protected void addArgValue(ArgValue av, boolean beingSetByWildcard)
132   {
133     // allow a non-wildcard value to overwrite a wildcard set single value
134     boolean overwrite = !arg.hasOption(Opt.MULTI) && setByWildcard
135             && !beingSetByWildcard;
136     if ((!arg.hasOption(Opt.MULTI) && argValueList.size() > 0)
137             && !overwrite)
138       return;
139     if (arg.hasOption(Opt.NODUPLICATEVALUES)
140             && this.containsValue(av.getValue()))
141       return;
142     // new or overwrite if single valued
143     if (argValueList == null || overwrite)
144     {
145       argValueList = new ArrayList<ArgValue>();
146     }
147     SubVals sv = new SubVals(av.getValue());
148     if (sv.has(ID))
149     {
150       String id = sv.get(ID);
151       av.setId(id);
152       idMap.put(id, av);
153     }
154     argValueList.add(av);
155     this.setSetByWildcard(beingSetByWildcard);
156   }
157
158   protected boolean hasValue(String val)
159   {
160     return argValueList.contains(val);
161   }
162
163   protected ArgValue getArgValue()
164   {
165     if (arg.hasOption(Opt.MULTI))
166       Console.warn("Requesting single value for multi value argument");
167     return argValueList.size() > 0 ? argValueList.get(0) : null;
168   }
169
170   protected List<ArgValue> getArgValueList()
171   {
172     return argValueList;
173   }
174
175   protected boolean hasId(String id)
176   {
177     return idMap.containsKey(id);
178   }
179
180   protected ArgValue getId(String id)
181   {
182     return idMap.get(id);
183   }
184
185   private boolean containsValue(String v)
186   {
187     if (argValueList == null)
188       return false;
189     for (ArgValue av : argValueList)
190     {
191       String val = av.getValue();
192       if (v == null && val == null)
193         return true;
194       if (v == null)
195         continue;
196       if (v.equals(val))
197         return true;
198     }
199     return false;
200   }
201 }