|
From: <sa...@us...> - 2004-02-26 10:49:11
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24419/org/jrobin/core Modified Files: RrdDef.java RrdDefTemplate.java Util.java XmlTemplate.java Log Message: XML templates (finished) Index: RrdDef.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDef.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** RrdDef.java 8 Dec 2003 13:47:40 -0000 1.6 --- RrdDef.java 26 Feb 2004 10:33:29 -0000 1.7 *************** *** 27,30 **** --- 27,32 ---- import java.util.ArrayList; + import java.util.Date; + import java.util.GregorianCalendar; /** *************** *** 141,146 **** /** ! * Sets RRD starting timestamp. ! * @param startTime RRD starting timestamp. */ public void setStartTime(long startTime) { --- 143,148 ---- /** ! * Sets RRD's starting timestamp. ! * @param startTime starting timestamp. */ public void setStartTime(long startTime) { *************** *** 149,153 **** /** ! * Sets RRD time step. * @param step RRD time step. */ --- 151,171 ---- /** ! * Sets RRD's starting timestamp. ! * @param date starting date ! */ ! public void setStartTime(Date date) { ! this.startTime = Util.getTimestamp(date); ! } ! ! /** ! * Sets RRD's starting timestamp. ! * @param gc starting date ! */ ! public void setStartTime(GregorianCalendar gc) { ! this.startTime = Util.getTimestamp(gc); ! } ! ! /** ! * Sets RRD's time step. * @param step RRD time step. */ Index: RrdDefTemplate.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDefTemplate.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** RrdDefTemplate.java 25 Feb 2004 15:28:05 -0000 1.2 --- RrdDefTemplate.java 26 Feb 2004 10:33:29 -0000 1.3 *************** *** 30,48 **** 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> --- 30,49 ---- import java.io.IOException; import java.io.File; + import java.util.GregorianCalendar; /** ! * Class used to create an arbitrary number of RrdDef (RRD file definition) objects ! * from a single XML template. XML template can be supplied as an XML InputSource, ! * XML file or XML formatted string.<p> * ! * Here is an example of a properly formatted XML template with all available options in it ! * (unwanted options can be removed):<p> ! * <pre> * <rrd_def> ! * <path>test.rrd</path> * <!-- not mandatory --> * <start>1000123456</start> * <!-- not mandatory --> ! * <step>300</step> * <!-- at least one datasource must be supplied --> * <datasource> *************** *** 65,69 **** * <xff>0.5</xff> * <steps>1</steps> ! * <rows>${rows}</rows> * </archive> * <archive> --- 66,70 ---- * <xff>0.5</xff> * <steps>1</steps> ! * <rows>600</rows> * </archive> * <archive> *************** *** 74,123 **** * </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 { --- 75,131 ---- * </archive> * </rrd_def> ! * </pre> ! * Notes on the template syntax:<p> ! * <ul> ! * <li>There is a strong relation between the XML template syntax and the syntax of ! * {@link RrdDef} class methods. If you are not sure what some XML tag means, check javadoc ! * for the corresponding class. ! * <li>starting timestamp can be supplied either as a long integer ! * (like: 1000243567) or as an ISO formatted string (like: 2004-02-21 12:25:45) ! * <li>whitespaces are not harmful ! * <li>floating point values: anything that cannot be parsed will be treated as Double.NaN ! * (like: U, unknown, 12r.23) ! * <li>comments are allowed. ! * </ul> ! * Any template value (text between <code><some_tag></code> and ! * <code></some_tag></code>) can be replaced with ! * a variable of the following form: <code>${variable_name}</code>. Use ! * {@link XmlTemplate#setVariable(String, String) setVariable()} ! * methods from the base class to replace template variables with real values ! * at runtime.<p> * + * Typical usage scenario:<p> + * <ul> + * <li>Create your XML template and save it to a file (template.xml, for example) + * <li>Replace hardcoded template values with variables if you want to change them during runtime. + * For example, file path should not be hardcoded in the template - you probably want to create + * many different RRD files from the same XML template. For example, your XML + * template could start with: + * <pre> + * <rrd_def> + * <path>${path}</path> + * <step>300</step> + * ... + * </pre> + * <li>In your Java code, create RrdDefTemplate object using your XML template file: + * <pre> + * RrdDefTemplate t = new RrdDefTemplate(new File(template.xml)); + * </pre> + * <li>Then, specify real values for template variables: + * <pre> + * t.setVariable("path", "demo/test.rrd"); + * </pre> + * <li>Once all template variables are set, just use the template object to create RrdDef + * object. This object is actually used to create JRobin RRD files: * <pre> * RrdDef def = t.getRrdDef(); ! * RrdDb rrd = new RrdDb(def); ! * rrd.close(); * </pre> + * </ul> + * You should create new RrdDefTemplate object only once for each XML template. Single template + * object can be reused to create as many RrdDef objects as needed, with different values + * specified for template variables. XML synatax check is performed only once - the first + * definition object gets created relatively slowly, but it will be created much faster next time. */ public class RrdDefTemplate extends XmlTemplate { *************** *** 159,163 **** * 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> --- 167,171 ---- * is called, values for all non-optional placeholders must be supplied. To specify * placeholder values at runtime, use some of the overloaded ! * {@link XmlTemplate#setVariable(String, String) setVariable()} methods. Once this method * returns, all placeholder values are preserved. To remove them all, call inhereted * {@link XmlTemplate#clearValues() clearValues()} method explicitly.<p> *************** *** 167,171 **** * 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 */ --- 175,179 ---- * of the new RrdDb object. * @throws RrdException Thrown (in most cases) if the value for some placeholder ! * was not supplied through {@link XmlTemplate#setVariable(String, String) setVariable()} * method call */ *************** *** 174,183 **** 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 --- 182,195 ---- throw new RrdException("XML definition must start with <rrd_def>"); } + validateTagsOnlyOnce(root, new String[] { + "path", "start", "step", "datasource*", "archive*" + }); // PATH must be supplied or exception is thrown String path = getChildValue(root, "path"); RrdDef rrdDef = new RrdDef(path); try { ! String startStr = getChildValue(root, "start"); ! GregorianCalendar startGc = Util.getGregorianCalendar(startStr); ! rrdDef.setStartTime(startGc); } catch (RrdException e) { // START is not mandatory *************** *** 192,195 **** --- 204,210 ---- Node[] dsNodes = getChildNodes(root, "datasource"); for (int i = 0; i < dsNodes.length; i++) { + validateTagsOnlyOnce(dsNodes[i], new String[] { + "name", "type", "heartbeat", "min", "max" + }); String name = getChildValue(dsNodes[i], "name"); String type = getChildValue(dsNodes[i], "type"); *************** *** 202,205 **** --- 217,223 ---- Node[] arcNodes = getChildNodes(root, "archive"); for (int i = 0; i < arcNodes.length; i++) { + validateTagsOnlyOnce(arcNodes[i], new String[] { + "cf", "xff", "steps", "rows" + }); String consolFun = getChildValue(arcNodes[i], "cf"); double xff = getChildValueAsDouble(arcNodes[i], "xff"); *************** *** 211,226 **** } ! public static void main(String[] args) throws RrdException, IOException { File f = new File("work/test.xml"); RrdDefTemplate t = new RrdDefTemplate(f); ! t.setMapping("path", "test1.rrd"); ! t.setMapping("step", 310); ! t.setMapping("hb", 123); RrdDef def = t.getRrdDef(); System.out.println(def.dump()); - } } --- 229,254 ---- } ! /* public static void main(String[] args) throws RrdException, IOException { File f = new File("work/test.xml"); RrdDefTemplate t = new RrdDefTemplate(f); ! t.setVariable("path", "work/test1.rrd"); ! t.setVariable("start", new GregorianCalendar(2004, 2, 12, 12, 23, 34)); ! t.setVariable("step", 310); ! t.setVariable("hb", 123); RrdDef def = t.getRrdDef(); System.out.println(def.dump()); + t.setVariable("path", "work/test2.rrd"); + t.setVariable("step", 320); + t.setVariable("hb", 321); + t.setVariable("start", new GregorianCalendar()); + + RrdDef def2 = t.getRrdDef(); + System.out.println(def2.dump()); + + } + */ } Index: Util.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Util.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** Util.java 25 Feb 2004 15:28:05 -0000 1.10 --- Util.java 26 Feb 2004 10:33:29 -0000 1.11 *************** *** 38,41 **** --- 38,43 ---- import java.text.DecimalFormat; import java.text.NumberFormat; + import java.text.SimpleDateFormat; + import java.text.ParseException; import java.util.Date; import java.util.Locale; *************** *** 43,47 **** import java.util.ArrayList; import java.io.*; - import java.awt.*; /** --- 45,48 ---- *************** *** 166,169 **** --- 167,171 ---- */ public static long getTimestamp(Date date) { + // round to whole seconds, ignore milliseconds return (date.getTime() + 499L) / 1000L; } *************** *** 288,291 **** --- 290,321 ---- } + static final String ISO_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; // ISO + + /** + * Creates GregorianCalendar object from a string. The string should represent + * either a long integer (UNIX timestamp in seconds without milliseconds, + * like "1002354657") or a human readable date string in the format "yyyy-MM-dd HH:mm:ss" + * (like "2004-02-25 12:23:45"). + * @param timeStr Input string + * @return GregorianCalendar object + */ + public static GregorianCalendar getGregorianCalendar(String timeStr) { + // try to parse it as long + try { + long timestamp = Long.parseLong(timeStr); + return Util.getGregorianCalendar(timestamp); + } catch (NumberFormatException e) { } + // not a long timestamp, try to parse it as data + SimpleDateFormat df = new SimpleDateFormat(ISO_DATE_FORMAT); + df.setLenient(false); + try { + Date date = df.parse(timeStr); + return Util.getGregorianCalendar(date); + } catch (ParseException e) { + throw new IllegalArgumentException("Time/date not in " + ISO_DATE_FORMAT + + " format: " + timeStr); + } + } + /** * Various DOM utility functions Index: XmlTemplate.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/XmlTemplate.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** XmlTemplate.java 25 Feb 2004 15:28:05 -0000 1.2 --- XmlTemplate.java 26 Feb 2004 10:33:29 -0000 1.3 *************** *** 76,80 **** * @param value value to be set in the XML template */ ! public void setMapping(String name, String value) { valueMap.put(name, value); } --- 76,80 ---- * @param value value to be set in the XML template */ ! public void setVariable(String name, String value) { valueMap.put(name, value); } *************** *** 87,91 **** * @param value value to be set in the XML template */ ! public void setMapping(String name, int value) { valueMap.put(name, new Integer(value)); } --- 87,91 ---- * @param value value to be set in the XML template */ ! public void setVariable(String name, int value) { valueMap.put(name, new Integer(value)); } *************** *** 98,102 **** * @param value value to be set in the XML template */ ! public void setMapping(String name, long value) { valueMap.put(name, new Long(value)); } --- 98,102 ---- * @param value value to be set in the XML template */ ! public void setVariable(String name, long value) { valueMap.put(name, new Long(value)); } *************** *** 109,113 **** * @param value value to be set in the XML template */ ! public void setMapping(String name, double value) { valueMap.put(name, new Double(value)); } --- 109,113 ---- * @param value value to be set in the XML template */ ! public void setVariable(String name, double value) { valueMap.put(name, new Double(value)); } *************** *** 120,124 **** * @param value value to be set in the XML template */ ! public void setMapping(String name, Color value) { valueMap.put(name, "#" + Integer.toHexString(value.getRGB() & 0xFFFFFF)); } --- 120,124 ---- * @param value value to be set in the XML template */ ! public void setVariable(String name, Color value) { valueMap.put(name, "#" + Integer.toHexString(value.getRGB() & 0xFFFFFF)); } *************** *** 131,136 **** * @param value value to be set in the XML template */ ! public void setMapping(String name, Date value) { ! setMapping(name, Util.getTimestamp(value)); } --- 131,136 ---- * @param value value to be set in the XML template */ ! public void setVariable(String name, Date value) { ! setVariable(name, Util.getTimestamp(value)); } *************** *** 142,147 **** * @param value value to be set in the XML template */ ! public void setMapping(String name, GregorianCalendar value) { ! setMapping(name, Util.getTimestamp(value)); } --- 142,147 ---- * @param value value to be set in the XML template */ ! public void setVariable(String name, GregorianCalendar value) { ! setVariable(name, Util.getTimestamp(value)); } *************** *** 153,157 **** * @param value value to be set in the XML template */ ! public void setMapping(String name, boolean value) { valueMap.put(name, "" + value); } --- 153,157 ---- * @param value value to be set in the XML template */ ! public void setVariable(String name, boolean value) { valueMap.put(name, "" + value); } *************** *** 193,197 **** else { // no mapping found - this is illegal ! throw new IllegalArgumentException("No mapping found for template variable " + value); } } --- 193,198 ---- else { // no mapping found - this is illegal ! throw new IllegalArgumentException( ! "No mapping found for template variable " + value); } } *************** *** 245,252 **** } ! protected void validateOnce(Node parentNode, String[] allowedChildNames) throws RrdException { // validate node only once if(validatedNodes.contains(parentNode)) { - //System.out.println("Already validated"); return; } --- 246,252 ---- } ! protected void validateTagsOnlyOnce(Node parentNode, String[] allowedChildNames) throws RrdException { // validate node only once if(validatedNodes.contains(parentNode)) { return; } *************** *** 256,260 **** String childName = childs[i].getNodeName(); for(int j = 0; j < allowedChildNames.length; j++) { ! if(childName.equals(allowedChildNames[j])) { continue main; } --- 256,266 ---- String childName = childs[i].getNodeName(); for(int j = 0; j < allowedChildNames.length; j++) { ! if(allowedChildNames[j].equals(childName)) { ! // only one such tag is allowed ! allowedChildNames[j] = "<--removed-->"; ! continue main; ! } ! else if(allowedChildNames[j].equals(childName + "*")) { ! // several tags allowed continue main; } *************** *** 264,267 **** --- 270,274 ---- } } + // everything is OK validatedNodes.add(parentNode); } |