diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ContentCenter.java b/ccm-cms/src/main/java/com/arsdigita/cms/ContentCenter.java index 24445a50c..73eb958ae 100644 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ContentCenter.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ContentCenter.java @@ -25,6 +25,8 @@ import org.libreccm.web.CcmApplication; * @author Jens Pelzetter */ public class ContentCenter extends CcmApplication { + + private static final long serialVersionUID = 6672720141286517654L; diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/AdminView.java b/ccm-core/src/main/java/org/libreccm/admin/ui/AdminView.java index 06a81873c..5b75c3766 100644 --- a/ccm-core/src/main/java/org/libreccm/admin/ui/AdminView.java +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/AdminView.java @@ -60,7 +60,7 @@ public class AdminView extends CustomComponent implements View { private final SystemInformationTab sysInfoTab; @Inject - protected AdminView(final AdminViewController controller) { + AdminView(final AdminViewController controller) { this.controller = controller; @@ -89,6 +89,9 @@ public class AdminView extends CustomComponent implements View { final SitesTab sitesTab = new SitesTab(controller); tabSheet.addTab(sitesTab, "Sites"); + final PageModelsTab pageModelsTab = new PageModelsTab(controller); + tabSheet.addTab(pageModelsTab, "PageModels"); + configurationTab = new ConfigurationTab(); tabSheet.addTab(configurationTab, "Configuration"); diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/AdminViewController.java b/ccm-core/src/main/java/org/libreccm/admin/ui/AdminViewController.java index 3ff397497..d47b11c9d 100644 --- a/ccm-core/src/main/java/org/libreccm/admin/ui/AdminViewController.java +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/AdminViewController.java @@ -36,6 +36,9 @@ class AdminViewController implements Serializable { private static final long serialVersionUID = 4880298854970416968L; + @Inject + private ApplicationTreeDataProvider applicationTreeDataProvider; + @Inject private ConfigurationsTabController confTabController; @@ -45,6 +48,9 @@ class AdminViewController implements Serializable { @Inject private JpqlConsoleController jpqlConsoleController; + @Inject + private PageModelsController pageModelsController; + @Inject private SitesController sitesController; @@ -55,6 +61,10 @@ class AdminViewController implements Serializable { super(); } + public ApplicationTreeDataProvider getApplicationTreeDataProvider() { + return applicationTreeDataProvider; + } + public ConfigurationsTabController getConfTabController() { return confTabController; } @@ -66,6 +76,10 @@ class AdminViewController implements Serializable { protected JpqlConsoleController getJpqlConsoleController() { return jpqlConsoleController; } + + protected PageModelsController getPageModelsController() { + return pageModelsController; + } protected SitesController getSitesController() { return sitesController; diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeDataProvider.java b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeDataProvider.java new file mode 100644 index 000000000..7d0d12503 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeDataProvider.java @@ -0,0 +1,190 @@ +/* + * 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.libreccm.admin.ui; + +import com.vaadin.cdi.ViewScoped; +import com.vaadin.data.provider.AbstractBackEndHierarchicalDataProvider; +import com.vaadin.data.provider.HierarchicalQuery; +import org.libreccm.core.UnexpectedErrorException; +import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.web.ApplicationManager; +import org.libreccm.web.ApplicationRepository; +import org.libreccm.web.ApplicationType; +import org.libreccm.web.CcmApplication; + +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.inject.Inject; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@ViewScoped +class ApplicationTreeDataProvider + extends AbstractBackEndHierarchicalDataProvider { + + private static final long serialVersionUID = 7089444870777208500L; + + @Inject + private ApplicationManager applicationManager; + + @Inject + private ApplicationRepository applicationRepo; + + @Inject + private GlobalizationHelper globalizationHelper; + + private final ApplicationTreeNode rootNode; + + public ApplicationTreeDataProvider() { + rootNode = new ApplicationTreeNode(); + rootNode.setNodeId(ApplicationTreeNode.ROOT); + rootNode.setNodeType(ApplicationTreeNodeType.ROOT_NODE); + } + + @Transactional(Transactional.TxType.REQUIRED) + @Override + protected Stream fetchChildrenFromBackEnd( + final HierarchicalQuery query) { + + final ApplicationTreeNode node = query + .getParentOptional() + .orElse(rootNode); + + switch (node.getNodeType()) { + case APPLICATION_TYPE_NODE: + return fetchApplicationInstances(node); + case ROOT_NODE: + return fetchApplicationTypes(); + default: + throw new IllegalArgumentException(String + .format("Invalid value \"%s\" for nodeType.", + node.getNodeType())); + } + } + + private Stream fetchApplicationTypes() { + + return applicationManager + .getApplicationTypes() + .values() + .stream() + .map(this::buildApplicationTreeNode) + .sorted(); + } + + private ApplicationTreeNode buildApplicationTreeNode( + final ApplicationType type) { + + final ResourceBundle bundle = ResourceBundle + .getBundle(type.descBundle()); + + final String title = bundle.getString(type.titleKey()); + + final ApplicationTreeNode node = new ApplicationTreeNode(); + node.setTitle(title); + + if (type.singleton()) { + node.setNodeType(ApplicationTreeNodeType.SINGLETON_APPLICATION_NODE); + + final List instances = applicationRepo + .findByType(type.name()); + + if (instances.size() > 1) { + throw new UnexpectedErrorException(String + .format("Application type \"%s\" is marked as singleton but" + + "there are multiple instances.", + type.name())); + } + + final CcmApplication instance = instances.get(0); + node.setNodeId(instance.getUuid()); + } else { + node.setNodeType(ApplicationTreeNodeType.APPLICATION_TYPE_NODE); + node.setNodeId(type.name()); + } + + return node; + } + + private Stream fetchApplicationInstances( + final ApplicationTreeNode parent) { + + if (parent.getNodeType() + != ApplicationTreeNodeType.APPLICATION_TYPE_NODE) { + throw new IllegalArgumentException("Provided parent node is not a " + + ApplicationTreeNodeType.APPLICATION_TYPE_NODE); + } + + final String type = parent.getNodeId(); + + return applicationRepo + .findByType(type) + .stream() + .map(this::buildApplicationTreeNode) + .sorted(); + } + + private ApplicationTreeNode buildApplicationTreeNode( + final CcmApplication application) { + + final ApplicationTreeNode node = new ApplicationTreeNode(); + + node.setNodeId(application.getUuid()); + node.setNodeType(ApplicationTreeNodeType.APPLICATION_NODE); + node.setTitle(globalizationHelper + .getValueFromLocalizedString(application.getTitle())); + + return node; + } + + @Override + public int getChildCount( + final HierarchicalQuery query) { + + return (int) fetchChildrenFromBackEnd(query).count(); + } + + @Override + public boolean hasChildren(final ApplicationTreeNode item) { + + switch (item.getNodeType()) { + case APPLICATION_NODE: + return false; + case APPLICATION_TYPE_NODE: + return true; + case ROOT_NODE: + return true; + case SINGLETON_APPLICATION_NODE: + return false; + default: + throw new IllegalArgumentException(String + .format("Invalid value \"%s\" for nodeType.", + item.getNodeType())); + } + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNode.java b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNode.java new file mode 100644 index 000000000..25f3e57a3 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNode.java @@ -0,0 +1,149 @@ +/* + * 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.libreccm.admin.ui; + +import java.io.Serializable; +import java.util.Objects; + +/** + * Class encapsulating the information displayed in a application tree. + * + * @author Jens Pelzetter + */ +class ApplicationTreeNode implements Serializable, + Comparable { + + private static final long serialVersionUID = -3123536103514717506L; + + protected static final String ROOT = "@ROOT@"; + + + /** + * ID of the node. If the node is the root node, the ID will be + * {@link #ROOT}. If the node is an application type node the ID will be the + * name of the application type class. If it is an application (instance) + * node, the name will be the UUID of the instance. + */ + private String nodeId; + + /** + * Type of the the node. + */ + private ApplicationTreeNodeType nodeType; + + /** + * The title of the node. + */ + private String title; + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(final String nodeId) { + this.nodeId = nodeId; + } + + public ApplicationTreeNodeType getNodeType() { + return nodeType; + } + + public void setNodeType(final ApplicationTreeNodeType nodeType) { + this.nodeType = nodeType; + } + + public String getTitle() { + return title; + } + + public void setTitle(final String title) { + this.title = title; + } + + @Override + public int compareTo(final ApplicationTreeNode other) { + + int result = title.compareTo(other.getTitle()); + if (result == 0) { + result = nodeType.compareTo(other.getNodeType()); + } + + if (result == 0) { + result = nodeId.compareTo(other.getNodeId()); + } + + return result; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 53 * hash + Objects.hashCode(this.nodeId); + hash = 53 * hash + Objects.hashCode(this.nodeType); + hash = 53 * hash + Objects.hashCode(this.title); + return hash; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof ApplicationTreeNode)) { + return false; + } + final ApplicationTreeNode other = (ApplicationTreeNode) obj; + if (!other.canEqual(this)) { + return false; + } + if (!Objects.equals(this.nodeId, other.getNodeId())) { + return false; + } + if (!Objects.equals(this.title, other.getTitle())) { + return false; + } + return this.nodeType == other.getNodeType(); + } + + public boolean canEqual(final Object obj) { + return obj instanceof ApplicationTreeNode; + } + + @Override + public final String toString() { + return toString(""); + } + + public String toString(final String data) { + return String.format("%s{ " + + "nodeId = \"%s\", " + + "nodeType = \"%s\", " + + "title = \"%s\"%s" + + " }", + super.toString(), + nodeId, + nodeType, + title, + data); + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNodeType.java b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNodeType.java new file mode 100644 index 000000000..5c2baa7a0 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNodeType.java @@ -0,0 +1,30 @@ +/* + * 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.libreccm.admin.ui; + +/** + * Enum of the possible types of a node. + */ +enum ApplicationTreeNodeType { + ROOT_NODE, + APPLICATION_TYPE_NODE, + APPLICATION_NODE, + SINGLETON_APPLICATION_NODE + +} diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelDetails.java b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelDetails.java new file mode 100644 index 000000000..155cd7ab0 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelDetails.java @@ -0,0 +1,39 @@ +/* + * 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.libreccm.admin.ui; + +import com.vaadin.ui.Window; +import org.libreccm.pagemodel.PageModel; + +/** + * + * @author Jens Pelzetter + */ + class PageModelDetails extends Window { + + private static final long serialVersionUID = -3617001410191320596L; + + PageModelDetails(final PageModel pageModel, + final AdminViewController controller) { + + super(); + + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsController.java b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsController.java new file mode 100644 index 000000000..a5b7e93ca --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsController.java @@ -0,0 +1,74 @@ +/* + * 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.libreccm.admin.ui; + +import com.vaadin.cdi.ViewScoped; +import org.libreccm.pagemodel.PageModel; +import org.libreccm.pagemodel.PageModelManager; +import org.libreccm.pagemodel.PageModelRepository; + +import java.io.Serializable; + +import javax.inject.Inject; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@ViewScoped +class PageModelsController implements Serializable { + + private static final long serialVersionUID = 6204724295214879943L; + + @Inject + private PageModelManager pageModelManager; + + @Inject + private PageModelRepository pageModelRepo; + + @Inject + private PageModelsTableDataProvider pageModelsTableDataProvider; + + protected PageModelManager getPageModelManager() { + return pageModelManager; + } + + protected PageModelRepository getPageModelRepo() { + return pageModelRepo; + } + + protected PageModelsTableDataProvider getPageModelsTableDataProvider() { + return pageModelsTableDataProvider; + } + + @Transactional(Transactional.TxType.REQUIRED) + protected void deletePageModel(final long pageModelId) { + + final PageModel pageModel = pageModelRepo + .findById(pageModelId) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No PageModel with ID %d in the database.", + pageModelId))); + + pageModelRepo.delete(pageModel); + pageModelsTableDataProvider.refreshAll(); + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTab.java b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTab.java new file mode 100644 index 000000000..c8810d4cc --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTab.java @@ -0,0 +1,174 @@ +/* + * 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.libreccm.admin.ui; + +import com.arsdigita.ui.admin.AdminUiConstants; + +import com.vaadin.icons.VaadinIcons; +import com.vaadin.ui.Button; +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.Grid; +import com.vaadin.ui.HorizontalSplitPanel; +import com.vaadin.ui.Tree; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.themes.ValoTheme; +import org.libreccm.l10n.LocalizedTextsUtil; +import org.libreccm.pagemodel.PageModel; +import org.libreccm.ui.ConfirmDialog; +import org.libreccm.web.CcmApplication; + +import java.util.concurrent.Callable; + +/** + * + * @author Jens Pelzetter + */ +class PageModelsTab extends CustomComponent { + + private static final long serialVersionUID = -1116995764418892909L; + + private static final String COL_NAME = "name"; + private static final String COL_TITLE = "title"; + private static final String COL_DESC = "description"; + private static final String COL_LIVE = "live"; + private static final String COL_EDIT = "edit"; + private static final String COL_DELETE = "delete"; + + protected PageModelsTab(final AdminViewController adminViewController) { + + super(); + + final Tree applicationTree = new Tree<>( + adminViewController.getApplicationTreeDataProvider()); + + applicationTree.addItemClickListener(event -> { + }); + applicationTree.setItemCollapseAllowedProvider(node -> { + return !node.getNodeType().equals(ApplicationTreeNodeType.ROOT_NODE); + }); + + final LocalizedTextsUtil localizedTextsUtil = adminViewController + .getGlobalizationHelper() + .getLocalizedTextsUtil(AdminUiConstants.ADMIN_BUNDLE); + + final Grid pageModelsGrid = new Grid<>(); + pageModelsGrid.setDataProvider(adminViewController + .getPageModelsController() + .getPageModelsTableDataProvider()); + pageModelsGrid + .addColumn(PageModelsTableRow::getName) + .setCaption(localizedTextsUtil + .getText("ui.admin.pagemodels.table.columns.headers.name")) + .setId(COL_NAME); + pageModelsGrid + .addColumn(PageModelsTableRow::getTitle) + .setCaption(localizedTextsUtil + .getText("ui.admin.pagemodels.table.columns.headers.title")) + .setId(COL_TITLE); + pageModelsGrid + .addColumn(PageModelsTableRow::getDescription) + .setCaption(localizedTextsUtil + .getText("ui.admin.pagemodels.table.columns.headers.desc")) + .setId(COL_DESC); + pageModelsGrid + .addColumn(PageModelsTableRow::isPublished) + .setCaption(localizedTextsUtil + .getText("ui.admin.pagemodels.table.columns.headers.islive")) + .setId(COL_LIVE); + pageModelsGrid + .addComponentColumn(row -> buildEditButton(row, + adminViewController)) + .setId(COL_EDIT); + pageModelsGrid + .addComponentColumn(row -> buildDeleteButton(row, + adminViewController)) + .setId(COL_DELETE); + + super.setCompositionRoot(new HorizontalSplitPanel(applicationTree, + pageModelsGrid)); + + } + + private Component buildEditButton(final PageModelsTableRow row, + final AdminViewController controller) { + + final LocalizedTextsUtil localizedTextsUtil = controller + .getGlobalizationHelper() + .getLocalizedTextsUtil(AdminUiConstants.ADMIN_BUNDLE); + + final Button button = new Button(localizedTextsUtil + .getText("ui.admin.pagemodels.table.columns.edit.label"), + VaadinIcons.EDIT); + button.addStyleName(ValoTheme.BUTTON_TINY); + button.addClickListener(event -> { + final PageModel pageModel = controller + .getPageModelsController() + .getPageModelRepo() + .findById(row.getPageModelId()) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No PageModel with ID %d in the database.", + row.getPageModelId()))); + + final PageModelDetails pageModelDetails = new PageModelDetails( + pageModel, controller); + pageModelDetails.center(); + pageModelDetails.setModal(true); + pageModelDetails.setWidth("90%"); + pageModelDetails.setHeight("90%"); + UI.getCurrent().addWindow(pageModelDetails); + }); + + return button; + } + + private Component buildDeleteButton(final PageModelsTableRow row, + final AdminViewController controller) { + + final LocalizedTextsUtil localizedTextsUtil = controller + .getGlobalizationHelper() + .getLocalizedTextsUtil(AdminUiConstants.ADMIN_BUNDLE); + + final Button button = new Button(localizedTextsUtil + .getText("ui.admin.pagemodels.table.columns.delete.label"), + VaadinIcons.CLOSE_CIRCLE_O); + button.addStyleNames(ValoTheme.BUTTON_TINY, + ValoTheme.BUTTON_DANGER); + button.addClickListener(event -> { + final ConfirmDialog confirmDialog = new ConfirmDialog( + () -> { + controller + .getPageModelsController() + .deletePageModel(row.getPageModelId()); + + return null; + }); + confirmDialog.setMessage(localizedTextsUtil + .getText("ui.admin.pagemodels.delete.confirm")); + confirmDialog.setModal(true); + confirmDialog.center(); + UI.getCurrent().addWindow(confirmDialog); + }); + button.setEnabled(!row.isPublished()); + + return button; + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableDataProvider.java b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableDataProvider.java new file mode 100644 index 000000000..051c668e6 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableDataProvider.java @@ -0,0 +1,145 @@ +/* + * 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.libreccm.admin.ui; + +import com.vaadin.cdi.ViewScoped; +import com.vaadin.data.provider.AbstractBackEndDataProvider; +import com.vaadin.data.provider.Query; +import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.pagemodel.PageModel; +import org.libreccm.pagemodel.PageModelManager; +import org.libreccm.pagemodel.PageModelVersion; +import org.libreccm.web.CcmApplication; + +import java.util.stream.Stream; + +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@ViewScoped +class PageModelsTableDataProvider + extends AbstractBackEndDataProvider { + + private static final long serialVersionUID = 8052894182508842905L; + + @Inject + private EntityManager entityManager; + + @Inject + private GlobalizationHelper globalizationHelper; + + @Inject + private PageModelManager pageModelManager; + + private CcmApplication application; + + public CcmApplication getApplication() { + return application; + } + + public void setApplication(final CcmApplication application) { + this.application = application; + refreshAll(); + } + + @Transactional(Transactional.TxType.REQUIRED) + @Override + protected Stream fetchFromBackEnd( + final Query query) { + + if (application == null) { + return Stream.empty(); + } else { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder + .createQuery(PageModel.class); + + final Root from = criteriaQuery.from(PageModel.class); + + criteriaQuery + .where(builder + .and(builder.equal(from.get("application"), application), + builder.equal(from.get("version"), + PageModelVersion.DRAFT))) + .orderBy(builder.asc(from.get("name"))) + .orderBy(builder.asc(from.get("title"))); + + return entityManager + .createQuery(criteriaQuery) + .setFirstResult(query.getOffset()) + .setMaxResults(query.getLimit()) + .getResultList() + .stream() + .map(this::buildRow); + } + } + + private PageModelsTableRow buildRow(final PageModel model) { + + final PageModelsTableRow row = new PageModelsTableRow(); + + row.setPageModelId(model.getPageModelId()); + row.setName(model.getName()); + row.setTitle(globalizationHelper + .getValueFromLocalizedString(model.getTitle())); + row.setDescription(globalizationHelper + .getValueFromLocalizedString(model.getDescription())); + row.setPublished(pageModelManager.isLive(model)); + + return row; + + } + + @Override + protected int sizeInBackEnd(final Query query) { + + if (application == null) { + return 0; + } else { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder + .createQuery(Long.class); + + final Root from = criteriaQuery.from(PageModel.class); + criteriaQuery.select(builder.count(from)); + + criteriaQuery + .where(builder + .and(builder.equal(from.get("application"), application), + builder.equal(from.get("version"), + PageModelVersion.DRAFT))); + + return entityManager + .createQuery(criteriaQuery) + .getSingleResult() + .intValue(); + } + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableRow.java b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableRow.java new file mode 100644 index 000000000..d0cbb8633 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableRow.java @@ -0,0 +1,164 @@ +/* + * 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.libreccm.admin.ui; + +import java.io.Serializable; +import java.util.Objects; + +/** + * + * @author Jens Pelzetter + */ +public class PageModelsTableRow implements Serializable, + Comparable { + + private static final long serialVersionUID = -6995542858134206603L; + + private long pageModelId; + private String name; + private String title; + private String description; + private boolean published; + + public long getPageModelId() { + return pageModelId; + } + + public void setPageModelId(final long pageModelId) { + this.pageModelId = pageModelId; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getTitle() { + return title; + } + + public void setTitle(final String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + public boolean isPublished() { + return published; + } + + public void setPublished(final boolean published) { + this.published = published; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 17 * hash + (int) (pageModelId ^ (pageModelId >>> 32)); + hash = 17 * hash + Objects.hashCode(name); + hash = 17 * hash + Objects.hashCode(title); + hash = 17 * hash + Objects.hashCode(description); + hash = 17 * hash + (published ? 1 : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof PageModelsTableRow)) { + return false; + } + final PageModelsTableRow other = (PageModelsTableRow) obj; + if (!other.canEqual(this)) { + return false; + } + + if (pageModelId != other.getPageModelId()) { + return false; + } + if (published != other.isPublished()) { + return false; + } + if (!Objects.equals(name, other.getName())) { + return false; + } + if (!Objects.equals(title, other.getTitle())) { + return false; + } + return Objects.equals(description, other.getDescription()); + } + + public boolean canEqual(final Object obj) { + return obj instanceof PageModelsTableRow; + } + + @Override + public int compareTo(final PageModelsTableRow other) { + + int result = title.compareTo(other.getTitle()); + + if (result == 0) { + result = name.compareTo(other.getName()); + } + + if (result == 0) { + result = Boolean.compare(published, other.isPublished()); + } + + return result; + } + + @Override + public final String toString() { + return toString(""); + } + + public String toString(final String data) { + + return String.format("%s{ " + + "pageModelId = %d, " + + "name = \"%s\", " + + "published = %b, " + + "title = \"%s\", " + + "description = \"%s\"%s" + + " }", + super.toString(), + pageModelId, + name, + published, + title, + description, + data); + + } +} diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/SitesController.java b/ccm-core/src/main/java/org/libreccm/admin/ui/SitesController.java index e7a3f415e..46233773d 100644 --- a/ccm-core/src/main/java/org/libreccm/admin/ui/SitesController.java +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/SitesController.java @@ -26,7 +26,6 @@ import org.libreccm.theming.Themes; import java.io.Serializable; import javax.inject.Inject; -import javax.persistence.EntityManager; import javax.transaction.Transactional; /** diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/SitesTab.java b/ccm-core/src/main/java/org/libreccm/admin/ui/SitesTab.java index 4f6d191fe..9b317d4dd 100644 --- a/ccm-core/src/main/java/org/libreccm/admin/ui/SitesTab.java +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/SitesTab.java @@ -103,6 +103,7 @@ class SitesTab extends CustomComponent { final SiteEditor editor = new SiteEditor( site, adminViewController); editor.center(); + editor.setModal(true); editor.setWidth("66%"); editor.setHeight("80%"); UI.getCurrent().addWindow(editor); diff --git a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java index 69851b1fd..3b3a96ef6 100644 --- a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java +++ b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java @@ -26,15 +26,23 @@ import com.arsdigita.ui.login.LoginApplicationCreator; import com.arsdigita.ui.login.LoginApplicationSetup; import com.arsdigita.ui.login.LoginConstants; import com.arsdigita.ui.login.LoginServlet; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.libreccm.admin.ui.AdminJsfApplicationCreator; import org.libreccm.admin.ui.AdminJsfApplicationSetup; -import org.libreccm.modules.*; +import org.libreccm.modules.CcmModule; +import org.libreccm.modules.InitEvent; +import org.libreccm.modules.InstallEvent; +import org.libreccm.modules.Module; +import org.libreccm.modules.ShutdownEvent; +import org.libreccm.modules.UnInstallEvent; + import org.libreccm.security.SystemUsersSetup; import org.libreccm.web.ApplicationType; import javax.persistence.EntityManager; + import java.io.IOException; import java.io.InputStream; import java.util.Properties; diff --git a/ccm-core/src/main/java/org/libreccm/web/ApplicationManager.java b/ccm-core/src/main/java/org/libreccm/web/ApplicationManager.java index 059a4cc85..4c5917c3b 100644 --- a/ccm-core/src/main/java/org/libreccm/web/ApplicationManager.java +++ b/ccm-core/src/main/java/org/libreccm/web/ApplicationManager.java @@ -74,6 +74,12 @@ public class ApplicationManager { } } + /** + * Get all available application types. + * + * @return An unmodifiable {@link Map} containing all available application + * types. The key of the map is the name of the application. + */ public Map getApplicationTypes() { return Collections.unmodifiableMap(applicationTypes); } diff --git a/ccm-core/src/test/java/org/libreccm/portation/CoreDataImportTest.java b/ccm-core/src/test/java/org/libreccm/portation/CoreDataImportTest.java index a679ab98e..ba14ebc03 100644 --- a/ccm-core/src/test/java/org/libreccm/portation/CoreDataImportTest.java +++ b/ccm-core/src/test/java/org/libreccm/portation/CoreDataImportTest.java @@ -30,7 +30,7 @@ import org.jboss.arquillian.transaction.api.annotation.Transactional; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.EmptyAsset; import org.jboss.shrinkwrap.api.spec.WebArchive; -import org.junit.*; + import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.libreccm.security.GroupRepository; @@ -40,6 +40,13 @@ import javax.inject.Inject; import static org.libreccm.testutils.DependenciesHelpers.getModuleDependencies; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + /** * Test class. Tests the import capabilities of the core module diff --git a/ccm-core/src/test/java/org/libreccm/portation/ImportHelper.java b/ccm-core/src/test/java/org/libreccm/portation/ImportHelper.java index e5a354017..227ac3691 100644 --- a/ccm-core/src/test/java/org/libreccm/portation/ImportHelper.java +++ b/ccm-core/src/test/java/org/libreccm/portation/ImportHelper.java @@ -64,8 +64,9 @@ import javax.inject.Inject; */ @RequestScoped class ImportHelper { - //private String repoPath = "/home/jensp/pwi/libreccm/ccm/"; - private final String repoPath = "/home/tosmers/Svn/libreccm/"; + + private String repoPath = "/home/jensp/pwi/libreccm/ccm/"; +// private final String repoPath = "/home/tosmers/Svn/libreccm/"; private final String projectPath = "ccm_ng/ccm-core/src/test/resources/" + "portation/trunk-iaw-exports"; private final boolean indentation = false;