001 package com.mockrunner.jdbc; 002 003 import java.io.File; 004 import java.io.FileNotFoundException; 005 import java.util.Iterator; 006 import java.util.List; 007 008 import org.jdom.Document; 009 import org.jdom.Element; 010 import org.jdom.input.SAXBuilder; 011 012 import com.mockrunner.base.NestedApplicationException; 013 import com.mockrunner.mock.jdbc.MockResultSet; 014 import com.mockrunner.util.common.FileUtil; 015 016 /** 017 * Can be used to create a <code>ResultSet</code> based on 018 * a an XML <code>Document</code> of the proper format. You can specify 019 * the dialect, for proper parsing of the document. Furthermore you can 020 * specify the dialect of the <code>ResultSet</code>, which determines 021 * the expected format of the XML <code>Document</code> and whether or not 022 * the column entries should be trimmed (default is <code>true</code>). 023 * The file can be specified directly or by its name. The class 024 * tries to find the file in the absolut or relative path and 025 * (if not found) by calling <code>getResource</code>. Note that the 026 * file must exist in the local file system and cannot be loaded from 027 * inside a jar archive. 028 */ 029 public class XMLResultSetFactory implements ResultSetFactory 030 { 031 public final static int SYBASE_DIALECT = 0; 032 033 private File file = null; 034 private String fileName = null; 035 private boolean trim = true; 036 private int dialect = SYBASE_DIALECT; 037 038 public XMLResultSetFactory(String fileName) 039 { 040 this.file = new File(fileName); 041 this.fileName = fileName; 042 } 043 044 public XMLResultSetFactory(File file) 045 { 046 this.file = file; 047 this.fileName = file.getAbsolutePath(); 048 } 049 050 /** 051 * Makes and returns a MockResultSet created from 052 * an existing and valid XML <code>Document</code>. 053 * 054 * @return a new MockResultSet 055 */ 056 public MockResultSet create(String id) 057 { 058 MockResultSet resultSet; 059 060 switch (dialect) 061 { 062 case SYBASE_DIALECT: 063 resultSet = createSybaseResultSet(id); 064 break; 065 default: 066 resultSet = createSybaseResultSet(id); 067 break; 068 } 069 070 return resultSet; 071 } 072 073 /** 074 * Get the <code>File</code> being used to read in the 075 * <code>ResultSet</code>. Returns <code>null</code> if 076 * the file does not exist. 077 * @return the file 078 */ 079 public File getXMLFile() 080 { 081 if(file.exists() && file.isFile()) 082 { 083 return file; 084 } 085 else 086 { 087 try 088 { 089 file = FileUtil.findFile(file.getPath()); 090 return file; 091 } 092 catch(FileNotFoundException exc) 093 { 094 throw new RuntimeException("Could not find: " + file.getPath()); 095 } 096 } 097 } 098 099 /** 100 * Set if the column entries should be trimmed. 101 * Default is <code>true</code>. 102 * 103 * @param trim 104 */ 105 public void setTrim(boolean trim) 106 { 107 this.trim = trim; 108 } 109 110 /** 111 * Get whether or not trim is true or false. 112 */ 113 public boolean getTrim() 114 { 115 return trim; 116 } 117 118 /** 119 * Set the dialect of the XML <code>Document</code>. Can be 120 * different for different database systems. 121 * Will determine the expected XML format for 122 * the <code>ResultSet</code>. <code>SYBASE_DIALECT</code> 123 * is the <b>only</b> accepted dialect for now. 124 * @param dialect int specifying which createXXXResultSet 125 * method to call. 126 */ 127 public void setDialect(int dialect) 128 { 129 //this.dialect = dialect; 130 this.dialect = SYBASE_DIALECT; 131 } 132 133 /** 134 * Get the dialect of the XML <code>Document</code. 135 * 136 * @return dialect 137 */ 138 public int getDialect() 139 { 140 return dialect; 141 } 142 143 /** 144 * Return a MockResultSet with proper column names and 145 * rows based on the XML <code>Document</code>. 146 * @return MockResultSet Results read from XML 147 * <code>Document</code>. 148 */ 149 public MockResultSet createSybaseResultSet(String id) 150 { 151 MockResultSet resultSet = new MockResultSet(id); 152 SAXBuilder builder = new SAXBuilder(); 153 Document doc = null; 154 File fileToParse = getXMLFile(); 155 if(null == fileToParse) 156 { 157 throw new RuntimeException("File " + fileName + " not found."); 158 } 159 try 160 { 161 doc = builder.build(fileToParse); 162 Element root = doc.getRootElement(); 163 List rows = root.getChildren("row"); 164 Iterator ri = rows.iterator(); 165 boolean firstIteration = true; 166 int colNum = 0; 167 while (ri.hasNext()) 168 { 169 Element cRow = (Element)ri.next(); 170 List cRowChildren = cRow.getChildren(); 171 Iterator cri = cRowChildren.iterator(); 172 if (firstIteration) 173 { 174 List columns = cRowChildren; 175 Iterator ci = columns.iterator(); 176 177 while (ci.hasNext()) 178 { 179 Element ccRow = (Element)ci.next(); 180 resultSet.addColumn(ccRow.getName()); 181 colNum++; 182 } 183 firstIteration = false; 184 } 185 String[] cRowValues = new String[colNum]; 186 int curCol = 0; 187 while (cri.hasNext()) 188 { 189 Element crValue = (Element)cri.next(); 190 String value = trim ? crValue.getTextTrim() : crValue.getText(); 191 cRowValues[curCol] = value; 192 curCol++; 193 } 194 resultSet.addRow(cRowValues); 195 } 196 } 197 catch(Exception exc) 198 { 199 throw new NestedApplicationException("Failure while reading from XML file", exc); 200 } 201 return resultSet; 202 } 203 }