From f8d8d38f6ec8f79ced95d3e2c241d7f30f1587ab Mon Sep 17 00:00:00 2001 From: jensp Date: Fri, 13 Oct 2017 15:59:22 +0000 Subject: [PATCH] CCM NG: Sites/Pages/Themes next part git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5044 8810af33-2d31-482b-a856-94f89814c4df --- .../org/librecms/pagemodel/GreetingItem.java | 155 ++++++ .../pagemodel/GreetingItemBuilder.java | 293 ++++++++++++ .../main/java/org/librecms/pages/Page.java | 113 +++-- .../java/org/librecms/pages/PageManager.java | 9 +- .../org/librecms/pages/PageRepository.java | 2 +- .../main/java/org/librecms/pages/Pages.java | 2 +- .../org/librecms/pages/PagesConstants.java | 38 ++ .../org/librecms/pages/PagesRepository.java | 3 - .../java/org/librecms/pages/PagesRouter.java | 443 ++++++++++++++---- .../ccm_cms/h2/V7_0_0_16__create_pages.sql | 56 +++ .../ccm_cms/h2/V7_0_0_16__create_sites.sql | 20 - .../ccm_cms/pgsql/V7_0_0_16__create_pages.sql | 57 +++ .../ccm_cms/pgsql/V7_0_0_16__create_sites.sql | 20 - .../scripts/create_ccm_cms_schema.sql | 102 +++- .../scripts/create_ccm_cms_schema.sql | 101 +++- .../libreccm/l10n/GlobalizationHelper.java | 6 + .../ccm_core/h2/V7_0_0_16__create_sites.sql | 16 + .../pgsql/V7_0_0_16__create_sites.sql | 16 + .../scripts/create_ccm_core_schema.sql | 23 +- .../scripts/create_ccm_core_schema.sql | 1 - 20 files changed, 1258 insertions(+), 218 deletions(-) create mode 100644 ccm-cms/src/main/java/org/librecms/pagemodel/GreetingItem.java create mode 100644 ccm-cms/src/main/java/org/librecms/pagemodel/GreetingItemBuilder.java create mode 100644 ccm-cms/src/main/java/org/librecms/pages/PagesConstants.java create mode 100644 ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_16__create_pages.sql delete mode 100644 ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_16__create_sites.sql create mode 100644 ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_16__create_pages.sql delete mode 100644 ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_16__create_sites.sql create mode 100644 ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/h2/V7_0_0_16__create_sites.sql create mode 100644 ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/pgsql/V7_0_0_16__create_sites.sql diff --git a/ccm-cms/src/main/java/org/librecms/pagemodel/GreetingItem.java b/ccm-cms/src/main/java/org/librecms/pagemodel/GreetingItem.java new file mode 100644 index 000000000..2698538ed --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/pagemodel/GreetingItem.java @@ -0,0 +1,155 @@ +/* + * 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 org.libreccm.categorization.Category; +import org.libreccm.pagemodel.ComponentModel; +import org.libreccm.pagemodel.PageModel; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.Table; + +import static org.librecms.CmsConstants.*; + +/** + * A {@link PageModel} component model for displaying the Greeting/Index item of + * a {@link Category}. + * + * @author Jens Pelzetter + */ +@Entity +@Table(name = "GREETING_ITEMS", schema = DB_SCHEMA) +public class GreetingItem extends ComponentModel { + + private static final long serialVersionUID = -5509783666595294223L; + + @ElementCollection + @CollectionTable(name = "GREETING_ITEM_INCLUDED_PATHS", + schema = DB_SCHEMA, + joinColumns = { + @JoinColumn(name = "GREETING_ITEM_ID") + }) + private Set includedPropertyPaths; + + @ElementCollection + @CollectionTable(name = "GREETING_ITEM_EXCLUDED_PATHS", + schema = DB_SCHEMA, + joinColumns = { + @JoinColumn(name = "GREETING_ITEM_ID") + }) + private Set excludedProperties; + + public GreetingItem() { + includedPropertyPaths = new HashSet<>(); + excludedProperties = new HashSet<>(); + } + + public Set getIncludedPropertyPaths() { + return Collections.unmodifiableSet(includedPropertyPaths); + } + + protected void setIncludedPropertyPaths( + final Set includePropertyPaths) { + this.includedPropertyPaths = new HashSet<>(includePropertyPaths); + } + + public void addIncludedPropertyPath(final String path) { + includedPropertyPaths.add(path); + } + + public void removeIncludedPropertyPath(final String path) { + includedPropertyPaths.remove(path); + } + + public Set getExcludedPropertyPaths() { + return Collections.unmodifiableSet(excludedProperties); + } + + protected void setExcludedPropertyPaths( + final Set excludedProperties) { + this.excludedProperties = new HashSet<>(excludedProperties); + } + + public void addExcludedProperty(final String path) { + excludedProperties.add(path); + } + + public void removeExcludedProperty(final String path) { + excludedProperties.remove(path); + } + + @Override + public int hashCode() { + int hash = super.hashCode(); + hash = 13 * hash + Objects.hashCode(includedPropertyPaths); + hash = 13 * hash + Objects.hashCode(excludedProperties); + return hash; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!super.equals(obj)) { + return false; + } + if (!(obj instanceof GreetingItem)) { + return false; + } + final GreetingItem other = (GreetingItem) obj; + if (!other.canEqual(this)) { + return false; + } + + if (!Objects.equals(includedPropertyPaths, + other.getIncludedPropertyPaths())) { + return false; + } + return Objects.equals(excludedProperties, + other.getExcludedPropertyPaths()); + } + + @Override + public boolean canEqual(final Object obj) { + return obj instanceof GreetingItem; + } + + @Override + public String toString(final String data) { + return super.toString(String + .format(", includedPropertyPaths = %s, " + + "excludedProperties = %s%s", + Objects.toString(includedPropertyPaths), + Objects.toString(excludedProperties), + data)); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/pagemodel/GreetingItemBuilder.java b/ccm-cms/src/main/java/org/librecms/pagemodel/GreetingItemBuilder.java new file mode 100644 index 000000000..b90b41e42 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/pagemodel/GreetingItemBuilder.java @@ -0,0 +1,293 @@ +/* + * 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 org.libreccm.categorization.Category; +import org.libreccm.categorization.CategoryManager; +import org.libreccm.categorization.CategoryRepository; +import org.libreccm.core.CcmObject; +import org.libreccm.core.UnexpectedErrorException; +import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.pagemodel.ComponentBuilder; +import org.libreccm.pagemodel.ComponentModelType; +import org.libreccm.security.PermissionChecker; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentItemL10NManager; +import org.librecms.contentsection.ContentItemManager; +import org.librecms.contentsection.ContentItemRepository; +import org.librecms.contentsection.privileges.ItemPrivileges; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.transaction.Transactional; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +import static org.librecms.pages.PagesConstants.*; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@ComponentModelType(componentModel = GreetingItem.class) +public class GreetingItemBuilder implements ComponentBuilder { + + @Inject + private GlobalizationHelper globalizationHelper; + + @Inject + private CategoryRepository categoryRepo; + + @Inject + private ContentItemL10NManager iteml10nManager; + + @Inject + private CategoryManager categoryManager; + + @Inject + private ContentItemManager itemManager; + + @Inject + private ContentItemRepository itemRepo; + + @Inject + private PermissionChecker permissionChecker; + + @Transactional(Transactional.TxType.REQUIRED) + @Override + public Map buildComponent( + final GreetingItem componentModel, + final Map 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 = categoryRepo + .findById(((CcmObject) parameters.get(PARAMETER_CATEGORY)) + .getObjectId()) + .orElseThrow(() -> new IllegalArgumentException(String.format( + "No category with ID %d in the database.", + ((CcmObject) parameters.get(PARAMETER_CATEGORY)).getObjectId()))); + + final Optional indexObj = categoryManager + .getIndexObject(category); + + if (indexObj.isPresent()) { + + if (indexObj.get() instanceof ContentItem) { + + final ContentItem indexItem; + if (itemManager.isLive((ContentItem) indexObj.get())) { + indexItem = itemManager + .getLiveVersion((ContentItem) indexObj.get(), + ContentItem.class) + .get(); + } else { + throw new NotFoundException(String + .format( + "The index item %s of category %s does not have " + + "a live version.", + Objects.toString(indexObj), + Objects.toString(category))); + } + + if (permissionChecker.isPermitted(ItemPrivileges.VIEW_PUBLISHED, + indexItem)) { + return generateGreetingItem(componentModel, + parameters, + indexItem); + } else { + throw new WebApplicationException( + "You are not permitted to view the view version of this item.", + Response.Status.UNAUTHORIZED); + } + } else { + throw new NotFoundException(String + .format("The index object %s of category %s is not a " + + "ContentItem.", + Objects.toString(indexObj), + Objects.toString(category))); + } + } else { + throw new NotFoundException(String + .format("The category %s does not have a index item.", + Objects.toString(category))); + } + } + + private Map generateGreetingItem( + final GreetingItem componentModel, + final Map parameters, + final ContentItem item) { + + final String language = (String) parameters.get(PARAMETER_LANGUAGE); + + if (iteml10nManager.hasLanguage(item, new Locale(language))) { + + final BeanInfo beanInfo; + try { + beanInfo = Introspector.getBeanInfo(item.getClass()); + } catch (IntrospectionException ex) { + throw new UnexpectedErrorException(ex); + } + + final PropertyDescriptor[] properties = beanInfo + .getPropertyDescriptors(); + + final Map result = new HashMap<>(); + + for (final PropertyDescriptor propertyDescriptor : properties) { + renderProperty(propertyDescriptor, componentModel, item, result); + } + + return result; + } else { + throw new NotFoundException("Requested language is not available."); + } + } + + private void renderProperty(final PropertyDescriptor propertyDescriptor, + final GreetingItem componentModel, + final ContentItem item, + final Map result) { + + final String propertyName = propertyDescriptor.getName(); + if (componentModel.getExcludedPropertyPaths().contains(propertyName)) { + return; + } + + final Method readMethod = propertyDescriptor.getReadMethod(); + if (Collection.class.isAssignableFrom(propertyDescriptor + .getPropertyType())) { + + final Map associated; + try { + associated = generateAssociatedObject(readMethod.invoke(item)); + } catch (IllegalAccessException | InvocationTargetException ex) { + throw new UnsupportedOperationException(ex); + } + result.put(propertyName, associated); + } else if (isValueType(propertyDescriptor.getPropertyType())) { + try { + result.put(propertyName, readMethod.invoke(item)); + } catch (IllegalAccessException | InvocationTargetException ex) { + throw new UnexpectedErrorException(ex); + } + } else { + //ToDo + } + + } + + private Map generateAssociatedObject(final Object obj) { + + final BeanInfo beanInfo; + try { + beanInfo = Introspector.getBeanInfo(obj.getClass()); + } catch (IntrospectionException ex) { + throw new UnexpectedErrorException(ex); + } + + final PropertyDescriptor[] properties = beanInfo + .getPropertyDescriptors(); + + final Map result = new HashMap<>(); + for (final PropertyDescriptor propertyDescriptor : properties) { + final Class type = propertyDescriptor.getPropertyType(); + if (isValueType(type)) { + final Method readMethod = propertyDescriptor.getReadMethod(); + try { + result.put(propertyDescriptor.getName(), + readMethod.invoke(obj)); + } catch (IllegalAccessException + | InvocationTargetException ex) { + throw new UnexpectedErrorException(ex); + } + } + } + + return result; + } + + private boolean isValueType(final Class typeToTest) { + final Class[] types = new Class[]{ + Boolean.class, + Boolean.TYPE, + Character.class, + Character.TYPE, + Byte.class, + Byte.TYPE, + Double.class, + Double.TYPE, + Float.class, + Float.TYPE, + Integer.class, + Integer.TYPE, + Long.class, + Long.TYPE, + Short.class, + Short.TYPE, + String.class + }; + + for (final Class type : types) { + if (type.isAssignableFrom(typeToTest)) { + return true; + } + } + + return typeToTest.isArray() + && (typeToTest.getComponentType() + .isAssignableFrom(Byte.class) + || typeToTest.getComponentType() + .isAssignableFrom(Byte.TYPE)); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/pages/Page.java b/ccm-cms/src/main/java/org/librecms/pages/Page.java index d0b2d714d..a36f95e37 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/Page.java +++ b/ccm-cms/src/main/java/org/librecms/pages/Page.java @@ -18,7 +18,7 @@ */ package org.librecms.pages; -import org.libreccm.categorization.Category; +import org.libreccm.core.CcmObject; import org.libreccm.pagemodel.PageModel; import java.io.Serializable; @@ -26,22 +26,23 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Objects; -import javax.persistence.Column; +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; import javax.persistence.Embedded; import javax.persistence.Entity; -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.MapKeyColumn; +import javax.persistence.MapKeyJoinColumn; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; -import javax.persistence.OneToOne; import javax.persistence.Table; import static org.librecms.CmsConstants.*; +import static org.librecms.pages.PagesConstants.*; /** * @@ -52,22 +53,17 @@ import static org.librecms.CmsConstants.*; @NamedQueries( @NamedQuery( name = "Page.findForCategory", - query = "SELECT p FROM Page p WHERE p.category = :category" + query = "SELECT p " + + "FROM Page p " + + "JOIN p.categories c " + + "WHERE c.category = :category " + + "AND C.type = '" + CATEGORIZATION_TYPE_PAGE_CONF + "'" ) ) -public class Page implements Serializable { +public class Page extends CcmObject implements Serializable { private static final long serialVersionUID = 5108486858438122008L; - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - @Column(name = "PAGE_ID") - private long pageId; - - @OneToOne - @JoinColumn(name = "CATEGORY_ID") - private Category category; - @ManyToOne @JoinColumn(name = "INDEX_PAGE_MODEL_ID") private PageModel indexPageModel; @@ -76,30 +72,20 @@ public class Page implements Serializable { @JoinColumn(name = "ITEM_PAGE_MODEL_ID") private PageModel itemPageModel; - @Embedded - @JoinTable(name = "PAGE_THEME_CONFIGURATIONS", - schema = DB_SCHEMA, - joinColumns = { - @JoinColumn(name = "PAGE_ID") - }) + @ElementCollection +// @JoinTable(name = "PAGE_THEME_CONFIGURATIONS", +// schema = DB_SCHEMA, +// joinColumns = { +// @JoinColumn(name = "PAGE_ID") +// }) + @CollectionTable(name = "PAGE_THEME_CONFIGURATIONS", + schema = DB_SCHEMA, + joinColumns = { + @JoinColumn(name = "PAGE_ID") + }) + @MapKeyColumn(name = "THEME") private Map themeConfiguration; - public long getPageId() { - return pageId; - } - - protected void setPageId(final long pageId) { - this.pageId = pageId; - } - - public Category getCategory() { - return category; - } - - public void setCategory(final Category category) { - this.category = category; - } - public PageModel getIndexPageModel() { return indexPageModel; } @@ -126,4 +112,53 @@ public class Page implements Serializable { this.themeConfiguration = new HashMap<>(themeConfiguration); } + @Override + public int hashCode() { + int hash = 7; + hash = 47 * hash + Objects.hashCode(indexPageModel); + hash = 47 * hash + Objects.hashCode(itemPageModel); + hash = 47 * hash + Objects.hashCode(themeConfiguration); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Page)) { + return false; + } + final Page other = (Page) obj; + if (!other.canEqual(this)) { + return false; + } + if (!Objects.equals(indexPageModel, other.getIndexPageModel())) { + return false; + } + if (!Objects.equals(itemPageModel, other.getItemPageModel())) { + return false; + } + return Objects.equals(themeConfiguration, other.getThemeConfiguration()); + } + + @Override + public boolean canEqual(final Object obj) { + return obj instanceof Page; + } + + @Override + public String toString(final String data) { + return super.toString(String.format(", indexPageModel = %s, " + + "itemPageModel = %s, " + + "themeConfiguration = %s%s", + Objects.toString(indexPageModel), + Objects.toString(itemPageModel), + Objects.toString(themeConfiguration), + data)); + } + } diff --git a/ccm-cms/src/main/java/org/librecms/pages/PageManager.java b/ccm-cms/src/main/java/org/librecms/pages/PageManager.java index 4c6ac65d9..601dfcbb4 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/PageManager.java +++ b/ccm-cms/src/main/java/org/librecms/pages/PageManager.java @@ -19,6 +19,7 @@ package org.librecms.pages; import org.libreccm.categorization.Category; +import org.libreccm.categorization.CategoryManager; import org.libreccm.categorization.CategoryRepository; import java.util.Optional; @@ -34,9 +35,12 @@ import javax.transaction.Transactional; @RequestScoped public class PageManager { + @Inject + private CategoryManager categoryManager; + @Inject private CategoryRepository categoryRepo; - + @Inject private PageRepository pageRepo; @@ -66,9 +70,8 @@ public class PageManager { public Page createPageForCategory(final Category category) { final Page page = new Page(); - page.setCategory(category); - pageRepo.save(page); + categoryManager.addObjectToCategory(page, category); return page; } diff --git a/ccm-cms/src/main/java/org/librecms/pages/PageRepository.java b/ccm-cms/src/main/java/org/librecms/pages/PageRepository.java index 5d02d5db7..5a205bc67 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/PageRepository.java +++ b/ccm-cms/src/main/java/org/librecms/pages/PageRepository.java @@ -69,7 +69,7 @@ public class PageRepository extends AbstractEntityRepository{ @Override public boolean isNew(final Page page) { - return page.getPageId() == 0; + return page.getObjectId() == 0; } diff --git a/ccm-cms/src/main/java/org/librecms/pages/Pages.java b/ccm-cms/src/main/java/org/librecms/pages/Pages.java index ed7daf702..9be461c18 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/Pages.java +++ b/ccm-cms/src/main/java/org/librecms/pages/Pages.java @@ -39,7 +39,7 @@ import static org.librecms.CmsConstants.*; * @author Jens Pelzetter */ @Entity -@Table(name = "PAGES", schema = DB_SCHEMA) +@Table(name = "PAGES_APP", schema = DB_SCHEMA) @NamedQueries({ @NamedQuery( name = "Pages.findForSite", diff --git a/ccm-cms/src/main/java/org/librecms/pages/PagesConstants.java b/ccm-cms/src/main/java/org/librecms/pages/PagesConstants.java new file mode 100644 index 000000000..cb519da38 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/pages/PagesConstants.java @@ -0,0 +1,38 @@ +/* + * 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.pages; + +/** + * + * @author Jens Pelzetter + */ +public final class PagesConstants { + + private PagesConstants() { + //Nothing + } + + public static final String CATEGORIZATION_TYPE_PAGE_CONF = "PAGE_CONFIGURATION"; + + public static final String PARAMETER_CATEGORY = "category"; + public static final String PARAMETER_ITEMNAME = "itemName"; + public static final String PARAMETER_LANGUAGE = "language"; + + +} diff --git a/ccm-cms/src/main/java/org/librecms/pages/PagesRepository.java b/ccm-cms/src/main/java/org/librecms/pages/PagesRepository.java index b9b212127..7b530627b 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/PagesRepository.java +++ b/ccm-cms/src/main/java/org/librecms/pages/PagesRepository.java @@ -18,14 +18,11 @@ */ package org.librecms.pages; -import org.libreccm.categorization.Category; import org.libreccm.core.AbstractEntityRepository; import org.libreccm.core.CoreConstants; -import org.libreccm.pagemodel.PageModelVersion; import org.libreccm.security.RequiresPrivilege; import org.libreccm.sites.SiteRepository; -import org.libreccm.pagemodel.PageModel; import java.util.Optional; diff --git a/ccm-cms/src/main/java/org/librecms/pages/PagesRouter.java b/ccm-cms/src/main/java/org/librecms/pages/PagesRouter.java index 8ed6d2c43..fe62a7f88 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/PagesRouter.java +++ b/ccm-cms/src/main/java/org/librecms/pages/PagesRouter.java @@ -18,9 +18,12 @@ */ package org.librecms.pages; +import com.arsdigita.kernel.KernelConfig; + import org.libreccm.categorization.Category; -import org.libreccm.categorization.CategoryManager; import org.libreccm.categorization.CategoryRepository; +import org.libreccm.configuration.ConfigurationManager; +import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.pagemodel.PageModel; import org.libreccm.pagemodel.PageModelManager; import org.libreccm.sites.Site; @@ -29,12 +32,15 @@ import org.libreccm.theming.ThemeInfo; import org.libreccm.theming.ThemeVersion; import org.libreccm.theming.Themes; +import java.net.URI; import java.util.HashMap; +import java.util.Locale; import java.util.Map; +import java.util.Objects; +import javax.annotation.PostConstruct; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; -import javax.persistence.EntityManager; import javax.transaction.Transactional; import javax.ws.rs.DefaultValue; import javax.ws.rs.NotFoundException; @@ -47,6 +53,8 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; +import static org.librecms.pages.PagesConstants.*; + /** * * @author Jens Pelzetter @@ -56,35 +64,98 @@ import javax.ws.rs.core.UriInfo; public class PagesRouter { @Inject - private CategoryManager categoryManager; + private CategoryRepository categoryRepo; @Inject - private CategoryRepository categoryRepo; + private ConfigurationManager confManager; + + @Inject + private GlobalizationHelper globalizationHelper; @Inject private CmsPageBuilder pageBuilder; - @Inject - private EntityManager entityManager; - @Inject private PagesRepository pagesRepo; - @Inject - private PageModelManager pageModelManager; - - @Inject - private PageRepository pageRepo; - @Inject private PageManager pageManager; + @Inject + private PageModelManager pageModelManager; + @Inject private SiteRepository siteRepo; @Inject private Themes themes; + private Locale defaultLocale; + + @PostConstruct + private void init() { + final KernelConfig kernelConfig = confManager + .findConfiguration(KernelConfig.class); + defaultLocale = kernelConfig.getDefaultLocale(); + } + + @Path("/") + public Response getCategoryIndexPage( + @Context + final UriInfo uriInfo, + @PathParam("page") + final String page) { + + final String domain = uriInfo.getBaseUri().getHost(); + final Pages pages = getPages(domain); + final Category category = getCategory(domain, pages, page); + + final Locale negoiatedLocale = globalizationHelper + .getNegotiatedLocale(); + + final String language; + if (category.getTitle().hasValue(negoiatedLocale)) { + language = negoiatedLocale.toString(); + } else if (category.getTitle().hasValue(defaultLocale)) { + language = defaultLocale.toString(); + } else { + throw new NotFoundException(); + } + + final String indexPage = String.format("/index.%s.html", language); + final URI uri = uriInfo.getBaseUriBuilder().path(indexPage).build(); + return Response.temporaryRedirect(uri).build(); + } + + @Path("/index.html") + public Response getCategoryIndexPageAsHtml( + @Context + final UriInfo uriInfo, + @PathParam("page") + final String page) { + + final String domain = uriInfo.getBaseUri().getHost(); + final Pages pages = getPages(domain); + final Category category = getCategory(domain, pages, page); + + final Locale negoiatedLocale = globalizationHelper + .getNegotiatedLocale(); + final String language; + if (category.getTitle().hasValue(negoiatedLocale)) { + language = negoiatedLocale.toString(); + } else if (category.getTitle().hasValue(defaultLocale)) { + language = defaultLocale.toString(); + } else { + throw new NotFoundException(); + } + + final String indexPage = String.format("/index.%s.html", language); + final String path = uriInfo.getPath().replace("index.html", indexPage); + + final URI uri = uriInfo.getBaseUriBuilder().replacePath(path).build(); + return Response.temporaryRedirect(uri).build(); + } + @Path("/index.{lang}.html") @Produces("text/html") @Transactional(Transactional.TxType.REQUIRED) @@ -105,6 +176,180 @@ public class PagesRouter { @DefaultValue("LIVE") final String pageModelVersion) { + final Map buildResult = getCategoryIndexPage( + uriInfo, page, language, pageModelVersion); + final Site site = getSite(uriInfo); + final ThemeInfo themeInfo = getTheme(site, theme, themeVersion); + + return themes.process(buildResult, themeInfo); + } + + @Path("/index.{lang}.json") + @Produces("text/html") + @Transactional(Transactional.TxType.REQUIRED) + public Map getCategoryIndexPageAsJson( + @Context + final UriInfo uriInfo, + @PathParam("page") + final String page, + @PathParam("lang") + final String language, + @QueryParam("pagemodel-version") + @DefaultValue("LIVE") + final String pageModelVersion) { + + return getCategoryIndexPage(uriInfo, page, language, pageModelVersion); + } + + @Path("/index.{lang}.xml") + @Produces("text/html") + @Transactional(Transactional.TxType.REQUIRED) + public Map getCategoryIndexPageAsXml( + @Context + final UriInfo uriInfo, + @PathParam("page") + final String page, + @PathParam("lang") + final String language, + @QueryParam("pagemodel-version") + @DefaultValue("LIVE") + final String pageModelVersion) { + + return getCategoryIndexPage(uriInfo, page, language, pageModelVersion); + } + + @Path("/{name}") + public Response getItemPage( + @Context final UriInfo uriInfo, + @PathParam("page") final String page, + @PathParam("name") final String itemName) { + + final String domain = uriInfo.getBaseUri().getHost(); + final Pages pages = getPages(domain); + final Category category = getCategory(domain, pages, page); + + final Locale negoiatedLocale = globalizationHelper + .getNegotiatedLocale(); + + final String language; + if (category.getTitle().hasValue(negoiatedLocale)) { + language = negoiatedLocale.toString(); + } else if (category.getTitle().hasValue(defaultLocale)) { + language = defaultLocale.toString(); + } else { + throw new NotFoundException(); + } + + final String itemPage = String.format("/%s.%s.html", itemName, language); + final URI uri = uriInfo.getBaseUriBuilder().path(itemPage).build(); + return Response.temporaryRedirect(uri).build(); + } + + @Path("/{name},html") + public Response getItemPageAsHtml( + @Context final UriInfo uriInfo, + @PathParam("page") final String page, + @PathParam("name") final String itemName) { + + final String domain = uriInfo.getBaseUri().getHost(); + final Pages pages = getPages(domain); + final Category category = getCategory(domain, pages, page); + + final Locale negoiatedLocale = globalizationHelper + .getNegotiatedLocale(); + + final String language; + if (category.getTitle().hasValue(negoiatedLocale)) { + language = negoiatedLocale.toString(); + } else if (category.getTitle().hasValue(defaultLocale)) { + language = defaultLocale.toString(); + } else { + throw new NotFoundException(); + } + + final String itemPage = String.format("/%s.%s.html", itemName, language); + final String path = uriInfo + .getPath() + .replace(String.format("%s.html", itemName), itemPage); + + final URI uri = uriInfo.getBaseUriBuilder().replacePath(path).build(); + return Response.temporaryRedirect(uri).build(); + } + + @Path("/{name}.{lang}.html") + public String getItemPageAsHtml( + @Context + final UriInfo uriInfo, + @PathParam("page") + final String page, + @PathParam("name") + final String itemName, + @PathParam("lang") + final String language, + @QueryParam("theme") + @DefaultValue("--DEFAULT--") + final String theme, + @QueryParam("theme-version") + @DefaultValue("LIVE") + final String themeVersion, + @QueryParam("pagemodel-version") + @DefaultValue("LIVE") + final String pageModelVersion) { + + final Map buildResult = getCategoryItemPage( + uriInfo, page, itemName, language, pageModelVersion); + final Site site = getSite(uriInfo); + final ThemeInfo themeInfo = getTheme(site, page, themeVersion); + + return themes.process(buildResult, themeInfo); + } + + @Path("/{name}.{lang}.html") + public Map getItemPageAsJson( + @Context + final UriInfo uriInfo, + @PathParam("page") + final String page, + @PathParam("name") + final String itemName, + @PathParam("lang") + final String language, + @QueryParam("pagemodel-version") + @DefaultValue("LIVE") + final String pageModelVersion) { + + return getCategoryItemPage(uriInfo, + page, + itemName, + language, + pageModelVersion); + } + + @Path("/{name}.{lang}.html") + public Map getItemPageAsXml( + @Context + final UriInfo uriInfo, + @PathParam("page") + final String page, + @PathParam("name") + final String itemName, + @PathParam("lang") + final String language, + @QueryParam("pagemodel-version") + @DefaultValue("LIVE") + final String pageModelVersion) { + + return getCategoryItemPage(uriInfo, + page, + itemName, + language, + pageModelVersion); + } + + private Site getSite(final UriInfo uriInfo) { + + Objects.requireNonNull(uriInfo); + final String domain = uriInfo.getBaseUri().getHost(); final Site site; @@ -117,36 +362,37 @@ public class PagesRouter { "No matching Site and no default Site.")); } - final Pages pages = pagesRepo + return site; + } + + private Pages getPages(final String domain) { + + return pagesRepo .findPagesForSite(domain) .orElseThrow(() -> new NotFoundException(String .format("No Pages for domain \"%s\" available.", domain))); + } - final Category category = categoryRepo - .findByPath(pages.getCategoryDomain(), page) + private Category getCategory(final String domain, + final Pages pages, + final String pagePath) { + + return categoryRepo + .findByPath(pages.getCategoryDomain(), pagePath) .orElseThrow(() -> new NotFoundException(String.format( - "No page for path \"%s\" in site \"%s\"", - page, + "No Page for path \"%s\" in site \"%s\"", + pagePath, domain))); - final Page pageConf = pageManager.findPageForCategory(category); + } - final PageModel pageModel = pageConf.getIndexPageModel(); + private ThemeInfo getTheme(final Site site, + final String theme, + final String themeVersion) { - final Map parameters = new HashMap<>(); - parameters.put("currentCategory", category); - - final Map buildResult; - if (pageModel == null) { - buildResult = pageBuilder.buildPage(parameters); - } else { - buildResult = pageBuilder.buildPage(pageModel, parameters); - } - - final ThemeInfo themeInfo; if ("--DEFAULT--".equals(theme)) { - themeInfo = themes + return themes .getTheme(site.getDefaultTheme(), ThemeVersion.valueOf(themeVersion)) .orElseThrow(() -> new WebApplicationException( @@ -156,71 +402,110 @@ public class PagesRouter { site.getDefaultTheme()), Response.Status.INTERNAL_SERVER_ERROR)); } else { - themeInfo = themes.getTheme(theme, - ThemeVersion.valueOf(themeVersion)) + return themes.getTheme(theme, + ThemeVersion.valueOf(themeVersion)) .orElseThrow(() -> new WebApplicationException( String.format("The theme \"%s\" is not available.", theme), Response.Status.BAD_REQUEST)); } - - return themes.process(buildResult, themeInfo); } - @Path("/index.{lang}.json") - @Produces("text/html") - @Transactional(Transactional.TxType.REQUIRED) - public String getCategoryIndexPageAsJson( - @Context + private Page getPage(final UriInfo uriInfo, + final String pagePath, + final String language, + final Map parameters) { + + Objects.requireNonNull(uriInfo); + Objects.requireNonNull(pagePath); + Objects.requireNonNull(parameters); + + final String domain = uriInfo.getBaseUri().getHost(); + final Pages pages = getPages(domain); + final Category category = getCategory(domain, pages, pagePath); + + final Locale locale = new Locale(language); + if (!category.getTitle().hasValue(locale)) { + throw new NotFoundException(); + } + + globalizationHelper.setSelectedLocale(locale); + + parameters.put(PARAMETER_CATEGORY, category); + return pageManager.findPageForCategory(category); + } + + private Map buildPage( + final PageModel pageModel, + final Map parameters) { + + Objects.requireNonNull(pageModel); + Objects.requireNonNull(parameters); + + final Map result; + if (pageModel == null) { + result = pageBuilder.buildPage(parameters); + } else { + result = pageBuilder.buildPage(pageModel, parameters); + } + + return result; + } + + private Map getCategoryIndexPage( final UriInfo uriInfo, - @PathParam("page") - final String page, - @PathParam("lang") + final String pagePath, final String language, - @QueryParam("theme") - @DefaultValue("--DEFAULT--") - final String theme, - @QueryParam("theme-version") - @DefaultValue("LIVE") - final String themeVersion, - @QueryParam("pagemodel-version") - @DefaultValue("LIVE") final String pageModelVersion) { - throw new UnsupportedOperationException(); + final Map parameters = new HashMap<>(); + final Page page = getPage(uriInfo, pagePath, language, parameters); + + final PageModel pageModel; + if ("DRAFT".equals(pageModelVersion)) { + pageModel = pageModelManager.getDraftVersion(page + .getIndexPageModel()); + } else { + pageModel = pageModelManager + .getLiveVersion(page.getIndexPageModel()) + .orElseThrow(() -> new NotFoundException(String + .format("The PageModel for the index page of the category" + + "\"%s\" is not available as live version.", + pagePath))); + } + + parameters.put(PARAMETER_LANGUAGE, language); + + return buildPage(pageModel, parameters); } - - @Path("/index.{lang}.xml") - @Produces("text/html") - @Transactional(Transactional.TxType.REQUIRED) - public String getCategoryIndexPageAsXml( - @Context + + private Map getCategoryItemPage( final UriInfo uriInfo, - @PathParam("page") - final String page, - @PathParam("lang") + final String pagePath, + final String itemName, final String language, - @QueryParam("theme") - @DefaultValue("--DEFAULT--") - final String theme, - @QueryParam("theme-version") - @DefaultValue("LIVE") - final String themeVersion, - @QueryParam("pagemodel-version") - @DefaultValue("LIVE") final String pageModelVersion) { - throw new UnsupportedOperationException(); - } + final Map parameters = new HashMap<>(); + final Page page = getPage(uriInfo, pagePath, language, parameters); - @Path("/{name}.{lang}.html") - public String getPage( - @Context final UriInfo uriInfo, - @PathParam("page") final String page, - @PathParam("lang") final String language, - @QueryParam("theme") @DefaultValue("--DEFAULT--") final String theme) { + final PageModel pageModel; + if ("DRAFT".equals(pageModelVersion)) { + pageModel = pageModelManager.getDraftVersion(page + .getItemPageModel()); + } else { + pageModel = pageModelManager + .getLiveVersion(page.getItemPageModel()) + .orElseThrow(() -> new NotFoundException(String + .format("The PageModel for the index page of the category" + + "\"%s\" is not available as live version.", + pagePath))); + } - throw new UnsupportedOperationException(); + parameters.put(PARAMETER_ITEMNAME, itemName); + parameters.put(PARAMETER_LANGUAGE, language); + + return buildPage(pageModel, parameters); } } diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_16__create_pages.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_16__create_pages.sql new file mode 100644 index 000000000..03ad269e7 --- /dev/null +++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_16__create_pages.sql @@ -0,0 +1,56 @@ + create table CCM_CMS.PAGE_THEME_CONFIGURATIONS ( + PAGE_ID bigint not null, + INDEX_PAGE_TEMPLATE varchar(255), + ITEM_PAGE_TEMPLATE varchar(255), + THEME varchar(255) not null, + primary key (PAGE_ID, THEME) +); + +create table CCM_CMS.PAGES ( + OBJECT_ID bigint not null, + INDEX_PAGE_MODEL_ID bigint, + ITEM_PAGE_MODEL_ID bigint, + primary key (OBJECT_ID) +); + +create table CCM_CMS.PAGES_APP ( + OBJECT_ID bigint not null, + CATEGORY_DOMAIN_ID bigint, + SITE_ID bigint, + primary key (OBJECT_ID) +); + +alter table CCM_CMS.PAGE_THEME_CONFIGURATIONS + add constraint FK6l6xp6ex6sh2uuxfmeekf6ckn + foreign key (PAGE_ID) + references CCM_CMS.PAGES; + +alter table CCM_CMS.PAGES + add constraint FKqweb08d151ot4ij9io72w3yhx + foreign key (INDEX_PAGE_MODEL_ID) + references CCM_CORE.PAGE_MODELS; + +alter table CCM_CMS.PAGES + add constraint FKg2p2ahbayc2coei72pk1lnenf + foreign key (ITEM_PAGE_MODEL_ID) + references CCM_CORE.PAGE_MODELS; + +alter table CCM_CMS.PAGES + add constraint FKmgmth087tmxwieujn2vs5opbo + foreign key (OBJECT_ID) + references CCM_CORE.CCM_OBJECTS; + +alter table CCM_CMS.PAGES_APP + add constraint FK5swx0e8pj0mm5t1es0lj4nwlx + foreign key (CATEGORY_DOMAIN_ID) + references CCM_CORE.CATEGORY_DOMAINS; + +alter table CCM_CMS.PAGES_APP + add constraint FK3wkyn4oxa65f7svtj917m61jc + foreign key (SITE_ID) + references CCM_CORE.SITES; + +alter table CCM_CMS.PAGES_APP + add constraint FKrrk4g7my3e4qkdoeiygkqxduy + foreign key (OBJECT_ID) + references CCM_CORE.APPLICATIONS; diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_16__create_sites.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_16__create_sites.sql deleted file mode 100644 index ff1974007..000000000 --- a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_16__create_sites.sql +++ /dev/null @@ -1,20 +0,0 @@ -create table CCM_CMS.SITES ( - DEFAULT_SITE boolean, - NAME varchar(255), - OBJECT_ID bigint not null, - CATEGORY_DOMAIN_ID bigint, - primary key (OBJECT_ID) -); - -alter table CCM_CMS.SITES - add constraint UK_fgjx0nuuxlgnuit724a96vw81 unique (NAME); - -alter table CCM_CMS.SITES - add constraint FKmiysfmv1nkcso6bm18sjhvtm8 - foreign key (CATEGORY_DOMAIN_ID) - references CCM_CORE.CATEGORY_DOMAINS; - -alter table CCM_CMS.SITES - add constraint FK5kmn26x72uue9t3dfnjwes45 - foreign key (OBJECT_ID) - references CCM_CORE.APPLICATIONS; diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_16__create_pages.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_16__create_pages.sql new file mode 100644 index 000000000..545a5027c --- /dev/null +++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_16__create_pages.sql @@ -0,0 +1,57 @@ +create table CCM_CMS.PAGE_THEME_CONFIGURATIONS ( + PAGE_ID int8 not null, + INDEX_PAGE_TEMPLATE varchar(255), + ITEM_PAGE_TEMPLATE varchar(255), + THEME varchar(255) not null, + primary key (PAGE_ID, THEME) +); + +create table CCM_CMS.PAGES ( + OBJECT_ID int8 not null, + INDEX_PAGE_MODEL_ID int8, + ITEM_PAGE_MODEL_ID int8, + primary key (OBJECT_ID) +); + +create table CCM_CMS.PAGES_APP ( + OBJECT_ID int8 not null, + CATEGORY_DOMAIN_ID int8, + SITE_ID int8, + primary key (OBJECT_ID) +); + +alter table CCM_CMS.PAGE_THEME_CONFIGURATIONS + add constraint FK6l6xp6ex6sh2uuxfmeekf6ckn + foreign key (PAGE_ID) + references CCM_CMS.PAGES; + +alter table CCM_CMS.PAGES + add constraint FKqweb08d151ot4ij9io72w3yhx + foreign key (INDEX_PAGE_MODEL_ID) + references CCM_CORE.PAGE_MODELS; + +alter table CCM_CMS.PAGES + add constraint FKg2p2ahbayc2coei72pk1lnenf + foreign key (ITEM_PAGE_MODEL_ID) + references CCM_CORE.PAGE_MODELS; + +alter table CCM_CMS.PAGES + add constraint FKmgmth087tmxwieujn2vs5opbo + foreign key (OBJECT_ID) + references CCM_CORE.CCM_OBJECTS; +); + +alter table CCM_CMS.PAGES_APP + add constraint FK5swx0e8pj0mm5t1es0lj4nwlx + foreign key (CATEGORY_DOMAIN_ID) + references CCM_CORE.CATEGORY_DOMAINS; + +alter table CCM_CMS.PAGES_APP + add constraint FK3wkyn4oxa65f7svtj917m61jc + foreign key (SITE_ID) + references CCM_CORE.SITES; + +alter table CCM_CMS.PAGES_APP + add constraint FKrrk4g7my3e4qkdoeiygkqxduy + foreign key (OBJECT_ID) + references CCM_CORE.APPLICATIONS; \ No newline at end of file diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_16__create_sites.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_16__create_sites.sql deleted file mode 100644 index 7526e4211..000000000 --- a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_16__create_sites.sql +++ /dev/null @@ -1,20 +0,0 @@ -create table CCM_CMS.SITES ( - DEFAULT_SITE boolean, - NAME varchar(255), - OBJECT_ID int8 not null, - CATEGORY_DOMAIN_ID int8, - primary key (OBJECT_ID) -); - -alter table CCM_CMS.SITES - add constraint UK_fgjx0nuuxlgnuit724a96vw81 unique (NAME); - -alter table CCM_CMS.SITES - add constraint FKmiysfmv1nkcso6bm18sjhvtm8 - foreign key (CATEGORY_DOMAIN_ID) - references CCM_CORE.CATEGORY_DOMAINS; - -alter table CCM_CMS.SITES - add constraint FK5kmn26x72uue9t3dfnjwes45 - foreign key (OBJECT_ID) - references CCM_CORE.APPLICATIONS; diff --git a/ccm-cms/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_cms_schema.sql b/ccm-cms/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_cms_schema.sql index 88ef238e7..d7d361e8b 100644 --- a/ccm-cms/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_cms_schema.sql +++ b/ccm-cms/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_cms_schema.sql @@ -3,7 +3,9 @@ drop schema if exists CCM_CORE; drop sequence if exists HIBERNATE_SEQUENCE; + create schema CCM_CMS; + create schema CCM_CORE; create table CCM_CMS.ARTICLE_TEXTS ( @@ -771,6 +773,28 @@ drop sequence if exists HIBERNATE_SEQUENCE; primary key (REV, OBJECT_ID, LOCALIZED_VALUE, LOCALE) ); + create table CCM_CMS.PAGE_THEME_CONFIGURATIONS ( + PAGE_ID bigint not null, + INDEX_PAGE_TEMPLATE varchar(255), + ITEM_PAGE_TEMPLATE varchar(255), + THEME varchar(255) not null, + primary key (PAGE_ID, THEME) + ); + + create table CCM_CMS.PAGES ( + OBJECT_ID bigint not null, + INDEX_PAGE_MODEL_ID bigint, + ITEM_PAGE_MODEL_ID bigint, + primary key (OBJECT_ID) + ); + + create table CCM_CMS.PAGES_APP ( + OBJECT_ID bigint not null, + CATEGORY_DOMAIN_ID bigint, + SITE_ID bigint, + primary key (OBJECT_ID) + ); + create table CCM_CMS.RELATED_LINKS ( OBJECT_ID bigint not null, BOOKMARK_ID bigint, @@ -814,14 +838,6 @@ drop sequence if exists HIBERNATE_SEQUENCE; primary key (OBJECT_ID, REV) ); - create table CCM_CMS.SITES ( - DEFAULT_SITE boolean, - NAME varchar(255), - OBJECT_ID bigint not null, - CATEGORY_DOMAIN_ID bigint, - primary key (OBJECT_ID) - ); - create table CCM_CMS.VIDEO_ASSETS ( HEIGHT bigint, WIDTH bigint, @@ -851,9 +867,6 @@ drop sequence if exists HIBERNATE_SEQUENCE; alter table CCM_CMS.CONTENT_SECTION_WORKFLOW_TEMPLATES add constraint UK_goj42ghwu4tf1akfb2r6ensns unique (WORKFLOW_TEMPLATE_ID); - alter table CCM_CMS.SITES - add constraint UK_fgjx0nuuxlgnuit724a96vw81 unique (NAME); - create table CCM_CORE.APPLICATIONS ( APPLICATION_TYPE varchar(1024) not null, PRIMARY_URL varchar(1024) not null, @@ -1379,11 +1392,11 @@ drop sequence if exists HIBERNATE_SEQUENCE; SETTING_ID bigint not null, CONFIGURATION_CLASS varchar(512) not null, NAME varchar(512) not null, - SETTING_VALUE_BOOLEAN boolean, - SETTING_VALUE_STRING varchar(1024), SETTING_VALUE_BIG_DECIMAL decimal(19,2), - SETTING_VALUE_LONG bigint, + SETTING_VALUE_STRING varchar(1024), SETTING_VALUE_DOUBLE double, + SETTING_VALUE_LONG bigint, + SETTING_VALUE_BOOLEAN boolean, primary key (SETTING_ID) ); @@ -1404,6 +1417,14 @@ drop sequence if exists HIBERNATE_SEQUENCE; value varchar(255) ); + create table CCM_CORE.SITES ( + DEFAULT_SITE boolean, + DEFAULT_THEME varchar(255), + DOMAIN_OF_SITE varchar(255), + OBJECT_ID bigint not null, + primary key (OBJECT_ID) + ); + create table CCM_CORE.THREADS ( OBJECT_ID bigint not null, ROOT_ID bigint, @@ -1529,6 +1550,9 @@ drop sequence if exists HIBERNATE_SEQUENCE; alter table CCM_CORE.SETTINGS add constraint UK5whinfxdaepqs09e5ia9y71uk unique (CONFIGURATION_CLASS, NAME); + alter table CCM_CORE.SITES + add constraint UK_kou1h4y4st2m173he44yy8grx unique (DOMAIN_OF_SITE); + alter table CCM_CORE.WORKFLOW_TASK_COMMENTS add constraint UK_4nnedf08odyjxalfkg16fmjoi unique (UUID); @@ -2220,6 +2244,41 @@ drop sequence if exists HIBERNATE_SEQUENCE; foreign key (REVEND) references CCM_CORE.CCM_REVISIONS; + alter table CCM_CMS.PAGE_THEME_CONFIGURATIONS + add constraint FK6l6xp6ex6sh2uuxfmeekf6ckn + foreign key (PAGE_ID) + references CCM_CMS.PAGES; + + alter table CCM_CMS.PAGES + add constraint FKqweb08d151ot4ij9io72w3yhx + foreign key (INDEX_PAGE_MODEL_ID) + references CCM_CORE.PAGE_MODELS; + + alter table CCM_CMS.PAGES + add constraint FKg2p2ahbayc2coei72pk1lnenf + foreign key (ITEM_PAGE_MODEL_ID) + references CCM_CORE.PAGE_MODELS; + + alter table CCM_CMS.PAGES + add constraint FKmgmth087tmxwieujn2vs5opbo + foreign key (OBJECT_ID) + references CCM_CORE.CCM_OBJECTS; + + alter table CCM_CMS.PAGES_APP + add constraint FK5swx0e8pj0mm5t1es0lj4nwlx + foreign key (CATEGORY_DOMAIN_ID) + references CCM_CORE.CATEGORY_DOMAINS; + + alter table CCM_CMS.PAGES_APP + add constraint FK3wkyn4oxa65f7svtj917m61jc + foreign key (SITE_ID) + references CCM_CORE.SITES; + + alter table CCM_CMS.PAGES_APP + add constraint FKrrk4g7my3e4qkdoeiygkqxduy + foreign key (OBJECT_ID) + references CCM_CORE.APPLICATIONS; + alter table CCM_CMS.RELATED_LINKS add constraint FKb517dnfj56oby2s34jp1omuim foreign key (BOOKMARK_ID) @@ -2265,16 +2324,6 @@ drop sequence if exists HIBERNATE_SEQUENCE; foreign key (OBJECT_ID, REV) references CCM_CMS.ASSETS_AUD; - alter table CCM_CMS.SITES - add constraint FKmiysfmv1nkcso6bm18sjhvtm8 - foreign key (CATEGORY_DOMAIN_ID) - references CCM_CORE.CATEGORY_DOMAINS; - - alter table CCM_CMS.SITES - add constraint FK5kmn26x72uue9t3dfnjwes45 - foreign key (OBJECT_ID) - references CCM_CORE.APPLICATIONS; - alter table CCM_CMS.VIDEO_ASSETS add constraint FKjuywvv7wq9pyid5b6ivyrc0yk foreign key (LEGAL_METADATA_ID) @@ -2710,6 +2759,11 @@ drop sequence if exists HIBERNATE_SEQUENCE; foreign key (LIST_ID) references CCM_CORE.SETTINGS; + alter table CCM_CORE.SITES + add constraint FKrca95c6p023men53b8ayu26kp + foreign key (OBJECT_ID) + references CCM_CORE.CCM_OBJECTS; + alter table CCM_CORE.THREADS add constraint FKsx08mpwvwnw97uwdgjs76q39g foreign key (ROOT_ID) diff --git a/ccm-cms/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_cms_schema.sql b/ccm-cms/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_cms_schema.sql index 84913c2e5..b0f45ce57 100644 --- a/ccm-cms/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_cms_schema.sql +++ b/ccm-cms/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_cms_schema.sql @@ -4,6 +4,7 @@ drop schema if exists CCM_CORE cascade; drop sequence if exists HIBERNATE_SEQUENCE; create schema CCM_CMS; + create schema CCM_CORE; create table CCM_CMS.ARTICLE_TEXTS ( @@ -771,6 +772,28 @@ drop sequence if exists HIBERNATE_SEQUENCE; primary key (REV, OBJECT_ID, LOCALIZED_VALUE, LOCALE) ); + create table CCM_CMS.PAGE_THEME_CONFIGURATIONS ( + PAGE_ID int8 not null, + INDEX_PAGE_TEMPLATE varchar(255), + ITEM_PAGE_TEMPLATE varchar(255), + THEME varchar(255) not null, + primary key (PAGE_ID, THEME) + ); + + create table CCM_CMS.PAGES ( + OBJECT_ID int8 not null, + INDEX_PAGE_MODEL_ID int8, + ITEM_PAGE_MODEL_ID int8, + primary key (OBJECT_ID) + ); + + create table CCM_CMS.PAGES_APP ( + OBJECT_ID int8 not null, + CATEGORY_DOMAIN_ID int8, + SITE_ID int8, + primary key (OBJECT_ID) + ); + create table CCM_CMS.RELATED_LINKS ( OBJECT_ID int8 not null, BOOKMARK_ID int8, @@ -814,14 +837,6 @@ drop sequence if exists HIBERNATE_SEQUENCE; primary key (OBJECT_ID, REV) ); - create table CCM_CMS.SITES ( - DEFAULT_SITE boolean, - NAME varchar(255), - OBJECT_ID int8 not null, - CATEGORY_DOMAIN_ID int8, - primary key (OBJECT_ID) - ); - create table CCM_CMS.VIDEO_ASSETS ( HEIGHT int8, WIDTH int8, @@ -851,9 +866,6 @@ drop sequence if exists HIBERNATE_SEQUENCE; alter table CCM_CMS.CONTENT_SECTION_WORKFLOW_TEMPLATES add constraint UK_goj42ghwu4tf1akfb2r6ensns unique (WORKFLOW_TEMPLATE_ID); - alter table CCM_CMS.SITES - add constraint UK_fgjx0nuuxlgnuit724a96vw81 unique (NAME); - create table CCM_CORE.APPLICATIONS ( APPLICATION_TYPE varchar(1024) not null, PRIMARY_URL varchar(1024) not null, @@ -1379,11 +1391,11 @@ drop sequence if exists HIBERNATE_SEQUENCE; SETTING_ID int8 not null, CONFIGURATION_CLASS varchar(512) not null, NAME varchar(512) not null, - SETTING_VALUE_BOOLEAN boolean, - SETTING_VALUE_STRING varchar(1024), SETTING_VALUE_BIG_DECIMAL numeric(19, 2), - SETTING_VALUE_LONG int8, + SETTING_VALUE_STRING varchar(1024), SETTING_VALUE_DOUBLE float8, + SETTING_VALUE_LONG int8, + SETTING_VALUE_BOOLEAN boolean, primary key (SETTING_ID) ); @@ -1404,6 +1416,14 @@ drop sequence if exists HIBERNATE_SEQUENCE; value varchar(255) ); + create table CCM_CORE.SITES ( + DEFAULT_SITE boolean, + DEFAULT_THEME varchar(255), + DOMAIN_OF_SITE varchar(255), + OBJECT_ID int8 not null, + primary key (OBJECT_ID) + ); + create table CCM_CORE.THREADS ( OBJECT_ID int8 not null, ROOT_ID int8, @@ -1529,6 +1549,9 @@ drop sequence if exists HIBERNATE_SEQUENCE; alter table CCM_CORE.SETTINGS add constraint UK5whinfxdaepqs09e5ia9y71uk unique (CONFIGURATION_CLASS, NAME); + alter table CCM_CORE.SITES + add constraint UK_kou1h4y4st2m173he44yy8grx unique (DOMAIN_OF_SITE); + alter table CCM_CORE.WORKFLOW_TASK_COMMENTS add constraint UK_4nnedf08odyjxalfkg16fmjoi unique (UUID); @@ -2220,6 +2243,41 @@ drop sequence if exists HIBERNATE_SEQUENCE; foreign key (REVEND) references CCM_CORE.CCM_REVISIONS; + alter table CCM_CMS.PAGE_THEME_CONFIGURATIONS + add constraint FK6l6xp6ex6sh2uuxfmeekf6ckn + foreign key (PAGE_ID) + references CCM_CMS.PAGES; + + alter table CCM_CMS.PAGES + add constraint FKqweb08d151ot4ij9io72w3yhx + foreign key (INDEX_PAGE_MODEL_ID) + references CCM_CORE.PAGE_MODELS; + + alter table CCM_CMS.PAGES + add constraint FKg2p2ahbayc2coei72pk1lnenf + foreign key (ITEM_PAGE_MODEL_ID) + references CCM_CORE.PAGE_MODELS; + + alter table CCM_CMS.PAGES + add constraint FKmgmth087tmxwieujn2vs5opbo + foreign key (OBJECT_ID) + references CCM_CORE.CCM_OBJECTS; + + alter table CCM_CMS.PAGES_APP + add constraint FK5swx0e8pj0mm5t1es0lj4nwlx + foreign key (CATEGORY_DOMAIN_ID) + references CCM_CORE.CATEGORY_DOMAINS; + + alter table CCM_CMS.PAGES_APP + add constraint FK3wkyn4oxa65f7svtj917m61jc + foreign key (SITE_ID) + references CCM_CORE.SITES; + + alter table CCM_CMS.PAGES_APP + add constraint FKrrk4g7my3e4qkdoeiygkqxduy + foreign key (OBJECT_ID) + references CCM_CORE.APPLICATIONS; + alter table CCM_CMS.RELATED_LINKS add constraint FKb517dnfj56oby2s34jp1omuim foreign key (BOOKMARK_ID) @@ -2265,16 +2323,6 @@ drop sequence if exists HIBERNATE_SEQUENCE; foreign key (OBJECT_ID, REV) references CCM_CMS.ASSETS_AUD; - alter table CCM_CMS.SITES - add constraint FKmiysfmv1nkcso6bm18sjhvtm8 - foreign key (CATEGORY_DOMAIN_ID) - references CCM_CORE.CATEGORY_DOMAINS; - - alter table CCM_CMS.SITES - add constraint FK5kmn26x72uue9t3dfnjwes45 - foreign key (OBJECT_ID) - references CCM_CORE.APPLICATIONS; - alter table CCM_CMS.VIDEO_ASSETS add constraint FKjuywvv7wq9pyid5b6ivyrc0yk foreign key (LEGAL_METADATA_ID) @@ -2710,6 +2758,11 @@ drop sequence if exists HIBERNATE_SEQUENCE; foreign key (LIST_ID) references CCM_CORE.SETTINGS; + alter table CCM_CORE.SITES + add constraint FKrca95c6p023men53b8ayu26kp + foreign key (OBJECT_ID) + references CCM_CORE.CCM_OBJECTS; + alter table CCM_CORE.THREADS add constraint FKsx08mpwvwnw97uwdgjs76q39g foreign key (ROOT_ID) diff --git a/ccm-core/src/main/java/org/libreccm/l10n/GlobalizationHelper.java b/ccm-core/src/main/java/org/libreccm/l10n/GlobalizationHelper.java index 33ca9c515..dcc3d365d 100644 --- a/ccm-core/src/main/java/org/libreccm/l10n/GlobalizationHelper.java +++ b/ccm-core/src/main/java/org/libreccm/l10n/GlobalizationHelper.java @@ -178,6 +178,12 @@ public class GlobalizationHelper { return selected; } + + public void setSelectedLocale(final Locale locale) { + + final HttpSession session = request.getSession(true); + session.setAttribute(LANG_PARAM, locale.toString()); + } /** * Retrieve the {@link ResourceBundle} identified by {@code name} for the diff --git a/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/h2/V7_0_0_16__create_sites.sql b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/h2/V7_0_0_16__create_sites.sql new file mode 100644 index 000000000..ff6abba4e --- /dev/null +++ b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/h2/V7_0_0_16__create_sites.sql @@ -0,0 +1,16 @@ +create table CCM_CORE.SITES ( + DEFAULT_SITE boolean, + DEFAULT_THEME varchar(255), + DOMAIN_OF_SITE varchar(255), + OBJECT_ID bigint not null, + primary key (OBJECT_ID) +); + +alter table CCM_CORE.SITES + add constraint UK_kou1h4y4st2m173he44yy8grx unique (DOMAIN_OF_SITE); + +alter table CCM_CORE.SITES + add constraint FKrca95c6p023men53b8ayu26kp + foreign key (OBJECT_ID) + references CCM_CORE.CCM_OBJECTS; + diff --git a/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/pgsql/V7_0_0_16__create_sites.sql b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/pgsql/V7_0_0_16__create_sites.sql new file mode 100644 index 000000000..cb937955a --- /dev/null +++ b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/pgsql/V7_0_0_16__create_sites.sql @@ -0,0 +1,16 @@ +create table CCM_CORE.SITES ( + DEFAULT_SITE boolean, + DEFAULT_THEME varchar(255), + DOMAIN_OF_SITE varchar(255), + OBJECT_ID int8 not null, + primary key (OBJECT_ID) +); + +alter table CCM_CORE.SITES + add constraint UK_kou1h4y4st2m173he44yy8grx unique (DOMAIN_OF_SITE); + +alter table CCM_CORE.SITES + add constraint FKrca95c6p023men53b8ayu26kp + foreign key (OBJECT_ID) + references CCM_CORE.CCM_OBJECTS; + 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 5a0d4b856..114218bc4 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 @@ -2,7 +2,8 @@ drop schema if exists CCM_CORE; drop sequence if exists HIBERNATE_SEQUENCE; -create schema CCM_CORE; + + create schema CCM_CORE; create table CCM_CORE.APPLICATIONS ( APPLICATION_TYPE varchar(1024) not null, @@ -529,11 +530,11 @@ create schema CCM_CORE; SETTING_ID bigint not null, CONFIGURATION_CLASS varchar(512) not null, NAME varchar(512) not null, - SETTING_VALUE_BOOLEAN boolean, - SETTING_VALUE_BIG_DECIMAL decimal(19,2), SETTING_VALUE_LONG bigint, + SETTING_VALUE_BIG_DECIMAL decimal(19,2), SETTING_VALUE_DOUBLE double, SETTING_VALUE_STRING varchar(1024), + SETTING_VALUE_BOOLEAN boolean, primary key (SETTING_ID) ); @@ -554,6 +555,14 @@ create schema CCM_CORE; value varchar(255) ); + create table CCM_CORE.SITES ( + DEFAULT_SITE boolean, + DEFAULT_THEME varchar(255), + DOMAIN_OF_SITE varchar(255), + OBJECT_ID bigint not null, + primary key (OBJECT_ID) + ); + create table CCM_CORE.THREADS ( OBJECT_ID bigint not null, ROOT_ID bigint, @@ -679,6 +688,9 @@ create schema CCM_CORE; alter table CCM_CORE.SETTINGS add constraint UK5whinfxdaepqs09e5ia9y71uk unique (CONFIGURATION_CLASS, NAME); + alter table CCM_CORE.SITES + add constraint UK_kou1h4y4st2m173he44yy8grx unique (DOMAIN_OF_SITE); + alter table CCM_CORE.WORKFLOW_TASK_COMMENTS add constraint UK_4nnedf08odyjxalfkg16fmjoi unique (UUID); @@ -1105,6 +1117,11 @@ create schema CCM_CORE; foreign key (LIST_ID) references CCM_CORE.SETTINGS; + alter table CCM_CORE.SITES + add constraint FKrca95c6p023men53b8ayu26kp + foreign key (OBJECT_ID) + references CCM_CORE.CCM_OBJECTS; + alter table CCM_CORE.THREADS add constraint FKsx08mpwvwnw97uwdgjs76q39g foreign key (ROOT_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 67041e43b..cd634eb75 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 @@ -1203,4 +1203,3 @@ drop sequence if exists HIBERNATE_SEQUENCE; alter table CCM_CORE.WORKFLOWS add constraint FK9ray5beiny6wm2mi0uwyecay2 foreign key (TEMPLATE_ID) - references CCM_CORE.WORKFLOWS; \ No newline at end of file