lafcadio 0.4.3 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/bin/lafcadio_schema +28 -0
  2. data/lib/lafcadio.rb +3 -4
  3. data/lib/lafcadio.rb~ +3 -4
  4. data/lib/lafcadio/TestSuite.rb +2 -0
  5. data/lib/lafcadio/TestSuite.rb~ +16 -0
  6. data/lib/lafcadio/dateTime.rb +93 -2
  7. data/lib/lafcadio/{dateTime/Month.rb → dateTime.rb~} +33 -33
  8. data/lib/lafcadio/depend.rb +3 -0
  9. data/lib/lafcadio/domain.rb +574 -70
  10. data/lib/lafcadio/domain.rb~ +570 -70
  11. data/lib/lafcadio/mock.rb +92 -2
  12. data/lib/lafcadio/mock.rb~ +93 -0
  13. data/lib/lafcadio/objectField.rb +614 -3
  14. data/lib/lafcadio/objectField.rb~ +618 -0
  15. data/lib/lafcadio/objectStore.rb +662 -19
  16. data/lib/lafcadio/objectStore.rb~ +746 -0
  17. data/lib/lafcadio/query.rb +415 -31
  18. data/lib/lafcadio/query.rb~ +572 -0
  19. data/lib/lafcadio/schema.rb +57 -2
  20. data/lib/lafcadio/test.rb +17 -2
  21. data/lib/lafcadio/{test/LafcadioTestCase.rb → test.rb~} +5 -5
  22. data/lib/lafcadio/test/testconfig.dat +1 -1
  23. data/lib/lafcadio/util.rb +337 -20
  24. metadata +16 -77
  25. data/lib/lafcadio/domain/DomainObject.rb +0 -375
  26. data/lib/lafcadio/domain/DomainObject.rb~ +0 -371
  27. data/lib/lafcadio/domain/MapObject.rb +0 -22
  28. data/lib/lafcadio/domain/ObjectType.rb +0 -80
  29. data/lib/lafcadio/includer.rb +0 -18
  30. data/lib/lafcadio/mock/MockDbBridge.rb +0 -78
  31. data/lib/lafcadio/mock/MockDbBridge.rb~ +0 -74
  32. data/lib/lafcadio/mock/MockObjectStore.rb +0 -20
  33. data/lib/lafcadio/objectField/AutoIncrementField.rb +0 -25
  34. data/lib/lafcadio/objectField/BooleanField.rb +0 -83
  35. data/lib/lafcadio/objectField/DateField.rb +0 -33
  36. data/lib/lafcadio/objectField/DateTimeField.rb +0 -25
  37. data/lib/lafcadio/objectField/DecimalField.rb +0 -41
  38. data/lib/lafcadio/objectField/EmailField.rb +0 -28
  39. data/lib/lafcadio/objectField/EnumField.rb +0 -62
  40. data/lib/lafcadio/objectField/FieldValueError.rb +0 -4
  41. data/lib/lafcadio/objectField/IntegerField.rb +0 -15
  42. data/lib/lafcadio/objectField/LinkField.rb +0 -92
  43. data/lib/lafcadio/objectField/LinkField.rb~ +0 -86
  44. data/lib/lafcadio/objectField/MoneyField.rb +0 -13
  45. data/lib/lafcadio/objectField/MonthField.rb +0 -16
  46. data/lib/lafcadio/objectField/ObjectField.rb +0 -142
  47. data/lib/lafcadio/objectField/PasswordField.rb +0 -29
  48. data/lib/lafcadio/objectField/StateField.rb +0 -13
  49. data/lib/lafcadio/objectField/SubsetLinkField.rb +0 -25
  50. data/lib/lafcadio/objectField/TextField.rb +0 -23
  51. data/lib/lafcadio/objectField/TextListField.rb +0 -21
  52. data/lib/lafcadio/objectField/TimeStampField.rb +0 -15
  53. data/lib/lafcadio/objectStore/Cache.rb +0 -81
  54. data/lib/lafcadio/objectStore/Committer.rb +0 -65
  55. data/lib/lafcadio/objectStore/CouldntMatchObjectTypeError.rb +0 -4
  56. data/lib/lafcadio/objectStore/DbBridge.rb +0 -140
  57. data/lib/lafcadio/objectStore/DbBridge.rb~ +0 -140
  58. data/lib/lafcadio/objectStore/DomainComparable.rb +0 -25
  59. data/lib/lafcadio/objectStore/DomainObjectInitError.rb +0 -9
  60. data/lib/lafcadio/objectStore/DomainObjectNotFoundError.rb +0 -4
  61. data/lib/lafcadio/objectStore/DomainObjectProxy.rb +0 -62
  62. data/lib/lafcadio/objectStore/DomainObjectSqlMaker.rb +0 -74
  63. data/lib/lafcadio/objectStore/ObjectStore.rb +0 -207
  64. data/lib/lafcadio/objectStore/ObjectStore.rb~ +0 -207
  65. data/lib/lafcadio/objectStore/SqlValueConverter.rb +0 -30
  66. data/lib/lafcadio/objectStore/SqlValueConverter.rb~ +0 -30
  67. data/lib/lafcadio/query/Compare.rb +0 -55
  68. data/lib/lafcadio/query/CompoundCondition.rb +0 -39
  69. data/lib/lafcadio/query/Condition.rb +0 -66
  70. data/lib/lafcadio/query/Condition.rb~ +0 -66
  71. data/lib/lafcadio/query/Equals.rb +0 -45
  72. data/lib/lafcadio/query/In.rb +0 -20
  73. data/lib/lafcadio/query/Like.rb +0 -48
  74. data/lib/lafcadio/query/Link.rb +0 -20
  75. data/lib/lafcadio/query/Max.rb +0 -32
  76. data/lib/lafcadio/query/Max.rb~ +0 -25
  77. data/lib/lafcadio/query/Not.rb +0 -21
  78. data/lib/lafcadio/query/Query.rb +0 -92
  79. data/lib/lafcadio/schema/CreateTableStatement.rb +0 -61
  80. data/lib/lafcadio/schema/CreateTableStatement.rb~ +0 -59
  81. data/lib/lafcadio/util/Context.rb +0 -61
  82. data/lib/lafcadio/util/ContextualService.rb +0 -33
  83. data/lib/lafcadio/util/English.rb +0 -117
  84. data/lib/lafcadio/util/HashOfArrays.rb +0 -48
  85. data/lib/lafcadio/util/LafcadioConfig.rb +0 -25
  86. data/lib/lafcadio/util/QueueHash.rb +0 -67
  87. data/lib/lafcadio/util/UsStates.rb +0 -29
  88. data/lib/lafcadio/xml.rb +0 -2
@@ -0,0 +1,572 @@
1
+ # = Overview
2
+ # By passing a block to ObjectStore, you can write complex, ad-hoc queries in
3
+ # Ruby. This involves a few more keystrokes than writing raw SQL, but also makes
4
+ # it easier to change queries at runtime, and these queries can also be fully
5
+ # tested against the MockObjectStore.
6
+ # big_invoices = object_store.getInvoices { |inv| inv.rate.gt( 50 ) }
7
+ # # => "select * from invoices where rate > 50"
8
+ # This a full-fledged block, so you can pass in values from the calling context.
9
+ # date = Date.new( 2004, 1, 1 )
10
+ # recent_invoices = object_store.getInvoices { |inv| inv.date.gt( date ) }
11
+ # # => "select * from invoices where date > '2004-01-01'"
12
+ #
13
+ # = Query operators
14
+ # You can compare fields either to simple values, or to other fields in the same
15
+ # table.
16
+ # paid_immediately = object_store.getInvoices { |inv|
17
+ # inv.date.equals( inv.paid )
18
+ # }
19
+ # # => "select * from invoices where date = paid"
20
+ #
21
+ # == Numerical comparisons: +lt+, +lte+, +gte+, +gt+
22
+ # +lt+, +lte+, +gte+, and +gt+ stand for "less than", "less than or equal",
23
+ # "greater than or equal", and "greater than", respectively.
24
+ # tiny_invoices = object_store.getInvoices { |inv| inv.rate.lte( 25 ) }
25
+ # # => "select * from invoices where rate <= 25"
26
+ # These comparators work on fields that contain numbers, dates, and even
27
+ # references to other domain objects.
28
+ # for_1st_ten_clients = object_store.getInvoices { |inv|
29
+ # inv.client.lte( 10 )
30
+ # }
31
+ # # => "select * from invoices where client <= 10"
32
+ #
33
+ # == Equality: +equals+
34
+ # full_week_invs = object_store.getInvoices { |inv| inv.hours.equals( 40 ) }
35
+ # # => "select * from invoices where hours = 40"
36
+ # If you're comparing to a domain object you should pass in the object itself.
37
+ # client = object_store.getClient( 99 )
38
+ # invoices = object_store.getInvoices { |inv| inv.client.equals( client ) }
39
+ # # => "select * from invoices where client = 99"
40
+ #
41
+ # == Inclusion: +in+
42
+ # first_three_invs = object_store.getInvoices { |inv| inv.pk_id.in( 1, 2, 3 ) }
43
+ # # => "select * from invoices where pk_id in ( 1, 2, 3 )"
44
+ #
45
+ # == Text comparison: +like+
46
+ # fname_starts_with_a = object_store.getUsers { |user|
47
+ # user.fname.like( /^a/ )
48
+ # }
49
+ # # => "select * from users where fname like 'a%'"
50
+ # fname_ends_with_a = object_store.getUsers { |user|
51
+ # user.fname.like( /a$/ )
52
+ # }
53
+ # # => "select * from users where fname like '%a'"
54
+ # fname_contains_a = object_store.getUsers { |user|
55
+ # user.fname.like( /a/ )
56
+ # }
57
+ # # => "select * from users where fname like '%a%'"
58
+ # Please note that although we're using the Regexp operators here, these aren't
59
+ # full-fledged regexps. Only ^ and $ work for this.
60
+ #
61
+ # == Compound conditions: <tt>Query.And</tt> and <tt>Query.Or</tt>
62
+ # invoices = object_store.getInvoices { |inv|
63
+ # Query.And( inv.hours.equals( 40 ), inv.rate.equals( 50 ) )
64
+ # }
65
+ # # => "select * from invoices where (hours = 40 and rate = 50)"
66
+ # client99 = object_store.getClient( 99 )
67
+ # invoices = object_store.getInvoices { |inv|
68
+ # Query.Or( inv.hours.equals( 40 ),
69
+ # inv.rate.equals( 50 ),
70
+ # inv.client.equals( client99 ) )
71
+ # }
72
+ # # => "select * from invoices where (hours = 40 or rate = 50 or client = 99)"
73
+ # Note that both compound operators can take 2 or more arguments. Also, they can
74
+ # be nested:
75
+ # invoices = object_store.getInvoices { |inv|
76
+ # Query.And( inv.hours.equals( 40 ),
77
+ # Query.Or( inv.rate.equals( 50 ),
78
+ # inv.client.equals( client99 ) ) )
79
+ # }
80
+ # # => "select * from invoices where (hours = 40 and
81
+ # # (rate = 50 or client = 99))"
82
+ #
83
+ # == Negation: +not+
84
+ # invoices = object_store.getInvoices { |inv| inv.rate.equals( 50 ).not }
85
+ # # => "select * from invoices where rate != 50"
86
+
87
+ module Lafcadio
88
+ class Query
89
+ def self.And( *conditions ); CompoundCondition.new( *conditions ); end
90
+
91
+ def self.infer( domain_class, &action )
92
+ inferrer = Query::Inferrer.new( domain_class ) { |obj|
93
+ action.call( obj )
94
+ }
95
+ inferrer.execute
96
+ end
97
+
98
+ def self.Or( *conditions )
99
+ conditions << CompoundCondition::OR
100
+ CompoundCondition.new( *conditions)
101
+ end
102
+
103
+ ASC = 1
104
+ DESC = 2
105
+
106
+ attr_reader :object_type, :condition
107
+ attr_accessor :order_by, :order_by_order, :limit
108
+
109
+ def initialize(object_type, pk_idOrCondition = nil)
110
+ @object_type = object_type
111
+ ( @condition, @order_by, @limit ) = [ nil, nil, nil ]
112
+ if pk_idOrCondition
113
+ if pk_idOrCondition.class <= Condition
114
+ @condition = pk_idOrCondition
115
+ else
116
+ @condition = Query::Equals.new( object_type.sql_primary_key_name,
117
+ pk_idOrCondition, object_type )
118
+ end
119
+ end
120
+ @order_by_order = ASC
121
+ end
122
+
123
+ def and( &action ); compound( CompoundCondition::AND, action ); end
124
+
125
+ def compound( comp_type, action )
126
+ rquery = Query.infer( @object_type ) { |dobj| action.call( dobj ) }
127
+ comp_cond = Query::CompoundCondition.new( @condition, rquery.condition,
128
+ comp_type )
129
+ comp_cond.query
130
+ end
131
+
132
+ def eql?( other ); other.class <= Query && other.to_sql == to_sql; end
133
+
134
+ def fields; '*'; end
135
+
136
+ def hash; to_sql.hash; end
137
+
138
+ def limit_clause
139
+ "limit #{ @limit.begin }, #{ @limit.end - @limit.begin + 1 }" if @limit
140
+ end
141
+
142
+ def or( &action ); compound( CompoundCondition::OR, action ); end
143
+
144
+ def order_clause
145
+ if @order_by
146
+ clause = "order by #{ @order_by } "
147
+ clause += @order_by_order == ASC ? 'asc' : 'desc'
148
+ clause
149
+ end
150
+ end
151
+
152
+ def sql_primary_key_field(object_type)
153
+ "#{ object_type.table_name }.#{ object_type.sql_primary_key_name }"
154
+ end
155
+
156
+ def tables
157
+ concrete_classes = object_type.self_and_concrete_superclasses.reverse
158
+ table_names = concrete_classes.collect { |domain_class|
159
+ domain_class.table_name
160
+ }
161
+ table_names.join( ', ' )
162
+ end
163
+
164
+ def to_sql
165
+ clauses = [ "select #{ fields }", "from #{ tables }" ]
166
+ clauses << where_clause if where_clause
167
+ clauses << order_clause if order_clause
168
+ clauses << limit_clause if limit_clause
169
+ clauses.join ' '
170
+ end
171
+
172
+ def where_clause
173
+ concrete_classes = object_type.self_and_concrete_superclasses.reverse
174
+ where_clauses = []
175
+ concrete_classes.each_with_index { |domain_class, i|
176
+ if i < concrete_classes.size - 1
177
+ join_clause = sql_primary_key_field( domain_class ) + ' = ' +
178
+ sql_primary_key_field( concrete_classes[i+1] )
179
+ where_clauses << join_clause
180
+ else
181
+ where_clauses << @condition.to_sql if @condition
182
+ end
183
+ }
184
+ where_clauses.size > 0 ? 'where ' + where_clauses.join( ' and ' ) : nil
185
+ end
186
+
187
+ class Condition #:nodoc:
188
+ def Condition.search_term_type
189
+ Object
190
+ end
191
+
192
+ attr_reader :object_type
193
+
194
+ def initialize(fieldName, searchTerm, object_type)
195
+ @fieldName = fieldName
196
+ @searchTerm = searchTerm
197
+ unless @searchTerm.class <= self.class.search_term_type
198
+ raise "Incorrect searchTerm type #{ searchTerm.class }"
199
+ end
200
+ @object_type = object_type
201
+ if @object_type
202
+ unless @object_type <= DomainObject
203
+ raise "Incorrect object type #{ @object_type.to_s }"
204
+ end
205
+ end
206
+ end
207
+
208
+ def db_field_name; get_field.db_table_and_field_name; end
209
+
210
+ def get_field
211
+ anObjectType = @object_type
212
+ field = nil
213
+ while (anObjectType < DomainObject || anObjectType < DomainObject) &&
214
+ !field
215
+ field = anObjectType.get_class_field( @fieldName ) ||
216
+ anObjectType.get_class_field_by_db_name( @fieldName )
217
+ anObjectType = anObjectType.superclass
218
+ end
219
+ if field
220
+ field
221
+ else
222
+ errStr = "Couldn't find field \"#{ @fieldName }\" in " +
223
+ "#{ @object_type } domain class"
224
+ raise( MissingError, errStr, caller )
225
+ end
226
+ end
227
+
228
+ def query; Query.new( @object_type, self ); end
229
+
230
+ def not
231
+ Query::Not.new( self )
232
+ end
233
+
234
+ def primary_key_field?
235
+ [ @object_type.sql_primary_key_name, 'pk_id' ].include?( @fieldName )
236
+ end
237
+ end
238
+
239
+ class Compare < Condition #:nodoc:
240
+ LESS_THAN = 1
241
+ LESS_THAN_OR_EQUAL = 2
242
+ GREATER_THAN_OR_EQUAL = 3
243
+ GREATER_THAN = 4
244
+
245
+ @@comparators = {
246
+ LESS_THAN => '<',
247
+ LESS_THAN_OR_EQUAL => '<=',
248
+ GREATER_THAN_OR_EQUAL => '>=',
249
+ GREATER_THAN => '>'
250
+ }
251
+
252
+ @@mockComparators = {
253
+ LESS_THAN => Proc.new { |d1, d2| d1 < d2 },
254
+ LESS_THAN_OR_EQUAL => Proc.new { |d1, d2| d1 <= d2 },
255
+ GREATER_THAN_OR_EQUAL => Proc.new { |d1, d2| d1 >= d2 },
256
+ GREATER_THAN => Proc.new { |d1, d2| d1 > d2 }
257
+ }
258
+
259
+ def initialize(fieldName, searchTerm, object_type, compareType)
260
+ super fieldName, searchTerm, object_type
261
+ @compareType = compareType
262
+ end
263
+
264
+ def to_sql
265
+ if ( get_field.kind_of?( LinkField ) &&
266
+ !@searchTerm.respond_to?( :pk_id ) )
267
+ search_val = @searchTerm.to_s
268
+ else
269
+ search_val = get_field.value_for_sql( @searchTerm ).to_s
270
+ end
271
+ "#{ db_field_name } #{ @@comparators[@compareType] } " + search_val
272
+ end
273
+
274
+ def object_meets(anObj)
275
+ value = anObj.send @fieldName
276
+ value = value.pk_id if value.class <= DomainObject
277
+ if value
278
+ @@mockComparators[@compareType].call(value, @searchTerm)
279
+ else
280
+ false
281
+ end
282
+ end
283
+ end
284
+
285
+ class CompoundCondition < Condition #:nodoc:
286
+ AND = 1
287
+ OR = 2
288
+
289
+ def initialize(*conditions)
290
+ if( [ AND, OR ].index(conditions.last) )
291
+ @compoundType = conditions.last
292
+ conditions.pop
293
+ else
294
+ @compoundType = AND
295
+ end
296
+ @conditions = conditions
297
+ @object_type = conditions[0].object_type
298
+ end
299
+
300
+ def object_meets(anObj)
301
+ if @compoundType == AND
302
+ @conditions.inject( true ) { |result, cond|
303
+ result && cond.object_meets( anObj )
304
+ }
305
+ else
306
+ @conditions.inject( false ) { |result, cond|
307
+ result || cond.object_meets( anObj )
308
+ }
309
+ end
310
+ end
311
+
312
+ def to_sql
313
+ booleanString = @compoundType == AND ? 'and' : 'or'
314
+ subSqlStrings = @conditions.collect { |cond| cond.to_sql }
315
+ "(#{ subSqlStrings.join(" #{ booleanString } ") })"
316
+ end
317
+ end
318
+
319
+ class DomainObjectImpostor #:nodoc:
320
+ attr_reader :domain_class
321
+
322
+ def initialize( domain_class )
323
+ @domain_class = domain_class
324
+ end
325
+
326
+ def method_missing( methId, *args )
327
+ fieldName = methId.id2name
328
+ begin
329
+ classField = @domain_class.get_field( fieldName )
330
+ ObjectFieldImpostor.new( self, classField )
331
+ rescue MissingError
332
+ super( methId, *args )
333
+ end
334
+ end
335
+ end
336
+
337
+ class Equals < Condition #:nodoc:
338
+ def r_val_string
339
+ field = get_field
340
+ if @searchTerm.class <= ObjectField
341
+ @searchTerm.db_table_and_field_name
342
+ else
343
+ field.value_for_sql(@searchTerm).to_s
344
+ end
345
+ end
346
+
347
+ def object_meets(anObj)
348
+ if @searchTerm.class <= ObjectField
349
+ compare_value = anObj.send( @searchTerm.name )
350
+ else
351
+ compare_value = @searchTerm
352
+ end
353
+ compare_value == anObj.send( @fieldName )
354
+ end
355
+
356
+ def to_sql
357
+ sql = "#{ db_field_name } "
358
+ unless @searchTerm.nil?
359
+ sql += "= " + r_val_string
360
+ else
361
+ sql += "is null"
362
+ end
363
+ sql
364
+ end
365
+ end
366
+
367
+ class In < Condition #:nodoc:
368
+ def self.search_term_type
369
+ Array
370
+ end
371
+
372
+ def object_meets(anObj)
373
+ value = anObj.send @fieldName
374
+ @searchTerm.index(value) != nil
375
+ end
376
+
377
+ def to_sql
378
+ "#{ db_field_name } in (#{ @searchTerm.join(', ') })"
379
+ end
380
+ end
381
+
382
+ class Inferrer #:nodoc:
383
+ def initialize( domain_class, &action )
384
+ @domain_class = domain_class; @action = action
385
+ end
386
+
387
+ def execute
388
+ impostor = DomainObjectImpostor.new( @domain_class )
389
+ condition = @action.call( impostor )
390
+ query = Query.new( @domain_class, condition )
391
+ end
392
+ end
393
+
394
+ class Like < Condition #:nodoc:
395
+ PRE_AND_POST = 1
396
+ PRE_ONLY = 2
397
+ POST_ONLY = 3
398
+
399
+ def initialize(
400
+ fieldName, searchTerm, object_type, matchType = PRE_AND_POST)
401
+ super fieldName, searchTerm, object_type
402
+ @matchType = matchType
403
+ end
404
+
405
+ def get_regexp
406
+ if @matchType == PRE_AND_POST
407
+ Regexp.new(@searchTerm)
408
+ elsif @matchType == PRE_ONLY
409
+ Regexp.new(@searchTerm.to_s + "$")
410
+ elsif @matchType == POST_ONLY
411
+ Regexp.new("^" + @searchTerm)
412
+ end
413
+ end
414
+
415
+ def object_meets(anObj)
416
+ value = anObj.send @fieldName
417
+ if value.class <= DomainObject || value.class == DomainObjectProxy
418
+ value = value.pk_id.to_s
419
+ end
420
+ if value.class <= Array
421
+ (value.index(@searchTerm) != nil)
422
+ else
423
+ get_regexp.match(value) != nil
424
+ end
425
+ end
426
+
427
+ def to_sql
428
+ withWildcards = @searchTerm
429
+ if @matchType == PRE_AND_POST
430
+ withWildcards = "%" + withWildcards + "%"
431
+ elsif @matchType == PRE_ONLY
432
+ withWildcards = "%" + withWildcards
433
+ elsif @matchType == POST_ONLY
434
+ withWildcards += "%"
435
+ end
436
+ "#{ db_field_name } like '#{ withWildcards }'"
437
+ end
438
+ end
439
+
440
+ class Link < Condition #:nodoc:
441
+ def initialize( fieldName, searchTerm, object_type )
442
+ if searchTerm.pk_id.nil?
443
+ raise ArgumentError,
444
+ "Can't query using an uncommitted domain object as a search term",
445
+ caller
446
+ else
447
+ super( fieldName, searchTerm, object_type )
448
+ end
449
+ end
450
+
451
+ def self.search_term_type
452
+ DomainObject
453
+ end
454
+
455
+ def object_meets(anObj)
456
+ value = anObj.send @fieldName
457
+ value ? value.pk_id == @searchTerm.pk_id : false
458
+ end
459
+
460
+ def to_sql
461
+ "#{ db_field_name } = #{ @searchTerm.pk_id }"
462
+ end
463
+ end
464
+
465
+ class Max < Query #:nodoc:
466
+ attr_reader :field_name
467
+
468
+ def initialize( object_type, field_name = 'pk_id' )
469
+ super( object_type )
470
+ @field_name = field_name
471
+ end
472
+
473
+ def collect( coll )
474
+ max = coll.inject( nil ) { |max, d_obj|
475
+ a_value = d_obj.send( @field_name )
476
+ ( max.nil? || a_value > max ) ? a_value : max
477
+ }
478
+ [ max ]
479
+ end
480
+
481
+ def fields
482
+ "max(#{ @object_type.get_field( @field_name ).db_field_name })"
483
+ end
484
+ end
485
+
486
+ class Not < Condition #:nodoc:
487
+ def initialize(unCondition)
488
+ @unCondition = unCondition
489
+ end
490
+
491
+ def object_meets(obj)
492
+ !@unCondition.object_meets(obj)
493
+ end
494
+
495
+ def object_type; @unCondition.object_type; end
496
+
497
+ def to_sql
498
+ "!(#{ @unCondition.to_sql })"
499
+ end
500
+ end
501
+
502
+ class ObjectFieldImpostor #:nodoc:
503
+ def self.comparators
504
+ {
505
+ 'lt' => Compare::LESS_THAN, 'lte' => Compare::LESS_THAN_OR_EQUAL,
506
+ 'gte' => Compare::GREATER_THAN_OR_EQUAL,
507
+ 'gt' => Compare::GREATER_THAN
508
+ }
509
+ end
510
+
511
+ attr_reader :class_field
512
+
513
+ def initialize( domainObjectImpostor, class_field_or_name )
514
+ @domainObjectImpostor = domainObjectImpostor
515
+ if class_field_or_name == 'pk_id'
516
+ @db_field_name = 'pk_id'
517
+ else
518
+ @class_field = class_field_or_name
519
+ @db_field_name = class_field_or_name.db_field_name
520
+ end
521
+ end
522
+
523
+ def method_missing( methId, *args )
524
+ methodName = methId.id2name
525
+ if !ObjectFieldImpostor.comparators.keys.index( methodName ).nil?
526
+ register_compare_condition( methodName, *args )
527
+ else
528
+ super( methId, *args )
529
+ end
530
+ end
531
+
532
+ def register_compare_condition( compareStr, searchTerm)
533
+ compareVal = ObjectFieldImpostor.comparators[compareStr]
534
+ Compare.new( @db_field_name, searchTerm,
535
+ @domainObjectImpostor.domain_class, compareVal )
536
+ end
537
+
538
+ def equals( searchTerm )
539
+ Equals.new( @db_field_name, field_or_field_name( searchTerm ),
540
+ @domainObjectImpostor.domain_class )
541
+ end
542
+
543
+ def field_or_field_name( search_term )
544
+ if search_term.class == ObjectFieldImpostor
545
+ search_term.class_field
546
+ else
547
+ search_term
548
+ end
549
+ end
550
+
551
+ def like( regexp )
552
+ if regexp.source =~ /^\^(.*)/
553
+ searchTerm = $1
554
+ matchType = Query::Like::POST_ONLY
555
+ elsif regexp.source =~ /(.*)\$$/
556
+ searchTerm = $1
557
+ matchType = Query::Like::PRE_ONLY
558
+ else
559
+ searchTerm = regexp.source
560
+ matchType = Query::Like::PRE_AND_POST
561
+ end
562
+ Query::Like.new( @db_field_name, searchTerm,
563
+ @domainObjectImpostor.domain_class, matchType )
564
+ end
565
+
566
+ def in( *searchTerms )
567
+ Query::In.new( @db_field_name, searchTerms,
568
+ @domainObjectImpostor.domain_class )
569
+ end
570
+ end
571
+ end
572
+ end