001/* 002 * JDrupes Builder 003 * Copyright (C) 2025 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.stream.Stream; 024import org.jdrupes.builder.api.Renamable; 025import org.jdrupes.builder.api.Resource; 026import org.jdrupes.builder.api.ResourceFactory; 027import org.jdrupes.builder.api.ResourceProvider; 028import org.jdrupes.builder.api.ResourceProviderSpi; 029import org.jdrupes.builder.api.ResourceRequest; 030import org.jdrupes.builder.api.ResourceType; 031import org.jdrupes.builder.api.Resources; 032 033/// A base implementation for[ResourceProvider]s. 034/// 035public abstract class AbstractProvider implements ResourceProvider { 036 037 private static final FluentLogger logger = FluentLogger.forEnclosingClass(); 038 private String name; 039 040 /// Initializes a new abstract provider. 041 /// 042 public AbstractProvider() { 043 // Default name 044 name = getClass().getSimpleName(); 045 if (name.isBlank()) { 046 name = "Adapted " + getClass().getSuperclass().getSimpleName(); 047 } 048 } 049 050 @Override 051 public String name() { 052 return name; 053 } 054 055 /// Allows derived classes to change the provider's name in their 056 /// implementation of [Renamable#name]. Throws an 057 /// [UnsupportedOperationException] if the derived class does not 058 /// implement [Renamable]. 059 /// 060 /// @param name the name 061 /// @return the abstract provider 062 /// 063 protected final AbstractProvider rename(String name) { 064 if (!(this instanceof Renamable)) { 065 throw new UnsupportedOperationException(getClass().getName() 066 + " does not implement " + Renamable.class.getName()); 067 } 068 this.name = name; 069 return this; 070 } 071 072 /* default */ ResourceProviderSpi toSpi() { 073 return new ResourceProviderSpi() { 074 @Override 075 public <T extends Resource> Stream<T> 076 provide(ResourceRequest<T> requested) { 077 if (!FutureStream.isProviderInvocationAllowed()) { 078 logger.atWarning().withStackTrace(MEDIUM) 079 .log("Direct invocation of %s is not allowed", this); 080 } 081 return doProvide(requested); 082 } 083 }; 084 } 085 086 /// Invoked by [ResourceProviderSpi#provide] after checking if the 087 /// invocation is allowed. 088 /// 089 /// @param <T> the generic type 090 /// @param requested the requested 091 /// @return the stream 092 /// 093 protected abstract <T extends Resource> Stream<T> 094 doProvide(ResourceRequest<T> requested); 095 096 @Override 097 @SuppressWarnings("PMD.ShortMethodName") 098 public <T extends Resource> ResourceRequest<T> 099 of(ResourceType<? extends T> type) { 100 return new DefaultResourceRequest<>(type); 101 } 102 103 @Override 104 public DefaultBuildContext context() { 105 return LauncherSupport.buildContext(); 106 } 107 108 /// Convenience function to create a new resource. Short for invoking 109 /// [ResourceFactory#create] with the requested resource type, 110 /// `null` for the project and the remaining given arguments appended. 111 /// 112 /// @param <T> the resource type 113 /// @param type the type 114 /// @param args the arguments 115 /// @return the resource 116 /// 117 protected <T extends Resource> T newResource(ResourceType<T> type, 118 Object... args) { 119 return ResourceFactory.create(type, null, args); 120 } 121 122 /// Retrieves the resources as a Vavr stream. 123 /// 124 /// @param <T> the resource type 125 /// @param resources the resources 126 /// @return the stream 127 /// 128 public <T extends Resource> io.vavr.collection.Stream<T> 129 vavrStream(Resources<T> resources) { 130 return io.vavr.collection.Stream.ofAll(resources.stream()); 131 } 132 133 @Override 134 public String toString() { 135 return "Provider " + getClass().getSimpleName(); 136 } 137}