001 package org.apache.torque.task; 002 003 import java.io.File; 004 import java.io.FileWriter; 005 import java.io.IOException; 006 import java.io.StringWriter; 007 008 import javax.xml.parsers.DocumentBuilder; 009 import javax.xml.parsers.DocumentBuilderFactory; 010 import javax.xml.parsers.ParserConfigurationException; 011 import javax.xml.transform.OutputKeys; 012 import javax.xml.transform.Result; 013 import javax.xml.transform.Transformer; 014 import javax.xml.transform.TransformerFactory; 015 import javax.xml.transform.dom.DOMSource; 016 import javax.xml.transform.stream.StreamResult; 017 import javax.xml.xpath.XPath; 018 import javax.xml.xpath.XPathConstants; 019 import javax.xml.xpath.XPathFactory; 020 021 import org.apache.tools.ant.BuildException; 022 import org.apache.tools.ant.Task; 023 import org.w3c.dom.Document; 024 import org.w3c.dom.Element; 025 import org.w3c.dom.NodeList; 026 import org.xml.sax.SAXException; 027 028 /** 029 * This ant task will merge the schema-desc.xml with schema.xml, if 030 * schema-description.xml exists 031 * 032 * @author Kuali Rice Team (kuali-rice@googlegroups.com) 033 * 034 */ 035 public class TorqueMergeXMLDoc extends Task { 036 037 private static final String DESCRIPTION_ATTR = "description"; 038 private static final String JAVA_NAME_ATTR = "javaName"; 039 private static final String NAME_ATTR = "name"; 040 private static final String COLUMN_ELEMENT = "column"; 041 042 private File schemaWithDesc; 043 private File dbSchema; 044 private String schemaWithDescString; 045 private String dbSchemaString; 046 private Document schemaWithDescDoc; 047 private Document dbSchemaDoc; 048 049 050 public void setDbSchemaString(String dbSchemaString) { 051 this.dbSchemaString = dbSchemaString; 052 dbSchema = new File(dbSchemaString); 053 054 } 055 056 public void setSchemaWithDescString(String schemaWithDescString) { 057 this.schemaWithDescString = schemaWithDescString; 058 schemaWithDesc = new File(schemaWithDescString); 059 060 } 061 062 public File getDbSchema() { 063 return dbSchema; 064 } 065 066 public void setSchemaWithDesc(String schemaWithDescString) { 067 this.schemaWithDesc = new File(schemaWithDescString); 068 069 } 070 071 public void setDbSchema(String dbSchemaString) { 072 this.dbSchema = new File(dbSchemaString); 073 } 074 075 /** 076 * creates a document object from an input file 077 * 078 * @param file 079 * @return Document object 080 * @throws ParserConfigurationException 081 * @throws SAXException 082 * @throws IOException 083 */ 084 public static Document setDocument(File file) 085 throws ParserConfigurationException, SAXException, IOException { 086 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory 087 .newInstance(); 088 DocumentBuilder documentBuilder; 089 documentBuilder = documentBuilderFactory.newDocumentBuilder(); 090 Document XMLdocument = documentBuilder.parse(file); 091 XMLdocument.getDocumentElement().normalize(); 092 return XMLdocument; 093 } 094 095 /** 096 * performs the merge operation by taking two input files as input and then 097 * merges the file with description into the existing schema.xml file 098 * 099 * @param schemaWithDesc 100 * @param dbSchema 101 */ 102 public void mergeSchemas(File schemaWithDesc, File dbSchema) throws Exception { 103 104 schemaWithDescDoc = setDocument(schemaWithDesc); 105 dbSchemaDoc = setDocument(dbSchema); 106 dbSchemaDoc = createNewXML(dbSchemaDoc, schemaWithDescDoc); 107 108 } 109 110 /** 111 * merges the two xml document. The resulting document will be same as 112 * schema.xml except it will have a description attribute for all its tables 113 * and columns. 114 */ 115 public Document createNewXML(Document dbSchemaDoc, 116 Document schemaWithDescDoc) throws Exception { 117 118 XPath xpath = XPathFactory.newInstance().newXPath(); 119 120 NodeList listOfTablesInSchema = (NodeList)xpath.evaluate("/database/table", dbSchemaDoc, XPathConstants.NODESET); 121 122 for (int tableIndex = 0; tableIndex < listOfTablesInSchema.getLength(); tableIndex++) { 123 Element tableElementInSchema = (Element)listOfTablesInSchema.item(tableIndex); 124 String tableName = tableElementInSchema.getAttribute(NAME_ATTR); 125 // search the schema-description.xml file for a corresponding entry that contains the description 126 Element tableDescElem = (Element)xpath.evaluate("/database/table[@" + NAME_ATTR + "='" + tableName + "']", schemaWithDescDoc, XPathConstants.NODE); 127 if (tableDescElem != null) { 128 String tableDescription = tableDescElem.getAttribute(DESCRIPTION_ATTR); 129 String tableJavaName = tableDescElem.getAttribute(JAVA_NAME_ATTR); 130 tableElementInSchema.setAttribute(DESCRIPTION_ATTR, tableDescription); 131 tableElementInSchema.setAttribute(JAVA_NAME_ATTR, tableJavaName); 132 NodeList columnElements = tableElementInSchema.getElementsByTagName(COLUMN_ELEMENT); 133 for (int columnIndex = 0; columnIndex < columnElements.getLength(); columnIndex++) { 134 // look for the column in the schema description file 135 Element columnElementInSchema = (Element)columnElements.item(columnIndex); 136 String columnName = columnElementInSchema.getAttribute(NAME_ATTR); 137 Element columnDescElement = null; 138 NodeList columnDescElements = tableDescElem.getElementsByTagName(COLUMN_ELEMENT); 139 for (int columnDescIndex = 0; columnDescIndex < columnDescElements.getLength(); columnDescIndex++) { 140 Element element = (Element)columnDescElements.item(columnDescIndex); 141 if (columnName.equals(element.getAttribute(NAME_ATTR))) { 142 columnDescElement = element; 143 break; 144 } 145 } 146 if (columnDescElement != null) { 147 String columnDescription = columnDescElement.getAttribute(DESCRIPTION_ATTR); 148 String columnJavaName = columnDescElement.getAttribute(JAVA_NAME_ATTR); 149 columnElementInSchema.setAttribute(DESCRIPTION_ATTR, columnDescription); 150 columnElementInSchema.setAttribute(JAVA_NAME_ATTR, columnJavaName); 151 } 152 } 153 } 154 } 155 return dbSchemaDoc; 156 } 157 158 /** 159 * writes the document object to an output file 160 * 161 * @param newXMLDocument 162 * output xml document 163 */ 164 public void writeXMLToFile(Document newXMLDocument) throws Exception { 165 File dbSchema = this.getDbSchema(); 166 TransformerFactory tFactory = TransformerFactory.newInstance(); 167 168 Transformer transformer = tFactory.newTransformer(); 169 transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, 170 "database.dtd"); 171 DOMSource domSource = new DOMSource(newXMLDocument); 172 StringWriter writer = new StringWriter(); 173 Result result = new StreamResult(writer); 174 transformer.transform(domSource, result); 175 FileWriter fileWriter = new FileWriter(dbSchema); 176 177 if (dbSchema.exists()) { 178 StringBuffer bufferedWriter = new StringBuffer(writer 179 .toString()); 180 fileWriter.write(bufferedWriter.toString()); 181 fileWriter.close(); 182 System.out.println("The data has been written"); 183 } else { 184 System.out.println("This file is not exist"); 185 } 186 } 187 188 @Override 189 public void execute() throws BuildException { 190 setDbSchema(dbSchemaString); 191 setSchemaWithDesc(schemaWithDescString); 192 if (!schemaWithDesc.exists()) { 193 System.out.println("no schema file with description can be located"); 194 return; 195 } 196 try { 197 mergeSchemas(schemaWithDesc, dbSchema); 198 writeXMLToFile(dbSchemaDoc); 199 } catch (Exception e) { 200 throw new BuildException(e); 201 } 202 } 203 204 205 206 }