diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java.todo
similarity index 56%
rename from ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java.off
rename to ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java.todo
index a632c181a..54446684d 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java.off
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java.todo
@@ -23,7 +23,7 @@ import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ContentCenter;
import com.arsdigita.util.Assert;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
import org.libreccm.categorization.Category;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
@@ -36,121 +36,114 @@ 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.librecms.CmsConstants;
+import org.librecms.contentsection.ContentItemRepository;
+import org.librecms.contentsection.ContentItemVersion;
+import org.librecms.contentsection.Folder;
+import org.librecms.contentsection.FolderManager;
/**
- * Resolves items to URLs and URLs to items for multiple language
- * variants.
+ * Resolves items to URLs and URLs to items for multiple language variants.
*
* Created Mon Jan 20 14:30:03 2003.
*
* @author Michael Hanisch
* @version $Id: MultilingualItemResolver.java 2090 2010-04-17 08:04:14Z pboy $
*/
-public class MultilingualItemResolver
- extends AbstractItemResolver implements ItemResolver {
-
- private static final Logger s_log = Logger.getLogger
- (MultilingualItemResolver.class);
-
+public class MultilingualItemResolver
+ extends AbstractItemResolver implements ItemResolver {
+
+ private static final Logger LOGGER = LogManager.getLogger(
+ MultilingualItemResolver.class);
+
private static MasterPage s_masterP = null;
private static final String ADMIN_PREFIX = "admin";
/**
- * The string identifying an item's ID in the query string of a
- * URL.
+ * The string identifying an item's ID in the query string of a URL.
*/
protected static final String ITEM_ID = "item_id";
-
+
/**
- * The separator used in URL query strings; should be either "&"
- * or ";".
+ * The separator used in URL query strings; should be either "&" or ";".
*/
protected static final String SEPARATOR = "&";
-
+
public MultilingualItemResolver() {
- s_log.debug("Undergoing creation");
+ LOGGER.debug("Undergoing creation");
}
-
+
/**
* Returns a content item based on section, url, and use context.
*
* @param section The current content section
- * @param url The section-relative URL
- * @param context The use context,
- * e.g. ContentItem.LIVE,
- * CMSDispatcher.PREVIEW or
- * ContentItem.DRAFT. See {@link
+ * @param itemUrl The section-relative URL
+ * @param context The use context, e.g. ContentItem.LIVE,
+ * CMSDispatcher.PREVIEW or ContentItem.DRAFT. See {@link
* #getCurrentContext}.
* @return The content item, or null if no such item exists
*/
@Override
public ContentItem getItem(final ContentSection section,
- String url,
- final String context) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Resolving the item in content section " + section +
- " at URL '" + url + "' for context " + context);
- }
-
+ final String itemUrl,
+ final String context) {
+ LOGGER.debug("Resolving the item in content section \"{}\" at URL "
+ + "\"{}\" for context \"{}\"...",
+ section.getLabel(),
+ itemUrl,
+ context);
+
Assert.exists(section, "ContentSection section");
- Assert.exists(url, "String url");
+ Assert.exists(itemUrl, "String url");
Assert.exists(context, "String context");
-
- Category rootFolder = section.getRootDocumentsFolder();
- url = stripTemplateFromURL(url);
-
- // nothing to do, if root folder is null
+
+ final Folder rootFolder = section.getRootDocumentsFolder();
+ String url = stripTemplateFromURL(itemUrl);
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+
if (rootFolder == null) {
- s_log.debug("The root folder is null; returning no item");
+ // nothing to do, if root folder is null
+ LOGGER.debug("The root folder is null; returning no item");
} else {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Using root folder " + rootFolder);
- }
-
- if ("live".equals(context)) {
- s_log.debug("The use context is 'live'");
-
- // We allow for returning null, so the root folder may
- // not be live.
- //Assert.isTrue(rootFolder.isLive(),
- // "live context - root folder of secion must be live");
-
- // If the context is 'live', we need the live item.
-
- rootFolder = (Folder) rootFolder.getLiveVersion();
-
- if (rootFolder == null) {
- s_log.debug("The live version of the root folder is " +
- "null; returning no item");
- } else {
- s_log.debug("The root folder has a live version; " +
- "recursing");
-
- final String prefix =
- section.getURL() + rootFolder.getPath();
-
- if (url.startsWith(prefix)) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("The URL starts with prefix '" +
- prefix + "'; removing it");
- }
-
- url = url.substring(prefix.length());
- }
-
- final ContentItem item = getItemFromLiveURL(url, rootFolder);
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("Resolved URL '" + url + "' to item " +
- item);
- }
-
- return item;
+ LOGGER.debug("Using root folder {}...",
+ Objects.toString(rootFolder));
+
+ if (ContentItemVersion.LIVE.toString().equals(context)) {
+ LOGGER.debug("The use context is 'live'");
+
+ LOGGER.debug("The root folder has a live version; recursing");
+
+ final FolderManager folderManager = cdiUtil.findBean(
+ FolderManager.class);
+ final String prefix = String.join(
+ "",
+ section.getPrimaryUrl(),
+ folderManager.getFolderPath(rootFolder));
+
+ if (url.startsWith(prefix)) {
+ LOGGER.
+ debug("The starts with prefix \"{}\"; removing it...",
+ prefix);
+
+ url = url.substring(prefix.length());
}
- } else if (ContentItem.DRAFT.equals(context)) {
- s_log.debug("The use context is 'draft'");
-
+
+ final ContentItem item = getItemFromLiveURL(url, rootFolder);
+
+ LOGGER.debug("Resolved URL \"{}\" to item {}...",
+ url,
+ Objects.toString(item));
+
+ return item;
+
+ } else if (ContentItemVersion.DRAFT.toString().equals(context)) {
+ LOGGER.debug("The use context is 'draft'");
+
// For 'draft' items, 'generateUrl()' method returns
// URL like this
// '/acs/wcms/admin/item.jsp?item_id=10201&set_tab=1'
@@ -158,52 +151,50 @@ public class MultilingualItemResolver
// 'item_id', then try to instanciate item_id value
// and return FIXME: Please hack this if there is
// more graceful solution. [aavetyan]
-
if (Assert.isEnabled()) {
- Assert.isTrue
- (url.indexOf(ITEM_ID) >= 0,
- "url must contain parameter " + ITEM_ID);
+ Assert.isTrue(url.contains(ITEM_ID),
+ String.format("url must contain parameter %s",
+ ITEM_ID));
}
-
+
final ContentItem item = getItemFromDraftURL(url);
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("Resolved URL '" + url + "' to item " + item);
- }
-
+
+ LOGGER.debug("Resolved URL \"{}\" to item {}.",
+ url,
+ Objects.toString(item));
+
return item;
} else if (CMSDispatcher.PREVIEW.equals(context)) {
- s_log.debug("The use context is 'preview'");
-
+ LOGGER.debug("The use context is 'preview'");
+
final String prefix = CMSDispatcher.PREVIEW + "/";
-
+
if (url.startsWith(prefix)) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("The URL starts with prefix '" +
- prefix + "'; removing it");
- }
-
+ LOGGER.debug(
+ "The URL starts with prefix \"{}\"; removing it",
+ prefix);
+
url = url.substring(prefix.length());
}
-
+
final ContentItem item = getItemFromLiveURL(url, rootFolder);
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("Resolved URL '" + url + "' to item " + item);
- }
-
+
+ LOGGER.debug("Resolved URL \"{}\" to item {}.",
+ url,
+ Objects.toString(item));
+
return item;
} else {
- throw new IllegalArgumentException
- ("Invalid item resolver context " + context);
+ throw new IllegalArgumentException(String.format(
+ "Invalid item resolver context \"%s\".", context));
}
}
-
- s_log.debug("No item resolved; returning null");
-
+
+ LOGGER.debug("No item resolved; returning null");
+
return null;
}
-
+
/**
* Fetches the current context based on the page state.
*
@@ -212,44 +203,43 @@ public class MultilingualItemResolver
* ContentItem.LIVE or ContentItem.DRAFT
* @see ContentItem#LIVE
* @see ContentItem#DRAFT
+ *
+ * ToDo: Refactor to use the {@link ContentItemVersion} directly.
*/
@Override
public String getCurrentContext(final PageState state) {
- s_log.debug("Getting the current context");
-
+ LOGGER.debug("Getting the current context");
+
// XXX need to use Web.getWebContext().getRequestURL() here.
String url = state.getRequest().getRequestURI();
-
- final 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) {
- final String sectionURL = section.getURL();
-
+ final String sectionURL = section.getPrimaryUrl();
+
if (url.startsWith(sectionURL)) {
url = url.substring(sectionURL.length());
}
}
-
+
// Remove any template-specific URL components (will only work
// if they're first in the URL at this point; verify). XXX but
// we don't actually verify?
-
url = stripTemplateFromURL(url);
-
+
// Determine if we are under the admin UI.
-
- if (url.startsWith(ADMIN_PREFIX) || url.startsWith(ContentCenter.getURL())) {
- return ContentItem.DRAFT;
+ if (url.startsWith(ADMIN_PREFIX)
+ || url.startsWith(CmsConstants.CONTENT_CENTER_URL)) {
+ return ContentItemVersion.DRAFT.toString();
} else {
- return ContentItem.LIVE;
+ return ContentItemVersion.LIVE.toString();
}
}
-
+
/**
* Generates a URL for a content item.
*
@@ -257,20 +247,19 @@ public class MultilingualItemResolver
* @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 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 String name,
- final ContentSection section,
- final String context) {
+ final BigDecimal 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.
*
@@ -278,131 +267,129 @@ public class MultilingualItemResolver
* @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"
+ * @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 String name,
- final ContentSection section,
- final String context,
- final String templateContext) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Generating an item URL for item id " + itemId +
- ", section " + section + ", and context '" +
- context + "' with name '" + name + "'");
+ final BigDecimal 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 + "'");
}
-
- Assert.exists(itemId, "BigDecimal itemId");
+
+ Assert.exists(itemId, "BigDecimal itemId");
Assert.exists(context, "String context");
Assert.exists(section, "ContentSection section");
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final ContentItemRepository itemRepo = cdiUtil.findBean(ContentItemRepository.class);
- if (ContentItem.DRAFT.equals(context)) {
+ 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);
-
+
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");
+ "Generating " + ContentItem.LIVE + " "
+ + "URL; this item must be the live version");
}
-
+
return generateLiveURL(section, item, templateContext);
} else {
- throw new IllegalArgumentException
- ("Unknown context '" + context + "'");
+ throw new IllegalArgumentException("Unknown context '" + context
+ + "'");
}
}
-
+
/**
* 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 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 ContentItem item,
- final ContentSection section,
- final String context) {
+ 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 templateContext the context for the URL, such as
- * "public"
+ * @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 String context,
- final String templateContext) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Generating an item URL for item " + item +
- ", section " + section + ", and context " +
- context);
+ final ContentItem item,
+ 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);
}
-
+
Assert.exists(item, "ContentItem item");
Assert.exists(context, "String context");
-
+
if (section == null) {
section = item.getContentSection();
}
-
+
if (ContentItem.DRAFT.equals(context)) {
if (Assert.isEnabled()) {
Assert.isTrue(ContentItem.DRAFT.equals(item.getVersion()),
- "Generating " + ContentItem.DRAFT +
- " url: item must be draft version");
+ "Generating " + ContentItem.DRAFT
+ + " url: item must be draft version");
}
-
+
return generateDraftURL(section, item.getID());
} 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");
+ "Generating " + ContentItem.LIVE
+ + " url: item must be live version");
}
-
+
return generateLiveURL(section, item, templateContext);
} else {
throw new RuntimeException("Unknown context " + context);
}
}
-
+
/**
- * Returns a master page based on page state (and content
- * section).
+ * Returns a master page based on page state (and content section).
*
* @param item The content item
* @param request The HTTP request
@@ -411,80 +398,81 @@ public class MultilingualItemResolver
*/
@Override
public CMSPage getMasterPage(final ContentItem item,
- final HttpServletRequest request)
+ final HttpServletRequest request)
throws ServletException {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Getting the master page for item " + item);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Getting the master page for item " + item);
}
-
+
// taken from SimpleItemResolver
if (s_masterP == null) {
s_masterP = new MasterPage();
s_masterP.init();
}
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("Returning master page " + s_masterP);
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Returning master page " + s_masterP);
}
-
+
return s_masterP;
}
-
+
/**
* 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 section The content section to which the item belongs
+ * @param itemId The content item's ID
* @return generated URL string
*/
protected String generateDraftURL(final ContentSection section,
- final BigDecimal itemId) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Generating draft URL for item ID " + itemId +
- " and section " + section);
+ final BigDecimal itemId) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Generating draft URL for item ID " + itemId
+ + " and section " + section);
}
-
+
if (Assert.isEnabled()) {
Assert.isTrue(section != null && itemId != null,
- "get draft url: neither secion nor item " +
- "can be null");
+ "get draft url: neither secion nor item "
+ + "can be null");
}
-
- final String url = ContentItemPage.getItemURL
- (section.getPath() + "/", itemId, ContentItemPage.AUTHORING_TAB);
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("Generated draft URL " + url);
+
+ final String url = ContentItemPage.getItemURL(section.getPath() + "/",
+ itemId,
+ ContentItemPage.AUTHORING_TAB);
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Generated draft URL " + url);
}
-
+
return url;
}
-
+
/**
- * Generate a language-independent URL to the
- * item in the given section.
When a client
- * retrieves this URL, the URL is resolved to point to a specific
- * language instance of the item referenced here, i.e. this URL
- * will be resolved to a language-specific URL
- * internally.
+ * Generate a language-independent URL to the item in
+ * the given section.
+ * When a client retrieves this URL, the URL is resolved to point to a
+ * specific language instance of the item referenced here, i.e. this URL
+ * will be resolved to a language-specific URL internally.
*
* @param section the ContentSection that contains this item
* @param item ContentItem for which a URL should be
- * constructed.
- * @param templateContext template context; will be ignored if null
+ * constructed.
+ * @param templateContext template context; will be ignored if
+ * null
*
- * @return a language-independent URL to the
- * item in the given section, which will
- * be presented within the given templateContext
+ * @return a language-independent URL to the item in
+ * the given section, which will be presented within the given
+ * templateContext
*/
protected String generateLiveURL(final ContentSection section,
- final ContentItem item,
- final String templateContext) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Generating live URL for item " + item + " in " +
- "section " + section);
+ final ContentItem item,
+ final String templateContext) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Generating live URL for item " + item + " in "
+ + "section " + section);
}
-
+
/*
* URL = URL of section + templateContext + path to the ContentBundle
* which contains the item
@@ -492,19 +480,20 @@ public class MultilingualItemResolver
final StringBuffer url = new StringBuffer(400);
//url.append(section.getURL());
url.append(section.getPath()).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.
final ContentItem bundle = (ContentItem) item.getParent();
-
+
/*
* It would be nice if we had a ContentPage here, which
* supports the getContentBundle() method, but unfortunately
@@ -514,23 +503,22 @@ public class MultilingualItemResolver
* ContentItem.
*/
if (bundle != null && bundle instanceof ContentBundle) {
- s_log.debug("Found a bundle; building its file name");
-
+ LOGGER.debug("Found a bundle; building its file name");
+
final String fname = bundle.getPath();
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("Appending the bundle's file name '" +
- fname + "'");
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Appending the bundle's file name '" + fname + "'");
}
-
+
url.append(fname);
-
+
} else {
- s_log.debug("No bundle found; using the item's path directly");
-
+ 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();
@@ -548,34 +536,32 @@ public class MultilingualItemResolver
if (s_log.isDebugEnabled()) {
s_log.debug("Generated live URL " + url.toString());
}
-*/
+ */
return url.toString();
}
-
+
/**
- * Generate a URL which can be used to preview the
- * item, using the given
- * templateContext.
Only a specific language
- * instance can be previewed, meaning there no language
- * negotiation is involved when a request is made to a URL that
- * has been generated by this method.
+ * Generate a URL which can be used to preview the item, using
+ * the given templateContext.
+ * Only a specific language instance can be previewed, meaning there
+ * no language negotiation is involved when a request is made to a
+ * URL that has been generated by this method.
*
- * @param section The ContentSection which contains
- * the item
- * @param item The ContentItem 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 null
- * @return a URL which can be used to preview the given
+ * @param section The ContentSection which contains the
* item
+ * @param item The ContentItem 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 null
+ * @return a URL which can be used to preview the given item
*/
protected String generatePreviewURL(ContentSection section,
- ContentItem item,
- String templateContext) {
+ ContentItem item,
+ String templateContext) {
Assert.exists(section, "ContentSection section");
Assert.exists(item, "ContentItem item");
-
+
final StringBuffer url = new StringBuffer(100);
url.append(section.getPath());
url.append("/");
@@ -587,12 +573,13 @@ 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.
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
@@ -601,112 +588,111 @@ public class MultilingualItemResolver
* ContentItem.
*/
if (bundle != null && bundle instanceof ContentBundle) {
- s_log.debug("Found a bundle; using its path");
-
+ LOGGER.debug("Found a bundle; using its path");
+
url.append(bundle.getPath());
} else {
- s_log.debug("No bundle found; using the item's path directly");
-
+ LOGGER.debug("No bundle found; using the item's path directly");
+
url.append(item.getPath());
}
-
+
final String language = item.getLanguage();
-
+
if (language == null) {
- s_log.debug("The item has no language; omitting the " +
- "language encoding");
+ LOGGER.debug("The item has no language; omitting the "
+ + "language encoding");
} else {
- s_log.debug("Encoding the language of the item passed in, '" +
- language + "'");
-
+ LOGGER.debug("Encoding the language of the item passed in, '"
+ + language + "'");
+
url.append(".").append(language);
}
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("Generated preview URL " + url.toString());
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Generated preview URL " + url.toString());
}
-
+
return url.toString();
}
-
+
/**
- * Retrieves ITEM_ID parameter from URL and
- * instantiates item according to this ID.
+ * Retrieves ITEM_ID parameter from URL and instantiates item
+ * according to this ID.
*
- * @param url URL that indicates which item should be retrieved;
- * must contain the ITEM_ID parameter
- * @return the ContentItem the given url
- * points to, or null if no ID has been found in the
- * url
+ * @param url URL that indicates which item should be retrieved; must
+ * contain the ITEM_ID parameter
+ * @return the ContentItem the given url points
+ * to, or null if no ID has been found in the url
*/
protected ContentItem getItemFromDraftURL(final String url) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Looking up the item from draft URL " + url);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Looking up the item from draft URL " + url);
}
-
+
int pos = url.indexOf(ITEM_ID);
-
+
// XXX this is wrong: here we abort on not finding the
// parameter; below we return null.
if (Assert.isEnabled()) {
Assert.isTrue(pos >= 0,
- "Draft URL must contain parameter " + ITEM_ID);
+ "Draft URL must contain parameter " + ITEM_ID);
}
-
+
String item_id = url.substring(pos); // item_id == ITEM_ID=.... ?
-
+
pos = item_id.indexOf("="); // should be exactly after the ITEM_ID string
-
+
if (pos != ITEM_ID.length()) {
// item_id seems to be something like ITEM_IDFOO=
-
- s_log.debug("No suitable item_id parameter found; returning null");
-
+
+ LOGGER.debug("No suitable item_id parameter found; returning null");
+
return null; // no ID found
}
-
+
pos++; // skip the "="
-
+
// ID is the string between the equal (at pos) and the next separator
int i = item_id.indexOf(SEPARATOR);
- item_id = item_id.substring(pos, Math.min(i, item_id.length() -1));
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("Looking up item using item ID " + item_id);
+ item_id = item_id.substring(pos, Math.min(i, item_id.length() - 1));
+
+ if (LOGGER.isDebugEnabled()) {
+ 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);
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("Returning item " + item);
+
+ OID oid = new OID(ContentItem.BASE_DATA_OBJECT_TYPE, new BigDecimal(
+ item_id));
+ final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(
+ oid);
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Returning item " + item);
}
-
+
return item;
}
-
+
/**
- * Returns a content item based on URL relative to the root
- * folder.
+ * Returns a content item based on URL relative to the root folder.
*
- * @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
+ * @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
*/
protected ContentItem getItemFromLiveURL(String url,
- Folder parentFolder) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Resolving the item for live URL " + url +
- " and parent folder " + parentFolder);
+ Folder parentFolder) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Resolving the item for live URL " + url
+ + " and parent folder " + parentFolder);
}
if (parentFolder == null || url == null || url.equals("")) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("The url is null or parent folder was null " +
- "or something else is wrong, so just return " +
- "the parent folder");
+ 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");
}
return parentFolder;
@@ -716,43 +702,43 @@ public class MultilingualItemResolver
int index = url.indexOf('/');
if (index >= 0) {
- s_log.debug("The URL starts with a slash; paring off the first " +
- "URL element and recursing");
+ LOGGER.debug("The URL starts with a slash; paring off the first "
+ + "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);
+ : (Folder) parentFolder.getItem(URLEncoder.encode(
+ name), true);
url = index + 1 < len ? url.substring(index + 1) : "";
return getItemFromLiveURL(url, parentFolder);
} else {
- s_log.debug("Found a file element in the URL");
+ LOGGER.debug("Found a file element in the URL");
- String[] nameAndLang = getNameAndLangFromURLFrag(url);
+ String[] nameAndLang = getNameAndLangFromURLFrag(url);
String name = nameAndLang[0];
String lang = nameAndLang[1];
- ContentItem item = parentFolder.getItem(URLEncoder.encode(name), false);
- return getItemFromLangAndBundle(lang, item);
+ ContentItem item = parentFolder.getItem(URLEncoder.encode(name),
+ false);
+ return getItemFromLangAndBundle(lang, item);
}
}
/**
- * Returns an array containing the the item's name and lang based
- * on the URL fragment.
+ * Returns an array containing the the item's name and lang based on the URL
+ * fragment.
*
- * @return a two-element string array, the first element
- * containing the bundle name, and the second element containing
- * the lang string
+ * @return a two-element string array, the first element containing the
+ * bundle name, and the second element containing the lang string
*/
protected String[] getNameAndLangFromURLFrag(String url) {
String name = null;
String lang = null;
-
+
/*
* Try to find out if there's an extension with the language code
* 1 Get a list of all "extensions", i.e. parts of the url
@@ -763,20 +749,19 @@ public class MultilingualItemResolver
* from a bundle
* 2b if no match is found
*/
-
final ArrayList exts = new ArrayList(5);
final StringTokenizer tok = new StringTokenizer(url, ".");
-
+
while (tok.hasMoreTokens()) {
exts.add(tok.nextToken());
}
-
+
if (exts.size() > 0) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Found some file extensions to look at; they " +
- "are " + exts);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Found some file extensions to look at; they "
+ + "are " + exts);
}
-
+
/*
* We have found at least one extension, so we can
* proceed. Now try to find out if one of the
@@ -784,23 +769,22 @@ public class MultilingualItemResolver
* support 2-letter language codes!).
* If so, use this as the language to look for.
*/
-
- /*
+ /*
* First element is the NAME of the item, not an extension!
*/
name = (String) exts.get(0);
String ext = null;
- Collection supportedLangs =
- LanguageUtil.getSupportedLanguages2LA();
+ Collection supportedLangs
+ = LanguageUtil.getSupportedLanguages2LA();
Iterator supportedLangIt = null;
-
+
for (int i = 1; i < exts.size(); i++) {
ext = (String) exts.get(i);
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("Examining extension " + ext);
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Examining extension " + ext);
}
-
+
/*
* Loop through all extensions, but discard the
* first one, which is the name of the item.
@@ -817,67 +801,67 @@ public class MultilingualItemResolver
while (supportedLangIt.hasNext()) {
if (ext.equals(supportedLangIt.next())) {
lang = ext;
- if (s_log.isDebugEnabled()) {
- s_log.debug("Found a match; using " +
- "language " + lang);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Found a match; using "
+ + "language " + lang);
}
break;
}
}
} else {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Discarding extension " + ext + "; " +
- "it is too short");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Discarding extension " + ext + "; "
+ + "it is too short");
}
}
}
} else {
- s_log.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);
}
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("File name resolved to " + name);
- s_log.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];
returnArray[0] = name;
returnArray[1] = lang;
return returnArray;
}
-
-
+
/**
- * Finds a language instance of a content item given the bundle,
- * name, and lang string
+ * Finds a language instance of a content item given the bundle, name, and
+ * lang string
*
- * @param lang The lang string from the URL
- * @param item The content bundle
+ * @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 (s_log.isDebugEnabled()) {
- s_log.debug("Found content bundle " + item);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Found content bundle " + item);
}
if (lang == null) {
- s_log.debug("The URL has no language encoded in it; " +
- "negotiating the language");
+ 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);
+ return this.getItemFromLangAndBundle(GlobalizationHelper.
+ getNegotiatedLocale().getLanguage(), item);
} else {
- s_log.debug("The URL is encoded with a langauge; " +
- "fetching the appropriate item from " +
- "the bundle");
+ 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
@@ -885,21 +869,22 @@ public class MultilingualItemResolver
* the bundle does not contain an instance for the
* given language.
*/
-
- final ContentItem resolved =
- ((ContentBundle) item).getInstance(lang);
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("Resolved URL to item " + resolved);
+
+ final ContentItem resolved
+ = ((ContentBundle) item).getInstance(lang);
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Resolved URL to item " + resolved);
}
return resolved;
}
} else {
- if (s_log.isDebugEnabled()) {
- s_log.debug("I expected to get a content bundle; I got " +
- item);
+ 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
@@ -908,9 +893,8 @@ public class MultilingualItemResolver
*
* NOTE: This should never happen :-)
*/
-
return item; // might be null
}
}
-
+
}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitWizard.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitWizard.java.off
deleted file mode 100755
index ad268f1fb..000000000
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitWizard.java.off
+++ /dev/null
@@ -1,684 +0,0 @@
-/*
- * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-package com.arsdigita.cms.ui.authoring;
-
-import com.arsdigita.bebop.Component;
-import com.arsdigita.bebop.ControlLink;
-import com.arsdigita.bebop.FormProcessException;
-import com.arsdigita.bebop.GridPanel;
-import com.arsdigita.bebop.List;
-import com.arsdigita.bebop.Page;
-import com.arsdigita.bebop.PageState;
-import com.arsdigita.bebop.Resettable;
-import com.arsdigita.bebop.SimpleContainer;
-import com.arsdigita.bebop.SingleSelectionModel;
-import com.arsdigita.bebop.event.ActionEvent;
-import com.arsdigita.bebop.event.ActionListener;
-import com.arsdigita.bebop.event.ChangeEvent;
-import com.arsdigita.bebop.event.ChangeListener;
-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.ContentSection;
-import org.librecms.contentsection.ContentType;
-import com.arsdigita.cms.ItemSelectionModel;
-import com.arsdigita.cms.ui.ContentItemPage;
-import com.arsdigita.cms.ui.item.ItemWorkflowRequestLocal;
-import com.arsdigita.cms.ui.workflow.AssignedTaskSection;
-import com.arsdigita.cms.ui.workflow.AssignedTaskTable;
-import com.arsdigita.cms.ui.workflow.TaskFinishForm;
-import com.arsdigita.cms.ui.workflow.TaskRequestLocal;
-import com.arsdigita.cms.ui.workflow.WorkflowRequestLocal;
-import com.arsdigita.cms.util.GlobalizationUtil;
-import com.arsdigita.cms.workflow.CMSTask;
-import com.arsdigita.globalization.GlobalizedMessage;
-import com.arsdigita.persistence.metadata.MetadataRoot;
-import com.arsdigita.persistence.metadata.ObjectType;
-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;
-import java.lang.reflect.InvocationTargetException;
-import java.math.BigDecimal;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.ArrayList;
-import java.util.Collections;
-import org.apache.logging.log4j.LogManager;
-import org.librecms.contenttypes.AuthoringKitInfo;
-import org.librecms.contenttypes.ContentTypeInfo;
-
-/**
- * This class represents a single authoring kit. The wizard accepts a
- * {@link ContentType} in the constructor; it then extracts
- * the {@link AuthoringKit} for the content type, and creates the
- * components for all the steps in the kit.
- * - * This constructor will be called when the component is automatically - * instantiated by the- * public TheClass(ItemSelectionModel model, AuthoringKitWizard parent) { ... } - *
AuthoringKitWizard.
- *
- */
-public class AuthoringKitWizard extends LayoutPanel implements Resettable {
-
- /** Private Logger instance for this class */
- private static final Logger LOGGER = LogManager.getLogger(
- AuthoringKitWizard.class);
- private static Class[] s_args = new Class[]{
- ItemSelectionModel.class,
- AuthoringKitWizard.class
- };
- private static Class[] s_userDefinedArgs = new Class[]{
- ItemSelectionModel.class,
- AuthoringKitWizard.class,
- ContentType.class
- };
- //private static final ArrayList s_assets = new ArrayList();
- private static final java.util.List+ * + * This constructor will be called when the component is automatically + * instantiated by the+ * public TheClass(ItemSelectionModel model, AuthoringKitWizard parent) { ... } + *
AuthoringKitWizard.
+ *
+ */
+public class AuthoringKitWizard extends LayoutPanel implements Resettable {
+
+ /**
+ * Private Logger instance for this class
+ */
+ private static final Logger LOGGER = LogManager.getLogger(
+ AuthoringKitWizard.class);
+ private static Class[] arguments = new Class[]{
+ ItemSelectionModel.class,
+ AuthoringKitWizard.class
+ };
+ private static Class[] userDefinedArgs = new Class[]{
+ ItemSelectionModel.class,
+ AuthoringKitWizard.class,
+ ContentType.class
+ };
+ private static final java.util.ListItemLanguages.
+ *
+ * @param selectionModel the {@link ItemSelectionModel} which will supply the current
+ * item
+ */
+ public ItemLanguages(final ItemSelectionModel selectionModel) {
+ this.selectionModel = selectionModel;
+
+ final Section section = new Section(gz("cms.ui.item.languages"));
+ setBody(section);
+
+ final ActionGroup group = new ActionGroup();
+ section.setBody(group);
+
+ group.setSubject(new ItemLanguagesTable(selectionModel));
+
+ final Form form = new Form("newLanguage", new BoxPanel(
+ BoxPanel.HORIZONTAL));
+ group.addAction(form);
+
+ form.setRedirecting(true);
+ languageWidget = new LanguageWidget(ContentItem.LANGUAGE) {
+ protected void setupOptions() {
+ // Don't do anything.
+ }
+ };
+
+ try {
+ languageWidget.addPrintListener(new OptionPrinter());
+ } catch (TooManyListenersException tmle) {
+ new UncheckedWrapperException(tmle);
+ }
+
+ form.add(languageWidget);
+ changeSubmit = new Submit("change", gz("cms.ui.item.language.change"));
+ form.add(changeSubmit);
+ createSubmit = new Submit("create", gz("cms.ui.item.language.add"));
+ form.add(createSubmit);
+ form.addProcessListener(new ProcessListener());
+ }
+
+ /**
+ * Offers only languages not yet present in the bundle.
+ */
+ private class OptionPrinter implements PrintListener {
+
+ public final void prepare(final PrintEvent e) {
+ final PageState state = e.getPageState();
+ final OptionGroup optionGroup = (OptionGroup) e.getTarget();
+ final ContentPage item = (ContentPage) selectionModel.
+ getSelectedItem(state);
+ final Collection languages = LanguageUtil.convertToG11N(
+ LanguageUtil.getCreatableLanguages(item));
+
+ for (Iterator iter = languages.iterator(); iter.hasNext();) {
+ final Pair pair = (Pair) iter.next();
+ final String langCode = (String) pair.getKey();
+ final GlobalizedMessage langName
+ = (GlobalizedMessage) pair.getValue();
+ optionGroup.addOption(new Option(langCode, new Label(langName)));
+ }
+ }
+ }
+
+ /**
+ * Adds a new language instance to the bundle.
+ */
+ private class ProcessListener implements FormProcessListener {
+
+ public final void process(final FormSectionEvent e)
+ throws FormProcessException {
+ PageState state = e.getPageState();
+ String lang = (String) languageWidget.getValue(state);
+ ContentPage item = (ContentPage) selectionModel.getSelectedItem(state);
+ ContentBundle bundle = item.getContentBundle();
+ String name = bundle.getName();
+
+ if (createSubmit.isSelected(state)) {
+ ContentSection section = item.getContentSection();
+
+ Assert.exists(section, ContentSection.class);
+
+ ContentType type = item.getContentType();
+
+ item = (ContentPage) item.copy(lang);
+ item.setLanguage(lang);
+ item.setName(name);
+
+ // Apply default workflow
+ WorkflowTemplate template
+ = ContentTypeWorkflowTemplate
+ .getWorkflowTemplate(section, type);
+ if (template != null) {
+ Workflow w = template.instantiateNewWorkflow();
+ w.setObjectID(item.getID());
+ w.start(Kernel.getContext().getUser());
+ w.save();
+ }
+
+ selectionModel.setSelectedObject(state, item);
+
+ // redirect to ContentItemPage.AUTHORING_TAB of the new instance
+ final String target = URL.getDispatcherPath() + ContentItemPage.
+ getItemURL(item,
+ ContentItemPage.AUTHORING_TAB);
+
+ throw new RedirectSignal(target, true);
+ } else if (changeSubmit.isSelected(state)) {
+ String oldLang = item.getLanguage();
+ item.setLanguage(lang);
+ // propagate language change to the Name attribute
+ item.setName(name);
+ item.save();
+
+ // if the item being changed is the default, update the bundle
+ // to keep this item as the default
+ if (bundle.getDefaultLanguage().equals(oldLang)) {
+ bundle.setDefaultLanguage(lang);
+ bundle.save();
+ }
+ }
+ }
+ }
+
+ protected static final GlobalizedMessage gz(final String key) {
+ return GlobalizationUtil.globalize(key);
+ }
+
+ protected static final String lz(final String key) {
+ return (String) gz(key).localize();
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTable.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTable.java.todo
new file mode 100755
index 000000000..0aa27f364
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemLanguagesTable.java.todo
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.ui.item;
+
+import com.arsdigita.bebop.*;
+import com.arsdigita.bebop.event.TableActionAdapter;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.dispatcher.MultilingualItemResolver;
+import com.arsdigita.cms.ui.ContentItemPage;
+import org.librecms.util.LanguageUtil;
+import com.arsdigita.toolbox.ui.DataTable;
+import com.arsdigita.util.LockableImpl;
+import com.arsdigita.web.RedirectSignal;
+import com.arsdigita.web.URL;
+import java.math.BigDecimal;
+import org.apache.log4j.Logger;
+
+/**
+ * Displays a list of all language instances of an item.
+ *
+ */
+public class ItemLanguagesTable extends DataTable {
+
+ private static final Logger LOGGER = Logger.getLogger(ItemLanguagesTable.class);
+ private final ItemSelectionModel m_model;
+ private final TableColumn m_deleteColumn;
+
+ /**
+ * Construct a new
+ * ItemHistoryTable
+ *
+ * @param model the ItemSelectionModel that supplies the current item
+ */
+ public ItemLanguagesTable(ItemSelectionModel model) {
+ super(new LanguagesBuilder(model));
+ m_model = model;
+
+ addColumn("cms.ui.language.header",
+ ContentPage.LANGUAGE,
+ false,
+ new LanguageCellRenderer(m_model));
+ addColumn("cms.ui.title",
+ ContentPage.TITLE);
+ m_deleteColumn = addColumn("cms.ui.action", new ActionCellRenderer(
+ m_model));
+ setResourceBundle(GlobalizationUtil.getBundleName());
+ addTableActionListener(new InstanceDeleter(m_model));
+ }
+
+ /**
+ * Builds the query for all the language instances in the current Bundle
+ */
+ private static class LanguagesBuilder extends LockableImpl
+ implements DataQueryBuilder {
+
+ ItemSelectionModel m_model;
+
+ public LanguagesBuilder(ItemSelectionModel model) {
+ super();
+ m_model = model;
+ }
+
+ public DataQuery makeDataQuery(DataTable t, PageState s) {
+ ContentPage multiLingual =
+ (ContentPage) m_model.getSelectedObject(s);
+ DataQuery q = SessionManager.getSession().retrieveQuery(
+ "com.arsdigita.cms.getBundledItems");
+ q.setParameter("bundleID", multiLingual.getContentBundle().getID());
+ return q;
+ }
+
+ public String getKeyColumn() {
+ return ContentPage.ID;
+ }
+ }
+
+ /**
+ * Renders the full language name.
+ */
+ private static class LanguageCellRenderer implements TableCellRenderer {
+
+ private ItemSelectionModel m_model;
+
+ public LanguageCellRenderer(ItemSelectionModel model) {
+ m_model = model;
+ }
+
+ public Component getComponent(Table table, PageState state, Object value,
+ boolean isSelected, Object key,
+ int row, int column) {
+
+ BigDecimal id = (BigDecimal) key;
+ ContentPage cp;
+
+ try {
+ cp = new ContentPage(id);
+ } catch (DataObjectNotFoundException ex) {
+ // Content item was not found, return nothing
+ return new Label();
+ }
+
+ ContentBundle bundle = cp.getContentBundle();
+
+ if (bundle != null
+ && !(cp instanceof LanguageInvariantContentItem
+ && ((LanguageInvariantContentItem) cp).isLanguageInvariant())) {
+
+ StringBuilder fontWeight = new StringBuilder(2);
+ StringBuilder classes = new StringBuilder(20);
+
+ if (cp.isLive()) {
+ fontWeight.append(Label.BOLD);
+ classes.append("live ");
+ }
+ if (bundle.getPrimaryInstance().equals(cp)) {
+ fontWeight.append(Label.ITALIC);
+ classes.append("primaryInstance");
+ }
+
+ String target = ContentItemPage.getItemURL(cp, ContentItemPage.AUTHORING_TAB);
+ Label langLabel = new Label(LanguageUtil.getLangFull((String) value));
+
+ langLabel.setFontWeight(fontWeight.toString().trim());
+ langLabel.setClassAttr(classes.toString().trim());
+
+ if (m_model.getSelectedKey(state).equals(key)) {
+ // Current instance: no link
+ return langLabel;
+ } else {
+ return new Link(langLabel, target);
+ }
+ }
+
+ return new Label();
+ }
+ }
+
+ /**
+ * Delete language instance action link.
+ */
+ private static class ActionCellRenderer implements TableCellRenderer {
+
+ private static final Logger logger =
+ Logger.getLogger(ActionCellRenderer.class);
+ private static final Label s_noAction;
+ private static final Label s_primary;
+ private static final ControlLink s_link;
+
+ static {
+ logger.debug("Static initializer is starting...");
+ s_noAction = new Label(" ", false);
+ s_noAction.lock();
+ s_primary = new Label(GlobalizationUtil.globalize(
+ "cms.ui.primary_instance"), false);
+ s_primary.lock();
+ s_link = new ControlLink(new Label(GlobalizationUtil.globalize(
+ "cms.ui.delete")));
+ s_link.setConfirmation(GlobalizationUtil.globalize(
+ "cms.ui.delete_confirmation"));
+ logger.debug("Static initalizer finished.");
+ }
+ private ItemSelectionModel m_model;
+
+ public ActionCellRenderer(ItemSelectionModel model) {
+ m_model = model;
+ }
+
+ public Component getComponent(Table table, PageState state, Object value,
+ boolean isSelected, Object key,
+ int row, int column) {
+ // check if primary instance
+ BigDecimal id = new BigDecimal(key.toString());
+ OID oid = new OID(ContentPage.BASE_DATA_OBJECT_TYPE, id);
+ try {
+ ContentPage item = (ContentPage) DomainObjectFactory.newInstance(oid);
+ if (item.getLanguage().equals(
+ item.getContentBundle().getDefaultLanguage())) {
+ return s_primary;
+ } else if (item.isLive()) {
+ return s_noAction;
+ }
+ } catch (DataObjectNotFoundException ex) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Could not get item with id " + id);
+ }
+ return s_noAction;
+ }
+ return s_link;
+ }
+ }
+
+ // delete one language instance
+ private class InstanceDeleter extends TableActionAdapter {
+
+ private ItemSelectionModel m_model;
+
+ public InstanceDeleter(ItemSelectionModel model) {
+ m_model = model;
+ }
+
+ @Override
+ public void cellSelected(TableActionEvent e) {
+ int col = e.getColumn().intValue();
+
+ if (m_deleteColumn != getColumn(col)) {
+ return;
+ }
+
+ PageState s = e.getPageState();
+ BigDecimal id = new BigDecimal(e.getRowKey().toString());
+
+ OID oid = new OID(ContentPage.BASE_DATA_OBJECT_TYPE, id);
+ try {
+ ContentPage item =
+ (ContentPage) DomainObjectFactory.newInstance(oid);
+ ContentBundle bundle = item.getContentBundle();
+ bundle.removeInstance(item);
+ item.delete();
+
+ if (m_model.getSelectedKey(s).equals(id)) {
+ throw new RedirectSignal(
+ URL.there((new MultilingualItemResolver()
+ .generateItemURL(s,
+ bundle.getPrimaryInstance(),
+ bundle.getContentSection(),
+ ContentItem.DRAFT)),
+ null),
+ true);
+ }
+ } catch (com.arsdigita.domain.DataObjectNotFoundException ex) {
+ // Object not found is ok, it has probably been deleted already
+ }
+ ((Table) e.getSource()).clearSelection(s);
+ }
+ }
+}
diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemL10NManager.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemL10NManager.java
index ce6e3ee34..400880964 100644
--- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemL10NManager.java
+++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemL10NManager.java
@@ -134,6 +134,13 @@ public class ContentItemL10NManager {
return collectLanguages(item).contains(locale);
}
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public Set