001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2024–2025 microBean™.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
006 * the License. You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
011 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
012 * specific language governing permissions and limitations under the License.
013 */
014package org.microbean.bean;
015
016import java.util.Collection;
017import java.util.Collections;
018import java.util.SequencedSet;
019
020import java.util.function.Function;
021
022import static java.util.Collections.unmodifiableSequencedSet;
023
024import static java.util.LinkedHashSet.newLinkedHashSet;
025
026/**
027 * An object with {@linkplain AttributedElement dependencies}.
028 *
029 * <p>By default, {@link Aggregate}s have {@linkplain #EMPTY_DEPENDENCIES no dependencies}.</p>
030 *
031 * @author <a href="https://about.me/lairdnelson/" target="_top">Laird Nelson</a>
032 *
033 * @see #dependencies()
034 */
035public interface Aggregate {
036
037
038  /*
039   * Static fields.
040   */
041
042
043  /**
044   * An immutable, empty {@link SequencedSet} of {@link Assignment}s.
045   */
046  public static final SequencedSet<Assignment<?>> EMPTY_ASSIGNMENTS = unmodifiableSequencedSet(newLinkedHashSet(0));
047
048  /**
049   * An immutable, empty {@link SequencedSet} of {@link AttributedElement}s.
050   */
051  public static final SequencedSet<AttributedElement> EMPTY_DEPENDENCIES = unmodifiableSequencedSet(newLinkedHashSet(0));
052
053
054  /*
055   * Default instance methods.
056   */
057
058
059  /**
060   * Returns an immutable {@link SequencedSet} of {@link AttributedElement} instances.
061   *
062   * @return an immutable {@link SequencedSet} of {@link AttributedElement} instances; never {@code null}
063   *
064   * @see AttributedElement
065   */
066  public default SequencedSet<AttributedElement> dependencies() {
067    return EMPTY_DEPENDENCIES;
068  }
069
070  /**
071   * A convenience method that assigns a contextual reference to each of this {@link Aggregate}'s {@link
072   * AttributedElement} instances and returns the resulting {@link SequencedSet} of {@link Assignment}s.
073   *
074   * <p>Typically there is no need to override this method.</p>
075   *
076   * @param r a {@link Function} that retrieves a contextual reference suitable for an {@link AttributedType}; if {@link
077   * #dependencies()} returns a non-empty {@link SequencedSet} then this argument must not be {@code null}; normally a
078   * reference to the {@link Request#reference(AttributedType)} method
079   *
080   * @return an immutable {@link SequencedSet} of {@link Assignment} instances; never {@code null}
081   *
082   * @exception NullPointerException if {@code r} is {@code null}
083   */
084  public default SequencedSet<? extends Assignment<?>> assign(final Function<? super AttributedType, ?> r) {
085    final Collection<? extends AttributedElement> ds = this.dependencies();
086    if (ds == null || ds.isEmpty()) {
087      return EMPTY_ASSIGNMENTS;
088    }
089    final SequencedSet<Assignment<?>> assignments = newLinkedHashSet(ds.size());
090    ds.forEach(d -> assignments.add(new Assignment<>(d, r.apply(d.attributedType()))));
091    return Collections.unmodifiableSequencedSet(assignments);
092  }
093
094}