package treeProperties;
/**
* TreeProperties.java
*
* Created on 19.08.2009
*/
import static java.lang.String.*;
import static java.util.Collections.*;
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.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;
import treeProperties.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
*
* @version V0.0 19.08.2009
* @author Clemens Koza
* @see Properties
*/
public class TreeProperties implements Iterable {
private static final Map> suffixes;
private static final Map, PropertyType>> types;
private static final String transparent = "transparent-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;
public static void addType(PropertyType> type) {
types.put(type.getType(), type);
suffixes.put(type.getSuffix(), type);
}
public static void removeType(PropertyType> type) {
types.remove(type.getType());
suffixes.remove(type.getSuffix());
}
/**
* Delegate to {@link #TreeProperties(File)} with a new {@link File#File(String)}
*/
public TreeProperties(String f) throws IOException {
this(new File(f));
}
/**
* Delegate to {@link #TreeProperties(File)} with a new {@link File#File(File, String)}
*/
public TreeProperties(File parent, 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.
*/
public TreeProperties(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