API  0.9.8
 All Classes Files Functions Variables Typedefs Macros Groups Pages
CPPredicateEditorRowTemplate.j
Go to the documentation of this file.
1 /*
2  * CPPredicateEditorRowTemplate.j
3  * AppKit
4  *
5  * Created by cacaodev.
6  * Copyright 2011, cacaodev.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
24 
25 
26 
39 
40 @implementation CPPredicateEditorRowTemplate : CPObject
41 {
42  int _templateType;
43  unsigned _predicateOptions;
44  unsigned _predicateModifier;
45  unsigned _leftAttributeType;
46  unsigned _rightAttributeType;
47  BOOL _leftIsWildcard;
48  BOOL _rightIsWildcard;
49  CPArray _views;
50 
51 }
52 
86 - (id)initWithLeftExpressions:(CPArray)leftExpressions rightExpressions:(CPArray)rightExpressions modifier:(int)modifier operators:(CPArray)operators options:(int)options
87 {
88  self = [super init];
89  if (self != nil)
90  {
91  _templateType = 1;
92  _leftIsWildcard = NO;
93  _rightIsWildcard = NO;
94  _leftAttributeType = 0;
95  _rightAttributeType = 0;
96  _predicateModifier = modifier;
97  _predicateOptions = options;
98 
99  var leftView = [self _viewFromExpressions:leftExpressions],
100  rightView = [self _viewFromExpressions:rightExpressions],
101  middleView = [self _viewFromOperatorTypes:operators];
102 
103  _views = [[CPArray alloc] initWithObjects:leftView, middleView, rightView];
104  }
105 
106  return self;
107 }
108 
118 - (id)initWithLeftExpressions:(CPArray )leftExpressions rightExpressionAttributeType:(CPAttributeType)attributeType modifier:(CPComparisonPredicateModifier)modifier operators:(CPArray )operators options:(int)options
119 {
120  self = [super init];
121  if (self != nil)
122  {
123  var leftView = [self _viewFromExpressions:leftExpressions],
124  middleView = [self _viewFromOperatorTypes:operators],
125  rightView = [self _viewFromAttributeType:attributeType];
126 
127  _templateType = 1;
128  _leftIsWildcard = NO;
129  _rightIsWildcard = YES;
130  _leftAttributeType = 0;
131  _rightAttributeType = attributeType;
132  _predicateModifier = modifier;
133  _predicateOptions = options;
134  _views = [[CPArray alloc] initWithObjects:leftView, middleView, rightView];
135  }
136 
137  return self;
138 }
139 
146 - (id)initWithCompoundTypes:(CPArray )compoundTypes
147 {
148  self = [super init];
149  if (self != nil)
150  {
151  var leftView = [self _viewFromCompoundTypes:compoundTypes],
152  rightView = [[CPPopUpButton alloc] init];
153 
154  [rightView addItemWithTitle:@"of the following are true"];
155 
156  _templateType = 2;
157  _leftIsWildcard = NO;
158  _rightIsWildcard = NO;
159  _rightAttributeType = 0;
160  _views = [[CPArray alloc] initWithObjects:leftView, rightView];
161  }
162  return self;
163 }
164 
175 - (double)matchForPredicate:(CPPredicate)predicate
176 {
177  // How exactly this value (float 0-1) is computed ?
178  if ([self _templateType] == 2 && [predicate isKindOfClass:[CPCompoundPredicate class]])
179  {
180  if ([[self compoundTypes] containsObject:[predicate compoundPredicateType]])
181  return 1;
182  }
183  else if ([self _templateType] == 1 && [predicate isKindOfClass:[CPComparisonPredicate class]])
184  {
185  if (!_leftIsWildcard && ![[self leftExpressions] containsObject:[predicate leftExpression]])
186  return 0;
187 
188  if (![[self operators] containsObject:[predicate predicateOperatorType]])
189  return 0;
190 
191  if (!_rightIsWildcard && ![[self rightExpressions] containsObject:[predicate rightExpression]])
192  return 0;
193 
194  return 1;
195  }
196 
197  return 0;
198 }
199 
205 - (CPArray)templateViews
206 {
207  return _views;
208 }
209 
217 - (void)setPredicate:(CPPredicate)predicate
218 {
219  if (_templateType == 2)
220  [self _setCompoundPredicate:predicate];
221  else
222  [self _setComparisonPredicate:predicate];
223 }
224 
231 - (CPArray)displayableSubpredicatesOfPredicate:(CPPredicate)predicate
232 {
233  if ([predicate isKindOfClass:[CPCompoundPredicate class]])
234  {
235  var subpredicates = [predicate subpredicates];
236  if ([subpredicates count] == 0)
237  return nil;
238 
239  return subpredicates;
240  }
241 
242  return nil;
243 }
244 
253 - (CPPredicate)predicateWithSubpredicates:(CPArray)subpredicates
254 {
255  if (_templateType == 2)
256  {
257  var type = [[_views[0] selectedItem] representedObject];
258  return [[CPCompoundPredicate alloc] initWithType:type subpredicates:subpredicates];
259  }
260 
261  if (_templateType == 1)
262  {
263  var lhs = [self _leftExpression],
264  rhs = [self _rightExpression],
265  operator = [[_views[1] selectedItem] representedObject];
266 
268  rightExpression:rhs
269  modifier:[self modifier]
270  type:operator
271  options:[self options]];
272  }
273 
274  return nil;
275 }
276 
285 - (CPArray)leftExpressions
286 {
287  if (_templateType == 1 && !_leftIsWildcard)
288  {
289  var view = [_views objectAtIndex:0];
290  return [[view itemArray] valueForKey:@"representedObject"];
291  }
292 
293  return nil;
294 }
295 
300 - (CPArray)rightExpressions
301 {
302  if (_templateType == 1 && !_rightIsWildcard)
303  {
304  var view = [_views objectAtIndex:2];
305  return [[view itemArray] valueForKey:@"representedObject"];
306  }
307 
308  return nil;
309 }
310 
315 - (CPArray)compoundTypes
316 {
317  if (_templateType == 2)
318  {
319  var view = [_views objectAtIndex:0];
320  return [[view itemArray] valueForKey:@"representedObject"];
321  }
322 
323  return nil;
324 }
325 
330 - (CPComparisonPredicateModifier)modifier
331 {
332  if (_templateType == 1)
333  return _predicateModifier;
334 
335  return nil;
336 }
337 
342 - (CPArray)operators
343 {
344  if (_templateType == 1)
345  {
346  var view = [_views objectAtIndex:1];
347  return [[view itemArray] valueForKey:@"representedObject"];
348  }
349 
350  return nil;
351 }
352 
357 - (int)options
358 {
359  if (_templateType == 1)
360  return _predicateOptions;
361 
362  return nil;
363 }
364 
369 - (CPAttributeType)rightExpressionAttributeType
370 {
371  return _rightAttributeType;
372 }
373 
378 - (CPAttributeType)leftExpressionAttributeType
379 {
380  return _leftAttributeType;
381 }
382 
384 + (id)_bestMatchForPredicate:(CPPredicate)predicate inTemplates:(CPArray)templates quality:(double)quality
385 {
386  var count = [templates count],
387  match_value = 0,
388  templateIndex = CPNotFound,
389  i;
390 
391  for (i = 0; i < count; i++)
392  {
393  var template = [templates objectAtIndex:i],
394  amatch = [template matchForPredicate:predicate];
395 
396  if (amatch > match_value)
397  {
398  templateIndex = i;
399  match_value = amatch;
400  }
401  }
402 
403  if (templateIndex == CPNotFound)
404  {
405  [CPException raise:CPRangeException reason:@"Unable to find template matching predicate: " + [predicate predicateFormat]];
406  return nil;
407  }
408 
409  return [templates objectAtIndex:templateIndex];
410 }
411 
412 - (void)_setCompoundPredicate:(CPCompoundPredicate)predicate
413 {
414  var left = [_views objectAtIndex:0],
415  type = [predicate compoundPredicateType],
416  index = [left indexOfItemWithRepresentedObject:type];
417 
418  [left selectItemAtIndex:index];
419 }
420 
421 - (void)_setComparisonPredicate:(CPComparisonPredicate)predicate
422 {
423  var left = [_views objectAtIndex:0],
424  middle = [_views objectAtIndex:1],
425  right = [_views objectAtIndex:2],
426  leftExpression = [predicate leftExpression],
427  rightExpression = [predicate rightExpression],
428  operator = [predicate predicateOperatorType];
429 
430  if (_leftIsWildcard)
431  [left setObjectValue:[leftExpression constantValue]];
432  else
433  {
434  var index = [left indexOfItemWithRepresentedObject:leftExpression];
435  [left selectItemAtIndex:index];
436  }
437 
438  var op_index = [middle indexOfItemWithRepresentedObject:operator];
439  [middle selectItemAtIndex:op_index];
440 
441  if (_rightIsWildcard)
442  [right setObjectValue:[rightExpression constantValue]];
443  else
444  {
445  var index = [right indexOfItemWithRepresentedObject:rightExpression];
446  [right selectItemAtIndex:index];
447  }
448 }
449 
450 - (CPExpression)_leftExpression
451 {
452  return [self _expressionFromView:_views[0] forAttributeType:_leftAttributeType];
453 }
454 
455 - (CPExpression)_rightExpression
456 {
457  return [self _expressionFromView:_views[2] forAttributeType:_rightAttributeType];
458 }
459 
460 - (CPExpression)_expressionFromView:(CPView)aView forAttributeType:(CPAttributeType)attributeType
461 {
462  if (attributeType == 0)
463  return [[aView selectedItem] representedObject];
464 
465  var value;
466  if (attributeType >= CPInteger16AttributeType && attributeType <= CPFloatAttributeType)
467  value = [aView intValue];
468  else if (attributeType == CPBooleanAttributeType)
469  value = [aView state];
470  else
471  value = [aView stringValue];
472 
473  return [CPExpression expressionForConstantValue:value];
474 }
475 
476 - (int)_rowType
477 {
478  return (_templateType - 1);
479 }
480 
481 - (id)copy
482 {
483  var views = [CPArray array];
484 
485  var copy = [[[self class] alloc] init];
486  [copy _setTemplateType:_templateType];
487  [copy _setOptions:_predicateOptions];
488  [copy _setModifier:_predicateModifier];
489  [copy _setLeftAttributeType:_leftAttributeType];
490  [copy _setRightAttributeType:_rightAttributeType];
491  [copy setLeftIsWildcard:_leftIsWildcard];
492  [copy setRightIsWildcard:_rightIsWildcard];
493 
494  [_views enumerateObjectsUsingBlock:function(aView, idx, stop)
495  {
496  var vcopy;
497 
498  if ([aView implementsSelector:@selector(copy)])
499  {
500  vcopy = [aView copy];
501  }
502  else
503  {
505  }
506 
507  [views addObject:vcopy];
508  }];
509 
510  [copy setTemplateViews:views];
511 
512  return copy;
513 }
514 
515 + (id)_operatorsForAttributeType:(CPAttributeType)attributeType
516 {
517  var operators_array = [CPMutableArray array];
518 
519  switch (attributeType)
520  {
521  case CPInteger16AttributeType : [operators_array addObjects:4,5,0,2,1,3];
522  break;
523  case CPInteger32AttributeType : [operators_array addObjects:4,5,0,2,1,3];
524  break;
525  case CPInteger64AttributeType : [operators_array addObjects:4,5,0,2,1,3];
526  break;
527  case CPDecimalAttributeType : [operators_array addObjects:4,5,0,2,1,3];
528  break;
529  case CPDoubleAttributeType : [operators_array addObjects:4,5,0,2,1,3];
530  break;
531  case CPFloatAttributeType : [operators_array addObjects:4,5,0,2,1,3];
532  break;
533  case CPStringAttributeType : [operators_array addObjects:99,4,5,8,9];
534  break;
535  case CPBooleanAttributeType : [operators_array addObjects:4,5];
536  break;
537  case CPDateAttributeType : [operators_array addObjects:4,5,0,2,1,3];
538  break;
539  default : CPLogConsole("Cannot create operators for an CPAttributeType " + attributeType);
540  break;
541  }
542 
543  return operators_array;
544 }
545 
546 - (int)_templateType
547 {
548  return _templateType;
549 }
550 
551 - (id)_displayValueForPredicateOperator:(int)operator
552 {
553  var value;
554 
555  switch (operator)
556  {
557  case CPLessThanPredicateOperatorType : value = @"is less than";
558  break;
559  case CPLessThanOrEqualToPredicateOperatorType : value = @"is less than or equal to";
560  break;
561  case CPGreaterThanPredicateOperatorType : value = @"is greater than";
562  break;
563  case CPGreaterThanOrEqualToPredicateOperatorType : value = @"is greater than or equal to";
564  break;
565  case CPEqualToPredicateOperatorType : value = @"is";
566  break;
567  case CPNotEqualToPredicateOperatorType : value = @"is not";
568  break;
569  case CPMatchesPredicateOperatorType : value = @"matches";
570  break;
571  case CPLikePredicateOperatorType : value = @"is like";
572  break;
573  case CPBeginsWithPredicateOperatorType : value = @"begins with";
574  break;
575  case CPEndsWithPredicateOperatorType : value = @"ends with";
576  break;
577  case CPInPredicateOperatorType : value = @"in";
578  break;
579  case CPContainsPredicateOperatorType : value = @"contains";
580  break;
581  case CPBetweenPredicateOperatorType : value = @"between";
582  break;
583  default : CPLogConsole(@"unknown predicate operator %d" + operator);
584  }
585 
586  return value;
587 }
588 
589 - (id)_displayValueForCompoundPredicateType:(unsigned int)predicateType
590 {
591  var value;
592  switch (predicateType)
593  {
594  case CPNotPredicateType: value = @"None";
595  break;
596  case CPAndPredicateType: value = @"All";
597  break;
598  case CPOrPredicateType: value = @"Any";
599  break;
600  default : value = [CPString stringWithFormat:@"unknown compound predicate type %d",predicateType];
601  }
602 
603  return value;
604 }
605 
606 - (id)_displayValueForConstantValue:(id)value
607 {
608  return [value description]; // number, date, string, ... localize
609 }
610 
611 - (id)_displayValueForKeyPath:(CPString)keyPath
612 {
613  return keyPath; // localize
614 }
615 
616 - (CPPopUpButton)_viewFromExpressions:(CPArray)expressions
617 {
618  var popup = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0, 0, 100, 18)],
619  count = [expressions count];
620 
621  for (var i = 0; i < count; i++)
622  {
623  var exp = expressions[i],
624  type = [exp expressionType],
625  title;
626 
627  switch (type)
628  {
629  case CPKeyPathExpressionType: title = [self _displayValueForKeyPath:[exp keyPath]];
630  break;
631  case CPConstantValueExpressionType: title = [self _displayValueForConstantValue:[exp constantValue]];
632  break;
633  default: [CPException raise:CPInvalidArgumentException reason:@"Invalid Expression type " + type];
634  break;
635  }
636 
637  var item = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
638  [item setRepresentedObject:exp];
639  [popup addItem:item];
640  }
641 
642  [popup sizeToFit];
643 
644  return popup;
645 }
646 
647 - (CPPopUpButton)_viewFromOperatorTypes:(CPArray)operators
648 {
649  var popup = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0, 0, 100, 18)],
650  count = [operators count];
651 
652  for (var i = 0; i < count; i++)
653  {
654  var op = operators[i],
655  title = [self _displayValueForPredicateOperator:op],
656  item = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
657 
658  [item setRepresentedObject:op];
659  [popup addItem:item];
660  }
661 
662  [popup sizeToFit];
663 
664  return popup;
665 }
666 
667 - (CPView)_viewFromCompoundTypes:(CPArray)compoundTypes
668 {
669  var popup = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0, 0, 100, 18)],
670  count = [compoundTypes count];
671 
672  for (var i = 0; i < count; i++)
673  {
674  var type = compoundTypes[i],
675  title = [self _displayValueForCompoundPredicateType:type],
676  item = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
677 
678  [item setRepresentedObject:type];
679  [popup addItem:item];
680  }
681 
682  [popup sizeToFit];
683 
684  return popup;
685 }
686 
687 - (CPView)_viewFromAttributeType:(CPAttributeType)attributeType
688 {
689  var view;
690 
691  if (attributeType >= CPInteger16AttributeType && attributeType <= CPFloatAttributeType)
692  {
693  view = [self _textFieldWithFrame:CGRectMake(0, 0, 50, 26)];
694  }
695  else if (attributeType == CPStringAttributeType)
696  {
697  view = [self _textFieldWithFrame:CGRectMake(0, 0, 150, 26)];
698  }
699  else if (attributeType == CPBooleanAttributeType)
700  {
701  view = [[CPCheckBox alloc] initWithFrame:CGRectMake(0, 0, 50, 26)];
702  }
703  else if (attributeType == CPDateAttributeType)
704  {
705  view = [[CPDatePicker alloc] initWithFrame:CGRectMake(0, 0, 180, 26)];
706  [view setDatePickerElements:CPYearMonthDayDatePickerElementFlag];
707  }
708  else
709  return nil;
710 
711  [view setTag:attributeType];
712 
713  return view;
714 }
715 
716 - (CPTextField)_textFieldWithFrame:(CGRect)frame
717 {
718  var textField = [[CPTextField alloc] initWithFrame:frame];
719  [textField setBezeled:YES];
720  [textField setBezelStyle:CPTextFieldSquareBezel];
721  [textField setBordered:YES];
722  [textField setEditable:YES];
723  [textField setFont:[CPFont systemFontOfSize:10]];
724  [textField setSendsActionOnEndEditing:YES];
725 
726  return textField;
727 }
728 
729 - (void)_setOptions:(unsigned)options
730 {
731  _predicateOptions = options;
732 }
733 
734 - (void)_setModifier:(unsigned)modifier
735 {
736  _predicateModifier = modifier;
737 }
738 
739 - (CPString)description
740 {
741  if (_templateType == 2)
742  return [CPString stringWithFormat:@"<%@ %p %@>",[self className],self,[[self compoundTypes] componentsJoinedByString:@", "]];
743  else if (_templateType == 1 && _rightIsWildcard)
744  return [CPString stringWithFormat:@"<%@ %p [%@] [%@] %d>",[self className],self,[[self leftExpressions] componentsJoinedByString:@", "],[[self operators] componentsJoinedByString:@", "],[self rightExpressionAttributeType]];
745  else
746  return [CPString stringWithFormat:@"<%@ %p [%@] [%@] [%@]>",[self className],self,[[self leftExpressions] componentsJoinedByString:@", "],[[self operators] componentsJoinedByString:@", "],[[self rightExpressions] componentsJoinedByString:@", "]];
747 }
748 
749 /*
750 - (void)_setLeftExpressionObject:(id)object
751 {
752 }
753 - (void)_setRightExpressionObject:(id)object
754 {
755 }
756 - (BOOL)_predicateIsNoneAreTrue:(id)predicate
757 {
758 }
759 - (id)_viewFromExpressionObject:(id)object
760 {
761 }
762 */
763 @end
764 
765 var CPPredicateTemplateTypeKey = @"CPPredicateTemplateType",
766  CPPredicateTemplateOptionsKey = @"CPPredicateTemplateOptions",
767  CPPredicateTemplateModifierKey = @"CPPredicateTemplateModifier",
768  CPPredicateTemplateLeftAttributeTypeKey = @"CPPredicateTemplateLeftAttributeType",
769  CPPredicateTemplateRightAttributeTypeKey = @"CPPredicateTemplateRightAttributeType",
770  CPPredicateTemplateLeftIsWildcardKey = @"CPPredicateTemplateLeftIsWildcard",
771  CPPredicateTemplateRightIsWildcardKey = @"CPPredicateTemplateRightIsWildcard",
772  CPPredicateTemplateViewsKey = @"CPPredicateTemplateViews";
773 
774 @implementation CPPredicateEditorRowTemplate (CPCoding)
775 
776 - (id)initWithCoder:(CPCoder)coder
777 {
778  self = [super init];
779  if (self != nil)
780  {
781  _templateType = [coder decodeIntForKey:CPPredicateTemplateTypeKey];
782  _predicateOptions = [coder decodeIntForKey:CPPredicateTemplateOptionsKey];
783  _predicateModifier = [coder decodeIntForKey:CPPredicateTemplateModifierKey];
784  _leftAttributeType = [coder decodeIntForKey:CPPredicateTemplateLeftAttributeTypeKey];
785  _rightAttributeType = [coder decodeIntForKey:CPPredicateTemplateRightAttributeTypeKey];
786  _leftIsWildcard = [coder decodeBoolForKey:CPPredicateTemplateLeftIsWildcardKey];
787  _rightIsWildcard = [coder decodeBoolForKey:CPPredicateTemplateRightIsWildcardKey];
788  _views = [coder decodeObjectForKey:CPPredicateTemplateViewsKey];
789 
790  // In Xcode 4, when the menu item title == template's expression keypath, representedObject is empty.
791  // So we need to regenerate expressions from titles.
792  if (_templateType == 1 && _leftIsWildcard == NO)
793  {
794  var itemArray = [_views[0] itemArray],
795  count = [itemArray count];
796 
797  for (var i = 0; i < count; i++)
798  {
799  var item = itemArray[i];
800  if ([item representedObject] == nil)
801  {
802  var exp = [CPExpression expressionForKeyPath:[item title]];
803  [item setRepresentedObject:exp];
804  }
805  }
806  }
807  }
808 
809  return self;
810 }
811 
812 - (void)encodeWithCoder:(CPCoder)coder
813 {
814  [coder encodeInt:_templateType forKey:CPPredicateTemplateTypeKey];
815  [coder encodeInt:_predicateOptions forKey:CPPredicateTemplateOptionsKey];
816  [coder encodeInt:_predicateModifier forKey:CPPredicateTemplateModifierKey];
817  [coder encodeInt:_leftAttributeType forKey:CPPredicateTemplateLeftAttributeTypeKey];
818  [coder encodeInt:_rightAttributeType forKey:CPPredicateTemplateRightAttributeTypeKey];
819  [coder encodeBool:_leftIsWildcard forKey:CPPredicateTemplateLeftIsWildcardKey];
820  [coder encodeBool:_rightIsWildcard forKey:CPPredicateTemplateRightIsWildcardKey];
821  [coder encodeObject:_views forKey:CPPredicateTemplateViewsKey];
822 }
823 
824 @end
825 
826 // Copy support for built-in types
827 @implementation CPDatePicker (CPCopying)
828 
829 - (id)copy
830 {
831  var ret = [[[self class] alloc] initWithFrame:[self frame]];
832 
833  [ret setTextFont:[self textFont]];
834  [ret setMinDate:[self minDate]];
835  [ret setMaxDate:[self maxDate]];
836  [ret setTimeInterval:[self timeInterval]];
837  [ret setDatePickerMode:[self datePickerMode]];
838  [ret setDatePickerElements:[self datePickerElements]];
839  [ret setDatePickerStyle:[self datePickerStyle]];
840  [ret setLocale:[self locale]];
841  [ret setDateValue:[self dateValue]];
842  [ret setBackgroundColor:[self backgroundColor]];
843  [ret setDrawsBackground:[self drawsBackground]];
844  [ret setBordered:[self isBordered]];
845  [ret _init];
846 
847  return ret;
848 }
849 
850 @end
853 @implementation CPPredicateEditorRowTemplate (CPSynthesizedAccessors)
854 
855 
858 - (int)_templateType
859 {
860  return _templateType;
861 }
862 
866 - (void)_setTemplateType:(int)aValue
867 {
868  _templateType = aValue;
869 }
870 
874 - (void)_setOptions:(unsigned)aValue
875 {
876  _predicateOptions = aValue;
877 }
878 
882 - (void)_setModifier:(unsigned)aValue
883 {
884  _predicateModifier = aValue;
885 }
886 
890 - (unsigned)leftAttributeType
891 {
892  return _leftAttributeType;
893 }
894 
898 - (void)_setLeftAttributeType:(unsigned)aValue
899 {
900  _leftAttributeType = aValue;
901 }
902 
906 - (unsigned)rightAttributeType
907 {
908  return _rightAttributeType;
909 }
910 
914 - (void)_setRightAttributeType:(unsigned)aValue
915 {
916  _rightAttributeType = aValue;
917 }
918 
922 - (BOOL)leftIsWildcard
923 {
924  return _leftIsWildcard;
925 }
926 
930 - (void)setLeftIsWildcard:(BOOL)aValue
931 {
932  _leftIsWildcard = aValue;
933 }
934 
938 - (BOOL)rightIsWildcard
939 {
940  return _rightIsWildcard;
941 }
942 
946 - (void)setRightIsWildcard:(BOOL)aValue
947 {
948  _rightIsWildcard = aValue;
949 }
950 
954 - (void)setTemplateViews:(CPArray)aValue
955 {
956  _views = aValue;
957 }
958 
959 @end