001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.server.mcp.v20260728;
018
019import java.util.*;
020
021/**
022 * Binding-owned, immutable-after-construction cache configuration for a v2 {@link McpRevision}.
023 *
024 * <p>
025 * Applications populate one {@link McpCacheConfig} and pass it to
026 * {@link McpRevision#McpRevision(org.apache.juneau.bean.mcp.v20260728.ServerCapabilities, McpCacheConfig)}. Every
027 * setter validates its {@link McpCacheHint} argument eagerly (including entries assigned via
028 * {@link #setResourceReadOverrides(Map)}), so an invalid TTL fails at configuration time rather than at dispatch
029 * time.
030 *
031 * <p>
032 * This type holds no resolution logic; precedence between {@link #getDefaultHint()}, the per-method hints, and
033 * {@link #getResourceReadOverrides()} is owned by {@link McpRevision}.
034 */
035public class McpCacheConfig {
036
037   private McpCacheHint defaultHint;
038   private McpCacheHint toolsList;
039   private McpCacheHint promptsList;
040   private McpCacheHint resourcesList;
041   private McpCacheHint resourceTemplatesList;
042   private McpCacheHint resourcesRead;
043   private McpCacheHint serverDiscover;
044   private Map<String,McpCacheHint> resourceReadOverrides = new LinkedHashMap<>();
045
046   private static McpCacheHint validate(McpCacheHint value) {
047      if (value != null && value.getTtlMs() != null && value.getTtlMs() < 0)
048         throw new IllegalArgumentException("ttlMs " + value.getTtlMs() + " is below minimum 0");
049      return value;
050   }
051
052   /**
053    * The fallback hint applied when a method-specific hint is not configured.
054    *
055    * @return The hint, or {@code null} if not set.
056    */
057   public McpCacheHint getDefaultHint() {
058      return defaultHint;
059   }
060
061   /**
062    * Sets the fallback hint.
063    *
064    * @param value The new value. Can be {@code null} to unset the property.
065    * @return This object.
066    */
067   public McpCacheConfig setDefaultHint(McpCacheHint value) {
068      defaultHint = validate(value);
069      return this;
070   }
071
072   /**
073    * The hint applied to {@code tools/list}.
074    *
075    * @return The hint, or {@code null} if not set.
076    */
077   public McpCacheHint getToolsList() {
078      return toolsList;
079   }
080
081   /**
082    * Sets the hint applied to {@code tools/list}.
083    *
084    * @param value The new value. Can be {@code null} to unset the property.
085    * @return This object.
086    */
087   public McpCacheConfig setToolsList(McpCacheHint value) {
088      toolsList = validate(value);
089      return this;
090   }
091
092   /**
093    * The hint applied to {@code prompts/list}.
094    *
095    * @return The hint, or {@code null} if not set.
096    */
097   public McpCacheHint getPromptsList() {
098      return promptsList;
099   }
100
101   /**
102    * Sets the hint applied to {@code prompts/list}.
103    *
104    * @param value The new value. Can be {@code null} to unset the property.
105    * @return This object.
106    */
107   public McpCacheConfig setPromptsList(McpCacheHint value) {
108      promptsList = validate(value);
109      return this;
110   }
111
112   /**
113    * The hint applied to {@code resources/list}.
114    *
115    * @return The hint, or {@code null} if not set.
116    */
117   public McpCacheHint getResourcesList() {
118      return resourcesList;
119   }
120
121   /**
122    * Sets the hint applied to {@code resources/list}.
123    *
124    * @param value The new value. Can be {@code null} to unset the property.
125    * @return This object.
126    */
127   public McpCacheConfig setResourcesList(McpCacheHint value) {
128      resourcesList = validate(value);
129      return this;
130   }
131
132   /**
133    * The hint applied to {@code resources/templates/list}.
134    *
135    * @return The hint, or {@code null} if not set.
136    */
137   public McpCacheHint getResourceTemplatesList() {
138      return resourceTemplatesList;
139   }
140
141   /**
142    * Sets the hint applied to {@code resources/templates/list}.
143    *
144    * @param value The new value. Can be {@code null} to unset the property.
145    * @return This object.
146    */
147   public McpCacheConfig setResourceTemplatesList(McpCacheHint value) {
148      resourceTemplatesList = validate(value);
149      return this;
150   }
151
152   /**
153    * The hint applied to {@code resources/read} when no per-URI override matches.
154    *
155    * @return The hint, or {@code null} if not set.
156    */
157   public McpCacheHint getResourcesRead() {
158      return resourcesRead;
159   }
160
161   /**
162    * Sets the hint applied to {@code resources/read} when no per-URI override matches.
163    *
164    * @param value The new value. Can be {@code null} to unset the property.
165    * @return This object.
166    */
167   public McpCacheConfig setResourcesRead(McpCacheHint value) {
168      resourcesRead = validate(value);
169      return this;
170   }
171
172   /**
173    * The hint applied to {@code server/discover}.
174    *
175    * @return The hint, or {@code null} if not set.
176    */
177   public McpCacheHint getServerDiscover() {
178      return serverDiscover;
179   }
180
181   /**
182    * Sets the hint applied to {@code server/discover}.
183    *
184    * @param value The new value. Can be {@code null} to unset the property.
185    * @return This object.
186    */
187   public McpCacheConfig setServerDiscover(McpCacheHint value) {
188      serverDiscover = validate(value);
189      return this;
190   }
191
192   /**
193    * Per-URI hint overrides for {@code resources/read}, keyed by exact resource URI.
194    *
195    * <p>
196    * Returns an unmodifiable view (in insertion order) so callers cannot bypass validation via direct mutation.
197    *
198    * @return An unmodifiable map. Never {@code null}.
199    */
200   public Map<String,McpCacheHint> getResourceReadOverrides() {
201      return Collections.unmodifiableMap(resourceReadOverrides);
202   }
203
204   /**
205    * Replaces the per-URI hint overrides.
206    *
207    * @param value The new value (or {@code null} to clear). Every entry is validated; a {@code null} URI key is
208    *    rejected.
209    * @return This object.
210    */
211   public McpCacheConfig setResourceReadOverrides(Map<String,McpCacheHint> value) {
212      var copy = new LinkedHashMap<String,McpCacheHint>();
213      if (value != null)
214         value.forEach((uri, hint) -> putValidated(copy, uri, hint));
215      resourceReadOverrides = copy;
216      return this;
217   }
218
219   /**
220    * Adds or replaces a single per-URI hint override.
221    *
222    * @param uri The exact resource URI. Must not be {@code null}.
223    * @param hint The hint. Can be {@code null}.
224    * @return This object.
225    */
226   public McpCacheConfig addResourceReadOverride(String uri, McpCacheHint hint) {
227      putValidated(resourceReadOverrides, uri, hint);
228      return this;
229   }
230
231   private static void putValidated(Map<String,McpCacheHint> target, String uri, McpCacheHint hint) {
232      if (uri == null)
233         throw new IllegalArgumentException("resourceReadOverrides URI must not be null");
234      target.put(uri, validate(hint));
235   }
236}