001/* 002 * JDrupes Builder 003 * Copyright (C) 2025, 2026 Michael N. Lipp 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <https://www.gnu.org/licenses/>. 017 */ 018 019package org.jdrupes.builder.core; 020 021import com.google.common.flogger.FluentLogger; 022import static com.google.common.flogger.StackSize.*; 023import java.util.Collection; 024import org.jdrupes.builder.api.Renamable; 025import org.jdrupes.builder.api.Resource; 026import org.jdrupes.builder.api.ResourceProvider; 027import org.jdrupes.builder.api.ResourceProviderSpi; 028import org.jdrupes.builder.api.ResourceRequest; 029import org.jdrupes.builder.api.ResourceType; 030import org.jdrupes.builder.api.Resources; 031 032/// A base implementation for[ResourceProvider]s. 033/// 034public abstract class AbstractProvider implements ResourceProvider { 035 036 private static final FluentLogger logger = FluentLogger.forEnclosingClass(); 037 private String name; 038 039 /// Initializes a new abstract provider. 040 /// 041 public AbstractProvider() { 042 // Check that context is available 043 LauncherBase.context(); 044 // Default name 045 name = getClass().getSimpleName(); 046 if (name.isBlank()) { 047 name = "Adapted " + getClass().getSuperclass().getSimpleName(); 048 } 049 } 050 051 @Override 052 public String name() { 053 return name; 054 } 055 056 /// Allows derived classes to change the provider's name in their 057 /// implementation of [Renamable#name]. Throws an 058 /// [UnsupportedOperationException] if the derived class does not 059 /// implement [Renamable]. 060 /// 061 /// @param name the name 062 /// @return the abstract provider 063 /// 064 protected final AbstractProvider rename(String name) { 065 if (!(this instanceof Renamable)) { 066 throw new UnsupportedOperationException(getClass().getName() 067 + " does not implement " + Renamable.class.getName()); 068 } 069 this.name = name; 070 return this; 071 } 072 073 /* default */ ResourceProviderSpi toSpi() { 074 return new ResourceProviderSpi() { 075 @Override 076 public <T extends Resource> Collection<T> 077 provide(ResourceRequest<T> requested) { 078 if (!DefaultBuildContext.isProviderInvocationAllowed()) { 079 logger.atWarning().withStackTrace(MEDIUM) 080 .log("Direct invocation of %s is not allowed", this); 081 } 082 return doProvide(requested); 083 } 084 }; 085 } 086 087 /// Invoked by [ResourceProviderSpi#provide] after checking if the 088 /// invocation is allowed. 089 /// 090 /// @param <T> the generic type 091 /// @param request the request for resources 092 /// @return the stream 093 /// 094 protected abstract <T extends Resource> Collection<T> 095 doProvide(ResourceRequest<T> request); 096 097 @Override 098 @SuppressWarnings("PMD.ShortMethodName") 099 public <T extends Resource> ResourceRequest<T> 100 of(ResourceType<? extends T> type) { 101 return new DefaultResourceRequest<>(type); 102 } 103 104 @Override 105 public DefaultBuildContext context() { 106 return LauncherBase.context(); 107 } 108 109 /// Retrieves the resources as a Vavr stream. 110 /// 111 /// @param <T> the resource type 112 /// @param resources the resources 113 /// @return the stream 114 /// 115 public <T extends Resource> io.vavr.collection.Stream<T> 116 vavrStream(Resources<T> resources) { 117 return io.vavr.collection.Stream.ofAll(resources.stream()); 118 } 119 120 @Override 121 public String toString() { 122 if (name().equals(getClass().getSimpleName())) { 123 return getClass().getSimpleName(); 124 } 125 return "Provider " + name(); 126 } 127}