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