View Javadoc
1   /*
2    * *************************************************************************************************************************************************************
3    *
4    * SteelBlue: DCI User Interfaces
5    * http://tidalwave.it/projects/steelblue
6    *
7    * Copyright (C) 2015 - 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/steelblue-src
22   * git clone https://github.com/tidalwave-it/steelblue-src
23   *
24   * *************************************************************************************************************************************************************
25   */
26  package it.tidalwave.ui.core.spi;
27  
28  import jakarta.annotation.Nonnull;
29  import java.util.ArrayList;
30  import java.util.Collection;
31  import java.util.HashMap;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.function.Function;
35  import it.tidalwave.ui.core.PanelGroupControl;
36  import it.tidalwave.ui.core.PanelGroupProvider;
37  import org.apiguardian.api.API;
38  import it.tidalwave.util.As;
39  import it.tidalwave.util.ShortNames;
40  import lombok.RequiredArgsConstructor;
41  import lombok.experimental.Delegate;
42  import lombok.extern.slf4j.Slf4j;
43  import static org.apiguardian.api.API.Status.EXPERIMENTAL;
44  import static java.util.stream.Collectors.*;
45  
46  /***************************************************************************************************************************************************************
47   *
48   * A support implementation of {@link PanelGroupControl}.
49   *
50   * @param   <T> the type of the top container
51   * @param   <S>
52   * @since       2.0-ALPHA-3
53   * @author      Fabrizio Giudici
54   *
55   **************************************************************************************************************************************************************/
56  @API(status = EXPERIMENTAL)
57  @RequiredArgsConstructor @Slf4j
58  public abstract class PanelGroupControlSupport<T, S> implements As, PanelGroupControl<T>
59    {
60      @Delegate @Nonnull
61      private final As delegate = As.forObject(this);
62  
63      @Nonnull
64      private final Function<As, Collection<? extends PanelGroupProvider<S>>> pgpProvider;
65  
66      /***********************************************************************************************************************************************************
67       *
68       **********************************************************************************************************************************************************/
69      protected PanelGroupControlSupport()
70        {
71          this(PanelGroupControlSupport::defaultPanelGroupProviders);
72        }
73  
74      /***********************************************************************************************************************************************************
75       * {@inheritDoc}
76       **********************************************************************************************************************************************************/
77      @Override
78      public void setup (@Nonnull final Configuration<T> configuration)
79        {
80          final var topContainersByGroup = configuration.getTopContainersByGroup();
81          final var providersByGroup = new HashMap<Group, List<PanelGroupProvider<S>>>();
82          pgpProvider.apply(this).forEach(p -> providersByGroup.computeIfAbsent(p.getGroup(), ignored -> new ArrayList<>()).add(p));
83          log.debug("Providers by placement:");
84          providersByGroup.forEach((placement, provider) -> log.debug(">>>> {}: {}", placement, ShortNames.shortIds(provider)));
85          final var unboundPlacements = providersByGroup.keySet().stream().filter(p -> !topContainersByGroup.containsKey(p)).collect(toList());
86  
87          if (!unboundPlacements.isEmpty())
88            {
89              throw new RuntimeException("No top container(s) provider for " + unboundPlacements);
90            }
91  
92          providersByGroup.forEach((group, providers) ->
93              assemble(group, providers, topContainersByGroup.get(group), configuration.getGroupOptions(), configuration.getOptions()));
94        }
95  
96      /***********************************************************************************************************************************************************
97       * Assemble a set of panes for the given group.
98       * @param   group               the {@code Group}
99       * @param   panelProviders      the {@code PanelGroupProvider}s associated to the given {@code Group}
100      * @param   topContainer        the top container
101      * @param   groupOptions        options for each group
102      * @param   options             options for doing the job
103      **********************************************************************************************************************************************************/
104     protected abstract void assemble (@Nonnull final Group group,
105                                       @Nonnull final List<? extends PanelGroupProvider<S>> panelProviders,
106                                       @Nonnull final T topContainer,
107                                       @Nonnull final Map<Group, List<Options>> groupOptions,
108                                       @Nonnull final List<Options> options);
109 
110     /***********************************************************************************************************************************************************
111      *
112      **********************************************************************************************************************************************************/
113     @Nonnull
114     private static <S> Collection<PanelGroupProvider<S>> defaultPanelGroupProviders (@Nonnull final As as)
115       {
116         return as.asMany(As.<PanelGroupProvider<S>>type(PanelGroupProvider.class));
117       }
118   }