001/* 002 * JDrupes Builder 003 * Copyright (C) 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 java.util.Arrays; 022import java.util.EnumSet; 023import java.util.Objects; 024import java.util.Set; 025import org.jdrupes.builder.api.Cleanliness; 026import org.jdrupes.builder.api.Generator; 027import org.jdrupes.builder.api.Intent; 028import static org.jdrupes.builder.api.Intent.*; 029import org.jdrupes.builder.api.Project; 030import org.jdrupes.builder.api.Resource; 031import org.jdrupes.builder.api.ResourceProvider; 032import org.jdrupes.builder.api.ResourceQuery; 033import org.jdrupes.builder.api.ResourceType; 034 035/// Represents a request for [Resource]s of a specified type. 036/// The specified type provides two kinds of type information: 037/// 038/// 1. The type of the [Resource]s that are actually provided. 039/// 2. The type of the "context" in which the [Resource]s are to be provided. 040/// 041/// As an example, consider requests for a compile time and a runtime 042/// classpath. In both cases, the actually provided [Resource]s are 043/// of type "classpath element". However, depending on the kind of 044/// classpath, a [ResourceProvider] may deliver different collections of 045/// instances of "classpath elements". So instead of requesting 046/// "classpath element", 047/// 048/// Not all requested resource types require context information. For 049/// example, a request for [Cleanliness] usually refers to all resources 050/// that a [Generator] has created and does not depend on a context. 051/// However, in order to keep the API simple, the context is always 052/// required. 053/// 054/// @param <T> the generic type 055/// 056public class DefaultResourceQuery<T extends Resource> 057 implements ResourceQuery<T> { 058 059 private final ResourceType<? extends T> type; 060 private final Project[] queried; 061 private Set<Intent> uses; 062 063 /// Instantiates a new resource request without any restriction. 064 /// 065 /// @param type the requested type 066 /// 067 /* default */ DefaultResourceQuery(ResourceType<? extends T> type) { 068 this(type, EnumSet.of(Supply, Expose), new Project[0]); 069 } 070 071 @SuppressWarnings("PMD.UseVarargs") 072 private DefaultResourceQuery(ResourceType<? extends T> type, 073 Set<Intent> using, Project[] queried) { 074 this.type = type; 075 uses = using; 076 this.queried = queried; 077 } 078 079 @Override 080 public ResourceQuery<T> using(Set<Intent> intends) { 081 uses = intends; 082 return this; 083 } 084 085 @Override 086 public Set<Intent> uses() { 087 return EnumSet.copyOf(uses); 088 } 089 090 @Override 091 public ResourceType<? extends T> type() { 092 return type; 093 } 094 095 @Override 096 public boolean wants(ResourceType<?> type) { 097 return this.type.isAssignableFrom(type); 098 } 099 100 @SuppressWarnings("PMD.MethodReturnsInternalArray") 101 /* default */ Project[] queried() { 102 return queried; 103 } 104 105 /* default */ DefaultResourceQuery<T> queried(Project project) { 106 var newQueried = Arrays.copyOf(queried, queried.length + 1); 107 newQueried[newQueried.length - 1] = project; 108 return new DefaultResourceQuery<>(type(), uses, newQueried); 109 } 110 111 @Override 112 public int hashCode() { 113 return Objects.hash(type, uses); 114 } 115 116 @Override 117 public boolean equals(Object obj) { 118 if (this == obj) { 119 return true; 120 } 121 if (obj == null) { 122 return false; 123 } 124 if (getClass() != obj.getClass()) { 125 return false; 126 } 127 DefaultResourceQuery<?> other = (DefaultResourceQuery<?>) obj; 128 return Objects.equals(type, other.type) 129 && Objects.equals(uses, other.uses); 130 } 131 132 @Override 133 public String toString() { 134 return "ResourceRequest<" + type + ">"; 135 } 136 137}