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.Objects; 018 019import javax.lang.model.type.TypeMirror; 020 021import org.microbean.assign.Matcher; 022 023import org.microbean.qualifier.NamedAttributeMap; 024 025/** 026 * A {@link Matcher} that tests an {@link Id} to see if it matches an {@link AttributedType}. 027 * 028 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 029 * 030 * @see #test(AttributedType, Id) 031 */ 032public final class IdMatcher implements Matcher<AttributedType, Id> { 033 034 private final BeanQualifiersMatcher qm; 035 036 private final InterceptorBindingsMatcher ibm; 037 038 private final BeanTypeMatcher tm; 039 040 /** 041 * Creates a new {@link IdMatcher}. 042 * 043 * @param qm a {@link BeanQualifiersMatcher}; must not be {@code null} 044 * 045 * @param ibm an {@link InterceptorBindingsMatcher}; must not be {@code null} 046 * 047 * @param tm a {@link BeanTypeMatcher}; must not be {@code null} 048 * 049 * @exception NullPointerException} if any argument is {@code null} 050 */ 051 public IdMatcher(final BeanQualifiersMatcher qm, 052 final InterceptorBindingsMatcher ibm, 053 final BeanTypeMatcher tm) { 054 super(); 055 this.qm = Objects.requireNonNull(qm, "qm"); 056 this.ibm = Objects.requireNonNull(ibm, "ibm"); 057 this.tm = Objects.requireNonNull(tm, "tm"); 058 } 059 060 /** 061 * Tests the supplied {@link Id} to see if it <dfn>matches</dfn> the supplied {@link AttributedType} and returns the 062 * result. 063 * 064 * <p>An {@link Id} <dfn>matches</dfn> an {@link AttributedType} if and only if all of the following are {@code 065 * true}:</p> 066 * 067 * <ol> 068 * 069 * <li>An invocation of the {@link BeanQualifiersMatcher#test(Collection, Collection)} method on the {@link 070 * BeanQualifiersMatcher} supplied at {@linkplain #IdMatcher(BeanQualifiersMatcher, InterceptorBindingsMatcher, 071 * BeanTypeMatcher) construction time} supplied with the supplied {@linkplain AttributedType#attributes() 072 * <code>AttributedType</code>'s attributes} and the supplied {@linkplain Id#attributes() <code>Id</code>'s 073 * attributes} returns {@code true}</li> 074 * 075 * <li>An invocation of the {@link InterceptorBindingsMatcher#test(Collection, Collection)} method on the {@link 076 * BeanQualifiersMatcher} supplied at {@linkplain #IdMatcher(BeanQualifiersMatcher, InterceptorBindingsMatcher, 077 * BeanTypeMatcher) construction time} supplied with the supplied {@linkplain AttributedType#attributes() 078 * <code>AttributedType</code>'s attributes} and the supplied {@linkplain Id#attributes() <code>Id</code>'s 079 * attributes} returns {@code true}</li> 080 * 081 * <li>An invocation of this {@link IdMatcher}'s {@link #test(TypeMirror, Iterable)} method supplied with the supplied 082 * {@linkplain AttributedType#type() <code>AttributedType</code>'s type} and the supplied {@linkplain Id#attributes() 083 * <code>Id</code>'s attributes} returns {@code true}</li> 084 * 085 * </ol> 086 * 087 * @param t an {@link AttributedType}; must not be {@code null} 088 * 089 * @param id an {@link Id}; must not be {@code null} 090 * 091 * @return {@code true} if {@code id} matches {@code t}; {@code false} otherwise 092 * 093 * @exception NullPointerException if any argument is {@code null} 094 * 095 * @see BeanQualifiersMatcher#test(Collection, Collection) 096 * 097 * @see InterceptorBindingsMatcher#test(Collection, Collection) 098 * 099 * @see #test(TypeMirror, Iterable) 100 * 101 * @see BeanTypeMatcher#test(TypeMirror, TypeMirror) 102 */ 103 @Override // Matcher<AttributedType, Id> (BiPredicate<AttributedType, Id>) 104 public final boolean test(final AttributedType t, final Id id) { 105 final Collection<? extends NamedAttributeMap<?>> attributes = t.attributes(); 106 final Collection<? extends NamedAttributeMap<?>> idAttributes = id.attributes(); 107 return 108 this.qm.test(attributes, idAttributes) && 109 this.ibm.test(attributes, idAttributes) && 110 this.test(t.type(), id.types()); 111 } 112 113 /** 114 * Tests the supplied {@link Iterable} of {@link TypeMirror}s to see if at least one {@link TypeMirror} it yields 115 * <dfn>matches</dfn> the supplied {@link TypeMirror} and returns the result. 116 * 117 * <p>A {@link TypeMirror} <em>t</em> from the supplied {@link Iterable} <dfn>matches</dfn> the supplied {@code type} 118 * argument if an invocation of the {@link BeanTypeMatcher#test(TypeMirror, TypeMirror)} method invoked on the 119 * {@linkplain #IdMatcher(BeanQualifiersMatcher, InterceptorBindingsMatcher, BeanTypeMatcher) 120 * <code>BeanTypeManager</code> supplied at construction time} supplied with {@code type} and <em>t</em> returns 121 * {@code true}.</p> 122 * 123 * @param type a {@link TypeMirror} to test against; must not be {@code null} 124 * 125 * @param ts an {@link Iterable} of {@link TypeMirror}s; must not be {@code null} 126 * 127 * @return {@code true} if at least one {@link TypeMirror} from {@code ts} matches {@code t} 128 * 129 * @exception NullPointerException if any argument is {@code null} 130 * 131 * @see BeanTypeMatcher#test(TypeMirror, TypeMirror) 132 */ 133 public final boolean test(final TypeMirror type, final Iterable<? extends TypeMirror> ts) { 134 Objects.requireNonNull(type, "type"); 135 for (final TypeMirror t : ts) { 136 if (this.tm.test(type, t)) { 137 return true; 138 } 139 } 140 return false; 141 } 142 143}