CCM NG: ItemListComponent for the PageModel
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5072 8810af33-2d31-482b-a856-94f89814c4df
parent
cac7214f83
commit
2665ee2c61
|
|
@ -56,15 +56,17 @@ public class ItemListComponent extends ComponentModel {
|
|||
private boolean descending;
|
||||
|
||||
/**
|
||||
* Include only the types listed here into the list
|
||||
* Include only items of the specified type into the list. This must be a
|
||||
* subtype of {@link ContentItem}.
|
||||
*/
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "ITEM_LIST_LIMIT_TO_TYPES",
|
||||
schema = DB_SCHEMA,
|
||||
joinColumns = {
|
||||
@JoinColumn(name = "ITEM_LIST_ID")
|
||||
})
|
||||
private Set<String> limitToTypes;
|
||||
@Column(name = "LIMIT_TO_TYPE")
|
||||
private String limitToType;
|
||||
|
||||
/**
|
||||
* Maximum number of items shown on one page.
|
||||
*/
|
||||
@Column(name = "PAGE_SIZE")
|
||||
private int pageSize;
|
||||
|
||||
/**
|
||||
* Order the list by this properties. Warning: All items must have the
|
||||
|
|
@ -87,20 +89,20 @@ public class ItemListComponent extends ComponentModel {
|
|||
this.descending = descending;
|
||||
}
|
||||
|
||||
public Set<String> getLimitToTypes() {
|
||||
return Collections.unmodifiableSet(limitToTypes);
|
||||
public String getLimitToType() {
|
||||
return limitToType;
|
||||
}
|
||||
|
||||
public void addLimitToTypes(final String type) {
|
||||
limitToTypes.add(type);
|
||||
public void setLimitToTypes(final String limitToType) {
|
||||
this.limitToType = limitToType;
|
||||
}
|
||||
|
||||
public void removeLimitToType(final String type) {
|
||||
limitToTypes.remove(type);
|
||||
public int getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public void setLimitToTypes(final Set<String> limitToTypes) {
|
||||
this.limitToTypes = new HashSet<>(limitToTypes);
|
||||
public void setPageSize(final int pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
|
||||
public List<String> getListOrder() {
|
||||
|
|
@ -123,7 +125,7 @@ public class ItemListComponent extends ComponentModel {
|
|||
public int hashCode() {
|
||||
int hash = super.hashCode();
|
||||
hash = 41 * hash + (descending ? 1 : 0);
|
||||
hash = 41 * hash + Objects.hashCode(limitToTypes);
|
||||
hash = 41 * hash + Objects.hashCode(limitToType);
|
||||
hash = 41 * hash + Objects.hashCode(listOrder);
|
||||
return hash;
|
||||
}
|
||||
|
|
@ -152,7 +154,7 @@ public class ItemListComponent extends ComponentModel {
|
|||
if (descending != other.isDescending()) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(limitToTypes, other.getLimitToTypes())) {
|
||||
if (!Objects.equals(limitToType, other.getLimitToType())) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(listOrder, other.getListOrder());
|
||||
|
|
@ -169,7 +171,7 @@ public class ItemListComponent extends ComponentModel {
|
|||
+ "limitToTypes = %s, "
|
||||
+ "listOrder = %s%s",
|
||||
descending,
|
||||
Objects.toString(limitToTypes),
|
||||
limitToType,
|
||||
Objects.toString(listOrder),
|
||||
data));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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.pagemodel;
|
||||
|
||||
import com.arsdigita.kernel.KernelConfig;
|
||||
|
||||
import org.libreccm.categorization.Categorization;
|
||||
import org.libreccm.categorization.Category;
|
||||
import org.libreccm.categorization.CategoryManager;
|
||||
import org.libreccm.categorization.CategoryRepository;
|
||||
import org.libreccm.configuration.ConfigurationManager;
|
||||
import org.libreccm.core.UnexpectedErrorException;
|
||||
import org.libreccm.pagemodel.ComponentModelType;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
|
||||
import org.libreccm.pagemodel.ComponentRenderer;
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
import org.librecms.pagemodel.contentitems.AbstractContentItemRenderer;
|
||||
import org.librecms.pagemodel.contentitems.ContentItemRenderers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.Order;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static org.librecms.pages.PagesConstants.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@RequestScoped
|
||||
@ComponentModelType(componentModel = ItemListComponent.class)
|
||||
public class ItemListComponentRenderer
|
||||
implements ComponentRenderer<ItemListComponent> {
|
||||
|
||||
@Inject
|
||||
private ConfigurationManager confManager;
|
||||
|
||||
@Inject
|
||||
private ContentItemRenderers itemRenderers;
|
||||
|
||||
@Inject
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Inject
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Override
|
||||
public Map<String, Object> renderComponent(
|
||||
final ItemListComponent componentModel,
|
||||
final Map<String, Object> parameters) {
|
||||
|
||||
Objects.requireNonNull(componentModel);
|
||||
Objects.requireNonNull(parameters);
|
||||
|
||||
if (!parameters.containsKey(PARAMETER_CATEGORY)) {
|
||||
throw new IllegalArgumentException(
|
||||
"The parameters map passed to this GreetingItem component does "
|
||||
+ "not include the parameter \"category\"");
|
||||
}
|
||||
|
||||
if (!(parameters.get(PARAMETER_CATEGORY) instanceof Category)) {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("The parameters map passed to this GreetingItem "
|
||||
+ "component contains the parameter \"category\", but the "
|
||||
+ "parameter is not of type \"%s\" but of type \"%s\".",
|
||||
Category.class.getName(),
|
||||
parameters.get(PARAMETER_CATEGORY).getClass().getName()));
|
||||
}
|
||||
|
||||
final Category category = (Category) parameters.get(PARAMETER_CATEGORY);
|
||||
final Locale language;
|
||||
if (parameters.containsKey(PARAMETER_LANGUAGE)) {
|
||||
language = new Locale((String) parameters.get(PARAMETER_LANGUAGE));
|
||||
} else {
|
||||
final KernelConfig kernelConfig = confManager
|
||||
.findConfiguration(KernelConfig.class);
|
||||
language = kernelConfig.getDefaultLocale();
|
||||
}
|
||||
|
||||
final List<Category> categories;
|
||||
if (componentModel.isDescending()) {
|
||||
categories = collectCategories(category);
|
||||
} else {
|
||||
categories = new ArrayList<>();
|
||||
}
|
||||
categories.add(category);
|
||||
|
||||
final Class<? extends ContentItem> limitToType = getLimitToType(
|
||||
componentModel);
|
||||
|
||||
final List<? extends ContentItem> items = findItems(
|
||||
limitToType,
|
||||
categories,
|
||||
componentModel.getListOrder(),
|
||||
componentModel.getPageSize());
|
||||
|
||||
final Map<String, Object> result = new HashMap<>();
|
||||
result.put("items",
|
||||
items
|
||||
.stream()
|
||||
.map(item -> renderItem(item, language))
|
||||
.collect(Collectors.toList()));
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Category> collectCategories(final Category category) {
|
||||
|
||||
if (category.getSubCategories().isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
final List<Category> categories = new ArrayList<>();
|
||||
for (final Category subCategory : category.getSubCategories()) {
|
||||
categories.add(subCategory);
|
||||
categories.addAll(collectCategories(subCategory));
|
||||
}
|
||||
return categories;
|
||||
}
|
||||
}
|
||||
|
||||
private List<? extends ContentItem> findItems(
|
||||
final Class<? extends ContentItem> limitToType,
|
||||
final List<Category> categories,
|
||||
final List<String> listOrder,
|
||||
final int pageSize) {
|
||||
|
||||
final CriteriaBuilder criteriaBuilder = entityManager
|
||||
.getCriteriaBuilder();
|
||||
final CriteriaQuery<? extends ContentItem> criteriaQuery
|
||||
= criteriaBuilder
|
||||
.createQuery(limitToType);
|
||||
final Root<? extends ContentItem> from = criteriaQuery
|
||||
.from(limitToType);
|
||||
final Join<? extends ContentItem, Categorization> catJoin = from
|
||||
.join("categories");
|
||||
|
||||
criteriaQuery.where(catJoin.get("category").in(categories));
|
||||
|
||||
criteriaQuery
|
||||
.orderBy(listOrder
|
||||
.stream()
|
||||
.map(order -> createOrder(order, from, criteriaBuilder))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
return entityManager
|
||||
.createQuery(criteriaQuery)
|
||||
.setFirstResult(getOffset(pageSize))
|
||||
.setMaxResults(pageSize)
|
||||
.getResultList();
|
||||
}
|
||||
|
||||
private Class<? extends ContentItem> getLimitToType(
|
||||
final ItemListComponent componentModel) {
|
||||
|
||||
final String className = componentModel.getLimitToType();
|
||||
|
||||
if (className == null
|
||||
|| className.matches("\\s*")) {
|
||||
return ContentItem.class;
|
||||
} else {
|
||||
final Class<?> clazz;
|
||||
try {
|
||||
clazz = Class.forName(className);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
|
||||
if (ContentItem.class.isAssignableFrom(clazz)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<? extends ContentItem> type
|
||||
= (Class<? extends ContentItem>) clazz;
|
||||
return type;
|
||||
} else {
|
||||
throw new UnexpectedErrorException(String
|
||||
.format(
|
||||
"The type \"%s\" set in ItemList is not a subtype of "
|
||||
+ "\"%s\".",
|
||||
clazz.getName(),
|
||||
ContentItem.class.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Order createOrder(final String order,
|
||||
final Root<? extends ContentItem> from,
|
||||
final CriteriaBuilder criteriaBuilder) {
|
||||
|
||||
if (order.endsWith(" ASC")) {
|
||||
final String colName = order
|
||||
.substring(0, order.length() - " ASC".length());
|
||||
return (criteriaBuilder.asc(from.get(colName)));
|
||||
} else if (order.endsWith(" DESC")) {
|
||||
final String colName = order
|
||||
.substring(0, order.length() - " DESC".length());
|
||||
return criteriaBuilder.desc(from.get(colName));
|
||||
} else {
|
||||
return criteriaBuilder.asc(from.get(order));
|
||||
}
|
||||
}
|
||||
|
||||
private int getOffset(final int pageSize) {
|
||||
|
||||
if (request.getParameterMap().containsKey("page")) {
|
||||
final String value = request.getParameter("page");
|
||||
if (value.matches("\\d*")) {
|
||||
final int page = Integer.valueOf(value);
|
||||
|
||||
return page * pageSize;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> renderItem(final ContentItem item,
|
||||
final Locale language) {
|
||||
|
||||
final AbstractContentItemRenderer renderer = itemRenderers
|
||||
.findRenderer(item.getClass());
|
||||
return renderer.render(item, language);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue