| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| <!--NewPage--> |
| <HTML> |
| <HEAD> |
| <!-- Generated by javadoc (build 1.6.0_45) on Tue Mar 28 22:09:47 CEST 2017 --> |
| <META http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <TITLE> |
| Overview (Schema2template v0.8.11-incubating - http://incubator.apache.org/odftoolkit/) |
| </TITLE> |
| |
| <META NAME="date" CONTENT="2017-03-28"> |
| |
| <LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style"> |
| |
| <SCRIPT type="text/javascript"> |
| function windowTitle() |
| { |
| if (location.href.indexOf('is-external=true') == -1) { |
| parent.document.title="Overview (Schema2template v0.8.11-incubating - http://incubator.apache.org/odftoolkit/)"; |
| } |
| } |
| </SCRIPT> |
| <NOSCRIPT> |
| </NOSCRIPT> |
| |
| </HEAD> |
| |
| <BODY BGCOLOR="white" onload="windowTitle();"> |
| <HR> |
| |
| |
| <!-- ========= START OF TOP NAVBAR ======= --> |
| <A NAME="navbar_top"><!-- --></A> |
| <A HREF="#skip-navbar_top" title="Skip navigation links"></A> |
| <TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY=""> |
| <TR> |
| <TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> |
| <A NAME="navbar_top_firstrow"><!-- --></A> |
| <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY=""> |
| <TR ALIGN="center" VALIGN="top"> |
| <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Overview</B></FONT> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Use</FONT> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-files/index-1.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD> |
| </TR> |
| </TABLE> |
| </TD> |
| <TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM> |
| </EM> |
| </TD> |
| </TR> |
| |
| <TR> |
| <TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2"> |
| PREV |
| NEXT</FONT></TD> |
| <TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2"> |
| <A HREF="index.html?overview-summary.html" target="_top"><B>FRAMES</B></A> |
| <A HREF="overview-summary.html" target="_top"><B>NO FRAMES</B></A> |
| <SCRIPT type="text/javascript"> |
| <!-- |
| if(window==top) { |
| document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>'); |
| } |
| //--> |
| </SCRIPT> |
| <NOSCRIPT> |
| <A HREF="allclasses-noframe.html"><B>All Classes</B></A> |
| </NOSCRIPT> |
| |
| |
| </FONT></TD> |
| </TR> |
| </TABLE> |
| <A NAME="skip-navbar_top"></A> |
| <!-- ========= END OF TOP NAVBAR ========= --> |
| |
| <HR> |
| <CENTER> |
| <H1> |
| Schema2template |
| </H1> |
| </CENTER> |
| The schema2template project's objective is to provide an API for easily filling user templates from arbitrary XML schematas. |
| <P> |
| <B>See:</B> |
| <BR> |
| <A HREF="#overview_description"><B>Description</B></A> |
| <P> |
| |
| <TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY=""> |
| <TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> |
| <TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2"> |
| <B>Packages</B></FONT></TH> |
| </TR> |
| <TR BGCOLOR="white" CLASS="TableRowColor"> |
| <TD WIDTH="20%"><B><A HREF="schema2template/package-summary.html">schema2template</A></B></TD> |
| <TD>Classes to trigger the process of filling a template by a schema.</TD> |
| </TR> |
| <TR BGCOLOR="white" CLASS="TableRowColor"> |
| <TD WIDTH="20%"><B><A HREF="schema2template/example/odf/package-summary.html">schema2template.example.odf</A></B></TD> |
| <TD>Examples for the generation of source and reference for the OpenDocument XML format.</TD> |
| </TR> |
| <TR BGCOLOR="white" CLASS="TableRowColor"> |
| <TD WIDTH="20%"><B><A HREF="schema2template/model/package-summary.html">schema2template.model</A></B></TD> |
| <TD>Provide the XML model information parsed from a given XML schema.</TD> |
| </TR> |
| </TABLE> |
| |
| <P> |
| <A NAME="overview_description"><!-- --></A> |
| <P> |
| <p>The schema2template project's objective is to provide an API for easily filling user templates from arbitrary XML schematas.</p> |
| |
| <h2>Introduction</h2> |
| |
| <p>This project allows you to process a RelaxNG schema file and to convert the definitions to any text based format you like. E.g. |
| you can produce one source code file for each element defined in schema file. Or maybe you want to produce one single text or HTML |
| based overview of the schema.</p> |
| |
| <p>Since this project is based on the Sun Multi Schema Validator, it should be able to process multiple schema formats. However up to now it has only been |
| tested with RelaxNG.</p> |
| |
| <p>Several examples are delivered together with this project:</p> |
| <ol> |
| <li>Read the OpenDocument Schema and produce a Java based DOM API</li> |
| <li>Read the OpenDocument Schema and produce an HTML overview of all ODF elements and attributes</li> |
| <li>Read the OpenDocument Schema and produce one single Python file which represents the element hierarchy</li> |
| </ol> |
| |
| <p>A non-trivial topic is the concept of multiple definitions for a single element or attribute, which is possible in RelaxNG. |
| The easiest way would be to unite these definitions (we call them Multiples) to one common definition. However this way important information would be lost. |
| E.g. one element may have the attribute foo whith possible value <em>left</em>. This attribute may also be possible in another element, but then with |
| possible values <em>left</em> and <em>right</em>. That's why we decided to keep the distinction, even if it may make it harder to understand the API of this project. |
| We might enhance this concept in the future, e.g. to exactly determine which of the multiple definitions holds for the current element in an ODF element tree. |
| </p> |
| |
| <h2>Velocity Help</h2> |
| |
| Go to the "Engine" section of the the Velocity <a href="http://velocity.apache.org/">project site</a> to find the Velocity User Guide. |
| |
| The velocity template structure and commands are explained there. |
| |
| <h2>Schema2Template file structure</h2> |
| |
| <p>We use a 2-step procedure: First we generate a list of files we'd like to create. While we could write this list manually, the generation of this |
| list frees us from having to write an entry for each schema element or attribute. |
| |
| The template to generate this list is called output-files.vm, the list itself (i.e. the result of running output-files.vm) is called output-files.xml.</p> |
| |
| <p>Here's an example output-files.xml:</p> |
| |
| <pre> |
| <?xml version="1.0" encoding="UTF-8"?> |
| <filelist> |
| <file path="OdfHtmlSpecification.html" template="odf-reference-template.vm" /> |
| <file path="element/anim/AnimAnimateElement.java" |
| context="anim:animate" |
| template="java-odfdom-element-template.vm" /> |
| ... |
| </filelist> |
| </pre> |
| |
| <p>In the second step we parse output-files.xml. For every "file" entry we run the given Velocity "template", fill its context with the optional "context" |
| property and write the output to the given "path". |
| The "context" property (and as seen later - the optional "param" property as well) is used in templates which process only one element or attribute - |
| to provide them with the name of this element or attribute. |
| In the above example the template for the generation of a Java class is such a template, while the template to produce the whole |
| OdfHtmlSpecification.html is a template whith a global context, i.e. it processes the whole Schema.</p> |
| |
| <h2>Schema2Template specific template help</h2> |
| |
| <p>In velocity templates, you have context objects, provided by the Java Velocity Runner Class. These are Java objects and you can call any method |
| of these objects like you would do in Java. In Schema2Template we provide the following context objects (see JavaDoc of the given Classes):</p> |
| |
| <a name="contextObjects" /> |
| |
| <ul> |
| <li>SchemaModel model: Provides the elements and attributes defined in the schema.</li> |
| <li>OdfModel odfmodel: Provides additional information from the Odf Specification, like attribute standard values or element style families.</li> |
| <li>SourceCodeModel javamodel: Provides additional information for generation of Source Code, like common base classes for elements.</li> |
| <li>String context: The (optional) name of the current element. You can use model to get the element or attribute described by this name</li> |
| <li>String param: A freely usable (optional) argument. An example usage is to provide a number to distinguish between elements (or attributes) sharing the same name.</li> |
| </ul> |
| |
| <p>It should be noted that the context of output-files.vm behaves like the context of all templates which are started from there. Of course in the |
| context of output-files.vm the optional context Objects "context" and "param" are null.</p> |
| |
| <h3>PuzzlePiece Class</h3> |
| |
| <p>The PuzzlePiece class provides some sort of "piece of a puzzle", containing the definition of an Odf element, attribute, datatype or |
| constant attribute value. This class contains methods for quiering the relationship between definitions, e.g. to get all child elements, |
| attributes, parent elements, datatypes, values, etc... PuzzlePieces are |
| sorted by their name (which has the form "ns:localname").</p> |
| |
| <p>Some of these return parameters are collections. For these there is the class PuzzlePieceSet, which is a SortedSet of PuzzlePieces. PuzzlePiece |
| and PuzzlePieceSet both implement the interface QNamedPuzzleComponent, and therefore have many methods in common (you can query all child elements |
| for a PuzzlePiece as well as for a whole PuzzlePieceSet. And you can get the name for a PuzzlePiece as well as for a whole PuzzlePieceSet - provided all PuzzlePieces |
| are equally named, ...)</p> |
| |
| <p>Before we come to the point on how to use PuzzlePieces and how to get them, there's one more important thing to know: </p> |
| |
| <h3>Multiples and Multiple Number</h3> |
| |
| <p>One element (form:list-value) and many attributes (chart-symbol-type, text:outline-level, etc...) are defined multiple times in Odf Schema. |
| Each definition is represented by a PuzzlePiece object. Those PuzzlePieces sharing the same name are called Multiples. |
| Each Multiple may differ in parent elements, child elements and attributes. |
| From a PuzzlePiece you can get all PuzzlePieces sharing the same name as the PuzzlePiece |
| by its method withMultiples(). If there are no other PuzzlePieces you get at least a singleton PuzzlePieceSet containing only this PuzzlePiece.</p> |
| |
| <h3>How to get QNamedPuzzleComponent (PuzzlePiece and PuzzlePieceSets)</h3> |
| |
| <p>If you do not want to distinguish between elements (or attributes) sharing the same name you can use in templates processing only one element:<br /> |
| $model.getElement($context) or $model.getAttribute($context). By this you get a PuzzlePieceSet of PuzzlePieces sharing the same name. Since both |
| classes share most methods, you can go on with your template like you'd use one single PuzzlePiece.</p> |
| |
| <p>If you want to distinguish between elements (or attributes) sharing the same name you can use in templates processing only one element:<br /> |
| $model.getElement($context, $param) or $model.getAttribute($context, $param), provided that context contains the name of the PuzzlePiece and param |
| contains the multiple number to distinguish between these PuzzlePieces. In other words you have to fill both properties in output-files.vm with the needed values. |
| You get the name of a PuzzlePiece by ${aDefinition.getQName()} or directly by $aDefinition and the multiple number by ${aDefinition.getMultipleNumber()}.<br /> |
| <em>It should be noted that this is a very rare use case (e.g. if you want to produce one file per PuzzlePiece and not - as usual - per PuzzlePiece name).</em> |
| </p> |
| |
| <p>If you loop over a Set of PuzzlePieces, this Set will contain Multiples. If you want to distinguish between these elements/attributes, there's nothing special to do. |
| But if you do not want to distinguish between elements/attributes sharing the same name, you have two steps to do: <br /> |
| First, you have to create a new PuzzlePieceSet without |
| these Multiples by myPuzzlePiece.withoutMultiples(). Now you have a reduced Set of PuzzlePieces, where only one random PuzzlePiece per name remains. <br /> |
| If you'd process only the random remaining PuzzlePiece for a name, and you're processing more than just the PuzzlePiece name, you might miss some information |
| contained in the removed multiples. Even more, since you distinguish only between names, there might be some information contained in |
| Multiples which weren't even in the list before. (like an attribute Multiple |
| which wasn't in the $element.getAttributes() list as it's only defined for another element). So to get all |
| Multiples (not only those which were contained in the Set) of a PuzzlePiece, you use myPizzlePiece.withMultiples() for each |
| PuzzlePiece of the reduced PuzzlePieceSet your're looping over.</p> |
| |
| <h3>How to use QNamedPuzzleComponent (PuzzlePieces and PuzzlePieceSets)</h3> |
| |
| <p>Mostly you might want to use a PuzzlePiece by inserting it directly into the template, like "this element is called $element", or |
| like "the namespace of this element is ${element.getNamespace()}". It doesn't matter if $element is a PuzzlePiece as returned by model.getElement($context, $param), |
| or a PuzzlePieceSet of equally named PuzzlePieces as returned by model.getElement($context).</p> |
| |
| <p>The model provides a few additional functions for String formatting like model.camelCase($element) for text:p -> TextP or model.javaCase($element) |
| for text:p -> textP.</p> |
| |
| <p>Another usage of QNamedPuzzleComponents is to get other QNamedPuzzleComponents, e.g. by $element.getParents(), $attribute.getDatatypes(), $attribute.getValues(), |
| $element.getChildElements(), $element.getAttributes().</p> |
| |
| <p>To restrict a PuzzlePieceSet only to the PuzzlePieces which have a common parent, there is $elements.byParent($equallyNamedParents). With this method |
| you can implement very distinct validation method in attribute classes. See the byParent-example below.</p> |
| |
| <h3>How to read the Javadoc for Template Usage</h3> |
| |
| <p>Basically you could use every public method from the <a href="#contextObjects">context objects</a> in a Velocity template. But |
| this is not in our intention. There are quite a few public methods which are only to be used internally, e.g. to extract |
| our model from the Schema file.</p> |
| |
| <p>To see the list of template-ready methods, you might want to look at the TemplateAPICoverageTest and the |
| OdfTemplateAPICoverageTest from the source code bundle.</p> |
| |
| <p>To give an example you will see that the PuzzleComponent method "canHaveText" is meant for template usage. On the other hand |
| you wont find neither method compareTo nor extractPuzzlePieces from class PuzzlePiece there, so those methods are not |
| meant to be used in templates. Only the methods covered by the two mentioned tests are protected against internal |
| refactoring (especially against renaming).</p> |
| |
| <h3>Examples</h3> |
| |
| <h4>Here's an example template to generate a ODF reference of attribute / elements. Here the PuzzlePieces are distinguished:</h4> |
| <pre> |
| #foreach( $element in ${model.getElements()} ) |
| #if (${element.withMultiples().size()} == 1) |
| #set ($duptext = "") |
| #set ($hasdup = false) |
| #else |
| #set ($duptext = "[${element.getMultipleNumber()}]") |
| #set ($hasdup = true) |
| #end |
| <h3>${element}${duptext} Element</h3> |
| #if ( $hasdup ) |
| <p>There are more than one PuzzlePieces by this name.</p> |
| #end |
| #end |
| </pre> |
| |
| <h4>Here's an example output-files.vm which only produces one entry per name (processing just the element name so the Multiples can safely be removed):</h4> |
| |
| <pre> |
| <?xml version="1.0" encoding="UTF-8"?> |
| <filelist> |
| <file path="OdfHtmlSpecification.html" template="odf-reference-template.vm" /> |
| ## |
| #foreach ( $element in ${model.getElements().withoutMultiples()} ) |
| ## |
| #set($classname = "${model.camelCase($element)}Element" ) |
| <file path="element/${element.getNamespace()}/${classname}.java" |
| context="$element" |
| template="java-odfdom-element-template.vm" /> |
| ## |
| #end |
| </filelist> |
| </pre> |
| |
| <h4>Here's an example template to generate a Java class for an element name (by looking at all element Multiples at once).</h4> |
| |
| <p>To keep it short only the part where the Getter-Methods for all attribute names (by looking at all attribute multiples at once) are generated is shown:</p> |
| <pre> |
| ## This will return a PuzzlePieceSet containing all element PuzzlePieces with name $context |
| #set($element = ${model.getElement($context)}) |
| ... |
| ## |
| ## Step 1: Iterate over all attributes with one random attribute PuzzlePiece per attribute name |
| #foreach ( $singleattr in ${element.getAttributes().withoutMultiples()} ) |
| ## |
| ## Step 2: Get all attribute definitions for one attribute name. |
| ## Not needed if we're just processing the attribute name |
| #set($attribute = ${singleattr.withMultiples()} |
| ## |
| #set($aClassname = "${model.camelCase($attribute)}Attribute" ) |
| /** |
| * Gets the value of the <code>$aClassname</code> attribute, |
| * see {@odf.attribute ${attribute}} |
| * |
| * @return - the <code>String</code> attribute value |
| */ |
| public String get${aClassname}() { |
| ... |
| } |
| #end |
| ... |
| </pre> |
| |
| <h4>Example for the byParent method: Input value validation in attribute template</h4> |
| |
| <p>Implementation detail: one attribute and one parent class implemented per name - |
| thus ignoring PuzzlePiece multiples at Java class level. |
| However differences between attribute PuzzlePieces are respected by using a different validation:</p> |
| |
| <pre> |
| ## This will return a PuzzlePieceSet containing all attribute PuzzlePieces with name $context |
| #set($attribute = ${model.getAttribute($context)}) |
| ... |
| public void setValue(String value) { |
| boolean valid = false; |
| ## |
| ## Iterate over parent names and get all Multiples for each name |
| #foreach ($singleparent in ${attribute.getParents().withoutMultiples()}) |
| #set ($parent = $singleparent.withMultiples()) |
| if (getParent() instanceof ${model.camelCase($parent)}Element) { |
| ## |
| ## Allow only datatypes from attribute definitions reachable from $parent |
| ## Thus here we're respecting the different definitions for the current attribute |
| #foreach ($datatype in ${attribute.byParent($parent).getDatatypes()}) |
| valid = valid || validate(${datatype}.class, value); |
| #end |
| } |
| #end |
| if (!valid) { |
| throw new IllegalArgumentException( |
| "Invalid Value for attribute $attribute and parent " |
| + getParent().ELEMENT_NAME); |
| } |
| mValue = value; |
| } |
| </pre> |
| <P> |
| |
| <P> |
| <HR> |
| |
| |
| <!-- ======= START OF BOTTOM NAVBAR ====== --> |
| <A NAME="navbar_bottom"><!-- --></A> |
| <A HREF="#skip-navbar_bottom" title="Skip navigation links"></A> |
| <TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY=""> |
| <TR> |
| <TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> |
| <A NAME="navbar_bottom_firstrow"><!-- --></A> |
| <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY=""> |
| <TR ALIGN="center" VALIGN="top"> |
| <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Overview</B></FONT> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Use</FONT> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-files/index-1.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD> |
| <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD> |
| </TR> |
| </TABLE> |
| </TD> |
| <TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM> |
| </EM> |
| </TD> |
| </TR> |
| |
| <TR> |
| <TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2"> |
| PREV |
| NEXT</FONT></TD> |
| <TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2"> |
| <A HREF="index.html?overview-summary.html" target="_top"><B>FRAMES</B></A> |
| <A HREF="overview-summary.html" target="_top"><B>NO FRAMES</B></A> |
| <SCRIPT type="text/javascript"> |
| <!-- |
| if(window==top) { |
| document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>'); |
| } |
| //--> |
| </SCRIPT> |
| <NOSCRIPT> |
| <A HREF="allclasses-noframe.html"><B>All Classes</B></A> |
| </NOSCRIPT> |
| |
| |
| </FONT></TD> |
| </TR> |
| </TABLE> |
| <A NAME="skip-navbar_bottom"></A> |
| <!-- ======== END OF BOTTOM NAVBAR ======= --> |
| |
| <HR> |
| Copyright © 2010-2017 <a href="http://www.apache.org/">The Apache Software Foundation</a>. All Rights Reserved. |
| </BODY> |
| </HTML> |