package configuration;
import configuration.objects.Dropbox;
import configuration.objects.URLPattern;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Parse a configuration file (xml) and create the corresponding objects in a map
*/
public class Configuration {
/** XML tags */
/** Default configuration file path */
public static String DEFAULT_XML_PATH = "conf.xml";
/** Local folder in which the images will be downloaded */
public static String LOCAL_FOLDER_TAG = "local_folder";
/** Plugins and corresponding url patterns */
public static String PLUGIN_TAG = "plugin";
public static String PLUGIN_FOLDER_TAG = "plugin_folder";
public static String PATTERNS_TAG = "patterns";
public static String PATTERN_TAG = "pattern";
/** Simultaneous downloads */
public static String PARALLEL_DOWNLOAD_TAG = "parallel_download";
/** Dropbox related configuration */
public static String DROPBOX_TAG = "dropbox";
public static String DROPBOX_FOLDER_TAG = "dropbox_folder";
public static String DROPBOX_ACCESS_TOKEN_TAG = "dropbox_access_token";
/** Subreddits */
public static String SUBREDDITS_ALLOWED_TAG = "subreddits";
public static String SUBREDDIT_ALLOWED_TAG = "subreddit";
/** Extensions allowed */
public static String EXTENSIONS_ALLOWED_TAG = "extensions";
public static String EXTENSION_ALLOWED_TAG = "extension";
/** Sqlite credentials */
public static String SQLITE_TAG = "sqlite";
public static String SQLITE_DATABASE_TAG = "sqlite_database";
public static String SQLITE_USER_TAG = "sqlite_user";
public static String SQLITE_PASSWORD_TAG = "sqlite_password";
private Map<String, Object> keys;
private String xmlPath;
public Configuration()
{
//Default configuration file path
xmlPath = DEFAULT_XML_PATH;
keys = new HashMap<String, Object>();
/**
* Default parameters
*/
keys.put(Configuration.LOCAL_FOLDER_TAG, "/tmp");
//Source
keys.put("source_url", "/user/tama_92/liked");
//Dummy token, will not work without the true one.
keys.put("reddit_token", "totoIsFat");
}
public void loadFile(String filePath) throws IOException, SAXException, ParserConfigurationException
{
xmlPath = filePath;
parse();
}
/**
* Parse a xml file
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
*/
private void parse() throws IOException, SAXException, ParserConfigurationException {
File xmlFile = new File(xmlPath);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
doc.getDocumentElement().normalize();
NodeList rootNode = doc.getElementsByTagName("configuration");
if (rootNode == null)
return;
//Only get the first "configuration" node
Node root = rootNode.item(0);
NodeList nodes = root.getChildNodes();
for (int i = 0; i < nodes.getLength(); ++i)
{
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element e = (Element)node;
String nodeName = e.getTagName();
if (nodeName.equals(LOCAL_FOLDER_TAG)) {
keys.put(LOCAL_FOLDER_TAG, e.getTextContent());
} else if (nodeName.equals(EXTENSIONS_ALLOWED_TAG)) {
keys.put(EXTENSIONS_ALLOWED_TAG, getExtensions(e));
} else if (nodeName.equals(SUBREDDITS_ALLOWED_TAG)) {
keys.put(SUBREDDITS_ALLOWED_TAG, getSubreddits(e));
} else if (nodeName.equals(PARALLEL_DOWNLOAD_TAG)) {
keys.put(PARALLEL_DOWNLOAD_TAG, e.getTextContent());
} else if (nodeName.equals(PLUGIN_TAG)) {
parse_plugin_node(e);
} else if (nodeName.equals(DROPBOX_TAG)) {
parse_dropbox_node(e);
} else if (nodeName.equals(SQLITE_TAG)) {
parse_sqlite_node(e);
}
}
}
}
/**
* Parse a plugin node
* <plugin>
* <plugin_folder>...</plugin_folder>
* <patterns>
* <pattern></pattern>
* </patterns>
* </plugin>
* @param e the root pattern element
*/
private void parse_plugin_node(Element e)
{
NodeList children = e.getChildNodes();
for (int i = 0; i < children.getLength(); ++i)
{
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element elt = (Element)node;
if (elt.getTagName().equals(PLUGIN_FOLDER_TAG)) {
keys.put(PLUGIN_FOLDER_TAG, elt.getTextContent());
} else if (elt.getTagName().equals(PATTERNS_TAG)) {
keys.put(PATTERNS_TAG, getPatterns(elt));
}
}
}
}
/**
* Get the list of patterns :
* <patterns>
* <pattern>
* <url>...</url>
* <plugin>...</plugin>
* </pattern>
* </patterns>
* @param e root node
* @return a list of @{Pattern} objects
*/
private List<URLPattern> getPatterns(Element e)
{
List<URLPattern> patterns = (List<URLPattern>)get("pattern");
if (patterns == null) {
patterns = new ArrayList<URLPattern>();
NodeList children = e.getChildNodes();
for (int i = 0; i < children.getLength(); ++i)
{
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element elt = (Element)node;
if (elt.getTagName().equals(PATTERN_TAG))
{
patterns.add(getPattern(elt));
}
}
}
}
return patterns;
}
/**
* Build a Pattern object from the xml
* <pattern [active="false"]>
* <url>...</url>
* <plugin>...</plugin>
* </pattern>
* @param e the root pattern element
* @return a Pattern object
*/
private URLPattern getPattern(Element e)
{
URLPattern pattern = new URLPattern();
//Assume that the pattern is active by default
pattern.active = true;
//check if the pattern is active
if (e.getAttribute("active") != null && e.getAttribute("active").equals("false"))
{
pattern.active = false;
}
NodeList children = e.getChildNodes();
for (int i = 0; i < children.getLength(); ++i)
{
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element elt = (Element)node;
if (elt.getTagName().equals("url"))
{
String text = elt.getTextContent();
pattern.pattern = Pattern.compile(text);
}
else if (elt.getTagName().equals("plugin"))
{
pattern.pluginName = elt.getTextContent();
}
}
}
return pattern;
}
/**
* Get the list of image extensions allowed to be downloaded
* <extensions>
* <extension>...</extension>
* <extension>...</extension>
* </extensions>
* @param e the root pattern element
* @return a list of strings representing the extensions allowed
*/
private List<String> getExtensions(Element e)
{
List<String> extensions = new ArrayList<String>();
NodeList children = e.getChildNodes();
for (int i = 0; i < children.getLength(); ++i)
{
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element elt = (Element)node;
if (elt.getTagName().equals(EXTENSION_ALLOWED_TAG))
{
extensions.add(elt.getTextContent());
}
}
}
return extensions;
}
/**
* Get the list of subreddits from which the images will be downloaded
* <subreddits>
* <subreddit>...</subreddit>
* <subreddit>...</subreddit>
* </subreddits>
* @param e the root pattern element
* @return a list of strings representing the subreddits allowed
*/
private List<String> getSubreddits(Element e)
{
List<String> subreddits = new ArrayList<String>();
NodeList children = e.getChildNodes();
for (int i = 0; i < children.getLength(); ++i)
{
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element elt = (Element)node;
if (elt.getTagName().equals(SUBREDDIT_ALLOWED_TAG))
{
subreddits.add(elt.getTextContent());
}
}
}
return subreddits;
}
/**
* Parse a dropbox node
* <dropbox>
* <dropbox_folder>...</dropbox_folder>
* <dropbox_access_token>...</dropbox_access_token>
* </dropbox>
* @param e the root pattern element
*/
private void parse_dropbox_node(Element e)
{
Dropbox dropbox = (Dropbox) get(DROPBOX_TAG);
if (dropbox == null)
{
dropbox = new Dropbox();
}
NodeList children = e.getChildNodes();
for (int i = 0; i < children.getLength(); ++i)
{
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element elt = (Element)node;
if (elt.getTagName().equals(DROPBOX_ACCESS_TOKEN_TAG)) {
dropbox.access_token = elt.getTextContent();
} else if (elt.getTagName().equals(DROPBOX_FOLDER_TAG)) {
dropbox.upload_folder = elt.getTextContent();
}
}
}
keys.put(DROPBOX_TAG, dropbox);
}
/**
* Parse a sqlite node
* <sqlite>
* <sqlite_database>...</sqlite_database>
* <sqlite_user>...</sqlite_user>
* <sqlite_password>...</sqlite_password>
* </sqlite>
*/
private void parse_sqlite_node(Element e)
{
NodeList children = e.getChildNodes();
for (int i = 0; i < children.getLength(); ++i)
{
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element elt = (Element)node;
if (elt.getTagName().equals(SQLITE_DATABASE_TAG)) {
keys.put(SQLITE_DATABASE_TAG, elt.getTextContent());
} else if (elt.getTagName().equals(SQLITE_USER_TAG)) {
keys.put(SQLITE_USER_TAG, elt.getTextContent());
} else if (elt.getTagName().equals(SQLITE_PASSWORD_TAG)) {
keys.put(SQLITE_PASSWORD_TAG, elt.getTextContent());
}
}
}
}
/**
* Get a key
* @param key
* @return the value of the key
*/
public Object get(String key)
{
return keys.get(key);
}
/**
* Put a key in the configuration map (default values)
* @param key key name
* @param value key value
*/
public void put(String key, Object value)
{
keys.put(key, value);
}
public static void main(String[] args)
{
try {
Configuration c = new Configuration();
c.loadFile("/tmp/configuration.xml");
System.out.println("Yay~");
} catch (Exception e) {
e.printStackTrace();
System.err.println("Failed :(");
}
}
}