Java tutorial
/* * Copyright 2013 Hippo B.V. (http://www.onehippo.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onehippo.repository.documentworkflow; import java.io.Serializable; import java.util.Calendar; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.TreeSet; import javax.jcr.PropertyType; import org.apache.commons.scxml2.model.EnterableState; import org.apache.jackrabbit.util.ISO8601; import org.hippoecm.repository.HippoStdNodeType; import org.hippoecm.repository.api.HippoNodeType; import org.hippoecm.repository.HippoStdPubWfNodeType; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.onehippo.repository.mock.MockNode; import org.onehippo.repository.mock.MockValue; import org.onehippo.repository.scxml.MockAccessManagedSession; import org.onehippo.repository.scxml.MockWorkflowContext; import org.onehippo.repository.scxml.SCXMLWorkflowExecutor; public class DocumentWorkflowTest extends BaseDocumentWorkflowTest { @BeforeClass public static void beforeClass() throws Exception { createDocumentWorkflowSCXMLRegistry(); } @AfterClass public static void afterClass() throws Exception { destroyDocumentWorkflowSCXMLRegistry(); } @SuppressWarnings("unchecked") protected static Map<?, ?> sortMap(Map<?, ?> map) { if (!(map instanceof SortedMap)) { SortedMap<Object, Object> sorted = new TreeMap<>(map); for (Map.Entry<Object, Object> entry : sorted.entrySet()) { if (entry.getValue() instanceof Map) { entry.setValue(sortMap((Map<Object, Object>) entry.getValue())); } } return sorted; } return map; } protected static Set<String> getSCXMLStatusStateIds(SCXMLWorkflowExecutor executor) { Set<EnterableState> targets = executor.getSCXMLExecutor().getCurrentStatus().getStates(); if (targets.isEmpty()) { return Collections.emptySet(); } Set<String> ids = new TreeSet<>(); for (EnterableState target : targets) { ids.add(target.getId()); } return ids; } protected static void assertMatchingSCXMLStates(SCXMLWorkflowExecutor executor, TreeSet<String> states) { Set<String> stateIds = getSCXMLStatusStateIds(executor); if (!stateIds.equals(states)) { Assert.fail("Current SCXML states not matching expected states.\n" + "States : " + stateIds + "\n" + "expected: " + states); } } protected static void assertMatchingHints(Map<String, Serializable> hints, Map<String, Serializable> expected) { if (!hints.equals(expected)) { Assert.fail("Hints map does not match expected map.\n" + "Hint map: " + sortMap(hints) + "\n" + "expected: " + sortMap(expected)); } } @Test public void testInitializeSCXML() throws Exception { MockAccessManagedSession session = new MockAccessManagedSession(MockNode.root()); MockWorkflowContext workflowContext = new MockWorkflowContext("testuser", session); DocumentWorkflowImpl wf = new DocumentWorkflowImpl(); wf.setWorkflowContext(workflowContext); MockNode handleNode = (MockNode) session.getRootNode().addNode("test", HippoNodeType.NT_HANDLE); addVariant(handleNode, HippoStdNodeType.DRAFT); wf.setNode(handleNode); wf.getWorkflowExecutor().start(); } @Test public void testVariants() throws Exception { MockAccessManagedSession session = new MockAccessManagedSession(MockNode.root()); MockWorkflowContext workflowContext = new MockWorkflowContext("testuser", session); MockNode handleNode = (MockNode) session.getRootNode().addNode("test", HippoNodeType.NT_HANDLE); DocumentWorkflowImpl wf = new DocumentWorkflowImpl(); wf.setWorkflowContext(workflowContext); wf.setNode(handleNode); // no document assertMatchingHints(wf.hints(), HintsBuilder.build().hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().noDocument().states()); MockNode publishedVariant = addVariant(handleNode, HippoStdNodeType.PUBLISHED); // set (only) author permission session.setPermissions(publishedVariant.getPath(), "hippo:author", true); // only published assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).noEdit() .editable().requestPublication(false).requestDepublication(true).listVersions() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().depublishable().noVersioning().noTerminate().noCopy().states()); MockNode unpublishedVariant = addVariant(handleNode, HippoStdNodeType.UNPUBLISHED); // set (only) author permission session.setPermissions(unpublishedVariant.getPath(), "hippo:author", true); // unpublished + published assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).noEdit() .editable().requestPublication(false).requestDepublication(true).listVersions() .retrieveVersion().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().depublishable().versionable().noTerminate().noCopy().states()); MockNode draftVariant = addVariant(handleNode, HippoStdNodeType.DRAFT); // set (only) author permission session.setPermissions(draftVariant.getPath(), "hippo:author", true); // draft + unpublished + published assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).noEdit() .editable().requestPublication(false).requestDepublication(true).listVersions() .retrieveVersion().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().depublishable().versionable().noTerminate().noCopy().states()); publishedVariant.remove(); // draft + unpublished assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(true).noEdit() .editable().requestPublication(true).requestDepublication(false).listVersions() .retrieveVersion().requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().publishable().noDepublish().versionable().terminateable().noCopy().states()); draftVariant.remove(); // unpublished assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .editable().requestPublication(true).requestDepublication(false).listVersions() .retrieveVersion().requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().publishable().noDepublish().versionable().terminateable().noCopy().states()); unpublishedVariant.remove(); addVariant(handleNode, HippoStdNodeType.DRAFT); // set (only) author permission session.setPermissions(draftVariant.getPath(), "hippo:author", true); // draft assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(false).checkModified(false) .noEdit().editable().requestPublication(false).requestDepublication(false).listVersions() .requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().noDepublish().noVersioning().terminateable().noCopy().states()); addVariant(handleNode, HippoStdNodeType.PUBLISHED); // set (only) author permission session.setPermissions(publishedVariant.getPath(), "hippo:author", true); // draft + published assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).noEdit() .editable().requestPublication(false).requestDepublication(true).listVersions() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().depublishable().noVersioning().noTerminate().noCopy().states()); } @Test public void testStatusState() throws Exception { MockAccessManagedSession session = new MockAccessManagedSession(MockNode.root()); MockWorkflowContext workflowContext = new MockWorkflowContext("testuser", session); MockNode handleNode = (MockNode) session.getRootNode().addNode("test", HippoNodeType.NT_HANDLE); DocumentWorkflowImpl wf = new DocumentWorkflowImpl(); wf.setWorkflowContext(workflowContext); wf.setNode(handleNode); MockNode draftVariant = addVariant(handleNode, HippoStdNodeType.DRAFT); // set (only) author permission session.setPermissions(draftVariant.getPath(), "hippo:author", true); // status=true (no holder) assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(false).checkModified(false) .noEdit().editable().requestPublication(false).requestDepublication(false).listVersions() .requestDelete(true).hints()); draftVariant.setProperty(HippoStdNodeType.HIPPOSTD_HOLDER, "testuser"); // status=true (holder == editor) assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(false).checkModified(false) .editing().requestPublication(false).requestDepublication(false).listVersions() .requestDelete(false).hints()); draftVariant.setProperty(HippoStdNodeType.HIPPOSTD_HOLDER, "otheruser"); // status=false (holder != editor, inUseBy=otheruser) assertMatchingHints(wf.hints(), HintsBuilder.build().status(false).isLive(false).previewAvailable(false).checkModified(false) .noEdit().inUseBy("otheruser").requestPublication(false).requestDepublication(false) .listVersions().requestDelete(false).hints()); MockNode publishedVariant = addVariant(handleNode, HippoStdNodeType.PUBLISHED); // set (only) author permission session.setPermissions(publishedVariant.getPath(), "hippo:author", true); // no/empty availability published: live + preview assertMatchingHints(wf.hints(), HintsBuilder.build().status(false).isLive(true).previewAvailable(true).checkModified(false).noEdit() .inUseBy("otheruser").requestPublication(false).requestDepublication(false).listVersions() .requestDelete(false).hints()); publishedVariant.setProperty(HippoNodeType.HIPPO_AVAILABILITY, new String[] { "foo" }); // no live|preview availability on published assertMatchingHints(wf.hints(), HintsBuilder.build().status(false).isLive(false).previewAvailable(false).checkModified(false) .noEdit().inUseBy("otheruser").requestPublication(false).requestDepublication(false) .listVersions().requestDelete(false).hints()); publishedVariant.setProperty(HippoNodeType.HIPPO_AVAILABILITY, new String[] { "live" }); // live availability on published assertMatchingHints(wf.hints(), HintsBuilder.build().status(false).isLive(true).previewAvailable(false).checkModified(false) .noEdit().inUseBy("otheruser").requestPublication(false).requestDepublication(false) .listVersions().requestDelete(false).hints()); publishedVariant.setProperty(HippoNodeType.HIPPO_AVAILABILITY, new String[] { "preview", "live" }); // live|preview availability on published assertMatchingHints(wf.hints(), HintsBuilder.build().status(false).isLive(true).previewAvailable(true).checkModified(false).noEdit() .inUseBy("otheruser").requestPublication(false).requestDepublication(false).listVersions() .requestDelete(false).hints()); MockNode unpublishedVariant = addVariant(handleNode, HippoStdNodeType.UNPUBLISHED); // set (only) author permission session.setPermissions(unpublishedVariant.getPath(), "hippo:author", true); unpublishedVariant.setProperty(HippoNodeType.HIPPO_AVAILABILITY, new String[] { "preview" }); publishedVariant.setProperty(HippoNodeType.HIPPO_AVAILABILITY, new String[] { "live" }); // live availability on published, preview availability on unpublished assertMatchingHints(wf.hints(), HintsBuilder.build().status(false).isLive(true).previewAvailable(true).checkModified(true).noEdit() .inUseBy("otheruser").requestPublication(false).requestDepublication(false).listVersions() .retrieveVersion().requestDelete(false).hints()); publishedVariant.remove(); // only preview availability on unpublished assertMatchingHints(wf.hints(), HintsBuilder.build().status(false).isLive(false).previewAvailable(true).checkModified(true).noEdit() .inUseBy("otheruser").requestPublication(false).requestDepublication(false).listVersions() .retrieveVersion().requestDelete(false).hints()); } @Test public void testEditState() throws Exception { MockAccessManagedSession session = new MockAccessManagedSession(MockNode.root()); MockWorkflowContext workflowContext = new MockWorkflowContext("testuser", session); MockNode handleNode = (MockNode) session.getRootNode().addNode("test", HippoNodeType.NT_HANDLE); DocumentWorkflowImpl wf = new DocumentWorkflowImpl(); wf.setWorkflowContext(workflowContext); wf.setNode(handleNode); MockNode draftVariant = addVariant(handleNode, HippoStdNodeType.DRAFT); // set (only) author permission session.setPermissions(draftVariant.getPath(), "hippo:author", true); // not editing, no request pending: editable assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(false).checkModified(false) .noEdit().editable().requestPublication(false).requestDepublication(false).listVersions() .requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().noDepublish().noVersioning().terminateable().noCopy().states()); draftVariant.setProperty(HippoStdNodeType.HIPPOSTD_HOLDER, "otheruser"); // editing, no request pending: editing assertMatchingHints(wf.hints(), HintsBuilder.build().status(false).isLive(false).previewAvailable(false).checkModified(false) .noEdit().inUseBy("otheruser").requestPublication(false).requestDepublication(false) .listVersions().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editing() .noRequest().noPublish().noDepublish().noVersioning().noTerminate().noCopy().states()); session.setPermissions(draftVariant.getPath(), "hippo:admin", true); // editing, no request pending, admin: editing, unlock assertMatchingHints(wf.hints(), HintsBuilder.build().status(false).isLive(false).previewAvailable(false).checkModified(false) .noEdit().inUseBy("otheruser").unlock(true).requestPublication(false) .requestDepublication(false).listVersions().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editing() .noRequest().noPublish().noDepublish().noVersioning().noTerminate().noCopy().states()); draftVariant.setProperty(HippoStdNodeType.HIPPOSTD_HOLDER, "testuser"); // editor, no request pending (, admin): editing, edit assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(false).checkModified(false) .editing().requestPublication(false).requestDepublication(false).listVersions() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editing() .noRequest().noPublish().noDepublish().noVersioning().noTerminate().noCopy().states()); draftVariant.getProperty(HippoStdNodeType.HIPPOSTD_HOLDER).remove(); MockNode rejectedRequest = addRequest(handleNode, HippoStdPubWfNodeType.REJECTED, true); // not editing, request rejected, admin: editable, unlock=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(false).checkModified(false) .noEdit().editable().unlock(false).cancelRequest(rejectedRequest.getIdentifier()) .requestPublication(false).requestDepublication(false).listVersions().requestDelete(true) .hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .requested().noPublish().noDepublish().noVersioning().terminateable().noCopy().states()); session.setPermissions(draftVariant.getPath(), "hippo:author", true); MockNode publishRequest = addRequest(handleNode, HippoStdPubWfNodeType.PUBLISH, true); // not editing, publish request: no-edit assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(false) .checkModified(false).noEdit().cancelRequest(rejectedRequest.getIdentifier()) .acceptRequest(publishRequest.getIdentifier(), false).cancelRequest(publishRequest.getIdentifier()) .rejectRequest(publishRequest.getIdentifier()).requestPublication(false).requestDepublication(false) .listVersions().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().noPublish().noDepublish().noVersioning().terminateable().noCopy().states()); } @Test public void testRequestState() throws Exception { MockAccessManagedSession session = new MockAccessManagedSession(MockNode.root()); MockWorkflowContext workflowContext = new MockWorkflowContext("testuser", session); MockNode handleNode = (MockNode) session.getRootNode().addNode("test", HippoNodeType.NT_HANDLE); DocumentWorkflowImpl wf = new DocumentWorkflowImpl(); wf.setWorkflowContext(workflowContext); wf.setNode(handleNode); // test state not-requested MockNode unpublishedVariant = addVariant(handleNode, HippoStdNodeType.UNPUBLISHED); session.setPermissions(unpublishedVariant.getPath(), "hippo:author", true); // no-request assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .editable().requestPublication(true).requestDepublication(false).listVersions() .retrieveVersion().requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().publishable().noDepublish().versionable().terminateable().noCopy().states()); MockNode publishRequest = addRequest(handleNode, HippoStdPubWfNodeType.PUBLISH, true); publishRequest.setProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_USERNAME, "testuser"); session.setPermissions(publishRequest.getPath(), "hippo:author", true); // author user publish request: cancelRequest=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .cancelRequest(publishRequest.getIdentifier()).requestPublication(false) .requestDepublication(false).listVersions().retrieveVersion().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().publishable().noDepublish().versionable().terminateable().noCopy().states()); publishRequest.setProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_USERNAME, "otheruser"); // author and other user publish request: no-op assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .requestPublication(false).requestDepublication(false).listVersions().retrieveVersion() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().publishable().noDepublish().versionable().terminateable().noCopy().states()); session.setPermissions(publishRequest.getPath(), "hippo:editor", true); // editor other user publish request: acceptRequest=true,rejectRequest=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .acceptRequest(publishRequest.getIdentifier(), true) .rejectRequest(publishRequest.getIdentifier()).requestPublication(false) .requestDepublication(false).listVersions().retrieveVersion().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().publishable().noDepublish().versionable().terminateable().noCopy().states()); MockNode publishedVariant = addVariant(handleNode, HippoStdNodeType.PUBLISHED); session.setPermissions(publishedVariant.getPath(), "hippo:author", true); // editor other user publish request but unmodified: acceptRequest=false,rejectRequest=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).noEdit() .acceptRequest(publishRequest.getIdentifier(), false) .rejectRequest(publishRequest.getIdentifier()).requestPublication(false) .requestDepublication(false).listVersions().retrieveVersion().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().noPublish().depublishable().versionable().noTerminate().noCopy().states()); publishRequest.setProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_USERNAME, "testuser"); // editor own publish request but unmodified: acceptRequest=false,rejectRequest=true,cancelRequest=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).noEdit() .acceptRequest(publishRequest.getIdentifier(), false) .rejectRequest(publishRequest.getIdentifier()).cancelRequest(publishRequest.getIdentifier()) .requestPublication(false).requestDepublication(false).listVersions().retrieveVersion() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().noPublish().depublishable().versionable().noTerminate().noCopy().states()); publishRequest.remove(); MockNode depublishRequest = addRequest(handleNode, HippoStdPubWfNodeType.DEPUBLISH, true); depublishRequest.setProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_USERNAME, "testuser"); session.setPermissions(depublishRequest.getPath(), "hippo:editor", true); // editor own depublish request live: acceptRequest=true,rejectRequest=true,cancelRequest=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).noEdit() .acceptRequest(depublishRequest.getIdentifier(), true) .rejectRequest(depublishRequest.getIdentifier()) .cancelRequest(depublishRequest.getIdentifier()).requestPublication(false) .requestDepublication(false).listVersions().retrieveVersion().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().noPublish().depublishable().versionable().noTerminate().noCopy().states()); publishedVariant.setProperty(HippoNodeType.HIPPO_AVAILABILITY, new String[] { "preview" }); // editor own depublish request !live: acceptRequest=false,rejectRequest=true,cancelRequest=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .acceptRequest(depublishRequest.getIdentifier(), false) .rejectRequest(depublishRequest.getIdentifier()) .cancelRequest(depublishRequest.getIdentifier()).requestPublication(false) .requestDepublication(false).listVersions().retrieveVersion().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().publishable().noDepublish().versionable().terminateable().noCopy().states()); depublishRequest.remove(); MockNode deleteRequest = addRequest(handleNode, HippoStdPubWfNodeType.DELETE, true); deleteRequest.setProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_USERNAME, "testuser"); session.setPermissions(deleteRequest.getPath(), "hippo:editor", true); // editor own delete request !live: acceptRequest=true,rejectRequest=true,cancelRequest=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .acceptRequest(deleteRequest.getIdentifier(), true) .rejectRequest(deleteRequest.getIdentifier()).cancelRequest(deleteRequest.getIdentifier()) .requestPublication(false).requestDepublication(false).listVersions().retrieveVersion() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().publishable().noDepublish().versionable().terminateable().noCopy().states()); publishedVariant.setProperty(HippoNodeType.HIPPO_AVAILABILITY, new String[] { "preview", "live" }); // editor own delete request !live: acceptRequest=false,rejectRequest=true,cancelRequest=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).noEdit() .acceptRequest(deleteRequest.getIdentifier(), false) .rejectRequest(deleteRequest.getIdentifier()).cancelRequest(deleteRequest.getIdentifier()) .requestPublication(false).requestDepublication(false).listVersions().retrieveVersion() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().noPublish().depublishable().versionable().noTerminate().noCopy().states()); deleteRequest.remove(); publishedVariant.remove(); MockNode rejectedRequest = addRequest(handleNode, HippoStdPubWfNodeType.REJECTED, true); rejectedRequest.setProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_USERNAME, "otheruser"); session.setPermissions(rejectedRequest.getPath(), "hippo:editor", true); // editor other user rejected request: no-op assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .editable().requestPublication(true).requestDepublication(false).listVersions() .retrieveVersion().requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .requested().publishable().noDepublish().versionable().terminateable().noCopy().states()); rejectedRequest.setProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_USERNAME, "testuser"); // editor own rejected request: cancelRequest=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .editable().cancelRequest(rejectedRequest.getIdentifier()).requestPublication(true) .requestDepublication(false).listVersions().retrieveVersion().requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .requested().publishable().noDepublish().versionable().terminateable().noCopy().states()); session.setPermissions(rejectedRequest.getPath(), "hippo:author", true); // author own rejected request: cancelRequest=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .editable().cancelRequest(rejectedRequest.getIdentifier()).requestPublication(true) .requestDepublication(false).listVersions().retrieveVersion().requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .requested().publishable().noDepublish().versionable().terminateable().noCopy().states()); rejectedRequest.setProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_USERNAME, "otheruser"); // author other user rejected request: no-op assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .editable().requestPublication(true).requestDepublication(false).listVersions() .retrieveVersion().requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .requested().publishable().noDepublish().versionable().terminateable().noCopy().states()); rejectedRequest.remove(); MockNode scheduledRequest = addRequest(handleNode, HippoStdPubWfNodeType.PUBLISH, false); session.setPermissions(scheduledRequest.getPath(), "hippo:editor", true); // editor scheduled request: cancelRequest=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .cancelRequest(scheduledRequest.getIdentifier()).requestPublication(false) .requestDepublication(false).listVersions().retrieveVersion().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().publishable().noDepublish().versionable().terminateable().noCopy().states()); session.setPermissions(scheduledRequest.getPath(), "hippo:author", true); // author scheduled request: no-op assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .requestPublication(false).requestDepublication(false).listVersions().retrieveVersion() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().publishable().noDepublish().versionable().terminateable().noCopy().states()); } @Test public void testPublishState() throws Exception { MockAccessManagedSession session = new MockAccessManagedSession(MockNode.root()); MockNode handleNode = (MockNode) session.getRootNode().addNode("test", HippoNodeType.NT_HANDLE); MockWorkflowContext workflowContext = new MockWorkflowContext("testuser", session); DocumentWorkflowImpl wf = new DocumentWorkflowImpl(); wf.setWorkflowContext(workflowContext); wf.setNode(handleNode); MockNode draftVariant = addVariant(handleNode, HippoStdNodeType.DRAFT); session.setPermissions(draftVariant.getPath(), "hippo:author", true); draftVariant.setProperty(HippoStdNodeType.HIPPOSTD_HOLDER, "testuser"); MockNode unpublishedVariant = addVariant(handleNode, HippoStdNodeType.UNPUBLISHED); session.setPermissions(unpublishedVariant.getPath(), "hippo:author", true); // author, no request, editing, modified (unpublished): requestPublication=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(true).editing() .requestPublication(false).requestDepublication(false).listVersions().retrieveVersion() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editing() .noRequest().noPublish().noDepublish().versionable().noTerminate().noCopy().states()); session.setPermissions(unpublishedVariant.getPath(), "hippo:editor", true); // editor, no request, editing, modified (unpublished): requestPublication=false,publish=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(true).editing() .requestPublication(false).publish(false).requestDepublication(false).depublish(false) .listVersions().retrieveVersion().versionable().requestDelete(false).terminateable(false) .copy().hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editing() .noRequest().noPublish().noDepublish().versionable().noTerminate().copyable().states()); MockNode publishedVariant = addVariant(handleNode, HippoStdNodeType.PUBLISHED); session.setPermissions(publishedVariant.getPath(), "hippo:author", true); draftVariant.getProperty(HippoStdNodeType.HIPPOSTD_HOLDER).remove(); // editor, no request, !editing, !modified (unpublished==published): requestPublication=false,publish=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).noEdit() .editable().requestPublication(false).publish(false).requestDepublication(true) .listVersions().retrieveVersion().versionable().requestDelete(false).terminateable(false) .hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().depublishable().versionable().noTerminate().noCopy().states()); // make unpublished modified Calendar publishedModified = Calendar.getInstance(); Calendar unpublishedModified = Calendar.getInstance(); publishedModified.setTimeInMillis(unpublishedModified.getTimeInMillis() - 1000); unpublishedVariant.setProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_LAST_MODIFIED_DATE, new MockValue(PropertyType.DATE, ISO8601.format(unpublishedModified))); publishedVariant.setProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_LAST_MODIFIED_DATE, new MockValue(PropertyType.DATE, ISO8601.format(publishedModified))); // editor, no request, !editing, modified (unpublished!=published): requestPublication=true,publish=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).noEdit() .editable().requestPublication(true).publish(true).requestDepublication(true).listVersions() .retrieveVersion().versionable().requestDelete(false).terminateable(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().publishable().depublishable().versionable().noTerminate().noCopy().states()); session.setPermissions(unpublishedVariant.getPath(), "hippo:author", true); // author, no request, !editing, modified (unpublished!=published): requestPublication=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).noEdit() .editable().requestPublication(true).requestDepublication(true).listVersions() .retrieveVersion().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().publishable().depublishable().versionable().noTerminate().noCopy().states()); MockNode scheduledRequest = addRequest(handleNode, HippoStdPubWfNodeType.PUBLISH, false); session.setPermissions(scheduledRequest.getPath(), "hippo:author", true); // author, request, !editing, modified (unpublished!=published): requestPublication=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).noEdit() .requestPublication(false).requestDepublication(false).listVersions().retrieveVersion() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().publishable().depublishable().versionable().noTerminate().noCopy().states()); workflowContext.setUserIdentity("system"); session.setPermissions(unpublishedVariant.getPath(), "hippo:editor", true); // system, request, !editing, modified (unpublished!=published): requestPublication=true,publish=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).noEdit() .requestPublication(true).publish(true).requestDepublication(true).listVersions() .retrieveVersion().versionable().requestDelete(false).terminateable(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().publishable().depublishable().versionable().noTerminate().noCopy().states()); } @Test public void testDePublishState() throws Exception { MockAccessManagedSession session = new MockAccessManagedSession(MockNode.root()); MockNode handleNode = (MockNode) session.getRootNode().addNode("test", HippoNodeType.NT_HANDLE); MockWorkflowContext workflowContext = new MockWorkflowContext("testuser", session); DocumentWorkflowImpl wf = new DocumentWorkflowImpl(); wf.setWorkflowContext(workflowContext); wf.setNode(handleNode); MockNode draftVariant = addVariant(handleNode, HippoStdNodeType.DRAFT); session.setPermissions(draftVariant.getPath(), "hippo:author", true); draftVariant.setProperty(HippoStdNodeType.HIPPOSTD_HOLDER, "testuser"); MockNode unpublishedVariant = addVariant(handleNode, HippoStdNodeType.UNPUBLISHED); session.setPermissions(unpublishedVariant.getPath(), "hippo:author", true); MockNode publishedVariant = addVariant(handleNode, HippoStdNodeType.PUBLISHED); session.setPermissions(publishedVariant.getPath(), "hippo:author", true); // author, no request, editing, live: requestDepublication=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).editing() .requestPublication(false).requestDepublication(false).listVersions().retrieveVersion() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editing() .noRequest().noPublish().noDepublish().versionable().noTerminate().noCopy().states()); session.setPermissions(publishedVariant.getPath(), "hippo:editor", true); // editor, no request, editing, live: requestDepublication=false,depublish=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).editing() .requestPublication(false).requestDepublication(false).depublish(false).listVersions() .retrieveVersion().requestDelete(false).copy().hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editing() .noRequest().noPublish().noDepublish().versionable().noTerminate().copyable().states()); draftVariant.getProperty(HippoStdNodeType.HIPPOSTD_HOLDER).remove(); publishedVariant.setProperty(HippoNodeType.HIPPO_AVAILABILITY, new String[] {}); // editor, no request, !editing, !live: requestDepublication=false,depublish=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(true).noEdit() .editable().requestPublication(true).requestDepublication(false).depublish(false) .listVersions().retrieveVersion().requestDelete(true).copy().hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().publishable().noDepublish().versionable().terminateable().copyable().states()); publishedVariant.setProperty(HippoNodeType.HIPPO_AVAILABILITY, new String[] { "live" }); // editor, no request, !editing, live: requestDepublication=true,depublish=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).noEdit() .editable().requestPublication(false).requestDepublication(true).depublish(true) .listVersions().retrieveVersion().requestDelete(false).copy().hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().depublishable().versionable().noTerminate().copyable().states()); session.setPermissions(publishedVariant.getPath(), "hippo:author", true); // author, no request, !editing, live: requestDepublication=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).noEdit() .editable().requestPublication(false).requestDepublication(true).listVersions() .retrieveVersion().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().depublishable().versionable().noTerminate().noCopy().states()); MockNode scheduledRequest = addRequest(handleNode, HippoStdPubWfNodeType.PUBLISH, false); session.setPermissions(scheduledRequest.getPath(), "hippo:author", true); // author, request, !editing, live: requestDepublication=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).noEdit() .requestPublication(false).requestDepublication(false).listVersions().retrieveVersion() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().noPublish().depublishable().versionable().noTerminate().noCopy().states()); workflowContext.setUserIdentity("system"); session.setPermissions(publishedVariant.getPath(), "hippo:editor", true); // system, request, !editing, live: requestDepublication=true,depublish=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(true).noEdit() .requestPublication(false).requestDepublication(true).depublish(true).listVersions() .retrieveVersion().requestDelete(false).copy().hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().noPublish().depublishable().versionable().noTerminate().copyable().states()); } @Test public void testVersioningState() throws Exception { MockAccessManagedSession session = new MockAccessManagedSession(MockNode.root()); MockNode handleNode = (MockNode) session.getRootNode().addNode("test", HippoNodeType.NT_HANDLE); MockWorkflowContext workflowContext = new MockWorkflowContext("testuser", session); DocumentWorkflowImpl wf = new DocumentWorkflowImpl(); wf.setWorkflowContext(workflowContext); wf.setNode(handleNode); MockNode draftVariant = addVariant(handleNode, HippoStdNodeType.DRAFT); session.setPermissions(draftVariant.getPath(), "hippo:author", true); // no unpublished: (only) listVersions=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(false).checkModified(false) .noEdit().editable().requestPublication(false).requestDepublication(false).listVersions() .requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().noDepublish().noVersioning().terminateable().noCopy().states()); draftVariant.remove(); MockNode unpublishedVariant = addVariant(handleNode, HippoStdNodeType.UNPUBLISHED); session.setPermissions(unpublishedVariant.getPath(), "hippo:author", true); // author, unpublished: listVersions=true, retrieveVersion=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .editable().requestPublication(true).requestDepublication(false).listVersions() .retrieveVersion().requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().publishable().noDepublish().versionable().terminateable().noCopy().states()); session.setPermissions(unpublishedVariant.getPath(), "hippo:editor", true); // author, unpublished: listVersions=true, retrieveVersion=true, versionable assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(true).checkModified(false).noEdit() .editable().requestPublication(true).publish(true).requestDepublication(false) .depublish(false).listVersions().retrieveVersion().versionable().requestDelete(true) .terminateable(true).copy().hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().publishable().noDepublish().versionable().terminateable().copyable().states()); } @Test public void testTerminateState() throws Exception { MockAccessManagedSession session = new MockAccessManagedSession(MockNode.root()); MockNode folderNode = (MockNode) session.getRootNode().addNode("folder", HippoNodeType.NT_DOCUMENT); session.setPermissions(folderNode.getPath(), "jcr:write", false); MockNode handleNode = (MockNode) folderNode.addNode("test", HippoNodeType.NT_HANDLE); MockWorkflowContext workflowContext = new MockWorkflowContext("testuser", session); DocumentWorkflowImpl wf = new DocumentWorkflowImpl(); wf.setWorkflowContext(workflowContext); wf.setNode(handleNode); MockNode draftVariant = addVariant(handleNode, HippoStdNodeType.DRAFT); session.setPermissions(draftVariant.getPath(), "hippo:author", true); draftVariant.setProperty(HippoStdNodeType.HIPPOSTD_HOLDER, "testuser"); MockNode publishedVariant = addVariant(handleNode, HippoStdNodeType.PUBLISHED); session.setPermissions(publishedVariant.getPath(), "hippo:author", true); // author, editing, live: requestDelete=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).editing() .requestPublication(false).requestDepublication(false).listVersions().requestDelete(false) .hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editing() .noRequest().noPublish().noDepublish().noVersioning().noTerminate().noCopy().states()); session.setPermissions(publishedVariant.getPath(), "hippo:editor", true); // editor, editing, live: requestDelete=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).editing() .requestPublication(false).publish(false).requestDepublication(false).depublish(false) .listVersions().requestDelete(false).copy().hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editing() .noRequest().noPublish().noDepublish().noVersioning().noTerminate().copyable().states()); session.setPermissions(folderNode.getPath(), "jcr:write", true); // editor + writable containing folder, editing, live: requestDelete=false, terminateable=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).editing() .requestPublication(false).publish(false).requestDepublication(false).depublish(false) .listVersions().requestDelete(false).terminateable(false).copy().hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editing() .noRequest().noPublish().noDepublish().noVersioning().noTerminate().copyable().states()); session.setPermissions(publishedVariant.getPath(), "hippo:author", true); // author + writable containing folder, editing, live: requestDelete=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).editing() .requestPublication(false).requestDepublication(false).listVersions().requestDelete(false) .hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editing() .noRequest().noPublish().noDepublish().noVersioning().noTerminate().noCopy().states()); draftVariant.getProperty(HippoStdNodeType.HIPPOSTD_HOLDER).remove(); publishedVariant.setProperty(HippoNodeType.HIPPO_AVAILABILITY, new String[0]); MockNode scheduledRequest = addRequest(handleNode, HippoStdPubWfNodeType.PUBLISH, false); // author + writable containing folder, !editing, !live, request: requestDelete=false assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(false).checkModified(false) .noEdit().cancelRequest(scheduledRequest.getIdentifier()).requestPublication(false) .requestDepublication(false).listVersions().requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().noEdit() .requested().noPublish().noDepublish().noVersioning().terminateable().noCopy().states()); scheduledRequest.remove(); // author + writable containing folder, !editing, !live: requestDelete=true assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(false).checkModified(false) .noEdit().editable().requestPublication(false).requestDepublication(false).listVersions() .requestDelete(true).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().noDepublish().noVersioning().terminateable().noCopy().states()); session.setPermissions(publishedVariant.getPath(), "hippo:editor", true); // editor + writable containing folder, !editing, !live: requestDelete=true, terminateable assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(false).previewAvailable(false).checkModified(false) .noEdit().editable().requestPublication(false).publish(false).requestDepublication(false) .depublish(false).listVersions().requestDelete(true).terminateable(true).copy().hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().noDepublish().noVersioning().terminateable().copyable().states()); } @Test public void testCopyState() throws Exception { MockAccessManagedSession session = new MockAccessManagedSession(MockNode.root()); MockNode handleNode = (MockNode) session.getRootNode().addNode("test", HippoNodeType.NT_HANDLE); MockWorkflowContext workflowContext = new MockWorkflowContext("testuser", session); DocumentWorkflowImpl wf = new DocumentWorkflowImpl(); wf.setWorkflowContext(workflowContext); wf.setNode(handleNode); MockNode publishedVariant = addVariant(handleNode, HippoStdNodeType.PUBLISHED); session.setPermissions(publishedVariant.getPath(), "hippo:author", true); // author, published: no-copy assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).noEdit() .editable().requestPublication(false).requestDepublication(true).listVersions() .requestDelete(false).hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().depublishable().noVersioning().noTerminate().noCopy().states()); session.setPermissions(publishedVariant.getPath(), "hippo:editor", true); // editor, published: copy assertMatchingHints(wf.hints(), HintsBuilder.build().status(true).isLive(true).previewAvailable(true).checkModified(false).noEdit() .editable().requestPublication(false).publish(false).requestDepublication(true) .depublish(true).listVersions().requestDelete(false).terminateable(false).copy().hints()); assertMatchingSCXMLStates(wf.getWorkflowExecutor(), StatesBuilder.build().status().logEvent().editable() .noRequest().noPublish().depublishable().noVersioning().noTerminate().copyable().states()); } }