View Javadoc
1   /*
2    * Copyright 2007 Werner Guttmann
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.castor.anttask;
17  
18  import java.io.File;
19  import java.io.FileWriter;
20  import java.io.IOException;
21  import java.util.Vector;
22  
23  import org.apache.tools.ant.BuildException;
24  import org.apache.tools.ant.DirectoryScanner;
25  import org.apache.tools.ant.taskdefs.MatchingTask;
26  import org.apache.tools.ant.types.FileSet;
27  import org.exolab.castor.xml.schema.Schema;
28  import org.exolab.castor.xml.schema.util.XMLInstance2Schema;
29  import org.xml.sax.SAXException;
30  
31  /**
32   * An <a href="http://ant.apache.org/">Ant</a> task to call the Castor {@link XMLInstance2Schema}
33   * tool. It can be passed a file, a directory, a Fileset or all three.
34   *
35   * @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
36   * @version $Revision: 6543 $ $Date: 2005-03-05 06:42:06 -0700 (Sat, 05 Mar 2005) $
37   */
38  public final class XMLInstance2SchemaTask extends MatchingTask {
39      //--------------------------------------------------------------------------
40  
41      /** 
42       * Error message -- no input provided. 
43       */
44      private static final String NO_XML_DOCUMENT_MSG =
45          "At least one XML document instance must be provided.";
46  
47      //--------------------------------------------------------------------------
48  
49      /** 
50      * Enlists the XML file to process. 
51       */
52      private File _xmlInstanceFile;
53      
54      /** 
55       * Enlists a directory, for which the user wants to process all XML instance files. 
56       **/
57      private File _xmlInstanceDir;
58      
59      /** 
60       * Enlists the fileset the user wants to process. 
61       */
62      private Vector _xmlInstanceFileSets = new Vector();
63  
64      // Begin application-specific parameters
65      
66      /** 
67       * Name of the XML schema file to which the output should be written. 
68       */
69      private String _xmlSchemaFileName;
70      
71      /**
72       * Default grouping to be <xsd:ALL/>.
73       */
74      private boolean _defaultGroupingAsAll;
75      
76      //--------------------------------------------------------------------------
77  
78      /**
79       * Sets the individual schema that will have code generated for it.
80       * 
81       * @param file One schema file.
82       */
83      public void setFile(final File file) {
84          _xmlInstanceFile = file;
85      }
86  
87      /**
88       * Sets the directory such that all schemas in this directory will have code
89       * generated for them.
90       * 
91       * @param dir The directory containing schemas to process.
92       */
93      public void setDir(final File dir) {
94          _xmlInstanceDir = dir;
95      }
96  
97      /**
98       * Adds a fileset to process that contains schemas to process.
99       * 
100      * @param set An individual file set containing schemas.
101      */
102     public void addFileset(final FileSet set) {
103         _xmlInstanceFileSets.addElement(set);
104     }
105 
106     /**
107      * Specifies the name of the DDL file to be generated.
108      * @param ddlFileName Name of the DDL file to be generated
109      */
110     public void setXmlSchemaFileName(final String ddlFileName) {
111         _xmlSchemaFileName = ddlFileName;
112     }
113     
114     /**
115      * Specifies the default grouping to be <xsd:all/>.
116      * @param defaultGroupingAsAll Default grouping to be used
117      */
118     public void setDefaultGrouping(final String defaultGroupingAsAll) {
119         _defaultGroupingAsAll = true;
120     }
121 
122     //--------------------------------------------------------------------------
123 
124     /**
125      * Configured the code generator. If anything goes wrong during configuration of the
126      * Ant task a BuildException will be thrown.
127      */
128     private void config() {
129     }
130 
131     /**
132      * Runs source generation. If anything goes wrong during source generation a
133      * BuildException will be thrown.
134      * 
135      * @param filePath an individual Schema to generate code for.
136      * @param outputFilePath Name of the output file to create.
137      */
138     private void processFile(final String filePath, final String outputFilePath) {
139         log("Processing " + filePath);
140         try {
141             XMLInstance2Schema schemaGenerator = new XMLInstance2Schema();
142             if (_defaultGroupingAsAll) {
143                 schemaGenerator.setDefaultGroupingAsAll();
144             }
145             Schema schema = schemaGenerator.createSchema(filePath);
146             String outputFileName = outputFilePath;
147             if (outputFileName == null) {
148                 outputFileName = deriveOutputFilePath(filePath);
149             }
150            FileWriter dstWriter = new FileWriter(outputFileName);
151             schemaGenerator.serializeSchema(dstWriter, schema);
152         } catch (IOException e) {
153             throw new BuildException ("Problem writing to the given putput sink " 
154                     + _xmlInstanceFile.getAbsolutePath(), e);
155         } catch (SAXException e) {
156             throw new BuildException ("Problem streaming the generated XML schema instance " 
157                     + "to the given file.", e); 
158         }
159     }
160 
161     /**
162      * Derives the XML schema file name from the XML instance document name.
163      * @param outputFileName Name of the XML instance document.
164      * @return The name of the XML schema instance.
165      */
166     private String deriveOutputFilePath(final String outputFileName) {
167         return outputFileName + ".xsd";
168     }
169 
170     /**
171      * Public execute method -- entry point for the Ant task.  Loops over all
172      * schema that need code generated and creates needed code generators, then
173      * executes them. If anything goes wrong during execution of the Ant task a
174      * BuildException will be thrown.
175      * 
176      * @see org.apache.tools.ant.Task#execute()
177      */
178     public void execute() {
179         // Must have something to run the source generator on
180         if (_xmlInstanceFile == null && _xmlInstanceDir == null 
181                 && _xmlInstanceFileSets.size() == 0) {
182             throw new BuildException(NO_XML_DOCUMENT_MSG);
183         }
184 
185         config();
186 
187         // process just the file specified
188         if (_xmlInstanceFile != null) {
189             processFile(_xmlInstanceFile.getAbsolutePath(), _xmlSchemaFileName);
190         }
191 
192         // process all files in the given directory
193         if (_xmlInstanceDir != null && _xmlInstanceDir.exists() && _xmlInstanceDir.isDirectory()) {
194             log("Given XML schema file name will be ignored.");
195             DirectoryScanner ds = this.getDirectoryScanner(_xmlInstanceDir);
196 
197             String[] files = ds.getIncludedFiles();
198             for (int i = 0; i < files.length; i++) {
199                 String filePath = _xmlInstanceDir.getAbsolutePath() + File.separator + files[i];
200                 processFile(filePath, null);
201             }
202         }
203 
204         // process all files of the given FileSet
205         for (int i = 0; i < _xmlInstanceFileSets.size(); i++) {
206             log("Given XML schema file name will be ignored.");
207             FileSet fs = (FileSet) _xmlInstanceFileSets.elementAt(i);
208             DirectoryScanner ds = fs.getDirectoryScanner(getProject());
209             File subdir = fs.getDir(getProject());
210 
211             String[] files = ds.getIncludedFiles();
212             for (int j = 0; j < files.length; j++) {
213                 String filePath = subdir.getAbsolutePath() + File.separator + files[j];
214                 processFile(filePath, null);
215             }
216         }
217     }
218 }