001package org.apache.commons.digester3.examples.api.dbinsert; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020import java.sql.Connection; 021import java.util.Iterator; 022 023import org.apache.commons.digester3.Rule; 024import org.apache.commons.digester3.examples.api.dbinsert.Row.Column; 025 026/** 027 * See Main.java. 028 */ 029public class RowInserterRule 030 extends Rule 031{ 032 033 private Connection conn; 034 035 public RowInserterRule( Connection conn ) 036 { 037 this.conn = conn; 038 } 039 040 /** 041 * This method is invoked when the start tag for an xml element representing 042 * a database row is encountered. It pushes a new Row instance onto the 043 * digester stack (rather like an ObjectCreateRule) so that column data 044 * can be stored on it. 045 */ 046 @Override 047 public void begin( String namespace, String name, org.xml.sax.Attributes attrs ) 048 { 049 getDigester().push( new Row() ); 050 } 051 052 /** 053 * This method is invoked when the end tag for an xml element representing 054 * a database row is encountered. It pops a fully-configured Row instance 055 * off the digester stack, accesses the object below it on the stack (a 056 * Table object) to get the tablename, then does an SQL insert). Actually, 057 * here we just print out text rather than do the sql insert, but the 058 * real implementation should be fairly simple. 059 * <p> 060 * Note that after this rule completes, the row/column information is 061 * <i>discarded</i>, ie this rule performs actions <i>as the input is 062 * parsed</i>. This contrasts with the more usual way digester is used, 063 * which is to build trees of objects for later use. But it's a perfectly 064 * valid use of Digester. 065 */ 066 @Override 067 public void end( String namespace, String name ) 068 { 069 Row row = getDigester().pop(); 070 Table table = getDigester().peek(); 071 072 // Obviously, all this would be replaced by code like: 073 // stmt = conn.prepareStatement(); 074 // stmt.setString(n, value); 075 // 076 // Many improvements can then be implemented, such as using the 077 // PreparedStatement.getParameterMetaData method to retrieve 078 // retrieve parameter types, etc. 079 080 StringBuilder colnames = new StringBuilder(); 081 StringBuilder colvalues = new StringBuilder(); 082 083 for ( Iterator<Column> i = row.getColumns().iterator(); i.hasNext(); ) 084 { 085 Column column = i.next(); 086 087 if ( colnames.length() > 0 ) 088 { 089 colnames.append( ", " ); 090 colvalues.append( ", " ); 091 } 092 093 colnames.append( "'" ); 094 colnames.append( column.getName() ); 095 colnames.append( "'" ); 096 097 colvalues.append( "'" ); 098 colvalues.append( column.getValue() ); 099 colvalues.append( "'" ); 100 } 101 102 StringBuilder buf = new StringBuilder(); 103 buf.append( "insert into " ); 104 buf.append( table.getName() ); 105 buf.append( " (" ); 106 buf.append( colnames.toString() ); 107 buf.append( ") values (" ); 108 buf.append( colvalues.toString() ); 109 buf.append( ")" ); 110 111 // here the prepared statement would be executed.... 112 System.out.println( buf.toString() ); 113 } 114 115}