Pages Application refactoring for MVC
parent
6383aec674
commit
27b18d8888
|
|
@ -31,17 +31,25 @@ import org.libreccm.theming.ThemeInfo;
|
|||
import org.libreccm.theming.ThemeVersion;
|
||||
import org.libreccm.theming.Themes;
|
||||
import org.libreccm.theming.mvc.ThemesMvc;
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
import org.librecms.contentsection.ContentItemL10NManager;
|
||||
import org.librecms.contentsection.ContentItemManager;
|
||||
import org.librecms.contentsection.ContentItemVersion;
|
||||
import org.librecms.pages.models.CategoryModel;
|
||||
import org.librecms.pages.models.ContentItemModel;
|
||||
import org.librecms.pages.models.SiteInfoModel;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
|
@ -173,6 +181,12 @@ public class PagesController {
|
|||
@Inject
|
||||
private ConfigurationManager confManager;
|
||||
|
||||
@Inject
|
||||
private ContentItemManager contentItemManager;
|
||||
|
||||
@Inject
|
||||
private ContentItemL10NManager contentItemL10NManager;
|
||||
|
||||
@Inject
|
||||
private ContentItemModel contentItemModel;
|
||||
|
||||
|
|
@ -182,6 +196,9 @@ public class PagesController {
|
|||
@Inject
|
||||
private PagesRepository pagesRepo;
|
||||
|
||||
@Inject
|
||||
private PagesService pagesService;
|
||||
|
||||
@Inject
|
||||
private SiteInfoModel siteInfoModel;
|
||||
|
||||
|
|
@ -206,13 +223,27 @@ public class PagesController {
|
|||
@GET
|
||||
@Path("/")
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Response redirectToIndexPage(@Context final UriInfo uriInfo) {
|
||||
public Response redirectToIndexPage(
|
||||
@Context
|
||||
final UriInfo uriInfo,
|
||||
@QueryParam("theme")
|
||||
@DefaultValue(ThemesMvc.DEFAULT_THEME_PARAM)
|
||||
final String theme,
|
||||
@QueryParam("preview")
|
||||
@DefaultValue("")
|
||||
final String preview
|
||||
) {
|
||||
final String domain = uriInfo.getBaseUri().getHost();
|
||||
final Pages pages = getPages(domain);
|
||||
final Category category = getCategory(domain, pages, "/");
|
||||
final String language = determineLanguage(category);
|
||||
final Versions versions = generateFromPreviewParam(preview);
|
||||
final String language = determineLanguage(category, versions);
|
||||
|
||||
final String indexPage = String.format("/index.%s.html", language);
|
||||
final String indexPage = String.format(
|
||||
"/index.%s.html%s",
|
||||
language,
|
||||
buildQueryParamsStr(preview, theme)
|
||||
);
|
||||
final URI uri = uriInfo.getBaseUriBuilder().path(indexPage).build();
|
||||
return Response.temporaryRedirect(uri).build();
|
||||
}
|
||||
|
|
@ -221,16 +252,27 @@ public class PagesController {
|
|||
@Path("/{name:[\\w\\-]+}")
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Response getRootPage(
|
||||
@Context final UriInfo uriInfo,
|
||||
@PathParam("name") final String itemName
|
||||
@Context
|
||||
final UriInfo uriInfo,
|
||||
@PathParam("name") final String itemName,
|
||||
@QueryParam("theme")
|
||||
@DefaultValue(ThemesMvc.DEFAULT_THEME_PARAM)
|
||||
final String theme,
|
||||
@QueryParam("preview")
|
||||
@DefaultValue("")
|
||||
final String preview
|
||||
) {
|
||||
final String domain = uriInfo.getBaseUri().getHost();
|
||||
final Pages pages = getPages(domain);
|
||||
final Category category = getCategory(domain, pages, "/");
|
||||
final String language = determineLanguage(category);
|
||||
final Versions versions = generateFromPreviewParam(preview);
|
||||
final String language = determineLanguage(category, versions);
|
||||
|
||||
final String itemPage = String.format(
|
||||
"/%s.%s.html", itemName, language
|
||||
"/%s.%s.html%s",
|
||||
itemName,
|
||||
language,
|
||||
buildQueryParamsStr(preview, theme)
|
||||
);
|
||||
final URI uri = uriInfo.getBaseUriBuilder().path(itemPage).build();
|
||||
return Response.temporaryRedirect(uri).build();
|
||||
|
|
@ -241,12 +283,20 @@ public class PagesController {
|
|||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Response getRootPageAsHtml(
|
||||
@Context final UriInfo uriInfo,
|
||||
@PathParam("name") final String itemName) {
|
||||
|
||||
@QueryParam("theme")
|
||||
@DefaultValue(ThemesMvc.DEFAULT_THEME_PARAM)
|
||||
final String theme,
|
||||
@QueryParam("preview")
|
||||
@DefaultValue("")
|
||||
final String preview,
|
||||
@PathParam("name")
|
||||
final String itemName
|
||||
) {
|
||||
final String domain = uriInfo.getBaseUri().getHost();
|
||||
final Pages pages = getPages(domain);
|
||||
final Category category = getCategory(domain, pages, "/");
|
||||
final String language = determineLanguage(category);
|
||||
final Versions versions = generateFromPreviewParam(preview);
|
||||
final String language = determineLanguage(category, itemName, versions);
|
||||
|
||||
final String itemPage = String.format(
|
||||
"/%s.%s.html", itemName, language
|
||||
|
|
@ -284,7 +334,14 @@ public class PagesController {
|
|||
contentItemModel.setItemName(itemName);
|
||||
contentItemModel.setItemVersion(versions.getContentItemVersion());
|
||||
|
||||
return themesMvc.getMvcTemplate(uriInfo, "pages", "page");
|
||||
final String domain = uriInfo.getBaseUri().getHost();
|
||||
final Pages pages = getPages(domain);
|
||||
final Category category = getCategory(domain, pages, "/");
|
||||
final Page page = pageManager.findPageForCategory(category);
|
||||
page.getDisplayName();
|
||||
return themesMvc.getMvcTemplate(
|
||||
uriInfo, "pages", page.getDisplayName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -297,6 +354,8 @@ public class PagesController {
|
|||
* @param uriInfo
|
||||
* @param page
|
||||
* @param itemName
|
||||
* @param theme
|
||||
* @param preview
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
|
@ -306,12 +365,21 @@ public class PagesController {
|
|||
public Response getPage(
|
||||
@Context final UriInfo uriInfo,
|
||||
@PathParam("page") final String page,
|
||||
@PathParam("name") final String itemName
|
||||
@PathParam("name") final String itemName,
|
||||
@QueryParam("theme")
|
||||
@DefaultValue("--DEFAULT--")
|
||||
final String theme,
|
||||
@QueryParam("preview")
|
||||
@DefaultValue("")
|
||||
final String preview
|
||||
) {
|
||||
// ToDo Check!!!
|
||||
|
||||
final String domain = uriInfo.getBaseUri().getHost();
|
||||
final Pages pages = getPages(domain);
|
||||
final Category category = getCategory(domain, pages, page);
|
||||
final String language = determineLanguage(category);
|
||||
final Versions versions = generateFromPreviewParam(preview);
|
||||
final String language = determineLanguage(category, versions);
|
||||
|
||||
final String redirectTo;
|
||||
if (uriInfo.getPath().endsWith("/")) {
|
||||
|
|
@ -346,12 +414,21 @@ public class PagesController {
|
|||
public Response getPageAsHtml(
|
||||
@Context final UriInfo uriInfo,
|
||||
@PathParam("page") final String page,
|
||||
@PathParam("name") final String itemName
|
||||
@PathParam("name") final String itemName,
|
||||
@QueryParam("theme")
|
||||
@DefaultValue("--DEFAULT--")
|
||||
final String theme,
|
||||
@QueryParam("preview")
|
||||
@DefaultValue("")
|
||||
final String preview
|
||||
) {
|
||||
//ToDo Check!
|
||||
|
||||
final String domain = uriInfo.getBaseUri().getHost();
|
||||
final Pages pages = getPages(domain);
|
||||
final Category category = getCategory(domain, pages, page);
|
||||
final String language = determineLanguage(category);
|
||||
final Versions versions = generateFromPreviewParam(preview);
|
||||
final String language = determineLanguage(category, versions);
|
||||
|
||||
final String redirectTo;
|
||||
if (uriInfo.getPath().endsWith("/")) {
|
||||
|
|
@ -461,20 +538,91 @@ public class PagesController {
|
|||
);
|
||||
}
|
||||
|
||||
private String determineLanguage(final Category category) {
|
||||
private String determineLanguage(
|
||||
final Category category, final Versions versions
|
||||
) {
|
||||
final Locale negoiatedLocale = globalizationHelper
|
||||
.getNegotiatedLocale();
|
||||
|
||||
final String language;
|
||||
if (category.getTitle().hasValue(negoiatedLocale)) {
|
||||
language = negoiatedLocale.toString();
|
||||
} else if (category.getTitle().hasValue(defaultLocale)) {
|
||||
language = defaultLocale.toString();
|
||||
if (categoryManager.hasIndexObject(category)) {
|
||||
final ContentItem indexItem = getIndexObject(category, versions)
|
||||
.get();
|
||||
if (contentItemL10NManager.hasLanguage(indexItem, negoiatedLocale)) {
|
||||
return negoiatedLocale.toString();
|
||||
} else {
|
||||
throw new NotFoundException();
|
||||
return confManager
|
||||
.findConfiguration(KernelConfig.class)
|
||||
.getDefaultLanguage();
|
||||
}
|
||||
} else {
|
||||
if (category.getTitle().hasValue(negoiatedLocale)) {
|
||||
return negoiatedLocale.toString();
|
||||
} else {
|
||||
return defaultLocale.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return language;
|
||||
private String determineLanguage(
|
||||
final Category category,
|
||||
final String itemName,
|
||||
final Versions versions
|
||||
) {
|
||||
final Locale negoiatedLocale = globalizationHelper
|
||||
.getNegotiatedLocale();
|
||||
|
||||
final ContentItem contentItem = pagesService.findCategorizedItem(
|
||||
category, itemName, versions.getContentItemVersion()
|
||||
)
|
||||
.orElseThrow(
|
||||
() -> new NotFoundException(
|
||||
String.format(
|
||||
"No item %s found in category %s.",
|
||||
itemName,
|
||||
categoryManager.getCategoryPath(category)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
final KernelConfig kernelConfig = confManager.findConfiguration(
|
||||
KernelConfig.class
|
||||
);
|
||||
|
||||
if (contentItemL10NManager.hasLanguage(contentItem, negoiatedLocale)) {
|
||||
return negoiatedLocale.toString();
|
||||
} else if (contentItemL10NManager.hasLanguage(contentItem, kernelConfig
|
||||
.getDefaultLocale())) {
|
||||
return kernelConfig.getDefaultLanguage();
|
||||
} else {
|
||||
throw new NotFoundException(
|
||||
String.format(
|
||||
"No item %s found in category %s.",
|
||||
itemName,
|
||||
categoryManager.getCategoryPath(category)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildQueryParamsStr(
|
||||
final String previewParam, final String themeParam
|
||||
) {
|
||||
return List
|
||||
.of(
|
||||
Optional
|
||||
.of(themeParam)
|
||||
.filter(String::isBlank)
|
||||
.map(param -> String.format("theme=%s", param))
|
||||
.orElse(""),
|
||||
Optional
|
||||
.of(previewParam)
|
||||
.filter(String::isBlank)
|
||||
.map(param -> String.format("preview=%s", param))
|
||||
.orElse("")
|
||||
)
|
||||
.stream()
|
||||
.filter(String::isBlank)
|
||||
.collect(Collectors.joining("&", "?", ""));
|
||||
}
|
||||
|
||||
private ThemeInfo getTheme(
|
||||
|
|
@ -508,6 +656,26 @@ public class PagesController {
|
|||
}
|
||||
}
|
||||
|
||||
private Optional<ContentItem> getIndexObject(
|
||||
final Category category, final Versions versions
|
||||
) {
|
||||
final Predicate<ContentItem> filter;
|
||||
if (versions.getContentItemVersion() == ContentItemVersion.DRAFT) {
|
||||
filter = (ContentItem item) -> !contentItemManager.isLive(item);
|
||||
} else {
|
||||
filter = (ContentItem item) -> contentItemManager.isLive(item);
|
||||
}
|
||||
|
||||
return categoryManager
|
||||
.getIndexObject(category)
|
||||
.stream()
|
||||
.filter(object -> object instanceof ContentItem)
|
||||
.map(object -> (ContentItem) object)
|
||||
.filter(filter)
|
||||
.findFirst();
|
||||
|
||||
}
|
||||
|
||||
private Page findPage(
|
||||
final UriInfo uriInfo, final String pagePath, final String language
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.librecms.pages;
|
||||
|
||||
import org.libreccm.categorization.Categorization;
|
||||
import org.libreccm.categorization.Category;
|
||||
import org.libreccm.categorization.CategoryManager;
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
import org.librecms.contentsection.ContentItemVersion;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@RequestScoped
|
||||
public class PagesService {
|
||||
|
||||
@Inject
|
||||
private CategoryManager categoryManager;
|
||||
|
||||
@Inject
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Optional<ContentItem> findIndexItem(
|
||||
final Category category, final ContentItemVersion version
|
||||
) {
|
||||
return categoryManager
|
||||
.getIndexObject(category)
|
||||
.stream()
|
||||
.filter(object -> object instanceof ContentItem)
|
||||
.map(object -> (ContentItem) object)
|
||||
.filter(item -> item.getVersion() == version)
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Optional<ContentItem> findCategorizedItem(
|
||||
final Category category,
|
||||
final String itemName,
|
||||
final ContentItemVersion version
|
||||
) {
|
||||
final CriteriaBuilder builder = entityManager
|
||||
.getCriteriaBuilder();
|
||||
final CriteriaQuery<ContentItem> criteriaQuery = builder
|
||||
.createQuery(ContentItem.class);
|
||||
final Root<ContentItem> from = criteriaQuery.from(
|
||||
ContentItem.class
|
||||
);
|
||||
final Join<ContentItem, Categorization> join = from.join(
|
||||
"categories"
|
||||
);
|
||||
|
||||
final TypedQuery<ContentItem> query = entityManager
|
||||
.createQuery(
|
||||
criteriaQuery
|
||||
.select(from)
|
||||
.where(
|
||||
builder.and(
|
||||
builder.equal(from.get("displayName"), itemName),
|
||||
builder.equal(
|
||||
from.get("version"),
|
||||
version
|
||||
),
|
||||
builder.equal(join.get("category"), category)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
return Optional.of(query.getSingleResult());
|
||||
} catch (NoResultException ex) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -20,33 +20,25 @@ package org.librecms.pages.models;
|
|||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.libreccm.categorization.Categorization;
|
||||
import org.libreccm.categorization.Category;
|
||||
import org.libreccm.categorization.CategoryManager;
|
||||
import org.libreccm.l10n.GlobalizationHelper;
|
||||
import org.librecms.contentsection.AttachmentList;
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
import org.librecms.contentsection.ContentItemVersion;
|
||||
import org.librecms.pages.PagesRouter;
|
||||
import org.librecms.pages.PagesService;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
|
||||
/**
|
||||
|
|
@ -77,6 +69,9 @@ public class ContentItemModel {
|
|||
@Inject
|
||||
private GlobalizationHelper globalizationHelper;
|
||||
|
||||
@Inject
|
||||
private PagesService pagesService;
|
||||
|
||||
private final DateTimeFormatter dateTimeFormatter
|
||||
= DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneId.systemDefault());
|
||||
|
||||
|
|
@ -221,66 +216,13 @@ public class ContentItemModel {
|
|||
|
||||
private void retrieveContentItem() {
|
||||
if (itemName == null) {
|
||||
retrieveIndexItem();
|
||||
contentItem = pagesService.findIndexItem(
|
||||
categoryModel.getCategory(), itemVersion
|
||||
);
|
||||
} else {
|
||||
retrieveCategorizedItem();
|
||||
}
|
||||
}
|
||||
|
||||
private void retrieveIndexItem() {
|
||||
final Category category = categoryModel.getCategory();
|
||||
|
||||
contentItem = categoryManager
|
||||
.getIndexObject(category)
|
||||
.stream()
|
||||
.filter(object -> object instanceof ContentItem)
|
||||
.map(object -> (ContentItem) object)
|
||||
.filter(item -> item.getVersion() == itemVersion)
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
private void retrieveCategorizedItem() {
|
||||
final Category category = categoryModel.getCategory();
|
||||
final CriteriaBuilder builder = entityManager
|
||||
.getCriteriaBuilder();
|
||||
final CriteriaQuery<ContentItem> criteriaQuery = builder
|
||||
.createQuery(ContentItem.class);
|
||||
|
||||
final Root<ContentItem> from = criteriaQuery.from(
|
||||
ContentItem.class
|
||||
);
|
||||
final Join<ContentItem, Categorization> join = from.join(
|
||||
"categories"
|
||||
);
|
||||
|
||||
final TypedQuery<ContentItem> query = entityManager
|
||||
.createQuery(criteriaQuery
|
||||
.select(from)
|
||||
.where(builder.and(
|
||||
builder.equal(from.get("displayName"), itemName),
|
||||
builder.equal(
|
||||
from.get("version"),
|
||||
itemVersion
|
||||
),
|
||||
builder.equal(join.get("category"), category)
|
||||
)));
|
||||
|
||||
try {
|
||||
contentItem = Optional.of(query.getSingleResult());
|
||||
} catch (NoResultException ex) {
|
||||
LOGGER.warn(
|
||||
"No ContentItem with name \"{}\" in Category \"{}\".",
|
||||
itemName,
|
||||
Objects.toString(category)
|
||||
);
|
||||
throw new NotFoundException(
|
||||
String.format(
|
||||
"No ContentItem with name \"%s\" in Category \"%s\".",
|
||||
itemName,
|
||||
Objects.toString(category)
|
||||
)
|
||||
contentItem = pagesService.findCategorizedItem(
|
||||
categoryModel.getCategory(), itemName, itemVersion
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ import javax.ws.rs.core.UriInfo;
|
|||
@RequestScoped
|
||||
public class ThemesMvc {
|
||||
|
||||
public static final String DEFAULT_THEME_PARAM = "--DEFAULT--";
|
||||
|
||||
@Inject
|
||||
private Models models;
|
||||
|
||||
|
|
@ -203,7 +205,7 @@ public class ThemesMvc {
|
|||
final Site site,
|
||||
final String theme,
|
||||
final ThemeVersion themeVersion) {
|
||||
if ("--DEFAULT--".equals(theme)) {
|
||||
if (DEFAULT_THEME_PARAM.equals(theme)) {
|
||||
return themes
|
||||
.getTheme(site.getDefaultTheme(), themeVersion)
|
||||
.orElseThrow(
|
||||
|
|
@ -239,13 +241,14 @@ public class ThemesMvc {
|
|||
* @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.
|
||||
* {@link #DEFAULT_THEME_PARAM} if the query parameter is not
|
||||
* present.
|
||||
*/
|
||||
private String parseThemeParam(final UriInfo uriInfo) {
|
||||
if (uriInfo.getQueryParameters().containsKey("theme")) {
|
||||
return uriInfo.getQueryParameters().getFirst("theme");
|
||||
} else {
|
||||
return "--DEFAULT--";
|
||||
return DEFAULT_THEME_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue