Index: bccm-diff-master-modules.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- bccm-diff-master-modules.xml (revision 238722)
+++ bccm-diff-master-modules.xml (revision )
@@ -589,4 +589,1180 @@
+
+
+ <?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Copyright 2013-2014 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.
+ -->
+<scxml version="1.0"
+ xmlns="http://www.w3.org/2005/07/scxml"
+ xmlns:hippo="http://www.onehippo.org/cms7/repository/scxml"
+ xmlns:cs="http://commons.apache.org/scxml">
+
+ <script>
+ def getScxmlId() { workflowContext.scxmlId }
+ // draft variant property method
+ def getDraft() { workflowData.documents['draft'] }
+ // unpublished variant property method
+ def getUnpublished() { workflowData.documents['unpublished'] }
+ // published variant property method
+ def getPublished() { workflowData.documents['published'] }
+ // current user property method
+ def getUser() { workflowContext.user }
+ // current requests map property method
+ def getRequests() { workflowData.requests }
+ // returns the variant for copying and checking copy access privileges
+ def getCopySource() { published ?: unpublished ?: null }
+ // returns the variant for deleting and checking delete privileges
+ def getDeleteSource() { unpublished ?: published ?: draft }
+ // returns the current draft holder (editor) if defined (and draft exists)
+ def getHolder() { draft?.holder }
+ // true if draft exists and currently being edited
+ def boolean isEditing() { !!holder }
+ // true if draft exists and edited by current user
+ def boolean isEditor() { holder == user }
+ // true if draft exists and not currently editor or edited by current user
+ def boolean isEditable() { !holder or editor }
+ // true if published variant exists with availability 'live'
+ def boolean isLive() { published?.isAvailable('live') }
+ // true if unpublished variant exists with availability 'preview'
+ def boolean isPreview() { unpublished?.isAvailable('preview') }
+ // true if either unpublished or published variant exits with availability 'preview'
+ def boolean isPreviewAvailable() { unpublished?.isAvailable('preview') or published?.isAvailable('preview') }
+ // true if unpublished variant exists and no published variant exists with availability 'live'
+ // or they have a different lastModified
+ def boolean isModified() { unpublished and (!live or unpublished.lastModified!=published.lastModified) }
+ // true if there is an outstanding workflow request
+ def boolean isRequestPending() { workflowData.requestPending }
+ def getContainingFolder() { workflowData.handle.parent }
+ </script>
+
+ <!-- the initial no-document state is used to prevent entering the handle state if there is no document -->
+ <state id="no-document">
+ <!-- automatic transition to and continue in parallel handle state only when a document variant exists -->
+ <transition target="handle" cond="!workflowData.documents.isEmpty()"/>
+ </state>
+
+ <parallel id="handle">
+
+ <!-- the atomic status state is used to report several statuses and info feedback to the invoking workflow -->
+ <state id="status">
+ <onentry>
+ <hippo:feedback key="status" value="editable"/>
+ <hippo:feedback key="isLive" value="live"/>
+ <hippo:feedback key="previewAvailable" value="previewAvailable"/>
+ <!-- enable the checkModified operation if both draft and unpublished variants exists -->
+ <hippo:action action="checkModified" enabledExpr="draft and unpublished"/>
+ </onentry>
+
+ <!-- target-less transition on event checkModified to compare the draft and unpublished variants which result is
+ reported back as Boolean value through the 'modified' feedback variable and the workflow operation result -->
+ <transition event="checkModified">
+ <hippo:isModified/>
+ <hippo:result value="workflowContext.feedback['modified']"/>
+ </transition>
+ </state>
+
+ <!-- the composite edit state is used to manage all operations for editing a draft variant -->
+ <state id="edit">
+
+ <!-- default no-edit state initially disables all editing operations -->
+ <state id="no-edit">
+ <onentry>
+ <hippo:action action="disposeEditableInstance" enabledExpr="false"/>
+ <hippo:action action="obtainEditableInstance" enabledExpr="false"/>
+ <hippo:action action="commitEditableInstance" enabledExpr="false"/>
+ </onentry>
+ <!-- event-less transition to state "editing" if there is no pending request and the draft variant is edited -->
+ <transition target="editing" cond="!requestPending and editing"/>
+ <!-- (else) event-less transition to state "editable" if there is no pending request and the draft variant
+ doesn't exist yet or isn't edited -->
+ <transition target="editable" cond="!requestPending"/>
+ </state>
+
+ <!-- editing state becomes active when the draft variant is currently edited -->
+ <state id="editing">
+ <onentry>
+ <if cond="editor">
+ <!-- current editor is allowed all editing operations -->
+ <hippo:action action="disposeEditableInstance" enabledExpr="true"/>
+ <hippo:action action="obtainEditableInstance" enabledExpr="true"/>
+ <hippo:action action="commitEditableInstance" enabledExpr="true"/>
+ <else/>
+ <!-- for a not-current editor the current editor (holder) is reported through the 'inUseBy' feedback -->
+ <hippo:feedback key="inUseBy" value="holder"/>
+ </if>
+ <if cond="!editor and workflowContext.isGranted(draft,'hippo:admin')">
+ <!-- For an admin (granted hippo:admin) enable the unlock operation if not-current editor -->
+ <hippo:action action="unlock" enabledExpr="true"/>
+ </if>
+ </onentry>
+ </state>
+
+ <!-- editable state becomes active if editing is possible but there is no current editor -->
+ <state id="editable">
+ <onentry>
+ <if cond="workflowContext.isGranted(draft,'hippo:admin')">
+ <!-- for an admin (granted hippo:admin) report the unlock operation as available but disabled -->
+ <hippo:action action="unlock" enabledExpr="false"/>
+ </if>
+ <!-- enable the operation to start editing -->
+ <hippo:action action="obtainEditableInstance" enabledExpr="true"/>
+ </onentry>
+ </state>
+
+ <!-- target-less transition to 'dispose' an editable instance by (only) removing the current draft holder, and the
+ current unpublished document variant is returned if currently in preview state else the published variant -->
+ <transition event="disposeEditableInstance">
+ <!-- remove holder from the draft document -->
+ <hippo:setHolder holder="null"/>
+ <hippo:result value="preview ? unpublished : published"/>
+ </transition>
+
+ <!-- target-less transition to 'obtain' an editable draft document variant by creating or updating a draft variant
+ by copying (the contents of) the current unpublished variant if available or else the published variant -->
+ <transition event="obtainEditableInstance">
+ <if cond="!!unpublished">
+ <!-- unpublished document exists: copy it to draft first -->
+ <hippo:copyVariant sourceState="unpublished" targetState="draft"/>
+ <elseif cond="!!published"/>
+ <!-- else if published document exists: copy it to draft first -->
+ <hippo:copyVariant sourceState="published" targetState="draft"/>
+ </if>
+ <!-- mark the draft document as modified, set the user as editor and remove possibly copied availabilities -->
+ <hippo:configVariant variant="draft" applyModified="true" setHolder="true" availabilities=""/>
+ <!-- store the newly created or updated draft document as result -->
+ <hippo:result value="draft"/>
+ </transition>
+
+ <!-- target-less transition to 'commit' an editable instance by removing the holder and, if new or modified,
+ copying its content to the unpublished variant -->
+ <transition event="commitEditableInstance">
+ <hippo:setHolder holder="null"/>
+ <if cond="!!unpublished">
+ <!-- if unpublished variant exist only 'commit' changes if there are any -->
+ <hippo:isModified/>
+ </if>
+ <if cond="!unpublished or workflowContext.feedback['modified']">
+ <!-- we either have a new draft (no unpublished) or the draft is modified compared to the unpublished -->
+ <if cond="!unpublished and !!published">
+ <!-- we have no unpublished variant yet but do have a published variant:
+ remove possible 'preview' availability from the published variant -->
+ <if cond="live">
+ <hippo:configVariant variant="published" availabilities="live"/>
+ <else/>
+ <hippo:configVariant variant="published" availabilities=""/>
+ </if>
+ </if>
+ <!-- copy the new or modified draft variant to the unpublished variant, creating it if needed -->
+ <hippo:copyVariant sourceState="draft" targetState="unpublished"/>
+ <!-- configure the new or updated unpublished to be versionable, modified and available as 'preview' -->
+ <hippo:configVariant variant="unpublished" versionable="true" applyModified="true" availabilities="preview"/>
+ </if>
+ <!-- return the possibly updated unpublished variant -->
+ <hippo:result value="unpublished"/>
+ </transition>
+
+ <!-- target-less transition to 'unlock' the current edited draft variant by overriding its current holder
+ with that of the current invoking admin (granted hippo:admin) user. -->
+ <transition event="unlock">
+ <hippo:setHolder holder="user"/>
+ </transition>
+
+ </state>
+
+ <!-- the composite request state is used to manage all workflow operations on existing document workflow requests -->
+ <state id="request">
+
+ <!-- the initial no-request state is used and active when there are no current document workflow requests -->
+ <state id="no-request">
+ <!-- event-less transition to state "requested" when requests exists -->
+ <transition target="requested" cond="!empty(requests)"/>
+ </state>
+
+ <!-- the requested state becomes active when document workflow requests are present -->
+ <state id="requested">
+ <onentry>
+ <foreach item="request" array="requests.values()">
+ <!-- for all requests determine the available request actions and report them through the special 'requests'
+ feedback map variable -->
+ <!-- for document workflow requests: -->
+ <if cond="request.workflowRequest">
+ <if cond="workflowContext.isGranted(request, 'hippo:editor')">
+ <!-- editor users (granted hippo:editor) may reject and accept as well as cancel requests -->
+ <if cond="request.workflowType!='rejected'">
+ <!-- if request not rejected yet, enable reject operation -->
+ <hippo:requestAction identifierExpr="request.identity" action="rejectRequest" enabledExpr="true"/>
+ </if>
+ <if cond="request.workflowType=='delete'">
+ <!-- if request for delete: enable accept operation if not live and not editing -->
+ <hippo:requestAction identifierExpr="request.identity" action="acceptRequest" enabledExpr="!live and !editing"/>
+ <elseif cond="request.workflowType=='publish'">
+ <!-- if request for publish: enable accept operation if modified and not editing -->
+ <hippo:requestAction identifierExpr="request.identity" action="acceptRequest" enabledExpr="modified and !editing"/>
+ </elseif>
+ <elseif cond="request.workflowType=='depublish'"/>
+ <!-- if request for depublish: enable accept operation if live and not editing -->
+ <hippo:requestAction identifierExpr="request.identity" action="acceptRequest" enabledExpr="live and !editing"/>
+ </if>
+ <if cond="!request.owner or request.owner==user">
+ <!-- if request owner or no request owner: enable cancel operation -->
+ <hippo:requestAction identifierExpr="request.identity" action="cancelRequest" enabledExpr="true"/>
+ </if>
+ <!-- when not an editor user (not granted hippo:editor) then: -->
+ <elseif cond="request?.owner==user"/>
+ <!-- if request owner: enable cancel operation -->
+ <hippo:requestAction identifierExpr="request.identity" action="cancelRequest" enabledExpr="true"/>
+ </if>
+ <else/>
+ <!-- scheduled workflow operation -->
+ <if cond="workflowContext.isGranted(request, 'hippo:editor')">
+ <!-- if editor user (granted hippo:editor): enable cancel operation -->
+ <hippo:requestAction identifierExpr="request.identity" action="cancelRequest" enabledExpr="true"/>
+ </if>
+ </if>
+ </foreach>
+ </onentry>
+
+ <!-- target-less transition to 'accept' a specific request -->
+ <transition event="acceptRequest">
+
+ <!-- define temporary request variable for the event payload request parameter -->
+ <cs:var name="request" expr="_event.data?.request"/>
+ <!-- store the request workflow type as temporary variable -->
+ <cs:var name="workflowType" expr="request.workflowType"/>
+ <!-- store the request targetDate as temporary variable -->
+ <cs:var name="targetDate" expr="request.scheduledDate"/>
+
+ <!-- First delete the request itself.
+ Note: After this, the request object no longer can be accessed!
+ Which is why we need to define the temporary variables workflowType and targetDate above.
+ -->
+ <hippo:deleteRequest requestExpr="request"/>
+
+ <if cond="!targetDate">
+ <!-- the request didn't have a targetDate defined, simply trigger the "workflowType" value as event -->
+ <send event="workflowType"/>
+ <!-- log the workflowType after it has been processed -->
+ <send event="'logEvent.'+workflowType"/>
+ <else/>
+ <!-- the request did have a targetDate: trigger a 'scheduled' workflow action event -->
+ <send event="workflowType" namelist="targetDate"/>
+ </if>
+
+ </transition>
+
+ <!-- target-less transition to 'reject' a request -->
+ <transition event="rejectRequest">
+ <!-- update the specific request to type rejected with an optional reason, using the event payload
+ 'request' and optional 'reason' parameters -->
+ <hippo:rejectRequest requestExpr="_event.data?.request" reasonExpr="_event.data?.reason"/>
+ </transition>
+
+ <!-- target-less transition to 'cancel' a request -->
+ <transition event="cancelRequest">
+ <!-- delete the specific request using the event payload 'request' parameter -->
+ <hippo:deleteRequest requestExpr="_event.data?.request"/>
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the composite publish state is used to manage workflow operations for publishing a document -->
+ <state id="publish">
+
+ <!-- the initial no-publish state is used and active to indicate publish operations are currently not
+ allowed or possible because the document is being edited or not (yet) modified -->
+ <state id="no-publish">
+ <onentry>
+ <!-- by default report the request publication operation as available but disabled -->
+ <hippo:action action="requestPublication" enabledExpr="false"/>
+ <if cond="workflowContext.isGranted(unpublished ?: published ?: draft, 'hippo:editor')">
+ <!-- if editor user (granted hippo:editor) by default report the publish operation as available but disabled -->
+ <hippo:action action="publish" enabledExpr="false"/>
+ </if>
+ </onentry>
+ <!-- event-less transition to publishable state if not currently editing and the document is modified -->
+ <transition target="publishable" cond="!editing and modified"/>
+ </state>
+
+ <!-- state publishable is active when the document is modified and not currently edited -->
+ <state id="publishable">
+ <onentry>
+ <if cond="!requestPending or user=='system'">
+ <!-- if no request pending OR invoked by the 'system' user (scheduled workflow jobs daemon):
+ enable request publication operation -->
+ <hippo:action action="requestPublication" enabledExpr="true"/>
+ <if cond="workflowContext.isGranted(unpublished, 'hippo:editor')">
+ <!-- if (also) editor user (granted hippo:editor): enable publish operation -->
+ <hippo:action action="publish" enabledExpr="true"/>
+ </if>
+ </if>
+ </onentry>
+
+ <!-- target-less transition to create a publish request when no event payload parameter targetDate is provided -->
+ <transition event="requestPublication" cond="!_event.data?.targetDate">
+ <hippo:workflowRequest type="publish" contextVariantExpr="unpublished"/>
+ </transition>
+
+ <!-- target-less transition to create a scheduledpublish request at the required event payload parameter targetDate -->
+ <transition event="requestPublication" cond="!!_event.data?.targetDate">
+ <hippo:workflowRequest type="scheduledpublish" contextVariantExpr="unpublished" targetDateExpr="_event.data?.targetDate"/>
+ </transition>
+
+ <!-- target-less transition to publish the document when no event payload parameter targetDate is provided -->
+ <transition event="publish" cond="!_event.data?.targetDate">
+ <!-- copy the content of the unpublished variant to the published variant -->
+ <hippo:copyVariant sourceState="unpublished" targetState="published"/>
+ <!-- mark the published variant as published and set its availability to (only) 'live' -->
+ <hippo:configVariant variant="published" applyPublished="true" availabilities="live"/>
+ <!-- create a JCR version of the published document via the unpublished variant -->
+ <hippo:version variant="unpublished"/>
+ </transition>
+
+ <!-- target-less transition to schedule the publication of the document at the required event payload parameter targetDate -->
+ <transition event="publish" cond="!!_event.data?.targetDate">
+ <hippo:scheduleWorkflow type="publish" targetDateExpr="_event.data?.targetDate"/>
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the composite depublish state is used to manage workflow operations for depublishing a document -->
+ <state id="depublish">
+
+ <!-- the initial no-depublish state is used and active to indicate depublish operations are currently not
+ allowed or possible because the document is being edited or not 'live' -->
+ <state id="no-depublish">
+ <onentry>
+ <!-- by default report the request depublication operation as available but disabled -->
+ <hippo:action action="requestDepublication" enabledExpr="false"/>
+ <if cond="workflowContext.isGranted(published ?: unpublished ?: draft, 'hippo:editor')">
+ <!-- if editor user (granted hippo:editor) by default report the depublish operation as available but disabled -->
+ <hippo:action action="depublish" enabledExpr="false"/>
+ </if>
+ </onentry>
+ <!-- event-less transition to depublishable state if not currently editing and the document is 'live' -->
+ <transition target="depublishable" cond="!editing and live"/>
+ </state>
+
+ <!-- state depublishable is active when the document is live and not currently edited -->
+ <state id="depublishable">
+ <onentry>
+ <if cond="!requestPending or user=='system'">
+ <!-- if no request pending OR invoked by the 'system' user (scheduled workflow jobs daemon):
+ enable request depublication operation -->
+ <hippo:action action="requestDepublication" enabledExpr="true"/>
+ <if cond="workflowContext.isGranted(published, 'hippo:editor')">
+ <!-- if (also) editor user (granted hippo:editor): enable publish operation -->
+ <hippo:action action="depublish" enabledExpr="true"/>
+ </if>
+ </if>
+ </onentry>
+
+ <!-- target-less transition to create a depublish request when no event payload parameter targetDate is provided -->
+ <transition event="requestDepublication" cond="!_event.data?.targetDate">
+ <hippo:workflowRequest type="depublish" contextVariantExpr="published"/>
+ </transition>
+
+ <!-- target-less transition to create a scheduleddepublish request at the required event payload parameter targetDate -->
+ <transition event="requestDepublication" cond="!!_event.data?.targetDate">
+ <hippo:workflowRequest type="scheduleddepublish" contextVariantExpr="published" targetDateExpr="_event.data?.targetDate"/>
+ </transition>
+
+ <!-- target-less transition to depublish the document when no event payload parameter targetDate is provided -->
+ <transition event="depublish" cond="!_event.data?.targetDate">
+ <if cond="!unpublished">
+ <!-- if no unpublished variant exists yet, copy it from the published variant -->
+ <hippo:copyVariant sourceState="published" targetState="unpublished"/>
+ </if>
+ <!-- ensure the unpublished variant to be versionable set its availability to (only) 'live' -->
+ <hippo:configVariant variant="unpublished" versionable="true" availabilities="preview"/>
+ <!-- remove all availabilities from the published variant -->
+ <hippo:configVariant variant="published" availabilities=""/>
+ <!-- create an extra version of the current unpublished (possibly modified?) -->
+ <hippo:version variant="unpublished"/>
+ </transition>
+
+ <!-- target-less transition to schedule the depublication of the document at the required event payload parameter targetDate -->
+ <transition event="depublish" cond="!!_event.data?.targetDate">
+ <hippo:scheduleWorkflow type="depublish" targetDateExpr="_event.data?.targetDate"/>
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the composite versioning state is used to manage versioning related workflow operations of a document -->
+ <state id="versioning">
+
+ <onentry>
+ <!-- always enable the listVersions, even if no version is available (yet) -->
+ <hippo:action action="listVersions" enabledExpr="true"/>
+ </onentry>
+
+ <!-- target-less transition to report a list of available versions of the document -->
+ <transition event="listVersions">
+ <hippo:listVersions variant="unpublished" />
+ </transition>
+
+ <!-- the initial no-versioning state is used and active to indicate versioning operations are currently not
+ allowed or possible because there is no unpublished document variant yet -->
+ <state id="no-versioning">
+ <!-- event-less transition to versionable state when an unpublished document variant exists -->
+ <transition target="versionable" cond="!!unpublished"/>
+ </state>
+
+ <!-- the versionable state becomes active when an unpublished document variant exists -->
+ <state id="versionable">
+ <onentry>
+ <!-- enable the retrieveVersion operation -->
+ <hippo:action action="retrieveVersion" enabledExpr="true"/>
+ <if cond="workflowContext.isGranted(unpublished, 'hippo:editor')">
+ <!-- if the user is editor (granted hippo:editor) also enable the other versioning operations -->
+ <hippo:action action="version" enabledExpr="true"/>
+ <hippo:action action="restoreVersion" enabledExpr="true"/>
+ <hippo:action action="versionRestoreTo" enabledExpr="true"/>
+ </if>
+ </onentry>
+
+ <!-- target-less transition to create a new version for the current unpublished variant -->
+ <transition event="version">
+ <hippo:version variant="unpublished" />
+ </transition>
+
+ <!-- target-less transition to retrieve a specific version created on the event payload provided date parameter -->
+ <transition event="retrieveVersion">
+ <hippo:retrieveVersion historic="_event.data?.date" variant="unpublished" />
+ </transition>
+
+ <!-- target-less transition to restore a specific version from the event payload provided parameter date to the
+ payload provided parameter target (document).
+ Note: this uses custom/manual copying of the version contents, unlike the restoreVersion operation below -->
+ <transition event="versionRestoreTo">
+ <hippo:versionRestoreTo historic="_event.data?.date" variant="unpublished" target="_event.data?.target"/>
+ </transition>
+
+ <!-- target-less transition to restore a specific document version from the event payload provided parameter date.
+ Note: this uses standard JCR version restore unlike the versionRestoreTo operation above -->
+ <transition event="restoreVersion">
+ <hippo:restoreVersion historic="_event.data?.date" variant="unpublished" />
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the composite terminate state is used to manage termination and related/similar workflow operations like
+ move and rename -->
+ <state id="terminate">
+
+ <!-- the initial no-terminate state is used and active when delete/move/rename operations are currently now
+ allowed or possible -->
+ <state id="no-terminate">
+ <onentry>
+ <!-- report request delete operation as available but default disabled -->
+ <hippo:action action="requestDelete" enabledExpr="false"/>
+ <if cond="workflowContext.isGranted(deleteSource, 'hippo:editor') and workflowContext.isGranted(containingFolder, 'jcr:write')">
+ <!-- if the user is editor (granted hippo:editor) AND allowed to modify (jcr:write) the document folder,
+ report the delete/move/rename operations as available but default disabled -->
+ <if cond="!deleteSource.isNodeTypeEqual('hippotaxonomy:taxonomy')">
+ <hippo:action action="delete" enabledExpr="false"/>
+ <hippo:action action="move" enabledExpr="false"/>
+ </if>
+ <hippo:action action="rename" enabledExpr="false"/>
+ </if>
+ </onentry>
+ <!-- event-less transition to terminatable state if the document is not live and not being edited -->
+ <transition target="terminateable" cond="!live and !editing"/>
+ </state>
+
+ <!-- the terminateable state becomes active when the document is not live and not being edited -->
+ <state id="terminateable">
+ <onentry>
+ <if cond="!requestPending">
+ <!-- delete operations are only allowed when (also) no request is pending -->
+ <!-- (then) always enable the request delete operation -->
+ <hippo:action action="requestDelete" enabledExpr="true"/>
+ <if cond="workflowContext.isGranted(deleteSource, 'hippo:editor') and workflowContext.isGranted(containingFolder, 'jcr:write')">
+ <!-- if the user is editor (granted hippo:editor) AND allowed to modify (jcr:write) the document folder,
+ enable the delete/move/rename operations -->
+ <if cond="!deleteSource.isNodeTypeEqual('hippotaxonomy:taxonomy')">
+ <hippo:action action="delete" enabledExpr="true"/>
+ <hippo:action action="move" enabledExpr="true"/>
+ </if>
+ <hippo:action action="rename" enabledExpr="true"/>
+ </if>
+ </if>
+ </onentry>
+
+ <!-- target-less transition to create a delete request -->
+ <transition event="requestDelete">
+ <hippo:workflowRequest type="delete" contextVariantExpr="deleteSource"/>
+ </transition>
+
+ <!-- transition to delete the current document and go to final state terminated -->
+ <transition event="delete" target="terminated">
+ <hippo:archiveDocument/>
+ </transition>
+
+ <!-- transition to move the current document and go to final state terminated -->
+ <transition event="move" target="terminated">
+ <hippo:moveDocument destinationExpr="_event.data?.destination" newNameExpr="_event.data?.name"/>
+ </transition>
+
+ <!-- transition to rename the current document and go to final state terminated -->
+ <transition event="rename" target="terminated">
+ <hippo:renameDocument newNameExpr="_event.data?.name"/>
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the composite copy state is used to manage the copy workflow operation -->
+ <state id="copy">
+
+ <!-- the initial no-copy state is used and active when the user is not an editor (granted hippo:editor) -->
+ <state id="no-copy">
+ <!-- event-less transition to copyable state when the user is an editor (granted hippo:editor) -->
+ <transition target="copyable" cond="workflowContext.isGranted(copySource,'hippo:editor') and !copySource.isNodeTypeEqual('hippotaxonomy:taxonomy')"/>
+ </state>
+
+ <!-- the state copyable is only active for users which are editor (granted hippo:editor) -->
+ <state id="copyable">
+ <onentry>
+ <!-- always enable the copy operation -->
+ <hippo:action action="copy" enabledExpr="true"/>
+ </onentry>
+
+ <!-- target-less transition to copy the document to the event payload provided parameters destination and name -->
+ <transition event="copy">
+ <hippo:copyDocument destinationExpr="_event.data?.destination" newNameExpr="_event.data?.name"/>
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the simple and non-transitional logEvent state is used to log actions:
+ such actions needs to be 'send' using an event name prefixed by 'logEvent.'
+ the remainder of the event name will be logged as event action
+ -->
+ <state id="logEvent">
+ <transition event="logEvent.*">
+ <hippo:logEvent actionexpr="_event.name.substring('logEvent.'.length())" />
+ </transition>
+ </state>
+
+ </parallel>
+
+ <!-- the final terminated state is used when the document no longer exists, is renamed or moved -->
+ <final id="terminated" />
+
+</scxml>
+
+
+ <?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Copyright 2013-2014 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.
+ -->
+<scxml version="1.0"
+ xmlns="http://www.w3.org/2005/07/scxml"
+ xmlns:hippo="http://www.onehippo.org/cms7/repository/scxml"
+ xmlns:cs="http://commons.apache.org/scxml">
+
+ <script>
+ def getScxmlId() { workflowContext.scxmlId }
+ // draft variant property method
+ def getDraft() { workflowData.documents['draft'] }
+ // unpublished variant property method
+ def getUnpublished() { workflowData.documents['unpublished'] }
+ // published variant property method
+ def getPublished() { workflowData.documents['published'] }
+ // current user property method
+ def getUser() { workflowContext.user }
+ // current requests map property method
+ def getRequests() { workflowData.requests }
+ // returns the variant for copying and checking copy access privileges
+ def getCopySource() { published ?: unpublished ?: null }
+ // returns the variant for deleting and checking delete privileges
+ def getDeleteSource() { unpublished ?: published ?: draft }
+ // returns the current draft holder (editor) if defined (and draft exists)
+ def getHolder() { draft?.holder }
+ // true if draft exists and currently being edited
+ def boolean isEditing() { !!holder }
+ // true if draft exists and edited by current user
+ def boolean isEditor() { holder == user }
+ // true if draft exists and not currently editor or edited by current user
+ def boolean isEditable() { !holder or editor }
+ // true if published variant exists with availability 'live'
+ def boolean isLive() { published?.isAvailable('live') }
+ // true if unpublished variant exists with availability 'preview'
+ def boolean isPreview() { unpublished?.isAvailable('preview') }
+ // true if either unpublished or published variant exits with availability 'preview'
+ def boolean isPreviewAvailable() { unpublished?.isAvailable('preview') or published?.isAvailable('preview') }
+ // true if unpublished variant exists and no published variant exists with availability 'live'
+ // or they have a different lastModified
+ def boolean isModified() { unpublished and (!live or unpublished.lastModified!=published.lastModified) }
+ // true if there is an outstanding workflow request
+ def boolean isRequestPending() { workflowData.requestPending }
+ def getContainingFolder() { workflowData.handle.parent }
+ </script>
+
+ <!-- the initial no-document state is used to prevent entering the handle state if there is no document -->
+ <state id="no-document">
+ <!-- automatic transition to and continue in parallel handle state only when a document variant exists -->
+ <transition target="handle" cond="!workflowData.documents.isEmpty()"/>
+ </state>
+
+ <parallel id="handle">
+
+ <!-- the atomic status state is used to report several statuses and info feedback to the invoking workflow -->
+ <state id="status">
+ <onentry>
+ <hippo:feedback key="status" value="editable"/>
+ <hippo:feedback key="isLive" value="live"/>
+ <hippo:feedback key="previewAvailable" value="previewAvailable"/>
+ <!-- enable the checkModified operation if both draft and unpublished variants exists -->
+ <hippo:action action="checkModified" enabledExpr="draft and unpublished"/>
+ </onentry>
+
+ <!-- target-less transition on event checkModified to compare the draft and unpublished variants which result is
+ reported back as Boolean value through the 'modified' feedback variable and the workflow operation result -->
+ <transition event="checkModified">
+ <hippo:isModified/>
+ <hippo:result value="workflowContext.feedback['modified']"/>
+ </transition>
+ </state>
+
+ <!-- the composite edit state is used to manage all operations for editing a draft variant -->
+ <state id="edit">
+
+ <!-- default no-edit state initially disables all editing operations -->
+ <state id="no-edit">
+ <onentry>
+ <hippo:action action="disposeEditableInstance" enabledExpr="false"/>
+ <hippo:action action="obtainEditableInstance" enabledExpr="false"/>
+ <hippo:action action="commitEditableInstance" enabledExpr="false"/>
+ </onentry>
+ <!-- event-less transition to state "editing" if there is no pending request and the draft variant is edited -->
+ <transition target="editing" cond="!requestPending and editing"/>
+ <!-- (else) event-less transition to state "editable" if there is no pending request and the draft variant
+ doesn't exist yet or isn't edited -->
+ <transition target="editable" cond="!requestPending"/>
+ </state>
+
+ <!-- editing state becomes active when the draft variant is currently edited -->
+ <state id="editing">
+ <onentry>
+ <if cond="editor">
+ <!-- current editor is allowed all editing operations -->
+ <hippo:action action="disposeEditableInstance" enabledExpr="true"/>
+ <hippo:action action="obtainEditableInstance" enabledExpr="true"/>
+ <hippo:action action="commitEditableInstance" enabledExpr="true"/>
+ <else/>
+ <!-- for a not-current editor the current editor (holder) is reported through the 'inUseBy' feedback -->
+ <hippo:feedback key="inUseBy" value="holder"/>
+ </if>
+ <if cond="!editor and workflowContext.isGranted(draft,'hippo:admin')">
+ <!-- For an admin (granted hippo:admin) enable the unlock operation if not-current editor -->
+ <hippo:action action="unlock" enabledExpr="true"/>
+ </if>
+ </onentry>
+ </state>
+
+ <!-- editable state becomes active if editing is possible but there is no current editor -->
+ <state id="editable">
+ <onentry>
+ <if cond="workflowContext.isGranted(draft,'hippo:admin')">
+ <!-- for an admin (granted hippo:admin) report the unlock operation as available but disabled -->
+ <hippo:action action="unlock" enabledExpr="false"/>
+ </if>
+ <!-- enable the operation to start editing -->
+ <hippo:action action="obtainEditableInstance" enabledExpr="true"/>
+ </onentry>
+ </state>
+
+ <!-- target-less transition to 'dispose' an editable instance by (only) removing the current draft holder, and the
+ current unpublished document variant is returned if currently in preview state else the published variant -->
+ <transition event="disposeEditableInstance">
+ <!-- remove holder from the draft document -->
+ <hippo:setHolder holder="null"/>
+ <hippo:result value="preview ? unpublished : published"/>
+ </transition>
+
+ <!-- target-less transition to 'obtain' an editable draft document variant by creating or updating a draft variant
+ by copying (the contents of) the current unpublished variant if available or else the published variant -->
+ <transition event="obtainEditableInstance">
+ <if cond="!!unpublished">
+ <!-- unpublished document exists: copy it to draft first -->
+ <hippo:copyVariant sourceState="unpublished" targetState="draft"/>
+ <elseif cond="!!published"/>
+ <!-- else if published document exists: copy it to draft first -->
+ <hippo:copyVariant sourceState="published" targetState="draft"/>
+ </if>
+ <!-- mark the draft document as modified, set the user as editor and remove possibly copied availabilities -->
+ <hippo:configVariant variant="draft" applyModified="true" setHolder="true" availabilities=""/>
+ <!-- store the newly created or updated draft document as result -->
+ <hippo:result value="draft"/>
+ </transition>
+
+ <!-- target-less transition to 'commit' an editable instance by removing the holder and, if new or modified,
+ copying its content to the unpublished variant -->
+ <transition event="commitEditableInstance">
+ <hippo:setHolder holder="null"/>
+ <if cond="!!unpublished">
+ <!-- if unpublished variant exist only 'commit' changes if there are any -->
+ <hippo:isModified/>
+ </if>
+ <if cond="!unpublished or workflowContext.feedback['modified']">
+ <!-- we either have a new draft (no unpublished) or the draft is modified compared to the unpublished -->
+ <if cond="!unpublished and !!published">
+ <!-- we have no unpublished variant yet but do have a published variant:
+ remove possible 'preview' availability from the published variant -->
+ <if cond="live">
+ <hippo:configVariant variant="published" availabilities="live"/>
+ <else/>
+ <hippo:configVariant variant="published" availabilities=""/>
+ </if>
+ </if>
+ <!-- copy the new or modified draft variant to the unpublished variant, creating it if needed -->
+ <hippo:copyVariant sourceState="draft" targetState="unpublished"/>
+ <!-- configure the new or updated unpublished to be versionable, modified and available as 'preview' -->
+ <hippo:configVariant variant="unpublished" versionable="true" applyModified="true" availabilities="preview"/>
+ </if>
+ <!-- return the possibly updated unpublished variant -->
+ <hippo:result value="unpublished"/>
+ </transition>
+
+ <!-- target-less transition to 'unlock' the current edited draft variant by overriding its current holder
+ with that of the current invoking admin (granted hippo:admin) user. -->
+ <transition event="unlock">
+ <hippo:setHolder holder="user"/>
+ </transition>
+
+ </state>
+
+ <!-- the composite request state is used to manage all workflow operations on existing document workflow requests -->
+ <state id="request">
+
+ <!-- the initial no-request state is used and active when there are no current document workflow requests -->
+ <state id="no-request">
+ <!-- event-less transition to state "requested" when requests exists -->
+ <transition target="requested" cond="!empty(requests)"/>
+ </state>
+
+ <!-- the requested state becomes active when document workflow requests are present -->
+ <state id="requested">
+ <onentry>
+ <foreach item="request" array="requests.values()">
+ <!-- for all requests determine the available request actions and report them through the special 'requests'
+ feedback map variable -->
+ <!-- for document workflow requests: -->
+ <if cond="request.workflowRequest">
+ <if cond="workflowContext.isGranted(request, 'hippo:editor')">
+ <!-- editor users (granted hippo:editor) may reject and accept as well as cancel requests -->
+ <if cond="request.workflowType!='rejected'">
+ <!-- if request not rejected yet, enable reject operation -->
+ <hippo:requestAction identifierExpr="request.identity" action="rejectRequest" enabledExpr="true"/>
+ </if>
+ <if cond="request.workflowType=='delete'">
+ <!-- if request for delete: enable accept operation if not live and not editing -->
+ <hippo:requestAction identifierExpr="request.identity" action="acceptRequest" enabledExpr="!live and !editing"/>
+ <elseif cond="request.workflowType=='publish'">
+ <!-- if request for publish: enable accept operation if modified and not editing -->
+ <hippo:requestAction identifierExpr="request.identity" action="acceptRequest" enabledExpr="modified and !editing"/>
+ </elseif>
+ <elseif cond="request.workflowType=='depublish'"/>
+ <!-- if request for depublish: enable accept operation if live and not editing -->
+ <hippo:requestAction identifierExpr="request.identity" action="acceptRequest" enabledExpr="live and !editing"/>
+ </if>
+ <if cond="!request.owner or request.owner==user">
+ <!-- if request owner or no request owner: enable cancel operation -->
+ <hippo:requestAction identifierExpr="request.identity" action="cancelRequest" enabledExpr="true"/>
+ </if>
+ <!-- when not an editor user (not granted hippo:editor) then: -->
+ <elseif cond="request?.owner==user"/>
+ <!-- if request owner: enable cancel operation -->
+ <hippo:requestAction identifierExpr="request.identity" action="cancelRequest" enabledExpr="true"/>
+ </if>
+ <else/>
+ <!-- scheduled workflow operation -->
+ <if cond="workflowContext.isGranted(request, 'hippo:editor')">
+ <!-- if editor user (granted hippo:editor): enable cancel operation -->
+ <hippo:requestAction identifierExpr="request.identity" action="cancelRequest" enabledExpr="true"/>
+ </if>
+ </if>
+ </foreach>
+ </onentry>
+
+ <!-- target-less transition to 'accept' a specific request -->
+ <transition event="acceptRequest">
+
+ <!-- define temporary request variable for the event payload request parameter -->
+ <cs:var name="request" expr="_event.data?.request"/>
+ <!-- store the request workflow type as temporary variable -->
+ <cs:var name="workflowType" expr="request.workflowType"/>
+ <!-- store the request targetDate as temporary variable -->
+ <cs:var name="targetDate" expr="request.scheduledDate"/>
+
+ <!-- First delete the request itself.
+ Note: After this, the request object no longer can be accessed!
+ Which is why we need to define the temporary variables workflowType and targetDate above.
+ -->
+ <hippo:deleteRequest requestExpr="request"/>
+
+ <if cond="!targetDate">
+ <!-- the request didn't have a targetDate defined, simply trigger the "workflowType" value as event -->
+ <send event="workflowType"/>
+ <!-- log the workflowType after it has been processed -->
+ <send event="'logEvent.'+workflowType"/>
+ <else/>
+ <!-- the request did have a targetDate: trigger a 'scheduled' workflow action event -->
+ <send event="workflowType" namelist="targetDate"/>
+ </if>
+
+ </transition>
+
+ <!-- target-less transition to 'reject' a request -->
+ <transition event="rejectRequest">
+ <!-- update the specific request to type rejected with an optional reason, using the event payload
+ 'request' and optional 'reason' parameters -->
+ <hippo:rejectRequest requestExpr="_event.data?.request" reasonExpr="_event.data?.reason"/>
+ </transition>
+
+ <!-- target-less transition to 'cancel' a request -->
+ <transition event="cancelRequest">
+ <!-- delete the specific request using the event payload 'request' parameter -->
+ <hippo:deleteRequest requestExpr="_event.data?.request"/>
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the composite publish state is used to manage workflow operations for publishing a document -->
+ <state id="publish">
+
+ <!-- the initial no-publish state is used and active to indicate publish operations are currently not
+ allowed or possible because the document is being edited or not (yet) modified -->
+ <state id="no-publish">
+ <onentry>
+ <!-- by default report the request publication operation as available but disabled -->
+ <hippo:action action="requestPublication" enabledExpr="false"/>
+ <if cond="workflowContext.isGranted(unpublished ?: published ?: draft, 'hippo:editor')">
+ <!-- if editor user (granted hippo:editor) by default report the publish operation as available but disabled -->
+ <hippo:action action="publish" enabledExpr="false"/>
+ </if>
+ </onentry>
+ <!-- event-less transition to publishable state if not currently editing and the document is modified -->
+ <transition target="publishable" cond="!editing and modified"/>
+ </state>
+
+ <!-- state publishable is active when the document is modified and not currently edited -->
+ <state id="publishable">
+ <onentry>
+ <if cond="!requestPending or user=='system'">
+ <!-- if no request pending OR invoked by the 'system' user (scheduled workflow jobs daemon):
+ enable request publication operation -->
+ <hippo:action action="requestPublication" enabledExpr="true"/>
+ <if cond="workflowContext.isGranted(unpublished, 'hippo:editor')">
+ <!-- if (also) editor user (granted hippo:editor): enable publish operation -->
+ <hippo:action action="publish" enabledExpr="true"/>
+ </if>
+ </if>
+ </onentry>
+
+ <!-- target-less transition to create a publish request when no event payload parameter targetDate is provided -->
+ <transition event="requestPublication" cond="!_event.data?.targetDate">
+ <hippo:workflowRequest type="publish" contextVariantExpr="unpublished"/>
+ </transition>
+
+ <!-- target-less transition to create a scheduledpublish request at the required event payload parameter targetDate -->
+ <transition event="requestPublication" cond="!!_event.data?.targetDate">
+ <hippo:workflowRequest type="scheduledpublish" contextVariantExpr="unpublished" targetDateExpr="_event.data?.targetDate"/>
+ </transition>
+
+ <!-- target-less transition to publish the document when no event payload parameter targetDate is provided -->
+ <transition event="publish" cond="!_event.data?.targetDate">
+ <!-- copy the content of the unpublished variant to the published variant -->
+ <hippo:copyVariant sourceState="unpublished" targetState="published"/>
+ <!-- mark the published variant as published and set its availability to (only) 'live' -->
+ <hippo:configVariant variant="published" applyPublished="true" availabilities="live"/>
+ <!-- create a JCR version of the published document via the unpublished variant -->
+ <hippo:version variant="unpublished"/>
+ </transition>
+
+ <!-- target-less transition to schedule the publication of the document at the required event payload parameter targetDate -->
+ <transition event="publish" cond="!!_event.data?.targetDate">
+ <hippo:scheduleWorkflow type="publish" targetDateExpr="_event.data?.targetDate"/>
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the composite depublish state is used to manage workflow operations for depublishing a document -->
+ <state id="depublish">
+
+ <!-- the initial no-depublish state is used and active to indicate depublish operations are currently not
+ allowed or possible because the document is being edited or not 'live' -->
+ <state id="no-depublish">
+ <onentry>
+ <!-- by default report the request depublication operation as available but disabled -->
+ <hippo:action action="requestDepublication" enabledExpr="false"/>
+ <if cond="workflowContext.isGranted(published ?: unpublished ?: draft, 'hippo:editor')">
+ <!-- if editor user (granted hippo:editor) by default report the depublish operation as available but disabled -->
+ <hippo:action action="depublish" enabledExpr="false"/>
+ </if>
+ </onentry>
+ <!-- event-less transition to depublishable state if not currently editing and the document is 'live' -->
+ <transition target="depublishable" cond="!editing and live"/>
+ </state>
+
+ <!-- state depublishable is active when the document is live and not currently edited -->
+ <state id="depublishable">
+ <onentry>
+ <if cond="!requestPending or user=='system'">
+ <!-- if no request pending OR invoked by the 'system' user (scheduled workflow jobs daemon):
+ enable request depublication operation -->
+ <hippo:action action="requestDepublication" enabledExpr="true"/>
+ <if cond="workflowContext.isGranted(published, 'hippo:editor')">
+ <!-- if (also) editor user (granted hippo:editor): enable publish operation -->
+ <hippo:action action="depublish" enabledExpr="true"/>
+ </if>
+ </if>
+ </onentry>
+
+ <!-- target-less transition to create a depublish request when no event payload parameter targetDate is provided -->
+ <transition event="requestDepublication" cond="!_event.data?.targetDate">
+ <hippo:workflowRequest type="depublish" contextVariantExpr="published"/>
+ </transition>
+
+ <!-- target-less transition to create a scheduleddepublish request at the required event payload parameter targetDate -->
+ <transition event="requestDepublication" cond="!!_event.data?.targetDate">
+ <hippo:workflowRequest type="scheduleddepublish" contextVariantExpr="published" targetDateExpr="_event.data?.targetDate"/>
+ </transition>
+
+ <!-- target-less transition to depublish the document when no event payload parameter targetDate is provided -->
+ <transition event="depublish" cond="!_event.data?.targetDate">
+ <if cond="!unpublished">
+ <!-- if no unpublished variant exists yet, copy it from the published variant -->
+ <hippo:copyVariant sourceState="published" targetState="unpublished"/>
+ </if>
+ <!-- ensure the unpublished variant to be versionable set its availability to (only) 'live' -->
+ <hippo:configVariant variant="unpublished" versionable="true" availabilities="preview"/>
+ <!-- remove all availabilities from the published variant -->
+ <hippo:configVariant variant="published" availabilities=""/>
+ <!-- create an extra version of the current unpublished (possibly modified?) -->
+ <hippo:version variant="unpublished"/>
+ </transition>
+
+ <!-- target-less transition to schedule the depublication of the document at the required event payload parameter targetDate -->
+ <transition event="depublish" cond="!!_event.data?.targetDate">
+ <hippo:scheduleWorkflow type="depublish" targetDateExpr="_event.data?.targetDate"/>
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the composite versioning state is used to manage versioning related workflow operations of a document -->
+ <state id="versioning">
+
+ <onentry>
+ <!-- always enable the listVersions, even if no version is available (yet) -->
+ <hippo:action action="listVersions" enabledExpr="true"/>
+ </onentry>
+
+ <!-- target-less transition to report a list of available versions of the document -->
+ <transition event="listVersions">
+ <hippo:listVersions variant="unpublished" />
+ </transition>
+
+ <!-- the initial no-versioning state is used and active to indicate versioning operations are currently not
+ allowed or possible because there is no unpublished document variant yet -->
+ <state id="no-versioning">
+ <!-- event-less transition to versionable state when an unpublished document variant exists -->
+ <transition target="versionable" cond="!!unpublished"/>
+ </state>
+
+ <!-- the versionable state becomes active when an unpublished document variant exists -->
+ <state id="versionable">
+ <onentry>
+ <!-- enable the retrieveVersion operation -->
+ <hippo:action action="retrieveVersion" enabledExpr="true"/>
+ <if cond="workflowContext.isGranted(unpublished, 'hippo:editor')">
+ <!-- if the user is editor (granted hippo:editor) also enable the other versioning operations -->
+ <hippo:action action="version" enabledExpr="true"/>
+ <hippo:action action="restoreVersion" enabledExpr="true"/>
+ <hippo:action action="versionRestoreTo" enabledExpr="true"/>
+ </if>
+ </onentry>
+
+ <!-- target-less transition to create a new version for the current unpublished variant -->
+ <transition event="version">
+ <hippo:version variant="unpublished" />
+ </transition>
+
+ <!-- target-less transition to retrieve a specific version created on the event payload provided date parameter -->
+ <transition event="retrieveVersion">
+ <hippo:retrieveVersion historic="_event.data?.date" variant="unpublished" />
+ </transition>
+
+ <!-- target-less transition to restore a specific version from the event payload provided parameter date to the
+ payload provided parameter target (document).
+ Note: this uses custom/manual copying of the version contents, unlike the restoreVersion operation below -->
+ <transition event="versionRestoreTo">
+ <hippo:versionRestoreTo historic="_event.data?.date" variant="unpublished" target="_event.data?.target"/>
+ </transition>
+
+ <!-- target-less transition to restore a specific document version from the event payload provided parameter date.
+ Note: this uses standard JCR version restore unlike the versionRestoreTo operation above -->
+ <transition event="restoreVersion">
+ <hippo:restoreVersion historic="_event.data?.date" variant="unpublished" />
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the composite terminate state is used to manage termination and related/similar workflow operations like
+ move and rename -->
+ <state id="terminate">
+
+ <!-- the initial no-terminate state is used and active when delete/move/rename operations are currently now
+ allowed or possible -->
+ <state id="no-terminate">
+ <onentry>
+ <!-- report request delete operation as available but default disabled -->
+ <hippo:action action="requestDelete" enabledExpr="false"/>
+ <if cond="workflowContext.isGranted(deleteSource, 'hippo:editor') and workflowContext.isGranted(containingFolder, 'jcr:write')">
+ <!-- if the user is editor (granted hippo:editor) AND allowed to modify (jcr:write) the document folder,
+ report the delete/move/rename operations as available but default disabled -->
+ <hippo:action action="delete" enabledExpr="false"/>
+ <hippo:action action="move" enabledExpr="false"/>
+ <hippo:action action="rename" enabledExpr="false"/>
+ </if>
+ </onentry>
+ <!-- event-less transition to terminatable state if the document is not live and not being edited -->
+ <transition target="terminateable" cond="!live and !editing"/>
+ </state>
+
+ <!-- the terminateable state becomes active when the document is not live and not being edited -->
+ <state id="terminateable">
+ <onentry>
+ <if cond="!requestPending">
+ <!-- delete operations are only allowed when (also) no request is pending -->
+ <!-- (then) always enable the request delete operation -->
+ <hippo:action action="requestDelete" enabledExpr="true"/>
+ <if cond="workflowContext.isGranted(deleteSource, 'hippo:editor') and workflowContext.isGranted(containingFolder, 'jcr:write')">
+ <!-- if the user is editor (granted hippo:editor) AND allowed to modify (jcr:write) the document folder,
+ enable the delete/move/rename operations -->
+ <hippo:action action="delete" enabledExpr="true"/>
+ <hippo:action action="move" enabledExpr="true"/>
+ <hippo:action action="rename" enabledExpr="true"/>
+ </if>
+ </if>
+ </onentry>
+
+ <!-- target-less transition to create a delete request -->
+ <transition event="requestDelete">
+ <hippo:workflowRequest type="delete" contextVariantExpr="deleteSource"/>
+ </transition>
+
+ <!-- transition to delete the current document and go to final state terminated -->
+ <transition event="delete" target="terminated">
+ <hippo:archiveDocument/>
+ </transition>
+
+ <!-- transition to move the current document and go to final state terminated -->
+ <transition event="move" target="terminated">
+ <hippo:moveDocument destinationExpr="_event.data?.destination" newNameExpr="_event.data?.name"/>
+ </transition>
+
+ <!-- transition to rename the current document and go to final state terminated -->
+ <transition event="rename" target="terminated">
+ <hippo:renameDocument newNameExpr="_event.data?.name"/>
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the composite copy state is used to manage the copy workflow operation -->
+ <state id="copy">
+
+ <!-- the initial no-copy state is used and active when the user is not an editor (granted hippo:editor) -->
+ <state id="no-copy">
+ <!-- event-less transition to copyable state when the user is an editor (granted hippo:editor) -->
+ <transition target="copyable" cond="workflowContext.isGranted(copySource,'hippo:editor')"/>
+ </state>
+
+ <!-- the state copyable is only active for users which are editor (granted hippo:editor) -->
+ <state id="copyable">
+ <onentry>
+ <!-- always enable the copy operation -->
+ <hippo:action action="copy" enabledExpr="true"/>
+ </onentry>
+
+ <!-- target-less transition to copy the document to the event payload provided parameters destination and name -->
+ <transition event="copy">
+ <hippo:copyDocument destinationExpr="_event.data?.destination" newNameExpr="_event.data?.name"/>
+ </transition>
+
+ </state>
+
+ </state>
+
+ <!-- the simple and non-transitional logEvent state is used to log actions:
+ such actions needs to be 'send' using an event name prefixed by 'logEvent.'
+ the remainder of the event name will be logged as event action
+ -->
+ <state id="logEvent">
+ <transition event="logEvent.*">
+ <hippo:logEvent actionexpr="_event.name.substring('logEvent.'.length())" />
+ </transition>
+ </state>
+
+ </parallel>
+
+ <!-- the final terminated state is used when the document no longer exists, is renamed or moved -->
+ <final id="terminated" />
+
+</scxml>
+
+
+
Index: bccm-changes-modules.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- bccm-changes-modules.xml (revision 238722)
+++ bccm-changes-modules.xml (revision )
@@ -1,6 +1,6 @@