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 }