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; 017import java.util.Collections; 018import java.util.LinkedHashSet; 019import java.util.Objects; 020import java.util.SequencedSet; 021 022import org.microbean.interceptor.InterceptionFunction; 023import org.microbean.interceptor.InterceptorMethod; 024 025import static org.microbean.interceptor.Interceptions.ofConstruction; 026 027// Applies around-construct logic to contextual instance production. 028public final class InterceptingProducer<I> implements Producer<I> { 029 030 private final InterceptionFunction f; 031 032 private final Producer<I> producer; 033 034 @SuppressWarnings("unchecked") 035 public InterceptingProducer(final Collection<? extends InterceptorMethod> interceptorMethods, 036 final Producer<I> producer) { 037 super(); 038 this.producer = Objects.requireNonNull(producer, "producer"); 039 final SequencedSet<AttributedElement> dependencies = producer.dependencies(); 040 this.f = ofConstruction(interceptorMethods, (ignored, argumentsArray) -> { 041 final SequencedSet<Assignment<?>> assignments = new LinkedHashSet<>(); 042 int i = 0; 043 for (final AttributedElement dependency : dependencies) { 044 assignments.add(new Assignment<>(dependency, argumentsArray[i++])); 045 } 046 return this.produce(Collections.unmodifiableSequencedSet(assignments)); 047 }); 048 } 049 050 @Override // Producer<I> (Aggregate) 051 public final SequencedSet<? extends Assignment<?>> assign(final Request<?> r) { 052 return this.producer.assign(r); 053 } 054 055 @Override // Producer<I> (Aggregate) 056 public final SequencedSet<AttributedElement> dependencies() { 057 return this.producer.dependencies(); 058 } 059 060 @Override // Producer<I> 061 public final void dispose(final I i, final Request<I> r) { 062 this.producer.dispose(i, r); 063 } 064 065 @Override // Producer<I> 066 @SuppressWarnings("unchecked") 067 public final I produce(final Request<?> r) { 068 final Collection<? extends AttributedElement> dependencies = this.dependencies(); 069 final Object[] array = new Object[dependencies.size()]; 070 int i = 0; 071 for (final AttributedElement d : dependencies) { 072 array[i++] = r.reference(d.attributedType()); 073 } 074 return (I)this.f.apply(array); 075 } 076 077 @Override // Producer<I> 078 public final I produce(final SequencedSet<? extends Assignment<?>> assignments) { 079 return this.producer.produce(assignments); 080 } 081 082}