View Javadoc

1   /***
2    * 
3    */
4   package ar.com.epere4.java2excel.parser;
5   
6   import java.io.IOException;
7   import java.io.InputStream;
8   
9   import net.socialchange.doctype.Doctype;
10  import net.socialchange.doctype.DoctypeChangerStream;
11  import net.socialchange.doctype.DoctypeGenerator;
12  import net.socialchange.doctype.DoctypeImpl;
13  
14  import org.apache.commons.digester.Digester;
15  import org.xml.sax.SAXException;
16  
17  import ar.com.epere4.java2excel.parser.impl.BodyDtdImpl;
18  import ar.com.epere4.java2excel.parser.impl.HeaderDtdImpl;
19  import ar.com.epere4.java2excel.parser.impl.Java2ExcelDtdImpl;
20  import ar.com.epere4.java2excel.parser.impl.PropertyDtdImpl;
21  
22  /***
23   * @author epere4
24   */
25  public class Parser {
26      /***
27       * This is the public id of java2excel DTD.
28       * 
29       * @see Doctype#getPublicId()
30       */
31      public static final String JAVA2EXCEL_PUBLIC_ID = 
32          "-//epere4/DTD Java2Excel mapping file//EN";
33  
34      /***
35       * This is the system id of java2excel DTD.
36       * 
37       * @see Doctype#getSystemId()
38       */
39      public static final String JAVA2EXCEL_SYSTEM_ID = 
40          "http://java2excel.sourceforge.net/dtd/java2excel-mapping.dtd";
41  
42      /***
43       * The root element in the dtd, that needs to be the root element in the
44       * xml.
45       * 
46       * @see Doctype#getRootElement()
47       */
48      public static final String JAVA2EXCEL_ROOT_ELEMENT = "java2excel";
49  
50      /***
51       * The url that identifies the local dtd location.
52       */
53      public static final String JAVA2EXCEL_LOCAL_DTD_URL = Parser.class
54              .getResource("/ar/com/epere4/java2excel/dtd/java2excel-mapping.dtd")
55              .toString();
56  
57      /***
58       * Default Constructor.
59       */
60      protected Parser() {
61      }
62  
63      /***
64       * This parses the xml input and returns an instance of
65       * {@link Java2ExcelDtd} ready to be processed.
66       * 
67       * @param input
68       *            the xml. Must validate against
69       *            {@link #JAVA2EXCEL_LOCAL_DTD_URL}.
70       * @return an instance of {@link Java2ExcelDtd} ready to be processed
71       * @throws IOException
72       *             if in input/output error comes up.
73       * @throws SAXException
74       *             if the is a problem with the xml format.
75       * @since 17/02/2006
76       */
77      public final Java2ExcelDtd parse(final InputStream input)
78              throws IOException, SAXException {
79          final Digester digester = new Digester();
80          digester.register(JAVA2EXCEL_PUBLIC_ID, JAVA2EXCEL_LOCAL_DTD_URL);
81          digester.setValidating(true);
82          digester.push(new Java2ExcelDtdImpl());
83          addRules(digester);
84  
85          return (Java2ExcelDtd) digester.parse(replaceDoctype(input));
86      }
87  
88      /***
89       * Replaces the old doctype for a new one, so we enforce the xml validation
90       * with the official dtd.
91       * 
92       * @param inputXml
93       *            the input stream that has the xml.
94       * @return the changed input stream that must be passed to the
95       *         {@link Digester}.
96       * @since 17/02/2006
97       */
98      private InputStream replaceDoctype(final InputStream inputXml) {
99          DoctypeChangerStream changer = new DoctypeChangerStream(inputXml);
100         changer.setGenerator(new DoctypeGenerator() {
101             public Doctype generate(final Doctype old) {
102                 return new DoctypeImpl(JAVA2EXCEL_ROOT_ELEMENT,
103                         JAVA2EXCEL_PUBLIC_ID, JAVA2EXCEL_SYSTEM_ID, null);
104             }
105         });
106         return changer;
107     }
108 
109     /***
110      * This method adds the necessary rules to the digester so it can read and
111      * interprete the xml config file.
112      * 
113      * @param d
114      *            the digester
115      * @since 17/02/2006
116      */
117     private static void addRules(final Digester d) {
118         // --------------------------------------------------
119         // when we encounter a "header" tag, do the following:
120 
121         // create a new instance of class HeaderDtdImpl, and push that
122         // object onto the digester stack of objects
123         d.addObjectCreate("java2excel/header", HeaderDtdImpl.class);
124 
125         // map *any* attributes on the tag to appropriate
126         // setter-methods on the top object on the stack (the HeaderDtdImpl
127         // instance created by the preceeding rule).
128         //
129         // For example:
130         // if attribute "id" exists on the xml tag, and method setId
131         // with one parameter exists on the object that is on top of
132         // the digester object stack, then a call will be made to that
133         // method. The value will be type-converted from string to
134         // whatever type the target method declares (where possible),
135         // using the commons ConvertUtils functionality.
136         //
137         // Attributes on the xml tag for which no setter methods exist
138         // on the top object on the stack are just ignored.
139         d.addSetProperties("java2excel/header");
140 
141         // call the setHeader method on the second-to-top object on
142         // the stack (the Java2ExcelDtdImpl object), passing the top object
143         // on the stack (the recently created HeaderDtdImpl object).
144         d.addSetNext("java2excel/header", "setHeader");
145 
146         d.addObjectCreate("java2excel/body", BodyDtdImpl.class);
147         d.addSetProperties("java2excel/body");
148         d.addSetProperties("java2excel/body/properties");
149         d.addSetNext("java2excel/body", "setBody");
150 
151         d.addObjectCreate("java2excel/body/properties/property",
152                 PropertyDtdImpl.class);
153         d.addSetProperties("java2excel/body/properties/property");
154         d.addSetNext("java2excel/body/properties/property", "addProperty");
155         d.addSetNestedProperties("java2excel/body/properties/property");
156 
157     }
158 }