Skip to contentMethod: type(Class)
1: /*
2: * *********************************************************************************************************************
3: *
4: * TheseFoolishThings: Miscellaneous utilities
5: * http://tidalwave.it/projects/thesefoolishthings
6: *
7: * Copyright (C) 2009 - 2023 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *********************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
12: * the License. You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
17: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
18: * specific language governing permissions and limitations under the License.
19: *
20: * *********************************************************************************************************************
21: *
22: * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
23: * git clone https://github.com/tidalwave-it/thesefoolishthings-src
24: *
25: * *********************************************************************************************************************
26: */
27: package it.tidalwave.util;
28:
29: import javax.annotation.Nonnull;
30: import javax.annotation.Nullable;
31: import java.util.Collection;
32: import java.util.Optional;
33: import it.tidalwave.util.impl.DefaultAs;
34: import lombok.EqualsAndHashCode;
35: import lombok.RequiredArgsConstructor;
36: import lombok.ToString;
37:
38: /***********************************************************************************************************************
39: *
40: * Objects implementing this interface can provide am adapter of the required type. The adapter can be found with a
41: * variety of approaches that depend on the implementation. This capability can be used to implement a design based
42: * on the Data, Context and Interaction pattern (DCI). For further details, please look at the
43: * <a href="http://tidalwave.it/projects/thesefoolishthings">project website</a>, where a tutorial is available.
44: *
45: * @author Fabrizio Giudici
46: * @it.tidalwave.javadoc.stable
47: *
48: **********************************************************************************************************************/
49: public interface As
50: {
51: /*******************************************************************************************************************
52: *
53: * @it.tidalwave.javadoc.stable
54: *
55: ******************************************************************************************************************/
56: @Deprecated
57: public static interface NotFoundBehaviour<T>
58: {
59: @Nonnull
60: public T run (@Nullable final Throwable t);
61: }
62:
63: /*******************************************************************************************************************
64: *
65: *
66: ******************************************************************************************************************/
67: @Deprecated
68: public static final class Defaults
69: {
70: private Defaults()
71: {
72: }
73:
74: public static <X> NotFoundBehaviour<X> throwAsException (@Nonnull final Class<X> clazz)
75: {
76: return new NotFoundBehaviour<X>()
77: {
78: // @Override
79: @Nonnull
80: public X run (@Nonnull final Throwable t)
81: {
82: throw new AsException(clazz, t);
83: }
84: };
85: }
86: }
87:
88: /*******************************************************************************************************************
89: *
90: * A type reference for roles that can be used in place of a class literal, especially when roles with generics are
91: * used. Example of usage:
92: * <pre>
93: *
94: * interface DataRetriever<T>
95: * {
96: * public List<T> retrieve();
97: * }
98: *
99: * class CodeSample
100: * {
101: * private static final As.Type<DataRetriever<String>> _StringRetriever_ = As.type(DataRetriever.class);
102: *
103: * public void method (As object)
104: * {
105: * List<String> f3 = object.as(_StringRetriever_).retrieve();
106: * }
107: * }
108: * </pre>
109: *
110: * @since 3.2-ALPHA-12
111: *
112: ******************************************************************************************************************/
113: @RequiredArgsConstructor @EqualsAndHashCode @ToString
114: public static final class Type<T>
115: {
116: @Nonnull
117: private final Class<?> type;
118:
119: @Nonnull
120: public Class<T> getType()
121: {
122: return (Class<T>)type;
123: }
124: }
125:
126: /*******************************************************************************************************************
127: *
128: * Creates an {@code As} implementation delegate for the given object (or returns the object itself if it is the
129: * default implementation of {@code As}).
130: *
131: * @param object the object
132: * @return the implementation
133: * @since 3.2-ALPHA-12
134: *
135: ******************************************************************************************************************/
136: @Nonnull
137: public static As forObject (@Nonnull final Object object)
138: {
139: return (object instanceof DefaultAs) ? (As)object : new DefaultAs(object);
140: }
141:
142: /*******************************************************************************************************************
143: *
144: * Creates an {@code As} implementation delegate for the given object. It accepts a single pre-instantiated role,
145: * or a {@link RoleFactory} that will be invoked to create additional roles.
146: *
147: * @param object the object
148: * @param role the role or {@link it.tidalwave.util.RoleFactory}
149: * @return the implementation
150: * @since 3.2-ALPHA-13
151: *
152: ******************************************************************************************************************/
153: @Nonnull
154: public static As forObject (@Nonnull final Object object, @Nonnull final Object role)
155: {
156: return new DefaultAs(object, role);
157: }
158:
159: /*******************************************************************************************************************
160: *
161: * Creates an {@code As} implementation delegate for the given object. It accepts a collection of pre-instantiated
162: * roles, or instances of {@link RoleFactory} that will be invoked to create additional roles.
163: *
164: * @param object the object
165: * @param roles roles or {@link it.tidalwave.util.RoleFactory} instances
166: * @return the implementation
167: * @since 3.2-ALPHA-13
168: *
169: ******************************************************************************************************************/
170: @Nonnull
171: public static As forObject (@Nonnull final Object object, @Nonnull final Collection<Object> roles)
172: {
173: return new DefaultAs(object, roles);
174: }
175:
176: /*******************************************************************************************************************
177: *
178: * Returns an adapter to this object of the specified type. If the implementation can find multiple compliant
179: * adapters, only one will be returned.
180: *
181: * @param <T> the static type
182: * @param type the dynamic type
183: * @return the adapter
184: * @throws AsException if no adapter is found
185: *
186: ******************************************************************************************************************/
187: @Nonnull
188: public default <T> T as (@Nonnull final Class<T> type)
189: {
190: return maybeAs(type).orElseThrow(() -> new AsException(type));
191: }
192:
193: /*******************************************************************************************************************
194: *
195: * Returns an adapter to this object of the specified type. If the implementation can find multiple compliant
196: * adapters, only one will be returned. If no adapter is found, the result provided by the given default
197: * behaviour will be returned.
198: *
199: * @param <T> the static type
200: * @param type the dynamic type
201: * @param notFoundBehaviour the behaviour to apply when an adapter is not found
202: * @return the adapter
203: * @deprecated
204: *
205: ******************************************************************************************************************/
206: @Nonnull @Deprecated
207: public default <T> T as (@Nonnull final Class<T> type, @Nonnull final NotFoundBehaviour<T> notFoundBehaviour)
208: {
209: return maybeAs(type).orElseGet(() -> notFoundBehaviour.run(new AsException(type)));
210: }
211:
212: /*******************************************************************************************************************
213: *
214: * Returns the requested role or an empty {@link Optional}.
215: *
216: * @param <T> the static type
217: * @param type the dynamic type
218: * @return the optional role
219: * @since 3.2-ALPHA-3
220: *
221: ******************************************************************************************************************/
222: @Nonnull
223: public <T> Optional<T> maybeAs (@Nonnull Class<T> type);
224:
225: /*******************************************************************************************************************
226: *
227: * Searches for multiple adapters of the given type and returns them.
228: *
229: * @param <T> the static type
230: * @param type the dynamic type
231: * @return a collection of adapters, possibly empty
232: *
233: ******************************************************************************************************************/
234: @Nonnull
235: public <T> Collection<T> asMany (@Nonnull Class<T> type);
236:
237: /*******************************************************************************************************************
238: *
239: * Creates a role type reference.
240: *
241: * @param <T> the static type
242: * @param type the dynamic type
243: * @return the type reference
244: * @since 3.2-ALPHA-12
245: *
246: ******************************************************************************************************************/
247: @Nonnull
248: public static <T> Type<T> type (@Nonnull final Class<?> type) // FIXME: there's no static check of the argument
249: {
250: return new Type<>(type);
251: }
252:
253: /*******************************************************************************************************************
254: *
255: * Returns a role for this object of the specified type. If the implementation can find multiple compliant
256: * roles, only one will be returned.
257: *
258: * @param <T> the static type
259: * @param type the type reference
260: * @return the role
261: * @since 3.2-ALPHA-12
262: *
263: ******************************************************************************************************************/
264: @Nonnull
265: public default <T> T as (@Nonnull final Type<T> type)
266: {
267: return as(type.getType());
268: }
269:
270: /*******************************************************************************************************************
271: *
272: * Returns the requested role or an empty {@link Optional}.
273: *
274: * @param <T> the static type
275: * @param type the type reference
276: * @return the optional role
277: * @since 3.2-ALPHA-12
278: *
279: ******************************************************************************************************************/
280: @Nonnull
281: public default <T> Optional<T> maybeAs (@Nonnull final Type<T> type)
282: {
283: return maybeAs(type.getType());
284: }
285:
286: /*******************************************************************************************************************
287: *
288: * Returns the requested role or an empty {@link Optional}.
289: *
290: * @param <T> the static type
291: * @param type the type reference
292: * @return the roles
293: * @since 3.2-ALPHA-12
294: *
295: ******************************************************************************************************************/
296: @Nonnull
297: public default <T> Collection<T> asMany (@Nonnull final Type<T> type)
298: {
299: return asMany(type.getType());
300: }
301: }