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 java.nio.file.Path; 022import java.util.Optional; 023import static java.util.function.Predicate.not; 024import java.util.stream.Collectors; 025import org.jdrupes.builder.api.FileResource; 026import org.jdrupes.builder.api.FileTree; 027import org.jdrupes.builder.api.Project; 028import org.jdrupes.builder.api.Resource; 029import org.jdrupes.builder.api.ResourceFactory; 030import org.jdrupes.builder.api.ResourceType; 031import org.jdrupes.builder.api.Resources; 032 033/// A factory for creating the Core resource objects. 034/// 035public class CoreResourceFactory implements ResourceFactory { 036 037 /// Instantiates a new core resource factory. 038 /// 039 @SuppressWarnings("PMD.UnnecessaryConstructor") 040 public CoreResourceFactory() { 041 // Make javadoc happy. 042 } 043 044 /// Checks if the derived interface adds any methods to the 045 /// base interface. 046 /// 047 /// @param <T> the generic type 048 /// @param base the base 049 /// @param derived the derived 050 /// @return true, if successful 051 /// 052 public static <T> boolean addsMethod( 053 Class<T> base, Class<? extends T> derived) { 054 var baseItfs = ResourceType.getAllInterfaces(base) 055 .collect(Collectors.toSet()); 056 return ResourceType.getAllInterfaces(derived) 057 .filter(not(baseItfs::contains)) 058 .filter(itf -> itf.getDeclaredMethods().length > 0).findAny() 059 .isPresent(); 060 } 061 062 @Override 063 @SuppressWarnings({ "unchecked" }) 064 public <T extends Resource> Optional<T> newResource(ResourceType<T> type, 065 Project project, Object... args) { 066 if (ResourceType.FileResourceType.isAssignableFrom(type) 067 && type.rawType().getSuperclass() == null 068 && !addsMethod(FileResource.class, 069 (Class<? extends FileResource>) type.rawType())) { 070 return Optional.of((T) DefaultFileResource.createFileResource( 071 (ResourceType<? extends FileResource>) type, (Path) args[0])); 072 } 073 if (Resources.class.isAssignableFrom(type.rawType()) 074 && type.rawType().getSuperclass() == null 075 && !addsMethod(Resources.class, 076 (Class<? extends Resources<?>>) type.rawType())) { 077 return Optional.of((T) DefaultResources.createResources( 078 (ResourceType<? extends Resources<?>>) type)); 079 } 080 if (FileTree.class.isAssignableFrom(type.rawType()) 081 && type.rawType().getSuperclass() == null 082 && !addsMethod(FileTree.class, 083 (Class<? extends FileTree<?>>) type.rawType())) { 084 return Optional.of( 085 (T) DefaultFileTree.createFileTree( 086 (ResourceType<? extends FileTree<?>>) type, 087 project, (Path) args[0], (String) args[1])); 088 } 089 if (Resource.class.isAssignableFrom(type.rawType()) 090 && type.rawType().getSuperclass() == null 091 && !addsMethod(Resource.class, 092 (Class<? extends Resource>) type.rawType())) { 093 return Optional.of((T) ResourceObject.createResource( 094 (ResourceType<?>) type)); 095 } 096 return Optional.empty(); 097 } 098 099}