001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: QueryParameters.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package com.uwyn.rife.database.queries;
009:
010: import java.util.*;
011:
012: import com.uwyn.rife.database.exceptions.DatabaseException;
013: import com.uwyn.rife.database.queries.QueryParameterType;
014: import com.uwyn.rife.pcj.map.IntKeyIntMap;
015: import com.uwyn.rife.pcj.map.IntKeyIntOpenHashMap;
016: import com.uwyn.rife.tools.ArrayUtils;
017:
018: public class QueryParameters implements Cloneable {
019: private AbstractParametrizedQuery mQuery = null;
020: private Map<QueryParameterType, Object> mParameters = null;
021:
022: private List<String> mCombinedParameters = null;
023: private String[] mCombinedParametersArray = null;
024:
025: public QueryParameters(AbstractParametrizedQuery query) {
026: if (null == query)
027: throw new IllegalArgumentException("query can't be null");
028:
029: mQuery = query;
030: }
031:
032: public QueryParameters getNewInstance() {
033: return new QueryParameters(mQuery);
034: }
035:
036: public int getNumberOfTypes() {
037: if (null == mParameters) {
038: return 0;
039: }
040:
041: return mParameters.size();
042: }
043:
044: public void clear() {
045: mParameters = null;
046: mCombinedParameters = null;
047: mCombinedParametersArray = null;
048: }
049:
050: public boolean hasParameter(QueryParameterType type, String value) {
051: if (null == type || null == value || null == mParameters) {
052: return false;
053: }
054:
055: if (!mParameters.containsKey(type)) {
056: return false;
057: }
058:
059: if (type.isSingular()) {
060: return value.equals(mParameters.get(type));
061: } else {
062: List<String> list = (List<String>) mParameters.get(type);
063: if (null == list) {
064: return false;
065: }
066:
067: return list.contains(value);
068: }
069: }
070:
071: public Set<String> getDistinctNames() {
072: if (null == mParameters || 0 == mParameters.size()) {
073: return null;
074: }
075:
076: HashSet<String> names = new HashSet<String>();
077: for (Map.Entry<QueryParameterType, Object> entry : mParameters
078: .entrySet()) {
079: if (entry.getKey().isSingular()) {
080: names.add((String) entry.getValue());
081: } else {
082: names.addAll((List<String>) entry.getValue());
083: }
084: }
085:
086: return names;
087: }
088:
089: public List<String> getOrderedNames() {
090: if (null == mCombinedParameters) {
091: ArrayList<String> combined_parameters = null;
092:
093: if (mParameters != null && mParameters.size() > 0) {
094: if (mParameters.containsKey(QueryParameterType.FIELD)) {
095: combined_parameters = new ArrayList<String>();
096:
097: for (String parameter : (List<String>) mParameters
098: .get(QueryParameterType.FIELD)) {
099: // add the parameter to the combined list
100: combined_parameters.add(parameter);
101: }
102: }
103:
104: if (mParameters.containsKey(QueryParameterType.TABLE)) {
105: if (null == combined_parameters) {
106: combined_parameters = new ArrayList<String>();
107: }
108:
109: for (String parameter : (List<String>) mParameters
110: .get(QueryParameterType.TABLE)) {
111: // add the parameter to the combined list
112: combined_parameters.add(parameter);
113: }
114: }
115:
116: if (mParameters.containsKey(QueryParameterType.WHERE)) {
117: if (null == combined_parameters) {
118: combined_parameters = new ArrayList<String>();
119: }
120:
121: for (String parameter : (List<String>) mParameters
122: .get(QueryParameterType.WHERE)) {
123: // add the parameter to the combined list
124: combined_parameters.add(parameter);
125: }
126: }
127:
128: if (mParameters.containsKey(QueryParameterType.UNION)) {
129: if (null == combined_parameters) {
130: combined_parameters = new ArrayList<String>();
131: }
132:
133: for (String parameter : (List<String>) mParameters
134: .get(QueryParameterType.UNION)) {
135: // add the parameter to the combined list
136: combined_parameters.add(parameter);
137: }
138: }
139:
140: if (mParameters.containsKey(QueryParameterType.LIMIT)
141: || mParameters
142: .containsKey(QueryParameterType.OFFSET)) {
143: if (mQuery.isLimitBeforeOffset()) {
144: if (mParameters
145: .containsKey(QueryParameterType.LIMIT)) {
146: if (null == combined_parameters) {
147: combined_parameters = new ArrayList<String>();
148: }
149:
150: // get the parameter value
151: String value = (String) mParameters
152: .get(QueryParameterType.LIMIT);
153: // add the parameter to the combined list
154: combined_parameters.add(value);
155: }
156:
157: if (mParameters
158: .containsKey(QueryParameterType.OFFSET)) {
159: if (null == combined_parameters) {
160: combined_parameters = new ArrayList<String>();
161: }
162:
163: // get the parameter value
164: String value = (String) mParameters
165: .get(QueryParameterType.OFFSET);
166: // add the parameter to the combined list
167: combined_parameters.add(value);
168: }
169: } else {
170: if (mParameters
171: .containsKey(QueryParameterType.OFFSET)) {
172: if (null == combined_parameters) {
173: combined_parameters = new ArrayList<String>();
174: }
175:
176: // get the parameter value
177: String value = (String) mParameters
178: .get(QueryParameterType.OFFSET);
179: // add the parameter to the combined list
180: combined_parameters.add(value);
181: }
182:
183: if (mParameters
184: .containsKey(QueryParameterType.LIMIT)) {
185: if (null == combined_parameters) {
186: combined_parameters = new ArrayList<String>();
187: }
188:
189: // get the parameter value
190: String value = (String) mParameters
191: .get(QueryParameterType.LIMIT);
192: // add the parameter to the combined list
193: combined_parameters.add(value);
194: }
195: }
196: }
197: }
198:
199: mCombinedParameters = combined_parameters;
200: mCombinedParametersArray = null;
201: }
202:
203: return mCombinedParameters;
204: }
205:
206: private void addVirtualIndexMapping(
207: QueryParameters virtualParameters, IntKeyIntMap map,
208: int[] parameterIndex, int[] realIndex,
209: QueryParameterType type, String parameter) {
210: if (virtualParameters.hasParameter(type, parameter)) {
211: map.put(parameterIndex[0], -1);
212: } else {
213: map.put(parameterIndex[0], realIndex[0]);
214: realIndex[0]++;
215: }
216:
217: parameterIndex[0]++;
218: }
219:
220: public IntKeyIntMap getVirtualIndexMapping(
221: QueryParameters virtualParameters) {
222: IntKeyIntMap map = null;
223:
224: if (mParameters != null && mParameters.size() > 0
225: && virtualParameters != null
226: && virtualParameters.getNumberOfTypes() > 0) {
227: map = new IntKeyIntOpenHashMap();
228:
229: int[] parameter_index = new int[] { 1 };
230: int[] real_index = new int[] { 1 };
231:
232: if (mParameters.containsKey(QueryParameterType.FIELD)) {
233: for (String parameter : (List<String>) mParameters
234: .get(QueryParameterType.FIELD)) {
235: addVirtualIndexMapping(virtualParameters, map,
236: parameter_index, real_index,
237: QueryParameterType.FIELD, parameter);
238: }
239: }
240:
241: if (mParameters.containsKey(QueryParameterType.TABLE)) {
242: for (String parameter : (List<String>) mParameters
243: .get(QueryParameterType.TABLE)) {
244: addVirtualIndexMapping(virtualParameters, map,
245: parameter_index, real_index,
246: QueryParameterType.TABLE, parameter);
247: }
248: }
249:
250: if (mParameters.containsKey(QueryParameterType.WHERE)) {
251: for (String parameter : (List<String>) mParameters
252: .get(QueryParameterType.WHERE)) {
253: addVirtualIndexMapping(virtualParameters, map,
254: parameter_index, real_index,
255: QueryParameterType.WHERE, parameter);
256: }
257: }
258:
259: if (mParameters.containsKey(QueryParameterType.UNION)) {
260: for (String parameter : (List<String>) mParameters
261: .get(QueryParameterType.UNION)) {
262: addVirtualIndexMapping(virtualParameters, map,
263: parameter_index, real_index,
264: QueryParameterType.UNION, parameter);
265: }
266: }
267:
268: if (mParameters.containsKey(QueryParameterType.LIMIT)
269: || mParameters
270: .containsKey(QueryParameterType.OFFSET)) {
271: if (mQuery.isLimitBeforeOffset()) {
272: if (mParameters
273: .containsKey(QueryParameterType.LIMIT)) {
274: String parameter = (String) mParameters
275: .get(QueryParameterType.LIMIT);
276: addVirtualIndexMapping(virtualParameters, map,
277: parameter_index, real_index,
278: QueryParameterType.LIMIT, parameter);
279: }
280:
281: if (mParameters
282: .containsKey(QueryParameterType.OFFSET)) {
283: String parameter = (String) mParameters
284: .get(QueryParameterType.OFFSET);
285: addVirtualIndexMapping(virtualParameters, map,
286: parameter_index, real_index,
287: QueryParameterType.OFFSET, parameter);
288: }
289: } else {
290: if (mParameters
291: .containsKey(QueryParameterType.OFFSET)) {
292: String parameter = (String) mParameters
293: .get(QueryParameterType.OFFSET);
294: addVirtualIndexMapping(virtualParameters, map,
295: parameter_index, real_index,
296: QueryParameterType.OFFSET, parameter);
297: }
298:
299: if (mParameters
300: .containsKey(QueryParameterType.LIMIT)) {
301: String parameter = (String) mParameters
302: .get(QueryParameterType.LIMIT);
303: addVirtualIndexMapping(virtualParameters, map,
304: parameter_index, real_index,
305: QueryParameterType.LIMIT, parameter);
306: }
307: }
308: }
309: }
310:
311: return map;
312: }
313:
314: public String[] getOrderedNamesArray() {
315: if (null == mParameters || 0 == mParameters.size()) {
316: return null;
317: }
318:
319: if (null == mCombinedParametersArray) {
320: String[] array = new String[0];
321:
322: for (String parameter_name : getOrderedNames()) {
323: array = ArrayUtils.join(array, parameter_name);
324: }
325:
326: mCombinedParametersArray = array;
327: }
328:
329: return mCombinedParametersArray;
330: }
331:
332: private void clearCombinedParameters() {
333: mCombinedParameters = null;
334: mCombinedParametersArray = null;
335: }
336:
337: public void clearTypedParameters(QueryParameterType type) {
338: if (null == type)
339: throw new IllegalArgumentException(
340: "the parameter type can't be null");
341:
342: if (null == mParameters) {
343: return;
344: }
345:
346: mParameters.remove(type);
347: clearCombinedParameters();
348: }
349:
350: public <T> T getTypedParameters(QueryParameterType type) {
351: if (null == type)
352: throw new IllegalArgumentException(
353: "the parameter type can't be null");
354:
355: if (null == mParameters) {
356: return null;
357: }
358:
359: return (T) mParameters.get(type);
360: }
361:
362: public void addTypedParameters(QueryParameterType type,
363: List<String> parameters) {
364: if (null == type)
365: throw new IllegalArgumentException(
366: "the parameter type can't be null");
367: if (type.isSingular())
368: throw new IllegalArgumentException("the parameter type '"
369: + type + "' only supports a singular value");
370:
371: // don't add empty parameters
372: if (null == parameters || 0 == parameters.size()) {
373: return;
374: }
375:
376: // obtain the existing typed parameters
377: List<String> typed_parameters = null;
378: if (null == mParameters) {
379: mParameters = new HashMap<QueryParameterType, Object>();
380: } else {
381: typed_parameters = (List<String>) mParameters.get(type);
382: }
383:
384: // initialize the typed parameters collection if it didn't exist before
385: boolean new_collection = false;
386: if (null == typed_parameters) {
387: typed_parameters = new ArrayList<String>();
388: new_collection = true;
389: }
390:
391: // add the new parameters
392: typed_parameters.addAll(parameters);
393:
394: if (new_collection) {
395: mParameters.put(type, typed_parameters);
396: }
397:
398: // clear the already calculated combined parameters
399: clearCombinedParameters();
400: }
401:
402: public void addTypedParameter(QueryParameterType type, String value) {
403: if (null == type)
404: throw new IllegalArgumentException(
405: "the parameter type can't be null");
406:
407: if (value != null) {
408: // initialize the parameters map if it doesn't exist yet
409: if (null == mParameters) {
410: mParameters = new HashMap<QueryParameterType, Object>();
411: }
412:
413: // remove the table-field separator dot
414: if (value.indexOf(".") != -1) {
415: value = value.substring(value.lastIndexOf(".") + 1);
416: }
417: }
418:
419: // check if the parameter is singular
420: if (type.isSingular()) {
421: // empty singular parameters clear out the key
422: if (null == value) {
423: if (null == mParameters) {
424: return;
425: }
426:
427: mParameters.remove(type);
428: }
429: // store the singular parameter
430: else {
431: mParameters.put(type, value);
432: }
433: } else {
434: // don't add empty parameters
435: if (null == value) {
436: return;
437: }
438:
439: // obtain the existing typed parameters
440: List<String> typed_parameters = (List<String>) mParameters
441: .get(type);
442:
443: // initialize the typed parameters collection if it didn't exist before
444: boolean new_collection = false;
445: if (null == typed_parameters) {
446: typed_parameters = new ArrayList<String>();
447: new_collection = true;
448: }
449:
450: // add the new parameters
451: typed_parameters.add(value);
452:
453: // store the new collection if it has been allocated
454: if (new_collection) {
455: mParameters.put(type, typed_parameters);
456: }
457: }
458:
459: // clear the already calculated combined parameters
460: clearCombinedParameters();
461: }
462:
463: public QueryParameters clone() {
464: QueryParameters new_instance = null;
465: try {
466: new_instance = (QueryParameters) super .clone();
467: } catch (CloneNotSupportedException e) {
468: throw new DatabaseException(e);
469: }
470:
471: if (new_instance != null) {
472: if (mCombinedParameters != null) {
473: new_instance.mCombinedParameters = new ArrayList<String>();
474: new_instance.mCombinedParameters
475: .addAll(mCombinedParameters);
476: }
477:
478: if (mParameters != null) {
479: new_instance.mParameters = new HashMap<QueryParameterType, Object>();
480: for (Map.Entry<QueryParameterType, Object> entry : mParameters
481: .entrySet()) {
482: if (entry.getKey().isSingular()) {
483: new_instance.mParameters.put(entry.getKey(),
484: entry.getValue());
485: } else {
486: List<String> values = new ArrayList<String>();
487: values.addAll((List<String>) entry.getValue());
488: new_instance.mParameters.put(entry.getKey(),
489: values);
490: }
491: }
492: }
493: }
494:
495: return new_instance;
496: }
497: }
|