hi marcel

i would go for variant 1. making oak-jcr very complex in order
to keep oak-core simple is the wrong approach IMO and contradicts
the original goal of making it very simple to implement a
jcr-like client on top of oak without having to take care
of complex stuff such as node types, versioning and so on...
that doesn't necessarily mean that we need to extend the OAK-API...
but i think the logic should be part of the oak-core project
rather than with oak-jcr.

apart from that i am bit confused by your description of the
different versioning operations. you write that changes are
being saved... i would in any case avoid writing transient
modifications to the session and persist them using Session#save().
instead i would rather use the same mechanism as is currently
used by other workspace operations as we should never have
transient modifications pending if - for whatever reason - a
workspace (version) operations fails.

kind regards
angela

On 11/29/12 3:11 PM, Marcel Reutegger wrote:
hi all,

during the last oak hackathon in basel a couple of people started a
discussion how to implement JCR versioning in oak. I'd like to give
a quick overview what was discussed and how I think we could implement
the various version related operations in oak.

to properly support JCR versioning we will have to make the version
store available to all workspaces in oak. though, right now we don't
even support multiple workspaces in oak. this means in a first step
we will probably have to implement multi-workspace support by
moving the current workspace tree one level down the hierarchy.
the version store could then simply become a special workspace
that will be made visible under /jcr:system/jcr:versionStorage. during
the hackathon we discussed multiple options how to make the versions
appear at that location:

- the version store is mounted at the NodeState level. this has the
advantage of being easier to implement, because the API is rather
small. it would also allow us to enforce write protection on the version
store by exposing it read-only at this location.

- the version store is mounted on a higher level. that is, oak-jcr is
responsible for constructing the node tree correctly as required
by the JCR spec. this way it might be easier to separate JCR concerns
from oak core and keep the latter as simple as possible.

no matter which approach we take the version storage will be
persisted as oak Trees ;)

now, to implement the various JCR versioning operations, I'd like
to encapsulate them in commit hooks as much as possible. this
avoid the need to duplicate code and perform consistency checks
in various places. my idea is to trigger those hooks with a defined
set of content modification on Trees on through the oak API:

= making a node versionable / create an initial version history

a node is made versionable by adding a mix:versionable mixin type
or by creating a node with a primary type that extends from mix:versionable.
a commit hook will detect these modifications and create a version
history for that node. in addition it will also modify the versionable
node and set appropriate values for jcr:baseVersion, jcr:isCheckedOut,
jcr:versionHistory, etc. this is very similar to how the current Jackrabbit
implementation works.

= checkin / checkout

the jcr:isCheckedOut Boolean property is flipped and the change is
saved. a commit hook will be triggered by this change and perform
either a checkin or checkout operation. e.g. on checkin a version is created
in the version store and the version related properties on the versionable
node are updated accordingly. any other modification on a previously
checked in node is rejected by the commit hook. at the same time
oak-jcr will of course respect the jcr:isCheckedOut value and prevent
changes when the node is checked in.

= checkpoint

an easy implementation could simply perform a checkin followed by
a checkout. though, this wouldn't be 100% correct because it's not
atomic.

= restore version

on the versionable node the jcr:baseVersion is set and save is called.
a commit hook will be triggered by this change and perform the
actual restore.
handling of removeExisting: oak-jcr takes care of this flag and removes
existing nodes if requested and necessary. the version restore commit
hook will always fail if it encounters an identifier collision.
restoring a node that doesn't exist in the workspace (15.7.8): create
node with type stored in jcr:frozenPrimaryType of version to restore.
jcr:baseVersion identifies version to restore. on save, the commit hook
will restore the rest of the version.

= version labels, remove a version

these two are a bit tricky because changes are only reflected in the
version storage, but not on the versionable node. the idea I have
in mind is to set something like a temporary version operation property
on the versionable node. e.g. rep:addVersionLabel = '<uuid>:foo'
but this only works when the versionable node is actually present
in the workspace, which doesn't need to be the case. specifically in
the 'remove version' case where you might want to delete a complete
version history, you first have to remove the versionable node in
the workspace first. maybe version label manipulation and removing
versions can work with operation properties on the jcr:versionStorage
node? in any case such a property will be removed again by the
commit hook, which would perform the requested operation.

= merge

this operation may work similar to version label manipulation and removing
a version. setting a version operation property on the versionable
node triggers a commit hook, which performs the actual operation and
removes the property on save.

feedback is very welcome ;)

regards
  marcel

Reply via email to