| OptionList.java |
1 /**
2 * Distribution License:
3 * JSword is free software; you can redistribute it and/or modify it under
4 * the terms of the GNU Lesser General Public License, version 2.1 or later
5 * as published by the Free Software Foundation. This program is distributed
6 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
7 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8 * See the GNU Lesser General Public License for more details.
9 *
10 * The License is available on the internet at:
11 * http://www.gnu.org/copyleft/lgpl.html
12 * or by writing to:
13 * Free Software Foundation, Inc.
14 * 59 Temple Place - Suite 330
15 * Boston, MA 02111-1307, USA
16 *
17 * © CrossWire Bible Society, 2008 - 2016
18 *
19 */
20 package org.crosswire.common.options;
21
22 import java.util.ArrayList;
23 import java.util.LinkedHashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 /**
28 * An OptionList contains an ordered set of Options. The primary ability of an
29 * OptionList is to find the matches for an Option.
30 *
31 * @see gnu.lgpl.License The GNU Lesser General Public License for details.
32 * @author DM Smith
33 */
34 public class OptionList {
35 public OptionList() {
36 longOptions = new LinkedHashMap<String, Option>();
37 shortOptions = new LinkedHashMap<String, Option>();
38 }
39
40 /**
41 * Adds an Option to the end of this OptionList. It is an error with
42 * "undefined" behavior for an Option's short or long name to already be
43 * known.
44 *
45 * @param option the option to append
46 */
47 public void add(Option option) {
48 char shortName = option.getShortName();
49 String longName = option.getLongName();
50 if (shortName != '\u0000') {
51 String optionName = Character.toString(shortName);
52 assert !shortOptions.containsKey(optionName) : optionName + " already present";
53 shortOptions.put(optionName, option);
54 }
55
56 if (longName != null) {
57 assert !longOptions.containsKey(longName) : longName + " already present";
58 longOptions.put(longName, option);
59 }
60 }
61
62 /**
63 * Get a list of Options that match the Option's long name. Return all
64 * Options where the key is a prefix of its long name. If there is an exact
65 * match then it is at the head of the list. It is up to the program to
66 * decide how to handle ambiguity.
67 *
68 * @param key
69 * the input to match
70 * @return a list of all matches, or an empty list
71 */
72 public List<Option> getLongOptions(String key) {
73 List<Option> matches = new ArrayList<Option>();
74 if (longOptions.containsKey(key)) {
75 matches.add(longOptions.get(key));
76 }
77
78 for (Map.Entry<String, Option> entry : longOptions.entrySet()) {
79 String entryKey = entry.getKey();
80 Option entryValue = entry.getValue();
81 if (entryKey.startsWith(key) && !matches.contains(entryValue)) {
82 matches.add(entryValue);
83 }
84 }
85
86 return matches;
87 }
88
89 /**
90 * Get the Option that matches the key on the Option's short name.
91 *
92 * @param key
93 * the input to match
94 * @return the matching Option, null otherwise.
95 */
96 public Option getShortOption(char key) {
97 String optionName = Character.toString(key);
98
99 Option match = null;
100 if (shortOptions.containsKey(optionName)) {
101 match = shortOptions.get(optionName);
102 }
103
104 return match;
105 }
106
107 /**
108 * Get a list of Options that match the Option's short or long name.
109 * Obviously, if the key is longer than a single character it won't match a
110 * short name. Return all Options where the key is a prefix of its long
111 * name. If there is an exact match then it is at the head of the list. It
112 * is up to the program to decide how to handle ambiguity.
113 *
114 * @param key
115 * the input to match
116 * @return a list of all matches, or an empty list
117 */
118 public List<Option> getOptions(String key) {
119 List<Option> matches = new ArrayList<Option>();
120 if (key.length() == 1) {
121 Option match = getShortOption(key.charAt(0));
122 if (match != null) {
123 matches.add(match);
124 }
125 }
126
127 for (Option match : getLongOptions(key)) {
128 if (!matches.contains(match)) {
129 matches.add(match);
130 }
131 }
132
133 return matches;
134 }
135
136 private Map<String, Option> shortOptions;
137 private Map<String, Option> longOptions;
138 }
139