1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.caleigo.core.service;
20
21
22 import java.util.*;
23 import java.text.*;
24
25 import java.sql.Connection;
26 import java.sql.PreparedStatement;
27 import java.sql.SQLException;
28 import java.sql.Timestamp;
29
30 import org.caleigo.core.*;
31 import org.caleigo.core.exception.*;
32
33 /*** This class constanis help methods for building valid SQL language
34 * statements based on CEL entities, descriptors and qualifiers.
35 *
36 * The class can be used by any IDataService implementation that connects
37 * to SQL based databases.
38 *
39 * @author Dennis Zikovic
40 * @version 1.00
41 *
42 *
43 * WHEN WHO WHY & WHAT
44 * -----------------------------------------------------------------------------
45 * 2001-07-24 Dennis Zikovic Creation
46 */
47 public class SQLToolKitPS implements java.io.Serializable
48 {
49
50 private static final String SELECT = "SELECT ";
51 private static final String INSERT = "INSERT INTO ";
52 private static final String UPDATE = "UPDATE ";
53 private static final String DELETE = "DELETE FROM ";
54 private static final String FROM = "FROM ";
55 private static final String WHERE = "WHERE ";
56 private static final String ORDER = "ORDER BY ";
57
58
59 private Map mQualifierParserMap;
60 private Map mDataTypeConverterMap;
61 private boolean mIsQuotingIdentifiers = false;
62
63
64 /***
65 * Constructs a new SQLToolKitPS and does necessary initialization
66 */
67 public SQLToolKitPS()
68 {
69
70 mDataTypeConverterMap = new HashMap();
71 mDataTypeConverterMap.put(DataType.STRING, new StringTypeConverter());
72 mDataTypeConverterMap.put(DataType.BOOLEAN, new BooleanTypeConverter());
73 mDataTypeConverterMap.put(DataType.DATE, new DateTypeConverter());
74
75
76 mQualifierParserMap = new HashMap();
77 mQualifierParserMap.put(RelationQualifier.class, new RelationQualifierParser());
78 mQualifierParserMap.put(CompositeQualifier.class, new CompositeQualifierParser());
79 mQualifierParserMap.put(NegateQualifier.class, new NegateQualifierParser());
80 }
81
82
83
84
85
86 public void addDataTypeConverter(DataType dataType, IDataTypeConverter converter)
87 {
88 mDataTypeConverterMap.remove(dataType);
89 mDataTypeConverterMap.put(dataType, converter);
90 }
91
92 public IDataTypeConverter getDataTypeConverter(DataType dataType)
93 {
94 return (IDataTypeConverter)mDataTypeConverterMap.get(dataType);
95 }
96
97
98 /***
99 * Adds a qualifierParser for the specified qualifier class. The Parser is responsible for analysing the
100 * qualifier and constructing a SQL query
101 *
102 * @param qualifierClass The qualifier class that should be handled by the parser
103 * @param parser The parser that should handle the qualifier class
104 */
105 public void addQualifierParser(Class qualifierClass, IQualifierParser parser)
106 {
107 mQualifierParserMap.remove(qualifierClass);
108 mQualifierParserMap.put(qualifierClass, parser);
109 }
110
111 public IQualifierParser getQualifierParser(Class qualifierClass)
112 {
113 return (IQualifierParser)mQualifierParserMap.get(qualifierClass);
114 }
115
116 public void setQuotingIdentifiers(boolean allwaysQuote)
117 {
118 mIsQuotingIdentifiers = allwaysQuote;
119 }
120
121 public boolean isQuotingIdentifiers()
122 {
123 return mIsQuotingIdentifiers;
124 }
125
126
127 public String buildSelectCommand(DataQuery query, ArrayList values)
128 {
129
130 StringBuffer command = new StringBuffer(1000);
131 command.append(this.buildSelectCommand(query.getEntityDescriptor(), query.getQualifier(), values));
132
133
134 if(query.getEntityCollator()!=null)
135 {
136 EntityCollator collator = query.getEntityCollator();
137
138 command.append(' ');
139 command.append(ORDER);
140 for(int j=0; j<collator.getFieldCount(); j++)
141 {
142 if(j>0)
143 command.append(", ");
144 command.append(this.quoteIdentifier(collator.getFieldCollator(j).getFieldDescriptor().getEntityDescriptor().getSourceName()));
145 command.append('.');
146 command.append(this.quoteIdentifier(collator.getFieldCollator(j).getFieldDescriptor().getSourceName()));
147 if(!collator.getFieldCollator(j).isAscending())
148 command.append(" DESC");
149 }
150 }
151
152 return command.toString();
153 }
154
155 /***
156 * Builds the select query to be used by a PreparedStatement
157 *
158 * @param descriptor The Entity type to be queried
159 * @param qualifier The qualifier that identies the wanted subset of entities
160 * @param values ArrayList that should be populated with the data to be set by the PreparedStatement
161 * @return String Returns a sql query used with a PreparedStatement
162 */
163 public String buildSelectCommand(IEntityDescriptor descriptor, Qualifier qualifier, ArrayList values)
164 {
165
166
167
168 StringBuffer command = new StringBuffer(1000);
169 command.append(SELECT);
170
171 for(int j=0; j<descriptor.getFieldCount(); j++)
172 {
173 if(j>0)
174 {
175 command.append(',');
176 command.append(' ');
177 }
178 command.append(this.quoteIdentifier(descriptor.getFieldDescriptor(j).getEntityDescriptor().getSourceName()));
179 command.append('.');
180 command.append(this.quoteIdentifier(descriptor.getFieldDescriptor(j).getSourceName()));
181 }
182 command.append(' ');
183
184
185 command.append(FROM);
186 command.append(buildFromExpresion(descriptor, qualifier));
187 command.append(' ');
188
189
190 if(qualifier!=null)
191 {
192 command.append(WHERE);
193 command.append(this.buildWhereExpresion(qualifier, values));
194 }
195
196 return command.toString();
197 }
198
199 /***
200 * Builds a Select PreparedStatement from a IEntityDescriptor and a Qualifier
201 *
202 * @param descriptor IEntityDescriptor that identied the Type of entity wanted
203 * @param qualifier Qualifier that is used to limit the result to a wanted subset of entities
204 * @param connection SQL Connection that is the link to the database
205 * @return PreparedStatement Returns a fully populated Prepared Statement to be used for querying
206 * @throws SQLException throwmn if a database problem occurs
207 */
208 public PreparedStatement buildSelectStatement(IEntityDescriptor descriptor, Qualifier qualifier, Connection connection)
209 throws SQLException
210 {
211 ArrayList values = new ArrayList();
212 String sql = buildSelectCommand(descriptor, qualifier, values);
213 PreparedStatement preparedStatement = connection.prepareStatement(sql);
214
215 Iterator iter = values.iterator();
216
217 int count = 1;
218 while (iter.hasNext())
219 {
220 Object data = iter.next();
221
222 preparedStatement.setObject(count++, data);
223 }
224
225 return preparedStatement;
226 }
227
228 /***
229 * Build the Prepared Statement SQL query for for an update of an entity
230 *
231 * @param entity The entity that should be updated
232 * @param qualifier The qualifier that uniqely identifies the entity
233 * @param values Should be populated with all data to be set in the query and in the correct order.
234 * @return String Returns a SQL query representing the Update
235 */
236 public String buildUpdateCommand(IEntity entity, Qualifier qualifier, ArrayList values)
237 {
238
239 StringBuffer command = new StringBuffer(1000);
240 command.append(UPDATE);
241 command.append(this.quoteIdentifier(entity.getEntityDescriptor().getSourceName()));
242 command.append(' ');
243
244
245 command.append("SET ");
246 int addedCount = 0;
247 for(int j=0; j<entity.getEntityDescriptor().getFieldCount(); j++)
248 {
249 if(!entity.getEntityDescriptor().getFieldDescriptor(j).isAutoGenerated()
250 && entity.isFieldDirty(entity.getEntityDescriptor().getFieldDescriptor(j)))
251 {
252 if(addedCount>0)
253 {
254 command.append(',');
255 command.append(' ');
256 }
257
258 command.append(this.quoteIdentifier(entity.getEntityDescriptor().getFieldDescriptor(j).getSourceName()));
259 command.append('=');
260
261 values.add(entity.getData(entity.getEntityDescriptor().getFieldDescriptor(j)));
262 addedCount++;
263 }
264 }
265 command.append(' ');
266
267
268 if(qualifier==null)
269 qualifier = entity.getOriginQualifier();
270 command.append(WHERE);
271 command.append(this.buildWhereExpresion(qualifier, values));
272
273
274 return command.toString();
275 }
276
277
278 /***
279 * Build a Update Prepared Statement from a Entity and a Qualifier
280 *
281 * @param entity The entity containing the data to be updated
282 * @param qualifier A qualifier that identifies the entity to be updated
283 * @param connection A reference to a SQL connection
284 * @return PreparedStatement Returns a fully runnable PreparedStatement
285 * @throws SQLException thrown if there was a problem with the sql connection
286 */
287 public PreparedStatement buildUpdateStatement(IEntity entity, Qualifier qualifier, Connection connection)
288 throws SQLException
289 {
290 ArrayList values = new ArrayList();
291 String sql = buildUpdateCommand(entity, qualifier, values);
292
293 PreparedStatement preparedStatement = connection.prepareStatement(sql);
294
295 Iterator iter = values.iterator();
296 int count = 1;
297 while (iter.hasNext())
298 {
299 Object data = iter.next();
300
301 preparedStatement.setObject(count++, data);
302 }
303
304 return preparedStatement;
305 }
306
307
308 /***
309 * Build the SQL Insert String for Prepared statements
310 *
311 * @param entity The entity to be inserted
312 * @return String Returns the string that should be run by the prepared Statement
313 */
314 public String buildInsertCommand(IEntity entity)
315 {
316
317
318
319 StringBuffer declarationPart = new StringBuffer(1000);
320 StringBuffer valuePart = new StringBuffer(1000);
321 int addedCount = 0;
322
323 declarationPart.append(INSERT);
324 declarationPart.append(this.quoteIdentifier(entity.getEntityDescriptor().getSourceName()));
325 declarationPart.append(" (");
326
327 valuePart.append(" VALUES (");
328
329 for(int j=0; j<entity.getEntityDescriptor().getFieldCount(); j++)
330 {
331
332 if(!entity.getEntityDescriptor().getFieldDescriptor(j).isAutoGenerated())
333 {
334 Object data = entity.getData(entity.getEntityDescriptor().getFieldDescriptor(j));
335
336
337 if(data!=null)
338 {
339 if(addedCount>0)
340 {
341 declarationPart.append(", ");
342 valuePart.append(", ");
343 }
344 addedCount++;
345
346 declarationPart.append(this.quoteIdentifier(entity.getEntityDescriptor().getFieldDescriptor(j).getSourceName()));
347 valuePart.append("?");
348
349 }
350 }
351 }
352 declarationPart.append(')');
353 valuePart.append(')');
354
355
356 if (declarationPart.toString().endsWith("()") && valuePart.toString().endsWith("()"))
357 {
358 declarationPart.delete(declarationPart.indexOf("()"), declarationPart.length());
359 valuePart.replace(0, valuePart.length(), "DEFAULT VALUES");
360 }
361
362
363 declarationPart.append(valuePart);
364 return declarationPart.toString();
365 }
366
367
368 /***
369 * Build a PreparedStatement for inserting the Entity
370 *
371 * @param entity The entity to be inserted
372 * @param connection The SQL connections that should handle the Statement
373 * @param generateKeys Set to true if Generated Keys should be returned
374 * @return PreparedStatement A fully runnable Prepared Statement
375 * @exception SQLException Returned if an SQLException occured
376 */
377 public PreparedStatement buildInsertStatement(IEntity entity, Connection connection, boolean generateKeys)
378 throws SQLException
379 {
380 String sql = buildInsertCommand(entity);
381 PreparedStatement preparedStatement = null;
382 if (generateKeys)
383 connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
384 else
385 connection.prepareStatement(sql, PreparedStatement.NO_GENERATED_KEYS);
386
387 int count=1;
388
389
390 for(int j=0; j<entity.getEntityDescriptor().getFieldCount(); j++)
391 {
392
393 if(!entity.getEntityDescriptor().getFieldDescriptor(j).isAutoGenerated())
394 {
395 Object data = entity.getData(entity.getEntityDescriptor().getFieldDescriptor(j));
396
397
398 if(data!=null)
399 {
400 preparedStatement.setObject(count++, data);
401 }
402 }
403 }
404
405 return preparedStatement;
406 }
407
408
409 /***
410 * Build the delete SQL Prepared Statement Query
411 *
412 * @param descriptor The descriptor that describes the entity/ies being removed
413 * @param qualifier The qualifier that identifies the entities to be removed
414 * @param values Should be updated with the data that should complement the PreparedStatement
415 * @return String Returns the Prepared Statement query string
416 */
417 public String buildDeleteCommand(IEntityDescriptor descriptor, Qualifier qualifier, ArrayList values)
418 {
419
420 if(descriptor.getEntityType()==IEntityDescriptor.CUSTOM_ENTITY)
421 throw new SQLToolKitException("Can't delete composite entities.");
422 if(qualifier==null || !qualifier.canUniquelyQualify(descriptor))
423 throw new SQLToolKitException("Delete command requires an identity qualifier.");
424
425
426 StringBuffer command = new StringBuffer(1000);
427 command.append(DELETE);
428 command.append(this.quoteIdentifier(descriptor.getSourceName()));
429 command.append(' ');
430
431
432 command.append(WHERE);
433 command.append(this.buildWhereExpresion(qualifier, values));
434
435
436
437 return command.toString();
438 }
439
440
441 /***
442 * Build a Delete Prepared Statement from a EntityDescriptor and a Qualifier
443 *
444 * @param descriptor A IEntityDescriptor stating what descriptor type to be deleted
445 * @param qualifier A qualifier that identifies the subset of entities to be removed
446 * @param connection A reference to a SQL connection
447 * @return PreparedStatement Returns a fully runnable PreparedStatement
448 * @throws SQLException thrown if there was a problem with the sql connection
449 */
450 public PreparedStatement buildDeleteStatement(IEntityDescriptor descriptor, Qualifier qualifier, Connection connection)
451 throws SQLException
452 {
453 ArrayList values = new ArrayList();
454 String sql = buildDeleteCommand(descriptor, qualifier, values);
455
456 PreparedStatement preparedStatement = connection.prepareStatement(sql);
457
458 Iterator iter = values.iterator();
459 int count = 1;
460 while (iter.hasNext())
461 {
462 Object data = iter.next();
463
464 preparedStatement.setObject(count++, data);
465 }
466
467 return preparedStatement;
468
469 }
470
471 /***
472 * This method creates a comma seperated string with the source name
473 * of all referenced entity descriptors.
474 *
475 * @param descriptor The descriptor that describes the entity/ies
476 * @param qualifier The qualifier that identifies the entities
477 * @return Returns a String containing the FROM section of the query
478 */
479 public String buildFromExpresion(IEntityDescriptor descriptor, Qualifier qualifier)
480 {
481
482 Set descriptorSet = this.getQualifierDescriptorSet(qualifier);
483 if(descriptorSet==null)
484 descriptorSet = new HashSet();
485
486
487 for(int j=0; j<descriptor.getFieldCount(); j++)
488 descriptorSet.add(descriptor.getFieldDescriptor(j).getEntityDescriptor());
489
490
491 StringBuffer expresion = new StringBuffer(1000);
492 Iterator it = descriptorSet.iterator();
493 while(it.hasNext())
494 {
495 if(expresion.length()>0)
496 {
497 expresion.append(',');
498 expresion.append(' ');
499 }
500 expresion.append(this.quoteIdentifier(((IEntityDescriptor)it.next()).getSourceName()));
501 }
502
503 return expresion.toString();
504 }
505
506
507 /***
508 * Builds a WHERE Prepared statement from a qualifier
509 *
510 * @param qualifier The qualifier that should be parsed
511 * @param values The data stored should be stored in values in the same order it is being added to the generated query
512 * @return String The prepared WHERE statement
513 */
514 public String buildWhereExpresion(Qualifier qualifier, ArrayList values)
515 {
516 if(qualifier==null)
517 return null;
518 else if(mQualifierParserMap.containsKey(qualifier.getClass()))
519 return ((IQualifierParser)mQualifierParserMap.get(qualifier.getClass())).process(qualifier, this, values);
520 else
521 throw new SQLToolKitException("Failed to process unknown Qualifier class: "+qualifier.getClass().getName());
522 }
523
524 public String buildDataString(DataType type, Object data)
525 {
526 if(mDataTypeConverterMap.containsKey(type))
527 return (String)((IDataTypeConverter)mDataTypeConverterMap.get(type)).convertToDB(data);
528 else
529 return type.convertToString(data);
530 }
531
532 public String prepareWildcards(String dataString)
533 {
534 StringBuffer buf = new StringBuffer(dataString);
535 for(int j=0; j<dataString.length(); j++)
536 {
537 if(buf.charAt(j)=='*')
538 buf.setCharAt(j, '%');
539 else if(buf.charAt(j)=='?')
540 buf.setCharAt(j, '_');
541 }
542 return buf.toString();
543 }
544
545 /*** Returns a Set containing the entity descriptors meaded for the WHERE
546 * statement built by the submited qualifier. Can be used to build the
547 * FROM statement of the SQL command. May return null
548 */
549 protected Set getQualifierDescriptorSet(Qualifier qualifier)
550 {
551 if(qualifier==null)
552 return null;
553 else if(mQualifierParserMap.containsKey(qualifier.getClass()))
554 return ((IQualifierParser)mQualifierParserMap.get(qualifier.getClass())).stateDescriptorRequirement(qualifier, this);
555 else
556 throw new SQLToolKitException("Failed to process unknown Qualifier class: "+qualifier.getClass().getName());
557 }
558
559 public String quoteIdentifier(String indentifier)
560 {
561 if(mIsQuotingIdentifiers || indentifier.indexOf(' ')>=0)
562 return "\""+indentifier+"\"";
563 else
564 return indentifier;
565 }
566
567
568
569 public static interface IQualifierParser
570 {
571 /*** Should produce a valid logic "term" to iclude in an sql where-
572 * statement.
573 */
574 public String process(Qualifier qualifier, SQLToolKitPS sql, ArrayList values);
575
576 /*** Should produce a set of entity descriptors that are adressed by
577 * the qualifier.
578 */
579 public Set stateDescriptorRequirement(Qualifier qualifier, SQLToolKitPS sql);
580 }
581
582
583 /***
584 * Class for parsing RelationQualifiers.
585 */
586 public class RelationQualifierParser implements IQualifierParser
587 {
588
589 /***
590 * Processes a qualifier and creates a Conditional query
591 *
592 * @param qualifier the qualifier that should be parsed
593 * @param sql The Toolkit containing all data about the conversion
594 * @param values An ArrayList with all data needed to be set in the PreparedStatement
595 * @return Returns a string with the sql query
596 */
597 public String process(Qualifier qualifier, SQLToolKitPS sql, ArrayList values)
598 {
599 if(qualifier==null)
600 return null;
601
602 StringBuffer buf = new StringBuffer(100);
603 RelationQualifier qual = (RelationQualifier)qualifier;
604
605
606 buf.append(quoteIdentifier(qual.getFieldDescriptor().getEntityDescriptor().getSourceName()));
607 buf.append('.');
608 buf.append(quoteIdentifier(qual.getFieldDescriptor().getSourceName()));
609
610
611 if(qual.getRelationType()==RelationType.EQUAL)
612 {
613 if(qual.getRelationValue()==null)
614 buf.append(" IS NULL");
615 else
616 buf.append('=');
617 }
618 else if(qual.getRelationType()==RelationType.NOT_EQUAL)
619 {
620 if(qual.getRelationValue()==null)
621 buf.append(" IS NOT NULL");
622 else
623 buf.append("<>");
624 }
625 else if(qual.getRelationType()==RelationType.LESS)
626 buf.append('<');
627 else if(qual.getRelationType()==RelationType.LESS_EQUAL)
628 buf.append("<=");
629 else if(qual.getRelationType()==RelationType.LARGER)
630 buf.append('>');
631 else if(qual.getRelationType()==RelationType.LARGER_EQUAL)
632 buf.append(">=");
633 else if(qual.getRelationType()==RelationType.SIMULAR)
634 buf.append(" LIKE ");
635 else
636 buf.append(qual.getRelationType().toString());
637
638
639 if(qual.getRelationValue() instanceof IFieldDescriptor)
640 {
641 buf.append(quoteIdentifier(((IFieldDescriptor)qual.getRelationValue()).getEntityDescriptor().getSourceName()));
642 buf.append('.');
643 buf.append(quoteIdentifier(((IFieldDescriptor)qual.getRelationValue()).getSourceName()));
644 }
645 else if(qual.getRelationValue()!=null)
646 {
647 if(qual.getRelationType()==RelationType.SIMULAR)
648 values.add(sql.prepareWildcards(sql.buildDataString(qual.getFieldDescriptor().getDataType(), qual.getRelationValue())));
649 else
650 values.add(qual.getRelationValue());
651
652 buf.append("?");
653 }
654 else if(!(qual.getRelationType()==RelationType.EQUAL || qual.getRelationType()==RelationType.NOT_EQUAL))
655 throw new SQLToolKitException("Relation using \""+qual.getRelationType()+"\" can not relate to NULL.");
656
657 return buf.toString();
658 }
659
660 /***
661 * States what descriptors are needed for the FROM expression
662 *
663 * @param qualifier The qualifier constituting the condition
664 * @param sql The toolkit containinig the overall data for the expressionbuilding
665 * @return Returns a set of FieldDescriptor needed to be in the FROM sections of the sql expression.
666 */
667 public Set stateDescriptorRequirement(Qualifier qualifier, SQLToolKitPS sql)
668 {
669 Set descriptorSet = new HashSet();
670 descriptorSet.add(((RelationQualifier)qualifier).getFieldDescriptor().getEntityDescriptor());
671 if(((RelationQualifier)qualifier).getRelationValue() instanceof IFieldDescriptor)
672 descriptorSet.add(((IFieldDescriptor)((RelationQualifier)qualifier).getRelationValue()).getEntityDescriptor());
673 return descriptorSet;
674 }
675 }
676
677
678 /***
679 * Parser for CompositeQualifiers. Creates the necessary sql query
680 */
681 public static class CompositeQualifierParser implements IQualifierParser
682 {
683
684 /***
685 * Processes the qualifier and creates the necessary SQL query
686 *
687 * @param qualifier The qualifier constituting the condition
688 * @param sql The Toolkit containing all data about the conversion
689 * @param values An ArrayList with all data needed to be set in the PreparedStatement
690 * @return Returns a string with the sql query
691 */
692 public String process(Qualifier qualifier, SQLToolKitPS sql, ArrayList values)
693 {
694 if(qualifier==null || ((CompositeQualifier)qualifier).getQualifierCount()<=0)
695 return null;
696
697 StringBuffer buf = new StringBuffer(500);
698 buf.append('(');
699 buf.append(sql.buildWhereExpresion(((CompositeQualifier)qualifier).getQualifier(0), values));
700 for(int j=1; j<((CompositeQualifier)qualifier).getQualifierCount(); j++)
701 {
702 if(((CompositeQualifier)qualifier).getUnionType()==CompositeQualifier.INTERSECTION)
703 buf.append(" AND ");
704 else
705 buf.append(" OR ");
706 buf.append(sql.buildWhereExpresion(((CompositeQualifier)qualifier).getQualifier(j), values));
707 }
708 buf.append(')');
709
710 return buf.toString();
711 }
712
713 /***
714 * States what descriptors are needed for the FROM expression
715 *
716 * @param qualifier The qualifier constituting the condition
717 * @param sql The toolkit containinig the overall data for the expressionbuilding
718 * @return Returns a set of FieldDescriptor needed to be in the FROM sections of the sql expression.
719 */
720 public Set stateDescriptorRequirement(Qualifier qualifier, SQLToolKitPS sql)
721 {
722 Set descriptorSet = new HashSet();
723 for(int j=0; j<((CompositeQualifier)qualifier).getQualifierCount(); j++)
724 descriptorSet.addAll(sql.getQualifierDescriptorSet(((CompositeQualifier)qualifier).getQualifier(j)));
725 return descriptorSet;
726 }
727 }
728
729 public static class NegateQualifierParser
730 {
731 public String process(Qualifier qualifier, SQLToolKitPS sql, ArrayList values)
732 {
733 if(((NegateQualifier)qualifier).getNegatedQualifier()==null)
734 return null;
735 else
736 return "NOT "+sql.buildWhereExpresion(((NegateQualifier)qualifier).getNegatedQualifier(), values);
737 }
738
739 public Set stateDescriptorRequirement(Qualifier qualifier, SQLToolKitPS sql)
740 {
741 if(((NegateQualifier)qualifier).getNegatedQualifier()!=null)
742 return sql.getQualifierDescriptorSet(((NegateQualifier)qualifier).getNegatedQualifier());
743 else
744 return null;
745 }
746 }
747
748 public static class BooleanCharTypeConverter implements IDataTypeConverter
749 {
750 private static final Character DEFAULT_TRUE_CHARACTER = new Character('t');
751 private static final Character DEFAULT_FALSE_CHARACTER = new Character('f');
752 private static final String DEFAULT_ACCEPTED_TRUE_CHARS = "tT1yY";
753
754 private Character mTrueCharacter;
755 private Character mFalseCharacter;
756 private String mAcceptedTrueChars;
757
758 public BooleanCharTypeConverter()
759 {
760 mTrueCharacter = DEFAULT_TRUE_CHARACTER;
761 mFalseCharacter = DEFAULT_FALSE_CHARACTER;
762 mAcceptedTrueChars = DEFAULT_ACCEPTED_TRUE_CHARS;
763 }
764
765 public BooleanCharTypeConverter(char trueChar, char falseChar)
766 {
767 this(trueChar, falseChar, DEFAULT_ACCEPTED_TRUE_CHARS);
768 }
769
770 public BooleanCharTypeConverter(char trueChar, char falseChar,
771 String acceptedTrueChars)
772 {
773 mTrueCharacter = new Character(trueChar);
774 mFalseCharacter = new Character(falseChar);
775
776 if ( acceptedTrueChars != null )
777 mAcceptedTrueChars = acceptedTrueChars;
778 else
779 mAcceptedTrueChars = "" + mTrueCharacter;
780
781 if ( acceptedTrueChars.indexOf(mTrueCharacter.charValue()) < 0 )
782 acceptedTrueChars = mTrueCharacter + acceptedTrueChars;
783 }
784
785 public Object convertToDB(Object data)
786 {
787 if(!(data instanceof Boolean))
788 data = DataType.BOOLEAN.convertFrom(data);
789 if(data==null)
790 return null;
791 else
792 return ((Boolean)data).booleanValue() ? "\'" + mTrueCharacter + "\'": "\'" + mFalseCharacter + "\'";
793 }
794
795 public Object convertFromDB(Object data)
796 {
797 if (data instanceof String && ((String) data).length()==1)
798 data = new Character(((String) data).charAt(0));
799 if (data instanceof Character)
800 {
801 Character characterData = (Character) data;
802 if (characterData == mFalseCharacter)
803 {
804 data = new Boolean(false);
805 }
806 else
807 {
808 data = new Boolean(mAcceptedTrueChars.indexOf((characterData).charValue()) >= 0);
809 }
810 }
811 else if(!(data instanceof Boolean))
812 {
813 data = DataType.BOOLEAN.convertFrom(data);
814 }
815
816 return data;
817 }
818 }
819
820
821 public static class BooleanTypeConverter implements IDataTypeConverter
822 {
823 public Object convertToDB(Object data)
824 {
825 if(!(data instanceof Boolean))
826 data = DataType.BOOLEAN.convertFrom(data);
827 if(data==null)
828 return null;
829 else
830 return ((Boolean)data).booleanValue() ? "1" : "0";
831 }
832
833 public Object convertFromDB(Object data)
834 {
835 if(!(data instanceof Boolean))
836 data = DataType.BOOLEAN.convertFrom(data);
837 return data;
838 }
839 }
840
841
842 public static class DateTypeConverter implements IDataTypeConverter
843 {
844 private DateFormat mDateFormat = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss''");
845
846 public Object convertToDB(Object data)
847 {
848 if(!(data instanceof Date))
849 data = DataType.DATE.convertFrom(data);
850 if(data==null)
851 return null;
852 else
853 return mDateFormat.format((Date)data);
854 }
855
856 public Object convertFromDB(Object data)
857 {
858 if(data instanceof Timestamp)
859 data = new Date(((Timestamp)data).getTime());
860 if(!(data instanceof Date))
861 data = DataType.DATE.convertFrom(data);
862 return data;
863 }
864 }
865
866
867
868 public static interface IDataTypeConverter
869 {
870 public Object convertToDB(Object data);
871 public Object convertFromDB(Object data);
872 }
873
874
875 public static class StringTypeConverter implements IDataTypeConverter
876 {
877
878 private boolean mDoTrim;
879
880
881 public StringTypeConverter()
882 {
883 this(true);
884 }
885
886 public StringTypeConverter(boolean trim)
887 {
888 mDoTrim = trim;
889 }
890
891
892 public Object convertToDB(Object data)
893 {
894 String text = (String)data;
895 StringBuffer buf = new StringBuffer(text.length()+20);
896 buf.append('\'');
897
898 int prevIndex = 0;
899 int index = text.indexOf('\'');
900 while(index>=0)
901 {
902 buf.append(text.substring(prevIndex, index));
903 buf.append('\'');
904 prevIndex = index;
905 index = text.indexOf('\'', index+1);
906 }
907 buf.append(text.substring(prevIndex));
908
909 buf.append('\'');
910 return buf.toString();
911 }
912
913 public Object convertFromDB(Object data)
914 {
915 if(data==null)
916 return null;
917 else if(!(data instanceof String))
918 data = data.toString();
919
920 if(mDoTrim)
921 data = ((String)data).trim();
922
923 return data;
924 }
925 }
926
927
928
929
930
931 }