001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2024 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;
017
018import java.util.function.Predicate;
019
020import org.microbean.qualifier.NamedAttributeMap;
021
022import static org.microbean.bean.Qualifiers.anyQualifier;
023import static org.microbean.bean.Qualifiers.defaultQualifier;
024import static org.microbean.bean.Qualifiers.defaultQualifiers;
025import static org.microbean.bean.Qualifiers.qualifiers;
026
027public final class QualifiersMatcher implements Matcher<Collection<? extends NamedAttributeMap<?>>, Collection<? extends NamedAttributeMap<?>>> {
028
029  public QualifiersMatcher() {
030    super();
031  }
032
033  @Override // Matcher<Collection<? extends NamedAttributeMap<?>>, Collection<? extends NamedAttributeMap<?>>>
034  public final boolean test(final Collection<? extends NamedAttributeMap<?>> receiverAttributes,
035                            final Collection<? extends NamedAttributeMap<?>> payloadAttributes) {
036    final Collection<? extends NamedAttributeMap<?>> receiverQualifiers = qualifiers(receiverAttributes);
037    final Collection<? extends NamedAttributeMap<?>> payloadQualifiers = qualifiers(payloadAttributes);
038    if (receiverQualifiers.isEmpty()) {
039      // Pretend receiver had [@Default] and payload had at least [@Default] (e.g. [@Default, @Any])
040      return payloadQualifiers.isEmpty() || containsAllMatching(payloadQualifiers::contains, defaultQualifiers());
041    } else if (payloadQualifiers.isEmpty()) {
042      for (final NamedAttributeMap<?> receiverQualifier : receiverQualifiers) {
043        if (anyQualifier(receiverQualifier) || defaultQualifier(receiverQualifier)) {
044          // receiver had [@Default] or [@Any] or [@Default, @Any]; pretend payload had [@Default, @Any].
045          return true;
046        }
047      }
048      return false;
049    }
050    return containsAllMatching(payloadQualifiers::contains, receiverQualifiers);
051  }
052
053  private static final boolean containsAllMatching(final Predicate<? super Object> p, final Iterable<?> i) {
054    for (final Object o : i) {
055      if (!p.test(o)) {
056        return false;
057      }
058    }
059    return true;
060  }
061
062}