package com.meidusa.amoeba.xmltable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.LogLog;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import com.meidusa.amoeba.config.ConfigurationException;
import com.meidusa.amoeba.route.AbstractQueryRouter;
import com.meidusa.amoeba.util.InitialisationException;
import com.meidusa.amoeba.util.StringUtil;
/**
*
* @author struct
*
* @param <K>
* @param <V>
*/
public class XmlTableLoader {
private static Logger logger = Logger.getLogger(XmlTableLoader.class);
private String dtdPath;
private String dtdSystemID;
public void setDTD(String dtdPath){
this.dtdPath = dtdPath;
}
public void setDTDSystemID(String dtdSystemID){
this.dtdSystemID = dtdSystemID;
}
public Map<String,XmlTable> loadXmlTable(String configFileName){
DocumentBuilder db;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(true);
dbf.setNamespaceAware(false);
db = dbf.newDocumentBuilder();
db.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId) {
if (systemId.endsWith(dtdSystemID)) {
InputStream in = AbstractQueryRouter.class.getResourceAsStream(dtdPath);
if (in == null) {
LogLog.error("Could not find ["+dtdSystemID+"]. Used [" + AbstractQueryRouter.class.getClassLoader()
+ "] class loader in the search.");
return null;
} else {
return new InputSource(in);
}
} else {
return null;
}
}
});
db.setErrorHandler(new ErrorHandler() {
public void warning(SAXParseException exception) {
}
public void error(SAXParseException exception) throws SAXException {
logger.error(exception.getMessage() + " at (" + exception.getLineNumber() + ":" + exception.getColumnNumber() + ")");
throw exception;
}
public void fatalError(SAXParseException exception) throws SAXException {
logger.fatal(exception.getMessage() + " at (" + exception.getLineNumber() + ":" + exception.getColumnNumber() + ")");
throw exception;
}
});
return loadXmlTable(configFileName, db);
} catch (Exception e) {
logger.fatal("Could not load configuration file, failing", e);
throw new ConfigurationException("Error loading configuration file " + configFileName, e);
}
}
private Map<String,XmlTable> loadXmlTable(String fileName, DocumentBuilder db) throws InitialisationException {
Document doc = null;
InputStream is = null;
Map<String,XmlTable> tableMap = new HashMap<String,XmlTable>();
try {
is = new FileInputStream(new File(fileName));
if (is == null) {
throw new Exception("Could not open file " + fileName);
}
doc = db.parse(is);
} catch (Exception e) {
final String s = "Caught exception while loading file " + fileName;
logger.error(s, e);
throw new ConfigurationException(s, e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
logger.error("Unable to close input stream", e);
}
}
}
Element rootElement = doc.getDocumentElement();
NodeList children = rootElement.getChildNodes();
int childSize = children.getLength();
for (int i = 0; i < childSize; i++) {
Node childNode = children.item(i);
if (childNode instanceof Element) {
Element child = (Element) childNode;
final String nodeName = child.getNodeName();
if (nodeName.equals("table")) {
XmlTable table = loadXmlTable(child);
tableMap.put(table.getName().toLowerCase(), table);
}
}
}
if (logger.isInfoEnabled()) {
logger.info("Loaded xml table from: " + fileName);
}
return tableMap;
}
protected XmlTable loadXmlTable(Element current){
XmlTable table = new XmlTable();
String name = current.getAttribute("name");
table.setName(name);
NodeList children = current.getChildNodes();
int childSize = children.getLength();
for (int i = 0; i < childSize; i++) {
Node childNode = children.item(i);
if (childNode instanceof Element) {
Element child = (Element) childNode;
final String nodeName = child.getNodeName();
if (nodeName.equals("row")) {
XmlRow row = loadRow(table,child);
table.getRows().add(row);
}
}
}
return table;
}
protected XmlRow loadRow(XmlTable table,Element current){
XmlRow row = new XmlRow();
NodeList children = current.getChildNodes();
int childSize = children.getLength();
for (int i = 0; i < childSize; i++) {
Node childNode = children.item(i);
if (childNode instanceof Element) {
Element child = (Element) childNode;
final String nodeName = child.getNodeName();
if (nodeName.equals("field")) {
String name = child.getAttribute("name").toLowerCase();
if(!table.getColumns().contains(name)){
table.getColumns().add(name);
}
String value = child.getAttribute("value");
if(StringUtil.isEmpty(value)){
value = child.getTextContent();
}
XmlColumn column = new XmlColumn();
column.setName(name);
column.setValue(value);
row.addColumn(name, column);
}
}
}
return row;
}
}