1 /*
2 * Copyright 2006-2010 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package net.sourceforge.domian.specification;
17
18
19 import java.lang.reflect.Field;
20 import java.util.Collection;
21
22 import static java.lang.Boolean.FALSE;
23
24
25 /**
26 * A parameterized specification deals, as opposed to <i>value bound specifications</i>,
27 * also with <i>value context</i>. In this specification, this context is a class field.
28 * <p/>
29 * For candidate objects to be approved by a parameterized specifications, two things must be fulfilled:
30 * <ol>
31 * <li/>A field value must be successfully extracted from the candidate object
32 * <li/>The field value must then be approved by the provided {@link net.sourceforge.domian.specification.Specification}
33 * </ol>
34 * <p/>
35 *
36 * @author Eirik Torske
37 * @since 0.1
38 */
39 // TODO: rename to FieldSpecification?
40 final class FieldParameterizedSpecification<T, F> extends ParameterizedSpecification<T, F> {
41
42 FieldParameterizedSpecification(final Class<T> declaringClass,
43 final Field field,
44 final Specification<F> accessibleObjectSpecification) {
45 this.type = declaringClass;
46 this.accessibleObject = field;
47 this.accessibleObjectSpecification = accessibleObjectSpecification;
48 }
49
50 @Override
51 String getName() {
52 return ((Field) this.accessibleObject).getName();
53 }
54
55 @Override
56 // @SuppressWarnings("unchecked")
57 public Boolean isSatisfiedBy(final T candidate) {
58 if (candidate == null) {
59 return FALSE;
60 }
61 try {
62 /*
63 Field field = (Field) this.accessibleObject;
64 if (this.accessibleObjectSpecification instanceof CollectionSpecification) {
65 @SuppressWarnings("unchecked") -> "I solemnly swear that this statement will not throw any ClassCastException!" -eirik torske-
66 Such a type mismatch will be detected in the parent static factory method, and a java.lang.IllegalArgumentException will be thrown
67 final Collection<F> candidateFieldValue = (Collection<F>) field.get(candidate);
68 return ((CollectionSpecification<F>) this.accessibleObjectSpecification).isSatisfiedBy(candidateFieldValue);
69
70 } else if (candidate instanceof ParameterizedSpecification) {
71 @SuppressWarnings("unchecked") -> TODO: not entirely sure what's going on here...
72 return this.accessibleObjectSpecification.isSatisfiedBy((F) ((ParameterizedSpecification) candidate).accessibleObjectSpecification);
73
74 } else {
75 final F candidateFieldValue = this.accessibleObjectSpecification.getType().cast(field.get(candidate));
76 return this.accessibleObjectSpecification.isSatisfiedBy(candidateFieldValue);
77 }
78 */
79 Field field = (Field) this.accessibleObject;
80
81 return this.accessibleObjectSpecification.isSatisfiedBy((F) field.get(candidate));
82
83
84 } catch (IllegalAccessException e) {
85 // Keep until beta or something...
86 e.printStackTrace();
87
88 throw new IllegalArgumentException(e);
89 }
90 }
91 }