|
From: <sa...@us...> - 2004-02-23 16:03:18
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11576/org/jrobin/core Added Files: RrdDefTemplate.java XmlTemplate.java Log Message: XML templates revisited --- NEW FILE: RrdDefTemplate.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@jr...) * Arne Vandamme (cob...@jr...) * * This library is free software; you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Foundation; * either version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ package org.jrobin.core; import org.xml.sax.InputSource; import org.w3c.dom.Node; import java.io.IOException; import java.io.File; /** * Class to represent RrdDef XML template. Use this class to produce similar RRD definitions * (RrdDef objects) from the same XML template. Use <code>${placeholder_name}</code> placeholders * in the XML source to mark XML code which will be modified (replaced) at run time.<p> * * Here is a self-explaining example of a valid XML definition:<p> * * <pre><code> * <rrd_def> * <path>${path}</path> * <!-- not mandatory --> * <start>1000123456</start> * <!-- not mandatory --> * <step>${step}</step> * <!-- at least one datasource must be supplied --> * <datasource> * <name>input</name> * <type>COUNTER</type> * <heartbeat>300</heartbeat> * <min>0</min> * <max>U</max> * </datasource> * <datasource> * <name>temperature</name> * <type>GAUGE</type> * <heartbeat>400</heartbeat> * <min>U</min> * <max>1000</max> * </datasource> * <!-- at least one archive must be supplied --> * <archive> * <cf>AVERAGE</cf> * <xff>0.5</xff> * <steps>1</steps> * <rows>${rows}</rows> * </archive> * <archive> * <cf>MAX</cf> * <xff>0.6</xff> * <steps>6</steps> * <rows>7000</rows> * </archive> * </rrd_def> * </code></pre> * XML template can be embedded in a String or a file - the class provides constructors in both * cases. <p> * * Note that the above XML definition contains three placeholders (<code>${path}</code>, * <code>${step}</code> and <code>${rows}</code>) - these placeholders must be replaced with * real values before the RrdDef object is requested by calling {@link #getRrdDef getRrdDef()} * method. To replace placeholders with real values at run time use inhereted * (and overloaded) public {@link XmlTemplate#setMapping(String, String) setMapping()} * methods.<p> * * You are free to use the same template object to create as many RrdDef objects as needed * (probably with different placeholder-value mappings).<p> * * Here is an example how to create two different RRD files using the template given above:<p> * * <pre> * // 'template.xml' file contains XML template already specified * File file = new File("template.xml"); * RrdDefTemplate t = new RrdDefTemplate(file); * * // replace ${path} placeholder with the real value (test1.rrd) * t.setMapping("path", "test1.rrd"); * * // replace ${step} placeholder with the real value (600) * t.setMapping("step", 600); * * // replace ${rows} placeholder with the real value (800) * t.setMapping("rows", 800); * * // get RrdDef from the template object... * RrdDef def = t.getRrdDef(); * * // ...and use it to construct the first RRD file * RrdDb rrd = new RrdDb(def); rrd.close(); * * // note that all mappings are still active * // change the value for some (or all) placeholders * // to construct the second database * // with different parameters * t.setMapping("path", "test2.rrd"); * def = t.getRrdDef(); * * // the second RRD file will be also created with step=600, rows=800 * rrd = new RrdDb(def); rrd.close(); * </pre> */ public class RrdDefTemplate extends XmlTemplate { /** * Creates RrdDefTemplate object from any parsable XML input source. Read general information * for this class to find an example of a properly formatted RrdDef XML source. * @param xmlInputSource Xml input source * @throws IOException Thrown in case of I/O error * @throws RrdException Thrown in case of XML related error (parsing error, for example) */ public RrdDefTemplate(InputSource xmlInputSource) throws IOException, RrdException { super(xmlInputSource); } /** * Creates RrdDefTemplate object from the string containing XML template. * Read general information for this class to see an example of a properly formatted XML source. * @param xmlString String containing XML template * @throws IOException Thrown in case of I/O error * @throws RrdException Thrown in case of XML related error (parsing error, for example) */ public RrdDefTemplate(String xmlString) throws IOException, RrdException { super(xmlString); } /** * Creates RrdDefTemplate object from the file containing XML template. * Read general information for this class to see an example of a properly formatted XML source. * @param xmlFile File object representing file with XML template * @throws IOException Thrown in case of I/O error * @throws RrdException Thrown in case of XML related error (parsing error, for example) */ public RrdDefTemplate(File xmlFile) throws IOException, RrdException { super(xmlFile); } /** * Returns RrdDef object constructed from the underlying XML template. Before this method * is called, values for all non-optional placeholders must be supplied. To specify * placeholder values at runtime, use some of the overloaded * {@link XmlTemplate#setMapping(String, String) setMapping()} methods. Once this method * returns, all placeholder values are preserved. To remove them all, call inhereted * {@link XmlTemplate#clearValues() clearValues()} method explicitly.<p> * * @return RrdDef object constructed from the underlying XML template, * with all placeholders replaced with real values. This object can be passed to the constructor * of the new RrdDb object. * @throws RrdException Thrown (in most cases) if the value for some placeholder * was not supplied through {@link XmlTemplate#setMapping(String, String) setMapping()} * method call */ public RrdDef getRrdDef() throws RrdException { if (!root.getTagName().equals("rrd_def")) { throw new RrdException("XML definition must start with <rrd_def>"); } // PATH must be supplied or exception is thrown String path = getChildValue(root, "path"); RrdDef rrdDef = new RrdDef(path); try { long start = getChildValueAsLong(root, "start"); rrdDef.setStartTime(start); } catch (RrdException e) { // START is not mandatory } try { long step = getChildValueAsLong(root, "step"); rrdDef.setStep(step); } catch (RrdException e) { // STEP is not mandatory } // datsources Node[] dsNodes = getChildNodes(root, "datasource"); for (int i = 0; i < dsNodes.length; i++) { String name = getChildValue(dsNodes[i], "name"); String type = getChildValue(dsNodes[i], "type"); long heartbeat = getChildValueAsLong(dsNodes[i], "heartbeat"); double min = getChildValueAsDouble(dsNodes[i], "min"); double max = getChildValueAsDouble(dsNodes[i], "max"); rrdDef.addDatasource(name, type, heartbeat, min, max); } // archives Node[] arcNodes = getChildNodes(root, "archive"); for (int i = 0; i < arcNodes.length; i++) { String consolFun = getChildValue(arcNodes[i], "cf"); double xff = getChildValueAsDouble(arcNodes[i], "xff"); int steps = getChildValueAsInt(arcNodes[i], "steps"); int rows = getChildValueAsInt(arcNodes[i], "rows"); rrdDef.addArchive(consolFun, xff, steps, rows); } return rrdDef; } /* public static void main(String[] args) throws RrdException, IOException { String s = "<rrd_def> " + " <path>${path}</path> " + " <start>1000000000</start> " + " <step>${step}</step> " + " <datasource> " + " <name>input</name> " + " <type>COUNTER</type> " + " <heartbeat>300</heartbeat> " + " <min>10</min> " + " <max>U</max> " + " </datasource> " + " <datasource> " + " <name>temperature</name> " + " <type>GAUGE</type> " + " <heartbeat>400</heartbeat> " + " <min>U</min> " + " <max>1000</max> " + " </datasource> " + " <archive> " + " <cf>AVERAGE</cf> " + " <xff>0.5</xff> " + " <steps>1</steps> " + " <rows>${rows}</rows> " + " </archive> " + " <archive> " + " <cf>MAX</cf> " + " <xff>0.6</xff> " + " <steps>6</steps> " + " <rows>7000</rows> " + " </archive> " + "</rrd_def> "; RrdDefTemplate t = new RrdDefTemplate(s); // works as well: // File f = new File("test.xml"); // RrdDefTemplate t = new RrdDefTemplate(f); t.setMapping("path", "test1.rrd"); t.setMapping("step", 310); t.setMapping("rows", 888); RrdDef def = t.getRrdDef(); System.out.println(def.dump()); new RrdDb(def).close(); t.setMapping("path", "test2.rrd"); t.setMapping("step", 320); t.setMapping("rows", 999); def = t.getRrdDef(); System.out.println(def.dump()); new RrdDb(def).close(); } */ } --- NEW FILE: XmlTemplate.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@jr...) * Arne Vandamme (cob...@jr...) * * This library is free software; you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Foundation; * either version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ package org.jrobin.core; import org.w3c.dom.Node; import org.w3c.dom.Element; import org.xml.sax.InputSource; import java.io.IOException; import java.io.File; import java.util.HashMap; /** * Class used as a base class for various XML template related classes. Class provides * methods for XML source parsing and XML tree traversing. XML source may have unlimited * number of placeholders in the format <code>${placeholder_name}</code>. Methods are provided * to specify values of placeholders at runtime. Note that this class has limited functionality: * XML source gets parsed, and placeholder values are collected. You have to extend this class * to do anything more useful.<p> */ public abstract class XmlTemplate { /** * root element of the DOM hierarchy representing XML source */ protected Element root; private HashMap valueMap = new HashMap(); /** * Creates XmlTemplate object from any parsable XML input source * @param xmlSource Any parsable XML input source * @throws IOException thrown in case of I/O error * @throws RrdException thrown (in most cases) when the source has invalid XML syntax * (cannot be parsed at all) */ protected XmlTemplate(InputSource xmlSource) throws IOException, RrdException { root = Util.Xml.getRootElement(xmlSource); } /** * Creates XmlTemplate object from a string containing properly formatted XML * @param xmlString parsable XML string * @throws IOException thrown in case of I/O error * @throws RrdException thrown (in most cases) when the source has invalid XML syntax * (cannot be parsed at all) */ protected XmlTemplate(String xmlString) throws IOException, RrdException { root = Util.Xml.getRootElement(xmlString); } /** * Creates XmlTemplate object from a file containing properly formatted XML * @param xmlFile File object representing file containing parsable XML source * @throws IOException thrown in case of I/O error * @throws RrdException thrown (in most cases) when the source has invalid XML syntax * (cannot be parsed at all) */ protected XmlTemplate(File xmlFile) throws IOException, RrdException { root = Util.Xml.getRootElement(xmlFile); } /** * Removes all placeholder-value mappings. */ public void clearValues() { valueMap.clear(); } /** * Sets value for the given placeholder. Placeholder should be supplied by its name. * For example, for a placeholder <code>${param}</code> specify just <code>param</code> * for its name. * @param name Name of the placeholder (placeholder without leading '${' and ending '}'). * @param value Value to replace placeholder with. */ public void setMapping(String name, String value) { valueMap.put(name, value); } /** * Sets value for the given placeholder. Placeholder should be supplied by its name. * For example, for a placeholder <code>${param}</code> specify just <code>param</code> * for its name. * @param name Name of the placeholder (placeholder without leading '${' and ending '}'). * @param value Value to replace placeholder with. */ public void setMapping(String name, int value) { valueMap.put(name, new Integer(value)); } /** * Sets value for the given placeholder. Placeholder should be supplied by its name. * For example, for a placeholder <code>${param}</code> specify just <code>param</code> * for its name. * @param name Name of the placeholder (placeholder without leading '${' and ending '}'). * @param value Value to replace placeholder with. */ public void setMapping(String name, long value) { valueMap.put(name, new Long(value)); } /** * Sets value for the given placeholder. Placeholder should be supplied by its name. * For example, for a placeholder <code>${param}</code> specify just <code>param</code> * for its name. * @param name Name of the placeholder (placeholder without leading '${' and ending '}'). * @param value Value to replace placeholder with. */ public void setMapping(String name, double value) { valueMap.put(name, new Double(value)); } /** * Returns all child nodes with the given tag * belonging to the specified parent Node * @param parentNode Parent node * @param childName Child node tag * @return Array of child nodes with the specified parent and with the given tag name */ protected static Node[] getChildNodes(Node parentNode, String childName) { return Util.Xml.getChildNodes(parentNode, childName); } /** * Returns the first child node with the given parent and the given tag. * @param parentNode Parent node * @param childName Child node tag * @return First child node with the given parent node and the given tag. * @throws RrdException Thrown if no such child can be found */ protected static Node getFirstChildNode(Node parentNode, String childName) throws RrdException { return Util.Xml.getFirstChildNode(parentNode, childName); } /** * Returns the 'value' of the child node with the given parent and the given tag name. * For example, in a DOM-tree created from the following XML source:<p> * <pre> * ...<root><branch>abc</branch></root>... * </pre> * and assuming that <code>parentNode</code> points to the <code><root></code> element, * the following call:<p> * <pre> * getChildValue(parentNode, "branch"); * </pre> * returns:<p> * <code>abc</code><p> * @param parentNode Parent DOM node * @param childName Child node tag * @return XML 'value' of the child node (trimmed content between <childName> and </childName> * tags) * @throws RrdException Thrown if no such child node exists. */ protected String getChildValue(Node parentNode, String childName) throws RrdException { String value = Util.Xml.getChildValue(parentNode, childName); if(value.startsWith("${") && value.endsWith("}")) { // template variable found, remove leading "${" and trailing "}" String var = value.substring(2, value.length() - 1); if(valueMap.containsKey(var)) { // mapping found value = valueMap.get(var).toString(); } else { // no mapping found - this is illegal throw new RrdException("No mapping found for template variable " + value); } } return value; } /** * Returns the 'value' of the child node with the given parent and the given tag name. * For example, in a DOM-tree created from the following XML source:<p> * <pre> * ...<root><branch>123</branch></root>... * </pre> * and assuming that <code>parentNode</code> points to the <code><root></code> element, * the following call:<p> * <pre> * getChildValue(parentNode, "branch"); * </pre> * returns:<p> * <code>123</code><p> * @param parentNode Parent DOM node * @param childName Child node tag * @return XML 'value' of the child node (trimmed content between <childName> and </childName> * tags) * @throws RrdException Thrown if no such child node exists. */ protected int getChildValueAsInt(Node parentNode, String childName) throws RrdException, NumberFormatException { String valueStr = getChildValue(parentNode, childName); return Integer.parseInt(valueStr); } /** * Returns the 'value' of the child node with the given parent and the given tag name. * For example, in a DOM-tree created from the following XML source:<p> * <pre> * ...<root><branch>123</branch></root>... * </pre> * and assuming that <code>parentNode</code> points to the <code><root></code> element, * the following call:<p> * <pre> * getChildValue(parentNode, "branch"); * </pre> * returns:<p> * <code>123</code><p> * @param parentNode Parent DOM node * @param childName Child node tag * @return XML 'value' of the child node (trimmed content between <childName> and </childName> * tags) * @throws RrdException Thrown if no such child node exists. */ protected long getChildValueAsLong(Node parentNode, String childName) throws RrdException, NumberFormatException { String valueStr = getChildValue(parentNode, childName); return Long.parseLong(valueStr); } /** * Returns the 'value' of the child node with the given parent and the given tag name. * For example, in a DOM-tree created from the following XML source:<p> * <pre> * ...<root><branch>123.45</branch></root>... * </pre> * and assuming that <code>parentNode</code> points to the <code><root></code> element, * the following call:<p> * <pre> * getChildValue(parentNode, "branch"); * </pre> * returns:<p> * <code>123.45</code><p> * @param parentNode Parent DOM node * @param childName Child node tag * @return XML 'value' of the child node (trimmed content between <childName> and </childName> * tags) * @throws RrdException Thrown if no such child node exists. */ protected double getChildValueAsDouble(Node parentNode, String childName) throws RrdException { String valueStr = getChildValue(parentNode, childName); return Util.parseDouble(valueStr); } } |