View Javadoc
1 /*
2 * Types.java
3 * Created on August 1, 2003
4 *
5 * The Blues Framework - A lightweight application framework
6 * Copyright (C) 2003 Lonnie Pryor
7 * http://blues.lonniepryor.com
8 *
9 * This library is free software; you can redistribute it and/or modify it under the
10 * terms of the GNU Lesser General Public License as published by the Free Software
11 * Foundation; either version 2.1 of the License, or (at your option) any later
12 * version.
13 *
14 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
16 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License along
19 * with this library; if not, write to:
20 *
21 * The Free Software Foundation, Inc.
22 * 59 Temple Place, Suite 330
23 * Boston, MA 02111-1307 USA
24 *
25 */
26 package com.lonniepryor.blues.util;
27
28 import java.lang.reflect.Modifier;
29
30 import java.util.ArrayList;
31 import java.util.List;
32
33 /***
34 * Specification interface for identifying types and classes. Instances of this
35 * class may be logically combined using the AND, OR, and NOT operations. Many
36 * common use-cases are supplied via static accessor methods.
37 *
38 * @author Lonnie Pryor
39 * @version $Revision: 1.1 $
40 */
41 public abstract class Types {
42 /*** A specification matching the void type. */
43 private static final Types voids = new Types() {
44 public boolean evaluate (Class cls) {
45 return cls == Void.TYPE;
46 }
47 };
48 /*** A specification matching primitive types. */
49 private static final Types primitives = new Types() {
50 public boolean evaluate (Class cls) {
51 return (cls != Void.TYPE) && cls.isPrimitive();
52 }
53 };
54 /*** A specification matching array types. */
55 private static final Types arrays = new Types() {
56 public boolean evaluate (Class cls) {
57 return cls.isArray();
58 }
59 };
60 /*** A specification matching interface types. */
61 private static final Types interfaces = new Types() {
62 public boolean evaluate (Class cls) {
63 return cls.isInterface();
64 }
65 };
66 /*** A specification matching class types. */
67 private static final Types classes = voids.or(primitives).or(arrays).or(
68 interfaces).not();
69 /*** A specification matching public types. */
70 private static final Types declaredPublic = new Types() {
71 public boolean evaluate (Class cls) {
72 return Modifier.isPublic(cls.getModifiers());
73 }
74 };
75 /*** A specification matching protected types. */
76 private static final Types declaredProtected = new Types() {
77 public boolean evaluate (Class cls) {
78 return Modifier.isProtected(cls.getModifiers());
79 }
80 };
81 /*** A specification matching private types. */
82 private static final Types declaredPrivate = new Types() {
83 public boolean evaluate (Class cls) {
84 return Modifier.isPrivate(cls.getModifiers());
85 }
86 };
87 /*** A specification matching package protected types/ *//package-summary/html">color="#AA0000">* A specification matching package protected types/ *//package-summary.html">nt color="#AA0000">/*** A specification matching package protected types/ *//package-summary.html">color="#AA0000">* A specification matching package protected types. */
88 private static final Types declaredPackageProtected = declaredPublic.or(
89 declaredProtected).or(declaredPrivate).not();
90 /*** A specification matching abstract types. */
91 private static final Types declaredAbstract = new Types() {
92 public boolean evaluate (Class cls) {
93 return !cls.isPrimitive() && !cls.isArray()
94 && Modifier.isAbstract(cls.getModifiers());
95 }
96 };
97 /*** A specification matching concrete types. */
98 private static final Types declaredConcrete = declaredAbstract.not();
99 /*** A specification matching final types. */
100 private static final Types declaredFinal = new Types() {
101 public boolean evaluate (Class cls) {
102 return Modifier.isFinal(cls.getModifiers());
103 }
104 };
105 /*** A specification matching static types. */
106 private static final Types declaredStatic = new Types() {
107 public boolean evaluate (Class cls) {
108 return Modifier.isStatic(cls.getModifiers());
109 }
110 };
111 /*** A specification matching classes with a public , no-arguments constructor. */
112 private static final Types withAPublicNoArgCtor = withAConstructor(
113 Constructors.publicFactories());
114 /*** A specification matching public classes that are valid JavaBeans. */
115 private static final Types javaBeans = classes.and(declaredPublic).and(
116 declaredConcrete).and(withAPublicNoArgCtor);
117
118 /***
119 * Creates a new Types object.
120 */
121 protected Types () {
122 }
123
124 /***
125 * Returns a specification matching the void type.
126 *
127 * @return A specification matching the void type.
128 */
129 public static Types voids () {
130 return voids;
131 }
132
133 /***
134 * Returns a specification matching primitive types.
135 *
136 * @return A specification matching primitive types.
137 */
138 public static Types primitives () {
139 return primitives;
140 }
141
142 /***
143 * Returns a specification matching array types.
144 *
145 * @return A specification matching array types.
146 */
147 public static Types arrays () {
148 return arrays;
149 }
150
151 /***
152 * Returns a specification matching interface types.
153 *
154 * @return A specification matching interface types.
155 */
156 public static Types interfaces () {
157 return interfaces;
158 }
159
160 /***
161 * Returns a specification matching class types.
162 *
163 * @return A specification matching class types.
164 */
165 public static Types classes () {
166 return classes;
167 }
168
169 /***
170 * Returns a specification matching public types.
171 *
172 * @return A specification matching public types.
173 */
174 public static Types declaredPublic () {
175 return declaredPublic;
176 }
177
178 /***
179 * Returns a specification matching protected types.
180 *
181 * @return A specification matching protected types.
182 */
183 public static Types declaredProtected () {
184 return declaredProtected;
185 }
186
187 /***
188 * Returns a specification matching private types.
189 *
190 * @return A specification matching private types.
191 */
192 public static Types declaredPrivate () {
193 return declaredPrivate;
194 }
195
196 /***
197 * Returns a specification matching package protected types.
198 *
199 * @return A specification matching package protected types.
200 */
201 public static Types declaredPackageProtected () {
202 return declaredPackageProtected;
203 }
204
205 /***
206 * Returns a specification matching abstract types.
207 *
208 * @return A specification matching abstract types.
209 */
210 public static Types declaredAbstract () {
211 return declaredAbstract;
212 }
213
214 /***
215 * Returns a specification matching concrete types.
216 *
217 * @return A specification matching concrete types.
218 */
219 public static Types declaredConcrete () {
220 return declaredConcrete;
221 }
222
223 /***
224 * Returns a specification matching final types.
225 *
226 * @return A specification matching final types.
227 */
228 public static Types declaredFinal () {
229 return declaredFinal;
230 }
231
232 /***
233 * Returns a specification matching static types.
234 *
235 * @return A specification matching static types.
236 */
237 public static Types declaredStatic () {
238 return declaredStatic;
239 }
240
241 /***
242 * Returns a specification matching classes with a public , no-arguments
243 * constructor.
244 *
245 * @return A specification matching classes with a public , no-arguments
246 * constructor.
247 */
248 public static Types withAPublicNoArgCtor () {
249 return withAPublicNoArgCtor;
250 }
251
252 /***
253 * Returns a specification matching public classes that are valid JavaBeans.
254 *
255 * @return A specification matching public classes that are valid JavaBeans.
256 */
257 public static Types javaBeans () {
258 return javaBeans;
259 }
260
261 /***
262 * Creates a new specification satisfied by Types equal to the supplied Class.
263 *
264 * @param toTest The Class to be equal to.
265 *
266 * @return A new specification satisfied by Types equal to the supplied Class.
267 */
268 public static Types equalTo (final Class toTest) {
269 if (toTest == null)
270 throw new NullPointerException("toTest");
271 return new Types() {
272 public boolean evaluate (Class cls) {
273 return (toTest == cls) || toTest.equals(cls);
274 }
275 };
276 }
277
278 /***
279 * Creates a new specification satisfied only by Types declared on the Types that
280 * satisfy the supplied specification.
281 *
282 * @param specification The specification that Types must match.
283 *
284 * @return A new specification satisfied only by Types declared on the Types that
285 * satisfy the supplied specification.
286 */
287 public static Types declaredOn (final Types specification) {
288 if (specification == null)
289 throw new NullPointerException("specification");
290 return new Types() {
291 public boolean evaluate (Class cls) {
292 return specification.isSatisfiedBy(cls.getDeclaringClass());
293 }
294 };
295 }
296
297 /***
298 * Parses a pattern consisting of a dot-delimeted type name pattern. Example:
299 * <pre>
300 * com.lonniepryor..
301 * </pre>
302 * The above matches any class in the 'com.lonniepryor' namespace.
303 *
304 * @param namePattern The pattern names must match.
305 *
306 * @return A new specification satisfied by Types whose names match the supplied
307 * pattern.
308 *
309 * @throws ParseException if the name pattern is invalid.
310 */
311 public static Types named (String namePattern) {
312 if (namePattern == null)
313 throw new NullPointerException("namePattern");
314 return named(TokenizedStrings.parse(namePattern, '.'));
315 }
316
317 /***
318 * Creates a new specification satisfied by Types whose names match the supplied
319 * pattern.
320 *
321 * @param specification The specification names must match.
322 *
323 * @return A new specification satisfied by Types whose names match the supplied
324 * pattern.
325 */
326 public static Types named (final Strings specification) {
327 if (specification == null)
328 throw new NullPointerException("specification");
329 return new Types() {
330 public boolean evaluate (Class cls) {
331 return specification.isSatisfiedBy(
332 ((cls.getName().indexOf('$') >= 0) ? cls.getName().replace('$', '.')
333 : cls.getName()));
334 }
335 };
336 }
337
338 /***
339 * Creates a new specification satisfied by array types whose component type
340 * matches the supplied specification.
341 *
342 * @param specification The specification component types must match.
343 *
344 * @return A new specification satisfied by array types whose component type
345 * matches the supplied specification.
346 */
347 public static Types arraysOf (final Types specification) {
348 if (specification == null)
349 throw new NullPointerException("specification");
350 return new Types() {
351 public boolean evaluate (Class cls) {
352 return cls.isArray()
353 && specification.isSatisfiedBy(cls.getComponentType());
354 }
355 };
356 }
357
358 /***
359 * Creates a new specification satisfied by Types that are assignable from the
360 * supplied Class.
361 *
362 * @param toTest The Class to be assignable from.
363 *
364 * @return A new specification satisfied by Types that are assignable from the
365 * supplied Class.
366 */
367 public static Types assignableFrom (final Class toTest) {
368 if (toTest == null)
369 throw new NullPointerException("toTest");
370 return new Types() {
371 public boolean evaluate (Class cls) {
372 return cls.isAssignableFrom(toTest);
373 }
374 };
375 }
376
377 /***
378 * Creates a new specification satisfied by Types that are assignable to the
379 * supplied Class.
380 *
381 * @param toTest The Class to be assignable to.
382 *
383 * @return A new specification satisfied by Types that are assignable to the
384 * supplied Class.
385 */
386 public static Types assignableTo (final Class toTest) {
387 if (toTest == null)
388 throw new NullPointerException("toTest");
389 return new Types() {
390 public boolean evaluate (Class cls) {
391 return toTest.isAssignableFrom(cls);
392 }
393 };
394 }
395
396 /***
397 * Creates a new specification satisfied by Types that inherit from any Class
398 * that is satisfied by the supplied specification.
399 *
400 * @param specification The specification to inherit from.
401 *
402 * @return A new specification satisfied by Types that inherit from to any Class
403 * that is satisfied by the supplied specification.
404 */
405 public static Types inheritingFrom (final Types specification) {
406 if (specification == null)
407 throw new NullPointerException("specification");
408 return new Types() {
409 public boolean evaluate (Class cls) {
410 if (specification.isSatisfiedBy(cls))
411 return true;
412 if (cls.isInterface() && specification.isSatisfiedBy(Object.class))
413 return true;
414 Class[] interfaces = cls.getInterfaces();
415 for (int i = 0; i < interfaces.length; ++i)
416 if (evaluate(interfaces[i]))
417 return true;
418 return isSatisfiedBy(cls.getSuperclass());
419 }
420 };
421 }
422
423 /***
424 * Creates a new specification satisfied by Types that have at least one field
425 * matching the supplied specification.
426 *
427 * @param specification The specification to match fields to.
428 *
429 * @return A new specification satisfied by Types that have at least one field
430 * matching the supplied specification.
431 */
432 public static Types withAField (final Fields specification) {
433 if (specification == null)
434 throw new NullPointerException("specification");
435 return new Types() {
436 public boolean evaluate (Class cls) {
437 return specification.isSatisifiedByAny(cls.getFields());
438 }
439 };
440 }
441
442 /***
443 * Creates a new specification satisfied by Types that have at least one declared
444 * field matching the supplied specification.
445 *
446 * @param specification The specification to match fields to.
447 *
448 * @return A new specification satisfied by Types that have at least one declared
449 * field matching the supplied specification.
450 */
451 public static Types withADeclaredField (final Fields specification) {
452 if (specification == null)
453 throw new NullPointerException("specification");
454 return new Types() {
455 public boolean evaluate (Class cls) {
456 return specification.isSatisifiedByAny(cls.getDeclaredFields());
457 }
458 };
459 }
460
461 /***
462 * Creates a new specification satisfied by Types that have all fields matching
463 * the supplied specification.
464 *
465 * @param specification The specification to match fields to.
466 *
467 * @return A new specification satisfied by Types that have all fields matching
468 * the supplied specification.
469 */
470 public static Types withAllFields (final Fields specification) {
471 if (specification == null)
472 throw new NullPointerException("specification");
473 return new Types() {
474 public boolean evaluate (Class cls) {
475 return specification.isSatisifiedByAll(cls.getFields());
476 }
477 };
478 }
479
480 /***
481 * Creates a new specification satisfied by Types that have all declared fields
482 * matching the supplied specification.
483 *
484 * @param specification The specification to match fields to.
485 *
486 * @return A new specification satisfied by Types that have all declared fields
487 * matching the supplied specification.
488 */
489 public static Types withAllDeclaredConstructors (final Fields specification) {
490 if (specification == null)
491 throw new NullPointerException("specification");
492 return new Types() {
493 public boolean evaluate (Class cls) {
494 return specification.isSatisifiedByAll(cls.getDeclaredFields());
495 }
496 };
497 }
498
499 /***
500 * Creates a new specification satisfied by Types that have at least one
501 * constructor matching the supplied specification.
502 *
503 * @param specification The specification to match constructors to.
504 *
505 * @return A new specification satisfied by Types that have at least one
506 * constructor matching the supplied specification.
507 */
508 public static Types withAConstructor (final Constructors specification) {
509 if (specification == null)
510 throw new NullPointerException("specification");
511 return new Types() {
512 public boolean evaluate (Class cls) {
513 return specification.isSatisfiedByAny(cls.getConstructors());
514 }
515 };
516 }
517
518 /***
519 * Creates a new specification satisfied by Types that have at least one declared
520 * constructor matching the supplied specification.
521 *
522 * @param specification The specification to match constructors to.
523 *
524 * @return A new specification satisfied by Types that have at least one declared
525 * constructor matching the supplied specification.
526 */
527 public static Types withADeclaredConstructor (final Constructors specification) {
528 if (specification == null)
529 throw new NullPointerException("specification");
530 return new Types() {
531 public boolean evaluate (Class cls) {
532 return specification.isSatisfiedByAny(cls.getDeclaredConstructors());
533 }
534 };
535 }
536
537 /***
538 * Creates a new specification satisfied by Types that have all constructors
539 * matching the supplied specification.
540 *
541 * @param specification The specification to match constructors to.
542 *
543 * @return A new specification satisfied by Types that have all constructors
544 * matching the supplied specification.
545 */
546 public static Types withAllConstructors (final Constructors specification) {
547 if (specification == null)
548 throw new NullPointerException("specification");
549 return new Types() {
550 public boolean evaluate (Class cls) {
551 return specification.isSatisfiedByAll(cls.getConstructors());
552 }
553 };
554 }
555
556 /***
557 * Creates a new specification satisfied by Types that have all declared
558 * constructors matching the supplied specification.
559 *
560 * @param specification The specification to match constructors to.
561 *
562 * @return A new specification satisfied by Types that have all declared
563 * constructors matching the supplied specification.
564 */
565 public static Types withAllDeclaredConstructors (
566 final Constructors specification) {
567 if (specification == null)
568 throw new NullPointerException("specification");
569 return new Types() {
570 public boolean evaluate (Class cls) {
571 return specification.isSatisfiedByAll(cls.getDeclaredConstructors());
572 }
573 };
574 }
575
576 /***
577 * Creates a new specification satisfied by Types that have at least one method
578 * matching the supplied specification.
579 *
580 * @param specification The specification to match methods to.
581 *
582 * @return A new specification satisfied by Types that have at least one method
583 * matching the supplied specification.
584 */
585 public static Types withAMethod (final Methods specification) {
586 if (specification == null)
587 throw new NullPointerException("specification");
588 return new Types() {
589 public boolean evaluate (Class cls) {
590 return specification.isSatisfiedByAny(cls.getMethods());
591 }
592 };
593 }
594
595 /***
596 * Creates a new specification satisfied by Types that have at least one declared
597 * method matching the supplied specification.
598 *
599 * @param specification The specification to match methods to.
600 *
601 * @return A new specification satisfied by Types that have at least one declared
602 * method matching the supplied specification.
603 */
604 public static Types withADeclaredMethod (final Methods specification) {
605 if (specification == null)
606 throw new NullPointerException("specification");
607 return new Types() {
608 public boolean evaluate (Class cls) {
609 return specification.isSatisfiedByAny(cls.getDeclaredMethods());
610 }
611 };
612 }
613
614 /***
615 * Creates a new specification satisfied by Types that have all methods matching
616 * the supplied specification.
617 *
618 * @param specification The specification to match methods to.
619 *
620 * @return A new specification satisfied by Types that have all methods matching
621 * the supplied specification.
622 */
623 public static Types withAllMethods (final Methods specification) {
624 if (specification == null)
625 throw new NullPointerException("specification");
626 return new Types() {
627 public boolean evaluate (Class cls) {
628 return specification.isSatisfiedByAll(cls.getMethods());
629 }
630 };
631 }
632
633 /***
634 * Creates a new specification satisfied by Types that have all declared methods
635 * matching the supplied specification.
636 *
637 * @param specification The specification to match methods to.
638 *
639 * @return A new specification satisfied by Types that have all declared methods
640 * matching the supplied specification.
641 */
642 public static Types withAllDeclaredMethods (final Methods specification) {
643 if (specification == null)
644 throw new NullPointerException("specification");
645 return new Types() {
646 public boolean evaluate (Class cls) {
647 return specification.isSatisfiedByAll(cls.getDeclaredMethods());
648 }
649 };
650 }
651
652 /***
653 * Parses a pattern consisting of a dot-delimeted class name optionally followed
654 * by a '+' to match all subclasses, then a '[]' to match arrays. Format:
655 * <pre>
656 * types ::= name-pattern [ "+" ] [ "[]" ]
657 * name-pattern ::= A '.'-delimeted TokenizedStrings pattern.
658 * </pre>
659 * Example:
660 * <pre>
661 * com.lonniepryor..*+[]
662 * </pre>
663 * The above matches arrays of any class inheriting from any class in the
664 * 'com.lonniepryor' namespace.
665 *
666 * @param classPattern The pattern definition string.
667 *
668 * @return A specification matching the pattern.
669 *
670 * @throws ParseException if the pattern is invalid.
671 *
672 * @see TokenizedStrings#parse(String, char)
673 */
674 public static Types parse (String classPattern) {
675 if (classPattern == null)
676 throw new NullPointerException("classPattern");
677 if (classPattern.endsWith("+[]"))
678 return arraysOf(
679 inheritingFrom(named(classPattern.substring(0, classPattern.length() - 3))));
680 if (classPattern.endsWith("[]"))
681 return arraysOf(named(classPattern.substring(0, classPattern.length() - 2)));
682 if (classPattern.endsWith("+"))
683 return inheritingFrom(
684 named(classPattern.substring(0, classPattern.length() - 1)));
685 return named(classPattern);
686 }
687
688 /***
689 * Parses a logical expression as described in the Expression class, using this
690 * class's parse() method for creating values.
691 *
692 * @param classPatternExpr The pattern expression definition string.
693 *
694 * @return A specification matching the pattern expression.
695 *
696 * @throws ParseException if the pattern expression is invalid.
697 *
698 * @see Expression
699 * @see Types#parse(String)
700 */
701 public static Types parseExpression (String classPatternExpr) {
702 if (classPatternExpr == null)
703 throw new NullPointerException("classPatternExpr");
704 return (Types)Expression.parse(
705 classPatternExpr,
706 new Expression.Builder() {
707 public Object or (Object left, Object right) {
708 return ((Types)left).or((Types)right);
709 }
710
711 public Object and (Object left, Object right) {
712 return ((Types)left).and((Types)right);
713 }
714
715 public Object not (Object value) {
716 return ((Types)value).not();
717 }
718
719 public Object create (String classPattern) {
720 return parse(classPattern);
721 }
722 });
723 }
724
725 /***
726 * Returns true if the supplied Class is not null and satisfies this
727 * specification.
728 *
729 * @param cls The Class to test.
730 *
731 * @return True if the supplied Class is not null and satisfies this
732 * specification.
733 */
734 public final boolean isSatisfiedBy (Class cls) {
735 return (cls != null) && evaluate(cls);
736 }
737
738 /***
739 * Returns true if the supplied Class satisfies this specification.
740 *
741 * @param attr The Class to test.
742 *
743 * @return True if the supplied Class satisfies this specification.
744 */
745 public abstract boolean evaluate (Class cls);
746
747 /***
748 * Returns true if all of the supplied Types satisfy this specification.
749 *
750 * @param all The array of Types to test.
751 *
752 * @return True if all of the supplied Types satisfy this specification.
753 */
754 public final boolean isSatisifiedByAll (Class[] all) {
755 if (all == null)
756 throw new NullPointerException("all");
757 for (int i = 0; i < all.length; ++i)
758 if (!isSatisfiedBy(all[i]))
759 return false;
760 return true;
761 }
762
763 /***
764 * Returns true if any of the supplied Types satisfy this specification.
765 *
766 * @param any The array of Types to test.
767 *
768 * @return True if any of the supplied Types satisfy this specification.
769 */
770 public final boolean isSatisifiedByAny (Class[] any) {
771 if (any == null)
772 throw new NullPointerException("any");
773 for (int i = 0; i < any.length; ++i)
774 if (isSatisfiedBy(any[i]))
775 return true;
776 return false;
777 }
778
779 /***
780 * Selects the first Class that satisfies this specification from the supplied
781 * array.
782 *
783 * @param from The array to select from.
784 *
785 * @return The first Class that satisfies this specification from the supplied
786 * array.
787 */
788 public final Class selectFirst (Class[] from) {
789 if (from == null)
790 throw new NullPointerException("from");
791 for (int i = 0; i < from.length; ++i)
792 if (isSatisfiedBy(from[i]))
793 return from[i];
794 return null;
795 }
796
797 /***
798 * Selects all the Types that satisfy this specification from the supplied array.
799 *
800 * @param from The array to select from.
801 *
802 * @return All the Types that satisfy this specification from the supplied array.
803 */
804 public final Class[] selectAll (Class[] from) {
805 if (from == null)
806 throw new NullPointerException("from");
807 List results = new ArrayList(from.length);
808 for (int i = 0; i < from.length; ++i)
809 if (isSatisfiedBy(from[i]))
810 results.add(from[i]);
811 return (Class[])results.toArray(new Class[results.size()]);
812 }
813
814 /***
815 * Returns a specification representing a logical AND of this specification on
816 * the left and the supplied specification on the right.
817 *
818 * @param specification The specification to AND with.
819 *
820 * @return A specification representing a logical AND of this specification on
821 * the left and the supplied specification on the right.
822 */
823 public final Types and (final Types specification) {
824 if (specification == null)
825 throw new NullPointerException("specification");
826 return new Types() {
827 public boolean evaluate (Class cls) {
828 return Types.this.evaluate(cls) && specification.evaluate(cls);
829 }
830 };
831 }
832
833 /***
834 * Returns a specification representing a logical OR of this specification on the
835 * left and the supplied specification on the right.
836 *
837 * @param specification The specification to OR with.
838 *
839 * @return A specification representing a logical OR of this specification on the
840 * left and the supplied specification on the right.
841 */
842 public final Types or (final Types specification) {
843 if (specification == null)
844 throw new NullPointerException("specification");
845 return new Types() {
846 public boolean evaluate (Class cls) {
847 return Types.this.evaluate(cls) || specification.evaluate(cls);
848 }
849 };
850 }
851
852 /***
853 * Returns a specification representing a logical NOT of this specification.
854 *
855 * @return A specification representing a logical NOT of this specification.
856 */
857 public final Types not () {
858 return new Types() {
859 public boolean evaluate (Class cls) {
860 return !Types.this.evaluate(cls);
861 }
862 };
863 }
864 }
This page was automatically generated by Maven