CCM NG:
- Some preparation for the editor UI for PageModel
- SimpleItemResolver and MultilingualItemResolver ported to new API (still disabled because of circular dependencies in UI classes)
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4486 8810af33-2d31-482b-a856-94f89814c4df
Former-commit-id: aa3f76e4a1
pull/2/head
parent
08ba214405
commit
a38485014b
|
|
@ -26,7 +26,6 @@ import org.librecms.contentsection.ContentSection;
|
|||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
|
|
@ -36,82 +35,45 @@ public abstract class AbstractItemResolver implements ItemResolver {
|
|||
|
||||
protected static final String TEMPLATE_CONTEXT_PREFIX = "tem_";
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.arsdigita.cms.dispatcher.ItemResolver#getItem(
|
||||
* com.arsdigita.cms.ContentSection, java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public abstract ContentItem getItem(
|
||||
ContentSection section,
|
||||
String url,
|
||||
String context);
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.arsdigita.cms.dispatcher.ItemResolver#getCurrentContext(
|
||||
* com.arsdigita.bebop.PageState)
|
||||
*/
|
||||
@Override
|
||||
public abstract String getCurrentContext(PageState state);
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.arsdigita.cms.dispatcher.ItemResolver#generateItemURL(
|
||||
* com.arsdigita.bebop.PageState, java.math.BigDecimal,
|
||||
* java.lang.String, com.arsdigita.cms.ContentSection,
|
||||
* java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public abstract String generateItemURL(
|
||||
PageState state,
|
||||
BigDecimal itemId,
|
||||
Long itemId,
|
||||
String name,
|
||||
ContentSection section,
|
||||
String context);
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.arsdigita.cms.dispatcher.ItemResolver#generateItemURL(
|
||||
* com.arsdigita.bebop.PageState,
|
||||
* java.math.BigDecimal,
|
||||
* java.lang.String,
|
||||
* com.arsdigita.cms.ContentSection,
|
||||
* java.lang.String, java.lang.String)
|
||||
*/
|
||||
public abstract String generateItemURL(
|
||||
PageState state,
|
||||
BigDecimal itemId,
|
||||
String name,
|
||||
ContentSection section,
|
||||
String context,
|
||||
String templateContext);
|
||||
@Override
|
||||
public abstract String generateItemURL(PageState state,
|
||||
Long itemId,
|
||||
String name,
|
||||
ContentSection section,
|
||||
String context,
|
||||
String templateContext);
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.arsdigita.cms.dispatcher.ItemResolver#generateItemURL(
|
||||
* com.arsdigita.bebop.PageState,
|
||||
* com.arsdigita.cms.ContentItem,
|
||||
* com.arsdigita.cms.ContentSection,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public abstract String generateItemURL(
|
||||
PageState state,
|
||||
ContentItem item,
|
||||
ContentSection section,
|
||||
String context);
|
||||
@Override
|
||||
public abstract String generateItemURL(PageState state,
|
||||
ContentItem item,
|
||||
ContentSection section,
|
||||
String context);
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.arsdigita.cms.dispatcher.ItemResolver#generateItemURL(
|
||||
* com.arsdigita.bebop.PageState,
|
||||
* com.arsdigita.cms.ContentItem,
|
||||
* com.arsdigita.cms.ContentSection,
|
||||
* java.lang.String, java.lang.String)
|
||||
*/
|
||||
public abstract String generateItemURL(
|
||||
PageState state,
|
||||
ContentItem item,
|
||||
ContentSection section,
|
||||
String context,
|
||||
String templateContext);
|
||||
@Override
|
||||
public abstract String generateItemURL(PageState state,
|
||||
ContentItem item,
|
||||
ContentSection section,
|
||||
String context,
|
||||
String templateContext);
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.arsdigita.cms.dispatcher.ItemResolver#getMasterPage(
|
||||
* com.arsdigita.cms.ContentItem,
|
||||
* javax.servlet.http.HttpServletRequest)
|
||||
*/
|
||||
@Override
|
||||
public abstract CMSPage getMasterPage(ContentItem item,
|
||||
HttpServletRequest request)
|
||||
throws ServletException;
|
||||
|
|
@ -124,7 +86,8 @@ public abstract class AbstractItemResolver implements ItemResolver {
|
|||
*
|
||||
* @return the template context, or null if there is no template context
|
||||
*/
|
||||
public String getTemplateFromURL(String inUrl) {
|
||||
@Override
|
||||
public String getTemplateFromURL(final String inUrl) {
|
||||
String tempUrl;
|
||||
String url;
|
||||
if (inUrl.startsWith("/")) {
|
||||
|
|
@ -155,13 +118,15 @@ public abstract class AbstractItemResolver implements ItemResolver {
|
|||
*
|
||||
* @return <code>inUrl</code> with the template context removed
|
||||
*/
|
||||
public String stripTemplateFromURL(String inUrl) {
|
||||
@Override
|
||||
public String stripTemplateFromURL(final String inUrl) {
|
||||
|
||||
String sTemplateContext = getTemplateFromURL(inUrl);
|
||||
|
||||
if (sTemplateContext != null) {
|
||||
//there is a template context, so strip it
|
||||
int iTemplateLength = TEMPLATE_CONTEXT_PREFIX.length()
|
||||
+ sTemplateContext.length() + 1;
|
||||
+ sTemplateContext.length() + 1;
|
||||
String sStripped = inUrl.substring(iTemplateLength, inUrl.length());
|
||||
return sStripped;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -20,45 +20,64 @@ package com.arsdigita.cms.dispatcher;
|
|||
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.cms.CMS;
|
||||
import com.arsdigita.cms.ContentCenter;
|
||||
import com.arsdigita.cms.ui.ContentItemPage;
|
||||
import com.arsdigita.kernel.KernelConfig;
|
||||
import com.arsdigita.util.Assert;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.libreccm.categorization.Category;
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
import org.librecms.contentsection.ContentSection;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.core.CcmObject;
|
||||
import org.libreccm.l10n.GlobalizationHelper;
|
||||
import org.librecms.CmsConstants;
|
||||
import org.librecms.contentsection.ContentItemManager;
|
||||
import org.librecms.contentsection.ContentItemRepository;
|
||||
import org.librecms.contentsection.ContentItemVersion;
|
||||
import org.librecms.contentsection.Folder;
|
||||
import org.librecms.contentsection.FolderManager;
|
||||
import org.librecms.util.LanguageUtil;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static javax.naming.ldap.SortControl.*;
|
||||
|
||||
/**
|
||||
* Resolves items to URLs and URLs to items for multiple language variants.
|
||||
*
|
||||
* Created Mon Jan 20 14:30:03 2003.
|
||||
* * <strong>
|
||||
* AS of version 7.0.0 this class not longer part of the public API. It is left
|
||||
* here to keep the changes to the UI classes as minimal as possible. For new
|
||||
* code other methods, for example from the {@link ContentItemManager} or the
|
||||
* {@link ContentItemRepository} should be used. Because this class is no longer
|
||||
* part of the public API the will might be removed or changed in future
|
||||
* releases without prior warning.
|
||||
* </strong>
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author <a href="mailto:mhanisch@redhat.com">Michael Hanisch</a>
|
||||
* @version $Id: MultilingualItemResolver.java 2090 2010-04-17 08:04:14Z pboy $
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
public class MultilingualItemResolver
|
||||
extends AbstractItemResolver implements ItemResolver {
|
||||
extends AbstractItemResolver implements ItemResolver {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(
|
||||
MultilingualItemResolver.class);
|
||||
MultilingualItemResolver.class);
|
||||
|
||||
private static MasterPage s_masterP = null;
|
||||
private static final String ADMIN_PREFIX = "admin";
|
||||
|
|
@ -83,8 +102,10 @@ public class MultilingualItemResolver
|
|||
* @param section The current content section
|
||||
* @param itemUrl The section-relative URL
|
||||
* @param context The use context, e.g. <code>ContentItem.LIVE</code>,
|
||||
* <code>CMSDispatcher.PREVIEW</code> or <code>ContentItem.DRAFT</code>. See {@link
|
||||
* <code>CMSDispatcher.PREVIEW</code> or
|
||||
* <code>ContentItem.DRAFT</code>. See {@link
|
||||
* #getCurrentContext}.
|
||||
*
|
||||
* @return The content item, or null if no such item exists
|
||||
*/
|
||||
@Override
|
||||
|
|
@ -92,7 +113,7 @@ public class MultilingualItemResolver
|
|||
final String itemUrl,
|
||||
final String context) {
|
||||
LOGGER.debug("Resolving the item in content section \"{}\" at URL "
|
||||
+ "\"{}\" for context \"{}\"...",
|
||||
+ "\"{}\" for context \"{}\"...",
|
||||
section.getLabel(),
|
||||
itemUrl,
|
||||
context);
|
||||
|
|
@ -119,16 +140,16 @@ public class MultilingualItemResolver
|
|||
LOGGER.debug("The root folder has a live version; recursing");
|
||||
|
||||
final FolderManager folderManager = cdiUtil.findBean(
|
||||
FolderManager.class);
|
||||
FolderManager.class);
|
||||
final String prefix = String.join(
|
||||
"",
|
||||
section.getPrimaryUrl(),
|
||||
folderManager.getFolderPath(rootFolder));
|
||||
"",
|
||||
section.getPrimaryUrl(),
|
||||
folderManager.getFolderPath(rootFolder));
|
||||
|
||||
if (url.startsWith(prefix)) {
|
||||
LOGGER.
|
||||
debug("The starts with prefix \"{}\"; removing it...",
|
||||
prefix);
|
||||
debug("The starts with prefix \"{}\"; removing it...",
|
||||
prefix);
|
||||
|
||||
url = url.substring(prefix.length());
|
||||
}
|
||||
|
|
@ -171,8 +192,8 @@ public class MultilingualItemResolver
|
|||
|
||||
if (url.startsWith(prefix)) {
|
||||
LOGGER.debug(
|
||||
"The URL starts with prefix \"{}\"; removing it",
|
||||
prefix);
|
||||
"The URL starts with prefix \"{}\"; removing it",
|
||||
prefix);
|
||||
|
||||
url = url.substring(prefix.length());
|
||||
}
|
||||
|
|
@ -186,7 +207,7 @@ public class MultilingualItemResolver
|
|||
return item;
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Invalid item resolver context \"%s\".", context));
|
||||
"Invalid item resolver context \"%s\".", context));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -199,11 +220,13 @@ public class MultilingualItemResolver
|
|||
* Fetches the current context based on the page state.
|
||||
*
|
||||
* @param state the current page state
|
||||
*
|
||||
* @return the context of the current URL, such as
|
||||
* <code>ContentItem.LIVE</code> or <code>ContentItem.DRAFT</code>
|
||||
* <code>ContentItem.LIVE</code> or <code>ContentItem.DRAFT</code>
|
||||
*
|
||||
* @see ContentItem#LIVE
|
||||
* @see ContentItem#DRAFT
|
||||
*
|
||||
*
|
||||
* ToDo: Refactor to use the {@link ContentItemVersion} directly.
|
||||
*/
|
||||
@Override
|
||||
|
|
@ -232,8 +255,8 @@ public class MultilingualItemResolver
|
|||
url = stripTemplateFromURL(url);
|
||||
|
||||
// Determine if we are under the admin UI.
|
||||
if (url.startsWith(ADMIN_PREFIX)
|
||||
|| url.startsWith(CmsConstants.CONTENT_CENTER_URL)) {
|
||||
if (url.startsWith(ADMIN_PREFIX)
|
||||
|| url.startsWith(CmsConstants.CONTENT_CENTER_URL)) {
|
||||
return ContentItemVersion.DRAFT.toString();
|
||||
} else {
|
||||
return ContentItemVersion.LIVE.toString();
|
||||
|
|
@ -243,17 +266,19 @@ public class MultilingualItemResolver
|
|||
/**
|
||||
* Generates a URL for a content item.
|
||||
*
|
||||
* @param itemId The item ID
|
||||
* @param name The name of the content page
|
||||
* @param state The page state
|
||||
* @param itemId The item ID
|
||||
* @param name The name of the content page
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "live" or "admin"
|
||||
*
|
||||
* @return The URL of the item
|
||||
*
|
||||
* @see #getCurrentContext
|
||||
*/
|
||||
@Override
|
||||
public String generateItemURL(final PageState state,
|
||||
final BigDecimal itemId,
|
||||
final Long itemId,
|
||||
final String name,
|
||||
final ContentSection section,
|
||||
final String context) {
|
||||
|
|
@ -263,27 +288,29 @@ public class MultilingualItemResolver
|
|||
/**
|
||||
* Generates a URL for a content item.
|
||||
*
|
||||
* @param itemId The item ID
|
||||
* @param name The name of the content page
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "live" or "admin"
|
||||
* @param itemId The item ID
|
||||
* @param name The name of the content page
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "live" or "admin"
|
||||
* @param templateContext the context for the URL, such as "public"
|
||||
*
|
||||
* @return The URL of the item
|
||||
*
|
||||
* @see #getCurrentContext
|
||||
*/
|
||||
@Override
|
||||
public String generateItemURL(final PageState state,
|
||||
final BigDecimal itemId,
|
||||
final Long itemId,
|
||||
final String name,
|
||||
final ContentSection section,
|
||||
final String context,
|
||||
final String templateContext) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Generating an item URL for item id " + itemId
|
||||
+ ", section " + section + ", and context '"
|
||||
+ context
|
||||
+ "' with name '" + name + "'");
|
||||
+ ", section " + section + ", and context '"
|
||||
+ context
|
||||
+ "' with name '" + name + "'");
|
||||
}
|
||||
|
||||
Assert.exists(itemId, "BigDecimal itemId");
|
||||
|
|
@ -291,40 +318,35 @@ public class MultilingualItemResolver
|
|||
Assert.exists(section, "ContentSection section");
|
||||
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final ContentItemRepository itemRepo = cdiUtil.findBean(ContentItemRepository.class);
|
||||
|
||||
final ContentItemRepository itemRepo = cdiUtil.findBean(
|
||||
ContentItemRepository.class);
|
||||
|
||||
if (ContentItemVersion.DRAFT.toString().equals(context)) {
|
||||
// No template context here.
|
||||
return generateDraftURL(section, itemId);
|
||||
} else if (CMSDispatcher.PREVIEW.equals(context)) {
|
||||
ContentItem item = new ContentItem(itemId);
|
||||
|
||||
final ContentItem item = itemRepo.findById(itemId);
|
||||
return generatePreviewURL(section, item, templateContext);
|
||||
} else if (ContentItem.LIVE.equals(context)) {
|
||||
ContentItem item = new ContentItem(itemId);
|
||||
|
||||
if (Assert.isEnabled()) {
|
||||
Assert.exists(item, "item");
|
||||
Assert.isTrue(ContentItem.LIVE.equals(item.getVersion()),
|
||||
"Generating " + ContentItem.LIVE + " "
|
||||
+ "URL; this item must be the live version");
|
||||
}
|
||||
} else if (ContentItemVersion.LIVE.toString().equals(context)) {
|
||||
final ContentItem item = itemRepo.findById(itemId);
|
||||
|
||||
return generateLiveURL(section, item, templateContext);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown context '" + context
|
||||
+ "'");
|
||||
+ "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a URL for a content item.
|
||||
*
|
||||
* @param item The item
|
||||
* @param state The page state
|
||||
* @param item The item
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "live" or "admin"
|
||||
*
|
||||
* @return The URL of the item
|
||||
*
|
||||
* @see #getCurrentContext
|
||||
*/
|
||||
@Override
|
||||
|
|
@ -338,68 +360,61 @@ public class MultilingualItemResolver
|
|||
/**
|
||||
* Generates a URL for a content item.
|
||||
*
|
||||
* @param item The item
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "live" or "admin"
|
||||
* @param item The item
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "live" or "admin"
|
||||
* @param templateContext the context for the URL, such as "public"
|
||||
*
|
||||
* @return The URL of the item
|
||||
*
|
||||
* @see #getCurrentContext
|
||||
*/
|
||||
@Override
|
||||
public String generateItemURL(final PageState state,
|
||||
final ContentItem item,
|
||||
ContentSection section,
|
||||
final ContentSection section,
|
||||
final String context,
|
||||
final String templateContext) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Generating an item URL for item " + item
|
||||
+ ", section "
|
||||
+ section + ", and context " + context);
|
||||
+ ", section "
|
||||
+ section + ", and context " + context);
|
||||
}
|
||||
|
||||
Assert.exists(item, "ContentItem item");
|
||||
Assert.exists(context, "String context");
|
||||
|
||||
final ContentSection contentSection;
|
||||
if (section == null) {
|
||||
section = item.getContentSection();
|
||||
contentSection = item.getContentType().getContentSection();
|
||||
} else {
|
||||
contentSection = section;
|
||||
}
|
||||
|
||||
if (ContentItem.DRAFT.equals(context)) {
|
||||
if (Assert.isEnabled()) {
|
||||
Assert.isTrue(ContentItem.DRAFT.equals(item.getVersion()),
|
||||
"Generating " + ContentItem.DRAFT
|
||||
+ " url: item must be draft version");
|
||||
}
|
||||
|
||||
return generateDraftURL(section, item.getID());
|
||||
if (ContentItemVersion.DRAFT.toString().equals(context)) {
|
||||
return generateDraftURL(section, item.getObjectId());
|
||||
} else if (CMSDispatcher.PREVIEW.equals(context)) {
|
||||
return generatePreviewURL(section, item, templateContext);
|
||||
} else if (ContentItem.LIVE.equals(context)) {
|
||||
if (Assert.isEnabled()) {
|
||||
Assert.isTrue(ContentItem.LIVE.equals(item.getVersion()),
|
||||
"Generating " + ContentItem.LIVE
|
||||
+ " url: item must be live version");
|
||||
}
|
||||
|
||||
return generateLiveURL(section, item, templateContext);
|
||||
} else if (ContentItemVersion.LIVE.toString().equals(context)) {
|
||||
return generateLiveURL(contentSection, item, templateContext);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown context " + context);
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Unknown context \"%s\".", context));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a master page based on page state (and content section).
|
||||
*
|
||||
* @param item The content item
|
||||
* @param item The content item
|
||||
* @param request The HTTP request
|
||||
*
|
||||
* @return The master page
|
||||
*
|
||||
* @throws javax.servlet.ServletException
|
||||
*/
|
||||
@Override
|
||||
public CMSPage getMasterPage(final ContentItem item,
|
||||
final HttpServletRequest request)
|
||||
throws ServletException {
|
||||
throws ServletException {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Getting the master page for item " + item);
|
||||
}
|
||||
|
|
@ -421,25 +436,27 @@ public class MultilingualItemResolver
|
|||
* Returns content item's draft version URL
|
||||
*
|
||||
* @param section The content section to which the item belongs
|
||||
* @param itemId The content item's ID
|
||||
* @param itemId The content item's ID
|
||||
*
|
||||
* @return generated URL string
|
||||
*/
|
||||
protected String generateDraftURL(final ContentSection section,
|
||||
final BigDecimal itemId) {
|
||||
final Long itemId) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Generating draft URL for item ID " + itemId
|
||||
+ " and section " + section);
|
||||
+ " and section " + section);
|
||||
}
|
||||
|
||||
if (Assert.isEnabled()) {
|
||||
Assert.isTrue(section != null && itemId != null,
|
||||
"get draft url: neither secion nor item "
|
||||
+ "can be null");
|
||||
+ "can be null");
|
||||
}
|
||||
|
||||
final String url = ContentItemPage.getItemURL(section.getPath() + "/",
|
||||
itemId,
|
||||
ContentItemPage.AUTHORING_TAB);
|
||||
final String url = ContentItemPage.getItemURL(
|
||||
String.format("%s/", section.getPrimaryUrl()),
|
||||
itemId,
|
||||
ContentItemPage.AUTHORING_TAB);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Generated draft URL " + url);
|
||||
|
|
@ -455,23 +472,23 @@ public class MultilingualItemResolver
|
|||
* specific language instance of the item referenced here, i.e. this URL
|
||||
* will be resolved to a <em>language-specific</em> URL internally.
|
||||
*
|
||||
* @param section the <code>ContentSection</code> that contains this item
|
||||
* @param item <code>ContentItem</code> for which a URL should be
|
||||
* constructed.
|
||||
* @param section the <code>ContentSection</code> that contains this
|
||||
* item
|
||||
* @param item <code>ContentItem</code> for which a URL should be
|
||||
* constructed.
|
||||
* @param templateContext template context; will be ignored if
|
||||
* <code>null</code>
|
||||
* <code>null</code>
|
||||
*
|
||||
* @return a <em>language-independent</em> URL to the <code>item</code> in
|
||||
* the given <code>section</code>, which will be presented within the given
|
||||
* <code>templateContext</code>
|
||||
* the given <code>section</code>, which will be presented within
|
||||
* the given <code>templateContext</code>
|
||||
*/
|
||||
protected String generateLiveURL(final ContentSection section,
|
||||
final ContentItem item,
|
||||
final String templateContext) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Generating live URL for item " + item + " in "
|
||||
+ "section " + section);
|
||||
}
|
||||
LOGGER.debug("Generating live URL for item {} in section {}",
|
||||
Objects.toString(item),
|
||||
Objects.toString(section));
|
||||
|
||||
/*
|
||||
* URL = URL of section + templateContext + path to the ContentBundle
|
||||
|
|
@ -479,7 +496,9 @@ public class MultilingualItemResolver
|
|||
*/
|
||||
final StringBuffer url = new StringBuffer(400);
|
||||
//url.append(section.getURL());
|
||||
url.append(section.getPath()).append("/");
|
||||
url
|
||||
.append(section.getPrimaryUrl())
|
||||
.append("/");
|
||||
|
||||
/*
|
||||
* add template context, if one is given
|
||||
|
|
@ -487,56 +506,17 @@ public class MultilingualItemResolver
|
|||
// This is breaking URL's...not sure why it's here. XXX
|
||||
// this should work with the appropriate logic. trying again.
|
||||
if (!(templateContext == null || templateContext.length() == 0)) {
|
||||
url.append(TEMPLATE_CONTEXT_PREFIX).append(templateContext).append(
|
||||
"/");
|
||||
url
|
||||
.append(TEMPLATE_CONTEXT_PREFIX)
|
||||
.append(templateContext)
|
||||
.append("/");
|
||||
}
|
||||
|
||||
// Try to retrieve the bundle.
|
||||
final ContentItem bundle = (ContentItem) item.getParent();
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final ContentItemManager itemManager = cdiUtil.findBean(
|
||||
ContentItemManager.class);
|
||||
url.append(itemManager.getItemPath(item));
|
||||
|
||||
/*
|
||||
* It would be nice if we had a ContentPage here, which
|
||||
* supports the getContentBundle() method, but unfortunately
|
||||
* the API sucks and there is no real distinction between mere
|
||||
* ContentItems and top-level items, so we have to use this
|
||||
* hack. TODO: add sanity check that bundle is actually a
|
||||
* ContentItem.
|
||||
*/
|
||||
if (bundle != null && bundle instanceof ContentBundle) {
|
||||
LOGGER.debug("Found a bundle; building its file name");
|
||||
|
||||
final String fname = bundle.getPath();
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Appending the bundle's file name '" + fname + "'");
|
||||
}
|
||||
|
||||
url.append(fname);
|
||||
|
||||
} else {
|
||||
LOGGER.debug("No bundle found; using the item's path directly");
|
||||
|
||||
url.append(item.getPath());
|
||||
}
|
||||
/*
|
||||
* This will append the language to the url, which will in turn render
|
||||
* the language negotiation inoperative
|
||||
final String language = item.getLanguage();
|
||||
|
||||
if (language == null) {
|
||||
s_log.debug("The item has no language; omitting the " +
|
||||
"language encoding");
|
||||
} else {
|
||||
s_log.debug("Encoding the language of the item passed in, '" +
|
||||
language + "'");
|
||||
|
||||
url.append("." + language);
|
||||
}
|
||||
|
||||
if (s_log.isDebugEnabled()) {
|
||||
s_log.debug("Generated live URL " + url.toString());
|
||||
}
|
||||
*/
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
|
|
@ -547,71 +527,44 @@ public class MultilingualItemResolver
|
|||
* <em>no</em> language negotiation is involved when a request is made to a
|
||||
* URL that has been generated by this method.
|
||||
*
|
||||
* @param section The <code>ContentSection</code> which contains the
|
||||
* <code>item</code>
|
||||
* @param item The <code>ContentItem</code> for which a URL should be
|
||||
* generated.
|
||||
* @param section The <code>ContentSection</code> which contains the
|
||||
* <code>item</code>
|
||||
* @param item The <code>ContentItem</code> for which a URL
|
||||
* should be generated.
|
||||
* @param templateContext the context that determines which template should
|
||||
* render the item when it is previewed; ignored if the argument given here
|
||||
* is <code>null</code>
|
||||
* render the item when it is previewed; ignored if
|
||||
* the argument given here is <code>null</code>
|
||||
*
|
||||
* @return a URL which can be used to preview the given <code>item</code>
|
||||
*/
|
||||
protected String generatePreviewURL(ContentSection section,
|
||||
ContentItem item,
|
||||
String templateContext) {
|
||||
protected String generatePreviewURL(final ContentSection section,
|
||||
final ContentItem item,
|
||||
final String templateContext) {
|
||||
Assert.exists(section, "ContentSection section");
|
||||
Assert.exists(item, "ContentItem item");
|
||||
|
||||
final StringBuffer url = new StringBuffer(100);
|
||||
url.append(section.getPath());
|
||||
url.append("/");
|
||||
url.append(CMSDispatcher.PREVIEW);
|
||||
url.append("/");
|
||||
url
|
||||
.append(section.getPrimaryUrl())
|
||||
.append("/")
|
||||
.append(CMSDispatcher.PREVIEW)
|
||||
.append("/");
|
||||
/*
|
||||
* add template context, if one is given
|
||||
*/
|
||||
// This is breaking URL's...not sure why it's here. XXX
|
||||
// this should work with the appropriate logic. trying again.
|
||||
if (!(templateContext == null || templateContext.length() == 0)) {
|
||||
url.append(TEMPLATE_CONTEXT_PREFIX).append(templateContext).append(
|
||||
"/");
|
||||
url
|
||||
.append(TEMPLATE_CONTEXT_PREFIX)
|
||||
.append(templateContext)
|
||||
.append("/");
|
||||
}
|
||||
|
||||
// Try to retrieve the bundle.
|
||||
ContentItem bundle = (ContentItem) item.getParent();
|
||||
|
||||
/* It would be nice if we had a ContentPage here, which
|
||||
* supports the getContentBundle() method, but unfortunately
|
||||
* the API sucks and there is no real distinction between mere
|
||||
* ContentItems and top-level items, so we have to use this
|
||||
* hack. TODO: add sanity check that bundle is actually a
|
||||
* ContentItem.
|
||||
*/
|
||||
if (bundle != null && bundle instanceof ContentBundle) {
|
||||
LOGGER.debug("Found a bundle; using its path");
|
||||
|
||||
url.append(bundle.getPath());
|
||||
} else {
|
||||
LOGGER.debug("No bundle found; using the item's path directly");
|
||||
|
||||
url.append(item.getPath());
|
||||
}
|
||||
|
||||
final String language = item.getLanguage();
|
||||
|
||||
if (language == null) {
|
||||
LOGGER.debug("The item has no language; omitting the "
|
||||
+ "language encoding");
|
||||
} else {
|
||||
LOGGER.debug("Encoding the language of the item passed in, '"
|
||||
+ language + "'");
|
||||
|
||||
url.append(".").append(language);
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Generated preview URL " + url.toString());
|
||||
}
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final ContentItemManager itemManager = cdiUtil.findBean(
|
||||
ContentItemManager.class);
|
||||
url.append(itemManager.getItemPath(item));
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
|
@ -621,9 +574,11 @@ public class MultilingualItemResolver
|
|||
* according to this ID.
|
||||
*
|
||||
* @param url URL that indicates which item should be retrieved; must
|
||||
* contain the <code>ITEM_ID</code> parameter
|
||||
* contain the <code>ITEM_ID</code> parameter
|
||||
*
|
||||
* @return the <code>ContentItem</code> the given <code>url</code> points
|
||||
* to, or <code>null</code> if no ID has been found in the <code>url</code>
|
||||
* to, or <code>null</code> if no ID has been found in the
|
||||
* <code>url</code>
|
||||
*/
|
||||
protected ContentItem getItemFromDraftURL(final String url) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
|
|
@ -661,41 +616,45 @@ public class MultilingualItemResolver
|
|||
LOGGER.debug("Looking up item using item ID " + item_id);
|
||||
}
|
||||
|
||||
OID oid = new OID(ContentItem.BASE_DATA_OBJECT_TYPE, new BigDecimal(
|
||||
item_id));
|
||||
final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(
|
||||
oid);
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final ContentItemRepository itemRepo = cdiUtil.findBean(
|
||||
ContentItemRepository.class);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Returning item " + item);
|
||||
final Optional<ContentItem> item = itemRepo.findById(Long.parseLong(
|
||||
item_id));
|
||||
|
||||
if (item.isPresent()) {
|
||||
LOGGER.debug("Returning item {}", Objects.toString(item));
|
||||
return item.get();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a content item based on URL relative to the root folder.
|
||||
*
|
||||
* @param url The content item url
|
||||
* @param url The content item url
|
||||
* @param parentFolder The parent folder object, url must be relevant to it
|
||||
*
|
||||
* @return The Content Item instance, it can also be either Bundle or Folder
|
||||
* objects, depending on URL and file language extension
|
||||
* objects, depending on URL and file language extension
|
||||
*/
|
||||
protected ContentItem getItemFromLiveURL(String url,
|
||||
Folder parentFolder) {
|
||||
protected ContentItem getItemFromLiveURL(final String url,
|
||||
final Folder parentFolder) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Resolving the item for live URL " + url
|
||||
+ " and parent folder " + parentFolder);
|
||||
+ " and parent folder " + parentFolder);
|
||||
}
|
||||
|
||||
if (parentFolder == null || url == null || url.equals("")) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("The url is null or parent folder was null "
|
||||
+ "or something else is wrong, so just return "
|
||||
+ "the parent folder");
|
||||
+ "or something else is wrong, so just return "
|
||||
+ "null");
|
||||
}
|
||||
|
||||
return parentFolder;
|
||||
return null;
|
||||
}
|
||||
|
||||
int len = url.length();
|
||||
|
|
@ -703,28 +662,28 @@ public class MultilingualItemResolver
|
|||
|
||||
if (index >= 0) {
|
||||
LOGGER.debug("The URL starts with a slash; paring off the first "
|
||||
+ "URL element and recursing");
|
||||
+ "URL element and recursing");
|
||||
|
||||
// If we got first slash (index == 0), ignore it and go
|
||||
// on, sample '/foo/bar/item.html.en', in next recursion
|
||||
// will have deal with 'foo' folder.
|
||||
String name = index > 0 ? url.substring(0, index) : "";
|
||||
parentFolder = "".equals(name) ? parentFolder
|
||||
: (Folder) parentFolder.getItem(URLEncoder.encode(
|
||||
name), true);
|
||||
url = index + 1 < len ? url.substring(index + 1) : "";
|
||||
final String liveUrl = index + 1 < len ? url.substring(index + 1)
|
||||
: "";
|
||||
|
||||
return getItemFromLiveURL(url, parentFolder);
|
||||
return getItemFromLiveURL(liveUrl, parentFolder);
|
||||
} else {
|
||||
LOGGER.debug("Found a file element in the URL");
|
||||
|
||||
String[] nameAndLang = getNameAndLangFromURLFrag(url);
|
||||
String name = nameAndLang[0];
|
||||
String lang = nameAndLang[1];
|
||||
final String[] nameAndLang = getNameAndLangFromURLFrag(url);
|
||||
final String name = nameAndLang[0];
|
||||
|
||||
ContentItem item = parentFolder.getItem(URLEncoder.encode(name),
|
||||
false);
|
||||
return getItemFromLangAndBundle(lang, item);
|
||||
final Optional<CcmObject> item = parentFolder.getObjects().stream()
|
||||
.map(categorization -> categorization.getCategorizedObject())
|
||||
.filter(object -> object.getDisplayName().equals(name))
|
||||
.findFirst();
|
||||
|
||||
if (item.isPresent() && item.get() instanceof ContentItem) {
|
||||
return (ContentItem) item.get();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -732,11 +691,13 @@ public class MultilingualItemResolver
|
|||
* Returns an array containing the the item's name and lang based on the URL
|
||||
* fragment.
|
||||
*
|
||||
* @param url
|
||||
*
|
||||
* @return a two-element string array, the first element containing the
|
||||
* bundle name, and the second element containing the lang string
|
||||
* bundle name, and the second element containing the lang string
|
||||
*/
|
||||
protected String[] getNameAndLangFromURLFrag(String url) {
|
||||
String name = null;
|
||||
protected String[] getNameAndLangFromURLFrag(final String url) {
|
||||
String name;
|
||||
String lang = null;
|
||||
|
||||
/*
|
||||
|
|
@ -749,7 +710,7 @@ public class MultilingualItemResolver
|
|||
* from a bundle
|
||||
* 2b if no match is found
|
||||
*/
|
||||
final ArrayList exts = new ArrayList(5);
|
||||
final List<String> exts = new ArrayList<>(5);
|
||||
final StringTokenizer tok = new StringTokenizer(url, ".");
|
||||
|
||||
while (tok.hasMoreTokens()) {
|
||||
|
|
@ -757,10 +718,9 @@ public class MultilingualItemResolver
|
|||
}
|
||||
|
||||
if (exts.size() > 0) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Found some file extensions to look at; they "
|
||||
+ "are " + exts);
|
||||
}
|
||||
LOGGER.debug("Found some file extensions to look at; they "
|
||||
+ "are {}",
|
||||
exts);
|
||||
|
||||
/*
|
||||
* We have found at least one extension, so we can
|
||||
|
|
@ -772,18 +732,16 @@ public class MultilingualItemResolver
|
|||
/*
|
||||
* First element is the NAME of the item, not an extension!
|
||||
*/
|
||||
name = (String) exts.get(0);
|
||||
String ext = null;
|
||||
Collection supportedLangs
|
||||
= LanguageUtil.getSupportedLanguages2LA();
|
||||
Iterator supportedLangIt = null;
|
||||
name = exts.get(0);
|
||||
String ext;
|
||||
final Collection<String> supportedLangs = KernelConfig.getConfig()
|
||||
.getSupportedLanguages();
|
||||
Iterator<String> supportedLangIt;
|
||||
|
||||
for (int i = 1; i < exts.size(); i++) {
|
||||
ext = (String) exts.get(i);
|
||||
ext = exts.get(i);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Examining extension " + ext);
|
||||
}
|
||||
LOGGER.debug("Examining extension {}", ext);
|
||||
|
||||
/*
|
||||
* Loop through all extensions, but discard the
|
||||
|
|
@ -801,37 +759,26 @@ public class MultilingualItemResolver
|
|||
while (supportedLangIt.hasNext()) {
|
||||
if (ext.equals(supportedLangIt.next())) {
|
||||
lang = ext;
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Found a match; using "
|
||||
+ "language " + lang);
|
||||
}
|
||||
LOGGER.debug("Found a match; using "
|
||||
+ "language {}", lang);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Discarding extension " + ext + "; "
|
||||
+ "it is too short");
|
||||
}
|
||||
LOGGER.debug("Discarding extension {}; it is too short",
|
||||
ext);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGGER.debug("The file has no extensions; no language was "
|
||||
+ "encoded");
|
||||
LOGGER.debug("The file has no extensions; no language was encoded");
|
||||
name = url; // no extension, so we just have a name here
|
||||
lang = null; // no extension, so we cannot guess the language
|
||||
}
|
||||
|
||||
if (Assert.isEnabled()) {
|
||||
Assert.exists(name, "String name");
|
||||
Assert.exists(lang == null || lang.length() == 2);
|
||||
}
|
||||
LOGGER.debug("File name resolved to {}", name);
|
||||
LOGGER.debug("File language resolved to {}", lang);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("File name resolved to " + name);
|
||||
LOGGER.debug("File language resolved to " + lang);
|
||||
}
|
||||
String[] returnArray = new String[2];
|
||||
final String[] returnArray = new String[2];
|
||||
returnArray[0] = name;
|
||||
returnArray[1] = lang;
|
||||
return returnArray;
|
||||
|
|
@ -839,62 +786,17 @@ public class MultilingualItemResolver
|
|||
|
||||
/**
|
||||
* Finds a language instance of a content item given the bundle, name, and
|
||||
* lang string
|
||||
* lang string. Note: Because there not ContentBundles anymore this method
|
||||
* simply returns the provided item.
|
||||
*
|
||||
* @param lang The lang string from the URL
|
||||
* @param item The content bundle
|
||||
*
|
||||
* @return The negotiated lang instance for the current request.
|
||||
*/
|
||||
protected ContentItem getItemFromLangAndBundle(String lang, ContentItem item) {
|
||||
if (item != null && item instanceof ContentBundle) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Found content bundle " + item);
|
||||
}
|
||||
if (lang == null) {
|
||||
LOGGER.debug("The URL has no language encoded in it; "
|
||||
+ "negotiating the language");
|
||||
// There is no language, so we get the negotiated locale and call
|
||||
// this method again with a proper language
|
||||
return this.getItemFromLangAndBundle(GlobalizationHelper.
|
||||
getNegotiatedLocale().getLanguage(), item);
|
||||
} else {
|
||||
LOGGER.debug("The URL is encoded with a langauge; "
|
||||
+ "fetching the appropriate item from "
|
||||
+ "the bundle");
|
||||
/*
|
||||
* So the request contains a language code as an
|
||||
* extension of the "name" ==>go ahead and try to
|
||||
* find the item from its ContentBundle. Fail if
|
||||
* the bundle does not contain an instance for the
|
||||
* given language.
|
||||
*/
|
||||
|
||||
final ContentItem resolved
|
||||
= ((ContentBundle) item).getInstance(lang);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Resolved URL to item " + resolved);
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.
|
||||
debug("I expected to get a content bundle; I got "
|
||||
+ item);
|
||||
}
|
||||
|
||||
/*
|
||||
* We expected something like a Bundle, but it seems
|
||||
* like we got something completely different... just
|
||||
* return this crap and let other people's code deal
|
||||
* with it ;-).
|
||||
*
|
||||
* NOTE: This should never happen :-)
|
||||
*/
|
||||
return item; // might be null
|
||||
}
|
||||
protected ContentItem getItemFromLangAndBundle(final String lang,
|
||||
final ContentItem item) {
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,56 +18,78 @@
|
|||
*/
|
||||
package com.arsdigita.cms.dispatcher;
|
||||
|
||||
|
||||
import com.arsdigita.bebop.Page;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.cms.CMS;
|
||||
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
import org.librecms.contentsection.ContentSection;
|
||||
import org.librecms.contentsection.Folder;
|
||||
import com.arsdigita.cms.ContentCenter;
|
||||
|
||||
import com.arsdigita.cms.ui.ContentItemPage;
|
||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
||||
import org.apache.log4j.Logger;
|
||||
import com.arsdigita.web.URL;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.core.CcmObject;
|
||||
import org.librecms.CmsConstants;
|
||||
import org.librecms.contentsection.ContentItemManager;
|
||||
import org.librecms.contentsection.ContentItemRepository;
|
||||
import org.librecms.contentsection.ContentItemVersion;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* <p>This is the default implementation of
|
||||
* {@link com.arsdigita.cms.dispatcher.ItemResolver}.</p>
|
||||
* This is the default implementation of
|
||||
* {@link com.arsdigita.cms.dispatcher.ItemResolver}.
|
||||
*
|
||||
* <p>The <tt>getItem</tt> method of the default implementation of
|
||||
* <tt>ItemResolver</tt>,
|
||||
* {@link com.arsdigita.cms.dispatcher.SimpleItemResolver}
|
||||
* runs a simple query using the passed in information to retrieve the
|
||||
* content item with a name that matches the URL stub, in our example
|
||||
* it looks for a content item with name <tt>cheese</tt>. If no such item
|
||||
* exists, or if there is such an item, but without a live version, even
|
||||
* though one has been requested, <tt>getItem</tt> returns <tt>null</tt>.</p>
|
||||
* The {@link #getItem(java.lang.String, org.librecms.contentsection.Folder) }
|
||||
* method of the default implementation of {@link ItemResolver},
|
||||
* {@link com.arsdigita.cms.dispatcher.SimpleItemResolver} runs a simple query
|
||||
* using the passed in information to retrieve the content item with a name that
|
||||
* matches the URL stub, in our example it looks for a content item with name
|
||||
* {@code cheese}. If no such item exists, or if there is such an item, but
|
||||
* without a live version, even though one has been requested, {@code getItem}
|
||||
* returns {@code null}.
|
||||
*
|
||||
* <p>After the CMS Dispatcher received the content item from the
|
||||
* <tt>ItemResolver</tt>, it also asks it for the
|
||||
* {@link com.arsdigita.cms.dispatcher.MasterPage} for that item in the
|
||||
* current request. With the content item and the master page in hand,
|
||||
* the dispatcher calls <tt>service</tt> on the page.</p>
|
||||
* After the CMS Dispatcher received the content item from the
|
||||
* {@link ItemResolver}, it also asks it for the
|
||||
* {@link com.arsdigita.cms.dispatcher.MasterPage} for that item in the current
|
||||
* request. With the content item and the master page in hand, the dispatcher
|
||||
* calls {@code service} on the page.
|
||||
*
|
||||
* <strong>
|
||||
* AS of version 7.0.0 this class not longer part of the public API. It is left
|
||||
* here to keep the changes to the UI classes as minimal as possible. For new
|
||||
* code other methods, for example from the {@link ContentItemManager} or
|
||||
* the {@link ContentItemRepository} should be used. Because this class is no
|
||||
* longer part of the public API the will might be removed or changed in future
|
||||
* releases without prior warning.
|
||||
* </strong>
|
||||
*
|
||||
* @author Michael Pih (pihman@arsdigita.com)
|
||||
* @version $Revision: #15 $ $DateTime: 2004/08/17 23:15:09 $
|
||||
* @version $Id: SimpleItemResolver.java 2090 2010-04-17 08:04:14Z pboy $
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
public class SimpleItemResolver extends AbstractItemResolver implements ItemResolver {
|
||||
public class SimpleItemResolver
|
||||
extends AbstractItemResolver
|
||||
implements ItemResolver {
|
||||
|
||||
private static final Logger s_log =
|
||||
Logger.getLogger(SimpleItemResolver.class.getName());
|
||||
private static final Logger LOGGER = LogManager.getLogger(
|
||||
SimpleItemResolver.class.getName());
|
||||
|
||||
private static final String ADMIN_PREFIX = "admin";
|
||||
private static final String WORKSPACE_PREFIX = ContentCenter.getURL();
|
||||
private static final String WORKSPACE_PREFIX
|
||||
= CmsConstants.CONTENT_CENTER_URL;
|
||||
|
||||
private static MasterPage s_masterP = null;
|
||||
private static MasterPage masterPage = null;
|
||||
|
||||
public SimpleItemResolver() {}
|
||||
public SimpleItemResolver() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a content item based on page state (and content section).
|
||||
|
|
@ -75,17 +97,20 @@ public class SimpleItemResolver extends AbstractItemResolver implements ItemReso
|
|||
* @param section The current content section
|
||||
* @param url The section-relative URL
|
||||
* @param context The LIVE/DRAFT context (*not* the template use context)
|
||||
* @return The content item mapped to the content section and URL, or
|
||||
* null if no such item exists
|
||||
*
|
||||
* @return The content item mapped to the content section and URL, or null
|
||||
* if no such item exists
|
||||
*/
|
||||
public ContentItem getItem(ContentSection section, String url,
|
||||
String context) {
|
||||
@Override
|
||||
public ContentItem getItem(final ContentSection section,
|
||||
final String url,
|
||||
final String context) {
|
||||
|
||||
if (s_log.isDebugEnabled()) {
|
||||
s_log.debug("trying to get " + context + " item for url " + url);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("trying to get " + context + " item for url " + url);
|
||||
}
|
||||
|
||||
String itemUrl = stripTemplateFromURL(url);
|
||||
final String itemUrl = stripTemplateFromURL(url);
|
||||
|
||||
// getItem fails if called from a JSP template, because the request URL
|
||||
// gets replaced with the filesystem path to the JSP (when
|
||||
|
|
@ -95,58 +120,36 @@ public class SimpleItemResolver extends AbstractItemResolver implements ItemReso
|
|||
ContentItem reqItem = (ContentItem) DispatcherHelper.getRequest().
|
||||
getAttribute("com.arsdigita.cms.dispatcher.item");
|
||||
if (reqItem != null) {
|
||||
s_log.info("found item in the request, returning it");
|
||||
LOGGER.info("found item in the request, returning it");
|
||||
return reqItem;
|
||||
}
|
||||
|
||||
//ContentItem item = getCachedItem(section, itemUrl, context);
|
||||
//if (item != null) {
|
||||
// return item;
|
||||
//}
|
||||
|
||||
Folder rootFolder = section.getRootFolder();
|
||||
if ( rootFolder == null ) {
|
||||
s_log.info("no root folder found, returning null");
|
||||
final Folder rootFolder = section.getRootDocumentsFolder();
|
||||
if (rootFolder == null) {
|
||||
LOGGER.info("no root folder found, returning null");
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( context.equals(ContentItem.LIVE) ) {
|
||||
rootFolder = (Folder) rootFolder.getLiveVersion();
|
||||
if ( rootFolder == null ) {
|
||||
s_log.info("no LIVE version of root folder found, returning null");
|
||||
return null;
|
||||
}
|
||||
} else if ( context.equals(ContentItem.DRAFT) ) {
|
||||
// Do nothing ?
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"getItem: Invalid item resolver context " + context);
|
||||
}
|
||||
|
||||
ContentItem item = getItem(itemUrl, rootFolder);
|
||||
//if (item != null) {
|
||||
// cacheItem(section, itemUrl, context, item);
|
||||
//}
|
||||
|
||||
return item;
|
||||
}
|
||||
return getItem(itemUrl, rootFolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state the current page state
|
||||
*
|
||||
* @return the context of the current URL, such as "live" or "admin"
|
||||
*/
|
||||
public String getCurrentContext(PageState state) {
|
||||
@Override
|
||||
public String getCurrentContext(final PageState state) {
|
||||
|
||||
String url = state.getRequest().getRequestURI();
|
||||
|
||||
ContentSection section =
|
||||
CMS.getContext().getContentSection();
|
||||
final ContentSection section = CMS.getContext().getContentSection();
|
||||
|
||||
// If this page is associated with a content section, transform
|
||||
// the URL so that it is relative to the content section site node.
|
||||
if ( section != null ) {
|
||||
String sectionURL = section.getURL();
|
||||
if ( url.startsWith(sectionURL) ) {
|
||||
if (section != null) {
|
||||
final String sectionURL = section.getPrimaryUrl();
|
||||
if (url.startsWith(sectionURL)) {
|
||||
url = url.substring(sectionURL.length());
|
||||
}
|
||||
}
|
||||
|
|
@ -156,176 +159,256 @@ public class SimpleItemResolver extends AbstractItemResolver implements ItemReso
|
|||
url = stripTemplateFromURL(url);
|
||||
|
||||
// Determine if we are under the admin UI.
|
||||
if ( url.startsWith(ADMIN_PREFIX) ||
|
||||
url.startsWith(WORKSPACE_PREFIX) ) {
|
||||
return ContentItem.DRAFT;
|
||||
if (url.startsWith(ADMIN_PREFIX) || url.startsWith(WORKSPACE_PREFIX)) {
|
||||
return ContentItemVersion.DRAFT.toString();
|
||||
} else {
|
||||
return ContentItem.LIVE;
|
||||
return ContentItemVersion.LIVE.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content item at the specified path, or null
|
||||
* if no such item exists. The path is interpreted as a series
|
||||
* of folders; for example, "/foo/bar/baz" will look for
|
||||
* an item named "baz" in a folder named "bar" in a folder named "foo"
|
||||
* under the specified root folder.
|
||||
* Return the content item at the specified path, or null if no such item
|
||||
* exists. The path is interpreted as a series of folders; for example,
|
||||
* "/foo/bar/baz" will look for an item named "baz" in a folder named "bar"
|
||||
* in a folder named "foo" under the specified root folder.
|
||||
*
|
||||
* @param url the URL to the item
|
||||
* @param url the URL to the item
|
||||
* @param rootFolder The root folder where the item search will start
|
||||
*
|
||||
* @return the item on success, null if no such item exists
|
||||
* @pre rootFolder != null
|
||||
* @pre url != null
|
||||
*/
|
||||
public ContentItem getItem(String url, Folder rootFolder) {
|
||||
public ContentItem getItem(final String url, final Folder rootFolder) {
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(url, "/");
|
||||
String name = null;
|
||||
Folder oldFolder = null;
|
||||
final String[] tokens = url.split("/");
|
||||
|
||||
while(rootFolder != null && tokenizer.hasMoreTokens()) {
|
||||
name = tokenizer.nextToken();
|
||||
oldFolder = rootFolder;
|
||||
rootFolder = (Folder)rootFolder.getItem(name, true);
|
||||
Folder currentFolder = rootFolder;
|
||||
int i;
|
||||
for (i = 0; i < tokens.length; i++) {
|
||||
final String token = tokens[i];
|
||||
final Optional<Folder> folder = currentFolder.getSubFolders()
|
||||
.stream()
|
||||
.filter(subFolder -> subFolder.getDisplayName().equals(token))
|
||||
.findFirst();
|
||||
|
||||
if (folder.isPresent()) {
|
||||
currentFolder = folder.get();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(tokenizer.hasMoreTokens()) {
|
||||
if (i >= tokens.length - 1) {
|
||||
// failure
|
||||
s_log.debug("no more tokens found, returning null");
|
||||
LOGGER.debug("no more tokens found, returning null");
|
||||
return null;
|
||||
} else {
|
||||
// Get the content item which is the last token
|
||||
if (rootFolder != null ) {
|
||||
ContentItem indexItem = rootFolder.getIndexItem();
|
||||
if (indexItem != null) {
|
||||
s_log.info("returning index item for folder");
|
||||
return indexItem;
|
||||
}
|
||||
}
|
||||
if ( name == null ) {
|
||||
s_log.debug("no name found");
|
||||
//Get the content item which is the last token
|
||||
final String name = tokens[tokens.length - 1];
|
||||
final Optional<CcmObject> item = currentFolder.getObjects()
|
||||
.stream()
|
||||
.map(categorization -> categorization.getCategorizedObject())
|
||||
.filter(object -> object.getDisplayName().equals(name))
|
||||
.findFirst();
|
||||
if (item.isPresent() && item.get() instanceof ContentItem) {
|
||||
return (ContentItem) item.get();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return oldFolder.getItem(name, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the URL for an item in the DRAFT context
|
||||
private String generateDraftURL(BigDecimal itemId, ContentSection section) {
|
||||
return ContentItemPage.getItemURL(section.getFullPath() + "/", itemId,
|
||||
ContentItemPage.AUTHORING_TAB);
|
||||
/**
|
||||
* Generate the URL for an item in the DRAFT context
|
||||
*
|
||||
* @param itemId
|
||||
* @param section
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String generateDraftURL(final Long itemId,
|
||||
final ContentSection section) {
|
||||
return ContentItemPage.getItemURL(
|
||||
String.format("%s%s/",
|
||||
URL.getDispatcherPath(),
|
||||
section.getPrimaryUrl()),
|
||||
itemId,
|
||||
ContentItemPage.AUTHORING_TAB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the URL for an item in the LIVE context with a given template
|
||||
* context
|
||||
*
|
||||
* @param item
|
||||
* @param section
|
||||
* @param templateContext
|
||||
*
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
private String generateLiveURL(final ContentItem item,
|
||||
final ContentSection section,
|
||||
final String templateContext) {
|
||||
|
||||
// Generate the URL for an item in the LIVE context with a given template context
|
||||
private String generateLiveURL(ContentItem item, ContentSection section,
|
||||
String templateContext) {
|
||||
String templateURLFrag =
|
||||
(templateContext == null || templateContext.length() == 0) ?
|
||||
"" : TEMPLATE_CONTEXT_PREFIX + templateContext + "/";
|
||||
return section.getPath() + "/" + templateURLFrag + item.getPath();
|
||||
final String templateUrlFrag;
|
||||
if (templateContext == null || templateContext.isEmpty()) {
|
||||
templateUrlFrag = "";
|
||||
} else {
|
||||
templateUrlFrag = String.format(TEMPLATE_CONTEXT_PREFIX + "%s/",
|
||||
templateContext);
|
||||
}
|
||||
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final ContentItemManager itemManager = cdiUtil.findBean(
|
||||
ContentItemManager.class);
|
||||
|
||||
return String.format("%s/%s%s",
|
||||
section.getPrimaryUrl(),
|
||||
templateUrlFrag,
|
||||
itemManager.getItemPath(item));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the preview URL for an item in the DRAFT context.
|
||||
*
|
||||
* @param item
|
||||
* @param section
|
||||
* @param templateContext
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String generatePreviewURL(final ContentItem item,
|
||||
final ContentSection section,
|
||||
final String templateContext) {
|
||||
final String templateUrlFrag;
|
||||
if (templateContext == null || templateContext.isEmpty()) {
|
||||
templateUrlFrag = "";
|
||||
} else {
|
||||
templateUrlFrag = String.format(TEMPLATE_CONTEXT_PREFIX + "%s/",
|
||||
templateContext);
|
||||
}
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final ContentItemManager itemManager = cdiUtil.findBean(
|
||||
ContentItemManager.class);
|
||||
|
||||
// Generate the preview URL for an item in the DRAFT context
|
||||
private String generatePreviewURL(ContentItem item, ContentSection section,
|
||||
String templateContext) {
|
||||
String templateURLFrag =
|
||||
(templateContext == null || templateContext.length() == 0) ?
|
||||
"" : TEMPLATE_CONTEXT_PREFIX + templateContext + "/";
|
||||
StringBuffer url = new StringBuffer();
|
||||
final StringBuilder url = new StringBuilder();
|
||||
url
|
||||
.append(section.getPath())
|
||||
.append("/" + CMSDispatcher.PREVIEW)
|
||||
.append(section.getPrimaryUrl())
|
||||
.append("/")
|
||||
.append(templateURLFrag)
|
||||
.append(item.getPath());
|
||||
.append(CMSDispatcher.PREVIEW)
|
||||
.append("/")
|
||||
.append(templateUrlFrag)
|
||||
.append(itemManager.getItemPath(item));
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a URL for a content item.
|
||||
*
|
||||
* @param itemId The item ID
|
||||
* @param name The name of the content page
|
||||
* @param state The page state
|
||||
* @param itemId The item ID
|
||||
* @param name The name of the content page
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "LIVE" or "DRAFT"
|
||||
*
|
||||
* @return The URL of the item
|
||||
* @pre context != null
|
||||
*/
|
||||
public String generateItemURL(PageState state, BigDecimal itemId,
|
||||
String name, ContentSection section,
|
||||
String context) {
|
||||
@Override
|
||||
public String generateItemURL(final PageState state,
|
||||
final Long itemId,
|
||||
final String name,
|
||||
final ContentSection section,
|
||||
final String context) {
|
||||
return generateItemURL(state, itemId, name, section, context, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a URL for a content item.
|
||||
*
|
||||
* @param itemId The item ID
|
||||
* @param name The name of the content page
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "live" or "admin"
|
||||
* @param itemId The item ID
|
||||
* @param name The name of the content page
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "live" or "admin"
|
||||
* @param templateContext the context for the URL, such as "public"
|
||||
*
|
||||
* @return The URL of the item
|
||||
* @pre context != null
|
||||
*/
|
||||
public String generateItemURL(PageState state, BigDecimal itemId,
|
||||
String name, ContentSection section,
|
||||
String context, String templateContext) {
|
||||
if ( ContentItem.DRAFT.equals(context) ) {
|
||||
@Override
|
||||
public String generateItemURL(final PageState state,
|
||||
final Long itemId,
|
||||
final String name,
|
||||
final ContentSection section,
|
||||
final String context,
|
||||
final String templateContext) {
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final ContentItemRepository itemRepo = cdiUtil.findBean(
|
||||
ContentItemRepository.class);
|
||||
|
||||
if (ContentItemVersion.DRAFT.toString().equals(context)) {
|
||||
return generateDraftURL(itemId, section);
|
||||
} else if (ContentItem.LIVE.equals(context)) {
|
||||
ContentItem item = new ContentItem(itemId);
|
||||
} else if (ContentItemVersion.LIVE.toString().equals(context)) {
|
||||
final ContentItem item = itemRepo.findById(itemId);
|
||||
return generateLiveURL(item, section, templateContext);
|
||||
} else if (CMSDispatcher.PREVIEW.equals(context)) {
|
||||
ContentItem item = new ContentItem(itemId);
|
||||
final ContentItem item = itemRepo.findById(itemId);
|
||||
return generatePreviewURL(item, section, templateContext);
|
||||
} else {
|
||||
throw new RuntimeException( (String) GlobalizationUtil.globalize("cms.dispatcher.unknown_context").localize() + context);
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Unknown context \"%s\".", context));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a URL for a content item.
|
||||
*
|
||||
* @param item The item
|
||||
* @param state The page state
|
||||
* @param item The item
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "LIVE" or "DRAFT"
|
||||
*
|
||||
* @return The URL of the item
|
||||
*
|
||||
* @see #getCurrentContext
|
||||
*/
|
||||
public String generateItemURL (
|
||||
PageState state, ContentItem item, ContentSection section, String context
|
||||
) {
|
||||
@Override
|
||||
public String generateItemURL(final PageState state,
|
||||
final ContentItem item,
|
||||
final ContentSection section,
|
||||
final String context) {
|
||||
return generateItemURL(state, item, section, context, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a URL for a content item.
|
||||
*
|
||||
* @param item The item
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "live" or "admin"
|
||||
* @param item The item
|
||||
* @param state The page state
|
||||
* @param section the content section to which the item belongs
|
||||
* @param context the context of the URL, such as "live" or "admin"
|
||||
* @param templateContext the context for the URL, such as "public"
|
||||
*
|
||||
* @return The URL of the item
|
||||
*
|
||||
* @see #getCurrentContext
|
||||
*/
|
||||
public String generateItemURL (
|
||||
PageState state, ContentItem item, ContentSection section,
|
||||
String context, String templateContext
|
||||
) {
|
||||
if (ContentItem.LIVE.equals(context)) {
|
||||
@Override
|
||||
public String generateItemURL(final PageState state,
|
||||
final ContentItem item,
|
||||
final ContentSection section,
|
||||
final String context,
|
||||
final String templateContext) {
|
||||
|
||||
if (ContentItemVersion.LIVE.toString().equals(context)) {
|
||||
return generateLiveURL(item, section, templateContext);
|
||||
} else if (ContentItem.DRAFT.equals(context)) {
|
||||
return generateDraftURL(item.getID(), section);
|
||||
} else if (ContentItemVersion.DRAFT.toString().equals(context)) {
|
||||
return generateDraftURL(item.getObjectId(), section);
|
||||
} else if (CMSDispatcher.PREVIEW.equals(context)) {
|
||||
return generatePreviewURL(item, section, templateContext);
|
||||
} else {
|
||||
throw new RuntimeException( (String) GlobalizationUtil.globalize("cms.dispatcher.unknown_context").localize() + context);
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Unknown context \"%s\".", context));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -334,16 +417,20 @@ public class SimpleItemResolver extends AbstractItemResolver implements ItemReso
|
|||
*
|
||||
* @param item The content item
|
||||
* @param request The HTTP request
|
||||
*
|
||||
* @throws javax.servlet.ServletException
|
||||
*/
|
||||
public CMSPage getMasterPage(ContentItem item, HttpServletRequest request)
|
||||
@Override
|
||||
public CMSPage getMasterPage(final ContentItem item,
|
||||
final HttpServletRequest request)
|
||||
throws ServletException {
|
||||
|
||||
if ( s_masterP == null ) {
|
||||
s_masterP = new MasterPage();
|
||||
s_masterP.init();
|
||||
if (masterPage == null) {
|
||||
masterPage = new MasterPage();
|
||||
masterPage.init();
|
||||
}
|
||||
|
||||
return s_masterP;
|
||||
return masterPage;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,9 @@ import com.arsdigita.bebop.event.FormProcessListener;
|
|||
import com.arsdigita.bebop.event.FormSectionEvent;
|
||||
import com.arsdigita.bebop.Label;
|
||||
import com.arsdigita.bebop.list.ListCellRenderer;
|
||||
|
||||
import org.librecms.contentsection.ContentType;
|
||||
|
||||
import com.arsdigita.cms.ItemSelectionModel;
|
||||
import com.arsdigita.cms.ui.ContentItemPage;
|
||||
import com.arsdigita.cms.ui.item.ItemWorkflowRequestLocal;
|
||||
|
|
@ -46,13 +48,13 @@ import com.arsdigita.cms.ui.workflow.TaskFinishForm;
|
|||
import com.arsdigita.cms.ui.workflow.TaskRequestLocal;
|
||||
import com.arsdigita.cms.ui.workflow.WorkflowRequestLocal;
|
||||
import com.arsdigita.globalization.GlobalizedMessage;
|
||||
import com.arsdigita.kernel.KernelConfig;
|
||||
import com.arsdigita.toolbox.ui.LayoutPanel;
|
||||
import com.arsdigita.toolbox.ui.ModalPanel;
|
||||
import com.arsdigita.toolbox.ui.Section;
|
||||
import com.arsdigita.util.Assert;
|
||||
import com.arsdigita.util.SequentialMap;
|
||||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
|
@ -60,9 +62,9 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.arsdigita.cms.CMSConfig;
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
|
|
|
|||
|
|
@ -21,26 +21,20 @@ package com.arsdigita.cms.ui.authoring;
|
|||
import com.arsdigita.bebop.Component;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.Resettable;
|
||||
import com.arsdigita.bebop.SimpleContainer;
|
||||
import com.arsdigita.bebop.SingleSelectionModel;
|
||||
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
||||
import com.arsdigita.bebop.parameters.LongParameter;
|
||||
import com.arsdigita.bebop.parameters.StringParameter;
|
||||
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
import org.librecms.contentsection.ContentType;
|
||||
|
||||
import com.arsdigita.cms.ItemSelectionModel;
|
||||
import com.arsdigita.toolbox.ui.LayoutPanel;
|
||||
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
||||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
import com.arsdigita.xml.Element;
|
||||
|
||||
import oracle.jrockit.jfr.events.ContentTypeImpl;
|
||||
import org.librecms.contenttypes.AuthoringKit;
|
||||
import org.librecms.contenttypes.AuthoringKitInfo;
|
||||
import org.librecms.contenttypes.ContentTypeInfo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* An invisible component which contains all the possible authoring kits. The
|
||||
|
|
@ -55,7 +49,7 @@ import java.math.BigDecimal;
|
|||
* @author unknown
|
||||
*/
|
||||
public class WizardSelector extends AuthoringKitSelector
|
||||
implements Resettable {
|
||||
implements Resettable {
|
||||
|
||||
private final ItemSelectionModel itemSelectionModel;
|
||||
|
||||
|
|
@ -63,11 +57,11 @@ public class WizardSelector extends AuthoringKitSelector
|
|||
* Construct a new WizardSelector. Load all the possible authoring kits from
|
||||
* the database and construct wizards for them.
|
||||
*
|
||||
* @param model the {@link ItemSelectionModel} which will supply the wizard
|
||||
* with its item
|
||||
* @param model the {@link ItemSelectionModel} which will supply the
|
||||
* wizard with its item
|
||||
*
|
||||
* @param typeModel the {@link ACSObjectSelectionModel} which will supply
|
||||
* the default content type
|
||||
* the default content type
|
||||
*
|
||||
* @pre itemModel != null
|
||||
*/
|
||||
|
|
@ -83,6 +77,7 @@ public class WizardSelector extends AuthoringKitSelector
|
|||
*
|
||||
* @param kit
|
||||
* @param type
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
|
|
@ -90,9 +85,10 @@ public class WizardSelector extends AuthoringKitSelector
|
|||
final ContentTypeInfo type) {
|
||||
|
||||
final ItemSelectionModel itemModel = new ItemSelectionModel(
|
||||
type, (LongParameter) itemSelectionModel.getStateParameter());
|
||||
type, (LongParameter) itemSelectionModel.getStateParameter());
|
||||
|
||||
final AuthoringKitWizard wizard = new AuthoringKitWizard(type, itemModel);
|
||||
final AuthoringKitWizard wizard
|
||||
= new AuthoringKitWizard(type, itemModel);
|
||||
return wizard;
|
||||
}
|
||||
|
||||
|
|
@ -111,8 +107,7 @@ public class WizardSelector extends AuthoringKitSelector
|
|||
throw new UncheckedWrapperException("No item selected.");
|
||||
}
|
||||
|
||||
final ContentItem item = (ContentItem) itemSelectionModel
|
||||
.getSelectedObject(state);
|
||||
final ContentItem item = itemSelectionModel.getSelectedObject(state);
|
||||
|
||||
final ContentType type = item.getContentType();
|
||||
final String typeClass;
|
||||
|
|
@ -128,7 +123,7 @@ public class WizardSelector extends AuthoringKitSelector
|
|||
}
|
||||
|
||||
// Return the selected wizard
|
||||
return (Component) getComponent(typeClass);
|
||||
return getComponent(typeClass);
|
||||
}
|
||||
|
||||
// Choose the right wizard and run it
|
||||
|
|
|
|||
|
|
@ -65,76 +65,83 @@ import static org.librecms.CmsConstants.*;
|
|||
@Table(name = "CONTENT_ITEMS", schema = DB_SCHEMA)
|
||||
@NamedQueries({
|
||||
@NamedQuery(
|
||||
name = "ContentItem.findByType",
|
||||
query = "SELECT i FROM ContentItem i WHERE TYPE(i) = :type")
|
||||
name = "ContentItem.findByType",
|
||||
query = "SELECT i FROM ContentItem i WHERE TYPE(i) = :type")
|
||||
,
|
||||
@NamedQuery(
|
||||
name = "ContentItem.findByFolder",
|
||||
query = "SELECT i FROM ContentItem i "
|
||||
+ "JOIN i.categories c "
|
||||
+ "WHERE c.category = :folder "
|
||||
+ "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER
|
||||
name = "ContentItem.findByFolder",
|
||||
query = "SELECT i FROM ContentItem i "
|
||||
+ "JOIN i.categories c "
|
||||
+ "WHERE c.category = :folder "
|
||||
+ "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER
|
||||
+ "'")
|
||||
,
|
||||
@NamedQuery(
|
||||
name = "ContentItem.countItemsInFolder",
|
||||
query = "SELECT count(i) FROM ContentItem i "
|
||||
+ "JOIN i.categories c "
|
||||
+ "WHERE c.category = :folder "
|
||||
+ "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER
|
||||
name = "ContentItem.countItemsInFolder",
|
||||
query = "SELECT count(i) FROM ContentItem i "
|
||||
+ "JOIN i.categories c "
|
||||
+ "WHERE c.category = :folder "
|
||||
+ "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER
|
||||
+ "'")
|
||||
,
|
||||
@NamedQuery(
|
||||
name = "ContentItem.countByNameInFolder",
|
||||
query = "SELECT COUNT(i) FROM ContentItem i "
|
||||
+ "JOIN i.categories c "
|
||||
+ "WHERE c.category = :folder "
|
||||
+ "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER
|
||||
+ "' "
|
||||
+ "AND i.displayName = :name")
|
||||
name = "ContentItem.findByNameInFolder",
|
||||
query = "SELECT i FROM ContentItem i "
|
||||
+ "JOIN i.categories c "
|
||||
+ "WHERE c.category = :folder "
|
||||
+ "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' "
|
||||
+ "AND i.displayName = :name")
|
||||
,
|
||||
@NamedQuery(
|
||||
name = "ContentItem.filterByFolderAndName",
|
||||
query = "SELECT i FROM ContentItem i "
|
||||
+ "JOIN i.categories c "
|
||||
+ "WHERE c.category = :folder "
|
||||
+ "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER
|
||||
+ "' "
|
||||
+ "AND LOWER(i.displayName) LIKE CONCAT(LOWER(:name), '%')")
|
||||
name = "ContentItem.countByNameInFolder",
|
||||
query = "SELECT COUNT(i) FROM ContentItem i "
|
||||
+ "JOIN i.categories c "
|
||||
+ "WHERE c.category = :folder "
|
||||
+ "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' "
|
||||
+ "AND i.displayName = :name")
|
||||
,
|
||||
@NamedQuery(
|
||||
name = "ContentItem.countFilterByFolderAndName",
|
||||
query = "SELECT COUNT(i) FROM ContentItem i "
|
||||
+ "JOIN i.categories c "
|
||||
+ "WHERE c.category = :folder "
|
||||
+ "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER
|
||||
name = "ContentItem.filterByFolderAndName",
|
||||
query = "SELECT i FROM ContentItem i "
|
||||
+ "JOIN i.categories c "
|
||||
+ "WHERE c.category = :folder "
|
||||
+ "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER
|
||||
+ "' "
|
||||
+ "AND LOWER(i.displayName) LIKE CONCAT(LOWER(:name), '%')"
|
||||
+ "AND LOWER(i.displayName) LIKE CONCAT(LOWER(:name), '%')")
|
||||
,
|
||||
@NamedQuery(
|
||||
name = "ContentItem.countFilterByFolderAndName",
|
||||
query = "SELECT COUNT(i) FROM ContentItem i "
|
||||
+ "JOIN i.categories c "
|
||||
+ "WHERE c.category = :folder "
|
||||
+ "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER
|
||||
+ "' "
|
||||
+ "AND LOWER(i.displayName) LIKE CONCAT(LOWER(:name), '%')"
|
||||
)
|
||||
,
|
||||
@NamedQuery(
|
||||
name = "ContentItem.hasLiveVersion",
|
||||
query = "SELECT (CASE WHEN COUNT(i) > 0 THEN true ELSE false END) "
|
||||
+ "FROM ContentItem i "
|
||||
+ "WHERE i.itemUuid = :uuid "
|
||||
+ "AND i.version = org.librecms.contentsection.ContentItemVersion.LIVE")
|
||||
name = "ContentItem.hasLiveVersion",
|
||||
query = "SELECT (CASE WHEN COUNT(i) > 0 THEN true ELSE false END) "
|
||||
+ "FROM ContentItem i "
|
||||
+ "WHERE i.itemUuid = :uuid "
|
||||
+ "AND i.version = org.librecms.contentsection.ContentItemVersion.LIVE")
|
||||
,
|
||||
@NamedQuery(
|
||||
name = "ContentItem.findDraftVersion",
|
||||
query = "SELECT i FROM ContentItem i "
|
||||
+ "WHERE i.itemUuid = :uuid "
|
||||
+ "AND i.version = org.librecms.contentsection.ContentItemVersion.DRAFT")
|
||||
name = "ContentItem.findDraftVersion",
|
||||
query = "SELECT i FROM ContentItem i "
|
||||
+ "WHERE i.itemUuid = :uuid "
|
||||
+ "AND i.version = org.librecms.contentsection.ContentItemVersion.DRAFT")
|
||||
,
|
||||
@NamedQuery(
|
||||
name = "ContentItem.findLiveVersion",
|
||||
query = "SELECT i FROM ContentItem i "
|
||||
+ "WHERE i.itemUuid = :uuid "
|
||||
+ "AND i.version = org.librecms.contentsection.ContentItemVersion.LIVE")
|
||||
name = "ContentItem.findLiveVersion",
|
||||
query = "SELECT i FROM ContentItem i "
|
||||
+ "WHERE i.itemUuid = :uuid "
|
||||
+ "AND i.version = org.librecms.contentsection.ContentItemVersion.LIVE")
|
||||
,
|
||||
@NamedQuery(
|
||||
name = "ContentItem.findItemWithWorkflow",
|
||||
query = "SELECT i FROM ContentItem i "
|
||||
+ "WHERE i.workflow = :workflow"
|
||||
name = "ContentItem.findItemWithWorkflow",
|
||||
query = "SELECT i FROM ContentItem i "
|
||||
+ "WHERE i.workflow = :workflow"
|
||||
)
|
||||
})
|
||||
public class ContentItem extends CcmObject implements Serializable,
|
||||
|
|
@ -153,13 +160,13 @@ public class ContentItem extends CcmObject implements Serializable,
|
|||
*/
|
||||
@Embedded
|
||||
@AssociationOverride(
|
||||
name = "values",
|
||||
joinTable = @JoinTable(name = "CONTENT_ITEM_NAMES",
|
||||
schema = DB_SCHEMA,
|
||||
joinColumns = {
|
||||
@JoinColumn(name = "OBJECT_ID")
|
||||
}
|
||||
)
|
||||
name = "values",
|
||||
joinTable = @JoinTable(name = "CONTENT_ITEM_NAMES",
|
||||
schema = DB_SCHEMA,
|
||||
joinColumns = {
|
||||
@JoinColumn(name = "OBJECT_ID")
|
||||
}
|
||||
)
|
||||
)
|
||||
private LocalizedString name;
|
||||
|
||||
|
|
@ -176,13 +183,13 @@ public class ContentItem extends CcmObject implements Serializable,
|
|||
*/
|
||||
@Embedded
|
||||
@AssociationOverride(
|
||||
name = "values",
|
||||
joinTable = @JoinTable(name = "CONTENT_ITEM_TITLES",
|
||||
schema = DB_SCHEMA,
|
||||
joinColumns = {
|
||||
@JoinColumn(name = "OBJECT_ID")
|
||||
}
|
||||
)
|
||||
name = "values",
|
||||
joinTable = @JoinTable(name = "CONTENT_ITEM_TITLES",
|
||||
schema = DB_SCHEMA,
|
||||
joinColumns = {
|
||||
@JoinColumn(name = "OBJECT_ID")
|
||||
}
|
||||
)
|
||||
)
|
||||
private LocalizedString title;
|
||||
|
||||
|
|
@ -191,12 +198,12 @@ public class ContentItem extends CcmObject implements Serializable,
|
|||
*/
|
||||
@Embedded
|
||||
@AssociationOverride(
|
||||
name = "values",
|
||||
joinTable = @JoinTable(name = "CONTENT_ITEM_DESCRIPTIONS",
|
||||
schema = DB_SCHEMA,
|
||||
joinColumns = {
|
||||
@JoinColumn(name = "OBJECT_ID")}
|
||||
))
|
||||
name = "values",
|
||||
joinTable = @JoinTable(name = "CONTENT_ITEM_DESCRIPTIONS",
|
||||
schema = DB_SCHEMA,
|
||||
joinColumns = {
|
||||
@JoinColumn(name = "OBJECT_ID")}
|
||||
))
|
||||
private LocalizedString description;
|
||||
|
||||
/**
|
||||
|
|
@ -352,10 +359,10 @@ public class ContentItem extends CcmObject implements Serializable,
|
|||
@Override
|
||||
public Optional<CcmObject> getParent() {
|
||||
final List<Categorization> result = getCategories().stream().filter(
|
||||
categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER.
|
||||
equals(
|
||||
categorization.getType()))
|
||||
.collect(Collectors.toList());
|
||||
categorization -> CmsConstants.CATEGORIZATION_TYPE_FOLDER.
|
||||
equals(
|
||||
categorization.getType()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (result.isEmpty()) {
|
||||
return Optional.empty();
|
||||
|
|
@ -434,15 +441,15 @@ public class ContentItem extends CcmObject implements Serializable,
|
|||
@Override
|
||||
public String toString(final String data) {
|
||||
return super.toString(String.format(", itemUuid = %s, "
|
||||
+ "name = %s, "
|
||||
+ "contentType = { %s }, "
|
||||
+ "title = %s, "
|
||||
+ "description = %s, "
|
||||
+ "version = %s, "
|
||||
+ "launchDate = %s, "
|
||||
+ "lifecycle = { %s }, "
|
||||
+ "workflow = { %s }"
|
||||
+ "%s",
|
||||
+ "name = %s, "
|
||||
+ "contentType = { %s }, "
|
||||
+ "title = %s, "
|
||||
+ "description = %s, "
|
||||
+ "version = %s, "
|
||||
+ "launchDate = %s, "
|
||||
+ "lifecycle = { %s }, "
|
||||
+ "workflow = { %s }"
|
||||
+ "%s",
|
||||
itemUuid,
|
||||
Objects.toString(name),
|
||||
Objects.toString(contentType),
|
||||
|
|
|
|||
|
|
@ -40,11 +40,14 @@ import org.libreccm.workflow.Workflow;
|
|||
*/
|
||||
@RequestScoped
|
||||
public class ContentItemRepository
|
||||
extends AbstractAuditedEntityRepository<Long, ContentItem> {
|
||||
extends AbstractAuditedEntityRepository<Long, ContentItem> {
|
||||
|
||||
@Inject
|
||||
private CcmObjectRepository ccmObjectRepo;
|
||||
|
||||
@Inject
|
||||
private FolderRepository folderRepo;
|
||||
|
||||
@Override
|
||||
public Long getEntityId(final ContentItem item) {
|
||||
return item.getObjectId();
|
||||
|
|
@ -59,7 +62,7 @@ public class ContentItemRepository
|
|||
public boolean isNew(final ContentItem item) {
|
||||
return ccmObjectRepo.isNew(item);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initNewEntity(final ContentItem item) {
|
||||
final String uuid = UUID.randomUUID().toString();
|
||||
|
|
@ -75,7 +78,7 @@ public class ContentItemRepository
|
|||
* @param itemId The id of item to retrieve.
|
||||
*
|
||||
* @return The content item identified by the provided {@code itemId} or
|
||||
* nothing if there is such content item.
|
||||
* nothing if there is such content item.
|
||||
*/
|
||||
public Optional<ContentItem> findById(final long itemId) {
|
||||
final Optional<CcmObject> result = ccmObjectRepo.findObjectById(itemId);
|
||||
|
|
@ -89,13 +92,13 @@ public class ContentItemRepository
|
|||
/**
|
||||
* Finds a content item by its ID and ensures that is a the requested type.
|
||||
*
|
||||
* @param <T> The type of the content item.
|
||||
* @param <T> The type of the content item.
|
||||
* @param itemId The id of item to retrieve.
|
||||
* @param type The type of the content item.
|
||||
* @param type The type of the content item.
|
||||
*
|
||||
* @return The content item identified by the provided id or an empty
|
||||
* {@link Optional} if there is no such item or if it is not of the
|
||||
* requested type.
|
||||
* {@link Optional} if there is no such item or if it is not of the
|
||||
* requested type.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ContentItem> Optional<T> findById(final long itemId,
|
||||
|
|
@ -114,7 +117,7 @@ public class ContentItemRepository
|
|||
* @param uuid The id of item to retrieve.
|
||||
*
|
||||
* @return The content item identified by the provided {@code uuid} or
|
||||
* nothing if there is such content item.
|
||||
* nothing if there is such content item.
|
||||
*/
|
||||
public Optional<ContentItem> findByUuid(final String uuid) {
|
||||
final Optional<CcmObject> result = ccmObjectRepo.findObjectByUuid(uuid);
|
||||
|
|
@ -129,21 +132,21 @@ public class ContentItemRepository
|
|||
* Finds a content item by its UUID and ensures that is a the requested
|
||||
* type.
|
||||
*
|
||||
* @param <T> The type of the content item.
|
||||
* @param <T> The type of the content item.
|
||||
* @param uuid The UUID of item to retrieve.
|
||||
* @param type The type of the content item.
|
||||
*
|
||||
* @return The content item identified by the provided UUID or an empty
|
||||
* {@link Optional} if there is no such item or if it is not of the
|
||||
* requested type.
|
||||
* {@link Optional} if there is no such item or if it is not of the
|
||||
* requested type.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ContentItem> Optional<T> findByUuid(final String uuid,
|
||||
final Class<T> type) {
|
||||
final Optional<CcmObject> result = ccmObjectRepo.findObjectByUuid(uuid);
|
||||
|
||||
if (result.isPresent()
|
||||
&& result.get().getClass().isAssignableFrom(type)) {
|
||||
if (result.isPresent()
|
||||
&& result.get().getClass().isAssignableFrom(type)) {
|
||||
return Optional.of((T) result.get());
|
||||
} else {
|
||||
return Optional.empty();
|
||||
|
|
@ -153,7 +156,7 @@ public class ContentItemRepository
|
|||
/**
|
||||
* Finds all content items of a specific type.
|
||||
*
|
||||
* @param <T> The type of the items.
|
||||
* @param <T> The type of the items.
|
||||
* @param type The type of the items.
|
||||
*
|
||||
* @return A list of all content items of the requested type.
|
||||
|
|
@ -161,7 +164,7 @@ public class ContentItemRepository
|
|||
@SuppressWarnings("unchecked")
|
||||
public <T extends ContentItem> List<T> findByType(final Class<T> type) {
|
||||
final TypedQuery<ContentItem> query = getEntityManager()
|
||||
.createNamedQuery("ContentItem.findByType", ContentItem.class);
|
||||
.createNamedQuery("ContentItem.findByType", ContentItem.class);
|
||||
query.setParameter("type", type);
|
||||
|
||||
return (List<T>) query.getResultList();
|
||||
|
|
@ -176,10 +179,10 @@ public class ContentItemRepository
|
|||
*/
|
||||
public List<ContentItem> findByFolder(final Category folder) {
|
||||
final TypedQuery<ContentItem> query = getEntityManager()
|
||||
.createNamedQuery("ContentItem.findByFolder",
|
||||
ContentItem.class);
|
||||
.createNamedQuery("ContentItem.findByFolder",
|
||||
ContentItem.class);
|
||||
query.setParameter("folder", folder);
|
||||
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
|
|
@ -187,26 +190,43 @@ public class ContentItemRepository
|
|||
* Counts the items in a folder/category.
|
||||
*
|
||||
* @param folder The folder/category
|
||||
*
|
||||
* @return The number of content items in the category/folder.
|
||||
*/
|
||||
public long countItemsInFolder(final Category folder) {
|
||||
final TypedQuery<Long> query = getEntityManager()
|
||||
.createNamedQuery("ContentItem.countItemsInFolder", Long.class);
|
||||
.createNamedQuery("ContentItem.countItemsInFolder", Long.class);
|
||||
query.setParameter("folder", folder);
|
||||
|
||||
return query.getSingleResult();
|
||||
}
|
||||
|
||||
public Optional<ContentItem> findByNameInFolder(final Category folder,
|
||||
final String name) {
|
||||
final TypedQuery<ContentItem> query = getEntityManager()
|
||||
.createNamedQuery("ContentItem.findByNameInFolder",
|
||||
ContentItem.class);
|
||||
query.setParameter("folder", folder);
|
||||
query.setParameter("name", name);
|
||||
|
||||
try {
|
||||
return Optional.of(query.getSingleResult());
|
||||
} catch (NoResultException ex) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of items with a specific name in a folder/category.
|
||||
*
|
||||
* @param folder
|
||||
* @param name
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public long countByNameInFolder(final Category folder, final String name) {
|
||||
final TypedQuery<Long> query = getEntityManager().createNamedQuery(
|
||||
"ContentItem.countByNameInFolder", Long.class);
|
||||
"ContentItem.countByNameInFolder", Long.class);
|
||||
query.setParameter("folder", folder);
|
||||
query.setParameter("name", name);
|
||||
|
||||
|
|
@ -219,14 +239,15 @@ public class ContentItemRepository
|
|||
* pattern.
|
||||
*
|
||||
* @param folder The folder/category whose items are filtered.
|
||||
* @param name The name pattern to use.
|
||||
* @param name The name pattern to use.
|
||||
*
|
||||
* @return A list with all items in the folder matching the provided filter.
|
||||
*/
|
||||
public List<ContentItem> filterByFolderAndName(final Category folder,
|
||||
final String name) {
|
||||
final TypedQuery<ContentItem> query = getEntityManager()
|
||||
.createNamedQuery("ContentItem.filterByFolderAndName",
|
||||
ContentItem.class);
|
||||
.createNamedQuery("ContentItem.filterByFolderAndName",
|
||||
ContentItem.class);
|
||||
query.setParameter("folder", folder);
|
||||
query.setParameter("name", name);
|
||||
|
||||
|
|
@ -238,15 +259,16 @@ public class ContentItemRepository
|
|||
* starts with the provided pattern.
|
||||
*
|
||||
* @param folder The folder/category to use.
|
||||
* @param name The name pattern to use.
|
||||
* @param name The name pattern to use.
|
||||
*
|
||||
* @return The number of items in the folder/category which match the
|
||||
* provided pattern.
|
||||
* provided pattern.
|
||||
*/
|
||||
public long countFilterByFolderAndName(final Category folder,
|
||||
final String name) {
|
||||
final TypedQuery<Long> query = getEntityManager()
|
||||
.createNamedQuery("ContentItem.countFilterByFolderAndName",
|
||||
Long.class);
|
||||
.createNamedQuery("ContentItem.countFilterByFolderAndName",
|
||||
Long.class);
|
||||
query.setParameter("folder", folder);
|
||||
query.setParameter("name", name);
|
||||
|
||||
|
|
@ -255,15 +277,74 @@ public class ContentItemRepository
|
|||
|
||||
public Optional<ContentItem> findItemWithWorkflow(final Workflow workflow) {
|
||||
final TypedQuery<ContentItem> query = getEntityManager()
|
||||
.createNamedQuery("ContentItem.findItemWithWorkflow",
|
||||
ContentItem.class);
|
||||
.createNamedQuery("ContentItem.findItemWithWorkflow",
|
||||
ContentItem.class);
|
||||
query.setParameter("workflow", workflow);
|
||||
|
||||
|
||||
try {
|
||||
return Optional.of(query.getSingleResult());
|
||||
} catch(NoResultException ex) {
|
||||
} catch (NoResultException ex) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds a {@link ContentItem} by its path inside a {@link ContentSection}.
|
||||
*
|
||||
* @param path The path of the item <strong>including</strong> the content
|
||||
* section, separated from the rest of the path by a
|
||||
* <code>:</code>.
|
||||
*
|
||||
* @return An {@link Optional} containing the content item identified by the
|
||||
* provided path or an empty {@code Optional} if there is no such
|
||||
* item.
|
||||
*/
|
||||
public Optional<ContentItem> findByPath(final String path) {
|
||||
//The last token is the name of the item itself. Remove this part an get
|
||||
//the folder containing the item using the FolderRepository.
|
||||
final String normalizedPath = PathUtil.normalizePath(path);
|
||||
final int lastTokenStart = normalizedPath.lastIndexOf('/');
|
||||
final String folderPath = normalizedPath.substring(0, lastTokenStart);
|
||||
final String itemName = normalizedPath.substring(lastTokenStart + 1);
|
||||
|
||||
final Optional<Folder> folder = folderRepo.findByPath(
|
||||
folderPath, FolderType.DOCUMENTS_FOLDER);
|
||||
|
||||
if (folder.isPresent()) {
|
||||
return findByNameInFolder(folder.get(), itemName);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a {@link ContentItem} by its path inside the provided
|
||||
* {@link ContentSection}.
|
||||
*
|
||||
* @param section The section to which the item belongs.
|
||||
* @param path The path of the item inside this content section.
|
||||
*
|
||||
* @return An {@link Optional} containing the content item identified by the
|
||||
* provided path or an empty {@code Optional} if there is no such
|
||||
* item.
|
||||
*/
|
||||
public Optional<ContentItem> findByPath(final ContentSection section,
|
||||
final String path) {
|
||||
//The last token is the name of the item itself. Remove this part an get
|
||||
//the folder containing the item using the FolderRepository.
|
||||
final String normalizedPath = PathUtil.normalizePath(path);
|
||||
final int lastTokenStart = normalizedPath.lastIndexOf('/');
|
||||
final String folderPath = normalizedPath.substring(0, lastTokenStart);
|
||||
final String itemName = normalizedPath.substring(lastTokenStart + 1);
|
||||
|
||||
final Optional<Folder> folder = folderRepo.findByPath(
|
||||
section, folderPath, FolderType.DOCUMENTS_FOLDER);
|
||||
|
||||
if (folder.isPresent()) {
|
||||
return findByNameInFolder(folder.get(), itemName);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,15 +125,17 @@ public class FolderRepository extends AbstractEntityRepository<Long, Folder> {
|
|||
throw new IllegalArgumentException("Path can't be null or empty.");
|
||||
}
|
||||
|
||||
String normalizedPath = path.replace('.', '/');
|
||||
if (normalizedPath.charAt(0) == '/') {
|
||||
normalizedPath = normalizedPath.substring(1);
|
||||
}
|
||||
|
||||
if (normalizedPath.endsWith("/")) {
|
||||
normalizedPath = normalizedPath.substring(0,
|
||||
normalizedPath.length());
|
||||
}
|
||||
// String normalizedPath = path.replace('.', '/');
|
||||
// if (normalizedPath.charAt(0) == '/') {
|
||||
// normalizedPath = normalizedPath.substring(1);
|
||||
// }
|
||||
//
|
||||
// if (normalizedPath.endsWith("/")) {
|
||||
// normalizedPath = normalizedPath.substring(0,
|
||||
// normalizedPath.length());
|
||||
// }
|
||||
//
|
||||
final String normalizedPath = PathUtil.normalizePath(path);
|
||||
|
||||
LOGGER.debug("Trying to find folder with path \"{}\" and type {} in"
|
||||
+ "content section \"{}\".",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.librecms.contentsection;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
public final class PathUtil {
|
||||
|
||||
private PathUtil() {
|
||||
//Nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalises a path so that the path can be easily processed. This is a
|
||||
* helper method used by several classes in this package.
|
||||
*
|
||||
* The method does the following:
|
||||
* <ul>
|
||||
* <li>Replace all "<code>.</code>" in the path with a slash.</li>
|
||||
* <li>If the first character is a slash remove the character.</li>
|
||||
* <li>If the last character is a slash remove the character.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
protected static final String normalizePath(final String path) {
|
||||
String normalizedPath = path.replace('.', '/');
|
||||
if (normalizedPath.charAt(0) == '/') {
|
||||
normalizedPath = normalizedPath.substring(1);
|
||||
}
|
||||
|
||||
if (normalizedPath.endsWith("/")) {
|
||||
normalizedPath = normalizedPath.substring(0,
|
||||
normalizedPath.length());
|
||||
}
|
||||
|
||||
return normalizedPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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.ui;
|
||||
|
||||
import com.arsdigita.bebop.tree.TreeNode;
|
||||
import com.arsdigita.kernel.KernelConfig;
|
||||
import java.util.Locale;
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.l10n.GlobalizationHelper;
|
||||
import org.libreccm.web.CcmApplication;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
public class ApplicationTreeNode implements TreeNode {
|
||||
|
||||
private final CcmApplication application;
|
||||
|
||||
public ApplicationTreeNode(final CcmApplication application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
public CcmApplication getApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getKey() {
|
||||
return application.getPrimaryUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElement() {
|
||||
final GlobalizationHelper globalizationHelper = CdiUtil.createCdiUtil().findBean(GlobalizationHelper.class);
|
||||
final Locale locale = globalizationHelper.getNegotiatedLocale();
|
||||
|
||||
if (application.getTitle().hasValue(locale)) {
|
||||
return application.getTitle().hasValue(locale);
|
||||
} else {
|
||||
final Locale defaultLocale = KernelConfig.getConfig().getDefaultLocale();
|
||||
return application.getTitle().getValue(defaultLocale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.ui;
|
||||
|
||||
import com.arsdigita.bebop.tree.TreeNode;
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.web.CcmApplication;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
class ApplicationTypeTreeNode implements TreeNode {
|
||||
|
||||
private final Class<? extends CcmApplication> appType;
|
||||
|
||||
protected ApplicationTypeTreeNode(
|
||||
final Class<? extends CcmApplication> appType) {
|
||||
|
||||
this.appType = appType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getKey() {
|
||||
return appType.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElement() {
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final PageModelTreeController controller = cdiUtil.findBean(
|
||||
PageModelTreeController.class);
|
||||
|
||||
return controller.getAppTypeTitle(appType);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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.ui;
|
||||
|
||||
import com.arsdigita.bebop.Tree;
|
||||
import com.arsdigita.toolbox.ui.LayoutPanel;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
public class PageModelPane extends LayoutPanel {
|
||||
|
||||
private final Tree tree;
|
||||
|
||||
public PageModelPane() {
|
||||
|
||||
super();
|
||||
|
||||
setClassAttr("sidebarNavPanel");
|
||||
|
||||
tree = new Tree(new PageModelTreeModelBuilder());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.ui;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import org.libreccm.web.ApplicationManager;
|
||||
import org.libreccm.web.ApplicationType;
|
||||
import org.libreccm.web.CcmApplication;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@RequestScoped
|
||||
public class PageModelTreeController {
|
||||
|
||||
@Inject
|
||||
private ApplicationManager applicationManager;
|
||||
|
||||
public String getAppTypeTitle(final Class<? extends CcmApplication> appType) {
|
||||
|
||||
final ApplicationType applicationType = applicationManager.
|
||||
getApplicationTypes().get(appType.getClass().getName());
|
||||
|
||||
return applicationManager.getApplicationTypeTitle(applicationType);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.ui;
|
||||
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.Tree;
|
||||
import com.arsdigita.bebop.tree.TreeModel;
|
||||
import com.arsdigita.bebop.tree.TreeModelBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
class PageModelTreeModelBuilder implements TreeModelBuilder {
|
||||
|
||||
@Override
|
||||
public TreeModel makeModel(final Tree tree, final PageState state) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lock() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocked() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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.ui;
|
||||
|
||||
import com.arsdigita.bebop.tree.TreeNode;
|
||||
import com.arsdigita.kernel.KernelConfig;
|
||||
import java.util.Locale;
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.l10n.GlobalizationHelper;
|
||||
import org.libreccm.pagemodel.PageModel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
class PageModelTreeNode implements TreeNode {
|
||||
|
||||
private final PageModel pageModel;
|
||||
|
||||
protected PageModelTreeNode(final PageModel pageModel) {
|
||||
this.pageModel = pageModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getKey() {
|
||||
return pageModel.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElement() {
|
||||
final GlobalizationHelper globalizationHelper = CdiUtil.createCdiUtil().
|
||||
findBean(GlobalizationHelper.class);
|
||||
final Locale locale = globalizationHelper.getNegotiatedLocale();
|
||||
|
||||
if (pageModel.getTitle().hasValue(locale)) {
|
||||
return pageModel.getTitle().getValue(locale);
|
||||
} else {
|
||||
final Locale defaultLocale = KernelConfig.getConfig().
|
||||
getDefaultLocale();
|
||||
return pageModel.getTitle().getValue(defaultLocale);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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.ui;
|
||||
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.tree.TreeModel;
|
||||
import com.arsdigita.bebop.tree.TreeNode;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.pagemodel.PageModelRepository;
|
||||
import org.libreccm.web.CcmApplication;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
class PageTreeModel implements TreeModel {
|
||||
|
||||
@Override
|
||||
public TreeNode getRoot(final PageState state) {
|
||||
return new RootNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasChildren(final TreeNode node, final PageState state) {
|
||||
if (node instanceof RootNode) {
|
||||
return true;
|
||||
} else if (node instanceof ApplicationTypeTreeNode) {
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final PageModelRepository pageModelRepo = cdiUtil.findBean(
|
||||
PageModelRepository.class);
|
||||
final CcmApplication application = ((ApplicationTreeNode) node)
|
||||
.getApplication();
|
||||
final long count = pageModelRepo.countByApplication(application);
|
||||
|
||||
return count > 0;
|
||||
} else if (node instanceof PageModelTreeNode) {
|
||||
return false;
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Unexpected node type: \"%s\".", node.getClass().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator getChildren(final TreeNode node, final PageState state) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
private class RootNode implements TreeNode {
|
||||
|
||||
@Override
|
||||
public Object getKey() {
|
||||
return "-1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElement() {
|
||||
return "PageModels";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue