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.api; 020 021import java.time.Instant; 022import java.util.Optional; 023import java.util.stream.Stream; 024 025/// Defines a container for a collection of resources. Implementations 026/// must behave as sets (no duplicate entries) and must maintain insertion 027/// order when providing the content through [stream]. 028/// 029/// @param <T> the contained type 030/// 031public interface Resources<T extends Resource> extends Resource { 032 033 /// Adds the given resource. 034 /// 035 /// @param resource the resource 036 /// @return the resources 037 /// 038 Resources<T> add(T resource); 039 040 /// Adds all resources from the given collection. 041 /// 042 /// @param resources the resources to add 043 /// @return the resources 044 /// 045 default Resources<T> addAll(Resources<? extends T> resources) { 046 return addAll(resources.stream()); 047 } 048 049 /// Adds all resources from the given stream. This terminates the given 050 /// stream. 051 /// 052 /// @param resources the resources to add 053 /// @return the resources 054 /// 055 default Resources<T> addAll(Stream<? extends T> resources) { 056 resources.forEach(this::add); 057 return this; 058 } 059 060 /// As of. 061 /// 062 /// @return the instant 063 /// 064 @Override 065 default Optional<Instant> asOf() { 066 return stream() 067 .reduce((newest, next) -> next.isNewerThan(newest) ? next : newest) 068 .map(Resource::asOf).orElse(Optional.empty()); 069 } 070 071 /// Checks if is empty. 072 /// 073 /// @return true, if is empty 074 /// 075 boolean isEmpty(); 076 077 /// Retrieves the resources as a stream. 078 /// 079 /// @return the stream 080 /// 081 Stream<T> stream(); 082 083 /// Clears the contained resources. 084 /// 085 /// @return the resources 086 /// 087 Resources<T> clear(); 088 089 /// Creates a new resource container with elements of the given type. 090 /// 091 /// @param <T> the generic type 092 /// @param type the type 093 /// @return the resources container 094 /// 095 @SuppressWarnings("unchecked") 096 static <T extends Resource> Resources<T> with(Class<T> type) { 097 return (Resources<T>) of(ResourceType.create(Resources.class, type)); 098 } 099 100 /// Creates a new resource container with elements of the given type. 101 /// 102 /// @param <T> the generic type 103 /// @param type the type 104 /// @return the resources container 105 /// 106 static <T extends Resource> Resources<T> with(ResourceType<T> type) { 107 return of(new ResourceType<>(Resources.class, type)); 108 } 109 110 /// Creates a new resource container with the specified container 111 /// and elements type. 112 /// 113 /// @param <T> the generic type 114 /// @param type the type 115 /// @return the resources container 116 /// 117 @SuppressWarnings("PMD.ShortMethodName") 118 static <T extends Resource> T of(ResourceType<T> type) { 119 return ResourceFactory.create(type); 120 } 121}