001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 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.producer; 015 016import java.util.List; 017import java.util.Map; 018import java.util.Map.Entry; 019 020import java.util.function.Supplier; 021 022import javax.lang.model.element.ExecutableElement; 023 024import org.microbean.bean.Id; 025 026import org.microbean.construct.Domain; 027 028import org.microbean.interceptor.InterceptorMethod; 029 030import org.microbean.proxy.ProxySpecification; 031 032import static java.util.Collections.unmodifiableMap; 033 034import static java.util.HashMap.newHashMap; 035 036/** 037 * A creator of proxies for business method interceptions. 038 * 039 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 040 */ 041public interface InterceptionProxier { 042 043 /** 044 * Creates an <dfn>interception proxy</dfn> for a given contextual instance. 045 * 046 * @param <I> the contextual instance type 047 * 048 * @param id an {@link Id}; must not be {@code null} 049 * 050 * @param instanceSupplier a {@link Supplier} of contextual instances of the appropriate type; must not be {@code null} 051 * 052 * @param aroundInvokeInterceptions a {@link Map} of {@link InterceptorMethod}s indexed by the {@link 053 * ExecutableElement} to which they apply; must not be {@code null} 054 * 055 * @return a non-{@code null} interception proxy 056 * 057 * @exception NullPointerException if any argument is {@code null} 058 */ 059 public <I> I interceptionProxy(final Id id, 060 final Supplier<? extends I> instanceSupplier, 061 final Map<ExecutableElement, List<InterceptorMethod>> aroundInvokeInterceptions); 062 063 /** 064 * A {@link ProxySpecification} that exposes {@link InterceptorMethod}-related information. 065 * 066 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 067 * 068 * @see #interceptorMethods(ExecutableElement) 069 * 070 * @see ProxySpecification 071 * 072 * @see org.microbean.proxy.AbstractProxier#proxy(ProxySpecification, Supplier) 073 */ 074 public static class Specification extends ProxySpecification { 075 076 private final Map<ExecutableElement, List<InterceptorMethod>> aroundInvokeInterceptions; 077 078 /** 079 * Creates a new {@link Specification}. 080 * 081 * @param domain a {@link Domain}; must not be {@code null} 082 * 083 * @param id an {@link Id}; must not be {@code null} 084 * 085 * @param aroundInvokeInterceptions a {@link Map} of {@link InterceptorMethod}s indexed by the {@link 086 * ExecutableElement} to which they apply; must not be {@code null} 087 * 088 * @exception NullPointerException if any argument is {@code null} 089 */ 090 public Specification(final Domain domain, 091 final Id id, 092 final Map<ExecutableElement, List<InterceptorMethod>> aroundInvokeInterceptions) { 093 super(domain, id); 094 final Map<ExecutableElement, List<InterceptorMethod>> m = newHashMap(aroundInvokeInterceptions.size()); 095 for (final Entry<ExecutableElement, List<InterceptorMethod>> e : aroundInvokeInterceptions.entrySet()) { 096 m.put(e.getKey(), List.copyOf(e.getValue())); 097 } 098 this.aroundInvokeInterceptions = unmodifiableMap(m); 099 } 100 101 /** 102 * Returns a non-{@code null}, immutable, determinate {@link List} of {@link InterceptorMethod}s pertaining to the 103 * supplied {@link ExecutableElement}. 104 * 105 * @param ee an {@link ExecutableElement}; must not be {@code null} 106 * 107 * @return a non-{@code null}, immutable, determinate {@link List} of {@link InterceptorMethod}s pertaining to the 108 * supplied {@link ExecutableElement} 109 * 110 * @exception NullPointerException if {@code ee} is {@code null} 111 */ 112 public final List<InterceptorMethod> interceptorMethods(final ExecutableElement ee) { 113 final List<InterceptorMethod> ims = this.aroundInvokeInterceptions.get(ee); 114 return ims == null || ims.isEmpty() ? List.of() : ims; 115 } 116 117 } 118 119}