Line | Hits | Source |
---|---|---|
1 | /* | |
2 | * Copyright (C) 2006 TopCoder Inc., All Rights Reserved. | |
3 | */ | |
4 | package com.topcoder.document.index.persistence.impl.db; | |
5 | ||
6 | import com.topcoder.db.connectionfactory.DBConnectionFactory; | |
7 | import com.topcoder.document.index.CollectionIndex; | |
8 | import com.topcoder.document.index.DocumentIndex; | |
9 | import com.topcoder.document.index.persistence.IndexPersistenceException; | |
10 | import com.topcoder.document.index.persistence.impl.PersistenceConfigurationException; | |
11 | import com.topcoder.document.index.persistence.impl.Utils; | |
12 | import com.topcoder.document.index.wordsource.WordSourceId; | |
13 | ||
14 | import java.sql.Connection; | |
15 | import java.text.CollationKey; | |
16 | import java.text.Collator; | |
17 | import java.util.HashMap; | |
18 | import java.util.Iterator; | |
19 | import java.util.List; | |
20 | import java.util.Locale; | |
21 | import java.util.Map; | |
22 | import java.util.Set; | |
23 | ||
24 | ||
25 | /** | |
26 | * This is an implementation of the AbstractDBIndexPersistence that deals with a simple and straightforward, normalized | |
27 | * data based schema. This is provided for a user who is not as concerned about speed of the execution but is more | |
28 | * concerned about simple data mining capabilities for 3rd party API. Since all the data is in plain view (nothing | |
29 | * except for a serialized BLOB java object DOCUMENT.SOURCE_IDENTITY) this can be easily utilized. | |
30 | * <p/> | |
31 | * <b>Thread safety:</b>This class is no designed to be thread-safe. | |
32 | * | |
33 | * @author AleaActaEst, TCSDEVELOPER | |
34 | * @version 1.0 | |
35 | */ | |
36 | public class SimpleAccessDBIndexPersistence extends AbstractDBIndexPersistence { | |
37 | ||
38 | /** | |
39 | * This constructor will populate the connectionFactory and connectionName information from configuration. | |
40 | * | |
41 | * @param namespace The namespace for connection-related properties | |
42 | * | |
43 | * @throws IllegalArgumentException if namespace param is <tt>null</tt> or an empty (trim'd) String | |
44 | * @throws PersistenceConfigurationException | |
45 | * if there are configuration issues encountered | |
46 | * @see AbstractDBIndexPersistence#AbstractDBIndexPersistence(String) | |
47 | */ | |
48 | public SimpleAccessDBIndexPersistence(final String namespace) throws PersistenceConfigurationException { | |
49 | // arg checking is done in super constructor | |
50 | 329 | super(namespace); |
51 | 320 | } |
52 | ||
53 | /** | |
54 | * This constructor will populate the connectionFactory and connectionName information from input parameters. | |
55 | * | |
56 | * @param connectionFactory DBConnectionFactory instance used to generate connections | |
57 | * @param connectionName The name of the connection used for persistence operations | |
58 | * | |
59 | * @throws IllegalArgumentException if connectionFactory is <tt>null</tt> | |
60 | */ | |
61 | public SimpleAccessDBIndexPersistence(final DBConnectionFactory connectionFactory, final String connectionName) { | |
62 | // arg checking is done in super constructor | |
63 | 4 | super(connectionFactory, connectionName); |
64 | 3 | } |
65 | ||
66 | /** | |
67 | * This method adds the given DocumentIndex to the persistence. | |
68 | * <p/> | |
69 | * CS section 1.4.1.3 describes the algorithm of this method. | |
70 | * | |
71 | * @param documentIndex WordSource representing the document to be persisted | |
72 | * | |
73 | * @throws IllegalArgumentException when documentIndex is <tt>null</tt> | |
74 | * @throws IndexPersistenceException when fails to add DocumentIndex to the persistence or given index is already | |
75 | * persisted | |
76 | */ | |
77 | public void addDocumentIndex(final DocumentIndex documentIndex) throws IndexPersistenceException { | |
78 | 36 | if (documentIndex == null) { |
79 | 1 | throw new IllegalArgumentException("The parameter named [documentIndex] was null."); |
80 | } | |
81 | ||
82 | 35 | final Connection connection = getConnection(); |
83 | 35 | beginTransaction(connection); |
84 | ||
85 | 35 | int idCounter = 1; |
86 | 35 | final String documentId = |
87 | CommonDatabaseOperations.insertDocumentHeaderData(this, documentIndex.getWordSourceId(), connection); | |
88 | ||
89 | // the validity of these values (CS 1.4.1.3) is guaranteed by the final class | |
90 | // DocumentIndex and its constructor logic | |
91 | 34 | final Map words = documentIndex.getWords(); |
92 | 34 | final Set wordSet = words.entrySet(); |
93 | 34 | for (Iterator iterator = wordSet.iterator(); iterator.hasNext();) { |
94 | 1096 | final Map.Entry entry = (Map.Entry) iterator.next(); |
95 | ||
96 | // insert the WORD record | |
97 | 1096 | final Integer wordId = new Integer(idCounter++); |
98 | 1096 | DatabaseUtils.doDMLQuery(connection, this, |
99 | "INSERT INTO WORD (WORD_ID,DOCUMENT_ID,WORD_ENTRY) VALUES (?,?,?)", | |
100 | new Object[]{ | |
101 | wordId, | |
102 | documentId, | |
103 | ((CollationKey) entry.getKey()).getSourceString() | |
104 | }); | |
105 | ||
106 | // insert the WORD_POSITION records | |
107 | 1096 | final List indices = (List) entry.getValue(); |
108 | 1096 | for (Iterator iterator1 = indices.iterator(); iterator1.hasNext();) { |
109 | 2288 | final Integer index = (Integer) iterator1.next(); |
110 | ||
111 | 2288 | DatabaseUtils.doDMLQuery(connection, this, |
112 | "INSERT INTO WORD_POSITION (DOCUMENT_ID,WORD_ID,WORD_POSITION) VALUES (?,?,?)", | |
113 | new Object[]{ | |
114 | documentId, | |
115 | wordId, | |
116 | index | |
117 | }); | |
118 | } | |
119 | } | |
120 | ||
121 | 34 | commitTransaction(connection); |
122 | 34 | } |
123 | ||
124 | /** | |
125 | * This method does retrieve a DocumentIndex with the specified WordSourceId from the persistence. It does return | |
126 | * <tt>null</tt>, if DocumentIndex with the given WordSourceId is not found in the persistence. | |
127 | * <p/> | |
128 | * CS section 1.4.1.1 describes the algorithm of this method. | |
129 | * | |
130 | * @param wordSourceId WordSourceId of document to retrieve | |
131 | * | |
132 | * @return retrieved DocumentIndex, or <tt>null</tt> if document index with given WordSourceId is not found in the | |
133 | * persistence | |
134 | * | |
135 | * @throws IllegalArgumentException when wordSourceId is <tt>null</tt> | |
136 | * @throws IndexPersistenceException when fails to retrieve document index with the specified WordSourceId | |
137 | */ | |
138 | public DocumentIndex getDocumentIndex(final WordSourceId wordSourceId) | |
139 | throws IndexPersistenceException { | |
140 | 25 | if (wordSourceId == null) { |
141 | 1 | throw new IllegalArgumentException("The parameter named [wordSourceId] was null."); |
142 | } | |
143 | ||
144 | 24 | final String documentId = Utils.createIdString(wordSourceId); |
145 | ||
146 | 24 | final Object[] queryArgsDocumentId = new Object[]{documentId}; |
147 | ||
148 | 24 | final Connection connection = getConnection(); |
149 | ||
150 | 24 | final Integer count = (Integer) DatabaseUtils.doSingleValueQuery(connection, this, |
151 | "SELECT COUNT(*) FROM DOCUMENT WHERE DOCUMENT_ID=?", queryArgsDocumentId, | |
152 | DatabaseUtils.INTEGER_TYPE); | |
153 | 24 | if (count.intValue() == 0) { |
154 | 2 | DatabaseUtils.closeSilently(connection); |
155 | 2 | return null; |
156 | } | |
157 | ||
158 | 22 | final Locale locale = wordSourceId.getSourceLocale(); |
159 | 22 | final Collator collator = Collator.getInstance(locale); |
160 | ||
161 | 22 | final Map words = new HashMap(); |
162 | // fetch all WORDs | |
163 | 22 | final List result3 = DatabaseUtils.doQuery(connection, this, |
164 | "SELECT WORD_ID,WORD_ENTRY FROM WORD WHERE DOCUMENT_ID=?", | |
165 | queryArgsDocumentId, | |
166 | new DatabaseUtils.DataType[]{DatabaseUtils.INTEGER_TYPE, DatabaseUtils.STRING_TYPE} | |
167 | ); | |
168 | ||
169 | 22 | for (Iterator iterator = result3.iterator(); iterator.hasNext();) { |
170 | 1060 | final Object[] wordRecord = (Object[]) iterator.next(); |
171 | 1060 | final Integer wordId = (Integer) wordRecord[0]; |
172 | 1060 | final CollationKey key = collator.getCollationKey((String) wordRecord[1]); |
173 | ||
174 | //fetch all indices | |
175 | 1060 | final List result4 = DatabaseUtils.doSingleColumnQuery(connection, this, |
176 | "SELECT WORD_POSITION FROM WORD_POSITION WHERE DOCUMENT_ID=? AND WORD_ID=?", | |
177 | new Object[]{documentId, wordId}, | |
178 | DatabaseUtils.INTEGER_TYPE | |
179 | ); | |
180 | 1060 | words.put(key, result4); |
181 | } | |
182 | 22 | DatabaseUtils.closeSilently(connection); |
183 | 22 | return new DocumentIndex(wordSourceId, words); |
184 | } | |
185 | ||
186 | /** | |
187 | * This method does remove a document index with given WordSourceId from the persistence. When the document index is | |
188 | * not found, its use count is greater that zero, or function fail to remove it exception is thrown. | |
189 | * <p/> | |
190 | * CS section 1.4.1.2 describes the algorithm of this method. | |
191 | * | |
192 | * @param wordSourceId WordSourceId of document index to remove | |
193 | * | |
194 | * @throws IllegalArgumentException when WordSourceId is <tt>null</tt> | |
195 | * @throws IndexPersistenceException when document index is not found in the persistence, its use count is not zero, | |
196 | * or error happens when trying to remove it | |
197 | */ | |
198 | public void removeDocumentIndex(final WordSourceId wordSourceId) throws IndexPersistenceException { | |
199 | //arg checking and everything else is in common method | |
200 | 4 | if (wordSourceId == null) { |
201 | 1 | throw new IllegalArgumentException("The parameter named [wordSourceId] was null."); |
202 | } | |
203 | 3 | final String documentId = Utils.createIdString(wordSourceId); |
204 | ||
205 | 3 | final Connection connection = getConnection(); |
206 | 3 | final Object[] documentIdQueryArg = new Object[]{documentId}; |
207 | 3 | final int count = getDocumentUseCount(wordSourceId); |
208 | 2 | if (count != 0) { |
209 | 1 | throw new IndexPersistenceException("The index with the given id [" + wordSourceId |
210 | + "] cannot be deleted as its use count is not 0, but is " + count + "."); | |
211 | } | |
212 | ||
213 | 1 | beginTransaction(connection); |
214 | ||
215 | 1 | DatabaseUtils.doDMLQuery(connection, this, "DELETE FROM WORD_POSITION WHERE DOCUMENT_ID=?", |
216 | documentIdQueryArg); | |
217 | 1 | DatabaseUtils.doDMLQuery(connection, this, "DELETE FROM WORD WHERE DOCUMENT_ID=?", documentIdQueryArg); |
218 | 1 | DatabaseUtils.doDMLQuery(connection, this, "DELETE FROM DELIMITER WHERE DOCUMENT_ID=?", |
219 | documentIdQueryArg); | |
220 | 1 | DatabaseUtils.doDMLQuery(connection, this, "DELETE FROM DOCUMENT WHERE DOCUMENT_ID=?", |
221 | documentIdQueryArg); | |
222 | // the DOCUMENT_COLLECTION_DOCUMENT_XREF table remains untouched, as the indexer component assures no | |
223 | // matching entry to exist in that table when use count of document is 0 | |
224 | ||
225 | 1 | commitTransaction(connection); |
226 | 1 | } |
227 | ||
228 | /** | |
229 | * This method does store the given document collection index in the persistence. | |
230 | * <p/> | |
231 | * CS section 1.4.3.1 describes the algorithm of this method. | |
232 | * | |
233 | * @param collectionIndex CollectionIndex to store | |
234 | * | |
235 | * @throws IllegalArgumentException if collectionIndex is <tt>null</tt> | |
236 | * @throws IndexPersistenceException if fails to store document collection index or given index is already | |
237 | * persisted | |
238 | */ | |
239 | public void addCollectionIndex(final CollectionIndex collectionIndex) | |
240 | throws IndexPersistenceException { | |
241 | //arg checking and everything else is in common method | |
242 | 9 | CommonDatabaseOperations.addCollectionIndex(this, collectionIndex); |
243 | 6 | } |
244 | ||
245 | /** | |
246 | * This method retrieves a document collection index with specified identifier. It does return <tt>null</tt> when | |
247 | * collection with specified identifier is not found. | |
248 | * <p/> | |
249 | * CS section 1.4.3.2 describes the algorithm of this method. | |
250 | * | |
251 | * @param collectionId identifier of document collection index to retrieve | |
252 | * | |
253 | * @return CollectionIndex with specified identifier or <tt>null</tt> if the collection index with the given | |
254 | * identifier was not found in persistence | |
255 | * | |
256 | * @throws IllegalArgumentException when collectionId is <tt>null</tt> or an empty (trim'd) string | |
257 | * @throws IndexPersistenceException when collection index can not be retrieved | |
258 | */ | |
259 | public CollectionIndex getCollectionIndex(final String collectionId) throws IndexPersistenceException { | |
260 | //arg checking and everything else is in common method | |
261 | 10 | return CommonDatabaseOperations.getCollectionIndex(this, collectionId); |
262 | } | |
263 | ||
264 | /** | |
265 | * This method does remove the document collection index with specified identifier from the persistence. | |
266 | * <p/> | |
267 | * CS section 1.4.3.4 describes the algorithm of this method. | |
268 | * | |
269 | * @param collectionId identifier of document collection index to remove | |
270 | * | |
271 | * @throws IllegalArgumentException when collectionId is <tt>null</tt> or empty (trim'd) string | |
272 | * @throws IndexPersistenceException when fails to remove CollectionIndex with given identifier from database, or | |
273 | * when collection with that specific identifier did not exist in database | |
274 | */ | |
275 | public void removeCollectionIndex(final String collectionId) throws IndexPersistenceException { | |
276 | //arg checking and everything else is in common method | |
277 | 4 | CommonDatabaseOperations.removeCollectionIndex(this, collectionId); |
278 | 1 | } |
279 | ||
280 | /** | |
281 | * This method does update specified CollectionIndex in the persistence. | |
282 | * <p/> | |
283 | * CS section 1.4.3.3 describes the algorithm of this method. | |
284 | * | |
285 | * @param collectionIndex CollectionIndex to update | |
286 | * | |
287 | * @throws IllegalArgumentException if collectionIndex parameter is <tt>null</tt> | |
288 | * @throws IndexPersistenceException if any error happens when updating the collection index in the persistence, | |
289 | * this includes the case, when the specified collectionIndex is not found in the | |
290 | * persistence | |
291 | */ | |
292 | public void updateCollectionIndex(final CollectionIndex collectionIndex) throws IndexPersistenceException { | |
293 | //arg checking and everything else is in common method | |
294 | 3 | CommonDatabaseOperations.updateCollectionIndex(this, collectionIndex); |
295 | 1 | } |
296 | ||
297 | /** | |
298 | * This method increases the use count value for document index with specified WordSourceId by 1. | |
299 | * | |
300 | * @param wordSourceId WordSourceId of document index of which to update use count | |
301 | * | |
302 | * @throws IllegalArgumentException if wordSourceId is <tt>null</tt> | |
303 | * @throws IndexPersistenceException when fails to increase document index use count in the persistence or the | |
304 | * document with the given wordSourceId does not exist in persistence | |
305 | */ | |
306 | public void increaseDocumentUseCount(final WordSourceId wordSourceId) throws IndexPersistenceException { | |
307 | //arg checking and everything else is in common method | |
308 | 7 | CommonDatabaseOperations.increaseDocumentUseCount(this, wordSourceId, 1); |
309 | 5 | } |
310 | ||
311 | /** | |
312 | * This method decreases the use count value for document index with specified WordSourceId by 1. | |
313 | * | |
314 | * @param wordSourceId WordSourceId of document index of which to update use count | |
315 | * | |
316 | * @throws IllegalArgumentException if wordSourceId is <tt>null</tt> | |
317 | * @throws IndexPersistenceException when fails to increase document index use count in the persistence or the | |
318 | * document with the given wordSourceId does not exist in persistence | |
319 | */ | |
320 | public void decreaseDocumentUseCount(final WordSourceId wordSourceId) throws IndexPersistenceException { | |
321 | //arg checking and everything else is in common method | |
322 | 6 | CommonDatabaseOperations.increaseDocumentUseCount(this, wordSourceId, -1); |
323 | 4 | } |
324 | ||
325 | /** | |
326 | * This method does return the use count of the document index with the given id. | |
327 | * | |
328 | * @param wordSourceId WordSourceId of document index of which to retrieve use count | |
329 | * | |
330 | * @return the use count of the document with the given id | |
331 | * | |
332 | * @throws IllegalArgumentException if wordSourceId is <tt>null</tt> | |
333 | * @throws IndexPersistenceException when fails to retrieve document index use count in the persistence or the | |
334 | * document with the given id does not exist in the persistence | |
335 | */ | |
336 | public int getDocumentUseCount(final WordSourceId wordSourceId) throws IndexPersistenceException { | |
337 | //arg checking and everything else is in common method | |
338 | 18 | return CommonDatabaseOperations.getDocumentUseCount(this, wordSourceId); |
339 | } | |
340 | ||
341 | /** | |
342 | * This method does return the set of WordSourceId of documents that exist in this persistence instance. | |
343 | * <p/> | |
344 | * CS section 1.4.1.1 describes the algorithm of this method. | |
345 | * | |
346 | * @return set of WordSourceId of documents that exist in this persistence | |
347 | * | |
348 | * @throws IndexPersistenceException when the retrieval fails | |
349 | */ | |
350 | public Set getIndexedDocuments() throws IndexPersistenceException { | |
351 | //arg checking and everything else is in common method | |
352 | 3 | return CommonDatabaseOperations.getIndexedDocuments(this); |
353 | } | |
354 | ||
355 | } |
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |