001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.cocoon.acting.modular;
019:
020: import java.sql.Connection;
021: import java.sql.PreparedStatement;
022: import java.sql.SQLException;
023: import java.util.Map;
024:
025: import org.apache.avalon.framework.configuration.Configuration;
026: import org.apache.avalon.framework.configuration.ConfigurationException;
027: import org.apache.avalon.framework.service.ServiceException;
028:
029: /**
030: * Updates a record in a database. The action can update one or more
031: * tables, and can update more than one row to a table at a time.
032: *
033: * @author <a href="mailto:haul@apache.org">Christian Haul</a>
034: * @version CVS $Id: DatabaseUpdateAction.java 433543 2006-08-22 06:22:54Z crossley $
035: */
036: public class DatabaseUpdateAction extends DatabaseAction {
037:
038: /**
039: * determine which mode to use as default mode
040: * here: UPDATE
041: * highly specific to operation INSERT / UPDATE / DELETE / SELECT
042: */
043: protected String selectMode(boolean isAutoIncrement, Map modes) {
044:
045: return (String) modes.get(MODE_OTHERS);
046: }
047:
048: /**
049: * determine whether autoincrement columns should be honoured by
050: * this operation. This is usually snsible only for INSERTs.
051: */
052: protected boolean honourAutoIncrement() {
053: return false;
054: }
055:
056: /**
057: * Fetch all values for all columns that are needed to do the
058: * database operation.
059: */
060: protected Object[][] getColumnValues(Configuration tableConf,
061: CacheHelper queryData, Map objectModel)
062: throws ConfigurationException, ServiceException {
063:
064: Object[][] columnValues = new Object[queryData.columns.length][];
065: for (int i = 0; i < queryData.columns.length; i++) {
066: columnValues[i] = this .getColumnValue(tableConf,
067: queryData.columns[i], objectModel);
068: }
069: return columnValues;
070: }
071:
072: /**
073: * Get the String representation of the PreparedStatement. This is
074: * mapped to the Configuration object itself, so if it doesn't exist,
075: * it will be created.
076: *
077: * @param table the table's configuration object
078: * @return the insert query as a string
079: */
080: protected CacheHelper getQuery(Configuration table, Map modeTypes,
081: Map defaultModeNames) throws ConfigurationException,
082: ServiceException {
083:
084: LookUpKey lookUpKey = new LookUpKey(table, modeTypes);
085: CacheHelper queryData = null;
086: synchronized (this .cachedQueryData) {
087: queryData = (CacheHelper) this .cachedQueryData
088: .get(lookUpKey);
089: if (queryData == null) {
090: Configuration[] keys = table.getChild("keys")
091: .getChildren("key");
092: Configuration[] values = table.getChild("values")
093: .getChildren("value");
094:
095: queryData = new CacheHelper(keys.length, keys.length
096: + values.length);
097: fillModes(keys, true, defaultModeNames, modeTypes,
098: queryData);
099: fillModes(values, false, defaultModeNames, modeTypes,
100: queryData);
101:
102: StringBuffer queryBuffer = new StringBuffer("UPDATE ");
103: queryBuffer.append(table.getAttribute("name"));
104:
105: if (values.length > 0) {
106: queryBuffer.append(" SET ");
107: int cols = 0;
108: for (int i = 0; i < queryData.columns.length; i++) {
109: if (!queryData.columns[i].isKey) {
110: if (cols > 0) {
111: queryBuffer.append(", ");
112: }
113: cols++;
114: queryBuffer.append(
115: queryData.columns[i].columnConf
116: .getAttribute("name"))
117: .append("= ?");
118: }
119: }
120: }
121:
122: queryBuffer.append(" WHERE ");
123: for (int i = 0; i < queryData.columns.length; i++) {
124: if (queryData.columns[i].isKey) {
125: if (i > 0) {
126: queryBuffer.append(" AND ");
127: }
128: queryBuffer.append(
129: queryData.columns[i].columnConf
130: .getAttribute("name")).append(
131: "= ?");
132: }
133: }
134:
135: queryData.queryString = queryBuffer.toString();
136:
137: this .cachedQueryData.put(lookUpKey, queryData);
138: }
139: }
140:
141: return queryData;
142: }
143:
144: /**
145: * set all necessary ?s and execute the query
146: */
147: protected int processRow(Map objectModel, Connection conn,
148: PreparedStatement statement, String outputMode,
149: Configuration table, CacheHelper queryData,
150: Object[][] columnValues, int rowIndex, Map results)
151: throws SQLException, ConfigurationException, Exception {
152:
153: int currentIndex = 1;
154:
155: // ordering is different for UPDATE than for INSERT: values, keys
156: for (int i = 0; i < queryData.columns.length; i++) {
157: Column col = queryData.columns[i];
158: if (!col.isKey) {
159: this .setColumn(objectModel, outputMode, results, table,
160: col.columnConf, rowIndex,
161: columnValues[i][(col.isSet ? rowIndex : 0)],
162: statement, currentIndex);
163: currentIndex++;
164: }
165: }
166: for (int i = 0; i < queryData.columns.length; i++) {
167: Column col = queryData.columns[i];
168: if (col.isKey) {
169: this .setColumn(objectModel, outputMode, results, table,
170: col.columnConf, rowIndex,
171: columnValues[i][(col.isSet ? rowIndex : 0)],
172: statement, currentIndex);
173: currentIndex++;
174: }
175: }
176: int rowCount = statement.executeUpdate();
177: return rowCount;
178: }
179:
180: }
|