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 }