diff --git a/ccm-core/src/main/java/org/libreccm/mvc/freemarker/FreemarkerViewEngine.java b/ccm-core/src/main/java/org/libreccm/mvc/freemarker/FreemarkerViewEngine.java
index 14e41ce92..910e74084 100644
--- a/ccm-core/src/main/java/org/libreccm/mvc/freemarker/FreemarkerViewEngine.java
+++ b/ccm-core/src/main/java/org/libreccm/mvc/freemarker/FreemarkerViewEngine.java
@@ -58,6 +58,22 @@ import javax.mvc.engine.ViewEngineException;
import javax.servlet.http.HttpServletRequest;
/**
+ * Customized version of the Freemarker View Engine. This class is based of the
+ * View Engine from the Krazo project, but has been extended:
+ *
+ * - Named Beans are supported
+ * - Freemarker template have access to the MvcContext under the name
+ * {@code mvc}, as in Facelet-based templates
+ * - The current {@link HttpServletRequest} is made avaiable in Freemarker
+ * templates as {@link request}.
+ * - The following utility functions are made available:
+ *
+ * - {@code getSetting}: retreives the value of a setting from the theme
+ * - {@code localize}: retreives a localized value from the theme
+ * - {@code truncateText}: Truncates text to a specific length.
+ *
+ *
+ *
*
* @author Jens Pelzetter
*/
@@ -123,8 +139,6 @@ public class FreemarkerViewEngine extends ViewEngineBase {
);
}
model.put("truncateText", new TruncateTextMethod());
-
-
final Map namedBeans = beanManager
.getBeans(Object.class)
@@ -149,6 +163,13 @@ public class FreemarkerViewEngine extends ViewEngineBase {
}
}
+ /**
+ * Helper method for retrieving a an instance of a named bean using CDI.
+ *
+ * @param bean The bean to retrieve.
+ *
+ * @return An instance of the bean.
+ */
@SuppressWarnings("rawtypes")
private Optional findBeanInstance(final Bean> bean) {
final Context context = beanManager.getContext(bean.getScope());
@@ -166,10 +187,19 @@ public class FreemarkerViewEngine extends ViewEngineBase {
}
}
+ /**
+ * Helper class encapsulating the information about a named bean.
+ */
private class NamedBeanInstance {
+ /**
+ * The name of the bean.
+ */
private final String name;
+ /**
+ * The bean instance.
+ */
private final Object beanInstance;
public NamedBeanInstance(String name, Object beanInstance) {
@@ -187,6 +217,9 @@ public class FreemarkerViewEngine extends ViewEngineBase {
}
+ /**
+ * Retrieves a setting from the theme using the {@link SettingsUtils}.
+ */
private class GetSettingMethod implements TemplateMethodModelEx {
private final ThemeInfo fromTheme;
@@ -241,6 +274,9 @@ public class FreemarkerViewEngine extends ViewEngineBase {
}
+ /**
+ * Retrieves a localized value from the theme using the {@link L10NUtils}.
+ */
private class LocalizeMethod implements TemplateMethodModelEx {
private final ThemeInfo fromTheme;
@@ -275,6 +311,9 @@ public class FreemarkerViewEngine extends ViewEngineBase {
}
+ /**
+ * Truncates text to a specific length.
+ */
private class TruncateTextMethod implements TemplateMethodModelEx {
@Override
diff --git a/ccm-core/src/main/java/org/libreccm/mvc/freemarker/TemplateInfo.java b/ccm-core/src/main/java/org/libreccm/mvc/freemarker/TemplateInfo.java
index 3eda69687..55d6fe3d2 100644
--- a/ccm-core/src/main/java/org/libreccm/mvc/freemarker/TemplateInfo.java
+++ b/ccm-core/src/main/java/org/libreccm/mvc/freemarker/TemplateInfo.java
@@ -21,13 +21,20 @@ package org.libreccm.mvc.freemarker;
import org.libreccm.theming.ThemeInfo;
/**
- *
+ * Encapulates the data of a template.
+ *
* @author Jens Pelzetter
*/
class TemplateInfo {
+ /**
+ * Info about the theme providing the template.
+ */
private final ThemeInfo themeInfo;
+ /**
+ * The path of the template,
+ */
private final String filePath;
public TemplateInfo(ThemeInfo themeInfo, String filePath) {
diff --git a/ccm-core/src/main/java/org/libreccm/mvc/freemarker/ThemeTemplateUtil.java b/ccm-core/src/main/java/org/libreccm/mvc/freemarker/ThemeTemplateUtil.java
index 80b693f6f..dc9721245 100644
--- a/ccm-core/src/main/java/org/libreccm/mvc/freemarker/ThemeTemplateUtil.java
+++ b/ccm-core/src/main/java/org/libreccm/mvc/freemarker/ThemeTemplateUtil.java
@@ -34,13 +34,15 @@ import javax.enterprise.inject.Instance;
import javax.inject.Inject;
/**
+ * Utility class for retreving a {@link TemplateInfo} instance for a template.
*
* @author Jens Pelzetter
*/
@RequestScoped
class ThemeTemplateUtil {
- private static final Logger LOGGER = LogManager.getLogger(ThemeTemplateUtil.class);
+ private static final Logger LOGGER = LogManager.getLogger(
+ ThemeTemplateUtil.class);
@Inject
private Instance themeProviders;
@@ -48,11 +50,28 @@ class ThemeTemplateUtil {
@Inject
private Themes themes;
+ /**
+ * Checks if the provided path points to a template.
+ *
+ * @param templatePath The path of the template.
+ *
+ * @return {@code true} if the path points to a template, {@code false}
+ * otherwise.
+ */
public boolean isValidTemplatePath(final String templatePath) {
return templatePath.startsWith("@themes")
|| templatePath.startsWith("/@themes");
}
+ /**
+ * Get the {@link TemplateInfo} for the template.
+ *
+ * @param templatePath The path of the template.
+ *
+ * @return An {@link Optional} with a {@link TemplateInfo} for the template.
+ * If the template is not available, an empty {@link Optional} is
+ * returned.
+ */
public Optional getTemplateInfo(final String templatePath) {
if (!isValidTemplatePath(templatePath)) {
throw new IllegalArgumentException(
@@ -74,6 +93,13 @@ class ThemeTemplateUtil {
return getTemplateInfo(tokens);
}
+ /**
+ * Find the {@link ThemeProvider} for a theme.
+ *
+ * @param forTheme The theme
+ *
+ * @return The {@link ThemeProvider} for the theme.
+ */
public ThemeProvider findThemeProvider(final ThemeInfo forTheme) {
final Instance extends ThemeProvider> provider = themeProviders
.select(forTheme.getProvider());
@@ -92,6 +118,15 @@ class ThemeTemplateUtil {
return provider.get();
}
+ /**
+ * Retrieves the {@link TemplateInfo} for a template.
+ *
+ * @param tokens The tokens of the template path.
+ *
+ * @return An {@link Optional} with a {@link TemplateInfo} for the template.
+ * If the template is not available, an empty {@link Optional} is
+ * returned.
+ */
private Optional getTemplateInfo(final String[] tokens) {
if (tokens.length >= 4) {
final String themeName = tokens[1];
@@ -108,7 +143,7 @@ class ThemeTemplateUtil {
final Optional themeInfo = themes.getTheme(
themeName, themeVersion
);
-
+
if (themeInfo.isPresent()) {
return Optional.of(new TemplateInfo(themeInfo.get(), filePath));
} else {
diff --git a/ccm-core/src/main/java/org/libreccm/mvc/freemarker/ThemesTemplateLoader.java b/ccm-core/src/main/java/org/libreccm/mvc/freemarker/ThemesTemplateLoader.java
index 999b90ebb..eaf9ede78 100644
--- a/ccm-core/src/main/java/org/libreccm/mvc/freemarker/ThemesTemplateLoader.java
+++ b/ccm-core/src/main/java/org/libreccm/mvc/freemarker/ThemesTemplateLoader.java
@@ -19,7 +19,6 @@
package org.libreccm.mvc.freemarker;
import freemarker.cache.TemplateLoader;
-import org.libreccm.theming.ThemeInfo;
import org.libreccm.theming.ThemeVersion;
import org.libreccm.theming.Themes;
@@ -27,7 +26,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
-import java.util.Arrays;
import java.util.Optional;
/**
diff --git a/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemeResourceProvider.java b/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemeResourceProvider.java
index e9dcd7d3b..18315fdd9 100644
--- a/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemeResourceProvider.java
+++ b/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemeResourceProvider.java
@@ -21,7 +21,6 @@ package org.libreccm.theming.mvc;
import org.libreccm.theming.ThemeFileInfo;
import org.libreccm.theming.ThemeProvider;
import org.libreccm.theming.ThemeVersion;
-import org.libreccm.theming.manager.Themes;
import java.io.InputStream;
import java.util.ArrayList;
@@ -38,6 +37,9 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
/**
+ * Provides access to the resources/assets of themes.
+ *
+ * @see ThemeResources
*
* @author Jens Pelzetter
*/
@@ -45,13 +47,30 @@ import javax.ws.rs.core.Response;
@Path("/")
public class ThemeResourceProvider {
+ /**
+ * Injection point for the available {@link ThemeProvider}s.
+ */
@Inject
@Any
private Instance providers;
- @Inject
- private Themes themes;
-
+ /**
+ * Serves a resources from a theme. This endpoint is mounted at
+ * {@code /@themes/{theme}/{themeVersion}/{path:.+}}. If the provided theme
+ * is not found, the provided theme is not available in the requested
+ * version, or if the theme does not provide the requested resource the
+ * endpoint will response with a 404 response. If the response is found, a
+ * response with the asset and the correct mime type is returned.
+ *
+ * @param themeName The name of the theme providing the resource.
+ * @param themeVersionParam The version of the theme to use (either
+ * {@code LIVE} or {@code DRAFT}.
+ * @param pathParam The path of the resource to serve.
+ *
+ * @return A response with the resource and the correct mime type, or a 404
+ * response if the resource, the theme version or the theme is not
+ * available.
+ */
@GET
@Path("/{theme}/{themeVersion}/{path:.+}")
public Response getThemeFile(
@@ -123,8 +142,15 @@ public class ThemeResourceProvider {
}
}
+ /**
+ * Helper method for finding the provider of a theme.
+ *
+ * @param forTheme The theme.
+ *
+ * @return An {@link Optional} with the provider of the theme. If there is
+ * no matching provider, an empty {@link Optional} is returned.
+ */
private Optional findProvider(final String forTheme) {
-
final List providersList = new ArrayList<>();
providers
.forEach(provider -> providersList.add(provider));
diff --git a/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemeResources.java b/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemeResources.java
index bdac41633..246bf19c6 100644
--- a/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemeResources.java
+++ b/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemeResources.java
@@ -25,6 +25,8 @@ import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
/**
+ * JAX-RS application providing the resources/assets of a theme (images, CSS
+ * files, etc) under the {@code /@themes} URL.
*
* @author Jens Pelzetter
*/
@@ -37,7 +39,5 @@ public class ThemeResources extends Application {
classes.add(ThemeResourceProvider.class);
return classes;
}
-
-
-
+
}
diff --git a/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemesMvc.java b/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemesMvc.java
index 999bb7630..70809320e 100644
--- a/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemesMvc.java
+++ b/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemesMvc.java
@@ -18,7 +18,6 @@
*/
package org.libreccm.theming.mvc;
-import org.libreccm.core.UnexpectedErrorException;
import org.libreccm.sites.Site;
import org.libreccm.sites.SiteRepository;
import org.libreccm.theming.ThemeInfo;
@@ -30,7 +29,6 @@ import org.libreccm.theming.manifest.ThemeTemplate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
@@ -42,6 +40,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
/**
+ * Main integration point for MVC application with the theme system.
*
* @author Jens Pelzetter
*/
@@ -60,6 +59,16 @@ public class ThemesMvc {
@Inject
private Themes themes;
+ /**
+ * Get the template for a specific application and view from the current
+ * theme.
+ *
+ * @param uriInfo URI is required for some tasks in inside the method.
+ * @param application The application for which the template is requested.
+ * @param view The view for which the template is requested.
+ *
+ * @return The path of the template to use for the view of the application.
+ */
public String getMvcTemplate(
final UriInfo uriInfo,
final String application,
@@ -136,6 +145,13 @@ public class ThemesMvc {
);
}
+ /**
+ * Helper method of retrieving the current site.
+ *
+ * @param uriInfo Used to extract the current site.
+ *
+ * @return The current site.
+ */
private Site getSite(final UriInfo uriInfo) {
Objects.requireNonNull(uriInfo);
@@ -154,6 +170,16 @@ public class ThemesMvc {
return site;
}
+ /**
+ * Helper method for retrieving a the theme to use.
+ *
+ * @param site The current site.
+ * @param theme The theme to retrieve.
+ * @param themeVersion The version of the theme to retrieve.
+ *
+ * @return A {@link ThemeInfo} object providing access to to the theme and
+ * its resources.
+ */
private ThemeInfo getTheme(
final Site site,
final String theme,
@@ -187,6 +213,15 @@ public class ThemesMvc {
}
}
+ /**
+ * Helper method for parsing the {@code theme} query parameter which can be
+ * used to override the default theme of a site.
+ *
+ * @param uriInfo Information about the current URI.
+ *
+ * @return The value of the {@link theme} query parameter if present, or
+ * {@code --DEFAULT--} if the query parameter is not present.
+ */
private String parseThemeParam(final UriInfo uriInfo) {
if (uriInfo.getQueryParameters().containsKey("theme")) {
return uriInfo.getQueryParameters().getFirst("theme");
@@ -195,6 +230,18 @@ public class ThemesMvc {
}
}
+ /**
+ * Helper method for parsing the {@code preview} query parameter. The
+ * {@code preview} query parameter allows it to test the draft version of a
+ * theme.
+ *
+ * @param uriInfo Information about the current URI.
+ *
+ * @return If the value of the parameter is {@code theme} or {@code all}
+ * {@link ThemeVersion#DRAFT} is returned. If the query parameter is
+ * not present or has another value, {@link ThemeVersion#LIVE} is
+ * returned.
+ */
private ThemeVersion parsePreviewParam(final UriInfo uriInfo) {
if (uriInfo.getQueryParameters().containsKey("preview")) {
final List values = uriInfo
diff --git a/ccm-core/src/main/java/org/libreccm/theming/mvc/package-info.java b/ccm-core/src/main/java/org/libreccm/theming/mvc/package-info.java
new file mode 100644
index 000000000..cc845360e
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/theming/mvc/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 LibreCCM Foundation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+/**
+ * Integration of the Theming System with Jakarta EE MVC.
+ */
+package org.libreccm.theming.mvc;