# HG changeset patch # User Sascha L. Teichmann # Date 1312187469 0 # Node ID b81626b10cb778e5d52f7aab05362b4af50a3388 # Parent 4c82609824c8aa49fc6c2e5c3c568979d2e3e3ee Datacage: Moved templating in a better suited package. flys-artifacts/trunk@2434 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Mon Aug 01 08:11:12 2011 +0000 +++ b/flys-artifacts/ChangeLog Mon Aug 01 08:31:09 2011 +0000 @@ -1,3 +1,16 @@ +2011-08-01 Sascha L. Teichmann + + * src/main/java/de/intevation/flys/artifacts/services/meta, + src/main/java/de/intevation/flys/artifacts/datacage/templating: + Moved/renamed package to better fit the common semantics. + DataCage.java is now call NoneUserSpecific.java to reflect the + fact that it is the template for the user independent db + analysis. + + * src/main/java/de/intevation/flys/artifacts/CollectionMonitor.java, + src/main/java/de/intevation/flys/artifacts/services/MetaDataService.java: + Ajusted imports and calls. + 2011-08-01 Sascha L. Teichmann * doc/conf/conf.xml: For documentation purposes added a out-commented diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/CollectionMonitor.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/CollectionMonitor.java Mon Aug 01 08:11:12 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/CollectionMonitor.java Mon Aug 01 08:31:09 2011 +0000 @@ -22,7 +22,7 @@ import de.intevation.artifactdatabase.state.Output; -import de.intevation.flys.artifacts.services.meta.DataCage; +import de.intevation.flys.artifacts.datacage.templating.NoneUserSpecific; public class CollectionMonitor implements Hook { @@ -58,9 +58,9 @@ result.appendChild(recommended); String[] outs = extractOutputNames(flys, context); - Map params = getDataCageParameters(flys, context); + Map params = getNoneUserSpecificParameters(flys, context); - DataCage dc = DataCage.getInstance(); + NoneUserSpecific dc = NoneUserSpecific.getInstance(); dc.recommend(flys, outs, params, recommended); } @@ -80,7 +80,7 @@ } - protected Map getDataCageParameters( + protected Map getNoneUserSpecificParameters( FLYSArtifact flys, CallContext context) { diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/App.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/App.java Mon Aug 01 08:31:09 2011 +0000 @@ -0,0 +1,118 @@ +package de.intevation.flys.artifacts.datacage.templating; + +import java.sql.Connection; +import java.sql.SQLException; + +import java.util.Map; +import java.util.HashMap; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.File; +import java.io.FileOutputStream; + +import de.intevation.flys.backend.SessionFactoryProvider; + +import org.hibernate.Session; + +import org.hibernate.jdbc.Work; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import de.intevation.artifacts.common.utils.XMLUtils; + +public class App +{ + private static Logger log = Logger.getLogger(App.class); + + public static final String template = + System.getProperty("meta.data.template", "meta-data-template.xml"); + + public static final String PARAMETERS = + System.getProperty("meta.data.parameters", ""); + + public static final String OUTPUT = + System.getProperty("meta.data.output"); + + public static Map getParameters() { + HashMap map = new HashMap(); + String [] parts = PARAMETERS.split("\\s*;\\s*"); + for (String part: parts) { + String [] kv = part.split("\\s*:\\s*"); + if (kv.length < 2 || (kv[0] = kv[0].trim()).length() == 0) { + continue; + } + String [] values = kv[1].split("\\s*,\\s*"); + map.put(kv[0], values.length == 1 ? values[0] : values); + } + return map; + } + + public static void main(String [] args) { + + NoneUserSpecific dc = new NoneUserSpecific( + NoneUserSpecific.createBuilder(new File(template))); + + final Document result = XMLUtils.newDocument(); + final Builder builder = dc.getBuilder(); + + if (builder == null) { + System.err.println("No builder created"); + return; + } + + final Map parameters = getParameters(); + + Session session = SessionFactoryProvider + .createSessionFactory() + .openSession(); + + try { + session.doWork(new Work() { + @Override + public void execute(Connection connection) + throws SQLException + { + builder.build(connection, result, parameters); + } + + }); + } + finally { + session.close(); + } + + OutputStream out; + + if (OUTPUT == null) { + out = System.out; + } + else { + try { + out = new FileOutputStream(OUTPUT); + } + catch (IOException ioe) { + log.error(ioe); + return; + } + } + + try { + XMLUtils.toStream(result, out); + } + finally { + if (OUTPUT != null) { + try { + out.close(); + } + catch (IOException ioe) { + log.error(ioe); + } + } + } + System.exit(0); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/Builder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/Builder.java Mon Aug 01 08:31:09 2011 +0000 @@ -0,0 +1,469 @@ +package de.intevation.flys.artifacts.datacage.templating; + +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; +import java.util.Map; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.w3c.dom.Node; +import org.w3c.dom.Element; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathConstants; + +import java.sql.SQLException; +import java.sql.Connection; + +import de.intevation.artifacts.common.utils.XMLUtils; + +import org.apache.log4j.Logger; + +public class Builder +{ + private static Logger log = Logger.getLogger(Builder.class); + + public static final Pattern STRIP_LINE_INDENT = + Pattern.compile("\\s*\\r?\\n\\s*"); + + public static final String DC_NAMESPACE_URI = + "http://www.intevation.org/2011/Datacage"; + + private static final Document EVAL_DOCUMENT = + XMLUtils.newDocument(); + + private static final XPathFactory XPATH_FACTORY = + XPathFactory.newInstance(); + + protected Document template; + + protected Map compiledStatements; + + + public class BuildHelper + { + protected Node output; + protected Document owner; + protected StackFrames frames; + protected Connection connection; + protected Map statements; + + public BuildHelper( + Node output, + Connection connection, + Map parameters + ) { + this.output = output; + this.connection = connection; + frames = new StackFrames(parameters); + statements = new HashMap(); + owner = getOwnerDocument(output); + } + + public void build() throws SQLException { + try { + synchronized (template) { + for (Node current: rootsToList()) { + build(output, current); + } + } + } + finally { + closeStatements(); + } + } + + protected void closeStatements() { + for (CompiledStatement.Instance csi: statements.values()) { + csi.close(); + } + statements.clear(); + } + + protected void context(Node parent, Element current) + throws SQLException + { + NodeList elements = current.getElementsByTagNameNS( + DC_NAMESPACE_URI, "elements"); + + if (elements.getLength() < 1) { + log.warn("no elements found -> ignore"); + return; + } + + NodeList subs = elements.item(0).getChildNodes(); + int S = subs.getLength(); + + if (S < 1) { + log.warn("elements is empty -> ignore"); + return; + } + + NodeList stmntNode = current.getElementsByTagNameNS( + DC_NAMESPACE_URI, "statement"); + + if (stmntNode.getLength() < 1) { + log.warn("dc:context: too less statements"); + return; + } + + String stmntText = stmntNode.item(0).getTextContent(); + + CompiledStatement.Instance csi = statements.get(stmntText); + + if (csi == null) { + CompiledStatement cs = compiledStatements.get(stmntText); + csi = cs.new Instance(); + statements.put(stmntText, csi); + } + + ResultData rd = csi.execute(connection, frames); + + String [] columns = rd.getColumnLabels(); + + + for (Object [] row: rd.getRows()) { + frames.enter(); + try { + frames.put(columns, row); + for (int i = 0; i < S; ++i) { + build(parent, subs.item(i)); + } + } + finally { + frames.leave(); + } + } + } + + protected void element(Node parent, Element current) + throws SQLException + { + String attr = expand(current.getAttribute("name")); + + if (log.isDebugEnabled()) { + log.debug("dc:element -> '" + attr + "'"); + } + + if (attr.length() == 0) { + log.warn("no name attribute found"); + return; + } + + Element element = owner.createElement(attr); + + NodeList children = current.getChildNodes(); + for (int i = 0, N = children.getLength(); i < N; ++i) { + build(element, children.item(i)); + } + + parent.appendChild(element); + } + + protected void text(Node parent, Element current) + throws SQLException + { + log.debug("dc:text"); + String value = expand(current.getTextContent()); + parent.appendChild(owner.createTextNode(value)); + } + + + protected void attribute(Node parent, Element current) { + + if (parent.getNodeType() != Node.ELEMENT_NODE) { + log.warn("need element here"); + return; + } + + String name = expand(current.getAttribute("name")); + String value = expand(current.getAttribute("value")); + + Element element = (Element)parent; + + element.setAttribute(name, value); + } + + protected void callMacro(Node parent, Element current) + throws SQLException + { + String name = current.getAttribute("name"); + + if (name.length() == 0) { + log.warn("missing 'name' attribute in 'call-macro'"); + return; + } + + NodeList macros = template.getElementsByTagNameNS( + DC_NAMESPACE_URI, "macro"); + + for (int i = 0, N = macros.getLength(); i < N; ++i) { + Element macro = (Element)macros.item(i); + if (name.equals(macro.getAttribute("name"))) { + NodeList subs = macro.getChildNodes(); + for (int j = 0, M = subs.getLength(); j < M; ++j) { + build(parent, subs.item(j)); + } + return; + } + } + + log.warn("no macro '" + name + "' found."); + } + + protected void ifClause(Node parent, Element current) + throws SQLException + { + String test = current.getAttribute("test"); + + if (test.length() == 0) { + log.warn("missing 'test' attribute in 'if'"); + return; + } + + Boolean result = evaluateXPath(test); + + if (result != null && result.booleanValue()) { + NodeList subs = current.getChildNodes(); + for (int i = 0, N = subs.getLength(); i < N; ++i) { + build(parent, subs.item(i)); + } + } + } + + protected void choose(Node parent, Element current) + throws SQLException + { + Node branch = null; + + NodeList children = current.getChildNodes(); + for (int i = 0, N = children.getLength(); i < N; ++i) { + Node child = children.item(i); + String ns = child.getNamespaceURI(); + if (ns == null + || !ns.equals(DC_NAMESPACE_URI) + || child.getNodeType() != Node.ELEMENT_NODE + ) { + continue; + } + String name = child.getLocalName(); + if ("when".equals(name)) { + Element when = (Element)child; + String test = when.getAttribute("test"); + if (test.length() == 0) { + log.warn("no 'test' attribute found for when"); + continue; + } + + Boolean result = evaluateXPath(test); + if (result != null && result.booleanValue()) { + branch = child; + break; + } + + continue; + } + else if ("otherwise".equals(name)) { + branch = child; + // No break here. + } + } + + if (branch != null) { + NodeList subs = branch.getChildNodes(); + for (int i = 0, N = subs.getLength(); i < N; ++i) { + build(parent, subs.item(i)); + } + } + } + + protected Boolean evaluateXPath(String expr) { + + if (log.isDebugEnabled()) { + log.debug("evaluate: '" + expr + "'"); + } + + try { + XPath xpath = XPATH_FACTORY.newXPath(); + xpath.setXPathVariableResolver(frames); + xpath.setXPathFunctionResolver(FunctionResolver.FUNCTIONS); + Object result = xpath.evaluate( + expr, EVAL_DOCUMENT, XPathConstants.BOOLEAN); + + return result instanceof Boolean + ? (Boolean)result + : null; + } + catch (XPathExpressionException xfce) { + log.error(xfce); + } + return null; + } + + protected void convert(Node parent, Element current) { + + String variable = expand(current.getAttribute("var")); + String type = expand(current.getAttribute("type")); + + if (frames.containsKey(variable)) { + Object object = TypeConverter.convert( + frames.get(variable), + type); + frames.put(variable, object); + } + } + + protected String expand(String s) { + Matcher m = CompiledStatement.VAR.matcher(s); + + StringBuffer sb = new StringBuffer(); + while (m.find()) { + String key = m.group(1); + Object value = frames.get(key); + m.appendReplacement(sb, value != null ? value.toString() : ""); + } + m.appendTail(sb); + return sb.toString(); + } + + protected void build(Node parent, Node current) + throws SQLException + { + String ns = current.getNamespaceURI(); + if (ns != null && ns.equals(DC_NAMESPACE_URI)) { + if (current.getNodeType() != Node.ELEMENT_NODE) { + log.warn("need elements here"); + } + else { + String localName = current.getLocalName(); + if ("attribute".equals(localName)) { + attribute(parent, (Element)current); + } + else if ("context".equals(localName)) { + context(parent, (Element)current); + } + else if ("if".equals(localName)) { + ifClause(parent, (Element)current); + } + else if ("choose".equals(localName)) { + choose(parent, (Element)current); + } + else if ("call-macro".equals(localName)) { + callMacro(parent, (Element)current); + } + else if ("macro".equals(localName)) { + // simply ignore the definition. + } + else if ("element".equals(localName)) { + element(parent, (Element)current); + } + else if ("text".equals(localName)) { + text(parent, (Element)current); + } + else if ("convert".equals(localName)) { + convert(parent, (Element)current); + } + else { + log.warn("unknown '" + localName + "' -> ignore"); + } + } + return; + } + + if (current.getNodeType() == Node.TEXT_NODE) { + String txt = current.getNodeValue(); + if (txt != null && txt.trim().length() == 0) { + return; + } + } + + Node copy = owner.importNode(current, false); + + NodeList children = current.getChildNodes(); + for (int i = 0, N = children.getLength(); i < N; ++i) { + build(copy, children.item(i)); + } + parent.appendChild(copy); + } + } // class BuildHelper + + + public Builder() { + compiledStatements = new HashMap(); + } + + public Builder(Document template) { + this(); + this.template = template; + compileStatements(); + } + + protected void compileStatements() { + + NodeList nodes = template.getElementsByTagNameNS( + DC_NAMESPACE_URI, "statement"); + + for (int i = 0, N = nodes.getLength(); i < N; ++i) { + Element stmntElement = (Element)nodes.item(i); + String stmnt = trimStatement(stmntElement.getTextContent()); + if (stmnt == null || stmnt.length() == 0) { + throw new IllegalArgumentException("found empty statement"); + } + CompiledStatement cs = new CompiledStatement(stmnt); + // for faster lookup store a shortend string into the template + stmnt = "s" + i; + stmntElement.setTextContent(stmnt); + compiledStatements.put(stmnt, cs); + } + } + + protected List rootsToList() { + + NodeList roots = template.getElementsByTagNameNS( + DC_NAMESPACE_URI, "template"); + + List elements = new ArrayList(); + + for (int i = 0, N = roots.getLength(); i < N; ++i) { + NodeList rootChildren = roots.item(i).getChildNodes(); + for (int j = 0, M = rootChildren.getLength(); j < M; ++j) { + Node child = rootChildren.item(j); + if (child.getNodeType() == Node.ELEMENT_NODE) { + elements.add(child); + } + } + } + + return elements; + } + + protected static final String trimStatement(String stmnt) { + if (stmnt == null) return null; + //XXX: Maybe a bit to radical for multiline strings? + return STRIP_LINE_INDENT.matcher(stmnt.trim()).replaceAll(" "); + } + + protected static Document getOwnerDocument(Node node) { + Document document = node.getOwnerDocument(); + return document != null ? document : (Document)node; + } + + public void build( + Connection connection, + Node output, + Map parameters + ) + throws SQLException + { + BuildHelper helper = new BuildHelper(output, connection, parameters); + + helper.build(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/CompiledStatement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/CompiledStatement.java Mon Aug 01 08:31:09 2011 +0000 @@ -0,0 +1,188 @@ +package de.intevation.flys.artifacts.datacage.templating; + +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.ArrayList; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Connection; +import java.sql.ResultSet; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import de.intevation.flys.artifacts.cache.CacheFactory; + +public class CompiledStatement +{ + public static final String DATACAGE_DB_CACHE = + "datacage.db"; + + public static final Pattern VAR = + Pattern.compile("\\$\\{([a-zA-Z0-9_-]+)\\}"); + + protected String original; + protected String statement; + + protected Map> positions; + + protected int numVars; + + public class Instance { + + protected PreparedStatement preparedStatement; + + public Instance() { + } + + protected ResultData executeCached( + Cache cache, + Connection connection, + StackFrames frames + ) + throws SQLException + { + Object [] values = new Object[numVars]; + + StringBuilder sb = new StringBuilder(original); + + for (Map.Entry> entry: positions.entrySet()) { + String key = entry.getKey(); + Object value = frames.get(key); + sb.append(';').append(key).append(':').append(value); + for (Integer index: entry.getValue()) { + values[index] = value; + } + } + + // XXX: Maybe too many collisions? + // String key = original + Arrays.hashCode(values); + String key = sb.toString(); + + Element element = cache.get(key); + + if (element != null) { + return (ResultData)element.getValue(); + } + + if (preparedStatement == null) { + preparedStatement = connection.prepareStatement(statement); + } + + for (int i = 0; i < values.length; ++i) { + preparedStatement.setObject(i+1, values[i]); + } + + ResultData data; + + ResultSet result = preparedStatement.executeQuery(); + try { + data = new ResultData(preparedStatement.getMetaData()) + .addAll(result); + } + finally { + result.close(); + } + + element = new Element(key, data); + cache.put(element); + + return data; + } + + protected ResultData executeUncached( + Connection connection, + StackFrames frames + ) + throws SQLException + { + if (preparedStatement == null) { + preparedStatement = connection.prepareStatement(statement); + } + + for (Map.Entry> entry: positions.entrySet()) { + Object value = frames.get(entry.getKey()); + for (Integer index: entry.getValue()) { + preparedStatement.setObject(index+1, value); + } + } + + ResultSet result = preparedStatement.executeQuery(); + try { + return new ResultData(preparedStatement.getMetaData()) + .addAll(result); + } + finally { + result.close(); + } + } + + public ResultData execute(Connection connection, StackFrames frames) + throws SQLException + { + Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE); + + return cache != null + ? executeCached(cache, connection, frames) + : executeUncached(connection, frames); + } + + public void close() { + if (preparedStatement != null) { + try { + preparedStatement.close(); + } + catch (SQLException sqle) { + } + preparedStatement = null; + } + } + } // class Instance + + public CompiledStatement() { + } + + public CompiledStatement(String original) { + this.original = original; + // TreeMap to ensure order + positions = new TreeMap>(); + compile(); + } + + protected void compile() { + + StringBuffer sb = new StringBuffer(); + + Matcher m = VAR.matcher(original); + + int index = 0; + + while (m.find()) { + String key = m.group(1); + List indices = positions.get(key); + if (indices == null) { + indices = new ArrayList(); + positions.put(key, indices); + } + indices.add(index); + m.appendReplacement(sb, "?"); + ++index; + } + + m.appendTail(sb); + + numVars = index; + + statement = sb.toString(); + } + + public String getStatement() { + return statement; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/FunctionResolver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/FunctionResolver.java Mon Aug 01 08:31:09 2011 +0000 @@ -0,0 +1,103 @@ +package de.intevation.flys.artifacts.datacage.templating; + +import java.util.List; +import java.util.Collection; +import java.util.Map; +import java.util.ArrayList; + +import javax.xml.xpath.XPathFunctionResolver; +import javax.xml.xpath.XPathFunction; +import javax.xml.xpath.XPathFunctionException; + +import javax.xml.namespace.QName; + +import org.apache.log4j.Logger; + +public class FunctionResolver +implements XPathFunctionResolver +{ + private static Logger log = Logger.getLogger(FunctionResolver.class); + + public static final String FUNCTION_NAMESPACE_URI = "dc"; + + public static final class Entry { + + String name; + XPathFunction function; + int arity; + + public Entry() { + } + + public Entry(String name, XPathFunction function, int arity) { + this.name = name; + this.function = function; + this.arity = arity; + } + } // class Entry + + public static final FunctionResolver FUNCTIONS = new FunctionResolver(); + + static { + FUNCTIONS.addFunction("contains", 2, new XPathFunction() { + @Override + public Object evaluate(List args) throws XPathFunctionException { + Object haystack = args.get(0); + Object needle = args.get(1); + try { + if (haystack instanceof Collection) { + return Boolean.valueOf( + ((Collection)haystack).contains(needle)); + } + + if (haystack instanceof Map) { + return Boolean.valueOf( + ((Map)haystack).containsKey(needle)); + } + + if (haystack instanceof Object []) { + for (Object straw: (Object [])haystack) { + if (straw.equals(needle)) { + return Boolean.TRUE; + } + } + } + + return Boolean.FALSE; + } + catch (Exception e) { + log.error(e); + throw new XPathFunctionException(e); + } + } + }); + } + + protected List functions; + + public FunctionResolver() { + functions = new ArrayList(); + } + + public void addFunction(String name, int arity, XPathFunction function) { + functions.add(new Entry(name, function, arity)); + } + + @Override + public XPathFunction resolveFunction(QName functionName, int arity) { + + if (!functionName.getNamespaceURI().equals(FUNCTION_NAMESPACE_URI)) { + return null; + } + + String name = functionName.getLocalPart(); + for (Entry entry: functions) { + if (entry.arity == arity && entry.name.equals(name)) { + return entry.function; + } + } + + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/NoneUserSpecific.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/NoneUserSpecific.java Mon Aug 01 08:31:09 2011 +0000 @@ -0,0 +1,175 @@ +package de.intevation.flys.artifacts.datacage.templating; + +import java.util.Map; +import java.util.HashMap; + +import java.io.InputStream; +import java.io.IOException; +import java.io.File; + +import java.io.FileInputStream; + +import java.sql.Connection; +import java.sql.SQLException; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import org.hibernate.Session; + +import org.hibernate.jdbc.Work; + +import de.intevation.artifacts.common.utils.Config; +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.flys.artifacts.FLYSArtifact; + +import de.intevation.flys.backend.SessionHolder; + +import de.intevation.artifactdatabase.data.StateData; + + +public class NoneUserSpecific +{ + private static Logger log = Logger.getLogger(NoneUserSpecific.class); + + public static final String XPATH_META_DATA_TEMPLATE = + "/artifact-database/metadata/@template"; + + private static NoneUserSpecific INSTANCE; + + protected Builder builder; + + public NoneUserSpecific() { + } + + public NoneUserSpecific(Builder builder) { + this.builder = builder; + } + + public Builder getBuilder() { + return builder; + } + + protected static void artifactToParameters( + FLYSArtifact artifact, + Map parameters + ) { + parameters.put("current-state-id", artifact.getCurrentStateId()); + + for (StateData sd: artifact.getAllData()) { + Object value = sd.getValue(); + if (value == null) { + continue; + } + String key = sd.getName().replace('.', '-'); + parameters.put(key, value); + } + } + + public void recommend( + FLYSArtifact artifact, + String [] outs, + Map extraParameters, + Node result + ) { + Map parameters = new HashMap(); + + if (extraParameters != null) { + parameters.putAll(extraParameters); + } + + if (artifact != null) { + artifactToParameters(artifact, parameters); + } + + parameters.put("artifact-outs", outs); + + parameters.put("parameters", parameters); + + recommend(parameters, result); + } + + public void recommend( + final Map parameters, + final Node result + ) { + if (builder == null) { + log.error("builder not configured properly."); + return; + } + + Session session = SessionHolder.HOLDER.get(); + + session.doWork(new Work() { + @Override + public void execute(Connection connection) + throws SQLException + { + builder.build(connection, result, parameters); + } + }); + } + + public static synchronized NoneUserSpecific getInstance() { + if (INSTANCE == null) { + INSTANCE = createNoneUserSpecific(); + } + return INSTANCE; + } + + protected static Builder createBuilder(File file) { + log.debug("NoneUserSpecific.createBuilder"); + + if (!file.isFile() || !file.canRead()) { + log.error("Cannot open template file '" + file + "'"); + return null; + } + + InputStream in = null; + + try { + in = new FileInputStream(file); + + Document template = XMLUtils.parseDocument(in); + + if (template == null) { + log.error("cannot parse meta data template"); + } + else { + return new Builder(template); + } + } + catch (IOException ioe) { + log.error(ioe); + } + finally { + if (in != null) { + try { + in.close(); + } + catch (IOException ioe) { + log.error(ioe); + } + } + } + return null; + } + + protected static NoneUserSpecific createNoneUserSpecific() { + log.debug("NoneUserSpecific.createNoneUserSpecific"); + + String path = Config.getStringXPath(XPATH_META_DATA_TEMPLATE); + if (path == null) { + log.error("no path to template file given"); + return null; + } + + path = Config.replaceConfigDir(path); + + return new NoneUserSpecific(createBuilder(new File(path))); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/ResultData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/ResultData.java Mon Aug 01 08:31:09 2011 +0000 @@ -0,0 +1,60 @@ +package de.intevation.flys.artifacts.datacage.templating; + +import java.io.Serializable; + +import java.sql.ResultSetMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; + +import java.util.List; +import java.util.ArrayList; + +public class ResultData +implements Serializable +{ + protected String [] columns; + + protected List rows; + + public ResultData() { + rows = new ArrayList(); + } + + public ResultData(ResultSetMetaData meta) + throws SQLException + { + this(); + + int N = meta.getColumnCount(); + + columns = new String[N]; + + for (int i = 1; i <= N; ++i) { + columns[i-1] = meta.getColumnLabel(i); + } + } + + public String [] getColumnLabels() { + return columns; + } + + public ResultData addAll(ResultSet result) throws SQLException { + while (result.next()) { + add(result); + } + return this; + } + + public void add(ResultSet result) throws SQLException { + Object [] row = new Object[columns.length]; + for (int i = 0; i < columns.length; ++i) { + row[i] = result.getObject(i+1); + } + rows.add(row); + } + + public List getRows() { + return rows; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/StackFrames.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/StackFrames.java Mon Aug 01 08:31:09 2011 +0000 @@ -0,0 +1,87 @@ +package de.intevation.flys.artifacts.datacage.templating; + +import java.util.Map; +import java.util.List; +import java.util.HashMap; +import java.util.ArrayList; + +import javax.xml.xpath.XPathVariableResolver; + +import javax.xml.namespace.QName; + +import org.apache.log4j.Logger; + +public class StackFrames +implements XPathVariableResolver +{ + private static Logger log = Logger.getLogger(StackFrames.class); + + protected List> frames; + + public StackFrames() { + frames = new ArrayList>(); + } + + public StackFrames(Map initialFrame) { + this(); + if (initialFrame != null) { + frames.add(new HashMap(initialFrame)); + } + } + + public void enter() { + frames.add(new HashMap()); + } + + public void leave() { + frames.remove(frames.size()-1); + } + + public void put(String key, Object value) { + int N = frames.size(); + if (N > 0) { + frames.get(N-1).put(key, value); + } + } + + public void put(String [] keys, Object [] values) { + Map top = frames.get(frames.size()-1); + for (int i = 0; i < keys.length; ++i) { + top.put(keys[i], values[i]); + } + } + + public boolean containsKey(String key) { + for (int i = frames.size()-1; i >= 0; --i) { + if (frames.get(i).containsKey(key)) { + return true; + } + } + return false; + } + + public Object get(String key) { + return get(key, null); + } + + public Object get(String key, Object def) { + + for (int i = frames.size()-1; i >= 0; --i) { + Map frame = frames.get(i); + if (frame.containsKey(key)) { + return frame.get(key); + } + } + + return def; + } + + @Override + public Object resolveVariable(QName variableName) { + if (log.isDebugEnabled()) { + log.debug("resolve var: " + variableName); + } + return get(variableName.getLocalPart()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/TypeConverter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/TypeConverter.java Mon Aug 01 08:31:09 2011 +0000 @@ -0,0 +1,31 @@ +package de.intevation.flys.artifacts.datacage.templating; + +public class TypeConverter +{ + private TypeConverter() { + } + + public static Object convert(Object object, String type) { + + if (type == null) { + return object; + } + + if ("Integer".equals(type)) { + return Integer.valueOf(object.toString()); + } + + if ("Double".equals(type)) { + return Double.valueOf(object.toString()); + } + + if ("String".equals(type)) { + return object.toString(); + } + + // TODO: Add more types + + return object; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/MetaDataService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/MetaDataService.java Mon Aug 01 08:11:12 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/MetaDataService.java Mon Aug 01 08:31:09 2011 +0000 @@ -23,8 +23,8 @@ import de.intevation.artifacts.common.ArtifactNamespaceContext; -import de.intevation.flys.artifacts.services.meta.Builder; -import de.intevation.flys.artifacts.services.meta.DataCage; +import de.intevation.flys.artifacts.datacage.templating.Builder; +import de.intevation.flys.artifacts.datacage.templating.NoneUserSpecific; import de.intevation.flys.artifacts.FLYSArtifact; @@ -74,7 +74,7 @@ final Document result = XMLUtils.newDocument(); - final Builder builder = DataCage.getInstance().getBuilder(); + final Builder builder = NoneUserSpecific.getInstance().getBuilder(); if (builder == null) { log.error("MetaDataService is not setup properly."); @@ -194,7 +194,7 @@ String [] outs = outsString.split("\\s*,\\s*"); - DataCage dc = DataCage.getInstance(); + NoneUserSpecific dc = NoneUserSpecific.getInstance(); dc.recommend(flysArtifact, outs, data, result); diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/App.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/App.java Mon Aug 01 08:11:12 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -package de.intevation.flys.artifacts.services.meta; - -import java.sql.Connection; -import java.sql.SQLException; - -import java.util.Map; -import java.util.HashMap; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.File; -import java.io.FileOutputStream; - -import de.intevation.flys.backend.SessionFactoryProvider; - -import org.hibernate.Session; - -import org.hibernate.jdbc.Work; - -import org.w3c.dom.Document; - -import org.apache.log4j.Logger; - -import de.intevation.artifacts.common.utils.XMLUtils; - -public class App -{ - private static Logger log = Logger.getLogger(App.class); - - public static final String template = - System.getProperty("meta.data.template", "meta-data-template.xml"); - - public static final String PARAMETERS = - System.getProperty("meta.data.parameters", ""); - - public static final String OUTPUT = - System.getProperty("meta.data.output"); - - public static Map getParameters() { - HashMap map = new HashMap(); - String [] parts = PARAMETERS.split("\\s*;\\s*"); - for (String part: parts) { - String [] kv = part.split("\\s*:\\s*"); - if (kv.length < 2 || (kv[0] = kv[0].trim()).length() == 0) { - continue; - } - String [] values = kv[1].split("\\s*,\\s*"); - map.put(kv[0], values.length == 1 ? values[0] : values); - } - return map; - } - - public static void main(String [] args) { - - DataCage dc = new DataCage( - DataCage.createBuilder(new File(template))); - - final Document result = XMLUtils.newDocument(); - final Builder builder = dc.getBuilder(); - - if (builder == null) { - System.err.println("No builder created"); - return; - } - - final Map parameters = getParameters(); - - Session session = SessionFactoryProvider - .createSessionFactory() - .openSession(); - - try { - session.doWork(new Work() { - @Override - public void execute(Connection connection) - throws SQLException - { - builder.build(connection, result, parameters); - } - - }); - } - finally { - session.close(); - } - - OutputStream out; - - if (OUTPUT == null) { - out = System.out; - } - else { - try { - out = new FileOutputStream(OUTPUT); - } - catch (IOException ioe) { - log.error(ioe); - return; - } - } - - try { - XMLUtils.toStream(result, out); - } - finally { - if (OUTPUT != null) { - try { - out.close(); - } - catch (IOException ioe) { - log.error(ioe); - } - } - } - System.exit(0); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/Builder.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/Builder.java Mon Aug 01 08:11:12 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,469 +0,0 @@ -package de.intevation.flys.artifacts.services.meta; - -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -import java.util.ArrayList; -import java.util.List; -import java.util.HashMap; -import java.util.Map; - -import org.w3c.dom.Document; -import org.w3c.dom.NodeList; -import org.w3c.dom.Node; -import org.w3c.dom.Element; - -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathFactory; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathConstants; - -import java.sql.SQLException; -import java.sql.Connection; - -import de.intevation.artifacts.common.utils.XMLUtils; - -import org.apache.log4j.Logger; - -public class Builder -{ - private static Logger log = Logger.getLogger(Builder.class); - - public static final Pattern STRIP_LINE_INDENT = - Pattern.compile("\\s*\\r?\\n\\s*"); - - public static final String DC_NAMESPACE_URI = - "http://www.intevation.org/2011/Datacage"; - - private static final Document EVAL_DOCUMENT = - XMLUtils.newDocument(); - - private static final XPathFactory XPATH_FACTORY = - XPathFactory.newInstance(); - - protected Document template; - - protected Map compiledStatements; - - - public class BuildHelper - { - protected Node output; - protected Document owner; - protected StackFrames frames; - protected Connection connection; - protected Map statements; - - public BuildHelper( - Node output, - Connection connection, - Map parameters - ) { - this.output = output; - this.connection = connection; - frames = new StackFrames(parameters); - statements = new HashMap(); - owner = getOwnerDocument(output); - } - - public void build() throws SQLException { - try { - synchronized (template) { - for (Node current: rootsToList()) { - build(output, current); - } - } - } - finally { - closeStatements(); - } - } - - protected void closeStatements() { - for (CompiledStatement.Instance csi: statements.values()) { - csi.close(); - } - statements.clear(); - } - - protected void context(Node parent, Element current) - throws SQLException - { - NodeList elements = current.getElementsByTagNameNS( - DC_NAMESPACE_URI, "elements"); - - if (elements.getLength() < 1) { - log.warn("no elements found -> ignore"); - return; - } - - NodeList subs = elements.item(0).getChildNodes(); - int S = subs.getLength(); - - if (S < 1) { - log.warn("elements is empty -> ignore"); - return; - } - - NodeList stmntNode = current.getElementsByTagNameNS( - DC_NAMESPACE_URI, "statement"); - - if (stmntNode.getLength() < 1) { - log.warn("dc:context: too less statements"); - return; - } - - String stmntText = stmntNode.item(0).getTextContent(); - - CompiledStatement.Instance csi = statements.get(stmntText); - - if (csi == null) { - CompiledStatement cs = compiledStatements.get(stmntText); - csi = cs.new Instance(); - statements.put(stmntText, csi); - } - - ResultData rd = csi.execute(connection, frames); - - String [] columns = rd.getColumnLabels(); - - - for (Object [] row: rd.getRows()) { - frames.enter(); - try { - frames.put(columns, row); - for (int i = 0; i < S; ++i) { - build(parent, subs.item(i)); - } - } - finally { - frames.leave(); - } - } - } - - protected void element(Node parent, Element current) - throws SQLException - { - String attr = expand(current.getAttribute("name")); - - if (log.isDebugEnabled()) { - log.debug("dc:element -> '" + attr + "'"); - } - - if (attr.length() == 0) { - log.warn("no name attribute found"); - return; - } - - Element element = owner.createElement(attr); - - NodeList children = current.getChildNodes(); - for (int i = 0, N = children.getLength(); i < N; ++i) { - build(element, children.item(i)); - } - - parent.appendChild(element); - } - - protected void text(Node parent, Element current) - throws SQLException - { - log.debug("dc:text"); - String value = expand(current.getTextContent()); - parent.appendChild(owner.createTextNode(value)); - } - - - protected void attribute(Node parent, Element current) { - - if (parent.getNodeType() != Node.ELEMENT_NODE) { - log.warn("need element here"); - return; - } - - String name = expand(current.getAttribute("name")); - String value = expand(current.getAttribute("value")); - - Element element = (Element)parent; - - element.setAttribute(name, value); - } - - protected void callMacro(Node parent, Element current) - throws SQLException - { - String name = current.getAttribute("name"); - - if (name.length() == 0) { - log.warn("missing 'name' attribute in 'call-macro'"); - return; - } - - NodeList macros = template.getElementsByTagNameNS( - DC_NAMESPACE_URI, "macro"); - - for (int i = 0, N = macros.getLength(); i < N; ++i) { - Element macro = (Element)macros.item(i); - if (name.equals(macro.getAttribute("name"))) { - NodeList subs = macro.getChildNodes(); - for (int j = 0, M = subs.getLength(); j < M; ++j) { - build(parent, subs.item(j)); - } - return; - } - } - - log.warn("no macro '" + name + "' found."); - } - - protected void ifClause(Node parent, Element current) - throws SQLException - { - String test = current.getAttribute("test"); - - if (test.length() == 0) { - log.warn("missing 'test' attribute in 'if'"); - return; - } - - Boolean result = evaluateXPath(test); - - if (result != null && result.booleanValue()) { - NodeList subs = current.getChildNodes(); - for (int i = 0, N = subs.getLength(); i < N; ++i) { - build(parent, subs.item(i)); - } - } - } - - protected void choose(Node parent, Element current) - throws SQLException - { - Node branch = null; - - NodeList children = current.getChildNodes(); - for (int i = 0, N = children.getLength(); i < N; ++i) { - Node child = children.item(i); - String ns = child.getNamespaceURI(); - if (ns == null - || !ns.equals(DC_NAMESPACE_URI) - || child.getNodeType() != Node.ELEMENT_NODE - ) { - continue; - } - String name = child.getLocalName(); - if ("when".equals(name)) { - Element when = (Element)child; - String test = when.getAttribute("test"); - if (test.length() == 0) { - log.warn("no 'test' attribute found for when"); - continue; - } - - Boolean result = evaluateXPath(test); - if (result != null && result.booleanValue()) { - branch = child; - break; - } - - continue; - } - else if ("otherwise".equals(name)) { - branch = child; - // No break here. - } - } - - if (branch != null) { - NodeList subs = branch.getChildNodes(); - for (int i = 0, N = subs.getLength(); i < N; ++i) { - build(parent, subs.item(i)); - } - } - } - - protected Boolean evaluateXPath(String expr) { - - if (log.isDebugEnabled()) { - log.debug("evaluate: '" + expr + "'"); - } - - try { - XPath xpath = XPATH_FACTORY.newXPath(); - xpath.setXPathVariableResolver(frames); - xpath.setXPathFunctionResolver(FunctionResolver.FUNCTIONS); - Object result = xpath.evaluate( - expr, EVAL_DOCUMENT, XPathConstants.BOOLEAN); - - return result instanceof Boolean - ? (Boolean)result - : null; - } - catch (XPathExpressionException xfce) { - log.error(xfce); - } - return null; - } - - protected void convert(Node parent, Element current) { - - String variable = expand(current.getAttribute("var")); - String type = expand(current.getAttribute("type")); - - if (frames.containsKey(variable)) { - Object object = TypeConverter.convert( - frames.get(variable), - type); - frames.put(variable, object); - } - } - - protected String expand(String s) { - Matcher m = CompiledStatement.VAR.matcher(s); - - StringBuffer sb = new StringBuffer(); - while (m.find()) { - String key = m.group(1); - Object value = frames.get(key); - m.appendReplacement(sb, value != null ? value.toString() : ""); - } - m.appendTail(sb); - return sb.toString(); - } - - protected void build(Node parent, Node current) - throws SQLException - { - String ns = current.getNamespaceURI(); - if (ns != null && ns.equals(DC_NAMESPACE_URI)) { - if (current.getNodeType() != Node.ELEMENT_NODE) { - log.warn("need elements here"); - } - else { - String localName = current.getLocalName(); - if ("attribute".equals(localName)) { - attribute(parent, (Element)current); - } - else if ("context".equals(localName)) { - context(parent, (Element)current); - } - else if ("if".equals(localName)) { - ifClause(parent, (Element)current); - } - else if ("choose".equals(localName)) { - choose(parent, (Element)current); - } - else if ("call-macro".equals(localName)) { - callMacro(parent, (Element)current); - } - else if ("macro".equals(localName)) { - // simply ignore the definition. - } - else if ("element".equals(localName)) { - element(parent, (Element)current); - } - else if ("text".equals(localName)) { - text(parent, (Element)current); - } - else if ("convert".equals(localName)) { - convert(parent, (Element)current); - } - else { - log.warn("unknown '" + localName + "' -> ignore"); - } - } - return; - } - - if (current.getNodeType() == Node.TEXT_NODE) { - String txt = current.getNodeValue(); - if (txt != null && txt.trim().length() == 0) { - return; - } - } - - Node copy = owner.importNode(current, false); - - NodeList children = current.getChildNodes(); - for (int i = 0, N = children.getLength(); i < N; ++i) { - build(copy, children.item(i)); - } - parent.appendChild(copy); - } - } // class BuildHelper - - - public Builder() { - compiledStatements = new HashMap(); - } - - public Builder(Document template) { - this(); - this.template = template; - compileStatements(); - } - - protected void compileStatements() { - - NodeList nodes = template.getElementsByTagNameNS( - DC_NAMESPACE_URI, "statement"); - - for (int i = 0, N = nodes.getLength(); i < N; ++i) { - Element stmntElement = (Element)nodes.item(i); - String stmnt = trimStatement(stmntElement.getTextContent()); - if (stmnt == null || stmnt.length() == 0) { - throw new IllegalArgumentException("found empty statement"); - } - CompiledStatement cs = new CompiledStatement(stmnt); - // for faster lookup store a shortend string into the template - stmnt = "s" + i; - stmntElement.setTextContent(stmnt); - compiledStatements.put(stmnt, cs); - } - } - - protected List rootsToList() { - - NodeList roots = template.getElementsByTagNameNS( - DC_NAMESPACE_URI, "template"); - - List elements = new ArrayList(); - - for (int i = 0, N = roots.getLength(); i < N; ++i) { - NodeList rootChildren = roots.item(i).getChildNodes(); - for (int j = 0, M = rootChildren.getLength(); j < M; ++j) { - Node child = rootChildren.item(j); - if (child.getNodeType() == Node.ELEMENT_NODE) { - elements.add(child); - } - } - } - - return elements; - } - - protected static final String trimStatement(String stmnt) { - if (stmnt == null) return null; - //XXX: Maybe a bit to radical for multiline strings? - return STRIP_LINE_INDENT.matcher(stmnt.trim()).replaceAll(" "); - } - - protected static Document getOwnerDocument(Node node) { - Document document = node.getOwnerDocument(); - return document != null ? document : (Document)node; - } - - public void build( - Connection connection, - Node output, - Map parameters - ) - throws SQLException - { - BuildHelper helper = new BuildHelper(output, connection, parameters); - - helper.build(); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java Mon Aug 01 08:11:12 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +0,0 @@ -package de.intevation.flys.artifacts.services.meta; - -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.ArrayList; - -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Connection; -import java.sql.ResultSet; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.Element; - -import de.intevation.flys.artifacts.cache.CacheFactory; - -public class CompiledStatement -{ - public static final String DATACAGE_DB_CACHE = - "datacage.db"; - - public static final Pattern VAR = - Pattern.compile("\\$\\{([a-zA-Z0-9_-]+)\\}"); - - protected String original; - protected String statement; - - protected Map> positions; - - protected int numVars; - - public class Instance { - - protected PreparedStatement preparedStatement; - - public Instance() { - } - - protected ResultData executeCached( - Cache cache, - Connection connection, - StackFrames frames - ) - throws SQLException - { - Object [] values = new Object[numVars]; - - StringBuilder sb = new StringBuilder(original); - - for (Map.Entry> entry: positions.entrySet()) { - String key = entry.getKey(); - Object value = frames.get(key); - sb.append(';').append(key).append(':').append(value); - for (Integer index: entry.getValue()) { - values[index] = value; - } - } - - // XXX: Maybe too many collisions? - // String key = original + Arrays.hashCode(values); - String key = sb.toString(); - - Element element = cache.get(key); - - if (element != null) { - return (ResultData)element.getValue(); - } - - if (preparedStatement == null) { - preparedStatement = connection.prepareStatement(statement); - } - - for (int i = 0; i < values.length; ++i) { - preparedStatement.setObject(i+1, values[i]); - } - - ResultData data; - - ResultSet result = preparedStatement.executeQuery(); - try { - data = new ResultData(preparedStatement.getMetaData()) - .addAll(result); - } - finally { - result.close(); - } - - element = new Element(key, data); - cache.put(element); - - return data; - } - - protected ResultData executeUncached( - Connection connection, - StackFrames frames - ) - throws SQLException - { - if (preparedStatement == null) { - preparedStatement = connection.prepareStatement(statement); - } - - for (Map.Entry> entry: positions.entrySet()) { - Object value = frames.get(entry.getKey()); - for (Integer index: entry.getValue()) { - preparedStatement.setObject(index+1, value); - } - } - - ResultSet result = preparedStatement.executeQuery(); - try { - return new ResultData(preparedStatement.getMetaData()) - .addAll(result); - } - finally { - result.close(); - } - } - - public ResultData execute(Connection connection, StackFrames frames) - throws SQLException - { - Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE); - - return cache != null - ? executeCached(cache, connection, frames) - : executeUncached(connection, frames); - } - - public void close() { - if (preparedStatement != null) { - try { - preparedStatement.close(); - } - catch (SQLException sqle) { - } - preparedStatement = null; - } - } - } // class Instance - - public CompiledStatement() { - } - - public CompiledStatement(String original) { - this.original = original; - // TreeMap to ensure order - positions = new TreeMap>(); - compile(); - } - - protected void compile() { - - StringBuffer sb = new StringBuffer(); - - Matcher m = VAR.matcher(original); - - int index = 0; - - while (m.find()) { - String key = m.group(1); - List indices = positions.get(key); - if (indices == null) { - indices = new ArrayList(); - positions.put(key, indices); - } - indices.add(index); - m.appendReplacement(sb, "?"); - ++index; - } - - m.appendTail(sb); - - numVars = index; - - statement = sb.toString(); - } - - public String getStatement() { - return statement; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/DataCage.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/DataCage.java Mon Aug 01 08:11:12 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -package de.intevation.flys.artifacts.services.meta; - -import java.util.Map; -import java.util.HashMap; - -import java.io.InputStream; -import java.io.IOException; -import java.io.File; - -import java.io.FileInputStream; - -import java.sql.Connection; -import java.sql.SQLException; - -import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import org.hibernate.Session; - -import org.hibernate.jdbc.Work; - -import de.intevation.artifacts.common.utils.Config; -import de.intevation.artifacts.common.utils.XMLUtils; - -import de.intevation.flys.artifacts.FLYSArtifact; - -import de.intevation.flys.backend.SessionHolder; - -import de.intevation.artifactdatabase.data.StateData; - - -public class DataCage -{ - private static Logger log = Logger.getLogger(DataCage.class); - - public static final String XPATH_META_DATA_TEMPLATE = - "/artifact-database/metadata/@template"; - - private static DataCage INSTANCE; - - protected Builder builder; - - public DataCage() { - } - - public DataCage(Builder builder) { - this.builder = builder; - } - - public Builder getBuilder() { - return builder; - } - - protected static void artifactToParameters( - FLYSArtifact artifact, - Map parameters - ) { - parameters.put("current-state-id", artifact.getCurrentStateId()); - - for (StateData sd: artifact.getAllData()) { - Object value = sd.getValue(); - if (value == null) { - continue; - } - String key = sd.getName().replace('.', '-'); - parameters.put(key, value); - } - } - - public void recommend( - FLYSArtifact artifact, - String [] outs, - Map extraParameters, - Node result - ) { - Map parameters = new HashMap(); - - if (extraParameters != null) { - parameters.putAll(extraParameters); - } - - if (artifact != null) { - artifactToParameters(artifact, parameters); - } - - parameters.put("artifact-outs", outs); - - parameters.put("parameters", parameters); - - recommend(parameters, result); - } - - public void recommend( - final Map parameters, - final Node result - ) { - if (builder == null) { - log.error("builder not configured properly."); - return; - } - - Session session = SessionHolder.HOLDER.get(); - - session.doWork(new Work() { - @Override - public void execute(Connection connection) - throws SQLException - { - builder.build(connection, result, parameters); - } - }); - } - - public static synchronized DataCage getInstance() { - if (INSTANCE == null) { - INSTANCE = createDataCage(); - } - return INSTANCE; - } - - protected static Builder createBuilder(File file) { - log.debug("DataCage.createBuilder"); - - if (!file.isFile() || !file.canRead()) { - log.error("Cannot open template file '" + file + "'"); - return null; - } - - InputStream in = null; - - try { - in = new FileInputStream(file); - - Document template = XMLUtils.parseDocument(in); - - if (template == null) { - log.error("cannot parse meta data template"); - } - else { - return new Builder(template); - } - } - catch (IOException ioe) { - log.error(ioe); - } - finally { - if (in != null) { - try { - in.close(); - } - catch (IOException ioe) { - log.error(ioe); - } - } - } - return null; - } - - protected static DataCage createDataCage() { - log.debug("DataCage.createDataCage"); - - String path = Config.getStringXPath(XPATH_META_DATA_TEMPLATE); - if (path == null) { - log.error("no path to template file given"); - return null; - } - - path = Config.replaceConfigDir(path); - - return new DataCage(createBuilder(new File(path))); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/FunctionResolver.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/FunctionResolver.java Mon Aug 01 08:11:12 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -package de.intevation.flys.artifacts.services.meta; - -import java.util.List; -import java.util.Collection; -import java.util.Map; -import java.util.ArrayList; - -import javax.xml.xpath.XPathFunctionResolver; -import javax.xml.xpath.XPathFunction; -import javax.xml.xpath.XPathFunctionException; - -import javax.xml.namespace.QName; - -import org.apache.log4j.Logger; - -public class FunctionResolver -implements XPathFunctionResolver -{ - private static Logger log = Logger.getLogger(FunctionResolver.class); - - public static final String FUNCTION_NAMESPACE_URI = "dc"; - - public static final class Entry { - - String name; - XPathFunction function; - int arity; - - public Entry() { - } - - public Entry(String name, XPathFunction function, int arity) { - this.name = name; - this.function = function; - this.arity = arity; - } - } // class Entry - - public static final FunctionResolver FUNCTIONS = new FunctionResolver(); - - static { - FUNCTIONS.addFunction("contains", 2, new XPathFunction() { - @Override - public Object evaluate(List args) throws XPathFunctionException { - Object haystack = args.get(0); - Object needle = args.get(1); - try { - if (haystack instanceof Collection) { - return Boolean.valueOf( - ((Collection)haystack).contains(needle)); - } - - if (haystack instanceof Map) { - return Boolean.valueOf( - ((Map)haystack).containsKey(needle)); - } - - if (haystack instanceof Object []) { - for (Object straw: (Object [])haystack) { - if (straw.equals(needle)) { - return Boolean.TRUE; - } - } - } - - return Boolean.FALSE; - } - catch (Exception e) { - log.error(e); - throw new XPathFunctionException(e); - } - } - }); - } - - protected List functions; - - public FunctionResolver() { - functions = new ArrayList(); - } - - public void addFunction(String name, int arity, XPathFunction function) { - functions.add(new Entry(name, function, arity)); - } - - @Override - public XPathFunction resolveFunction(QName functionName, int arity) { - - if (!functionName.getNamespaceURI().equals(FUNCTION_NAMESPACE_URI)) { - return null; - } - - String name = functionName.getLocalPart(); - for (Entry entry: functions) { - if (entry.arity == arity && entry.name.equals(name)) { - return entry.function; - } - } - - return null; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/ResultData.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/ResultData.java Mon Aug 01 08:11:12 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -package de.intevation.flys.artifacts.services.meta; - -import java.io.Serializable; - -import java.sql.ResultSetMetaData; -import java.sql.ResultSet; -import java.sql.SQLException; - -import java.util.List; -import java.util.ArrayList; - -public class ResultData -implements Serializable -{ - protected String [] columns; - - protected List rows; - - public ResultData() { - rows = new ArrayList(); - } - - public ResultData(ResultSetMetaData meta) - throws SQLException - { - this(); - - int N = meta.getColumnCount(); - - columns = new String[N]; - - for (int i = 1; i <= N; ++i) { - columns[i-1] = meta.getColumnLabel(i); - } - } - - public String [] getColumnLabels() { - return columns; - } - - public ResultData addAll(ResultSet result) throws SQLException { - while (result.next()) { - add(result); - } - return this; - } - - public void add(ResultSet result) throws SQLException { - Object [] row = new Object[columns.length]; - for (int i = 0; i < columns.length; ++i) { - row[i] = result.getObject(i+1); - } - rows.add(row); - } - - public List getRows() { - return rows; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/StackFrames.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/StackFrames.java Mon Aug 01 08:11:12 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -package de.intevation.flys.artifacts.services.meta; - -import java.util.Map; -import java.util.List; -import java.util.HashMap; -import java.util.ArrayList; - -import javax.xml.xpath.XPathVariableResolver; - -import javax.xml.namespace.QName; - -import org.apache.log4j.Logger; - -public class StackFrames -implements XPathVariableResolver -{ - private static Logger log = Logger.getLogger(StackFrames.class); - - protected List> frames; - - public StackFrames() { - frames = new ArrayList>(); - } - - public StackFrames(Map initialFrame) { - this(); - if (initialFrame != null) { - frames.add(new HashMap(initialFrame)); - } - } - - public void enter() { - frames.add(new HashMap()); - } - - public void leave() { - frames.remove(frames.size()-1); - } - - public void put(String key, Object value) { - int N = frames.size(); - if (N > 0) { - frames.get(N-1).put(key, value); - } - } - - public void put(String [] keys, Object [] values) { - Map top = frames.get(frames.size()-1); - for (int i = 0; i < keys.length; ++i) { - top.put(keys[i], values[i]); - } - } - - public boolean containsKey(String key) { - for (int i = frames.size()-1; i >= 0; --i) { - if (frames.get(i).containsKey(key)) { - return true; - } - } - return false; - } - - public Object get(String key) { - return get(key, null); - } - - public Object get(String key, Object def) { - - for (int i = frames.size()-1; i >= 0; --i) { - Map frame = frames.get(i); - if (frame.containsKey(key)) { - return frame.get(key); - } - } - - return def; - } - - @Override - public Object resolveVariable(QName variableName) { - if (log.isDebugEnabled()) { - log.debug("resolve var: " + variableName); - } - return get(variableName.getLocalPart()); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 4c82609824c8 -r b81626b10cb7 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/TypeConverter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/TypeConverter.java Mon Aug 01 08:11:12 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -package de.intevation.flys.artifacts.services.meta; - -public class TypeConverter -{ - private TypeConverter() { - } - - public static Object convert(Object object, String type) { - - if (type == null) { - return object; - } - - if ("Integer".equals(type)) { - return Integer.valueOf(object.toString()); - } - - if ("Double".equals(type)) { - return Double.valueOf(object.toString()); - } - - if ("String".equals(type)) { - return object.toString(); - } - - // TODO: Add more types - - return object; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :