001 /* 002 @license.text@ 003 */ 004 package biz.hammurapi.sql.xml; 005 006 import java.io.ByteArrayInputStream; 007 import java.sql.ResultSet; 008 import java.sql.ResultSetMetaData; 009 import java.sql.SQLException; 010 011 import org.w3c.dom.DOMException; 012 import org.w3c.dom.Document; 013 import org.w3c.dom.Element; 014 import org.w3c.dom.Node; 015 016 import biz.hammurapi.CarryOverException; 017 import biz.hammurapi.config.ConfigurationException; 018 import biz.hammurapi.config.Context; 019 import biz.hammurapi.config.DomConfigFactory; 020 import biz.hammurapi.config.PropertyParser; 021 import biz.hammurapi.sql.MetadataAwareRowProcessor; 022 import biz.hammurapi.sql.SQLProcessor; 023 import biz.hammurapi.xml.dom.DOMUtils; 024 025 026 /** 027 * @author Pavel Vlasov 028 * @version $Revision: 1.2 $ 029 */ 030 public class Select extends SQLCommand implements Command { 031 032 // private String pageSize; 033 // private String pageNumParameter; 034 private CompositeCommand onRow; 035 private CompositeCommand onEmptySet; 036 037 public void configure(Node configNode, Context context) throws ConfigurationException { 038 super.configure(configNode, context); 039 try { 040 Node n=DOMUtils.selectSingleNode(configNode, "on-row"); 041 if (n!=null) { 042 onRow=new CompositeCommand(); 043 onRow.configure(n, context); 044 } 045 046 n=DOMUtils.selectSingleNode(configNode, "on-empty-result-set"); 047 if (n!=null) { 048 onEmptySet=new CompositeCommand(); 049 onEmptySet.configure(n, context); 050 } 051 } catch (Exception e) { 052 throw new ConfigurationException(e); 053 } 054 } 055 056 public void execute(final Element holder, SQLProcessor pProcessor, final Context context) throws SQL2XMLException { 057 final SQLProcessor processor = getProcessor()==null ? pProcessor : getProcessor(); 058 // TODO Paged processing 059 try { 060 if (parameterizer==null || parameterizer.setContext(context)) { 061 final Document ownerDocument = holder.getOwnerDocument(); 062 final Element resultSetElement=ownerDocument.createElement("result-set"); 063 holder.appendChild(resultSetElement); 064 if (name!=null) { 065 resultSetElement.setAttribute("name", name); 066 } 067 068 processor.processSelect( 069 sql, 070 parameterizer, 071 new MetadataAwareRowProcessor() { 072 public boolean process(final ResultSet rs) throws SQLException { 073 Element rowElement=ownerDocument.createElement("row"); 074 resultSetElement.appendChild(rowElement); 075 for (int i=1, j=rs.getMetaData().getColumnCount(); i<=j; i++) { 076 Element columnElement=ownerDocument.createElement("column"); 077 rowElement.appendChild(columnElement); 078 columnElement.setAttribute("name", rs.getMetaData().getColumnName(i)); 079 columnElement.setAttribute("type", rs.getMetaData().getColumnTypeName(i)); 080 switch (rs.getMetaData().isNullable(i)) { 081 case ResultSetMetaData.columnNoNulls: 082 columnElement.setAttribute("nullable", "no"); 083 break; 084 case ResultSetMetaData.columnNullable: 085 columnElement.setAttribute("nullable", "yes"); 086 break; 087 case ResultSetMetaData.columnNullableUnknown: 088 columnElement.setAttribute("nullable", "unknown"); 089 break; 090 } 091 String value = rs.getString(i); 092 if (value!=null) { 093 columnElement.appendChild(ownerDocument.createTextNode(value)); 094 } 095 096 } 097 098 try { 099 if (onRow!=null) { 100 onRow.execute( 101 rowElement, 102 processor, 103 new Context() { 104 public Object get(String name) { 105 //System.out.println("Context.get("+name+")"); 106 if (Select.this.name!=null && name.startsWith(Select.this.name+".")) { 107 name=name.substring(Select.this.name.length()+1); 108 return findColumn(name); 109 } else if (name.indexOf('.')!=-1) { 110 return context==null ? null : context.get(name); 111 } else { 112 Object ret=findColumn(name); 113 return ret==null ? context==null ? null : context.get(name) : ret; 114 } 115 } 116 117 /** 118 * @param rs 119 * @param name 120 * @return 121 */ 122 private Object findColumn(String name) { 123 try { 124 for (int i=1; i<=rs.getMetaData().getColumnCount(); i++) { 125 if (name.equals(rs.getMetaData().getColumnName(i))) { 126 return rs.getObject(i); 127 } 128 } 129 return null; 130 } catch (SQLException e) { 131 throw new CarryOverException(e); 132 } 133 } 134 135 }); 136 } 137 } catch (SQL2XMLException e) { 138 throw new CarryOverException(e); 139 } 140 141 return true; 142 } 143 144 public void processMetadata(ResultSetMetaData metadata) throws DOMException, SQLException { 145 Element metadataElement=ownerDocument.createElement("metadata"); 146 resultSetElement.appendChild(metadataElement); 147 for (int i=1; i<=metadata.getColumnCount(); i++) { 148 Element columnElement=ownerDocument.createElement("column"); 149 metadataElement.appendChild(columnElement); 150 columnElement.setAttribute("name", metadata.getColumnName(i)); 151 columnElement.setAttribute("type", metadata.getColumnTypeName(i)); 152 } 153 } 154 155 public void onEmptyResultSet() throws SQLException { 156 try { 157 if (onEmptySet!=null) { 158 onEmptySet.execute(holder, processor, context); 159 } 160 } catch (SQL2XMLException e) { 161 throw new CarryOverException(e); 162 } 163 } 164 }); 165 } 166 } catch (final SQLException e) { 167 throw new SQL2XMLException( 168 new PropertyParser( 169 new Context() { 170 public Object get(String name) { 171 if ("error.message".equals(name)) { 172 return e.getMessage(); 173 } else if ("error.class".equals(name)) { 174 return e.getClass().getName(); 175 } else { 176 return context.get(name); 177 } 178 } 179 }, false).parse(errorMessage), e); 180 } catch (final CarryOverException e) { 181 if (e.getCause() instanceof SQL2XMLException) { 182 throw (SQL2XMLException) e.getCause(); 183 } else { 184 throw new SQL2XMLException( 185 new PropertyParser( 186 new Context() { 187 public Object get(String name) { 188 if ("error.message".equals(name)) { 189 return e.getCause().getMessage(); 190 } else if ("error.class".equals(name)) { 191 return e.getCause().getClass().getName(); 192 } else { 193 return context.get(name); 194 } 195 } 196 }, false).parse(errorMessage), e.getCause()); 197 } 198 } 199 } 200 201 public static void main(String[] args) throws Exception { 202 DomConfigFactory factory=new DomConfigFactory(); 203 String xml = "<query type=\"biz.hammurapi.sql.xml.Select\">" + 204 "<sql>select * from people where last_name=?[lastName]?</sql>" + 205 "</query>"; 206 Command select= (Command) factory.create(new ByteArrayInputStream(xml.getBytes()), "/query"); 207 208 } 209 }