// Copyright (c) 2004 Brian Wellington (bwelling@xbill.org) package org.xbill.DNS; import java.util.HashMap; /** * A utility class for converting between numeric codes and mnemonics * for those codes. Mnemonics are case insensitive. * * @author Brian Wellington */ class Mnemonic { private static Integer cachedInts[] = new Integer[64]; static { for (int i = 0; i < cachedInts.length; i++) { cachedInts[i] = new Integer(i); } } /* Strings are case-sensitive. */ static final int CASE_SENSITIVE = 1; /* Strings will be stored/searched for in uppercase. */ static final int CASE_UPPER = 2; /* Strings will be stored/searched for in lowercase. */ static final int CASE_LOWER = 3; private HashMap strings; private HashMap values; private String description; private int wordcase; private String prefix; private int max; private boolean numericok; /** * Creates a new Mnemonic table. * @param description A short description of the mnemonic to use when * @param wordcase Whether to convert strings into uppercase, lowercase, * or leave them unchanged. * throwing exceptions. */ public Mnemonic(String description, int wordcase) { this.description = description; this.wordcase = wordcase; strings = new HashMap(); values = new HashMap(); max = Integer.MAX_VALUE; } /** Sets the maximum numeric value */ public void setMaximum(int max) { this.max = max; } /** * Sets the prefix to use when converting to and from values that don't * have mnemonics. */ public void setPrefix(String prefix) { this.prefix = sanitize(prefix); } /** * Sets whether numeric values stored in strings are acceptable. */ public void setNumericAllowed(boolean numeric) { this.numericok = numeric; } /** * Converts an int into a possibly cached Integer. */ public static Integer toInteger(int val) { if (val >= 0 && val < cachedInts.length) return (cachedInts[val]); return new Integer(val); } /** * Checks that a numeric value is within the range [0..max] */ public void check(int val) { if (val < 0 || val > max) { throw new IllegalArgumentException(description + " " + val + "is out of range"); } } /* Converts a String to the correct case. */ private String sanitize(String str) { if (wordcase == CASE_UPPER) return str.toUpperCase(); else if (wordcase == CASE_LOWER) return str.toLowerCase(); return str; } private int parseNumeric(String s) { try { int val = Integer.parseInt(s); if (val >= 0 && val <= max) return val; } catch (NumberFormatException e) { } return -1; } /** * Defines the text representation of a numeric value. * @param val The numeric value * @param string The text string */ public void add(int val, String str) { check(val); Integer value = toInteger(val); str = sanitize(str); strings.put(str, value); values.put(value, str); } /** * Defines an additional text representation of a numeric value. This will * be used by getValue(), but not getText(). * @param val The numeric value * @param string The text string */ public void addAlias(int val, String str) { check(val); Integer value = toInteger(val); str = sanitize(str); strings.put(str, value); } /** * Copies all mnemonics from one table into another. * @param val The numeric value * @param string The text string * @throws IllegalArgumentException The wordcases of the Mnemonics do not * match. */ public void addAll(Mnemonic source) { if (wordcase != source.wordcase) throw new IllegalArgumentException(source.description + ": wordcases do not match"); strings.putAll(source.strings); values.putAll(source.values); } /** * Gets the text mnemonic corresponding to a numeric value. * @param val The numeric value * @return The corresponding text mnemonic. */ public String getText(int val) { check(val); String str = (String) values.get(toInteger(val)); if (str != null) return str; str = Integer.toString(val); if (prefix != null) return prefix + str; return str; } /** * Gets the numeric value corresponding to a text mnemonic. * @param str The text mnemonic * @return The corresponding numeric value, or -1 if there is none */ public int getValue(String str) { str = sanitize(str); Integer value = (Integer) strings.get(str); if (value != null) { return value.intValue(); } if (prefix != null) { if (str.startsWith(prefix)) { int val = parseNumeric(str.substring(prefix.length())); if (val >= 0) { return val; } } } if (numericok) { return parseNumeric(str); } return -1; } }