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.bean.rfc7807;
018
019import java.util.*;
020
021/**
022 * SPI seam for locale-aware translation of {@link Problem#getTitle()} / {@link Problem#getDetail()} (and any other
023 * human-readable fields) before serialization.
024 *
025 * <p>
026 * The default in-tree implementation is {@link #IDENTITY} &mdash; a pass-through that returns the input unchanged.
027 * Server-side wiring consults the resource's bean store for a registered {@code ProblemLocalizationStrategy} bean,
028 * and falls back to {@link #IDENTITY} when none is registered, so the seam is invisible at zero cost on the hot
029 * path until a deliberate strategy is contributed.
030 *
031 * <h5 class='section'>Status</h5>
032 * <p>
033 * This interface is shipped in {@code juneau-bean-rfc7807} as the future-work hook for an eventual
034 * {@code Messages}-driven (resource-bundle) translation pass. The reference {@code Messages} integration is
035 * intentionally out of scope for the v1 RFC 7807 server wiring; the no-op {@link #IDENTITY} default keeps the
036 * call site stable so a future implementation can be dropped in without changing the processor contract.
037 *
038 * <h5 class='section'>Example</h5>
039 * <p class='bjava'>
040 *    <ja>@Bean</ja>
041 *    <jk>public</jk> ProblemLocalizationStrategy localize() {
042 *       <jk>return</jk> (<jv>p</jv>, <jv>locale</jv>) -&gt; {
043 *          <jc>// Future work: look up titles/details from a ResourceBundle keyed by locale.</jc>
044 *          <jk>return</jk> <jv>p</jv>;
045 *       };
046 *    }
047 * </p>
048 *
049 * <h5 class='section'>See Also:</h5><ul>
050 *    <li class='jc'>{@link Problem}
051 *    <li class='jc'>{@link ProblemMapper}
052 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerProblemDetails">RFC 7807 / 9457 Problem Details</a>
053 * </ul>
054 */
055@FunctionalInterface
056public interface ProblemLocalizationStrategy {
057
058   /**
059    * Default no-op strategy. Returns the input {@link Problem} unchanged.
060    *
061    * <p>
062    * The server-side processor uses this constant as the fallback whenever no
063    * {@code ProblemLocalizationStrategy} bean is registered with the resource. Implementations that need to opt
064    * out of localization for a specific {@link Problem} can return this constant's behavior by simply returning
065    * the input.
066    */
067   ProblemLocalizationStrategy IDENTITY = (problem, locale) -> problem;
068
069   /**
070    * Translates the supplied {@link Problem} for the given {@link Locale}.
071    *
072    * <p>
073    * Implementations may mutate and return the input {@link Problem}, or return a fresh bean &mdash; the
074    * processor treats the return value as the bean to serialize. A {@code null} return is treated as "no opinion"
075    * and the original (pre-localization) {@link Problem} is used instead.
076    *
077    * @param problem The {@link Problem} to localize. Never <jk>null</jk>.
078    * @param locale The negotiated locale for the current request, or <jk>null</jk> when no locale is available.
079    * @return The localized {@link Problem} to emit, or the input {@code problem} for pass-through.
080    */
081   Problem localize(Problem problem, Locale locale);
082}