package hu.ppke.itk.itkStock.client;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.Namespace;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
/**
* A settings singleton for the client.<br>
* If any setting changes, the settings file will be reparsed entirely.
*
*/
public enum ClientSettings {
INSTANCE;
private int port;
private String hostname;
/**
* Consturctor<br>
* Invokes load() method to get the settings from the 'ClientConfig.xml' file<br>
* If file not present, generates default values to default 'ServerConfig.xml' file
*/
private ClientSettings()
{
load();
}
/**
* This methods load the configuration file, if not present, generates one with default values.
*/
private void load()
{
try {
parseFile("ClientConfig.xml");
} catch (JDOMException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
System.err.println("File not found!\nGenerating default values to \'ClientConfig.xml\'");
generateDefualt();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* This method parses XML config file with given nodes. Only the given nodes will be parsed, <br>
* they have to be in a specific order defined in the XML Scheme. Although it does not matter for <br>
* the parser.<br>
*
* @param filename The name of the file to be parsed
* @throws JDOMException
* @throws IOException
*/
private void parseFile(String filename) throws JDOMException, IOException
{
SAXBuilder builder = new SAXBuilder(/*XMLReaders.XSDVALIDATING*/);
Document doc = builder.build(filename);
Element root = doc.getRootElement();
port = xmlGetPort(root);
hostname = xmlGetHostname(root);
}
/**
* This method generates the default values for each option.<br>
* The default values will be parsed to an XML file, and reopened for reloading configuration.
*/
private void generateDefualt()
{
System.out.println("Generating default values...");
Element root = makeRoot();
//TODO generate default values to config file
root.addContent(new Element("connection")
.addContent(new Element("port").setText("3306"))
.addContent(new Element("hostname").setText("localhost")));
makeFile(root);
System.out.println("Default configuration generated. Reloading...");
try {
parseFile("ClientConfig.xml");
} catch (JDOMException | IOException e) {
e.printStackTrace();
}
}
/**
* Makes a new configuration file. This method invokes when change has been made to any of the data
*/
private void reparseConfig()
{
//TODO remove this, following line debug only
System.out.println("reparsing configuration file...");
Element root = makeRoot();
root.addContent(new Element("connection")
.addContent(new Element("port").setText(Integer.toString(port)))
.addContent(new Element("hostname").setText("localhost")));
makeFile(root);
}
/**
* Makes the default root element for the configuration. This adds the namespace and the XML-Scheme as well.
* @return The root configuration element
*/
private Element makeRoot()
{
Element root = new Element("client_config", "xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.setAttribute(new Attribute("noNamespaceSchemaLocation",
"ClientConfig.xsd", Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")));
return root;
}
/**
* Makes the configuration XML file from root element
* @param root The root element of the document
*/
private void makeFile(Element root)
{
Document doc = new Document();
doc.addContent(root);
XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
try {
File f = new File("ClientConfig.xml");
PrintWriter pw = new PrintWriter(f);
out.output(doc, pw);
out.output(doc, System.out); //TODO debug only line
} catch (IOException e1) {
e1.printStackTrace();
}
}
//xml data-getter methods
private int xmlGetPort(Element root)
{
return Integer.parseInt(root.getChild("connection")
.getChild("port").getText());
}
private String xmlGetHostname(Element root)
{
return root.getChild("connection").getChildText("host");
}
//setter methods
public void setPort(int dbPort) {
this.port = dbPort;
reparseConfig();
}
public void setHostname(String hostname) {
this.hostname = hostname;
reparseConfig();
}
//getter methods
public int getPort() {
return port;
}
public String getHostname() {
return hostname;
}
//toString method, debug purpose only
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("==ClientConfig==\n");
sb.append("port: ").append(Integer.toString(port));
sb.append(", hostname: ").append(hostname);
sb.append("\n================");
return sb.toString();
}
}