Há um bug na API java.util.prefs (bug nº 4772228 no Bug Database da Sun) rodando em Windows: como os métodos Preferences.userNodeForPackage(java.lang.Class) e Preferences.systemNodeForPackage(java.lang.class) utilizam o registro do Windows para guardar e recuperar as informações de preferências, programas rodando em contas de usuários sem privilégios de administrador não conseguem ler as preferências.
Como precisamos implementar preferências de usuário persistentes em um programa, implementamos uma classe XMLPreferences que faz exatamente o que a AbstractPreferences determina, utilizando a DTD definida pela Sun para preferências; usamos DOM para armazenar e recuperar preferências em arquivos XML, e escapar assim do registro.
Se alguém precisar da Preferences funcionando, manda um e-mail que eu repasso, ok? A implementação está meio vagabunda e precisa de melhoras, mas acho que é um bom começo.
Nãããããooooo!!! Não comecem mais uma feira-livre aqui no fórum. escordeiro, por favor, se for possível, disponibilize o código aqui no fórum. Ou, melhor ainda, faça um mini-tutorialzinho descrevendo sua solução.
Daniel, um mini-tutorial não vai dar, mas acho que pelos comentários dá pra entender. A implementação está meio ruim e tem um método que nós não implementamos, mas para o básico está funcionando. :oops:
Temos duas classes para fazer o negócio funcionar: XMLPreferences, que é a implementação de Preferences propriamente dita, e PreferencesController, que é um Singleton que mantém o documento XML e permite o uso da XMLPreferences.
/*
XMLPreferences.java
*/
import java.util.Vector;
import java.util.prefs.AbstractPreferences;
import java.util.prefs.BackingStoreException;
import org.w3c.dom.*;
/**
* This implementation of AbstractPreferences contains the SPI methods
* as defined in java.util.prefs.AbstractPreferences. These SPI iplementations
* make the preferences backing store an XML file. To avoid disk read-write
* issues, the Document tree is only saved to a file when the 'flush' method
* is called.
*
* This class assumes that there is a PreferencesController singleton object,
* which will take care of creating or loading an XML file to a DOM Document.
*
* Though the DTD provided for the preferences API has been followed in this
* implementation, the current DOM API doesn't provide a method to set a
* Document's DOCTYPE, so no DOCTYPE will be seen on XML files generated
* by this implementation.
*
* @author Eduardo S. Cordeiro and Tays C. A. P. Soares
*/
public class XMLPreferences extends AbstractPreferences {
/**
* Creates an instance of a preferences node, and sets the 'newNode'
* flag to null.
* @param parent the parent of this node
* @param name the name of this node
*/
public XMLPreferences(AbstractPreferences parent, String name) {
super(parent, name);
newNode = true;
}
/**
* Requests the PreferencesController to save the preferences tree
* to the backing store. Please note that, though the AbstractPreferences
* method signature defines that this method should throw a BackingStoreException,
* this implementation doesn't.
*/
protected void flushSpi() throws BackingStoreException {
PreferencesController.getInstance().savePreferences();
}
/**
* Removes this node from the backing store. Please note that, though the
* AbstractPreferences method signature defines that this method should
* throw a BackingStoreException, this implementation doesn't.
*/
protected void removeNodeSpi() throws BackingStoreException {
org.w3c.dom.Node root = PreferencesController.getInstance().getXMLDocument().getDocumentElement();
Element my_node = myXMLNode();
Element parent_node = (Element)my_node.getParentNode();
if(root.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
Element doc_root = (Element) root;
parent_node.removeChild(my_node);
}
}
/**
* Not implemented, but a future TO-DO.
*/
protected void syncSpi() throws BackingStoreException {}
/**
* Retrieves a String array with the names of this node's children from
* the backing store. Please note that, though the AbstractPreferences
* method signature defines that this method should throw a BackingStoreException,
* this implementation doesn't.
* @return a String array with the names of this node's children
*/
protected String[] childrenNamesSpi() throws BackingStoreException {
Element node = myXMLNode();
Vector node_names = null;
if (node != null) {
NodeList children = node.getChildNodes();
node_names = new Vector();
for (int i=0 ; i<children.getLength() ; i++) {
Element child = (Element)children.item(i);
if (child.getTagName().equals("node"))
node_names.addElement(child.getAttribute("name"));
}
}
String[] names = new String[node_names.size()];
for (int i=0 ; i<names.length ; i++)
names[i] = (String)node_names.elementAt(i);
return names;
}
/**
* Retrieves a String array with the keys assigned to this node from the
* backing store. Please note that, though the AbstractPreferences
* method signature defines that this method should throw a BackingStoreException,
* this implementation doesn't.
* @return a String array with the keys assigned to this node
*/
protected String[] keysSpi() throws BackingStoreException {
Element node = myXMLNode();
String[] keys = null;
if (node != null) {
NodeList entries = myEntries();
keys = new String[entries.getLength()];
for (int i=0 ; i<entries.getLength() ; i++) {
Element entry = (Element)entries.item(i);
keys[i] = entry.getAttribute("key");
}
}
return keys;
}
/**
* Removes a given key from this node on the backing store.
* @param key the key to be removed
*/
protected void removeSpi(String key) {
Element node = myXMLNode();
if (node != null) {
Element map = (Element)node.getElementsByTagName("map").item(0);
NodeList entries = myEntries();
for (int i=0 ; i<entries.getLength() ; i++) {
Element entry = (Element)entries.item(i);
String node_key = entry.getAttribute("key");
if (node_key.equals(key)) {
map.removeChild(entry);
}
}
}
}
/**
* Retrieves the value associated to a given key from this node from the
* backing store.
* @param key the key whose value will be retrieved
* @return the value associated to the given key, if this node contains such
* a pair, or null otherwise
*/
protected String getSpi(String key) {
Element node = myXMLNode();
if (node != null) {
NodeList entries = myEntries();
boolean key_exists = false;
// test whether or not the node already contains the given key
for (int j=0 ; j<entries.getLength() ; j++) {
Element entry = (Element)entries.item(j);
String node_key = entry.getAttribute("key");
if (node_key.equals(key)) {
return entry.getAttribute("value");
}
}
}
return null;
}
/**
* Sets a key-value pair on this node, on the backing store. If this node
* doesn't contain the given key, this pair will be created on the backing
* store.
* @param key the key to be set
* @param the value to be set on the given key
*/
protected void putSpi(String key, String value) {
Element node = myXMLNode();
if (node != null) {
Element map = (Element)node.getElementsByTagName("map").item(0);
NodeList entries = myEntries();
boolean key_exists = false;
// test whether or not the node already contains the given key
for (int j=0 ; j<entries.getLength() ; j++) {
Element entry = (Element)entries.item(j);
String node_key = entry.getAttribute("key");
if (node_key.equals(key)) {
entry.setAttribute("value",value);
key_exists = true;
}
}
// if the entry doesn't already exist, create it and append it to this node
if (!key_exists) {
Element entry = PreferencesController.getInstance().getXMLDocument().createElement("entry");
entry.setAttribute("key",key);
entry.setAttribute("value",value);
map.appendChild(entry);
}
}
}
/**
* Retrieves this node's child with the given name from the backing store. If
* such a child doesn't exist, one will be created.
* @param name the name of the desired child
* @return the desired node, which will have the 'newNode' flag set if it didn't
* exist before this method
*/
protected AbstractPreferences childSpi(String name) {
Element node = myXMLNode();
if (node != null) {
NodeList children = node.getElementsByTagName("node");
for (int i=0 ; i<children.getLength() ; i++) {
Element child = (Element)children.item(i);
String child_name = child.getAttribute("name");
if (child_name.equals(name))
return createPreferencesFromElement(child,child_name);
}
// the child doesn't exist, so one will be created
AbstractPreferences prefs = new XMLPreferences(this,name);
Element new_node = PreferencesController.getInstance().getXMLDocument().createElement("node");
Element map = PreferencesController.getInstance().getXMLDocument().createElement("map");
new_node.appendChild(map);
new_node.setAttribute("name",name);
node.appendChild(new_node);
return prefs;
}
return null;
}
/**
* Creates a preferences node from an XML element.
* @param child the XML element whose node will be created
* @return the newly created preferences node
*/
private AbstractPreferences createPreferencesFromElement(Element child, String name) {
AbstractPreferences prefs = new XMLPreferences(this,name);
NodeList map = child.getElementsByTagName("map");
NodeList entries = ((Element)map.item(0)).getElementsByTagName("entry");
for (int i=0 ; i<entries.getLength() ; i++) {
Element entry = (Element)entries.item(i);
prefs.put(entry.getAttribute("key"),entry.getAttribute("value"));
}
return prefs;
}
/**
* Retrieves a DOM/XML Element that represents this node on the backing store.
* @return
*/
private Element myXMLNode() {
org.w3c.dom.Node root = PreferencesController.getInstance().getXMLDocument().getDocumentElement();
if(root.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
Element doc_root = (Element)root;
Element prefs_root = (Element)doc_root.getElementsByTagName("root").item(0);
// checks whether this node is the root
if (this.name().equals(""))
return prefs_root;
// fetch the node with the name of this preferences node
Element my_node = findNode(prefs_root,this.name());
return my_node;
}
return null;
}
/**
* Recursively finds a node on the DOM/XML tree.
* @param parent the parent of nodes to be searched in a recursive
* call of this method
* @param name the name of the desired Element
* @return the desired Element if it is found, or null otherwise
*/
private Element findNode(Element parent, String name) {
NodeList children = parent.getElementsByTagName("node");
for (int i=0 ; i<children.getLength() ; i++) {
Element child = (Element)children.item(i);
String child_name = child.getAttribute("name");
if (child_name.equals(name))
return child;
else {
Element searched = findNode(child,name);
if (searched != null)
return searched;
}
}
return null;
}
/**
* Retrieves the DOM nodes that represent this preference's entries from
* the backing store.
* @return a NodeList with the entries in this preferences node
*/
private NodeList myEntries() {
Element node = myXMLNode();
if (node != null) {
NodeList map = node.getElementsByTagName("map");
return ((Element)map.item(0)).getElementsByTagName("entry");
}
return null;
}
/**
* Retrieves the String value associated with the given key from this preferences
* node, from the backing store.
* @param key the key of the desired entry
* @param def the default value to be set if the desired pair doesn't yet exist
* on the backing store
* @return the desired value
*/
public String get(String key, String def) {
String value = getSpi(key);
if (value == null)
this.put(key,def);
else
return value;
return getSpi(key);
}
/**
* Retrieves the boolean value associated with the given key from this preferences
* node, from the backing store.
* @param key the key of the desired entry
* @param def the default value to be set if the desired pair doesn't yet exist
* on the backing store
* @return the desired value
*/
public boolean getBoolean(String key, boolean def) {
String value = getSpi(key);
if (value == null) {
this.putBoolean(key,def);
return Boolean.getBoolean(getSpi(key));
}
else if (value.equals("true"))
return true;
else
return false;
}
/**
* Retrieves the double value associated with the given key from this preferences
* node, from the backing store.
* @param key the key of the desired entry
* @param def the default value to be set if the desired pair doesn't yet exist
* on the backing store
* @return the desired value
*/
public double getDouble(String key, double def) {
String value = getSpi(key);
if (value == null) {
this.putDouble(key,def);
return Double.parseDouble(getSpi(key));
}
else
return Double.parseDouble(value);
}
/**
* Retrieves the float value associated with the given key from this preferences
* node, from the backing store.
* @param key the key of the desired entry
* @param def the default value to be set if the desired pair doesn't yet exist
* on the backing store
* @return the desired value
*/
public float getFloat(String key, float def) {
String value = getSpi(key);
if (value == null) {
this.putFloat(key,def);
return Float.parseFloat(getSpi(key));
}
else
return Float.parseFloat(value);
}
/**
* Retrieves the String value associated with the given key from this preferences
* node, from the backing store.
* @param key the key of the desired entry
* @param def the default value to be set if the desired pair doesn't yet exist
* on the backing store
* @return the desired value
*/
public int getInt(String key, int def) {
String value = getSpi(key);
if (value == null) {
this.putInt(key,def);
return Integer.parseInt(getSpi(key));
}
else
return Integer.parseInt(value);
}
/**
* Retrieves the long value associated with the given key from this preferences
* node, from the backing store.
* @param key the key of the desired entry
* @param def the default value to be set if the desired pair doesn't yet exist
* on the backing store
* @return the desired value
*/
public long getLong(String key, long def) {
String value = getSpi(key);
if (value == null) {
this.putLong(key,def);
return Long.parseLong(getSpi(key));
}
else
return Long.parseLong(value);
}
/**
* Retrieves the 'newNode' flag for this node, which indicates whether or not
* it has been recently created.
* @return true if this node is new, false otherwise
*/
public boolean newNode() {
return newNode;
}
/**
* Sets this node's 'newNode' flag to false, to indicate that it has already
* been recognized as a new node and this value is no longer needed, or
* that this node should no longer be used as a new node
*/
public void setNotNewNode() {
newNode = false;
}
}
A PreferencesController faz um pequeno “desvio” do preferences original: ela é implementada de forma que a árvore de preferências tenha o nodo raiz, seus filhos sejam categorias de preferências, e os filhos das categorias sejam os valores de preferências propriamente ditos; só que esses valores são guardados na forma de duas keys - uma indica o tipo do valor, e a outra o valor do valor :roll: . Fizemos esse “desvio” para podermos criar uma interface dinâmica de preferências, que cria uma lista com as categorias e, quando clica-se em uma categoria da lista, um painel é aberto para exibir os valores de preferências. Só que, como cada tipo tem uma visão mais eficiente (como checkbox para boolean, caixinha para int e String e JColorChooser para cores), precisamos avaliar o tipo do valor durante a execução…
/*
PreferencesController.java
*/
import java.io.*;
import java.awt.Color;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import graph_editor.prefs.*;
/**
* This class is responsible for controlling the user XMLPreferences, which
* will be used throughout the program to allow persistence of these
* settings.
* The tree is composed in the following way: there is a root node that
* will cluster several property categories. Each category is a different
* node and will contain several children, each of which represents a
* preferences value to the program.
* Each preference value is a node, child
* of a category, and will contain two items: a value and a type. This is
* used to indicate to the program the type of the preference, in case it
* needs to be known in run-time.
*/
public class PreferencesController {
/**
* The properties category's identifier.
*/
public final static String PROPERTIES_CATEGORY = "Properties";
/**
* The performance category's identifier.
*/
public final static String PERFORMANCE_CATEGORY = "Performance";
/**
* The edge color property's identifier.
*/
public final static String EDGE_COLOR_PROPERTY = "Edge color";
/**
* The node color property's identifier.
*/
public final static String NODE_COLOR_PROPERTY = "Node color";
/**
* The anti-aliasing property's identifier.
*/
public final static String ANTIALIASING_PROPERTY = "Anti-aliasing";
/**
* The path in the filesystem to the XMLPreferences file.
*/
private final static String PREFERENCES_PATH = ".//user//.preferences";
/**
* A String that will represent an integer type.
*/
public final static String TYPE_INT = "int";
/**
* A String that will represent a double type.
*/
public final static String TYPE_DOUBLE = "double";
/**
* A String that will represent a boolean type.
*/
public final static String TYPE_BOOLEAN = "boolean";
/**
* A String that will represent a color type.
*/
public final static String TYPE_COLOR = "color";
/**
* A String that will represent a string type.
*/
public final static String TYPE_STRING = "string";
/**
* A String that will represent a type node.
*/
public final static String TYPE = "type";
/**
* A String that will represent a value node.
*/
public final static String VALUE = "value";
/**
* The unique instance to this class.
*/
private static PreferencesController instance;
/**
* The DOM document that will accesses the xml document
*/
private static Document prefs_document = null;
/**
* The tree's root node for user XMLPreferences.
*/
private static XMLPreferences root_prefs;
/**
* Creates an instance of this class and the root XMLPreferences node.
*/
protected PreferencesController() {
}
/**
* Retrieves the unique instance to this class.
* @return the unique instance to this class
*/
public static PreferencesController getInstance() {
if (instance == null) {
instance = new PreferencesController();
loadPreferences();
}
return instance;
}
/**
* Adds a new XMLPreferences category to the XMLPreferences tree; each
* category will be a leaf in the XMLPreferences tree.
* @param name the new XMLPreferences category
*/
public void addCategory(String name) {
XMLPreferences new_node = (XMLPreferences)root_prefs.node(name);
}
/**
* Puts an int value into a XMLPreferences category.
* @param category_name the name of the category
* @param key the key of the new value
* @param value the default value
*/
public void putInt(String category_name, String key, int value) {
XMLPreferences node = (XMLPreferences) root_prefs.node(category_name).node(key);
node.put(TYPE,TYPE_INT);
node.putInt(VALUE,value);
}
/**
* Puts a double value into a XMLPreferences category.
* @param category_name the name of the category
* @param key the key of the new value
* @param value the default value
*/
public void putDouble(String category_name, String key, double value) {
XMLPreferences node = (XMLPreferences) root_prefs.node(category_name).node(key);
node.put(TYPE,TYPE_DOUBLE);
node.putDouble(VALUE,value);
}
/**
* Puts a boolean value into a XMLPreferences category.
* @param category_name the name of the category
* @param key the key of the new value
* @param value the default value
*/
public void putBoolean(String category_name, String key, boolean value) {
XMLPreferences node = (XMLPreferences) root_prefs.node(category_name).node(key);
node.put(TYPE,TYPE_BOOLEAN);
node.putBoolean(VALUE,value);
}
/**
* Puts a String value into a XMLPreferences category.
* @param category_name the name of the category
* @param key the key of the new value
* @param value the default value
*/
public void put(String category_name, String key, String value) {
XMLPreferences node = (XMLPreferences) root_prefs.node(category_name).node(key);
node.put(TYPE,TYPE_STRING);
node.put(VALUE,value);
}
/**
* Puts a Color value into a XMLPreferences category.
* @param category_name the name of the category
* @param key the key of the new value
* @param value the default value
*/
public void putColor(String category_name, String key, Color value) {
XMLPreferences node = (XMLPreferences) root_prefs.node(category_name).node(key);
node.put(TYPE,TYPE_COLOR);
node.putInt(VALUE,value.getRGB());
}
/**
* Retrieves the int value in the specified category; the default value
* will be set if the category isn't found.
* @param category_name the name of the category
* @param key the key of the value
* @param def the default value
* @return the desired value, if it is found, or the default otherwise
*/
public int getInt(String category_name, String key, int def) {
XMLPreferences node = (XMLPreferences) root_prefs.node(category_name + "/" + key);
if (node.newNode()) {
this.putInt(category_name,key,def);
node.setNotNewNode();
}
return node.getInt(VALUE,def);
}
/**
* Retrieves the double value in the specified category; the default value
* will be set if the category isn't found.
* @param category_name the name of the category
* @param key the key of the value
* @param def the default value
* @return the desired value, if it is found, or the default otherwise
*/
public double getDouble(String category_name, String key, double def) {
XMLPreferences node = (XMLPreferences) root_prefs.node(category_name + "/" + key);
if (node.newNode()) {
this.putDouble(category_name,key,def);
node.setNotNewNode();
}
return node.getDouble(VALUE,def);
}
/**
* Retrieves the boolean value in the specified category; the default value
* will be set if the category isn't found.
* @param category_name the name of the category
* @param key the key of the value
* @param def the default value
* @return the desired value, if it is found, or the default otherwise
*/
public boolean getBoolean(String category_name, String key, boolean def) {
XMLPreferences node = (XMLPreferences) root_prefs.node(category_name + "/" + key);
if (node.newNode()) {
this.putBoolean(category_name,key,def);
node.setNotNewNode();
}
return node.getBoolean(VALUE,def);
}
/**
* Retrieves the String value in the specified category; the default value
* will be set if the category isn't found.
* @param category_name the name of the category
* @param key the key of the value
* @param def the default value
* @return the desired value, if it is found, or the default otherwise
*/
public String get(String category_name, String key, String def) {
XMLPreferences node = (XMLPreferences) root_prefs.node(category_name + "/" + key);
if (node.newNode()) {
this.put(category_name,key,def);
node.setNotNewNode();
}
return node.get(VALUE,def);
}
/**
* Retrieves the Color value in the specified category; the default value
* will be set if the category isn't found.
* @param category_name the name of the category
* @param key the key of the value
* @param def the default value
* @return the desired value, if it is found, or the default otherwise
*/
public Color getColor(String category_name, String key, Color def) {
XMLPreferences node = (XMLPreferences) root_prefs.node(category_name + "/" + key);
if (node.newNode()) {
this.putColor(category_name,key,def);
node.setNotNewNode();
}
return new Color(node.getInt(VALUE,def.getRGB()));
}
/**
* Flushes the XMLPreferences to the output file for persistence.
*/
public void savePreferences() {
try {
File pref_file = new File(PREFERENCES_PATH);
if(!pref_file.exists())
pref_file.createNewFile();
// save the XML tree to the XMLPreferences file
DOMSource source = new DOMSource(prefs_document);
StreamResult sr = new StreamResult(pref_file);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(source, sr);
}
catch(IOException exc) {
exc.printStackTrace();
} catch (TransformerConfigurationException exc) {
exc.printStackTrace();
} catch (TransformerFactoryConfigurationError exc) {
exc.printStackTrace();
} catch (TransformerException exc) {
exc.printStackTrace();
}
}
/**
* Loads the existing XMLPreferences file into the program's XMLPreferences
* tree; if the file does not exist, an IOException will be caught and
* no settings will be imported.
* @return the DOM Document to be used by all the preferences nodes
*/
public static Document loadPreferences() {
File xml_prefs = new File(PREFERENCES_PATH);
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
DocumentBuilder builder = factory.newDocumentBuilder();
if (xml_prefs.exists()){
prefs_document = builder.parse(xml_prefs);
buildPreferencesFromDocument();
}
else {
prefs_document = builder.newDocument();
// TODO set DOCTYPE
// create root node and its map
Element prefs = prefs_document.createElement("preferences");
prefs.setAttribute("EXTERNAL_XML_VERSION","1.0");
prefs_document.appendChild(prefs);
Element root = prefs_document.createElement("root");
root.setAttribute("type","user");
Element root_map = prefs_document.createElement("map");
root.appendChild(root_map);
prefs.appendChild(root);
root_prefs = new XMLPreferences(null,"");
}
}catch (ParserConfigurationException e){
e.printStackTrace();
}catch (SAXException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
return prefs_document;
}
/**
* Starts the creation of the preferences tree from the DOM/XML Document.
* This method will retrieve the 'root' Element from the DOM Document and
* call the recursive 'buildPreferences' method upon it to start the
* creation of the preferences tree.
*/
private static void buildPreferencesFromDocument() {
Element doc_root = (Element)(prefs_document.getElementsByTagName("root").item(0));
buildPreferences(doc_root,null);
}
/**
* Recursively builds the preferences tree from the DOM Element nodes. This method
* should be called initially for the 'root' Element, since it will build
* an XMLPreferences instance for the given node and call itself upon its
* children.
* @param node the DOM Element node for which an XMLPreferences instance
* will be created
* @param parent the parent of the node
*/
private static void buildPreferences(Element node,XMLPreferences parent) {
NodeList children = node.getChildNodes();
XMLPreferences prefs = null;
if (parent != null)
prefs = (XMLPreferences)parent.node(node.getAttribute("name"));
else
prefs = new XMLPreferences(null,"");
if (children.getLength() != 0) {
Element map = (Element)children.item(0);
NodeList entries = map.getElementsByTagName("entry");
for (int i=0 ; i<entries.getLength() ; i++) {
Element entry = (Element)entries.item(0);
prefs.put(entry.getAttribute("key"),entry.getAttribute("value"));
}
for (int i=1 ; i<children.getLength() ; i++)
buildPreferences((Element)children.item(i),prefs);
}
prefs.setNotNewNode();
if (parent == null)
root_prefs = prefs;
}
/**
* Retrieves the root node in the XMLPreferences tree.
* @return the root node in the XMLPreferences tree
*/
public XMLPreferences getRoot() {
return root_prefs;
}
/**
* Retrieves the DOM document for the Preferences XML tree.
* @return the DOM document for the Preferences XML tree
*/
public Document getXMLDocument() {
return prefs_document;
}
/**
*
* @param doc
*/
public void setXMLDocument(Document doc) {
prefs_document = doc;
}
}
:!: Disclaimer:
Aqueles nomes propriedades e categorias estáticas da classe PreferencesController fazem parte do nosso programa, mas estão aí apenas para exemplificar categorias e valores que utilizamos. Além disso, nem todos os tipos suportados por Preferences estão no PreferencesController…digamos que isso é pura preguiça :shock: .
Por favor, critiquem e comentem, acho que dá pra melhorar bastante esse código.