AsDelegate.java

  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.impl;

  27. import jakarta.annotation.Nonnull;
  28. import java.util.ArrayList;
  29. import java.util.Collection;
  30. import java.util.Collections;
  31. import java.util.List;
  32. import java.util.Optional;
  33. import java.util.function.Function;
  34. import it.tidalwave.util.As;
  35. import it.tidalwave.util.LazySupplier;
  36. import it.tidalwave.util.Parameters;
  37. import it.tidalwave.util.RoleFactory;
  38. import it.tidalwave.role.spi.OwnerRoleFactory;
  39. import it.tidalwave.role.spi.OwnerRoleFactoryProvider;
  40. import static it.tidalwave.util.Parameters.r;

  41. /***************************************************************************************************************************************************************
  42.  *
  43.  * An implementation of {@link As} that keeps some local roles and queries {@link OwnerRoleFactory}.
  44.  *
  45.  * @author  Fabrizio Giudici
  46.  *
  47.  **************************************************************************************************************************************************************/
  48. public class AsDelegate implements As
  49.   {
  50.     @Nonnull
  51.     private final LazySupplier<OwnerRoleFactory> ownerRoleFactory;

  52.     @Nonnull
  53.     private final List<Object> roles = new ArrayList<>();

  54.     /***********************************************************************************************************************************************************
  55.      * Constructor for use in composition.
  56.      * @param  owner          the owner
  57.      * @since  3.2-ALPHA-3 (refactored)
  58.      **********************************************************************************************************************************************************/
  59.     public AsDelegate (@Nonnull final Object owner)
  60.       {
  61.         this(owner, Collections.emptyList());
  62.       }

  63.     /***********************************************************************************************************************************************************
  64.      * Constructor for use in composition. In addition to the mandatory owner, it accepts a single pre-instantiated role, or a {@link RoleFactory} that will be
  65.      * invoked to create additional roles.
  66.      * @param  owner          the owner
  67.      * @param  role           the role or {@link it.tidalwave.util.RoleFactory}
  68.      * @since  3.2-ALPHA-3
  69.      **********************************************************************************************************************************************************/
  70.     public AsDelegate (@Nonnull final Object owner, @Nonnull final Object role)
  71.       {
  72.         this(owner, r(Parameters.mustNotBeArrayOrCollection(role, "role")));
  73.       }

  74.     /***********************************************************************************************************************************************************
  75.      * Constructor for use in composition. In addition to the mandatory owner, it accepts a collection of pre-instantiated roles, or instances of
  76.      * {@link RoleFactory} that will be invoked to create additional roles.
  77.      * @param  owner          the owner
  78.      * @param  roles          roles or {@link it.tidalwave.util.RoleFactory} instances
  79.      * @since  3.2-ALPHA-3 (refactored)
  80.      **********************************************************************************************************************************************************/
  81.     public AsDelegate (@Nonnull final Object owner, @Nonnull final Collection<Object> roles)
  82.       {
  83.         this(o -> OwnerRoleFactoryProvider.getInstance().createRoleFactory(o), owner, roles);
  84.       }

  85.     /***********************************************************************************************************************************************************
  86.      * Constructor for use in tests. This constructor doesn't call {@link OwnerRoleFactoryProvider#getInstance()}.
  87.      * @param  systemRoleFactoryFunction  the factory
  88.      * @param  owner          the owner
  89.      * @param  roles          roles or {@link it.tidalwave.util.RoleFactory} instances
  90.      * @since  3.2-ALPHA-3 (refactored)
  91.      **********************************************************************************************************************************************************/
  92.     public AsDelegate (@Nonnull final Function<Object, OwnerRoleFactory> systemRoleFactoryFunction,
  93.                        @Nonnull final Object owner,
  94.                        @Nonnull final Collection<Object> roles)
  95.       {
  96.         ownerRoleFactory = LazySupplier.of(() -> systemRoleFactoryFunction.apply(owner));
  97.         this.roles.addAll(RoleFactory.resolveFactories(owner, roles));
  98.       }

  99.     /***********************************************************************************************************************************************************
  100.      * {@inheritDoc}
  101.      **********************************************************************************************************************************************************/
  102.     @Override @Nonnull
  103.     public <T> Optional<T> maybeAs (@Nonnull final Class<? extends T> type)
  104.       {
  105.         for (final var role : roles)
  106.           {
  107.             if (type.isAssignableFrom(role.getClass()))
  108.               {
  109.                 return Optional.of(type.cast(role));
  110.               }
  111.           }

  112.         final var r = ownerRoleFactory.get().findRoles(type);
  113.         return r.isEmpty() ? Optional.empty() : Optional.of(r.iterator().next());
  114.       }

  115.     /***********************************************************************************************************************************************************
  116.      * {@inheritDoc}
  117.      **********************************************************************************************************************************************************/
  118.     @Override @Nonnull
  119.     public <T> Collection<T> asMany (@Nonnull final Class<? extends T> type)
  120.       {
  121.         final var results = new ArrayList<T>();

  122.         for (final var role : roles)
  123.           {
  124.             if (type.isAssignableFrom(role.getClass()))
  125.               {
  126.                 results.add(type.cast(role));
  127.               }
  128.           }

  129.         results.addAll(ownerRoleFactory.get().findRoles(type));
  130.         return results;
  131.       }
  132.   }