getEntityClass() {
+ return ComponentModel.class;
+ }
+
+ @Override
+ public boolean isNew(final ComponentModel componentModel) {
+ return componentModel.getComponentModelId() == 0;
+ }
+
+ @Override
+ public void initNewEntity(final ComponentModel componentModel) {
+ componentModel.setUUid(UUID.randomUUID().toString());
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/ComponentModelType.java b/ccm-core/src/main/java/org/libreccm/pagemodel/ComponentModelType.java
new file mode 100644
index 000000000..b42eac467
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/ComponentModelType.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Specifies for which view technology a {@link ComponentBuilder} builds the
+ * components.
+ *
+ * @author Jens Pelzetter
+ */
+@Qualifier
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface ComponentModelType {
+
+ String type();
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/PageBuilder.java b/ccm-core/src/main/java/org/libreccm/pagemodel/PageBuilder.java
new file mode 100644
index 000000000..7aa5125c2
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/PageBuilder.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 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;
+
+import javax.enterprise.context.RequestScoped;
+
+/**
+ * Interface for page builders. A page builder is invoked to build a page a
+ * specific type. An implementation should be a CDI bean which is annotated with
+ * the qualifier {@link PageModelType}. The recommended scope is
+ * {@link RequestScoped}.
+ *
+ * An implementation should add all default components which have to be present
+ * in page. The {@link PageModel} should only specify additional
+ * components.
+ *
+ *
+ * @author Jens Pelzetter
+ * @param The type of page the page builder creates.
+ */
+public interface PageBuilder
{
+
+ /**
+ * Build a page of type {@code P} using the provided {@link PageModel}.
+ *
+ * @param pageModel The {@link PageModel} from which the page is generated.
+ *
+ * @return The page generated from the provided {@link PageModel}.
+ */
+ P buildPage(PageModel pageModel);
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/PageBuilderManager.java b/ccm-core/src/main/java/org/libreccm/pagemodel/PageBuilderManager.java
new file mode 100644
index 000000000..2e5e263f6
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/PageBuilderManager.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 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;
+
+import org.libreccm.web.CcmApplication;
+
+import java.util.Iterator;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.inject.Inject;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+public class PageBuilderManager {
+
+ @Inject
+ private Instance> pageBuilders;
+
+ public PageBuilder> findPageBuilder(
+ final String type,
+ final Class extends CcmApplication> applicationType) {
+
+ final PageModelTypeLiteral literal = new PageModelTypeLiteral(
+ type, applicationType);
+
+ final Instance> instance = pageBuilders.select(literal);
+
+ if (instance.isUnsatisfied()) {
+ throw new IllegalArgumentException(String.format(
+ "No PageBuilder for type \"%s\" and application type \"%s\" "
+ + "available.",
+ type,
+ applicationType));
+ } else if (instance.isAmbiguous()) {
+ throw new IllegalArgumentException(String.format(
+ "There are more than one PageBuilders for type \"%s\" and "
+ + "application type \"%s\" avilable. Something is wrong.",
+ type,
+ applicationType));
+ } else {
+ final Iterator> iterator = instance.iterator();
+ final PageBuilder> pageBuilder = iterator.next();
+
+ return pageBuilder;
+ }
+ }
+
+ private class PageModelTypeLiteral
+ extends AnnotationLiteral
+ implements PageModelType {
+
+ private static final long serialVersionUID = 5919950993273871601L;
+
+ private final String type;
+ private final Class extends CcmApplication> applicationType;
+
+ public PageModelTypeLiteral(
+ final String type,
+ final Class extends CcmApplication> applicationType) {
+
+ this.type = type;
+ this.applicationType = applicationType;
+ }
+
+ @Override
+ public String type() {
+ return type;
+ }
+
+ @Override
+ public Class extends CcmApplication> applicationType() {
+ return applicationType;
+ }
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/PageModel.java b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModel.java
new file mode 100644
index 000000000..3c4752d50
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModel.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2016 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;
+
+import org.libreccm.core.CoreConstants;
+import org.libreccm.l10n.LocalizedString;
+import org.libreccm.web.CcmApplication;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import javax.persistence.AssociationOverride;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+
+/**
+ * A {@link PageModel} is used by a {@link PageBuilder} implementation to build
+ * a page. The {@code PageModel} specifics which components are used on a page.
+ *
+ * @author Jens Pelzetter
+ */
+@Entity
+@Table(name = "PAGE_MODELS", schema = CoreConstants.DB_SCHEMA)
+@NamedQueries({
+ @NamedQuery(
+ name = "PageModel.findByApplication",
+ query = "SELECT p FROM PageModel p WHERE p.application = :application")
+ ,
+ @NamedQuery(
+ name = "PageModel.countByApplication",
+ query = "SELECT COUNT(p) FROM PageModel p "
+ + "WHERE p.application = :application")
+ ,
+ @NamedQuery(
+ name = "PageModel.findByApplicationAndName",
+ query = "SELECT p FROM PageModel p "
+ + "WHERE p.name = :name AND p.application = :application"
+ ),
+ @NamedQuery(
+ name = "PageModel.countByApplicationAndName",
+ query = "SELECT COUNT(p) FROM PageModel p "
+ + "WHERE p.name = :name AND p.application = :application"
+ )
+})
+public class PageModel implements Serializable {
+
+ private static final long serialVersionUID = 7252512839926020978L;
+
+ @Id
+ @Column(name = "PAGE_MODEL_ID")
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long pageModelId;
+
+ @Column(name = "UUID", length = 255, nullable = false)
+ @NotNull
+ private String uuid;
+
+ @Column(name = "NAME", length = 255)
+ private String name;
+
+ @Column(name = "VERSION", length = 255, nullable = false)
+ @Enumerated(EnumType.STRING)
+ private PageModelVersion version;
+
+ @Embedded
+ @AssociationOverride(
+ name = "values",
+ joinTable = @JoinTable(name = "PAGE_MODEL_TITLES",
+ schema = CoreConstants.DB_SCHEMA,
+ joinColumns = {
+ @JoinColumn(name = "PAGE_MODEL_ID")
+ }))
+ private LocalizedString title;
+
+ @Embedded
+ @AssociationOverride(
+ name = "values",
+ joinTable = @JoinTable(name = "PAGE_MODEL_DESCRIPTIONS",
+ schema = CoreConstants.DB_SCHEMA,
+ joinColumns = {
+ @JoinColumn(name = "PAGE_MODEL_ID")
+ }))
+ private LocalizedString description;
+
+ @ManyToOne
+ @JoinColumn(name = "APPLICATION_ID")
+ private CcmApplication application;
+
+ @Column(name = "TYPE", length = 255, nullable = false)
+ @NotNull
+ private String type;
+
+ @OneToMany(mappedBy = "pageModel")
+ private List components;
+
+ public PageModel() {
+ title = new LocalizedString();
+ description = new LocalizedString();
+ }
+
+ public long getPageModelId() {
+ return pageModelId;
+ }
+
+ protected void setPageModelId(final long pageModelId) {
+ this.pageModelId = pageModelId;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ protected void setUuid(final String uuid) {
+ this.uuid = uuid;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public PageModelVersion getVersion() {
+ return version;
+ }
+
+ protected void setPageModelVersion(final PageModelVersion version) {
+ this.version = version;
+ }
+
+ public LocalizedString getTitle() {
+ return title;
+ }
+
+ protected void setTitle(final LocalizedString title) {
+ this.title = title;
+ }
+
+ public LocalizedString getDescription() {
+ return description;
+ }
+
+ protected void setDescription(final LocalizedString description) {
+ this.description = description;
+ }
+
+ public CcmApplication getApplication() {
+ return application;
+ }
+
+ protected void setApplication(final CcmApplication application) {
+ this.application = application;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(final String type) {
+ this.type = type;
+ }
+
+ public List getComponents() {
+ return Collections.unmodifiableList(components);
+ }
+
+ protected void setComponents(final List components) {
+ this.components = components;
+ }
+
+ public void addComponent(final ComponentModel component) {
+ components.add(component);
+ }
+
+ public void removeComponent(final ComponentModel component) {
+ components.remove(component);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 71 * hash + (int) (pageModelId ^ (pageModelId >>> 32));
+ hash = 71 * hash + Objects.hashCode(uuid);
+ hash = 71 * hash + Objects.hashCode(name);
+ hash = 71 * hash + Objects.hashCode(title);
+ hash = 71 * hash + Objects.hashCode(description);
+ hash = 71 * hash + Objects.hashCode(type);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof PageModel)) {
+ return false;
+ }
+ final PageModel other = (PageModel) obj;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ if (pageModelId != other.getPageModelId()) {
+ return false;
+ }
+ if (!Objects.equals(uuid, other.getUuid())) {
+ return false;
+ }
+ if (!Objects.equals(name, other.getName())) {
+ return false;
+ }
+ if (!Objects.equals(type, other.getType())) {
+ 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 PageModel;
+ }
+
+ @Override
+ public final String toString() {
+ return toString("");
+ }
+
+ public String toString(final String data) {
+ return String.format("%s{ "
+ + "pageModelId = %d, "
+ + "uuid = %s, "
+ + "name = \"%s\", "
+ + "title = %s, "
+ + "description = %s, "
+ + "type = \"%s\""
+ + " }",
+ super.toString(),
+ pageModelId,
+ uuid,
+ name,
+ Objects.toString(title),
+ Objects.toString(description),
+ type);
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelComponentModel.java b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelComponentModel.java
new file mode 100644
index 000000000..c8fb2f200
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelComponentModel.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface PageModelComponentModel {
+
+ String descBundle() default "";
+
+ String titleKey() default "component_model_title";
+
+ String descKey() default "component_model_desc";
+
+ Class extends ComponentModel> modelClass();
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelManager.java b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelManager.java
new file mode 100644
index 000000000..800c01abf
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelManager.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2016 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;
+
+import org.libreccm.core.CoreConstants;
+import org.libreccm.security.AuthorizationRequired;
+import org.libreccm.security.RequiresPrivilege;
+import org.libreccm.web.CcmApplication;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+public class PageModelManager {
+
+ @Inject
+ private PageModelRepository pageModelRepo;
+
+ @Inject
+ private ComponentModelRepository componentModelRepo;
+
+ /**
+ * Creates a new {@link PageModel} for the provided application.
+ *
+ * @param name The name of the new page model. Must be unique for the
+ * application.
+ * @param application The application for which the {@link PageModel} is
+ * created.
+ *
+ * @return The new {@link PageModel}.
+ */
+ @Transactional(Transactional.TxType.REQUIRED)
+ @AuthorizationRequired
+ @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
+ public PageModel createPageModel(final String name,
+ final CcmApplication application,
+ final String type) {
+
+ if (application == null) {
+ throw new IllegalArgumentException(
+ "Can't create a page model for application null");
+ }
+
+ if (name == null || name.trim().isEmpty()) {
+ throw new IllegalArgumentException(
+ "The name of a page model can't be null or empty.");
+ }
+
+ final long count = pageModelRepo.countByApplicationAndName(application,
+ name);
+
+ if (count > 0) {
+ throw new IllegalArgumentException(String.format(
+ "A page model with the name \"%s\" for the application \"%s\" "
+ + "already exists.",
+ name,
+ application.getPrimaryUrl()));
+ }
+
+ final PageModel pageModel = new PageModel();
+
+ pageModel.setName(name);
+ pageModel.setApplication(application);
+ pageModel.setType(type);
+
+ return pageModel;
+ }
+
+ /**
+ * Add a {@link ComponentModel} to a {@link PageModel}.
+ *
+ * @param pageModel The {@link PageModel} to which component model is
+ * added.
+ * @param componentModel The {@link ComponentModel} to add.
+ */
+ public void addComponentModel(final PageModel pageModel,
+ final ComponentModel componentModel) {
+
+ if (pageModel == null) {
+ throw new IllegalArgumentException(
+ "Can't add a component model to page model null.");
+ }
+
+ if (componentModel == null) {
+ throw new IllegalArgumentException(
+ "Can't add component model null to a page model.");
+ }
+
+ pageModel.addComponent(componentModel);
+ componentModel.setPageModel(pageModel);
+
+ pageModelRepo.save(pageModel);
+ componentModelRepo.save(componentModel);
+ }
+
+ /**
+ * Removes a {@link ComponentModel} from a {@link PageModel}.
+ *
+ * @param pageModel The {@link PageModel} from which the
+ * {@link ComponentModel} is removed.
+ * @param componentModel The {@link ComponentModel} to remove. The component
+ * model is also removed from the database.
+ */
+ public void removeComponentModel(final PageModel pageModel,
+ final ComponentModel componentModel) {
+
+ if (pageModel == null) {
+ throw new IllegalArgumentException(
+ "Can't remove a component model from page model null.");
+ }
+
+ if (componentModel == null) {
+ throw new IllegalArgumentException(
+ "Can't remove component model null from a page model.");
+ }
+
+ pageModel.removeComponent(componentModel);
+ componentModel.setPageModel(null);
+
+ pageModelRepo.save(pageModel);
+ componentModelRepo.delete(componentModel);
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelRepository.java b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelRepository.java
new file mode 100644
index 000000000..3135ba1c0
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelRepository.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2016 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;
+
+import org.libreccm.core.AbstractEntityRepository;
+import org.libreccm.web.CcmApplication;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+import javax.enterprise.context.RequestScoped;
+import javax.persistence.TypedQuery;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+public class PageModelRepository extends AbstractEntityRepository {
+
+ @Override
+ public Class getEntityClass() {
+ return PageModel.class;
+ }
+
+ @Override
+ public boolean isNew(final PageModel pageModel) {
+ if (pageModel == null) {
+ throw new IllegalArgumentException("PageModel can't be null.");
+ }
+
+ return pageModel.getPageModelId() == 0;
+ }
+
+ @Override
+ public void initNewEntity(final PageModel pageModel) {
+ if (pageModel == null) {
+ throw new IllegalArgumentException("PageModel can't be null.");
+ }
+
+ pageModel.setUuid(UUID.randomUUID().toString());
+ }
+
+ public List findByApplication(final CcmApplication application) {
+ if (application == null) {
+ throw new IllegalArgumentException(
+ "Can't find page models for application null");
+ }
+
+ final TypedQuery query = getEntityManager().createNamedQuery(
+ "PageModel.findByApplication", PageModel.class);
+ query.setParameter("application", application);
+
+ return query.getResultList();
+ }
+
+ public long countByApplication(final CcmApplication application) {
+ if (application == null) {
+ throw new IllegalArgumentException(
+ "Can't count page models for application null");
+ }
+
+ final TypedQuery query = getEntityManager().createNamedQuery(
+ "PageModel.countByApplication", Long.class);
+ query.setParameter("application", application);
+
+ return query.getSingleResult();
+ }
+
+ public Optional findByApplicationAndName(
+ final CcmApplication application,
+ final String name) {
+
+ if (application == null) {
+ throw new IllegalArgumentException(
+ "Can't find page models for application null");
+ }
+
+ if (name == null || name.trim().isEmpty()) {
+ throw new IllegalArgumentException(
+ "The name of a page model can't be null or empty.");
+ }
+
+ final long count = countByApplicationAndName(application, name);
+ if (count == 0) {
+ return Optional.empty();
+ }
+
+ final TypedQuery query = getEntityManager().createNamedQuery(
+ "PageModel.findByApplicationAndName", PageModel.class);
+ query.setParameter("application", application);
+ query.setParameter("name", name);
+
+ return Optional.of(query.getSingleResult());
+ }
+
+ public long countByApplicationAndName(final CcmApplication application,
+ final String name) {
+
+ if (application == null) {
+ throw new IllegalArgumentException(
+ "Can't count page models for application null");
+ }
+
+ if (name == null || name.trim().isEmpty()) {
+ throw new IllegalArgumentException(
+ "The name of a page model can't be null or empty.");
+ }
+
+ final TypedQuery query = getEntityManager().createNamedQuery(
+ "PageModel.countByApplicationAndName", Long.class);
+ query.setParameter("application", application);
+ query.setParameter("name", name);
+
+ return query.getSingleResult();
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelType.java b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelType.java
new file mode 100644
index 000000000..d444b4a8b
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelType.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 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;
+
+import org.libreccm.web.CcmApplication;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Specifies for which application type and which view technology a
+ * {@link PageBuilder} builds the pages.
+ *
+ * @author Jens Pelzetter
+ */
+@Qualifier
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface PageModelType {
+
+ String type();
+
+ Class extends CcmApplication> applicationType();
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelVersion.java b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelVersion.java
new file mode 100644
index 000000000..52e92d53c
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/PageModelVersion.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 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;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public enum PageModelVersion {
+
+ DRAFT,
+ LIVE
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/package-info.java b/ccm-core/src/main/java/org/libreccm/pagemodel/package-info.java
new file mode 100644
index 000000000..d52324560
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/package-info.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 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
+ */
+/**
+ * The {@code pagemodel} packages provides an abstraction layer between the data
+ * model of page and its generating components. This layer replaces the JSP
+ * templates which were used in previous versions for this purpose.
+ *
+ * The Page Model system allows it to specify which components are used on a
+ * page are therefore which information is displayed on a page. It is intended
+ * to be used for public pages (like the item page of a content item category
+ * page in ccm-cms. The Page Model system uses data container which are read by
+ * some builder classes. Because we are not using an active code in the page
+ * models this avoids a potential attack point.
+ *
+ *
+ *
+ */
+package org.libreccm.pagemodel;
diff --git a/ccm-core/src/main/java/org/libreccm/web/ApplicationType.java b/ccm-core/src/main/java/org/libreccm/web/ApplicationType.java
index 7dba4fb04..9db7cd54f 100644
--- a/ccm-core/src/main/java/org/libreccm/web/ApplicationType.java
+++ b/ccm-core/src/main/java/org/libreccm/web/ApplicationType.java
@@ -62,8 +62,6 @@ public @interface ApplicationType {
* bundle. Defaults to {@code application_title}
*
* @return
- *
- * @return
*/
String titleKey() default "application_title";
diff --git a/ccm-core/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_core_schema.sql b/ccm-core/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_core_schema.sql
index e65f64d92..a2686259e 100644
--- a/ccm-core/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_core_schema.sql
+++ b/ccm-core/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_core_schema.sql
@@ -4,6 +4,7 @@ drop sequence if exists HIBERNATE_SEQUENCE;
create schema CCM_CORE;
+
create table CCM_CORE.APPLICATIONS (
APPLICATION_TYPE varchar(1024) not null,
PRIMARY_URL varchar(1024) not null,
@@ -396,6 +397,41 @@ create schema CCM_CORE;
primary key (TOKEN_ID)
);
+ create table CCM_CORE.PAGE_MODEL_COMPONENT_MODELS (
+ COMPONENT_MODEL_ID bigint not null,
+ CLASS_ATTRIBUTE varchar(512),
+ ID_ATTRIBUTE varchar(255),
+ COMPONENT_KEY varchar(255),
+ STYLE_ATTRIBUTE varchar(1024),
+ UUID varchar(255) not null,
+ PAGE_MODEL_ID bigint,
+ primary key (COMPONENT_MODEL_ID)
+ );
+
+ create table CCM_CORE.PAGE_MODEL_DESCRIPTIONS (
+ PAGE_MODEL_ID bigint not null,
+ LOCALIZED_VALUE longvarchar,
+ LOCALE varchar(255) not null,
+ primary key (PAGE_MODEL_ID, LOCALE)
+ );
+
+ create table CCM_CORE.PAGE_MODEL_TITLES (
+ PAGE_MODEL_ID bigint not null,
+ LOCALIZED_VALUE longvarchar,
+ LOCALE varchar(255) not null,
+ primary key (PAGE_MODEL_ID, LOCALE)
+ );
+
+ create table CCM_CORE.PAGE_MODELS (
+ PAGE_MODEL_ID bigint not null,
+ NAME varchar(255),
+ TYPE varchar(255) not null,
+ UUID varchar(255) not null,
+ VERSION varchar(255) not null,
+ APPLICATION_ID bigint,
+ primary key (PAGE_MODEL_ID)
+ );
+
create table CCM_CORE.PARTIES (
PARTY_ID bigint not null,
NAME varchar(256) not null,
@@ -497,11 +533,11 @@ create schema CCM_CORE;
SETTING_ID bigint not null,
CONFIGURATION_CLASS varchar(512) not null,
NAME varchar(512) not null,
- SETTING_VALUE_STRING varchar(1024),
- SETTING_VALUE_LONG bigint,
- SETTING_VALUE_DOUBLE double,
SETTING_VALUE_BOOLEAN boolean,
+ SETTING_VALUE_STRING varchar(1024),
+ SETTING_VALUE_DOUBLE double,
SETTING_VALUE_BIG_DECIMAL decimal(19,2),
+ SETTING_VALUE_LONG bigint,
primary key (SETTING_ID)
);
@@ -966,6 +1002,26 @@ create sequence hibernate_sequence start with 1 increment by 1;
foreign key (USER_ID)
references CCM_CORE.USERS;
+ alter table CCM_CORE.PAGE_MODEL_COMPONENT_MODELS
+ add constraint FKo696ch035fe7rrueol1po13od
+ foreign key (PAGE_MODEL_ID)
+ references CCM_CORE.PAGE_MODELS;
+
+ alter table CCM_CORE.PAGE_MODEL_DESCRIPTIONS
+ add constraint FKcc5d6eqxu1369k8ycyyt6vn3e
+ foreign key (PAGE_MODEL_ID)
+ references CCM_CORE.PAGE_MODELS;
+
+ alter table CCM_CORE.PAGE_MODEL_TITLES
+ add constraint FKj14q9911yhd4js9p6rs21rwjf
+ foreign key (PAGE_MODEL_ID)
+ references CCM_CORE.PAGE_MODELS;
+
+ alter table CCM_CORE.PAGE_MODELS
+ add constraint FKk2lihllrxj89mn3tqv43amafe
+ foreign key (APPLICATION_ID)
+ references CCM_CORE.APPLICATIONS;
+
alter table CCM_CORE.PERMISSIONS
add constraint FKj9di7pawxgtouxmu2k44bj5c4
foreign key (CREATION_USER_ID)
diff --git a/ccm-core/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_core_schema.sql b/ccm-core/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_core_schema.sql
index a75baa7b6..a44665b1d 100644
--- a/ccm-core/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_core_schema.sql
+++ b/ccm-core/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_core_schema.sql
@@ -396,6 +396,41 @@ create schema CCM_CORE;
primary key (TOKEN_ID)
);
+ create table CCM_CORE.PAGE_MODEL_COMPONENT_MODELS (
+ COMPONENT_MODEL_ID int8 not null,
+ CLASS_ATTRIBUTE varchar(512),
+ ID_ATTRIBUTE varchar(255),
+ COMPONENT_KEY varchar(255),
+ STYLE_ATTRIBUTE varchar(1024),
+ UUID varchar(255) not null,
+ PAGE_MODEL_ID int8,
+ primary key (COMPONENT_MODEL_ID)
+ );
+
+ create table CCM_CORE.PAGE_MODEL_DESCRIPTIONS (
+ PAGE_MODEL_ID int8 not null,
+ LOCALIZED_VALUE text,
+ LOCALE varchar(255) not null,
+ primary key (PAGE_MODEL_ID, LOCALE)
+ );
+
+ create table CCM_CORE.PAGE_MODEL_TITLES (
+ PAGE_MODEL_ID int8 not null,
+ LOCALIZED_VALUE text,
+ LOCALE varchar(255) not null,
+ primary key (PAGE_MODEL_ID, LOCALE)
+ );
+
+ create table CCM_CORE.PAGE_MODELS (
+ PAGE_MODEL_ID int8 not null,
+ NAME varchar(255),
+ TYPE varchar(255) not null,
+ UUID varchar(255) not null,
+ VERSION varchar(255) not null,
+ APPLICATION_ID int8,
+ primary key (PAGE_MODEL_ID)
+ );
+
create table CCM_CORE.PARTIES (
PARTY_ID int8 not null,
NAME varchar(256) not null,
@@ -497,11 +532,11 @@ create schema CCM_CORE;
SETTING_ID int8 not null,
CONFIGURATION_CLASS varchar(512) not null,
NAME varchar(512) not null,
- SETTING_VALUE_STRING varchar(1024),
- SETTING_VALUE_LONG int8,
- SETTING_VALUE_DOUBLE float8,
SETTING_VALUE_BOOLEAN boolean,
+ SETTING_VALUE_STRING varchar(1024),
+ SETTING_VALUE_DOUBLE float8,
SETTING_VALUE_BIG_DECIMAL numeric(19, 2),
+ SETTING_VALUE_LONG int8,
primary key (SETTING_ID)
);
@@ -966,6 +1001,26 @@ create sequence hibernate_sequence start 1 increment 1;
foreign key (USER_ID)
references CCM_CORE.USERS;
+ alter table CCM_CORE.PAGE_MODEL_COMPONENT_MODELS
+ add constraint FKo696ch035fe7rrueol1po13od
+ foreign key (PAGE_MODEL_ID)
+ references CCM_CORE.PAGE_MODELS;
+
+ alter table CCM_CORE.PAGE_MODEL_DESCRIPTIONS
+ add constraint FKcc5d6eqxu1369k8ycyyt6vn3e
+ foreign key (PAGE_MODEL_ID)
+ references CCM_CORE.PAGE_MODELS;
+
+ alter table CCM_CORE.PAGE_MODEL_TITLES
+ add constraint FKj14q9911yhd4js9p6rs21rwjf
+ foreign key (PAGE_MODEL_ID)
+ references CCM_CORE.PAGE_MODELS;
+
+ alter table CCM_CORE.PAGE_MODELS
+ add constraint FKk2lihllrxj89mn3tqv43amafe
+ foreign key (APPLICATION_ID)
+ references CCM_CORE.APPLICATIONS;
+
alter table CCM_CORE.PERMISSIONS
add constraint FKj9di7pawxgtouxmu2k44bj5c4
foreign key (CREATION_USER_ID)