View Javadoc
1   /*
2    * *************************************************************************************************************************************************************
3    *
4    * TheseFoolishThings: Miscellaneous utilities
5    * http://tidalwave.it/projects/thesefoolishthings
6    *
7    * Copyright (C) 2009 - 2025 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 the License.
12   * 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 an "AS IS" BASIS, WITHOUT WARRANTIES OR
17   * CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License.
18   *
19   * *************************************************************************************************************************************************************
20   *
21   * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
22   * git clone https://github.com/tidalwave-it/thesefoolishthings-src
23   *
24   * *************************************************************************************************************************************************************
25   */
26  package it.tidalwave.util;
27  
28  import javax.annotation.Nonnull;
29  import java.util.Collection;
30  import java.util.Optional;
31  import it.tidalwave.role.impl.AsDelegate;
32  import lombok.EqualsAndHashCode;
33  import lombok.RequiredArgsConstructor;
34  import lombok.ToString;
35  
36  /***************************************************************************************************************************************************************
37   *
38   * Objects implementing this interface can provide am adapter of the required type. The adapter can be found with a
39   * variety of approaches that depend on the implementation. This capability can be used to implement a design based
40   * on the Data, Context and Interaction pattern (DCI). For further details, please look at the
41   * <a href="http://tidalwave.it/projects/thesefoolishthings">project website</a>, where a tutorial is available.
42   *
43   * @author  Fabrizio Giudici
44   * @it.tidalwave.javadoc.stable
45   *
46   **************************************************************************************************************************************************************/
47  public interface As
48    {
49      /***********************************************************************************************************************************************************
50       * A type reference for roles that can be used in place of a class literal, especially when roles with generics are
51       * used. Example of usage:
52       * <pre>
53       *
54       *     interface DataRetriever&lt;T&gt;
55       *       {
56       *         public List&lt;T&gt; retrieve();
57       *       }
58       *
59       *     class CodeSample
60       *       {
61       *         private static final As.Type&lt;DataRetriever&lt;String&gt;&gt; _StringRetriever_ = As.type(DataRetriever.class);
62       *
63       *         public void method (As object)
64       *           {
65       *             List&lt;String&gt; f3 = object.as(_StringRetriever_).retrieve();
66       *           }
67       *       }
68       * </pre>
69       *
70       * @since     3.2-ALPHA-12
71       **********************************************************************************************************************************************************/
72      @RequiredArgsConstructor @EqualsAndHashCode @ToString
73      public static final class Type<T>
74        {
75          @Nonnull
76          private final Class<?> type;
77  
78  
79          @Nonnull @SuppressWarnings("unchecked")
80          /* package */ Class<T> getType()
81            {
82              return (Class<T>)type;
83            }
84        }
85  
86      /***********************************************************************************************************************************************************
87       * Creates an {@code As} implementation delegate for the given object (or returns the object itself if it is the
88       * default implementation of {@code As}).
89       *
90       * @param     object         the object
91       * @return                   the implementation
92       * @since     3.2-ALPHA-12
93       **********************************************************************************************************************************************************/
94      @Nonnull
95      public static As forObject (@Nonnull final Object object)
96        {
97          return (object instanceof AsDelegate) ? (As)object : new AsDelegate(object);
98        }
99  
100     /***********************************************************************************************************************************************************
101      * Creates an {@code As} implementation delegate for the given object. It accepts a single pre-instantiated role,
102      * or a {@link RoleFactory} that will be invoked to create additional roles.
103      *
104      * @param     object         the object
105      * @param     role           the role or {@link it.tidalwave.util.RoleFactory}
106      * @return                   the implementation
107      * @since     3.2-ALPHA-13
108      **********************************************************************************************************************************************************/
109     @Nonnull
110     public static As forObject (@Nonnull final Object object, @Nonnull final Object role)
111       {
112         return new AsDelegate(object, role);
113       }
114 
115     /***********************************************************************************************************************************************************
116      * Creates an {@code As} implementation delegate for the given object. It accepts a collection of pre-instantiated
117      * roles, or instances of {@link RoleFactory} that will be invoked to create additional roles.
118      *
119      * @param     object         the object
120      * @param     roles          roles or {@link it.tidalwave.util.RoleFactory} instances
121      * @return                   the implementation
122      * @since     3.2-ALPHA-13
123      **********************************************************************************************************************************************************/
124     @Nonnull
125     public static As forObject (@Nonnull final Object object, @Nonnull final Collection<Object> roles)
126       {
127         return new AsDelegate(object, roles);
128       }
129 
130     /***********************************************************************************************************************************************************
131      * Returns an adapter to this object of the specified type. If the implementation can find multiple compliant
132      * adapters, only one will be returned.
133      *
134      * @param   <T>     the static type
135      * @param   type    the dynamic type
136      * @return          the adapter
137      * @throws          AsException if no adapter is found
138      **********************************************************************************************************************************************************/
139     @Nonnull
140     public default <T> T as (@Nonnull final Class<? extends T> type)
141       {
142         return maybeAs(type).orElseThrow(() -> new AsException(type));
143       }
144 
145     /***********************************************************************************************************************************************************
146      * Returns the requested role or an empty {@link Optional}.
147      *
148      * @param   <T>                 the static type
149      * @param   type                the dynamic type
150      * @return                      the optional role
151      * @since                       3.2-ALPHA-3
152      **********************************************************************************************************************************************************/
153     @Nonnull
154     public <T> Optional<T> maybeAs (@Nonnull Class<? extends T> type);
155 
156     /***********************************************************************************************************************************************************
157      * Searches for multiple adapters of the given type and returns them.
158      *
159      * @param   <T>     the static type
160      * @param   type    the dynamic type
161      * @return          a collection of adapters, possibly empty
162      **********************************************************************************************************************************************************/
163     @Nonnull
164     public <T> Collection<T> asMany (@Nonnull Class<? extends T> type);
165 
166     /***********************************************************************************************************************************************************
167      * Creates a role type reference.
168      *
169      * @param   <T>                 the static type
170      * @param   type                the dynamic type
171      * @return                      the type reference
172      * @since                       3.2-ALPHA-12
173      **********************************************************************************************************************************************************/
174     @Nonnull
175     public static <T> Type<T> type (@Nonnull final Class<?> type) // FIXME: there's no static check of the argument
176       {
177         return new Type<>(type);
178       }
179 
180     /***********************************************************************************************************************************************************
181      * Returns a role for this object of the specified type. If the implementation can find multiple compliant
182      * roles, only one will be returned.
183      *
184      * @param   <T>                 the static type
185      * @param   type                the type reference
186      * @return                      the role
187      * @since                       3.2-ALPHA-12
188      **********************************************************************************************************************************************************/
189     @Nonnull
190     public default <T> T as (@Nonnull final Type<? extends T> type)
191       {
192         return as(type.getType());
193       }
194 
195     /***********************************************************************************************************************************************************
196      * Returns the requested role or an empty {@link Optional}.
197      *
198      * @param   <T>                 the static type
199      * @param   type                the type reference
200      * @return                      the optional role
201      * @since                       3.2-ALPHA-12
202      **********************************************************************************************************************************************************/
203     @Nonnull
204     public default <T> Optional<T> maybeAs (@Nonnull final Type<? extends T> type)
205       {
206         return maybeAs(type.getType());
207       }
208 
209     /***********************************************************************************************************************************************************
210      * Returns the requested role or an empty {@link Optional}.
211      *
212      * @param   <T>                 the static type
213      * @param   type                the type reference
214      * @return                      the roles
215      * @since                       3.2-ALPHA-12
216      **********************************************************************************************************************************************************/
217     @Nonnull
218     public default <T> Collection<T> asMany (@Nonnull final Type<? extends T> type)
219       {
220         return asMany(type.getType());
221       }
222   }