package org.opencustomer.framework.db.util.engine;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.log4j.Logger;
import org.opencustomer.framework.db.util.engine.configuration.Configuration;
import org.opencustomer.framework.db.util.engine.configuration.DateFormatter;
import org.opencustomer.framework.db.util.engine.configuration.DateSearch;
import org.opencustomer.framework.db.util.engine.configuration.DefaultFormatter;
import org.opencustomer.framework.db.util.engine.configuration.Entity;
import org.opencustomer.framework.db.util.engine.configuration.EnumFormatter;
import org.opencustomer.framework.db.util.engine.configuration.EnumSearch;
import org.opencustomer.framework.db.util.engine.configuration.Join;
import org.opencustomer.framework.db.util.engine.configuration.ListSelectSearch;
import org.opencustomer.framework.db.util.engine.configuration.Property;
import org.opencustomer.framework.db.util.engine.configuration.Search;
import org.opencustomer.framework.db.util.engine.configuration.StringFormatter;
import org.opencustomer.framework.db.util.engine.configuration.TextSearch;
import org.opencustomer.framework.db.util.engine.configuration.TextSelectSearch;
import org.opencustomer.framework.db.vo.BaseVO;
import org.opencustomer.framework.util.EnumUtility;
import org.opencustomer.framework.webapp.util.html.Formatter;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class TableEngineFactory {
private final static Logger log = Logger.getLogger(TableEngineFactory.class);
private Hashtable<String, TableEngine> engines = new Hashtable<String, TableEngine>();
public TableEngineFactory(File packageDir) {
File[] configurationFiles = packageDir.listFiles(new FileFilter() {
public boolean accept(File file) {
if(file.isFile() && file.getName().endsWith(".xml")) {
return true;
} else {
return false;
}
};
});
for(File file : configurationFiles) {
loadConfiguration(file);
}
}
public final Configuration getConfiguration(String name) {
return engines.get(name).getConfiguration();
}
public final TableEngine getEngine(String name) {
return getEngine(name, (Integer[])null);
}
public final TableEngine getEngine(String name, Integer... columns) {
TableEngine engine = (TableEngine)engines.get(name).clone();
if(columns != null) {
List<Property> newProperties = new ArrayList<Property>();
for(Integer column : columns) {
newProperties.add(engine.getConfiguration().getProperties().get(column));
}
engine.getConfiguration().setProperties(newProperties);
} else {
engine.getConfiguration().getProperties().clear();
engine.getConfiguration().getProperties().addAll(engine.getConfiguration().getDefaultProperties().values());
}
// get group properties
for(Property property : engine.getConfiguration().getProperties()) {
if(property.isGroup())
engine.getConfiguration().getGroupProperties().add(property);
}
engine.optimizeQuery();
return engine;
}
private void loadConfiguration(File file) throws TableEngineException {
if(log.isDebugEnabled()) {
log.debug("load list configuraton: "+file);
}
FileInputStream in = null;
try {
in = new FileInputStream(file);
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.parse(in);
Node root = document.getDocumentElement();
if("configuration".equals(root.getNodeName())) {
Configuration conf = new Configuration(file.getName().substring(0, file.getName().indexOf(".")));
NodeList nodes = root.getChildNodes();
for(int i=0; i<nodes.getLength(); i++) {
if(nodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
if("entity".equals(nodes.item(i).getNodeName())) {
conf.setEntity(parseEntity(nodes.item(i)));
} else if("join".equals(nodes.item(i).getNodeName())) {
conf.getJoins().add(parseJoin(nodes.item(i)));
} else if("restriction".equals(nodes.item(i).getNodeName())) {
conf.getRestrictions().add(parseRestriction(nodes.item(i)));
} else if("property".equals(nodes.item(i).getNodeName())) {
Property property = parseProperty(conf, nodes.item(i));
if(property.isId()) {
if(conf.getId() == null) {
conf.setId(property);
} else {
throw new TableEngineException("found duplicate id property");
}
}
property.setAlias("alias_"+conf.getProperties().size());
property.setPosition(conf.getProperties().size());
conf.getProperties().add(property);
}
}
}
if(log.isDebugEnabled())
log.debug("add list renderer: "+conf.getName());
engines.put(conf.getName(), new TableEngine(conf));
} else {
throw new TableEngineException("invalid attribute found: '"+root.getNodeName()+"' (need: 'configuration')");
}
} catch(Exception e) {
if(in != null) {
try {
in.close();
} catch(IOException e2) {
}
}
throw new TableEngineException("could not load engine", e);
}
}
private Entity parseEntity(Node node) throws TableEngineException {
Entity entity = new Entity();
NamedNodeMap attributes = node.getAttributes();
for(int i=0; i<attributes.getLength(); i++) {
Node attributeNode = attributes.item(i);
if(attributeNode.getNodeType() == Node.ATTRIBUTE_NODE) {
String name = attributeNode.getNodeName();
if("class".equals(name)) {
try {
entity.setClazz((Class<? extends BaseVO>)Class.forName(attributeNode.getNodeValue()));
} catch(ClassNotFoundException e) {
throw new TableEngineException(e);
}
} else if("alias".equals(name)) {
entity.setAlias(attributeNode.getNodeValue());
} else if("messageKey".equals(name)) {
entity.setMessageKey(attributeNode.getNodeValue());
}
}
}
return entity;
}
private String parseRestriction(Node node) throws TableEngineException {
String restriction = null;
NamedNodeMap attributes = node.getAttributes();
for(int i=0; i<attributes.getLength(); i++) {
Node attributeNode = attributes.item(i);
if(attributeNode.getNodeType() == Node.ATTRIBUTE_NODE) {
String name = attributeNode.getNodeName();
if("hql".equals(name)) {
restriction = attributeNode.getNodeValue();
}
}
}
return restriction;
}
private Join parseJoin(Node node) throws TableEngineException {
Join join = new Join();
NamedNodeMap attributes = node.getAttributes();
for(int i=0; i<attributes.getLength(); i++) {
Node attributeNode = attributes.item(i);
if(attributeNode.getNodeType() == Node.ATTRIBUTE_NODE) {
String name = attributeNode.getNodeName();
if("name".equals(name)) {
join.setName(attributeNode.getNodeValue());
} else if("alias".equals(name)) {
join.setAlias(attributeNode.getNodeValue());
} else if("type".equals(name)) {
join.setType(EnumUtility.valueOf(Join.Type.class, attributeNode.getNodeValue()));
} else if("messageKey".equals(name)) {
join.setMessageKey(attributeNode.getNodeValue());
}
}
}
return join;
}
private Property parseProperty(Configuration configuration, Node node) throws TableEngineException {
Property property = new Property();
NamedNodeMap attributes = node.getAttributes();
for(int i=0; i<attributes.getLength(); i++) {
Node attributeNode = attributes.item(i);
if(attributeNode.getNodeType() == Node.ATTRIBUTE_NODE) {
String name = attributeNode.getNodeName();
if("name".equals(name)) {
property.setName(attributeNode.getNodeValue());
} else if("altName".equals(name)) {
property.setAltName(attributeNode.getNodeValue());
} else if("messageKey".equals(name)) {
property.setMessageKey(attributeNode.getNodeValue());
} else if("entityMessageKey".equals(name)) {
property.setEntityMessageKey(attributeNode.getNodeValue());
} else if("type".equals(name)) {
property.setSortable(Boolean.parseBoolean(attributeNode.getNodeValue()));
} else if("id".equals(name)) {
property.setId(Boolean.parseBoolean(attributeNode.getNodeValue()));
} else if("sortable".equals(name)) {
property.setSortable(Boolean.parseBoolean(attributeNode.getNodeValue()));
} else if("default".equals(name)) {
configuration.getDefaultProperties().put(Integer.parseInt(attributeNode.getNodeValue()), property);
} else if("group".equals(name)) {
property.setGroup(Boolean.parseBoolean(attributeNode.getNodeValue()));
}
}
}
NodeList nodes = node.getChildNodes();
for(int i=0; i<nodes.getLength(); i++) {
if(nodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
if("format".equals(nodes.item(i).getNodeName())) {
Formatter format = parseFormat(nodes.item(i));
if(format == null) {
format = new DefaultFormatter();
}
property.setFormatter(format);
} else if("search".equals(nodes.item(i).getNodeName())) {
property.setSearch(parseSearch(nodes.item(i)));
}
}
}
return property;
}
private Formatter parseFormat(Node node) throws TableEngineException {
Formatter format = null;
NamedNodeMap attributes = node.getAttributes();
for(int i=0; i<attributes.getLength(); i++) {
Node attributeNode = attributes.item(i);
if(attributeNode.getNodeType() == Node.ATTRIBUTE_NODE) {
String name = attributeNode.getNodeName();
if("type".equals(name)) {
if("date".equals(attributeNode.getNodeValue())) {
format = new DateFormatter(attributes.getNamedItem("formatKey").getNodeValue());
} else if("enum".equals(attributeNode.getNodeValue())) {
try {
EnumFormatter enumFormat = new EnumFormatter((Class<? extends Enum>)Class.forName(attributes.getNamedItem("class").getNodeValue()));
NodeList nodes = node.getChildNodes();
for(int j=0; j<nodes.getLength(); j++) {
if(nodes.item(j).getNodeType() == Node.ELEMENT_NODE) {
if("value".equals(nodes.item(j).getNodeName())) {
parseValue(enumFormat, nodes.item(j));
}
}
}
format = enumFormat;
} catch(ClassNotFoundException e) {
throw new TableEngineException("could get attribute 'class'", e);
}
} else if("string".equals(attributeNode.getNodeValue())) {
StringFormatter stringFormat = new StringFormatter();
NodeList nodes = node.getChildNodes();
for(int j=0; j<nodes.getLength(); j++) {
if(nodes.item(j).getNodeType() == Node.ELEMENT_NODE) {
if("value".equals(nodes.item(j).getNodeName())) {
parseValue(stringFormat, nodes.item(j));
}
}
}
format = stringFormat;
}
}
}
}
return format;
}
private void parseValue(EnumFormatter format, Node node) {
Enum[] enums = format.getClazz().getEnumConstants();
Enum type = null;
String messageKey = null;
NamedNodeMap attributes = node.getAttributes();
for(int i=0; i<attributes.getLength(); i++) {
Node attributeNode = attributes.item(i);
if(attributeNode.getNodeType() == Node.ATTRIBUTE_NODE) {
String name = attributeNode.getNodeName();
if("type".equals(name)) {
for(Enum e : enums) {
if(attributeNode.getNodeValue().equals(e.name())) {
type = e;
}
}
} else if("messageKey".equals(name)) {
messageKey = attributeNode.getNodeValue();
}
}
}
format.getMessageKeys().put(type, messageKey);
}
private void parseValue(StringFormatter format, Node node) {
String type = null;
String messageKey = null;
NamedNodeMap attributes = node.getAttributes();
for(int i=0; i<attributes.getLength(); i++) {
Node attributeNode = attributes.item(i);
if(attributeNode.getNodeType() == Node.ATTRIBUTE_NODE) {
String name = attributeNode.getNodeName();
if("type".equals(name)) {
type = attributeNode.getNodeValue();
} else if("messageKey".equals(name)) {
messageKey = attributeNode.getNodeValue();
}
}
}
format.getMessageKeys().put(type, messageKey);
}
private Search parseSearch(Node node) throws TableEngineException {
Search search = null;
NamedNodeMap attributes = node.getAttributes();
for(int i=0; i<attributes.getLength(); i++) {
Node attributeNode = attributes.item(i);
if(attributeNode.getNodeType() == Node.ATTRIBUTE_NODE) {
String name = attributeNode.getNodeName();
if("type".equals(name)) {
if("enum".equals(attributeNode.getNodeValue())) {
try {
EnumSearch enumSearch = new EnumSearch((Class<? extends Enum>)Class.forName(attributes.getNamedItem("class").getNodeValue()));
NodeList nodes = node.getChildNodes();
for(int j=0; j<nodes.getLength(); j++) {
if(nodes.item(j).getNodeType() == Node.ELEMENT_NODE) {
if("value".equals(nodes.item(i).getNodeName())) {
parseValue(enumSearch, nodes.item(j));
}
}
}
search = enumSearch;
} catch(ClassNotFoundException e) {
throw new TableEngineException("could get attribute 'class'", e);
}
} else if("text".equals(attributeNode.getNodeValue())) {
search = new TextSearch(attributes.getNamedItem("pattern").getNodeValue());
} else if("date".equals(attributeNode.getNodeValue())) {
search = new DateSearch(attributes.getNamedItem("formatKey").getNodeValue());
} else if("text.select".equals(attributeNode.getNodeValue())) {
TextSelectSearch textSelectSearch = new TextSelectSearch();
if(attributes.getNamedItem("hql") != null)
textSelectSearch.setHql(attributes.getNamedItem("hql").getNodeValue().equalsIgnoreCase("true") ? true : false);
NodeList nodes = node.getChildNodes();
for(int j=0; j<nodes.getLength(); j++) {
if(nodes.item(j).getNodeType() == Node.ELEMENT_NODE) {
if("value".equals(nodes.item(i).getNodeName())) {
parseValue(textSelectSearch, nodes.item(j));
}
}
}
search = textSelectSearch;
} else if("list.select".equals(attributeNode.getNodeValue())) {
String clazz = attributes.getNamedItem("class").getNodeValue();
try {
ListSelectSearch listSelectSearch = new ListSelectSearch();
listSelectSearch.setClazz(Class.forName(clazz));
if("true".equalsIgnoreCase(attributes.getNamedItem("all").getNodeValue()))
listSelectSearch.setAllAvailable(true);
else
listSelectSearch.setAllAvailable(false);
listSelectSearch.setSearchProperty(attributes.getNamedItem("searchProperty").getNodeValue());
search = listSelectSearch;
} catch(ClassNotFoundException e) {
throw new TableEngineException("could not create/use dao: "+clazz, e);
}
}
}
}
}
return search;
}
private void parseValue(EnumSearch search, Node node) {
Enum[] enums = search.getClazz().getEnumConstants();
Enum type = null;
String messageKey = null;
boolean isDefault = false;
NamedNodeMap attributes = node.getAttributes();
for(int i=0; i<attributes.getLength(); i++) {
Node attributeNode = attributes.item(i);
if(attributeNode.getNodeType() == Node.ATTRIBUTE_NODE) {
String name = attributeNode.getNodeName();
if("type".equals(name)) {
for(Enum e : enums) {
if(attributeNode.getNodeValue().equals(e.name())) {
type = e;
}
}
} else if("messageKey".equals(name)) {
messageKey = attributeNode.getNodeValue();
} else if("default".equals(name)) {
if("true".equalsIgnoreCase(attributeNode.getNodeValue())) {
isDefault = true;
}
}
}
}
search.getMessageKeys().put(type, messageKey);
if(isDefault) {
search.setDefaultValue(type);
}
}
private void parseValue(TextSelectSearch search, Node node) {
String type = null;
String messageKey = null;
String hql = null;
boolean isDefault = false;
NamedNodeMap attributes = node.getAttributes();
for(int i=0; i<attributes.getLength(); i++) {
Node attributeNode = attributes.item(i);
if(attributeNode.getNodeType() == Node.ATTRIBUTE_NODE) {
String name = attributeNode.getNodeName();
if("type".equals(name)) {
type = attributeNode.getNodeValue();
} else if("messageKey".equals(name)) {
messageKey = attributeNode.getNodeValue();
} else if("hql".equals(name) && search.isHql()) {
hql = attributeNode.getNodeValue();
} else if("default".equals(name)) {
if("true".equalsIgnoreCase(attributeNode.getNodeValue())) {
isDefault = true;
}
}
}
}
search.getBeans().put(type, new TextSelectSearch.Bean(messageKey, hql));
if(isDefault) {
search.setDefaultValue(type);
}
}
}