-
-
Notifications
You must be signed in to change notification settings - Fork 683
/
AssertFactory.java
111 lines (102 loc) · 4.13 KB
/
AssertFactory.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright 2012-2024 the original author or authors.
*/
package org.assertj.core.api;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.function.Function;
/**
* A factory that creates an {@link Assert} instance for a given value of type {@link T}.
* <p>
* The {@link #createAssert(Object)} factory method typically wraps a call to
* {@link Assertions#assertThat}.
* <p>
* More advanced use cases can be achieved via {@link #createAssert(ValueProvider)},
* where the provision of the value is externalized and the factory can require
* explicit type compatibility for the value to be provided.
*
* @param <T> the type of the given value.
* @param <ASSERT> the type of the resulting {@code Assert}.
* @since 2.5.0 / 3.5.0
* @see InstanceOfAssertFactory
*/
@FunctionalInterface
public interface AssertFactory<T, ASSERT extends Assert<?, ?>> {
/**
* Creates the custom {@link Assert} instance for the given value.
* <p>
* Typically, this will just invoke <code>assertThat(actual)</code>.
*
* @param actual the input value for the {@code Assert} instance
* @return the custom {@code Assert} instance for the given value
*/
ASSERT createAssert(T actual);
/**
* Creates the custom {@link Assert} instance for the value provided by the
* given {@code valueProvider}.
* <p>
* This is typically used by custom assertions that want to leverage existing
* factories and need to manipulate the value upfront.
* <p>
* The default implementation always requests a value compatible with {@code Object}.
* <p>
* Overriding implementations might provide a more specific {@link Type}
* instance to express the desired type of the value returned by the provider.
* When doing so, the factory is required to be consistent with the type parameter {@link T}.
*
* @param valueProvider the value provider for the {@code Assert} instance
* @return the custom {@code Assert} instance for the value provided by the given value provider
* @since 3.26.0
*/
default ASSERT createAssert(ValueProvider<? extends T> valueProvider) {
T actual = valueProvider.apply(Object.class);
return createAssert(actual);
}
/**
* A provider that provides a value compatible with a given {@link Type}.
*
* @param <T> the type of provided value.
* @since 3.26.0
*/
@FunctionalInterface
interface ValueProvider<T> extends Function<Type, T> {
/**
* Provides a value compatible with the given {@code type}.
* <p>
* The compatibility definition depends on the actual {@code type} instance:
* <ul>
* <li>If {@code type} is a {@link Class}, the provided value must be an instance of it.</li>
* <li>If {@code type} is a {@link ParameterizedType}, the provided value must be
* an instance of its {@link ParameterizedType#getRawType() raw type}.</li>
* </ul>
* All other {@link Type} subtypes are unsupported.
*
* @param type the given type, either a {@link Class} or a {@link ParameterizedType} instance
* @return the provided value
*/
T provide(Type type);
/**
* Provides a value compatible with the given {@code type}.
*
* @param type the given type
* @return the provided value
* @throws IllegalArgumentException if {@code type} is neither a {@link Class}
* nor a {@link ParameterizedType} instance
*/
default T apply(Type type) {
if (!(type instanceof Class || type instanceof ParameterizedType)) {
throw new IllegalArgumentException("Unsupported type: " + type.getClass());
}
return provide(type);
}
}
}