package tree.properties;
/**
* TreeProperties.java
*
* Created on 19.08.2009
*/
import static java.lang.String.format;
import static java.util.Collections.unmodifiableList;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import tree.properties.types.FileType;
/**
* The class TreeProperties. This class allows for a tree-like structure of
* properties-files. This class lays some restrictions on the keys used in
* properties-files:
*
*
The use of "--" is forbidden
*
The suffixes "--properties" and "--transparent-properties" are reserved
* for specifying additional properties-files in the tree (relative paths are
* relative to the properties-file where they are referenced)
*
Other suffixes are used by {@link PropertyType}s. PropertyTypes are
* registered or unregistered using {@link #addType(PropertyType)} or
* {@link #removeType(PropertyType)}.
*
* Take a look at these files:
*
*
*
* #root.properties
* title=directions
* icons--properties=img/icons.properties
*
* #img/icons.properties
* left--file=left.jpg
* right--file=right.jpg
* up--file=up.jpg
* down--file=down.jpg
* #note that the path does not contain "img/"
* size--transparent-properties=size.properties
*
* #img/size.properties
* width=20
* height=20
*
*
* As you can see, a properties file included with "--transparent-properties"
* hides its existence from the user. A file included with "--properties" is not
* hidden. The child properties are accessible as if their keys were prepended
* with the parent key, separated by a slash.
*
* Note that --file, --properties and --transparent-properties entries will be
* relative to the included file, even if the properties file is transparent.
*
* Also, the TreeProperties can be retrieved:
*
*
*
*
*
* TODO add edit & save support
*
* @author Clemens Koza
* @version V0.0 19.08.2009
* @see Properties
*/
public class TreeProperties implements Iterable {
/** Constant suffixes. */
private static final Map> SUFFIXES;
/** Constant types. */
private static final Map, PropertyType>> TYPES;
/** Constant transparent="transparent-properties". */
private static final String TRANSPARENT = "transparent-properties";
/** Constant child="properties". */
private static final String CHILD = "properties";
static {
TYPES = new HashMap, PropertyType>>();
SUFFIXES = new HashMap>();
PropertyType>[] pt = {new FileType()};
for (PropertyType> type : pt) {
addType(type);
}
}
private File path;
private Map, PropertyType>> instanceTypes;
private Map> instanceSuffixes;
private HashMap properties;
private List exceptions;
/**
*
* addType.
*
*
* @param type
* a {@link treeProperties.PropertyType} object.
*/
public static void addType(final PropertyType> type) {
TYPES.put(type.getType(), type);
SUFFIXES.put(type.getSuffix(), type);
}
/**
*
* removeType.
*
*
* @param type
* a {@link treeProperties.PropertyType} object.
*/
public static void removeType(final PropertyType> type) {
TYPES.remove(type.getType());
SUFFIXES.remove(type.getSuffix());
}
/**
* Delegate to {@link #TreeProperties(File)} with a new
* {@link File#File(String)}.
*
* @param f
* a {@link java.lang.String} object.
* @throws java.io.IOException
* if any.
*/
public TreeProperties(final String f) throws IOException {
this(new File(f));
}
/**
* Delegate to {@link #TreeProperties(File)} with a new
* {@link File#File(File, String)}.
*
* @param parent
* a {@link java.io.File} object.
* @param f
* a {@link java.lang.String} object.
* @throws java.io.IOException
* if any.
*/
public TreeProperties(final File parent, final String f) throws IOException {
this(new File(parent, f));
}
/**
* The constructor is forgiving in the way that Exceptions are not directly
* forwarded. The only fatal exception is if the parameter is null or not
* found. Instead, the rest of the properties are processed, so that the
* erroneous properties are the only ones not present in this
* TreeProperties. Afterwards, the exceptions can be accessed.
*
* @param f
* a {@link java.io.File} object.
* @throws java.io.IOException
* if any.
*/
public TreeProperties(final File f) throws IOException {
if (f == null) {
throw new FileNotFoundException("null");
}
this.path = f.getParentFile();
instanceTypes = new HashMap, PropertyType>>(TYPES);
instanceSuffixes = new HashMap>(SUFFIXES);
Properties p = new Properties();
// BufferedReader r = new BufferedReader(new FileReader(f));
// p.load(r);
// r.close();
BufferedInputStream is = new BufferedInputStream(new FileInputStream(f));
p.load(is);
is.close();
Set> entries = p.entrySet();
properties = new HashMap();
List exceptions = new ArrayList();
this.exceptions = unmodifiableList(exceptions);
for (Entry