1 // Copyright (c) 2004 Brian Wellington (bwelling (at) xbill.org) 2 3 package org.xbill.DNS; 4 5 import java.util.HashMap; 6 7 /** 8 * A utility class for converting between numeric codes and mnemonics 9 * for those codes. Mnemonics are case insensitive. 10 * 11 * @author Brian Wellington 12 */ 13 14 class Mnemonic { 15 16 private static Integer cachedInts[] = new Integer[64]; 17 18 static { 19 for (int i = 0; i < cachedInts.length; i++) { 20 cachedInts[i] = new Integer(i); 21 } 22 } 23 24 /* Strings are case-sensitive. */ 25 static final int CASE_SENSITIVE = 1; 26 27 /* Strings will be stored/searched for in uppercase. */ 28 static final int CASE_UPPER = 2; 29 30 /* Strings will be stored/searched for in lowercase. */ 31 static final int CASE_LOWER = 3; 32 33 private HashMap strings; 34 private HashMap values; 35 private String description; 36 private int wordcase; 37 private String prefix; 38 private int max; 39 private boolean numericok; 40 41 /** 42 * Creates a new Mnemonic table. 43 * @param description A short description of the mnemonic to use when 44 * @param wordcase Whether to convert strings into uppercase, lowercase, 45 * or leave them unchanged. 46 * throwing exceptions. 47 */ 48 public 49 Mnemonic(String description, int wordcase) { 50 this.description = description; 51 this.wordcase = wordcase; 52 strings = new HashMap(); 53 values = new HashMap(); 54 max = Integer.MAX_VALUE; 55 } 56 57 /** Sets the maximum numeric value */ 58 public void 59 setMaximum(int max) { 60 this.max = max; 61 } 62 63 /** 64 * Sets the prefix to use when converting to and from values that don't 65 * have mnemonics. 66 */ 67 public void 68 setPrefix(String prefix) { 69 this.prefix = sanitize(prefix); 70 } 71 72 /** 73 * Sets whether numeric values stored in strings are acceptable. 74 */ 75 public void 76 setNumericAllowed(boolean numeric) { 77 this.numericok = numeric; 78 } 79 80 /** 81 * Converts an int into a possibly cached Integer. 82 */ 83 public static Integer 84 toInteger(int val) { 85 if (val >= 0 && val < cachedInts.length) 86 return (cachedInts[val]); 87 return new Integer(val); 88 } 89 90 /** 91 * Checks that a numeric value is within the range [0..max] 92 */ 93 public void 94 check(int val) { 95 if (val < 0 || val > max) { 96 throw new IllegalArgumentException(description + " " + val + 97 "is out of range"); 98 } 99 } 100 101 /* Converts a String to the correct case. */ 102 private String 103 sanitize(String str) { 104 if (wordcase == CASE_UPPER) 105 return str.toUpperCase(); 106 else if (wordcase == CASE_LOWER) 107 return str.toLowerCase(); 108 return str; 109 } 110 111 private int 112 parseNumeric(String s) { 113 try { 114 int val = Integer.parseInt(s); 115 if (val >= 0 && val <= max) 116 return val; 117 } 118 catch (NumberFormatException e) { 119 } 120 return -1; 121 } 122 123 /** 124 * Defines the text representation of a numeric value. 125 * @param val The numeric value 126 * @param string The text string 127 */ 128 public void 129 add(int val, String str) { 130 check(val); 131 Integer value = toInteger(val); 132 str = sanitize(str); 133 strings.put(str, value); 134 values.put(value, str); 135 } 136 137 /** 138 * Defines an additional text representation of a numeric value. This will 139 * be used by getValue(), but not getText(). 140 * @param val The numeric value 141 * @param string The text string 142 */ 143 public void 144 addAlias(int val, String str) { 145 check(val); 146 Integer value = toInteger(val); 147 str = sanitize(str); 148 strings.put(str, value); 149 } 150 151 /** 152 * Copies all mnemonics from one table into another. 153 * @param val The numeric value 154 * @param string The text string 155 * @throws IllegalArgumentException The wordcases of the Mnemonics do not 156 * match. 157 */ 158 public void 159 addAll(Mnemonic source) { 160 if (wordcase != source.wordcase) 161 throw new IllegalArgumentException(source.description + 162 ": wordcases do not match"); 163 strings.putAll(source.strings); 164 values.putAll(source.values); 165 } 166 167 /** 168 * Gets the text mnemonic corresponding to a numeric value. 169 * @param val The numeric value 170 * @return The corresponding text mnemonic. 171 */ 172 public String 173 getText(int val) { 174 check(val); 175 String str = (String) values.get(toInteger(val)); 176 if (str != null) 177 return str; 178 str = Integer.toString(val); 179 if (prefix != null) 180 return prefix + str; 181 return str; 182 } 183 184 /** 185 * Gets the numeric value corresponding to a text mnemonic. 186 * @param str The text mnemonic 187 * @return The corresponding numeric value, or -1 if there is none 188 */ 189 public int 190 getValue(String str) { 191 str = sanitize(str); 192 Integer value = (Integer) strings.get(str); 193 if (value != null) { 194 return value.intValue(); 195 } 196 if (prefix != null) { 197 if (str.startsWith(prefix)) { 198 int val = parseNumeric(str.substring(prefix.length())); 199 if (val >= 0) { 200 return val; 201 } 202 } 203 } 204 if (numericok) { 205 return parseNumeric(str); 206 } 207 return -1; 208 } 209 210 } 211