001: // Copyright (c) 2004 Brian Wellington (bwelling@xbill.org)
002:
003: package org.xbill.DNS;
004:
005: import java.util.HashMap;
006:
007: /**
008: * A utility class for converting between numeric codes and mnemonics
009: * for those codes. Mnemonics are case insensitive.
010: *
011: * @author Brian Wellington
012: */
013:
014: class Mnemonic {
015:
016: private static Integer cachedInts[] = new Integer[64];
017:
018: static {
019: for (int i = 0; i < cachedInts.length; i++) {
020: cachedInts[i] = new Integer(i);
021: }
022: }
023:
024: /* Strings are case-sensitive. */
025: static final int CASE_SENSITIVE = 1;
026:
027: /* Strings will be stored/searched for in uppercase. */
028: static final int CASE_UPPER = 2;
029:
030: /* Strings will be stored/searched for in lowercase. */
031: static final int CASE_LOWER = 3;
032:
033: private HashMap strings;
034: private HashMap values;
035: private String description;
036: private int wordcase;
037: private String prefix;
038: private int max;
039: private boolean numericok;
040:
041: /**
042: * Creates a new Mnemonic table.
043: * @param description A short description of the mnemonic to use when
044: * @param wordcase Whether to convert strings into uppercase, lowercase,
045: * or leave them unchanged.
046: * throwing exceptions.
047: */
048: public Mnemonic(String description, int wordcase) {
049: this .description = description;
050: this .wordcase = wordcase;
051: strings = new HashMap();
052: values = new HashMap();
053: max = Integer.MAX_VALUE;
054: }
055:
056: /** Sets the maximum numeric value */
057: public void setMaximum(int max) {
058: this .max = max;
059: }
060:
061: /**
062: * Sets the prefix to use when converting to and from values that don't
063: * have mnemonics.
064: */
065: public void setPrefix(String prefix) {
066: this .prefix = sanitize(prefix);
067: }
068:
069: /**
070: * Sets whether numeric values stored in strings are acceptable.
071: */
072: public void setNumericAllowed(boolean numeric) {
073: this .numericok = numeric;
074: }
075:
076: /**
077: * Converts an int into a possibly cached Integer.
078: */
079: public static Integer toInteger(int val) {
080: if (val >= 0 && val < cachedInts.length)
081: return (cachedInts[val]);
082: return new Integer(val);
083: }
084:
085: /**
086: * Checks that a numeric value is within the range [0..max]
087: */
088: public void check(int val) {
089: if (val < 0 || val > max) {
090: throw new IllegalArgumentException(description + " " + val
091: + "is out of range");
092: }
093: }
094:
095: /* Converts a String to the correct case. */
096: private String sanitize(String str) {
097: if (wordcase == CASE_UPPER)
098: return str.toUpperCase();
099: else if (wordcase == CASE_LOWER)
100: return str.toLowerCase();
101: return str;
102: }
103:
104: private int parseNumeric(String s) {
105: try {
106: int val = Integer.parseInt(s);
107: if (val >= 0 && val <= max)
108: return val;
109: } catch (NumberFormatException e) {
110: }
111: return -1;
112: }
113:
114: /**
115: * Defines the text representation of a numeric value.
116: * @param val The numeric value
117: * @param string The text string
118: */
119: public void add(int val, String str) {
120: check(val);
121: Integer value = toInteger(val);
122: str = sanitize(str);
123: strings.put(str, value);
124: values.put(value, str);
125: }
126:
127: /**
128: * Defines an additional text representation of a numeric value. This will
129: * be used by getValue(), but not getText().
130: * @param val The numeric value
131: * @param string The text string
132: */
133: public void addAlias(int val, String str) {
134: check(val);
135: Integer value = toInteger(val);
136: str = sanitize(str);
137: strings.put(str, value);
138: }
139:
140: /**
141: * Copies all mnemonics from one table into another.
142: * @param val The numeric value
143: * @param string The text string
144: * @throws IllegalArgumentException The wordcases of the Mnemonics do not
145: * match.
146: */
147: public void addAll(Mnemonic source) {
148: if (wordcase != source.wordcase)
149: throw new IllegalArgumentException(source.description
150: + ": wordcases do not match");
151: strings.putAll(source.strings);
152: values.putAll(source.values);
153: }
154:
155: /**
156: * Gets the text mnemonic corresponding to a numeric value.
157: * @param val The numeric value
158: * @return The corresponding text mnemonic.
159: */
160: public String getText(int val) {
161: check(val);
162: String str = (String) values.get(toInteger(val));
163: if (str != null)
164: return str;
165: str = Integer.toString(val);
166: if (prefix != null)
167: return prefix + str;
168: return str;
169: }
170:
171: /**
172: * Gets the numeric value corresponding to a text mnemonic.
173: * @param str The text mnemonic
174: * @return The corresponding numeric value, or -1 if there is none
175: */
176: public int getValue(String str) {
177: str = sanitize(str);
178: Integer value = (Integer) strings.get(str);
179: if (value != null) {
180: return value.intValue();
181: }
182: if (prefix != null) {
183: if (str.startsWith(prefix)) {
184: int val = parseNumeric(str.substring(prefix.length()));
185: if (val >= 0) {
186: return val;
187: }
188: }
189: }
190: if (numericok) {
191: return parseNumeric(str);
192: }
193: return -1;
194: }
195:
196: }
|