From 6917b3addc21d2d61d8073f7a72a869895c9c7f8 Mon Sep 17 00:00:00 2001 From: jensp Date: Thu, 26 Apr 2018 12:10:31 +0000 Subject: [PATCH] CCM NG: RESTful backend for the PageModelEditor git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5378 8810af33-2d31-482b-a856-94f89814c4df --- .../contentsection/rs/ContentItems.java | 1 - .../libreccm/pagemodel/ContainerModel.java | 6 + .../org/libreccm/pagemodel/PageModel.java | 15 +- .../org/libreccm/pagemodel/rs/PageModels.java | 325 ++++++++++++++++++ .../libreccm/pagemodel/rs/PageModelsApp.java | 47 +++ 5 files changed, 389 insertions(+), 5 deletions(-) create mode 100644 ccm-core/src/main/java/org/libreccm/pagemodel/rs/PageModels.java create mode 100644 ccm-core/src/main/java/org/libreccm/pagemodel/rs/PageModelsApp.java diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentItems.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentItems.java index 53fffbea4..fa92f7c04 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentItems.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentItems.java @@ -20,7 +20,6 @@ package org.librecms.contentsection.rs; import org.libreccm.l10n.GlobalizationHelper; import org.librecms.contentsection.ContentItem; -import org.librecms.contentsection.ContentItemL10NManager; import org.librecms.contentsection.ContentItemManager; import org.librecms.contentsection.ContentItemRepository; import org.librecms.contentsection.ContentItemVersion; diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/ContainerModel.java b/ccm-core/src/main/java/org/libreccm/pagemodel/ContainerModel.java index 9dbbd2776..ca1b15d9c 100644 --- a/ccm-core/src/main/java/org/libreccm/pagemodel/ContainerModel.java +++ b/ccm-core/src/main/java/org/libreccm/pagemodel/ContainerModel.java @@ -41,6 +41,9 @@ import javax.persistence.OneToOne; import javax.persistence.OrderBy; import javax.persistence.Table; import javax.validation.constraints.NotNull; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; /** * A {@code ContainerModel} for grouping {@link ComponentModel}s. Each @@ -59,6 +62,7 @@ import javax.validation.constraints.NotNull; + "WHERE c.key = :key " + "AND c.pageModel = :pageModel") }) +@XmlRootElement(name = "container-model") public class ContainerModel implements Serializable { private static final long serialVersionUID = -7472858443655353588L; @@ -68,6 +72,7 @@ public class ContainerModel implements Serializable { */ @Id @Column(name = "CONTAINER_ID") + @XmlElement(name = "ocntainer-model-id") private long containerId; /** @@ -105,6 +110,7 @@ public class ContainerModel implements Serializable { @ManyToOne @JoinColumn(name = "PAGE_MODEL_ID") + @XmlTransient private PageModel pageModel; /** diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/PageModel.java b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModel.java index 11911714e..599d2f114 100644 --- a/ccm-core/src/main/java/org/libreccm/pagemodel/PageModel.java +++ b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModel.java @@ -49,6 +49,9 @@ import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.OrderBy; import javax.persistence.Table; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; /** * A {@link PageModel} is used by a {@link PageRenderer} implementation to @@ -98,7 +101,7 @@ import javax.persistence.Table; @NamedQuery( name = "PageModel.findDraftByApplication", query = "SELECT p FROM PageModel p " - + "WHERE p.application = :application " + + "WHERE p.application = :application " + "AND p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT" ) , @@ -106,6 +109,7 @@ import javax.persistence.Table; name = "PageModel.findDraftByApplicationAndName", query = "SELECT p FROM PageModel p " + "WHERE p.application = :application " + + "AND p.name = :name " + "AND p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT" ) , @@ -151,6 +155,7 @@ import javax.persistence.Table; + "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE" ) }) +@XmlRootElement(name = "pagemodel") public class PageModel implements Serializable { private static final long serialVersionUID = 7252512839926020978L; @@ -163,6 +168,7 @@ public class PageModel implements Serializable { @Id @Column(name = "PAGE_MODEL_ID") @GeneratedValue(strategy = GenerationType.AUTO) + @XmlElement(name = "pagemodel-id") private long pageModelId; /** @@ -228,6 +234,7 @@ public class PageModel implements Serializable { */ @ManyToOne @JoinColumn(name = "APPLICATION_ID") + @XmlTransient private CcmApplication application; /** @@ -328,15 +335,15 @@ public class PageModel implements Serializable { protected void setContainers(final List containers) { this.containers = new ArrayList<>(containers); } - + protected void addContainer(final ContainerModel container) { containers.add(container); } - + protected void removeContainer(final ContainerModel container) { containers.remove(container); } - + protected void clearContainers() { containers.clear(); } diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/rs/PageModels.java b/ccm-core/src/main/java/org/libreccm/pagemodel/rs/PageModels.java new file mode 100644 index 000000000..34d5114c9 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/pagemodel/rs/PageModels.java @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2018 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.pagemodel.rs; + +import org.libreccm.core.CoreConstants; +import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.pagemodel.ComponentModel; +import org.libreccm.pagemodel.ComponentModelRepository; +import org.libreccm.pagemodel.ContainerModel; +import org.libreccm.pagemodel.ContainerModelRepository; +import org.libreccm.pagemodel.PageModel; +import org.libreccm.pagemodel.PageModelRepository; +import org.libreccm.security.AuthorizationRequired; +import org.libreccm.security.RequiresPrivilege; +import org.libreccm.web.ApplicationRepository; +import org.libreccm.web.CcmApplication; + +import java.util.HashMap; +import java.util.Map; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; +import javax.transaction.Transactional; +import javax.ws.rs.GET; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Path("/{appPath}") +public class PageModels { + + @Inject + private ApplicationRepository appRepo; + + @Inject + private ComponentModelRepository componentModelRepo; + + @Inject + private ContainerModelRepository containerRepo; + + @Inject + private PageModelRepository pageModelRepo; + + @Inject + private GlobalizationHelper globalizationHelper; + +// @GET +// @Path("/{appPath}") +// @Produces("application/json; charset=utf-8") +// @Transactional(Transactional.TxType.REQUIRED) +// @AuthorizationRequired +// @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) +// public List> findAllPageModels( +// @PathParam("appPath") String appPath) { +// +// final CcmApplication app = findCcmApplication( +// String.format("/%s/", appPath)); +// return pageModelRepo +// .findDraftByApplication(app) +// .stream() +// .map(this::mapPageModelToDataMap) +// .collect(Collectors.toList()); +// } + @GET +// @Path("/{appPath}") + @Path("/") + @Produces("application/json; charset=utf-8") + @Transactional(Transactional.TxType.REQUIRED) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + public JsonArray findAllPageModels( + @PathParam("appPath") String appPath) { + + final CcmApplication app = findCcmApplication( + String.format("/%s/", appPath)); + final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); + pageModelRepo + .findDraftByApplication(app) + .stream() + .map(this::mapPageModelToJson) + .forEach(arrayBuilder::add); + + return arrayBuilder.build(); + } + + @GET +// @Path("/{appPath}/{pageModelName}") + @Path("/{pageModelName}") + @Produces("application/json; charset=utf-8") + @Transactional(Transactional.TxType.REQUIRED) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + public JsonObject findPageModel( + @PathParam("appPath") final String appPath, + @PathParam("pageModelName") final String pageModelName) { + + final CcmApplication app = findCcmApplication( + String.format("/%s/", appPath)); + + final PageModel pageModel = pageModelRepo + .findDraftByApplicationAndName(app, pageModelName) + .orElseThrow(() -> new NotFoundException(String.format( + "No PageModel with name \"%s\" for application \"%s\".", + pageModelName, appPath))); + return mapPageModelToJson(pageModel); + } + + @GET +// @Path("/{appPath}/{pageModelName}/containers") + @Path("/{pageModelName}/containers") + @Produces("application/json; charset=utf-8") + @Transactional(Transactional.TxType.REQUIRED) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + public JsonArray getContainers( + @PathParam("appPath") final String appPath, + @PathParam("pageModelName") final String pageModelName) { + + final CcmApplication app = findCcmApplication( + String.format("/%s/", appPath)); + + final PageModel pageModel = pageModelRepo + .findDraftByApplicationAndName(app, pageModelName) + .orElseThrow(() -> new NotFoundException(String.format( + "No PageModel with name \"%s\" for application \"%s\".", + pageModelName, appPath))); + + final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); + pageModel + .getContainers() + .stream() + .map(containerModel -> mapContainerModelToJson(containerModel)) + .forEach(arrayBuilder::add); + + return arrayBuilder.build(); + } + + @GET + @Path("/{pageModelName}/containers/{key}") + @Produces("application/json; charset=utf-8") + @Transactional(Transactional.TxType.REQUIRED) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + public JsonObject getContainer( + @PathParam("appPath") final String appPath, + @PathParam("pageModelName") final String pageModelName, + @PathParam("key") final String key) { + + final CcmApplication app = findCcmApplication( + String.format("/%s/", appPath)); + + final PageModel pageModel = pageModelRepo + .findDraftByApplicationAndName(app, pageModelName) + .orElseThrow(() -> new NotFoundException(String.format( + "No PageModel with name \"%s\" for application \"%s\".", + pageModelName, appPath))); + + final ContainerModel container = containerRepo + .findContainerByKeyAndPageModel(key, pageModel) + .orElseThrow(() -> new NotFoundException(String + .format("The PageModel \"%s\" of application \"%s\" does not have " + + "a container identified by the key \"%s\".", + pageModelName, + appPath, + key))); + + return mapContainerModelToJson(container); + } + + @GET + @Path("/{pageModelName}/containers/{key}/components") + @Produces("application/json; charset=utf-8") + @Transactional(Transactional.TxType.REQUIRED) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + public JsonArray getComponents( + @PathParam("appPath") final String appPath, + @PathParam("pageModelName") final String pageModelName, + @PathParam("key") final String key) { + + final CcmApplication app = findCcmApplication( + String.format("/%s/", appPath)); + + final PageModel pageModel = pageModelRepo + .findDraftByApplicationAndName(app, pageModelName) + .orElseThrow(() -> new NotFoundException(String.format( + "No PageModel with name \"%s\" for application \"%s\".", + pageModelName, appPath))); + + final ContainerModel container = containerRepo + .findContainerByKeyAndPageModel(key, pageModel) + .orElseThrow(() -> new NotFoundException(String + .format("The PageModel \"%s\" of application \"%s\" does not have " + + "a container identified by the key \"%s\".", + pageModelName, + appPath, + key))); + + final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); + container + .getComponents() + .stream() + .map(component -> mapComponentModelToJson(component)) + .forEach(arrayBuilder::add); + + return arrayBuilder.build(); + } + + private CcmApplication findCcmApplication(final String appPath) { + + return appRepo + .retrieveApplicationForPath(appPath) + .orElseThrow(() -> new NotFoundException(String + .format("No application with path \"%s\" found.", + appPath))); + } + + private JsonObject mapPageModelToJson(final PageModel pageModel) { + + return Json + .createObjectBuilder() + .add("description", + globalizationHelper + .getValueFromLocalizedString(pageModel.getDescription())) + .add("modelUuid", pageModel.getModelUuid()) + .add("name", pageModel.getName()) + .add("pageModelId", Long.toString(pageModel.getPageModelId())) + .add("title", + globalizationHelper + .getValueFromLocalizedString(pageModel.getTitle())) + .add("type", pageModel.getType()) + .add("uuid", pageModel.getUuid()) + .add("version", pageModel.getVersion().toString()) + .build(); + } + + private Map mapPageModelToDataMap(final PageModel pageModel) { + + final Map dataMap = new HashMap<>(); + + dataMap.put("description", + globalizationHelper + .getValueFromLocalizedString(pageModel.getDescription())); + dataMap.put("modelUuid", pageModel.getModelUuid()); + dataMap.put("name", pageModel.getName()); + dataMap.put("pageModelId", Long.toString(pageModel.getPageModelId())); + dataMap.put("title", + globalizationHelper + .getValueFromLocalizedString(pageModel.getTitle())); + dataMap.put("type", pageModel.getType()); + dataMap.put("uuid", pageModel.getUuid()); + dataMap.put("version", pageModel.getVersion().toString()); + + return dataMap; + } + + private JsonObject mapContainerModelToJson( + final ContainerModel containerModel) { + + return Json + .createObjectBuilder() + .add("containerId", Long.toString(containerModel.getContainerId())) + .add("uuid", containerModel.getUuid()) + .add("containerUuid", containerModel.getContainerUuid()) + .add("key", containerModel.getKey()) + .build(); + } + + private JsonObject mapComponentModelToJson( + final ComponentModel componentModel) { + + final JsonObjectBuilder objectBuilder = Json + .createObjectBuilder() + .add("componentModelId", + Long.toString(componentModel.getComponentModelId())) + .add("uuid", componentModel.getUuid()) + .add("modelUuid", componentModel.getModelUuid()) + .add("key", componentModel.getKey()) + .add("type", componentModel.getClass().getName()); + + if (componentModel.getIdAttribute() != null) { + objectBuilder.add("idAttribute", componentModel.getIdAttribute()); + } + + if (componentModel.getClassAttribute() != null) { + objectBuilder.add("classAttribute", + componentModel.getClassAttribute()); + } + + if (componentModel.getStyleAttribute() != null) { + objectBuilder.add("styleAttribute", + componentModel.getStyleAttribute()); + } + + return objectBuilder.build(); + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/rs/PageModelsApp.java b/ccm-core/src/main/java/org/libreccm/pagemodel/rs/PageModelsApp.java new file mode 100644 index 000000000..667570c43 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/pagemodel/rs/PageModelsApp.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018 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.pagemodel.rs; + +import org.libreccm.pagemodel.PageModel; + +import java.util.HashSet; +import java.util.Set; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +/** + * JAX-RS application for managing {@link PageModel}s. + * + * + * @author Jens Pelzetter + */ +@ApplicationPath("/page-models") +public class PageModelsApp extends Application { + + @Override + public Set> getClasses() { + + final Set> classes = new HashSet<>(); + classes.add(PageModels.class); + + return classes; + } + +}