001package io.jstach.opt.spring.webmvc;
002
003import java.util.Map;
004
005import org.springframework.web.servlet.View;
006import org.springframework.web.servlet.view.RedirectView;
007
008import io.jstach.jstache.JStache;
009import io.jstach.jstache.JStacheInterfaces;
010import io.jstach.jstachio.JStachio;
011import jakarta.servlet.http.HttpServletRequest;
012import jakarta.servlet.http.HttpServletResponse;
013
014/**
015 * Another way to use JStachio with Spring MVC is to have models implement Springs
016 * {@link View} interface. You can enforce that your models implement this interface with
017 * {@link JStacheInterfaces}.
018 * <p>
019 * The model will use the static jstachio singleton that will be the spring one.
020 * <p>
021 * This approach has pros and cons. It makes your models slightly coupled to Spring MVC
022 * but allows you to return different views if say you had to redirect on some inputs
023 * ({@link RedirectView}).
024 *
025 * @author agentgt
026 *
027 */
028public interface JStachioModelView extends View {
029
030        @SuppressWarnings("exports")
031        @Override
032        default void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
033                        throws Exception {
034
035                String contentType = getContentType();
036                if (contentType != null) {
037                        response.setContentType(contentType);
038                }
039                try (var w = response.getWriter()) {
040                        jstachio().execute(model(), w);
041                }
042
043        }
044
045        /**
046         * Returns the jstachio singleton by default.
047         * @return stachio singleton by default.
048         * @see JStachio#setStaticJStachio(java.util.function.Supplier)
049         */
050        default JStachio jstachio() {
051                return JStachio.of();
052        }
053
054        /**
055         * The model to be rendered by {@link #jstachio()}.
056         * @return model defaulting to <code>this</code> instance.
057         */
058        default Object model() {
059                return this;
060        }
061
062        /**
063         * Creates a spring view from a model with content type:
064         * "<code>text/html; charset=utf-8</code>".
065         * @param model an instance of a class annotated with {@link JStache}.
066         * @return view ready for rendering
067         */
068        public static JStachioModelView of(Object model) {
069                return of(model, "text/html; charset=utf-8");
070        }
071
072        /**
073         * Creates a spring view from a model.
074         * @param model an instance of a class annotated with {@link JStache}.
075         * @param contentType See {@link #getContentType()}
076         * @return view ready for rendering
077         */
078        public static JStachioModelView of(Object model, String contentType) {
079                return new JStachioModelView() {
080                        @Override
081                        public Object model() {
082                                return model;
083                        }
084
085                        @Override
086                        public String getContentType() {
087                                return contentType;
088                        }
089                };
090        }
091
092}