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.view;
018
019import java.util.*;
020
021import org.apache.juneau.rest.server.*;
022import org.apache.juneau.rest.server.processor.*;
023
024/**
025 * Engine-agnostic contract for a server-side-rendered template return value from an
026 * {@link RestOp @RestOp}-annotated method.
027 *
028 * <p>
029 * A {@code View} carries the information a templating engine needs to render a response: the
030 * <b>template name</b> (relative to a base path supplied by the corresponding mixin), an
031 * <b>attribute map</b> exposed to the template, and an optional <b>response-headers</b> seam for
032 * setting {@code Content-Type}, {@code Cache-Control}, or other headers on the rendered response.
033 *
034 * <p>
035 * The interface is deliberately minimal and engine-agnostic. Concrete implementations live in the
036 * per-engine bridge modules ({@code juneau-rest-server-view-jsp}, future
037 * {@code juneau-rest-server-view-thymeleaf} / {@code -mustache} / {@code -freemarker}), each
038 * paired with a {@link ResponseProcessor} that detects its own {@code View} subtype and dispatches
039 * to the underlying templating engine.
040 *
041 * <h5 class='figure'>End-state usage:</h5>
042 *
043 * <p class='bjava'>
044 *    <ja>@Rest</ja>(path=<js>"/app"</js>, mixins=JspMixin.<jk>class</jk>)
045 *    <jk>public class</jk> AppResource <jk>extends</jk> RestServlet {
046 *
047 *       <ja>@RestGet</ja>(<js>"/hello/{name}"</js>)
048 *       <jk>public</jk> View hello(<ja>@Path</ja> String <jv>name</jv>) {
049 *          <jk>return</jk> JspView.<jsm>of</jsm>(<js>"hello.jsp"</js>)
050 *             .attr(<js>"name"</js>, <jv>name</jv>)
051 *             .attr(<js>"ts"</js>, Instant.<jsm>now</jsm>());
052 *       }
053 *    }
054 * </p>
055 *
056 * <h5 class='section'>Contract:</h5>
057 *
058 * <ul class='spaced-list'>
059 *    <li>{@link #getTemplateName() getTemplateName()} &mdash; the template path the engine should
060 *       render, typically relative to a mixin-configured base path (e.g. {@code "hello.jsp"} with
061 *       base path {@code "/WEB-INF/views/"} resolves to {@code "/WEB-INF/views/hello.jsp"}).
062 *       <b>Must never be {@code null}.</b>
063 *    <li>{@link #getAttributes() getAttributes()} &mdash; key/value bindings exposed to the template
064 *       (e.g. {@code ${name}} in a JSP, {@code th:text="${name}"} in a Thymeleaf template). Returns
065 *       an immutable empty map when no attributes are bound. Must never be {@code null}.
066 *    <li>{@link #getResponseHeaders() getResponseHeaders()} &mdash; optional response-headers map
067 *       applied by the renderer before forwarding to the engine. Defaults to an empty map so most
068 *       implementations don't need to override it; engines that want to set {@code Content-Type}
069 *       or {@code Cache-Control} on the rendered response can populate this.
070 * </ul>
071 *
072 * <h5 class='section'>Stability:</h5>
073 *
074 * <p>
075 * This interface is the stable extension point for view modules. New methods will be added as
076 * {@code default}-bodied where possible to preserve backward compatibility with downstream view
077 * impls.
078 *
079 * <h5 class='section'>See Also:</h5><ul>
080 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JspViewSupport">JSP View Support</a>
081 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerComposition">REST Server — Mixins and Multi-Mount Paths</a>
082 * </ul>
083 *
084 * @since 10.0.0
085 */
086public interface View {
087
088   /**
089    * The name of the template to render &mdash; typically a path relative to the
090    * mixin-configured base path.
091    *
092    * <p>
093    * For example, {@code "hello.jsp"} with a JSP mixin {@code basePath("/WEB-INF/views/")}
094    * resolves to {@code "/WEB-INF/views/hello.jsp"} on the request dispatcher.
095    *
096    * @return The template name. Never {@code null}.
097    */
098   String getTemplateName();
099
100   /**
101    * The attributes to expose to the template.
102    *
103    * <p>
104    * Each entry is forwarded to the templating engine as a named binding accessible from inside
105    * the template (e.g. {@code ${name}} in JSP / EL, {@code th:text="${name}"} in Thymeleaf).
106    *
107    * @return The attributes map. Never {@code null}; returns an immutable empty map when no
108    *    attributes are bound.
109    */
110   Map<String,Object> getAttributes();
111
112   /**
113    * Optional response headers applied by the renderer before forwarding to the templating
114    * engine.
115    *
116    * <p>
117    * Typical use cases: setting {@code Content-Type} (e.g. {@code "text/html; charset=UTF-8"}) or
118    * {@code Cache-Control} on the rendered response. The default implementation returns an empty
119    * map so most {@code View} impls don't need to override it.
120    *
121    * @return An immutable map of headers to apply. Never {@code null}; defaults to an empty map.
122    */
123   default Map<String,String> getResponseHeaders() {
124      return Map.of();
125   }
126}