Merge change 459 into donut
* changes: TypedProperties: initial commit
This commit is contained in:
692
core/java/com/android/internal/util/TypedProperties.java
Normal file
692
core/java/com/android/internal/util/TypedProperties.java
Normal file
@@ -0,0 +1,692 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.internal.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.StreamTokenizer;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code Map} that publishes a set of typed properties, defined by
|
||||||
|
* zero or more {@code Reader}s containing textual definitions and assignments.
|
||||||
|
*/
|
||||||
|
public class TypedProperties extends HashMap<String, Object> {
|
||||||
|
/**
|
||||||
|
* Instantiates a {@link java.io.StreamTokenizer} and sets its syntax tables
|
||||||
|
* appropriately for the {@code TypedProperties} file format.
|
||||||
|
*
|
||||||
|
* @param r The {@code Reader} that the {@code StreamTokenizer} will read from
|
||||||
|
* @return a newly-created and initialized {@code StreamTokenizer}
|
||||||
|
*/
|
||||||
|
static StreamTokenizer initTokenizer(Reader r) {
|
||||||
|
StreamTokenizer st = new StreamTokenizer(r);
|
||||||
|
|
||||||
|
// Treat everything we don't specify as "ordinary".
|
||||||
|
st.resetSyntax();
|
||||||
|
|
||||||
|
/* The only non-quoted-string words we'll be reading are:
|
||||||
|
* - property names: [._$a-zA-Z0-9]
|
||||||
|
* - type names (case insensitive): [a-zA-Z]
|
||||||
|
* - number literals: [-0-9.eExXA-Za-z] ('x' for 0xNNN hex literals. "NaN", "Infinity")
|
||||||
|
* - "true" or "false" (case insensitive): [a-zA-Z]
|
||||||
|
*/
|
||||||
|
st.wordChars('0', '9');
|
||||||
|
st.wordChars('A', 'Z');
|
||||||
|
st.wordChars('a', 'z');
|
||||||
|
st.wordChars('_', '_');
|
||||||
|
st.wordChars('$', '$');
|
||||||
|
st.wordChars('.', '.');
|
||||||
|
st.wordChars('-', '-');
|
||||||
|
st.wordChars('+', '+');
|
||||||
|
|
||||||
|
// Single-character tokens
|
||||||
|
st.ordinaryChar('=');
|
||||||
|
|
||||||
|
// Other special characters
|
||||||
|
st.whitespaceChars(' ', ' ');
|
||||||
|
st.whitespaceChars('\t', '\t');
|
||||||
|
|
||||||
|
st.quoteChar('"');
|
||||||
|
|
||||||
|
st.commentChar('#');
|
||||||
|
|
||||||
|
st.eolIsSignificant(true);
|
||||||
|
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An unchecked exception that is thrown when encountering a syntax
|
||||||
|
* or semantic error in the input.
|
||||||
|
*/
|
||||||
|
public static class ParseException extends IllegalArgumentException {
|
||||||
|
ParseException(StreamTokenizer state, String expected) {
|
||||||
|
super("expected " + expected + ", saw " + state.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A sentinel instance used to indicate a null string.
|
||||||
|
static final String NULL_STRING = new String("<TypedProperties:NULL_STRING>");
|
||||||
|
|
||||||
|
// Constants used to represent the supported types.
|
||||||
|
static final int TYPE_UNSET = 'x';
|
||||||
|
static final int TYPE_BOOLEAN = 'Z';
|
||||||
|
static final int TYPE_BYTE = 'I' | 1 << 8;
|
||||||
|
// TYPE_CHAR: character literal syntax not supported; use short.
|
||||||
|
static final int TYPE_SHORT = 'I' | 2 << 8;
|
||||||
|
static final int TYPE_INT = 'I' | 4 << 8;
|
||||||
|
static final int TYPE_LONG = 'I' | 8 << 8;
|
||||||
|
static final int TYPE_FLOAT = 'F' | 4 << 8;
|
||||||
|
static final int TYPE_DOUBLE = 'F' | 8 << 8;
|
||||||
|
static final int TYPE_STRING = 'L' | 's' << 8;
|
||||||
|
static final int TYPE_ERROR = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a case-insensitive string to an internal type constant.
|
||||||
|
*
|
||||||
|
* @param typeName the type name to convert
|
||||||
|
* @return the type constant that corresponds to {@code typeName},
|
||||||
|
* or {@code TYPE_ERROR} if the type is unknown
|
||||||
|
*/
|
||||||
|
static int interpretType(String typeName) {
|
||||||
|
if ("unset".equalsIgnoreCase(typeName)) {
|
||||||
|
return TYPE_UNSET;
|
||||||
|
} else if ("boolean".equalsIgnoreCase(typeName)) {
|
||||||
|
return TYPE_BOOLEAN;
|
||||||
|
} else if ("byte".equalsIgnoreCase(typeName)) {
|
||||||
|
return TYPE_BYTE;
|
||||||
|
} else if ("short".equalsIgnoreCase(typeName)) {
|
||||||
|
return TYPE_SHORT;
|
||||||
|
} else if ("int".equalsIgnoreCase(typeName)) {
|
||||||
|
return TYPE_INT;
|
||||||
|
} else if ("long".equalsIgnoreCase(typeName)) {
|
||||||
|
return TYPE_LONG;
|
||||||
|
} else if ("float".equalsIgnoreCase(typeName)) {
|
||||||
|
return TYPE_FLOAT;
|
||||||
|
} else if ("double".equalsIgnoreCase(typeName)) {
|
||||||
|
return TYPE_DOUBLE;
|
||||||
|
} else if ("string".equalsIgnoreCase(typeName)) {
|
||||||
|
return TYPE_STRING;
|
||||||
|
}
|
||||||
|
return TYPE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes EOL tokens.
|
||||||
|
* Returns when a non-EOL token is found.
|
||||||
|
*
|
||||||
|
* @param st The {@code StreamTokenizer} to read tokens from
|
||||||
|
* @return > 0 if an EOL token was seen, < 0 if EOF was seen,
|
||||||
|
* 0 if no tokens were consumed
|
||||||
|
*/
|
||||||
|
static int eatEols(StreamTokenizer st) throws IOException {
|
||||||
|
int token;
|
||||||
|
boolean eolSeen = false;
|
||||||
|
do {
|
||||||
|
token = st.nextToken();
|
||||||
|
if (token == StreamTokenizer.TT_EOF) {
|
||||||
|
return -1;
|
||||||
|
} else if (token == StreamTokenizer.TT_EOL) {
|
||||||
|
eolSeen = true;
|
||||||
|
}
|
||||||
|
} while (token == StreamTokenizer.TT_EOL);
|
||||||
|
st.pushBack();
|
||||||
|
return eolSeen ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the data in the reader.
|
||||||
|
*
|
||||||
|
* @param r The {@code Reader} containing input data to parse
|
||||||
|
* @param map The {@code Map} to insert parameter values into
|
||||||
|
* @throws ParseException if the input data is malformed
|
||||||
|
* @throws IOException if there is a problem reading from the {@code Reader}
|
||||||
|
*/
|
||||||
|
static void parse(Reader r, Map<String, Object> map) throws ParseException, IOException {
|
||||||
|
final StreamTokenizer st = initTokenizer(r);
|
||||||
|
|
||||||
|
/* A property name must be a valid fully-qualified class + package name.
|
||||||
|
* We don't support Unicode, though.
|
||||||
|
*/
|
||||||
|
final String identifierPattern = "[a-zA-Z_$][0-9a-zA-Z_$]*";
|
||||||
|
final Pattern propertyNamePattern =
|
||||||
|
Pattern.compile("(" + identifierPattern + "\\.)*" + identifierPattern);
|
||||||
|
|
||||||
|
|
||||||
|
boolean eolNeeded = false;
|
||||||
|
while (true) {
|
||||||
|
int token;
|
||||||
|
|
||||||
|
// Eat one or more EOL, or quit on EOF.
|
||||||
|
int eolStatus = eatEols(st);
|
||||||
|
if (eolStatus < 0) {
|
||||||
|
// EOF occurred.
|
||||||
|
break;
|
||||||
|
} else if (eolNeeded && eolStatus == 0) {
|
||||||
|
throw new ParseException(st, "end of line or end of file");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the property name.
|
||||||
|
token = st.nextToken();
|
||||||
|
if (token != StreamTokenizer.TT_WORD) {
|
||||||
|
throw new ParseException(st, "property name");
|
||||||
|
}
|
||||||
|
final String propertyName = st.sval;
|
||||||
|
if (!propertyNamePattern.matcher(propertyName).matches()) {
|
||||||
|
throw new ParseException(st, "valid property name");
|
||||||
|
}
|
||||||
|
st.sval = null;
|
||||||
|
|
||||||
|
// Read the type.
|
||||||
|
token = st.nextToken();
|
||||||
|
if (token != StreamTokenizer.TT_WORD) {
|
||||||
|
throw new ParseException(st, "type name");
|
||||||
|
}
|
||||||
|
final int type = interpretType(st.sval);
|
||||||
|
if (type == TYPE_ERROR) {
|
||||||
|
throw new ParseException(st, "valid type name");
|
||||||
|
}
|
||||||
|
st.sval = null;
|
||||||
|
|
||||||
|
if (type == TYPE_UNSET) {
|
||||||
|
map.remove(propertyName);
|
||||||
|
} else {
|
||||||
|
// Expect '='.
|
||||||
|
token = st.nextToken();
|
||||||
|
if (token != '=') {
|
||||||
|
throw new ParseException(st, "'='");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a value of the appropriate type, and insert into the map.
|
||||||
|
final Object value = parseValue(st, type);
|
||||||
|
final Object oldValue = map.remove(propertyName);
|
||||||
|
if (oldValue != null) {
|
||||||
|
// TODO: catch the case where a string is set to null and then
|
||||||
|
// the same property is defined with a different type.
|
||||||
|
if (value.getClass() != oldValue.getClass()) {
|
||||||
|
throw new ParseException(st,
|
||||||
|
"(property previously declared as a different type)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
map.put(propertyName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Require that we see at least one EOL before the next token.
|
||||||
|
eolNeeded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the next token in the StreamTokenizer as the specified type.
|
||||||
|
*
|
||||||
|
* @param st The token source
|
||||||
|
* @param type The type to interpret next token as
|
||||||
|
* @return a Boolean, Number subclass, or String representing the value.
|
||||||
|
* Null strings are represented by the String instance NULL_STRING
|
||||||
|
* @throws IOException if there is a problem reading from the {@code StreamTokenizer}
|
||||||
|
*/
|
||||||
|
static Object parseValue(StreamTokenizer st, final int type) throws IOException {
|
||||||
|
final int token = st.nextToken();
|
||||||
|
|
||||||
|
if (type == TYPE_BOOLEAN) {
|
||||||
|
if (token != StreamTokenizer.TT_WORD) {
|
||||||
|
throw new ParseException(st, "boolean constant");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("true".equalsIgnoreCase(st.sval)) {
|
||||||
|
return Boolean.TRUE;
|
||||||
|
} else if ("false".equalsIgnoreCase(st.sval)) {
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ParseException(st, "boolean constant");
|
||||||
|
} else if ((type & 0xff) == 'I') {
|
||||||
|
if (token != StreamTokenizer.TT_WORD) {
|
||||||
|
throw new ParseException(st, "integer constant");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse the string. Long.decode() handles C-style integer constants
|
||||||
|
* ("0x" -> hex, "0" -> octal). It also treats numbers with a prefix of "#" as
|
||||||
|
* hex, but our syntax intentionally does not list '#' as a word character.
|
||||||
|
*/
|
||||||
|
long value;
|
||||||
|
try {
|
||||||
|
value = Long.decode(st.sval);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
throw new ParseException(st, "integer constant");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the type can hold this value, and return.
|
||||||
|
int width = (type >> 8) & 0xff;
|
||||||
|
switch (width) {
|
||||||
|
case 1:
|
||||||
|
if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
|
||||||
|
throw new ParseException(st, "8-bit integer constant");
|
||||||
|
}
|
||||||
|
return new Byte((byte)value);
|
||||||
|
case 2:
|
||||||
|
if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
|
||||||
|
throw new ParseException(st, "16-bit integer constant");
|
||||||
|
}
|
||||||
|
return new Short((short)value);
|
||||||
|
case 4:
|
||||||
|
if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
|
||||||
|
throw new ParseException(st, "32-bit integer constant");
|
||||||
|
}
|
||||||
|
return new Integer((int)value);
|
||||||
|
case 8:
|
||||||
|
if (value < Long.MIN_VALUE || value > Long.MAX_VALUE) {
|
||||||
|
throw new ParseException(st, "64-bit integer constant");
|
||||||
|
}
|
||||||
|
return new Long(value);
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Internal error; unexpected integer type width " + width);
|
||||||
|
}
|
||||||
|
} else if ((type & 0xff) == 'F') {
|
||||||
|
if (token != StreamTokenizer.TT_WORD) {
|
||||||
|
throw new ParseException(st, "float constant");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the string.
|
||||||
|
/* TODO: Maybe just parse as float or double, losing precision if necessary.
|
||||||
|
* Parsing as double and converting to float can change the value
|
||||||
|
* compared to just parsing as float.
|
||||||
|
*/
|
||||||
|
double value;
|
||||||
|
try {
|
||||||
|
/* TODO: detect if the string representation loses precision
|
||||||
|
* when being converted to a double.
|
||||||
|
*/
|
||||||
|
value = Double.parseDouble(st.sval);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
throw new ParseException(st, "float constant");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the type can hold this value, and return.
|
||||||
|
if (((type >> 8) & 0xff) == 4) {
|
||||||
|
// This property is a float; make sure the value fits.
|
||||||
|
double absValue = Math.abs(value);
|
||||||
|
if (absValue != 0.0 && !Double.isInfinite(value) && !Double.isNaN(value)) {
|
||||||
|
if (absValue < Float.MIN_VALUE || absValue > Float.MAX_VALUE) {
|
||||||
|
throw new ParseException(st, "32-bit float constant");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Float((float)value);
|
||||||
|
} else {
|
||||||
|
// This property is a double; no need to truncate.
|
||||||
|
return new Double(value);
|
||||||
|
}
|
||||||
|
} else if (type == TYPE_STRING) {
|
||||||
|
// Expect a quoted string or the word "null".
|
||||||
|
if (token == '"') {
|
||||||
|
return st.sval;
|
||||||
|
} else if (token == StreamTokenizer.TT_WORD && "null".equalsIgnoreCase(st.sval)) {
|
||||||
|
return NULL_STRING;
|
||||||
|
}
|
||||||
|
throw new ParseException(st, "double-quoted string or 'null'");
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Internal error; unknown type " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an empty TypedProperties instance.
|
||||||
|
*/
|
||||||
|
public TypedProperties() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads zero or more properties from the specified Reader.
|
||||||
|
* Properties that have already been loaded are preserved unless
|
||||||
|
* the new Reader overrides or unsets earlier values for the
|
||||||
|
* same properties.
|
||||||
|
*
|
||||||
|
* File syntax:
|
||||||
|
*
|
||||||
|
* <property-name> <type> = <value>
|
||||||
|
* <property-name> unset
|
||||||
|
*
|
||||||
|
* '#' is a comment character; it and anything appearing after it
|
||||||
|
* on the line is ignored.
|
||||||
|
*
|
||||||
|
* Blank lines are ignored.
|
||||||
|
*
|
||||||
|
* The only required whitespace is between the property name
|
||||||
|
* and the type.
|
||||||
|
*
|
||||||
|
* Property assignments may not be split across multiple lines.
|
||||||
|
*
|
||||||
|
* <property-name> is a valid fully-qualified class name
|
||||||
|
* (one or more valid identifiers separated by dot characters).
|
||||||
|
*
|
||||||
|
* <type> is one of {boolean, byte, short, int, long,
|
||||||
|
* float, double, string}, and is case-insensitive.
|
||||||
|
*
|
||||||
|
* <value> depends on the type:
|
||||||
|
* - boolean: one of {true, false} (case-insensitive)
|
||||||
|
* - byte, short, int, long: a valid Java integer constant
|
||||||
|
* (including non-base-10 constants like 0xabc and 074)
|
||||||
|
* whose value does not overflow the type. NOTE: these are
|
||||||
|
* interpreted as Java integer values, so they are all signed.
|
||||||
|
* - float, double: a valid Java floating-point constant.
|
||||||
|
* If the type is float, the value must fit in 32 bits.
|
||||||
|
* - string: a double-quoted string value, or the word {@code null}.
|
||||||
|
* NOTE: the contents of the string must be 7-bit clean ASCII;
|
||||||
|
* C-style octal escapes are recognized, but Unicode escapes are not.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param r The Reader to load properties from
|
||||||
|
* @throws IOException if an error occurs when reading the data
|
||||||
|
* @throws IllegalArgumentException if the data is malformed
|
||||||
|
*/
|
||||||
|
public void load(Reader r) throws IOException {
|
||||||
|
parse(r, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(Object key) {
|
||||||
|
Object value = super.get(key);
|
||||||
|
if (value == NULL_STRING) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Getters with explicit defaults
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An unchecked exception that is thrown if a {@code get<TYPE>()} method
|
||||||
|
* is used to retrieve a parameter whose type does not match the method name.
|
||||||
|
*/
|
||||||
|
public static class TypeException extends IllegalArgumentException {
|
||||||
|
TypeException(String property, Object value, String requestedType) {
|
||||||
|
super(property + " has type " + value.getClass().getName() +
|
||||||
|
", not " + requestedType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a boolean property, or the default if the property
|
||||||
|
* has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @param def The default value to return if the property is not set
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a boolean
|
||||||
|
*/
|
||||||
|
public boolean getBoolean(String property, boolean def) {
|
||||||
|
Object value = super.get(property);
|
||||||
|
if (value == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
if (value instanceof Boolean) {
|
||||||
|
return ((Boolean)value).booleanValue();
|
||||||
|
}
|
||||||
|
throw new TypeException(property, value, "boolean");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a byte property, or the default if the property
|
||||||
|
* has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @param def The default value to return if the property is not set
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a byte
|
||||||
|
*/
|
||||||
|
public byte getByte(String property, byte def) {
|
||||||
|
Object value = super.get(property);
|
||||||
|
if (value == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
if (value instanceof Byte) {
|
||||||
|
return ((Byte)value).byteValue();
|
||||||
|
}
|
||||||
|
throw new TypeException(property, value, "byte");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a short property, or the default if the property
|
||||||
|
* has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @param def The default value to return if the property is not set
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a short
|
||||||
|
*/
|
||||||
|
public short getShort(String property, short def) {
|
||||||
|
Object value = super.get(property);
|
||||||
|
if (value == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
if (value instanceof Short) {
|
||||||
|
return ((Short)value).shortValue();
|
||||||
|
}
|
||||||
|
throw new TypeException(property, value, "short");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of an integer property, or the default if the property
|
||||||
|
* has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @param def The default value to return if the property is not set
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not an integer
|
||||||
|
*/
|
||||||
|
public int getInt(String property, int def) {
|
||||||
|
Object value = super.get(property);
|
||||||
|
if (value == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
if (value instanceof Integer) {
|
||||||
|
return ((Integer)value).intValue();
|
||||||
|
}
|
||||||
|
throw new TypeException(property, value, "int");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a long property, or the default if the property
|
||||||
|
* has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @param def The default value to return if the property is not set
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a long
|
||||||
|
*/
|
||||||
|
public long getLong(String property, long def) {
|
||||||
|
Object value = super.get(property);
|
||||||
|
if (value == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
if (value instanceof Long) {
|
||||||
|
return ((Long)value).longValue();
|
||||||
|
}
|
||||||
|
throw new TypeException(property, value, "long");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a float property, or the default if the property
|
||||||
|
* has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @param def The default value to return if the property is not set
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a float
|
||||||
|
*/
|
||||||
|
public float getFloat(String property, float def) {
|
||||||
|
Object value = super.get(property);
|
||||||
|
if (value == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
if (value instanceof Float) {
|
||||||
|
return ((Float)value).floatValue();
|
||||||
|
}
|
||||||
|
throw new TypeException(property, value, "float");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a double property, or the default if the property
|
||||||
|
* has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @param def The default value to return if the property is not set
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a double
|
||||||
|
*/
|
||||||
|
public double getDouble(String property, double def) {
|
||||||
|
Object value = super.get(property);
|
||||||
|
if (value == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
if (value instanceof Double) {
|
||||||
|
return ((Double)value).doubleValue();
|
||||||
|
}
|
||||||
|
throw new TypeException(property, value, "double");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a string property, or the default if the property
|
||||||
|
* has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @param def The default value to return if the property is not set
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a string
|
||||||
|
*/
|
||||||
|
public String getString(String property, String def) {
|
||||||
|
Object value = super.get(property);
|
||||||
|
if (value == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
if (value == NULL_STRING) {
|
||||||
|
return null;
|
||||||
|
} else if (value instanceof String) {
|
||||||
|
return (String)value;
|
||||||
|
}
|
||||||
|
throw new TypeException(property, value, "string");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Getters with implicit defaults
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a boolean property, or false
|
||||||
|
* if the property has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a boolean
|
||||||
|
*/
|
||||||
|
public boolean getBoolean(String property) {
|
||||||
|
return getBoolean(property, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a byte property, or 0
|
||||||
|
* if the property has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a byte
|
||||||
|
*/
|
||||||
|
public byte getByte(String property) {
|
||||||
|
return getByte(property, (byte)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a short property, or 0
|
||||||
|
* if the property has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a short
|
||||||
|
*/
|
||||||
|
public short getShort(String property) {
|
||||||
|
return getShort(property, (short)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of an integer property, or 0
|
||||||
|
* if the property has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not an integer
|
||||||
|
*/
|
||||||
|
public int getInt(String property) {
|
||||||
|
return getInt(property, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a long property, or 0
|
||||||
|
* if the property has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a long
|
||||||
|
*/
|
||||||
|
public long getLong(String property) {
|
||||||
|
return getLong(property, 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a float property, or 0.0
|
||||||
|
* if the property has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a float
|
||||||
|
*/
|
||||||
|
public float getFloat(String property) {
|
||||||
|
return getFloat(property, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a double property, or 0.0
|
||||||
|
* if the property has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a double
|
||||||
|
*/
|
||||||
|
public double getDouble(String property) {
|
||||||
|
return getDouble(property, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a String property, or ""
|
||||||
|
* if the property has not been defined.
|
||||||
|
*
|
||||||
|
* @param property The name of the property to return
|
||||||
|
* @return the value of the property
|
||||||
|
* @throws TypeException if the property is set and is not a string
|
||||||
|
*/
|
||||||
|
public String getString(String property) {
|
||||||
|
return getString(property, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user