Home | History | Annotate | Download | only in DNS
      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