As.java

  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. 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.  * Objects implementing this interface can provide am adapter of the required type. The adapter can be found with a
  38.  * variety of approaches that depend on the implementation. This capability can be used to implement a design based
  39.  * on the Data, Context and Interaction pattern (DCI). For further details, please look at the
  40.  * <a href="http://tidalwave.it/projects/thesefoolishthings">project website</a>, where a tutorial is available.
  41.  *
  42.  * @author  Fabrizio Giudici
  43.  * @it.tidalwave.javadoc.stable
  44.  *
  45.  **********************************************************************************************************************/
  46. public interface As
  47.   {
  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.      ******************************************************************************************************************/
  73.     @RequiredArgsConstructor @EqualsAndHashCode @ToString
  74.     public static final class Type<T>
  75.       {
  76.         @Nonnull
  77.         private final Class<?> type;


  78.         @Nonnull @SuppressWarnings("unchecked")
  79.         /* package */ Class<T> getType()
  80.           {
  81.             return (Class<T>)type;
  82.           }
  83.       }

  84.     /*******************************************************************************************************************
  85.      *
  86.      * Creates an {@code As} implementation delegate for the given object (or returns the object itself if it is the
  87.      * default implementation of {@code As}).
  88.      *
  89.      * @param     object         the object
  90.      * @return                   the implementation
  91.      * @since     3.2-ALPHA-12
  92.      *
  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.      ******************************************************************************************************************/
  110.     @Nonnull
  111.     public static As forObject (@Nonnull final Object object, @Nonnull final Object role)
  112.       {
  113.         return new AsDelegate(object, role);
  114.       }

  115.     /*******************************************************************************************************************
  116.      *
  117.      * Creates an {@code As} implementation delegate for the given object. It accepts a collection of pre-instantiated
  118.      * roles, or instances of {@link RoleFactory} that will be invoked to create additional roles.
  119.      *
  120.      * @param     object         the object
  121.      * @param     roles          roles or {@link it.tidalwave.util.RoleFactory} instances
  122.      * @return                   the implementation
  123.      * @since     3.2-ALPHA-13
  124.      *
  125.      ******************************************************************************************************************/
  126.     @Nonnull
  127.     public static As forObject (@Nonnull final Object object, @Nonnull final Collection<Object> roles)
  128.       {
  129.         return new AsDelegate(object, roles);
  130.       }

  131.     /*******************************************************************************************************************
  132.      *
  133.      * Returns an adapter to this object of the specified type. If the implementation can find multiple compliant
  134.      * adapters, only one will be returned.
  135.      *
  136.      * @param   <T>     the static type
  137.      * @param   type    the dynamic type
  138.      * @return          the adapter
  139.      * @throws          AsException if no adapter is found
  140.      *
  141.      ******************************************************************************************************************/
  142.     @Nonnull
  143.     public default <T> T as (@Nonnull final Class<? extends T> type)
  144.       {
  145.         return maybeAs(type).orElseThrow(() -> new AsException(type));
  146.       }

  147.     /*******************************************************************************************************************
  148.      *
  149.      * Returns the requested role or an empty {@link Optional}.
  150.      *
  151.      * @param   <T>                 the static type
  152.      * @param   type                the dynamic type
  153.      * @return                      the optional role
  154.      * @since                       3.2-ALPHA-3
  155.      *
  156.      ******************************************************************************************************************/
  157.     @Nonnull
  158.     public <T> Optional<T> maybeAs (@Nonnull Class<? extends T> type);

  159.     /*******************************************************************************************************************
  160.      *
  161.      * Searches for multiple adapters of the given type and returns them.
  162.      *
  163.      * @param   <T>     the static type
  164.      * @param   type    the dynamic type
  165.      * @return          a collection of adapters, possibly empty
  166.      *
  167.      ******************************************************************************************************************/
  168.     @Nonnull
  169.     public <T> Collection<T> asMany (@Nonnull Class<? extends T> type);

  170.     /*******************************************************************************************************************
  171.      *
  172.      * Creates a role type reference.
  173.      *
  174.      * @param   <T>                 the static type
  175.      * @param   type                the dynamic type
  176.      * @return                      the type reference
  177.      * @since                       3.2-ALPHA-12
  178.      *
  179.      ******************************************************************************************************************/
  180.     @Nonnull
  181.     public static <T> Type<T> type (@Nonnull final Class<?> type) // FIXME: there's no static check of the argument
  182.       {
  183.         return new Type<>(type);
  184.       }

  185.     /*******************************************************************************************************************
  186.      *
  187.      * Returns a role for this object of the specified type. If the implementation can find multiple compliant
  188.      * roles, only one will be returned.
  189.      *
  190.      * @param   <T>                 the static type
  191.      * @param   type                the type reference
  192.      * @return                      the role
  193.      * @since                       3.2-ALPHA-12
  194.      *
  195.      ******************************************************************************************************************/
  196.     @Nonnull
  197.     public default <T> T as (@Nonnull final Type<? extends T> type)
  198.       {
  199.         return as(type.getType());
  200.       }

  201.     /*******************************************************************************************************************
  202.      *
  203.      * Returns the requested role or an empty {@link Optional}.
  204.      *
  205.      * @param   <T>                 the static type
  206.      * @param   type                the type reference
  207.      * @return                      the optional role
  208.      * @since                       3.2-ALPHA-12
  209.      *
  210.      ******************************************************************************************************************/
  211.     @Nonnull
  212.     public default <T> Optional<T> maybeAs (@Nonnull final Type<? extends T> type)
  213.       {
  214.         return maybeAs(type.getType());
  215.       }

  216.     /*******************************************************************************************************************
  217.      *
  218.      * Returns the requested role or an empty {@link Optional}.
  219.      *
  220.      * @param   <T>                 the static type
  221.      * @param   type                the type reference
  222.      * @return                      the roles
  223.      * @since                       3.2-ALPHA-12
  224.      *
  225.      ******************************************************************************************************************/
  226.     @Nonnull
  227.     public default <T> Collection<T> asMany (@Nonnull final Type<? extends T> type)
  228.       {
  229.         return asMany(type.getType());
  230.       }
  231.   }