001: /*
002: * $Header: /export/home/cvsroot/MyPersonalizerRepository/MyPersonalizer/Subsystems/Kernel/Sources/es/udc/mypersonalizer/kernel/model/repository/sql/storers/RemoveMetaPropertyVisitor.java,v 1.1.1.1 2004/03/25 12:08:36 fbellas Exp $
003: * $Revision: 1.1.1.1 $
004: * $Date: 2004/03/25 12:08:36 $
005: *
006: * =============================================================================
007: *
008: * Copyright (c) 2003, The MyPersonalizer Development Group
009: * (http://www.tic.udc.es/~fbellas/mypersonalizer/index.html) at
010: * University Of A Coruna
011: * All rights reserved.
012: *
013: * Redistribution and use in source and binary forms, with or without
014: * modification, are permitted provided that the following conditions are met:
015: *
016: * - Redistributions of source code must retain the above copyright notice,
017: * this list of conditions and the following disclaimer.
018: *
019: * - Redistributions in binary form must reproduce the above copyright notice,
020: * this list of conditions and the following disclaimer in the documentation
021: * and/or other materials provided with the distribution.
022: *
023: * - Neither the name of the University Of A Coruna nor the names of its
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
028: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
029: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
030: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
031: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
032: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
033: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
034: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
035: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
036: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
037: * POSSIBILITY OF SUCH DAMAGE.
038: *
039: */
040:
041: package es.udc.mypersonalizer.kernel.model.repository.sql.storers;
042:
043: import java.sql.PreparedStatement;
044: import java.sql.ResultSet;
045: import java.sql.Connection;
046: import java.sql.SQLException;
047: import java.util.ArrayList;
048: import java.util.Collection;
049: import java.util.Map;
050: import java.util.HashMap;
051: import java.util.Iterator;
052:
053: import es.udc.mypersonalizer.kernel.log.Log;
054: import es.udc.mypersonalizer.kernel.log.LogManager;
055: import es.udc.mypersonalizer.kernel.log.LogNamingConventions;
056: import es.udc.mypersonalizer.kernel.util.exceptions.VisitorException;
057: import es.udc.mypersonalizer.kernel.model.metainfo.MetaProperty;
058: import es.udc.mypersonalizer.kernel.model.metainfo.MetaSimpleProperty;
059: import es.udc.mypersonalizer.kernel.model.metainfo.MetaCompoundProperty;
060: import es.udc.mypersonalizer.kernel.model.repository.sql.config.DatabaseConventionsConfig;
061: import es.udc.mypersonalizer.kernel.model.repository.sql.config.DatabaseConventionsConfigManager;
062:
063: /**
064: * This class is a concrete Visitor in the "Visitor" pattern.
065: * It defines a way to <b>remove</b> a <code>Property</code>
066: * from a database by means of a object to relational mapping.
067: * The property is identified in the database by the key.
068: * <p>
069: * It is responsability of the "Visitor" implementations to
070: * make the traverse through the hierarchical structure.
071: *
072: * @author Abel Muinho
073: * @author Fernando Bellas
074: * @since 1.0
075: */
076:
077: public class RemoveMetaPropertyVisitor extends
078: AbstractSQLMetaPropertyVisitor {
079:
080: private static final String PROPERTY_IDENTIFIER_COLUMN_NAME;
081: private static final String GENERATED_IDENTIFIER_COLUMN_NAME;
082:
083: static {
084: String propertyIdentifierColumnName = null;
085: String generatedIdentifierColumnName = null;
086: try {
087: DatabaseConventionsConfig config = DatabaseConventionsConfigManager
088: .getConfig();
089: propertyIdentifierColumnName = config
090: .getPropertyIdentifierColumn();
091: generatedIdentifierColumnName = config
092: .getGeneratedIdentifierColumn();
093: } catch (Exception e) {
094: Log mypersonalizerLog = LogManager
095: .getLog(LogNamingConventions.MYPERSONALIZER);
096: mypersonalizerLog.write(
097: "Could not initialize configuration for "
098: + "RemoveMetaPropertyVisitor", e,
099: RemoveMetaPropertyVisitor.class);
100: }
101: PROPERTY_IDENTIFIER_COLUMN_NAME = propertyIdentifierColumnName;
102: GENERATED_IDENTIFIER_COLUMN_NAME = generatedIdentifierColumnName;
103: }
104:
105: /**
106: * The debug mode. This code should be commented out for the final
107: * release !
108: */
109: private boolean debugMode = true;
110:
111: /**
112: * Creates an instance of this class.
113: *
114: * @param connection a connection to the database
115: * @param key the map that contains pairs of key fields and their
116: * corresponding values.
117: */
118: public RemoveMetaPropertyVisitor(Connection connection, Map key) {
119:
120: super (connection, key);
121: }
122:
123: /**
124: * Visit operation for a <code>MetaSimpleProperty</code>.
125: *
126: * @param metaProperty the <code>MetaSimpleProperty</code>
127: * object over which the visitor can operate.
128: *
129: * @return an <code>Object</code> of needful for the caller.
130: * In this case it's <code>null</code>
131: * @throws VisitorException if an internal error occurs while
132: * processing the visited object
133: */
134: public Object visitMetaSimpleProperty(
135: MetaSimpleProperty metaProperty) throws VisitorException {
136:
137: /* If multi-valued ... */
138: if (metaProperty.isMultiValued()) {
139: removeCurrentRows(metaProperty);
140: }
141: return null;
142: }
143:
144: /**
145: * Visit operation for a <code>MetaCompoundProperty</code>.
146: *
147: * @param metaProperty the <code>MetaCompoundProperty</code>
148: * object over which the visitor can operate.
149: *
150: * @return an <code>Object</code> of needful for the caller.
151: * In this case it's <code>null</code>
152: * @throws VisitorException if an internal error occurs while
153: * processing the visited object
154: */
155: public Object visitMetaCompoundProperty(
156: MetaCompoundProperty metaProperty) throws VisitorException {
157:
158: /* If multi-valued */
159: if (metaProperty.isMultiValued()) {
160: Collection keysForValues = getAllPropertyValuesKeys(metaProperty);
161: Iterator keysValuesIterator = keysForValues.iterator();
162:
163: /* Iterate over the returned rows */
164: while (keysValuesIterator.hasNext()) {
165: Map newKey = new HashMap(1);
166: newKey.put(PROPERTY_IDENTIFIER_COLUMN_NAME,
167: (String) keysValuesIterator.next());
168:
169: visitComponents(metaProperty, newKey);
170: removeCurrentRows(metaProperty);
171: }
172: } else { // Otherwise, if we are single-valued...
173: visitComponents(metaProperty, getKey());
174: removeCurrentRows(metaProperty);
175: }
176: return null;
177: }
178:
179: /**
180: * Iterates over the components of the current
181: * <code>MetaCompoundProperty</code> visiting them with the given
182: * key.
183: * @param metaProperty The <code>CompoundMetaProperty</code> which
184: * components will be iterated over.
185: * @param newKey Key to be used when visiting the components.
186: * @throws VisitorException if a problem is detected during the visits.
187: */
188: protected void visitComponents(MetaCompoundProperty metaProperty,
189: Map newKey) throws VisitorException {
190: /*
191: * Get an iterator for the meta-properties of this
192: * compound-meta-property
193: */
194: Iterator componentIterator = metaProperty.getMetaProperties();
195:
196: /* Iterate over them */
197: while (componentIterator.hasNext()) {
198: MetaProperty aMetaProperty = (MetaProperty) componentIterator
199: .next();
200:
201: /*
202: * And go throught the tree removing all rows related
203: * to the one currently processed.
204: */
205: aMetaProperty.accept(new RemoveMetaPropertyVisitor(
206: getConnection(), newKey));
207: }
208: }
209:
210: /**
211: * Removes the rows for the currently being visited property.
212: * @param metaProperty Metainformation of the current property.
213: * @throws VisitorException if a problem occurs while deleting the row.
214: */
215: protected void removeCurrentRows(MetaProperty metaProperty)
216: throws VisitorException {
217:
218: /* Finally, remove the rows retrieved */
219: String query = "DELETE FROM " + getTableName(metaProperty)
220: + " WHERE " + allAndKeys();
221: try {
222: PreparedStatement statement = createStatement(query);
223: fillKeyValues(statement, 1);
224: debug("query: " + query);
225: statement.executeUpdate();
226: closeStatement(statement);
227: } catch (SQLException e) {
228: throw new VisitorException(
229: "ERROR: can't use PreparedStatement "
230: + "for MetaProperty '"
231: + metaProperty.getSimpleName()
232: + "' with query = '" + query + "' : "
233: + e.getMessage(), e);
234: }
235: }
236:
237: /**
238: * Returns a collection with all the values for the keys used to index
239: * each of the values of the current multivalued property.
240: * @param metaProperty Metainformation describing the current property.
241: * @return A collection of the key values for each of the property values.
242: * @throws VisitorException if the key values could not be accessed.
243: */
244: protected Collection getAllPropertyValuesKeys(
245: MetaCompoundProperty metaProperty) throws VisitorException {
246:
247: /* Get all rows belonging to the current property id */
248: String query = "SELECT " + GENERATED_IDENTIFIER_COLUMN_NAME
249: + " FROM " + getTableName(metaProperty) + " WHERE "
250: + allAndKeys();
251:
252: debug("query: " + query);
253: try {
254: PreparedStatement statement = getConnection()
255: .prepareStatement(query);
256: fillKeyValues(statement, 1);
257: ResultSet rs = statement.executeQuery();
258: ArrayList keysValues = new ArrayList();
259:
260: while (rs.next()) {
261: int keyValue = rs
262: .getInt(GENERATED_IDENTIFIER_COLUMN_NAME);
263: keysValues.add(String.valueOf(keyValue));
264: }
265: return keysValues;
266:
267: } catch (SQLException e) {
268: throw new VisitorException(
269: "ERROR: Accessing multivalued compound property"
270: + " keys for values: " + e.getMessage(), e);
271: }
272: }
273:
274: /**
275: * Echoes a message to the MyPersonalizer log if debugMode is enabled.
276: *
277: * @param message the message to be displayed.
278: */
279: private void debug(String message) {
280:
281: if (debugMode) {
282: Log mypersonalizerLog = LogManager
283: .getLog(LogNamingConventions.MYPERSONALIZER);
284: mypersonalizerLog.write(message, null,
285: RemoveMetaPropertyVisitor.class);
286: }
287:
288: }
289:
290: }
|