JAL-629 parse SubVals once with ArgValue. Ensure SubVals exists. Change to setprops...
[jalview.git] / src / jalview / bin / argparser / SubVals.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
8 import jalview.bin.Console;
9
10 /**
11  * A helper class to parse a string of the possible forms "content"
12  * "[index]content", "[keyName=keyValue]content" and return the integer index,
13  * the strings keyName and keyValue, and the content after the square brackets
14  * (if present). Values not set `will be -1 or null.
15  */
16 public class SubVals
17 {
18   public static int NOTSET = -1;
19
20   private int index = NOTSET;
21
22   private Map<String, String> subValMap;
23
24   private static char SEPARATOR = ';';
25
26   private static char EQUALS = '=';
27
28   private String content = null;
29
30   protected SubVals(SubVals sv, String c)
31   {
32     if (sv == null)
33     {
34       this.subValMap = new HashMap<>();
35     }
36     else
37     {
38       this.subValMap = sv == null ? new HashMap<>() : sv.getSubValMap();
39       this.index = sv.getIndex();
40     }
41     this.content = c;
42   }
43
44   protected SubVals(String item)
45   {
46     if (subValMap == null)
47       subValMap = new HashMap<>();
48     this.parseVals(item);
49   }
50
51   public void parseVals(String item)
52   {
53     if (item == null)
54       return;
55     if (item.indexOf('[') == 0 && item.indexOf(']') > 1)
56     {
57       int openBracket = 0;
58       int closeBracket = item.indexOf(']');
59       String subvalsString = item.substring(openBracket + 1, closeBracket);
60       this.content = item.substring(closeBracket + 1);
61       boolean setIndex = false;
62       for (String subvalString : subvalsString
63               .split(Character.toString(SEPARATOR)))
64       {
65         int equals = subvalString.indexOf(EQUALS);
66         if (equals > -1)
67         {
68           this.put(subvalString.substring(0, equals),
69                   subvalString.substring(equals + 1));
70         }
71         else
72         {
73           try
74           {
75             this.index = Integer.parseInt(subvalString);
76             setIndex = true;
77           } catch (NumberFormatException e)
78           {
79             // store this non-numeric key as a "true" value
80             this.put(subvalString, "true");
81           }
82         }
83       }
84       if (!setIndex)
85         this.index = NOTSET;
86       else
87         Console.debug("SubVals from '" + subvalsString + "' has index "
88                 + this.index + " set");
89     }
90     else
91     {
92       this.content = item;
93     }
94   }
95
96   protected void put(String key, String val)
97   {
98     subValMap.put(key, val);
99   }
100
101   public boolean notSet()
102   {
103     // notSet is true if content present but nonsensical
104     return index == NOTSET && (subValMap == null || subValMap.size() == 0);
105   }
106
107   public String get(String key)
108   {
109     return subValMap.get(key);
110   }
111
112   public boolean has(String key)
113   {
114     return subValMap.containsKey(key);
115   }
116
117   public int getIndex()
118   {
119     return index;
120   }
121
122   public String getContent()
123   {
124     return content;
125   }
126
127   protected Map<String, String> getSubValMap()
128   {
129     return subValMap;
130   }
131
132   public String toString()
133   {
134     if (subValMap == null && getIndex() == NOTSET)
135       return "";
136
137     StringBuilder sb = new StringBuilder();
138     List<String> entries = new ArrayList<>();
139     subValMap.entrySet().stream().forEachOrdered(
140             m -> entries.add(m.getValue().equals("true") ? m.getKey()
141                     : new StringBuilder().append(m.getKey()).append(EQUALS)
142                             .append(m.getValue()).toString()));
143     if (getIndex() != NOTSET)
144       entries.add(Integer.toString(getIndex()));
145     sb.append('[');
146     sb.append(String.join(Character.toString(SEPARATOR), entries));
147     sb.append(']');
148     return sb.toString();
149   }
150 }