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.petstore.console; 018 019import org.apache.juneau.commons.inject.*; 020import org.apache.juneau.petstore.console.dev.*; 021import org.apache.juneau.petstore.service.*; 022import org.apache.juneau.rest.server.*; 023import org.apache.juneau.console.datatables.*; 024import org.apache.juneau.rest.server.servlet.*; 025import org.apache.juneau.rest.server.staticfile.*; 026import org.apache.juneau.rest.server.view.*; 027import org.apache.juneau.rest.server.view.freemarker.*; 028import org.apache.juneau.console.freemarker.*; 029import org.apache.juneau.console.views.*; 030 031/** 032 * Base class for every petstore console page resource: registers the console FreeMarker mixin with 033 * {@code base.ftlh} as chrome, and injects the shared {@link PetStore}. 034 * 035 * <p> 036 * Children don't inherit the parent's mixins, so every page class extends this one instead of re-declaring the 037 * mixin, which E-B12 would reject. 038 * 039 * <p> 040 * The views and DataTables toolkit packs link their assets page-relative (e.g. {@code /console/store/juneau-views.js}), 041 * so every page also composes {@link ViewsMixin} and {@link DataTablesMixin} to serve them from its own mount. 042 * 043 * <h5 class='section'>Example:</h5> 044 * <p class='bjava'> 045 * <ja>@Rest</ja>(path=<js>"/ops/audit"</js>) 046 * <jk>public class</jk> AuditRest <jk>extends</jk> PetstoreConsolePage { 047 * <ja>@RestGet</ja>(path=<js>"/"</js>) 048 * <jk>public</jk> View page() { <jk>return</jk> FreemarkerView.<jsm>of</jsm>(<js>"audit.ftlh"</js>); } 049 * } 050 * </p> 051 */ 052@Rest(mixins={FreemarkerMixin.class, ViewsMixin.class, DataTablesMixin.class, WebJarsMixin.class}, responseProcessors=FreemarkerViewRenderer.class) 053public abstract class PetstoreConsolePage extends BasicRestServlet { 054 055 private static final long serialVersionUID = 1L; 056 057 /** Classpath folder holding the console templates. */ 058 public static final String TEMPLATES = "/org/apache/juneau/petstore/console/templates/"; 059 060 /** Response header naming the render path of a builder-twin page, so a twin test can tell the two paths apart. */ 061 public static final String PAGE_HEADER = "X-Petstore-Page"; 062 063 /** 064 * Whether this request asks for the builder twin of a page ({@code ?builder}, with or without a value). 065 * 066 * @param req The request. 067 * @return <jk>true</jk> if the page should render from its {@link PageSpec}. 068 */ 069 public static boolean builder(RestRequest req) { 070 return req.containsQueryParam("builder"); 071 } 072 073 /** 074 * Renders a builder-twin page, marked with {@link #PAGE_HEADER}. 075 * 076 * @param req The request. 077 * @param spec The page spec. 078 * @return The view. 079 */ 080 public static View twin(RestRequest req, PageSpec spec) { 081 return spec.header(PAGE_HEADER, "builder").view(req); 082 } 083 084 @SuppressWarnings({ 085 "java:S2226" // the field is set by the framework's @Bean injection after construction, so it cannot be final. 086 }) 087 @Bean 088 private transient PetStore store; 089 090 /** 091 * The console FreeMarker mixin: petstore templates, {@code base.ftlh} chrome, {@code assetUrl(..)} over this 092 * package's bundled scripts, and the {@link InventoryGaugeCardType} custom card type. 093 * 094 * @return The mixin. 095 */ 096 @Bean 097 public FreemarkerMixin freemarker() { 098 // assetUrl('/console/petstore.js') versions the shared page script served by PetstoreConsoleResource. 099 return ConsoleFreemarkerMixin.create().basePath(TEMPLATES).chromeTemplate("base.ftlh") 100 .adopterAssets(PetstoreConsolePage.class.getClassLoader(), "org/apache/juneau/petstore") 101 .cardType(new InventoryGaugeCardType()).requirePacks("charts").build(); 102 } 103 104 /** 105 * @return The shared store. 106 * @throws IllegalStateException If no {@link PetStore} {@code @Bean} was wired into the host. 107 */ 108 protected PetStore store() { 109 if (store == null) 110 throw new IllegalStateException("No PetStore bean is wired: declare a @Bean PetStore on the host that mounts " + getClass().getSimpleName()); 111 return store; 112 } 113}