001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2023 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.ArrayList;
017import java.util.Collection;
018import java.util.Collections;
019import java.util.List;
020import java.util.Map;
021import java.util.Objects;
022
023import org.microbean.qualifier.NamedAttributeMap;
024
025/**
026 * A utility class providing methods that work with interceptor bindings.
027 *
028 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a>
029 */
030public final class InterceptorBindings {
031
032  private static final NamedAttributeMap<String> INTERCEPTOR_BINDING = new NamedAttributeMap<>("InterceptorBinding");
033
034  private static final List<NamedAttributeMap<String>> INTERCEPTOR_BINDING_LIST = List.of(INTERCEPTOR_BINDING);
035
036  private static final NamedAttributeMap<String> ANY_INTERCEPTOR_BINDING =
037    new NamedAttributeMap<>("Any", Map.of(), Map.of(), INTERCEPTOR_BINDING_LIST);
038
039  private InterceptorBindings() {
040    super();
041  }
042
043  public static final NamedAttributeMap<String> anyInterceptorBinding() {
044    return ANY_INTERCEPTOR_BINDING;
045  }
046
047  public static final boolean anyInterceptorBinding(final NamedAttributeMap<?> nam) {
048    return ANY_INTERCEPTOR_BINDING.equals(nam) && interceptorBinding(nam);
049  }
050
051  public static final NamedAttributeMap<String> interceptorBinding() {
052    return INTERCEPTOR_BINDING;
053  }
054
055  public static final boolean interceptorBinding(final NamedAttributeMap<?> a) {
056    return a != null && interceptorBinding(a.metadata());
057  }
058
059  private static final boolean interceptorBinding(final Iterable<? extends NamedAttributeMap<?>> mds) {
060    for (final NamedAttributeMap<?> md : mds) {
061      if (md.equals(INTERCEPTOR_BINDING) && md.metadata().isEmpty() || interceptorBinding(md)) {
062        return true;
063      }
064    }
065    return false;
066  }
067
068  /**
069   * Given a {@link Collection} of {@link NamedAttributeMap}s, returns a {@link List} consisting of those {@link
070   * NamedAttributeMap} instances that are {@linkplain #interceptorBinding() deemed to be interceptor bindings}.
071   *
072   * @param c a {@link Collection}; must not be {@code null}
073   *
074   * @return a {@link List} of interceptor bindings
075   */
076  public static final List<NamedAttributeMap<?>> interceptorBindings(final Collection<? extends NamedAttributeMap<?>> c) {
077    if (c.isEmpty()) {
078      return List.of();
079    }
080    final ArrayList<NamedAttributeMap<?>> list = new ArrayList<>(c.size());
081    for (final NamedAttributeMap<?> nam : c) {
082      if (interceptorBinding(nam)) {
083        list.add(nam);
084      }
085    }
086    list.trimToSize();
087    return Collections.unmodifiableList(list);
088  }
089
090  public static final NamedAttributeMap<?> targetClassInterceptorBinding(final String type) {
091    return new NamedAttributeMap<String>("TargetClass", Map.of("class", Objects.requireNonNull(type, "type")), Map.of(), INTERCEPTOR_BINDING_LIST);
092  }
093
094  // Is nam a TargetClass interceptor binding?
095  public static final boolean targetClassInterceptorBinding(final NamedAttributeMap<?> nam) {
096    return nam.name().equals("TargetClass") && interceptorBinding(nam);
097  }
098
099}