001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: /*
051: * MetaInfoGenerator.java
052: *
053: * Created on April 25, 2002, 6:11 PM
054: */
055:
056: package org.jaffa.tools.domainmeta.uniface;
057:
058: import java.util.*;
059: import java.io.*;
060: import javax.xml.parsers.DocumentBuilderFactory;
061: import javax.xml.parsers.DocumentBuilder;
062: import org.w3c.dom.Document;
063: import org.w3c.dom.NamedNodeMap;
064: import org.w3c.dom.NodeList;
065: import org.w3c.dom.Node;
066: import java.sql.*;
067: import org.jaffa.datatypes.Parser;
068: import org.jaffa.patterns.library.domain_creator_1_1.domain.Root;
069: import org.jaffa.tools.patternmetaengine.DomainObjectHelper;
070: import org.jaffa.util.URLHelper;
071: import org.jaffa.util.DefaultEntityResolver;
072: import org.jaffa.util.DefaultErrorHandler;
073: import org.jaffa.util.XmlHelper;
074:
075: import javax.xml.parsers.ParserConfigurationException;
076: import org.xml.sax.SAXException;
077:
078: /**
079: * Use this class to generate the meta files for the domain objects.
080: * These meta files are then used by the Code Generator to generate the required classes and mapping files.
081: * @author GautamJ
082: */
083: public class MetaInfoGenerator {
084:
085: /**
086: * This will parse the input file generating meta files for each object specified in the tableinfo file.
087: * For each table object, the Uniface schema will be used for getting all the meta information.
088: *
089: * XML format for the input file is:
090: * <?xml version="1.0"?>
091: * <Root>
092: * <TableInfoFile file="C:\\PatternGenerator\\domain\\meta\\TableInfo.xml"/>
093: * <RelationshipInfoFile file="C:\\PatternGenerator\\domain\\meta\\RelationshipInfo.xml"/>
094: * <OutputDir dir="C:\\PatternGenerator\\domain\\xml"/>
095: * <Database driver="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@server1.example.org:1521:somesid"
096: * user="scott" password="tiger"/>
097: * <MappingPackage name="mapping"/>
098: * <PatternTemplate name="patterns/portlet/PatternTemplate/ObjectCreatorPattern.xml"/>
099: * </Root>
100: *
101: * @param input the input file.
102: * @throws ParserConfigurationException if the xml parsing fails.
103: * @throws SAXException if ?the xml parsing fails.
104: * @throws IOException if the xml parsing fails.
105: * @throws SQLException in case any database error occurs.
106: * @throws ClassNotFoundException in case the database driver class is not found.
107: */
108: public static void generate(String input)
109: throws ParserConfigurationException, SAXException,
110: IOException, SQLException, ClassNotFoundException {
111: Connection connection = null;
112: InputStream stream = null;
113: try {
114: // Create a factory object for creating DOM parsers
115: DocumentBuilderFactory factory = DocumentBuilderFactory
116: .newInstance();
117:
118: // Specifies that the parser produced by this factory will validate documents as they are parsed.
119: factory.setValidating(true);
120:
121: // Now use the factory to create a DOM parser
122: DocumentBuilder parser = factory.newDocumentBuilder();
123:
124: // Specifies the EntityResolver to resolve DTD used in XML documents
125: parser.setEntityResolver(new DefaultEntityResolver());
126:
127: // Specifies the ErrorHandler to handle warning/error/fatalError conditions
128: parser.setErrorHandler(new DefaultErrorHandler());
129:
130: // Parse the file and build a Document tree to represent its content
131: stream = URLHelper.getInputStream(input);
132: if (stream == null)
133: throw new IOException("File not found: " + input);
134: Document document = parser.parse(stream);
135: String tableInfoFileName = document.getElementsByTagName(
136: "TableInfoFile").item(0).getAttributes()
137: .getNamedItem("file").getNodeValue();
138: String relationshipInfoFileName = document
139: .getElementsByTagName("RelationshipInfoFile").item(
140: 0).getAttributes().getNamedItem("file")
141: .getNodeValue();
142: String outputDirName = document.getElementsByTagName(
143: "OutputDir").item(0).getAttributes().getNamedItem(
144: "dir").getNodeValue();
145: NamedNodeMap database = document.getElementsByTagName(
146: "Database").item(0).getAttributes();
147: String driver = database.getNamedItem("driver")
148: .getNodeValue();
149: String url = database.getNamedItem("url").getNodeValue();
150: String user = database.getNamedItem("user").getNodeValue();
151: String password = database.getNamedItem("password")
152: .getNodeValue();
153: String mappingPackage = document.getElementsByTagName(
154: "MappingPackage").item(0).getAttributes()
155: .getNamedItem("name").getNodeValue();
156: String patternTemplate = document.getElementsByTagName(
157: "PatternTemplate").item(0).getAttributes()
158: .getNamedItem("name").getNodeValue();
159: String dtd = document.getElementsByTagName("Dtd").item(0)
160: .getAttributes().getNamedItem("name")
161: .getNodeValue();
162: boolean ignoreNewFields = document.getElementsByTagName(
163: "IgnoreNewFields").getLength() == 1;
164: boolean doNotOverwriteExistingRelationships = document
165: .getElementsByTagName(
166: "DoNotOverwriteExistingRelationships")
167: .getLength() == 1;
168:
169: Class.forName(driver);
170: connection = java.sql.DriverManager.getConnection(url,
171: user, password);
172:
173: TableInfoReader.TableInfo tableInfo = TableInfoReader
174: .parse(tableInfoFileName);
175: List tables = tableInfo.getTables();
176: List relationshipInfo = relationshipInfoFileName == null ? null
177: : RelationshipInfoReader
178: .parse(relationshipInfoFileName);
179:
180: // invoke the UnifaceSchemaReader.parse() for each table in the TableInfofile
181: for (Iterator i = tables.iterator(); i.hasNext();) {
182: boolean doNotOverwriteExistingRelationshipsLocal;
183: TableInfoReader.Table table = (TableInfoReader.Table) i
184: .next();
185:
186: File file = new File(outputDirName, table
187: .getDomainObject()
188: + ".xml");
189:
190: String override = table.getRegenerate();
191: Root existingDomainObject = null;
192: if (file.exists()) {
193: override = override.toLowerCase();
194: if (override.equals("ask"))
195: override = askUser(file.getAbsolutePath());
196:
197: if (override.equals("merge")) {
198: DomainObjectHelper domainObjectHelper = new DomainObjectHelper();
199: domainObjectHelper.loadObjects(file, false);
200: existingDomainObject = domainObjectHelper
201: .getByDomain(table.getDomainObject());
202: } else if (!Parser.parseBoolean(override)
203: .booleanValue()) {
204: // do not regenerate if regenerate is disabled
205: continue;
206: }
207: doNotOverwriteExistingRelationshipsLocal = doNotOverwriteExistingRelationships;
208: } else
209: doNotOverwriteExistingRelationshipsLocal = false;
210:
211: Writer writer = new FileWriter(file);
212:
213: UnifaceSchemaReader.parse(table, mappingPackage,
214: patternTemplate, dtd, tableInfo,
215: relationshipInfo, writer, connection,
216: existingDomainObject, ignoreNewFields,
217: doNotOverwriteExistingRelationshipsLocal);
218:
219: writer.flush();
220: writer.close();
221: }
222:
223: document = null;
224: } finally {
225: if (stream != null)
226: stream.close();
227:
228: if (connection != null)
229: connection.close();
230: }
231: }
232:
233: private static String askUser(String fileName) throws IOException {
234: System.out.println("File '" + fileName + "' already exists..");
235: System.out
236: .println("1 - Leave It Alone / 2 - Overwrite / 3 - Merge ???");
237: System.out.flush();
238:
239: String s;
240: BufferedReader in = new BufferedReader(new InputStreamReader(
241: System.in));
242: while (true) {
243: s = in.readLine();
244: if (s.equals("1")) {
245: s = "false";
246: break;
247: } else if (s.equals("2")) {
248: s = "true";
249: break;
250: } else if (s.equals("3")) {
251: s = "merge";
252: break;
253: } else {
254: System.out.println("Enter either 1, 2 or 3 !!!");
255: }
256: }
257: return s;
258: }
259:
260: /** This will invoke the 'generate()' method, passing the input argument.
261: * @param args This expects one argument to be passed in. This argument will be the DomainMetaInfoGenerator.xml file, relative to the classpath.
262: */
263: public static void main(String args[]) {
264: try {
265: if (args.length != 1)
266: usage();
267: generate(args[0]);
268: } catch (Exception e) {
269: e.printStackTrace();
270: System.exit(1);
271: }
272: }
273:
274: private static void usage() {
275: System.err
276: .println("Usage: MetaInfoGenerator <DomainMetaInfoGenerator.xml file relative to ClassPath>");
277: System.exit(1);
278: }
279: }
|