CCM NG: ContentItem Page ported

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4517 8810af33-2d31-482b-a856-94f89814c4df
ccm-docs
jensp 2017-01-13 13:19:02 +00:00
parent 24db30a69b
commit 24942b7a5c
31 changed files with 2093 additions and 1685 deletions

View File

@ -23,16 +23,12 @@ import com.arsdigita.cms.CMS;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType;
import com.arsdigita.cms.ItemSelectionModel; import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.PageLocations; import com.arsdigita.cms.PageLocations;
import com.arsdigita.web.ParameterMap; import com.arsdigita.web.ParameterMap;
import com.arsdigita.web.URL; import com.arsdigita.web.URL;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List; import java.util.List;
/** /**

View File

@ -41,12 +41,12 @@ import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.cms.CMS; import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ItemSelectionModel; import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.PageLocations; import com.arsdigita.cms.PageLocations;
import com.arsdigita.cms.ui.item.CustomizedPreviewLink;
import com.arsdigita.cms.dispatcher.CMSDispatcher; import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.CMSPage; import com.arsdigita.cms.dispatcher.CMSPage;
import com.arsdigita.cms.dispatcher.ItemResolver; import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.ui.authoring.WizardSelector; import com.arsdigita.cms.ui.authoring.WizardSelector;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal; import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.cms.ui.item.CustomizedPreviewLink;
import com.arsdigita.cms.ui.item.ItemLanguages; import com.arsdigita.cms.ui.item.ItemLanguages;
import com.arsdigita.cms.ui.item.Summary; import com.arsdigita.cms.ui.item.Summary;
import com.arsdigita.cms.ui.lifecycle.ItemLifecycleAdminPane; import com.arsdigita.cms.ui.lifecycle.ItemLifecycleAdminPane;
@ -60,9 +60,7 @@ import com.arsdigita.util.Assert;
import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.xml.Document; import com.arsdigita.xml.Document;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
import java.io.IOException;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.arsdigita.cms.CMSConfig; import org.arsdigita.cms.CMSConfig;
@ -74,6 +72,11 @@ import org.librecms.contentsection.ContentItemVersion;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType; import org.librecms.contentsection.ContentType;
import java.io.IOException;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
/** /**
* Page for administering a content item. * Page for administering a content item.
* *

View File

@ -39,7 +39,7 @@ import com.arsdigita.cms.dispatcher.CMSPage;
//ToDo NG import com.arsdigita.cms.ui.cse.ContentSoonExpiredPane; //ToDo NG import com.arsdigita.cms.ui.cse.ContentSoonExpiredPane;
import com.arsdigita.cms.ui.folder.FolderAdminPane; import com.arsdigita.cms.ui.folder.FolderAdminPane;
import com.arsdigita.cms.ui.lifecycle.LifecycleAdminPane; import com.arsdigita.cms.ui.lifecycle.LifecycleAdminPane;
import com.arsdigita.cms.ui.role.RoleAdminPane; //import com.arsdigita.cms.ui.role.RoleAdminPane;
import com.arsdigita.cms.ui.type.ContentTypeAdminPane; import com.arsdigita.cms.ui.type.ContentTypeAdminPane;
import com.arsdigita.cms.ui.workflow.WorkflowAdminPane; import com.arsdigita.cms.ui.workflow.WorkflowAdminPane;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
@ -130,7 +130,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
//ToDo NG private BrowsePane m_browsePane; //ToDo NG private BrowsePane m_browsePane;
//ToDo NG private ItemSearch m_searchPane; //ToDo NG private ItemSearch m_searchPane;
//ToDo NG private ImagesPane m_imagesPane; //ToDo NG private ImagesPane m_imagesPane;
private RoleAdminPane m_rolePane; //ToDo NG private RoleAdminPane m_rolePane;
private WorkflowAdminPane m_workflowPane; private WorkflowAdminPane m_workflowPane;
private LifecycleAdminPane m_lifecyclePane; private LifecycleAdminPane m_lifecyclePane;
//ToDo NG private CategoryAdminPane m_categoryPane; //ToDo NG private CategoryAdminPane m_categoryPane;
@ -157,7 +157,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
//ToDo NG m_browsePane = getBrowsePane(); //ToDo NG m_browsePane = getBrowsePane();
//ToDo NG m_searchPane = getSearchPane(); //ToDo NG m_searchPane = getSearchPane();
//ToDo NG m_imagesPane = getImagesPane(); //ToDo NG m_imagesPane = getImagesPane();
m_rolePane = getRoleAdminPane(); //ToDo NG m_rolePane = getRoleAdminPane();
m_workflowPane = getWorkflowAdminPane(); m_workflowPane = getWorkflowAdminPane();
m_lifecyclePane = getLifecycleAdminPane(); m_lifecyclePane = getLifecycleAdminPane();
//ToDo NG m_categoryPane = getCategoryAdminPane(); //ToDo NG m_categoryPane = getCategoryAdminPane();
@ -211,11 +211,12 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
m_typePane, m_typePane,
permissionChecker.isPermitted( permissionChecker.isPermitted(
AdminPrivileges.ADMINISTER_CONTENT_TYPES)); AdminPrivileges.ADMINISTER_CONTENT_TYPES));
m_tabbedPane.setTabVisible( //ToDo NG
state, //m_tabbedPane.setTabVisible(
m_rolePane, // state,
permissionChecker.isPermitted( // m_rolePane,
AdminPrivileges.ADMINISTER_ROLES)); // permissionChecker.isPermitted(
// AdminPrivileges.ADMINISTER_ROLES));
// csePane: should check permission // csePane: should check permission
m_tabbedPane.setTabVisible(state, m_csePane, true); m_tabbedPane.setTabVisible(state, m_csePane, true);
// TODO Check for reportPane as well // TODO Check for reportPane as well
@ -275,12 +276,13 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
// return m_imagesPane; // return m_imagesPane;
// } // }
protected RoleAdminPane getRoleAdminPane() { // ToDo NG
if (m_rolePane == null) { // protected RoleAdminPane getRoleAdminPane() {
m_rolePane = new RoleAdminPane(); // if (m_rolePane == null) {
} // m_rolePane = new RoleAdminPane();
return m_rolePane; // }
} // return m_rolePane;
// }
/** /**
* Creates, and then caches, the workflow administration pane. Overriding * Creates, and then caches, the workflow administration pane. Overriding
@ -400,7 +402,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
// ToDo NG tab(pane, "cms.ui.browse", getBrowsePane()); // ToDo NG tab(pane, "cms.ui.browse", getBrowsePane());
// ToDo NG tab(pane, "cms.ui.search", getSearchPane()); // ToDo NG tab(pane, "cms.ui.search", getSearchPane());
// ToDo NG tab(pane, "cms.ui.images", getImagesPane()); // ToDo NG tab(pane, "cms.ui.images", getImagesPane());
tab(pane, "cms.ui.roles", getRoleAdminPane()); // ToDo NG tab(pane, "cms.ui.roles", getRoleAdminPane());
tab(pane, "cms.ui.workflows", getWorkflowAdminPane()); tab(pane, "cms.ui.workflows", getWorkflowAdminPane());
tab(pane, "cms.ui.lifecycles", getLifecycleAdminPane()); tab(pane, "cms.ui.lifecycles", getLifecycleAdminPane());
// ToDo NG tab(pane, "cms.ui.categories", getCategoryAdminPane()); // ToDo NG tab(pane, "cms.ui.categories", getCategoryAdminPane());
@ -448,8 +450,8 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
m_folderPane.reset(state); m_folderPane.reset(state);
//ToDo NG } else if (pane == m_browsePane) { //ToDo NG } else if (pane == m_browsePane) {
// m_browsePane.reset(state); // m_browsePane.reset(state);
} else if (pane == m_rolePane) { // } else if (pane == m_rolePane) {
m_rolePane.reset(state); // m_rolePane.reset(state);
} else if (pane == m_workflowPane) { } else if (pane == m_workflowPane) {
m_workflowPane.reset(state); m_workflowPane.reset(state);
} else if (pane == m_lifecyclePane) { } else if (pane == m_lifecyclePane) {

View File

@ -39,13 +39,11 @@ import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.Option; import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.SingleSelect; import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.bebop.form.Submit; import com.arsdigita.bebop.form.Submit;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ContentCenter;
import com.arsdigita.cms.dispatcher.Utilities;
import com.arsdigita.cms.ui.BaseItemPane; import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.cms.ui.ContentItemPage; import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal; import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.mail.Mail;
import com.arsdigita.toolbox.ui.ActionGroup; import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.Property; import com.arsdigita.toolbox.ui.Property;
import com.arsdigita.toolbox.ui.PropertyList; import com.arsdigita.toolbox.ui.PropertyList;
@ -53,7 +51,6 @@ import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.RedirectSignal; import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.URL; import com.arsdigita.web.URL;
import com.arsdigita.web.Web;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@ -61,18 +58,15 @@ import org.apache.logging.log4j.Logger;
import org.arsdigita.cms.CMSConfig; import org.arsdigita.cms.CMSConfig;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.notification.Notification;
import org.libreccm.security.Party;
import org.libreccm.security.PermissionChecker; import org.libreccm.security.PermissionChecker;
import org.libreccm.security.Shiro;
import org.libreccm.security.User; import org.libreccm.security.User;
import org.libreccm.workflow.Workflow; import org.libreccm.security.UserRepository;
import org.libreccm.workflow.WorkflowManager; import org.libreccm.workflow.WorkflowManager;
import org.librecms.CmsConstants; import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager; import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository; import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionConfig;
import org.librecms.contentsection.privileges.ItemPrivileges; import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.lifecycle.Lifecycle; import org.librecms.lifecycle.Lifecycle;
@ -85,6 +79,8 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Optional; import java.util.Optional;
import javax.mail.MessagingException;
/** /**
* This class contains the component which displays the information for a * This class contains the component which displays the information for a
* particular lifecycle, with the ability to edit and delete. This information * particular lifecycle, with the ability to edit and delete. This information
@ -322,10 +318,13 @@ class ItemLifecycleItemPane extends BaseItemPane {
public final void actionPerformed(final ActionEvent event) { public final void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState(); final PageState state = event.getPageState();
final ContentItem item = selectedItem.getContentItem(state); final ContentItem item = selectedItem.getContentItem(state);
final User user = Web.getWebContext().getUser(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final Shiro shiro = cdiUtil.findBean(Shiro.class);
final User user = shiro.getUser();
/* /*
* jensp 2011-12-14: Check is threaded publishing is active. If yes, execute publishing in a thread. * jensp 2011-12-14: Check is threaded publishing is active.
* If yes, execute publishing in a thread.
*/ */
if (CMSConfig.getConfig().isThreadPublishing()) { if (CMSConfig.getConfig().isThreadPublishing()) {
final Republisher republisher = new Republisher(item, user); final Republisher republisher = new Republisher(item, user);
@ -341,46 +340,30 @@ class ItemLifecycleItemPane extends BaseItemPane {
= new PrintWriter(strWriter); = new PrintWriter(strWriter);
ex.printStackTrace(writer); ex.printStackTrace(writer);
PublishLock.getInstance().setError(item, strWriter // PublishLock.getInstance().setError(item, strWriter
.toString()); // .toString());
LOGGER.error(String.format( LOGGER.error(String.format(
"An error occurred while " "An error occurred while "
+ "publishing the item '%s': ", + "publishing the item '%s': ",
item.getOID().toString()), item.getUuid()), ex);
ex);
if ((CMSConfig.getInstanceOf(). if ((CMSConfig.getConfig()
getPublicationFailureSender() .getPublishingFailureSender()
== null) == null)
&& (CMSConfig.getInstanceOf(). && (CMSConfig.getConfig()
getPublicationFailureReceiver() .getPublishingFailureReceiver()
== null)) { == null)) {
return; return;
} }
final PartyCollection receiverParties = Party final UserRepository userRepo = cdiUtil.findBean(
.retrieveAllParties(); UserRepository.class);
Party receiver = null; final User receiver = userRepo.findByEmailAddress(
receiverParties.addEqualsFilter("primaryEmail", CMSConfig.getConfig()
CMSConfig .getPublishingFailureReceiver());
.getInstanceOf() final User sender = userRepo.findByEmailAddress(
.getPublicationFailureReceiver()); CMSConfig.getConfig()
if (receiverParties.next()) { .getPublishingFailureSender());
receiver = receiverParties.getParty();
}
receiverParties.close();
final PartyCollection senderParties = Party
.retrieveAllParties();
Party sender = null;
senderParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf().
getPublicationFailureReceiver());
if (senderParties.next()) {
sender = senderParties.getParty();
}
senderParties.close();
if ((sender != null) && (receiver != null)) { if ((sender != null) && (receiver != null)) {
final Writer traceWriter = new StringWriter(); final Writer traceWriter = new StringWriter();
@ -388,21 +371,25 @@ class ItemLifecycleItemPane extends BaseItemPane {
traceWriter); traceWriter);
ex.printStackTrace(printWriter); ex.printStackTrace(printWriter);
final Notification notification final Mail notification = new Mail(
= new Notification( receiver.getPrimaryEmailAddress()
sender, .getAddress(),
receiver, sender.getPrimaryEmailAddress().getAddress(),
String.format( String.format(
"Failed to publish item '%s'", "Failed to publish item '%s'",
item.getOID().toString()), item.getUuid()));
String.format( notification.setBody(String.format(
"Publishing item '%s' failed " "Publishing item '%s' failed "
+ "with error message: %s.\n\n" + "with error message: %s.\n\n"
+ "Stacktrace:\n%s", + "Stacktrace:\n%s",
item.getOID().toString(), item.getUuid(),
ex.getMessage(), ex.getMessage(),
traceWriter.toString())); traceWriter.toString()));
notification.save(); try {
notification.send();
} catch (MessagingException msgex) {
throw new UncheckedWrapperException(msgex);
}
} }
} }
@ -420,10 +407,11 @@ class ItemLifecycleItemPane extends BaseItemPane {
*/ */
} else { } else {
republish(item, false, user); republish(item, false, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) { if (CMSConfig.getConfig().isUseStreamlinedCreation()) {
throw new RedirectSignal( throw new RedirectSignal(
URL.there(state.getRequest(), URL.there(state.getRequest(),
ContentCenter.getURL()), true); CmsConstants.CONTENT_CENTER_URL),
true);
} }
} }
} }
@ -435,29 +423,24 @@ class ItemLifecycleItemPane extends BaseItemPane {
*/ */
private class Republisher implements Runnable { private class Republisher implements Runnable {
/** private final String itemUuid;
* Saves OID of item as a string. This is necessary because it is
* not possible to access to same data object instance from multiple
* threads. So we have to create a new instance a the data object in
* the run method. To avoid any sort a problems, we store the OID as
* a string and convert it back to an OID in the run method.
*/
private final String itemOid;
private final User user; private final User user;
private Republisher(final ContentItem item, User user) { private Republisher(final ContentItem item, User user) {
itemOid = item.getOID().toString(); itemUuid = item.getUuid();
this.user = user; this.user = user;
} }
@Override @Override
public void run() { public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
.newInstance(OID.valueOf( final ContentItemRepository itemRepo = cdiUtil.findBean(
itemOid)); ContentItemRepository.class);
PublishLock.getInstance().lock(item); final ContentItem item = itemRepo.findByUuid(itemUuid).get();
// PublishLock.getInstance().lock(item);
republish(item, false, user); republish(item, false, user);
PublishLock.getInstance().unlock(item); // PublishLock.getInstance().unlock(item);
} }
} }
@ -482,13 +465,15 @@ class ItemLifecycleItemPane extends BaseItemPane {
public final void actionPerformed(final ActionEvent e) { public final void actionPerformed(final ActionEvent e) {
final PageState state = e.getPageState(); final PageState state = e.getPageState();
final ContentItem item = selectedItem.getContentItem(state); final ContentItem item = selectedItem.getContentItem(state);
final User user = Web.getWebContext().getUser(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final Shiro shiro = cdiUtil.findBean(Shiro.class);
final User user = shiro.getUser();
/** /**
* jensp 2011-12-14: Execute is a thread if threaded publishing * jensp 2011-12-14: Execute is a thread if threaded publishing
* is active. * is active.
*/ */
if (CMSConfig.getInstanceOf().getThreadedPublishing()) { if (CMSConfig.getConfig().isThreadPublishing()) {
final Republisher republisher = new Republisher(item, user); final Republisher republisher = new Republisher(item, user);
final Thread thread = new Thread(republisher); final Thread thread = new Thread(republisher);
thread.setUncaughtExceptionHandler( thread.setUncaughtExceptionHandler(
@ -502,46 +487,29 @@ class ItemLifecycleItemPane extends BaseItemPane {
= new PrintWriter(strWriter); = new PrintWriter(strWriter);
ex.printStackTrace(writer); ex.printStackTrace(writer);
PublishLock.getInstance().setError(item, strWriter // PublishLock.getInstance().setError(item, strWriter
.toString()); // .toString());
LOGGER.error(String.format( LOGGER.error(String.format(
"An error occurred while " "An error occurred while "
+ "publishing the item '%s': ", + "publishing the item '%s': ",
item.getOID().toString()), item.getUuid()), ex);
ex);
if ((CMSConfig.getInstanceOf(). if ((CMSConfig.getConfig().
getPublicationFailureSender() getPublishingFailureSender() == null)
== null) && (CMSConfig.getConfig().
&& (CMSConfig.getInstanceOf(). getPublishingFailureReceiver()
getPublicationFailureReceiver()
== null)) { == null)) {
return; return;
} }
final PartyCollection receiverParties = Party final UserRepository userRepo = cdiUtil.findBean(
.retrieveAllParties(); UserRepository.class);
Party receiver = null; final User receiver = userRepo.findByEmailAddress(
receiverParties.addEqualsFilter("primaryEmail", CMSConfig.getConfig()
CMSConfig .getPublishingFailureReceiver());
.getInstanceOf() final User sender = userRepo.findByEmailAddress(
.getPublicationFailureReceiver()); CMSConfig.getConfig()
if (receiverParties.next()) { .getPublishingFailureSender());
receiver = receiverParties.getParty();
}
receiverParties.close();
final PartyCollection senderParties = Party
.retrieveAllParties();
Party sender = null;
senderParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf().
getPublicationFailureReceiver());
if (senderParties.next()) {
sender = senderParties.getParty();
}
senderParties.close();
if ((sender != null) && (receiver != null)) { if ((sender != null) && (receiver != null)) {
final Writer traceWriter = new StringWriter(); final Writer traceWriter = new StringWriter();
@ -549,21 +517,25 @@ class ItemLifecycleItemPane extends BaseItemPane {
traceWriter); traceWriter);
ex.printStackTrace(printWriter); ex.printStackTrace(printWriter);
final Notification notification final Mail notification = new Mail(
= new Notification( receiver.getPrimaryEmailAddress()
sender, .getAddress(),
receiver, sender.getPrimaryEmailAddress().getAddress(),
String.format( String.format(
"Failed to publish item '%s'", "Failed to publish item '%s'",
item.getOID().toString()), item.getUuid()));
String.format( notification.setBody(String.format(
"Publishing item '%s' failed " "Publishing item '%s' failed "
+ "with error message: %s.\n\n" + "with error message: %s.\n\n"
+ "Stacktrace:\n%s", + "Stacktrace:\n%s",
item.getOID().toString(), item.getUuid(),
ex.getMessage(), ex.getMessage(),
traceWriter.toString())); traceWriter.toString()));
notification.save(); try {
notification.send();
} catch (MessagingException msgex) {
throw new UncheckedWrapperException(msgex);
}
} }
} }
@ -581,10 +553,11 @@ class ItemLifecycleItemPane extends BaseItemPane {
* jensp 2011-12-14 end * jensp 2011-12-14 end
*/ */
republish(item, true, user); republish(item, true, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) { if (CMSConfig.getConfig().isUseStreamlinedCreation()) {
throw new RedirectSignal( throw new RedirectSignal(
URL.there(state.getRequest(), URL.there(state.getRequest(),
ContentCenter.getURL()), true); CmsConstants.CONTENT_CENTER_URL),
true);
} }
} }
} }
@ -596,29 +569,23 @@ class ItemLifecycleItemPane extends BaseItemPane {
*/ */
private class Republisher implements Runnable { private class Republisher implements Runnable {
/** private final String itemUuid;
* Saves OID of item as a string. This is necessary because it is
* not possible to access to same data object instance from multiple
* threads. So we have to create a new instance a the data object in
* the run method. To avoid any sort a problems, we store the OID as
* a string and convert it back to an OID in the run method.
*/
private final String itemOid;
private final User user; private final User user;
private Republisher(final ContentItem item, User user) { private Republisher(final ContentItem item, User user) {
itemOid = item.getOID().toString(); itemUuid = item.getUuid();
this.user = user; this.user = user;
} }
@Override @Override
public void run() { public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
.newInstance(OID.valueOf( final ContentItemRepository itemRepo = cdiUtil.findBean(
itemOid)); ContentItemRepository.class);
PublishLock.getInstance().lock(item); final ContentItem item = itemRepo.findByUuid(itemUuid).get();
// PublishLock.getInstance().lock(item);
republish(item, true, user); republish(item, true, user);
PublishLock.getInstance().unlock(item); // PublishLock.getInstance().unlock(item);
} }
} }
@ -678,18 +645,17 @@ class ItemLifecycleItemPane extends BaseItemPane {
final SingleSelect actionSelect = new SingleSelect( final SingleSelect actionSelect = new SingleSelect(
LIFECYCLE_ACTION); LIFECYCLE_ACTION);
actionSelect.addOption(new Option(REPUBLISH, (String) gz( actionSelect.addOption(new Option(
"cms.ui.item.lifecycle.republish") REPUBLISH,
.localize())); new Label(gz("cms.ui.item.lifecycle.republish"))));
if (!ContentSection.getConfig().hideResetLifecycleLink()) { if (!CMSConfig.getConfig().isHideResetLifecycleLink()) {
actionSelect.addOption(new Option(REPUBLISH_AND_RESET, actionSelect.addOption(new Option(
(String) gz( REPUBLISH_AND_RESET,
"cms.ui.item.lifecycle.republish_and_reset") new Label(gz("cms.ui.item.lifecycle.republish_and_reset"))));
.localize()));
} }
actionSelect.addOption(new Option(UNPUBLISH, (String) gz( actionSelect.addOption(new Option(
"cms.ui.item.lifecycle.unpublish") UNPUBLISH,
.localize())); new Label(gz("cms.ui.item.lifecycle.unpublish"))));
submit = new Submit(gz("cms.ui.item.lifecycle.do")); submit = new Submit(gz("cms.ui.item.lifecycle.do"));
notAuthorized = new Label(gz( notAuthorized = new Label(gz(
@ -705,15 +671,17 @@ class ItemLifecycleItemPane extends BaseItemPane {
} }
@Override @Override
public void init(FormSectionEvent fse) throws FormProcessException { public void init(final FormSectionEvent event)
final PageState state = fse.getPageState(); throws FormProcessException {
final PageState state = event.getPageState();
final ContentItem item = selectedItem.getContentItem(state); final ContentItem item = selectedItem.getContentItem(state);
final SecurityManager sm = Utilities.getSecurityManager(state); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
if (sm.canAccess(state.getRequest(), if (permissionChecker.isPermitted(ItemPrivileges.PUBLISH, item)) {
SecurityManager.PUBLISH,
item)) {
submit.setVisible(state, true); submit.setVisible(state, true);
notAuthorized.setVisible(state, false); notAuthorized.setVisible(state, false);
} else { } else {
@ -723,11 +691,14 @@ class ItemLifecycleItemPane extends BaseItemPane {
} }
@Override @Override
public void process(final FormSectionEvent fse) throws public void process(final FormSectionEvent event)
FormProcessException { throws FormProcessException {
final PageState state = fse.getPageState();
final FormData data = fse.getFormData(); final PageState state = event.getPageState();
final User user = Web.getWebContext().getUser(); final FormData data = event.getFormData();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final Shiro shiro = cdiUtil.findBean(Shiro.class);
final User user = shiro.getUser();
String selected = (String) data.get(LIFECYCLE_ACTION); String selected = (String) data.get(LIFECYCLE_ACTION);
final ContentItem item = selectedItem.getContentItem(state); final ContentItem item = selectedItem.getContentItem(state);
@ -737,7 +708,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
* threaded publishing is active. * threaded publishing is active.
*/ */
if (REPUBLISH.equals(selected)) { if (REPUBLISH.equals(selected)) {
if (CMSConfig.getInstanceOf().getThreadedPublishing()) { if (CMSConfig.getConfig().isThreadPublishing()) {
final RepublishRunner runner = new RepublishRunner(item, final RepublishRunner runner = new RepublishRunner(item,
user); user);
final Thread thread = new Thread(runner); final Thread thread = new Thread(runner);
@ -752,46 +723,30 @@ class ItemLifecycleItemPane extends BaseItemPane {
= new PrintWriter(strWriter); = new PrintWriter(strWriter);
ex.printStackTrace(writer); ex.printStackTrace(writer);
PublishLock.getInstance().setError(item, strWriter // PublishLock.getInstance().setError(item, strWriter
.toString()); // .toString());
LOGGER.error(String.format( LOGGER.error(String.format(
"An error occurred while " "An error occurred while "
+ "publishing the item '%s': ", + "publishing the item '%s': ",
item.getOID().toString()), item.getUuid()), ex);
ex);
if ((CMSConfig.getInstanceOf(). if ((CMSConfig.getConfig()
getPublicationFailureSender() .getPublishingFailureSender()
== null) == null)
&& (CMSConfig.getInstanceOf(). && (CMSConfig.getConfig()
getPublicationFailureReceiver() .getPublishingFailureReceiver()
== null)) { == null)) {
return; return;
} }
final PartyCollection receiverParties = Party final UserRepository userRepo = cdiUtil.findBean(
.retrieveAllParties(); UserRepository.class);
Party receiver = null; final User receiver = userRepo.findByEmailAddress(
receiverParties.addEqualsFilter("primaryEmail", CMSConfig.getConfig()
CMSConfig .getPublishingFailureReceiver());
.getInstanceOf() final User sender = userRepo.findByEmailAddress(
.getPublicationFailureReceiver()); CMSConfig.getConfig()
if (receiverParties.next()) { .getPublishingFailureSender());
receiver = receiverParties.getParty();
}
receiverParties.close();
final PartyCollection senderParties = Party
.retrieveAllParties();
Party sender = null;
senderParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf().
getPublicationFailureReceiver());
if (senderParties.next()) {
sender = senderParties.getParty();
}
senderParties.close();
if ((sender != null) && (receiver != null)) { if ((sender != null) && (receiver != null)) {
final Writer traceWriter = new StringWriter(); final Writer traceWriter = new StringWriter();
@ -799,21 +754,25 @@ class ItemLifecycleItemPane extends BaseItemPane {
traceWriter); traceWriter);
ex.printStackTrace(printWriter); ex.printStackTrace(printWriter);
final Notification notification final Mail notification = new Mail(
= new Notification( receiver.getPrimaryEmailAddress()
sender, .getAddress(),
receiver, sender.getPrimaryEmailAddress().getAddress(),
String.format( String.format(
"Failed to publish item '%s'", "Failed to publish item '%s'",
item.getOID().toString()), item.getUuid()));
String.format( notification.setBody(String.format(
"Publishing item '%s' failed " "Publishing item '%s' failed "
+ "with error message: %s.\n\n" + "with error message: %s.\n\n"
+ "Stacktrace:\n%s", + "Stacktrace:\n%s",
item.getOID().toString(), item.getUuid(),
ex.getMessage(), ex.getMessage(),
traceWriter.toString())); traceWriter.toString()));
notification.save(); try {
notification.send();
} catch (MessagingException msgex) {
throw new UncheckedWrapperException(msgex);
}
} }
} }
@ -829,14 +788,14 @@ class ItemLifecycleItemPane extends BaseItemPane {
} else { } else {
republish(item, false, user); republish(item, false, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) { if (CMSConfig.getConfig().isUseStreamlinedCreation()) {
throw new RedirectSignal( throw new RedirectSignal(
URL.there(state.getRequest(), URL.there(state.getRequest(),
ContentCenter.getURL()), true); CmsConstants.CONTENT_CENTER_URL), true);
} }
} }
} else if (REPUBLISH_AND_RESET.equals(selected)) { } else if (REPUBLISH_AND_RESET.equals(selected)) {
if (CMSConfig.getInstanceOf().getThreadedPublishing()) { if (CMSConfig.getConfig().isThreadPublishing()) {
final RepublishAndResetRunner runner final RepublishAndResetRunner runner
= new RepublishAndResetRunner( = new RepublishAndResetRunner(
item, user); item, user);
@ -852,46 +811,30 @@ class ItemLifecycleItemPane extends BaseItemPane {
= new PrintWriter(strWriter); = new PrintWriter(strWriter);
ex.printStackTrace(writer); ex.printStackTrace(writer);
PublishLock.getInstance().setError(item, strWriter // PublishLock.getInstance().setError(item, strWriter
.toString()); // .toString());
LOGGER.error(String.format( LOGGER.error(String.format(
"An error occurred while " "An error occurred while "
+ "publishing the item '%s': ", + "publishing the item '%s': ",
item.getOID().toString()), item.getUuid()), ex);
ex);
if ((CMSConfig.getInstanceOf(). if ((CMSConfig.getConfig()
getPublicationFailureSender() .getPublishingFailureSender()
== null) == null)
&& (CMSConfig.getInstanceOf(). && (CMSConfig.getConfig()
getPublicationFailureReceiver() .getPublishingFailureReceiver()
== null)) { == null)) {
return; return;
} }
final PartyCollection receiverParties = Party final UserRepository userRepo = cdiUtil.findBean(
.retrieveAllParties(); UserRepository.class);
Party receiver = null; final User receiver = userRepo.findByEmailAddress(
receiverParties.addEqualsFilter("primaryEmail", CMSConfig.getConfig()
CMSConfig .getPublishingFailureReceiver());
.getInstanceOf() final User sender = userRepo.findByEmailAddress(
.getPublicationFailureReceiver()); CMSConfig.getConfig()
if (receiverParties.next()) { .getPublishingFailureSender());
receiver = receiverParties.getParty();
}
receiverParties.close();
final PartyCollection senderParties = Party
.retrieveAllParties();
Party sender = null;
senderParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf().
getPublicationFailureReceiver());
if (senderParties.next()) {
sender = senderParties.getParty();
}
senderParties.close();
if ((sender != null) && (receiver != null)) { if ((sender != null) && (receiver != null)) {
final Writer traceWriter = new StringWriter(); final Writer traceWriter = new StringWriter();
@ -899,21 +842,25 @@ class ItemLifecycleItemPane extends BaseItemPane {
traceWriter); traceWriter);
ex.printStackTrace(printWriter); ex.printStackTrace(printWriter);
final Notification notification final Mail notification = new Mail(
= new Notification( receiver.getPrimaryEmailAddress()
sender, .getAddress(),
receiver, sender.getPrimaryEmailAddress().getAddress(),
String.format( String.format(
"Failed to publish item '%s'", "Failed to publish item '%s'",
item.getOID().toString()), item.getUuid()));
String.format( notification.setBody(String.format(
"Publishing item '%s' failed " "Publishing item '%s' failed "
+ "with error message: %s.\n\n" + "with error message: %s.\n\n"
+ "Stacktrace:\n%s", + "Stacktrace:\n%s",
item.getOID().toString(), item.getUuid(),
ex.getMessage(), ex.getMessage(),
traceWriter.toString())); traceWriter.toString()));
notification.save(); try {
notification.send();
} catch (MessagingException msgex) {
throw new UncheckedWrapperException(msgex);
}
} }
} }
@ -929,14 +876,16 @@ class ItemLifecycleItemPane extends BaseItemPane {
} else { } else {
republish(item, true, user); republish(item, true, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) { if (CMSConfig.getConfig().isUseStreamlinedCreation()) {
throw new RedirectSignal( throw new RedirectSignal(
URL.there(state.getRequest(), URL.there(state.getRequest(),
ContentCenter.getURL()), true); CmsConstants.CONTENT_CENTER_URL), true);
} }
} }
} else if (UNPUBLISH.equals(selected)) { } else if (UNPUBLISH.equals(selected)) {
item.unpublish(); final ContentItemManager itemManager = cdiUtil.findBean(
ContentItemManager.class);
itemManager.unpublish(item);
} else { } else {
throw new IllegalArgumentException("Illegal selection"); throw new IllegalArgumentException("Illegal selection");
} }
@ -944,72 +893,60 @@ class ItemLifecycleItemPane extends BaseItemPane {
private class RepublishRunner implements Runnable { private class RepublishRunner implements Runnable {
/** private final String itemUuid;
* Saves OID of item as a string. This is necessary because it is
* not possible to access to same data object instance from multiple
* threads. So we have to create a new instance a the data object in
* the run method. To avoid any sort a problems, we store the OID as
* a string and convert it back to an OID in the run method.
*/
private final String itemOid;
private final User user; private final User user;
private RepublishRunner(final ContentItem item, User user) { private RepublishRunner(final ContentItem item,
itemOid = item.getOID().toString(); final User user) {
itemUuid = item.getUuid();
this.user = user; this.user = user;
} }
private void doRepublish() { private void doRepublish() {
final ContentItem item = (ContentItem) DomainObjectFactory final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
.newInstance(OID.valueOf( final ContentItemRepository itemRepo = cdiUtil.findBean(
itemOid)); ContentItemRepository.class);
final ContentItem item = itemRepo.findByUuid(itemUuid).get();
republish(item, false, user); republish(item, false, user);
} }
@Override @Override
public void run() { public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory // PublishLock.getInstance().lock(item);
.newInstance(OID.valueOf(
itemOid));
PublishLock.getInstance().lock(item);
doRepublish(); doRepublish();
PublishLock.getInstance().unlock(item); // PublishLock.getInstance().unlock(item);
} }
} }
private class RepublishAndResetRunner implements Runnable { private class RepublishAndResetRunner implements Runnable {
/** private final String itemUuid;
* Saves OID of item as a string. This is necessary because it is
* not possible to access to same data object instance from multiple
* threads. So we have to create a new instance a the data object in
* the run method. To avoid any sort a problems, we store the OID as
* a string and convert it back to an OID in the run method.
*/
private final String itemOid;
private final User user; private final User user;
private RepublishAndResetRunner(final ContentItem item, User user) { private RepublishAndResetRunner(final ContentItem item,
itemOid = item.getOID().toString(); final User user) {
itemUuid = item.getUuid();
this.user = user; this.user = user;
} }
private void doRepublishAndReset() { private void doRepublishAndReset() {
final ContentItem item = (ContentItem) DomainObjectFactory final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
.newInstance(OID.valueOf( final ContentItemRepository itemRepo = cdiUtil.findBean(
itemOid)); ContentItemRepository.class);
final ContentItem item = itemRepo.findByUuid(itemUuid).get();
republish(item, true, user); republish(item, true, user);
} }
@Override @Override
public void run() { public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
.newInstance(OID.valueOf( final ContentItemRepository itemRepo = cdiUtil.findBean(
itemOid)); ContentItemRepository.class);
PublishLock.getInstance().lock(item); final ContentItem item = itemRepo.findByUuid(itemUuid).get();
// PublishLock.getInstance().lock(item);
doRepublishAndReset(); doRepublishAndReset();
PublishLock.getInstance().unlock(item); // PublishLock.getInstance().unlock(item);
} }
} }

View File

@ -0,0 +1,137 @@
/*
* 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.lifecycle;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.globalization.GlobalizedMessage;
import org.arsdigita.cms.CMSConfig;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionConfig;
import org.librecms.lifecycle.Phase;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
* @author Xixi D'Moon <xdmoon@arsdigita.com>
* @author Michael Pih
* @author Justin Ross <jross@redhat.com>
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class ItemPhaseTableModelBuilder extends AbstractTableModelBuilder {
private final LifecycleRequestLocal lifecycle;
public ItemPhaseTableModelBuilder(final LifecycleRequestLocal lifecycle) {
this.lifecycle = lifecycle;
}
@Override
public final TableModel makeModel(final Table table,
final PageState state) {
return new Model(lifecycle.getLifecycle(state).getPhases());
}
private static class Model implements TableModel {
private final List<Phase> phases;
private int index = -1;
private Phase phase;
public Model(final List<Phase> phases) {
this.phases = phases;
}
@Override
public final int getColumnCount() {
return 4;
}
@Override
public final boolean nextRow() {
index++;
if (index < phases.size()) {
phase = phases.get(index);
return true;
} else {
return false;
}
}
@Override
public final Object getElementAt(final int column) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final GlobalizationHelper globalizationHelper = cdiUtil
.findBean(GlobalizationHelper.class);
final Locale locale = globalizationHelper.getNegotiatedLocale();
final DateFormat format;
if (CMSConfig.getConfig().isHideTimezone()) {
format = DateFormat.getDateTimeInstance(
DateFormat.FULL, DateFormat.SHORT, locale);
} else {
format = DateFormat.getDateTimeInstance(
DateFormat.FULL, DateFormat.FULL, locale);
}
switch (column) {
case 0:
return phase.getDefinition().getLabel().getValue(locale);
case 1:
return phase.getDefinition().getDescription().getValue(
locale);
case 2:
final Date startDate = phase.getStartDateTime();
return format.format(startDate);
case 3:
final Date endDate = phase.getEndDateTime();
if (endDate == null) {
return lz("cms.ui.lifecycle.forever");
} else {
return format.format(endDate);
}
default:
throw new IllegalArgumentException();
}
}
@Override
public final Object getKeyAt(final int column) {
return phase.getDefinition().getDefinitionId();
}
}
protected final static String lz(final String key) {
final GlobalizedMessage message = new GlobalizedMessage(key,
CmsConstants.CMS_BUNDLE);
return (String) message.localize();
}
}

View File

@ -36,6 +36,7 @@ import org.librecms.lifecycle.PhaseDefinition;
import com.arsdigita.cms.ui.BaseItemPane; import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.kernel.KernelConfig; import com.arsdigita.kernel.KernelConfig;
import com.arsdigita.toolbox.ui.ActionGroup; import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.Property;
import com.arsdigita.toolbox.ui.PropertyList; import com.arsdigita.toolbox.ui.PropertyList;
import com.arsdigita.toolbox.ui.Section; import com.arsdigita.toolbox.ui.Section;

View File

@ -38,26 +38,27 @@ import java.util.List;
class PhaseTableModelBuilder extends LockableImpl class PhaseTableModelBuilder extends LockableImpl
implements TableModelBuilder { implements TableModelBuilder {
private final LifecycleDefinitionRequestLocal m_cycle; private final LifecycleDefinitionRequestLocal cycle;
public PhaseTableModelBuilder public PhaseTableModelBuilder
(final LifecycleDefinitionRequestLocal cycle) { (final LifecycleDefinitionRequestLocal cycle) {
m_cycle = cycle; this.cycle = cycle;
} }
@Override
public final TableModel makeModel(final Table table, public final TableModel makeModel(final Table table,
final PageState state) { final PageState state) {
return new PhaseTableModel(m_cycle.getLifecycleDefinition(state)); return new PhaseTableModel(cycle.getLifecycleDefinition(state));
} }
private static class PhaseTableModel implements TableModel { private static class PhaseTableModel implements TableModel {
private PhaseDefinition m_phase;
private final List<PhaseDefinition> m_phases; private final List<PhaseDefinition> phases;
private int index = -1; private int index = -1;
private PhaseDefinition phase;
public PhaseTableModel(final LifecycleDefinition cycle) { public PhaseTableModel(final LifecycleDefinition cycle) {
m_phases = cycle.getPhaseDefinitions(); phases = cycle.getPhaseDefinitions();
m_phase = null;
} }
@Override @Override
@ -68,8 +69,8 @@ class PhaseTableModelBuilder extends LockableImpl
@Override @Override
public final boolean nextRow() { public final boolean nextRow() {
index++; index++;
if (index < m_phases.size()) { if (index < phases.size()) {
m_phase = m_phases.get(index); phase = phases.get(index);
return true; return true;
} else { } else {
@ -79,17 +80,17 @@ class PhaseTableModelBuilder extends LockableImpl
@Override @Override
public final Object getElementAt(final int column) { public final Object getElementAt(final int column) {
Assert.exists(m_phase, "PhaseDefinition m_phase"); Assert.exists(phase, "PhaseDefinition m_phase");
switch (column) { switch (column) {
case 0: case 0:
return m_phase.getLabel(); return phase.getLabel();
case 1: case 1:
return m_phase.getDescription(); return phase.getDescription();
case 2: case 2:
return Duration.formatDuration(m_phase.getDefaultDelay()); return Duration.formatDuration(phase.getDefaultDelay());
case 3: case 3:
final Long duration = m_phase.getDefaultDuration(); final Long duration = phase.getDefaultDuration();
if (duration == null) { if (duration == null) {
return lz("cms.ui.lifecycle.forever"); return lz("cms.ui.lifecycle.forever");
@ -105,11 +106,12 @@ class PhaseTableModelBuilder extends LockableImpl
} }
} }
@Override
public Object getKeyAt(int columnIndex) { public Object getKeyAt(int columnIndex) {
if (m_phase == null) { if (phase == null) {
throw new IllegalStateException(); throw new IllegalStateException();
} else { } else {
return m_phase.getDefinitionId(); return phase.getDefinitionId();
} }
} }
} }

View File

@ -0,0 +1,362 @@
/*
* 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.revision;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.GridPanel;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.RadioGroup;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
import com.arsdigita.bebop.table.DefaultTableColumnModel;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableColumnModel;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.toolbox.ui.NullComponent;
import com.arsdigita.toolbox.ui.Section;
import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSectionManager;
import java.math.BigInteger;
/**
* Displays the revision history of a {@link ContentItem}
*
* @author unknown
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*
*/
public final class ItemRevisionAdminPane extends BaseItemPane {
private final ContentItemRequestLocal itemRequestLocal;
private final RevisionTable revisionsTable;
private final RevisionRequestLocal fromRequestLocal;
private final RevisionRequestLocal toRequestLocal;
private final LayoutPanel selectPane;
//ToDo
//private final DifferencePane diffPane;
public ItemRevisionAdminPane(final ContentItemRequestLocal itemRequestLocal) {
this.itemRequestLocal = itemRequestLocal;
final RadioGroup fromSelect = new RadioGroup("from");
final RadioGroup toSelect = new RadioGroup("to");
fromRequestLocal = new SelectionRequestLocal(fromSelect);
toRequestLocal = new SelectionRequestLocal(toSelect);
revisionsTable = new RevisionTable(fromSelect, toSelect);
final RevisionForm form = new RevisionForm(fromSelect, toSelect,
revisionsTable);
selectPane = new LayoutPanel();
add(selectPane);
setDefault(selectPane);
selectPane.setBody(new Section(gz("cms.ui.item.revisions"), form));
final ActionLink returnLink = new ActionLink(new Label(gz(
"cms.ui.item.revision.return")));
// Todo
// diffPane = new DifferencePane(itemRequestLocal,
// fromRequestLocal,
// toRequestLocal,
// returnLink);
// add(diffPane);
//
// connect(form, diffPane);
connect(returnLink, selectPane);
}
private class SelectionRequestLocal extends RevisionRequestLocal {
private final RadioGroup group;
SelectionRequestLocal(final RadioGroup group) {
this.group = group;
}
@Override
protected final Object initialValue(final PageState state) {
final Object selected = group.getValue(state);
if (selected == null || selected.toString().equals("")) {
return null;
} else {
final long revisionNumber = Long.parseLong(selected.toString());
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepository = cdiUtil.findBean(
ContentItemRepository.class);
return itemRepository.retrieveRevision(revisionNumber);
}
}
}
private class RevisionForm extends Form {
RevisionForm(final RadioGroup fromSelect,
final RadioGroup toSelect,
final RevisionTable revisions) {
super("revisions", new GridPanel(1));
setMethod("get");
add(fromSelect);
add(toSelect);
// Sets the 'to' revision to the dummy current revision
// and the 'from' revision to the dummy root revision.
fromSelect.setOptionSelected("");
toSelect.setOptionSelected("");
final ActionGroup group = new ActionGroup();
add(group);
group.setSubject(revisions);
group.addAction(new Submit("diff",
gz("cms.ui.item.revision.difference.show")));
}
}
private class RevisionTable extends Table {
// XXX Need to fix the static l18n stuff
private final TableColumn fromCol = new TableColumn(
RevisionTableModelBuilder.FROM, lz("cms.ui.item.revision.from"));
private final TableColumn toCol = new TableColumn(
RevisionTableModelBuilder.TO,
lz("cms.ui.item.revision.to"));
private final TableColumn timestampCol = new TableColumn(
RevisionTableModelBuilder.TIMESTAMP, lz("cms.ui.item.revision"));
private final TableColumn userCol = new TableColumn(
RevisionTableModelBuilder.USER, lz("cms.ui.user"));
private final TableColumn descriptionCol = new TableColumn(
RevisionTableModelBuilder.DESCRIPTION, lz("cms.ui.description"));
private final TableColumn previewCol = new TableColumn(
RevisionTableModelBuilder.PREVIEW, lz("cms.ui.item.revision.view"));
private final TableColumn rollbackCol = new TableColumn(
RevisionTableModelBuilder.ROLLBACK,
lz("cms.ui.item.revision.rollback"));
public RevisionTable(final RadioGroup fromSelect,
final RadioGroup toSelect) {
super(new RevisionTableModelBuilder(itemRequestLocal),
new DefaultTableColumnModel());
final TableColumnModel columns = getColumnModel();
columns.add(fromCol);
columns.add(toCol);
columns.add(timestampCol);
columns.add(userCol);
columns.add(descriptionCol);
columns.add(previewCol);
columns.add(rollbackCol);
fromCol.setCellRenderer(new RadioCellRenderer(fromSelect));
toCol.setCellRenderer(new RadioCellRenderer(toSelect));
timestampCol.setCellRenderer(new DefaultTableCellRenderer(false));
userCol.setCellRenderer(new DefaultTableCellRenderer(false));
descriptionCol.setCellRenderer(new DefaultTableCellRenderer(false));
previewCol.setCellRenderer(new ViewCellRenderer());
rollbackCol.setCellRenderer(new RollbackCellRenderer());
setEmptyView(new Label(gz("cms.ui.item.revision.none")));
addTableActionListener(new RollbackActionListener());
}
class RadioCellRenderer implements TableCellRenderer {
private final RadioGroup group;
RadioCellRenderer(final RadioGroup group) {
this.group = group;
}
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
switch (key.toString()) {
case "first":
if (column == RevisionTableModelBuilder.FROM) {
return new NullComponent();
} else {
final Option option = new Option("", new Text(""));
option.setGroup(group);
return option;
}
case "last":
if (column == RevisionTableModelBuilder.FROM) {
final Option option = new Option("", "");
option.setGroup(group);
return option;
} else {
return new NullComponent();
}
default:
final Option option = new Option(key.toString(),
new Text(""));
option.setGroup(group);
return option;
}
}
}
class ViewCellRenderer implements TableCellRenderer {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
if (key instanceof String) {
return new NullComponent();
} else {
final BigInteger transID = (BigInteger) key;
final ContentItem item = itemRequestLocal.getContentItem(
state);
final ContentSection section = item.getContentType()
.getContentSection();
final ContentSectionManager sectionManager = CdiUtil
.createCdiUtil().findBean(ContentSectionManager.class);
final ItemResolver itemResolver = sectionManager
.getItemResolver(section);
final StringBuffer url = new StringBuffer(itemResolver
.generateItemURL(state, item, section,
CMSDispatcher.PREVIEW));
// Cheesy code should be fixed
final String sep;
if (url.toString().indexOf('?') == -1) {
sep = "?";
} else {
sep = "&";
}
// TODO: fix this
//url.append(sep).append
// (HistoryCollection.TRANS_ID).append("=");
url.append(sep).append("transID").append("=");
url.append(transID.toString());
final Link link = new Link(new Label(gz(
"cms.ui.item.revision.view")),
url.toString());
link.setTargetFrame(lz("cms.ui.item.revision.view"));
return link;
}
}
}
class RollbackActionListener extends TableActionAdapter {
@Override
public final void cellSelected(final TableActionEvent event) {
final PageState state = event.getPageState();
if (event.getColumn() == RevisionTableModelBuilder.ROLLBACK) {
final ContentItem item = itemRequestLocal.getContentItem(
state);
//Rollback not supported yet
// Versions.rollback(item.getOID(),
// new BigInteger(event.getRowKey()
// .toString()));
//
// item.applyTag(lz("cms.ui.item.revision.rolled_back"));
}
}
}
class RollbackCellRenderer implements TableCellRenderer {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
if (key instanceof String) {
return new NullComponent();
} else {
return new ControlLink(new Label(gz(
"cms.ui.item.revision.rollback")));
}
}
}
}
}

View File

@ -1,316 +0,0 @@
/*
* 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.revision;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.GridPanel;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.RadioGroup;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
import com.arsdigita.bebop.table.DefaultTableColumnModel;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableColumnModel;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.toolbox.ui.NullComponent;
import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.versioning.Transaction;
import com.arsdigita.versioning.Versions;
import java.math.BigInteger;
/**
*
* @version $Id: ItemRevisionAdminPane.java 287 2005-02-22 00:29:02Z sskracic $
*/
public final class ItemRevisionAdminPane extends BaseItemPane {
private final ContentItemRequestLocal m_item;
private final RevisionTable m_revisions;
private final TransactionRequestLocal m_from;
private final TransactionRequestLocal m_to;
private final LayoutPanel m_selectPane;
private final DifferencePane m_diffPane;
public ItemRevisionAdminPane(final ContentItemRequestLocal item) {
m_item = item;
final RadioGroup fromSelect = new RadioGroup("from");
final RadioGroup toSelect = new RadioGroup("to");
m_from = new SelectionRequestLocal(fromSelect);
m_to = new SelectionRequestLocal(toSelect);
m_revisions = new RevisionTable(fromSelect, toSelect);
final RevisionForm form = new RevisionForm
(fromSelect, toSelect, m_revisions);
m_selectPane = new LayoutPanel();
add(m_selectPane);
setDefault(m_selectPane);
m_selectPane.setBody
(new Section(gz("cms.ui.item.revisions"), form));
final ActionLink returnLink = new ActionLink
(new Label(gz("cms.ui.item.revision.return")));
m_diffPane = new DifferencePane(m_item, m_from, m_to, returnLink);
add(m_diffPane);
connect(form, m_diffPane);
connect(returnLink, m_selectPane);
}
private class SelectionRequestLocal extends TransactionRequestLocal {
private final RadioGroup m_group;
SelectionRequestLocal(final RadioGroup group) {
m_group = group;
}
protected final Object initialValue(final PageState state) {
final Object id = m_group.getValue(state);
if (id == null || id.toString().equals("")) {
return null;
} else {
return Transaction.retrieve(new BigInteger(id.toString()));
}
}
}
private class RevisionForm extends Form {
RevisionForm(final RadioGroup fromSelect,
final RadioGroup toSelect,
final RevisionTable revisions) {
super("revisions", new GridPanel(1));
setMethod("get");
add(fromSelect);
add(toSelect);
// Sets the 'to' revision to the dummy current revision
// and the 'from' revision to the dummy root revision.
fromSelect.setOptionSelected("");
toSelect.setOptionSelected("");
final ActionGroup group = new ActionGroup();
add(group);
group.setSubject(revisions);
group.addAction
(new Submit("diff",
gz("cms.ui.item.revision.difference.show")));
}
}
private class RevisionTable extends Table {
// XXX Need to fix the static l18n stuff
private TableColumn m_from = new TableColumn
(RevisionTableModelBuilder.FROM, lz("cms.ui.item.revision.from"));
private TableColumn m_to = new TableColumn
(RevisionTableModelBuilder.TO, lz("cms.ui.item.revision.to"));
private TableColumn m_timestamp = new TableColumn
(RevisionTableModelBuilder.TIMESTAMP, lz("cms.ui.item.revision"));
private TableColumn m_user = new TableColumn
(RevisionTableModelBuilder.USER, lz("cms.ui.user"));
private TableColumn m_description = new TableColumn
(RevisionTableModelBuilder.DESCRIPTION, lz("cms.ui.description"));
private TableColumn m_preview = new TableColumn
(RevisionTableModelBuilder.PREVIEW, lz("cms.ui.item.revision.view"));
private TableColumn m_rollback = new TableColumn
(RevisionTableModelBuilder.ROLLBACK,
lz("cms.ui.item.revision.rollback"));
public RevisionTable(final RadioGroup fromSelect,
final RadioGroup toSelect) {
super(new RevisionTableModelBuilder(m_item),
new DefaultTableColumnModel());
final TableColumnModel columns = getColumnModel();
columns.add(m_from);
columns.add(m_to);
columns.add(m_timestamp);
columns.add(m_user);
columns.add(m_description);
columns.add(m_preview);
columns.add(m_rollback);
m_from.setCellRenderer(new RadioCellRenderer(fromSelect));
m_to.setCellRenderer(new RadioCellRenderer(toSelect));
m_timestamp.setCellRenderer(new DefaultTableCellRenderer(false));
m_user.setCellRenderer(new DefaultTableCellRenderer(false));
m_description.setCellRenderer(new DefaultTableCellRenderer(false));
m_preview.setCellRenderer(new ViewCellRenderer());
m_rollback.setCellRenderer(new RollbackCellRenderer());
setEmptyView(new Label(gz("cms.ui.item.revision.none")));
addTableActionListener(new RollbackActionListener());
}
class RadioCellRenderer implements TableCellRenderer {
private final RadioGroup m_group;
RadioCellRenderer(final RadioGroup group) {
m_group = group;
}
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row, final int column) {
if (key.toString().equals("first")) {
if (column == RevisionTableModelBuilder.FROM) {
return new NullComponent();
} else {
final Option option = new Option("", "");
option.setGroup(m_group);
return option;
}
} else if (key.toString().equals("last")) {
if (column == RevisionTableModelBuilder.FROM) {
final Option option = new Option("", "");
option.setGroup(m_group);
return option;
} else {
return new NullComponent();
}
} else {
final Option option = new Option(key.toString(), "");
option.setGroup(m_group);
return option;
}
}
}
class ViewCellRenderer implements TableCellRenderer {
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row, final int column) {
if (key instanceof String) {
return new NullComponent();
} else {
final BigInteger transID = (BigInteger) key;
final ContentItem item = m_item.getContentItem(state);
final ContentSection section = item.getContentSection();
final ItemResolver itemResolver =
section.getItemResolver();
final StringBuffer url = new StringBuffer
(itemResolver.generateItemURL
(state, item, section, CMSDispatcher.PREVIEW));
// Cheesy code should be fixed
final String sep;
if (url.toString().indexOf('?') == -1) {
sep = "?";
} else {
sep = "&";
}
// TODO: fix this
//url.append(sep).append
// (HistoryCollection.TRANS_ID).append("=");
url.append(sep).append("transID").append("=");
url.append(transID.toString());
final Link link = new Link
(new Label(gz("cms.ui.item.revision.view")),
url.toString());
link.setTargetFrame(lz("cms.ui.item.revision.view"));
return link;
}
}
}
class RollbackActionListener extends TableActionAdapter {
public final void cellSelected(final TableActionEvent e) {
final PageState state = e.getPageState();
if (e.getColumn().intValue()
== RevisionTableModelBuilder.ROLLBACK) {
final ContentItem item = m_item.getContentItem(state);
Versions.rollback
(item.getOID(),
new BigInteger(e.getRowKey().toString()));
item.applyTag(lz("cms.ui.item.revision.rolled_back"));
}
}
}
class RollbackCellRenderer implements TableCellRenderer {
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row, final int column) {
if (key instanceof String) {
return new NullComponent();
} else {
return new ControlLink
(new Label(gz("cms.ui.item.revision.rollback")));
}
}
}
}
}

View File

@ -0,0 +1,33 @@
/*
* 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.revision;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.RequestLocal;
import org.libreccm.auditing.CcmRevision;
public abstract class RevisionRequestLocal extends RequestLocal {
public final CcmRevision getRevision(final PageState state) {
final CcmRevision revision = (CcmRevision) get(state);
return revision;
}
}

View File

@ -0,0 +1,164 @@
/*
* 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.revision;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.globalization.GlobalizedMessage;
import org.libreccm.security.User;
import com.arsdigita.toolbox.ui.FormatStandards;
import org.libreccm.auditing.CcmRevision;
import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemRepository;
import java.util.List;
/**
* @author Stanislav Freidin &lt;sfreidin@redhat.com&gt;
* @author Justin Ross &lt;jross@redhat.com&gt;
* @version $Id: RevisionTableModelBuilder.java 1942 2009-05-29 07:53:23Z terry
* $
*/
class RevisionTableModelBuilder extends AbstractTableModelBuilder {
static final int FROM = 0;
static final int TO = 1;
static final int TIMESTAMP = 2;
static final int USER = 3;
static final int DESCRIPTION = 4;
static final int PREVIEW = 5;
static final int ROLLBACK = 6;
static final int COLUMNS = 7;
private final ContentItemRequestLocal itemRequestLocal;
RevisionTableModelBuilder(final ContentItemRequestLocal itemRequestLocal) {
this.itemRequestLocal = itemRequestLocal;
}
@Override
public final TableModel makeModel(final Table table,
final PageState state) {
return new Model(itemRequestLocal.getContentItem(state));
}
private static class Model implements TableModel {
private final List<CcmRevision> revisions;
private CcmRevision currentRevision;
private long count = 0;
private long last = 2;
private int index = -1;
public Model(final ContentItem item) {
final ContentItemRepository itemRepository = CdiUtil
.createCdiUtil()
.findBean(ContentItemRepository.class);
revisions = itemRepository.retrieveRevisions(item,
item.getObjectId());
last = revisions.size() + 2;
}
@Override
public final int getColumnCount() {
return COLUMNS;
}
@Override
public final boolean nextRow() {
count++;
index++;
if (count == 1) {
return true;
} else if (count == last) {
return true;
} else if (revisions.size() < index) {
currentRevision = revisions.get(index);
return true;
} else {
return false;
}
}
@Override
public final Object getElementAt(final int column) {
if (count == 1) {
switch (column) {
case TIMESTAMP:
return lz("cms.ui.item.revision.current");
default:
return "";
}
} else if (count == last) {
switch (column) {
case TIMESTAMP:
return lz("cms.ui.item.revision.first");
default:
return "";
}
} else {
switch (column) {
case TIMESTAMP:
return FormatStandards.formatDateTime(
currentRevision.getRevisionDate());
case USER:
return currentRevision.getUserName();
case DESCRIPTION:
return "";
default:
return "";
}
}
}
@Override
public final Object getKeyAt(final int column) {
if (count == 1) {
return "first";
} else if (count == last) {
return "last";
} else {
return currentRevision.getId();
}
}
}
private static GlobalizedMessage gz(final String key) {
return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
}
private static String lz(final String key) {
return (String) gz(key).localize();
}
}

View File

@ -44,8 +44,17 @@ public abstract class AbstractAuditedEntityRepository<K, T>
public abstract K getEntityId(final T entity); public abstract K getEntityId(final T entity);
/**
* Retrieves an entity at specific revision. The entity will be in the state
* as it was when the revision was created.
*
* @param entity
* @param revision
*
* @return
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T retrieveRevisionOfEntity(final T entity, final Number revision) { public T retrieveEntityAtRevision(final T entity, final Number revision) {
final AuditQuery query = auditReader.createQuery() final AuditQuery query = auditReader.createQuery()
.forEntitiesAtRevision(getEntityClass(), revision); .forEntitiesAtRevision(getEntityClass(), revision);
query.add(AuditEntity.id().eq(getEntityId(entity))); query.add(AuditEntity.id().eq(getEntityId(entity)));
@ -104,7 +113,7 @@ public abstract class AbstractAuditedEntityRepository<K, T>
* Retrieves all revisions of the given entity. The list of revisions is * Retrieves all revisions of the given entity. The list of revisions is
* ordered from the oldest revision to the newest revision. * ordered from the oldest revision to the newest revision.
* *
* @param entity The entity. * @param entity The entity.
* @param objectId The primary key of the entity. * @param objectId The primary key of the entity.
* *
* @return A list of all revisions of the provided entity. * @return A list of all revisions of the provided entity.
@ -123,8 +132,9 @@ public abstract class AbstractAuditedEntityRepository<K, T>
/** /**
* Retrieves the current revision of an entity. * Retrieves the current revision of an entity.
* *
* @param entity The entity. * @param entity The entity.
* @param objectId the primary key the entity. * @param objectId the primary key the entity.
*
* @return The most current revision of the entity. * @return The most current revision of the entity.
*/ */
public CcmRevision retrieveCurrentRevision(final T entity, public CcmRevision retrieveCurrentRevision(final T entity,
@ -136,4 +146,17 @@ public abstract class AbstractAuditedEntityRepository<K, T>
return auditReader.findRevision(CcmRevision.class, lastRevision); return auditReader.findRevision(CcmRevision.class, lastRevision);
} }
/**
* Retrieves a specific revision object.
*
* @param entity
* @param objectId
* @param revision
*
* @return
*/
public CcmRevision retrieveRevision(final Number revision) {
return auditReader.findRevision(CcmRevision.class, revision);
}
} }

View File

@ -64,6 +64,10 @@ import org.libreccm.portation.Portable;
@Table(name = "WORKFLOWS", schema = DB_SCHEMA) @Table(name = "WORKFLOWS", schema = DB_SCHEMA)
@Inheritance(strategy = InheritanceType.JOINED) @Inheritance(strategy = InheritanceType.JOINED)
@NamedQueries({ @NamedQueries({
@NamedQuery(
name = "Workflow.findByUuid",
query = "SELECT W FROM Workflow w WHERE w.uuid = :uuid")
,
@NamedQuery( @NamedQuery(
name = "Workflow.findForObject", name = "Workflow.findForObject",
query = "SELECT w FROM Workflow w " query = "SELECT w FROM Workflow w "

View File

@ -52,22 +52,48 @@ public class WorkflowRepository extends AbstractEntityRepository<Long, Workflow>
workflow.setUuid(UUID.randomUUID().toString()); workflow.setUuid(UUID.randomUUID().toString());
} }
/**
* Find a {@link Workflow} by its UUID.
*
* @param uuid The UUID of the {@link Workflow} to find.
*
* @return An {@link Optional} containing the {@link Workflow} identified by
* the provided UUID.
*/
public Optional<Workflow> findByUuid(final String uuid) {
if (uuid == null || uuid.trim().isEmpty()) {
throw new IllegalArgumentException(
"The UUID of the Workflow to retrieve can't be null or empty.");
}
final TypedQuery<Workflow> query = getEntityManager().createNamedQuery(
"Workflow.findByUuid", Workflow.class);
query.setParameter("uuid", uuid);
try {
return Optional.of(query.getSingleResult());
} catch(NoResultException ex) {
return Optional.empty();
}
}
/** /**
* Finds the workflow for an given object if the object has workflow. * Finds the workflow for an given object if the object has workflow.
* *
* @param object The object * @param object The object
*
* @return An {@link Optional} containing the workflow assigned to the * @return An {@link Optional} containing the workflow assigned to the
* {@code object} if the object has a workflow. Otherwise an empty * {@code object} if the object has a workflow. Otherwise an empty
* {@link Optional} is returned. * {@link Optional} is returned.
*/ */
public Optional<Workflow> findWorkflowForObject(final CcmObject object) { public Optional<Workflow> findWorkflowForObject(final CcmObject object) {
if (object == null) { if (object == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Can't find a workflow for object null."); "Can't find a workflow for object null.");
} }
final TypedQuery<Workflow> query = getEntityManager().createNamedQuery( final TypedQuery<Workflow> query = getEntityManager().createNamedQuery(
"Workflow.findForObject", Workflow.class); "Workflow.findForObject", Workflow.class);
query.setParameter("object", object); query.setParameter("object", object);
try { try {