From 320e165ec4596269cf38a42a46f04070a06cb212 Mon Sep 17 00:00:00 2001 From: Vivek Date: Thu, 18 Aug 2016 16:39:45 +0530 Subject: [PATCH 1/9] changed from scratch --- .../steps/jcrnodes/JcrNodesWriter.groovy | 14 +----- .../grabbit/jcr/JCRNodeDecorator.groovy | 45 ++++++++++++++++++- .../grabbit/jcr/ProtoNodeDecorator.groovy | 20 ++++++++- .../grabbit/jcr/JCRNodeDecoratorSpec.groovy | 39 ++++++++++++++++ 4 files changed, 103 insertions(+), 15 deletions(-) diff --git a/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy b/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy index 85fe218..952e46f 100644 --- a/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy +++ b/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy @@ -17,7 +17,6 @@ package com.twcable.grabbit.client.batch.steps.jcrnodes import com.twcable.grabbit.client.batch.ClientBatchJobContext -import com.twcable.grabbit.jcr.JcrNodeDecorator import com.twcable.grabbit.jcr.ProtoNodeDecorator import com.twcable.grabbit.proto.NodeProtos.Node as ProtoNode import groovy.transform.CompileStatic @@ -71,7 +70,7 @@ class JcrNodesWriter implements ItemWriter, ItemWriteListener { void write(List nodeProtos) throws Exception { Session session = theSession() for (ProtoNode nodeProto : nodeProtos) { - writeToJcr(nodeProto, session) + new ProtoNodeDecorator(nodeProto).writeJcrNodesRecursively(session) } } @@ -87,16 +86,7 @@ class JcrNodesWriter implements ItemWriter, ItemWriteListener { return retVal } - private static void writeToJcr(ProtoNode nodeProto, Session session) { - JcrNodeDecorator jcrNode = new ProtoNodeDecorator(nodeProto).writeToJcr(session) - jcrNode.setLastModified() - // This will processed all mandatory child nodes only - if(nodeProto.mandatoryChildNodeList && nodeProto.mandatoryChildNodeList.size() > 0) { - for(ProtoNode childNode: nodeProto.mandatoryChildNodeList) { - writeToJcr(childNode, session) - } - } - } + private Session theSession() { ClientBatchJobContext.session diff --git a/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy index d3be775..f4a2f05 100644 --- a/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy +++ b/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy @@ -19,17 +19,23 @@ import com.twcable.grabbit.proto.NodeProtos.Node as ProtoNode import com.twcable.grabbit.proto.NodeProtos.Node.Builder as ProtoNodeBuilder import com.twcable.grabbit.proto.NodeProtos.Property as ProtoProperty import groovy.transform.CompileStatic - +import groovy.transform.TypeCheckingMode import groovy.util.logging.Slf4j +import org.apache.jackrabbit.commons.NamespaceHelper import org.apache.jackrabbit.value.DateValue +import com.twcable.grabbit.proto.NodeProtos.Value as ProtoValue + import javax.annotation.Nonnull import javax.annotation.Nullable +import javax.jcr.ItemNotFoundException import javax.jcr.Node as JCRNode import javax.jcr.Property import javax.jcr.Property as JcrProperty import javax.jcr.RepositoryException +import javax.jcr.Session import javax.jcr.nodetype.ItemDefinition +import javax.jcr.nodetype.NodeTypeManager import static org.apache.jackrabbit.JcrConstants.* @@ -135,6 +141,43 @@ class JcrNodeDecorator { } } + void checkoutNode() { + try { + JcrNodeDecorator decoratedVersionableAncestor = findVersionableAncestor(); + if (decoratedVersionableAncestor && !decoratedVersionableAncestor.isCheckedOut()) { + decoratedVersionableAncestor.session.workspace.versionManager.checkout(decoratedVersionableAncestor.path); + } + } + catch (Exception exception) { + log.warn "Could not checkout node ${this.path}, ${exception.message}" + exception.printStackTrace() + } + } + + private JcrNodeDecorator findVersionableAncestor() throws RepositoryException { + if (isVersionable()) { + return this; + } + try { + JcrNodeDecorator parentDecoratedNode = new JcrNodeDecorator(this.parent); + return parentDecoratedNode.findVersionableAncestor(); + } catch (ItemNotFoundException e) { + return null; + } + } + + /** + * mix:simpleVersionable cannot be checked in. Throws javax.jcr.UnsupportedRepositoryOperationException + * Checking here for mix:versionable only + * */ + private boolean isVersionable() throws RepositoryException { + return isNodeType(MIX_VERSIONABLE) + } + + String getName(String name) throws RepositoryException { + return new NamespaceHelper(getSession()).getJcrName(name); + } + /** * Returns the "jcr:lastModified", "cq:lastModified" or "jcr:created" date property * for current Jcr Node diff --git a/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy index 750eab3..e833438 100644 --- a/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy +++ b/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy @@ -59,9 +59,25 @@ class ProtoNodeDecorator { protoProperties.findAll { !(it.name in [JCR_PRIMARYTYPE, JCR_MIXINTYPES]) } } + void writeJcrNodesRecursively(Session session) { + JcrNodeDecorator decoratedJcrNode = writeToJcr(session) + decoratedJcrNode.setLastModified() + // This will processed all mandatory child nodes only + if(innerProtoNode.mandatoryChildNodeList && innerProtoNode.mandatoryChildNodeList.size() > 0) { + for(ProtoNode childProtoNode: innerProtoNode.mandatoryChildNodeList) { + new ProtoNodeDecorator(childProtoNode).writeJcrNodesRecursively(session) + } + } + } - JcrNodeDecorator writeToJcr(@Nonnull Session session) { + + private JcrNodeDecorator writeToJcr(@Nonnull Session session) { final jcrNode = getOrCreateNode(session) + + JcrNodeDecorator decoratedJcrNode = new JcrNodeDecorator(jcrNode) + if (!decoratedJcrNode.isCheckedOut()) { + decoratedJcrNode.checkoutNode() + } //Write mixin types first to avoid InvalidConstraintExceptions final mixinProperty = getMixinProperty() if(mixinProperty) { @@ -70,7 +86,7 @@ class ProtoNodeDecorator { //Then add other properties writableProperties.each { it.writeToNode(jcrNode) } - return new JcrNodeDecorator(jcrNode) + return decoratedJcrNode } diff --git a/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy b/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy index 6b5904e..08ed2ca 100644 --- a/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy +++ b/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy @@ -16,8 +16,11 @@ package com.twcable.grabbit.jcr import com.day.cq.commons.jcr.JcrConstants +import com.twcable.jackalope.NodeBuilder +import spock.lang.Ignore import spock.lang.Shared import spock.lang.Specification +import spock.util.mop.ConfineMetaClassChanges import javax.jcr.Node import javax.jcr.NodeIterator @@ -27,6 +30,14 @@ import javax.jcr.nodetype.ItemDefinition import javax.jcr.nodetype.NodeDefinition import javax.jcr.nodetype.NodeType +import static com.twcable.jackalope.JCRBuilder.node +import static com.twcable.jackalope.JCRBuilder.node +import static com.twcable.jackalope.JCRBuilder.property +import static com.twcable.jackalope.JCRBuilder.property +import static com.twcable.jackalope.JCRBuilder.property +import static com.twcable.jackalope.JCRBuilder.property +import static com.twcable.jackalope.JCRBuilder.property +import static com.twcable.jackalope.JcrConstants.NT_FILE import static org.apache.jackrabbit.JcrConstants.JCR_CREATED import static org.apache.jackrabbit.JcrConstants.JCR_LASTMODIFIED import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE @@ -234,4 +245,32 @@ class JCRNodeDecoratorSpec extends Specification { false | false | true | jcrCreatedDate.time false | false | false | null } + + /* + * Needs mixin implementation in Jackalope + * https://github.com/TWCable/jackalope/pull/7 + */ + @Ignore + def "Checkout nearest versionable node"() { + given: + NodeBuilder fakeNodeBuilder = + node("a", + node("b", property("jcr:mixinTypes", ["mix:versionable"].toArray()), + property("jcr:primaryType", "cq:Page"), + node("c", + node("d")), + + ), + ) + + Node parentNode = fakeNodeBuilder.build(); + + final nodeDecorator = new JcrNodeDecorator(parentNode.getNode("b/c/d")) + + when: + nodeDecorator.checkoutNode() + + then: + parentNode.getNode("b").getProperty("jcr:isCheckedOut") == true + } } From f7a9160114161987fb9aab22df62a226b9b36980 Mon Sep 17 00:00:00 2001 From: Vivek Date: Thu, 18 Aug 2016 16:42:39 +0530 Subject: [PATCH 2/9] some changes --- .../com/twcable/grabbit/jcr/JCRNodeDecorator.groovy | 10 ---------- .../twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy | 11 +---------- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy index f4a2f05..7c5922e 100644 --- a/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy +++ b/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy @@ -19,12 +19,8 @@ import com.twcable.grabbit.proto.NodeProtos.Node as ProtoNode import com.twcable.grabbit.proto.NodeProtos.Node.Builder as ProtoNodeBuilder import com.twcable.grabbit.proto.NodeProtos.Property as ProtoProperty import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode import groovy.util.logging.Slf4j -import org.apache.jackrabbit.commons.NamespaceHelper import org.apache.jackrabbit.value.DateValue -import com.twcable.grabbit.proto.NodeProtos.Value as ProtoValue - import javax.annotation.Nonnull import javax.annotation.Nullable @@ -33,9 +29,7 @@ import javax.jcr.Node as JCRNode import javax.jcr.Property import javax.jcr.Property as JcrProperty import javax.jcr.RepositoryException -import javax.jcr.Session import javax.jcr.nodetype.ItemDefinition -import javax.jcr.nodetype.NodeTypeManager import static org.apache.jackrabbit.JcrConstants.* @@ -174,10 +168,6 @@ class JcrNodeDecorator { return isNodeType(MIX_VERSIONABLE) } - String getName(String name) throws RepositoryException { - return new NamespaceHelper(getSession()).getJcrName(name); - } - /** * Returns the "jcr:lastModified", "cq:lastModified" or "jcr:created" date property * for current Jcr Node diff --git a/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy b/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy index 08ed2ca..1a705a1 100644 --- a/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy +++ b/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy @@ -20,7 +20,6 @@ import com.twcable.jackalope.NodeBuilder import spock.lang.Ignore import spock.lang.Shared import spock.lang.Specification -import spock.util.mop.ConfineMetaClassChanges import javax.jcr.Node import javax.jcr.NodeIterator @@ -31,16 +30,8 @@ import javax.jcr.nodetype.NodeDefinition import javax.jcr.nodetype.NodeType import static com.twcable.jackalope.JCRBuilder.node -import static com.twcable.jackalope.JCRBuilder.node -import static com.twcable.jackalope.JCRBuilder.property -import static com.twcable.jackalope.JCRBuilder.property -import static com.twcable.jackalope.JCRBuilder.property -import static com.twcable.jackalope.JCRBuilder.property import static com.twcable.jackalope.JCRBuilder.property -import static com.twcable.jackalope.JcrConstants.NT_FILE -import static org.apache.jackrabbit.JcrConstants.JCR_CREATED -import static org.apache.jackrabbit.JcrConstants.JCR_LASTMODIFIED -import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE +import static org.apache.jackrabbit.JcrConstants.* @SuppressWarnings("GroovyAssignabilityCheck") class JCRNodeDecoratorSpec extends Specification { From 1da84897008016b002f8de5f93bcc1f9e4c46d64 Mon Sep 17 00:00:00 2001 From: Vivek Date: Thu, 18 Aug 2016 17:20:51 +0530 Subject: [PATCH 3/9] renamed spec --- .../groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy b/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy index 1a705a1..3c61788 100644 --- a/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy +++ b/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy @@ -34,7 +34,7 @@ import static com.twcable.jackalope.JCRBuilder.property import static org.apache.jackrabbit.JcrConstants.* @SuppressWarnings("GroovyAssignabilityCheck") -class JCRNodeDecoratorSpec extends Specification { +class JcrNodeDecoratorSpec extends Specification { @Shared static Calendar jcrModifiedDate = Calendar.getInstance() static Calendar cqModifiedDate = Calendar.getInstance() From 3eea9d74f070904c6a1ad4d502b2eb5102b4824d Mon Sep 17 00:00:00 2001 From: Vivek Date: Fri, 19 Aug 2016 11:20:04 +0530 Subject: [PATCH 4/9] added java doc --- .../groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy | 4 +++- .../groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy index 7c5922e..7e19ce8 100644 --- a/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy +++ b/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy @@ -135,6 +135,9 @@ class JcrNodeDecorator { } } + /** + * Finds out nearest versionable ancestor for a node and performs a checkout + */ void checkoutNode() { try { JcrNodeDecorator decoratedVersionableAncestor = findVersionableAncestor(); @@ -144,7 +147,6 @@ class JcrNodeDecorator { } catch (Exception exception) { log.warn "Could not checkout node ${this.path}, ${exception.message}" - exception.printStackTrace() } } diff --git a/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy index e833438..f608044 100644 --- a/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy +++ b/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy @@ -59,6 +59,11 @@ class ProtoNodeDecorator { protoProperties.findAll { !(it.name in [JCR_PRIMARYTYPE, JCR_MIXINTYPES]) } } + /** + * This method writes a node with all the mandatory child node to the Jcr + * using current proto node properties + * @param session to write Jcr nodes + */ void writeJcrNodesRecursively(Session session) { JcrNodeDecorator decoratedJcrNode = writeToJcr(session) decoratedJcrNode.setLastModified() From 793360e267333c03269ecd158d42d9caf023cc16 Mon Sep 17 00:00:00 2001 From: Vivek Date: Mon, 22 Aug 2016 17:27:15 +0530 Subject: [PATCH 5/9] renamed files --- .../jcr/{JCRNodeDecorator.groovy => JcrNodeDecorator.groovy} | 0 ...{JCRNodeDecoratorSpec.groovy => JcrNodeDecoratorSpec.groovy} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/main/groovy/com/twcable/grabbit/jcr/{JCRNodeDecorator.groovy => JcrNodeDecorator.groovy} (100%) rename src/test/groovy/com/twcable/grabbit/jcr/{JCRNodeDecoratorSpec.groovy => JcrNodeDecoratorSpec.groovy} (99%) diff --git a/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy similarity index 100% rename from src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy rename to src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy diff --git a/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy b/src/test/groovy/com/twcable/grabbit/jcr/JcrNodeDecoratorSpec.groovy similarity index 99% rename from src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy rename to src/test/groovy/com/twcable/grabbit/jcr/JcrNodeDecoratorSpec.groovy index 3c61788..4d9c3a6 100644 --- a/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy +++ b/src/test/groovy/com/twcable/grabbit/jcr/JcrNodeDecoratorSpec.groovy @@ -1,4 +1,4 @@ -/* +`/* * Copyright 2015 Time Warner Cable, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); From 0814ee28f9e82a79bd6876c3b26034e740385a0e Mon Sep 17 00:00:00 2001 From: Vivek Date: Mon, 22 Aug 2016 17:50:07 +0530 Subject: [PATCH 6/9] minor character fix --- .../groovy/com/twcable/grabbit/jcr/JcrNodeDecoratorSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/groovy/com/twcable/grabbit/jcr/JcrNodeDecoratorSpec.groovy b/src/test/groovy/com/twcable/grabbit/jcr/JcrNodeDecoratorSpec.groovy index 4d9c3a6..3c61788 100644 --- a/src/test/groovy/com/twcable/grabbit/jcr/JcrNodeDecoratorSpec.groovy +++ b/src/test/groovy/com/twcable/grabbit/jcr/JcrNodeDecoratorSpec.groovy @@ -1,4 +1,4 @@ -`/* +/* * Copyright 2015 Time Warner Cable, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); From e4d36569d374f3375ea36d0748b1df59640784b4 Mon Sep 17 00:00:00 2001 From: Vivek Date: Tue, 23 Aug 2016 12:13:36 +0530 Subject: [PATCH 7/9] added check for simple versionable again --- .../grabbit/jcr/JcrNodeDecorator.groovy | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy index 7e19ce8..6c82562 100644 --- a/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy +++ b/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy @@ -140,9 +140,9 @@ class JcrNodeDecorator { */ void checkoutNode() { try { - JcrNodeDecorator decoratedVersionableAncestor = findVersionableAncestor(); + JcrNodeDecorator decoratedVersionableAncestor = findVersionableAncestor() if (decoratedVersionableAncestor && !decoratedVersionableAncestor.isCheckedOut()) { - decoratedVersionableAncestor.session.workspace.versionManager.checkout(decoratedVersionableAncestor.path); + decoratedVersionableAncestor.session.workspace.versionManager.checkout(decoratedVersionableAncestor.path) } } catch (Exception exception) { @@ -150,24 +150,20 @@ class JcrNodeDecorator { } } - private JcrNodeDecorator findVersionableAncestor() throws RepositoryException { + private JcrNodeDecorator findVersionableAncestor() { if (isVersionable()) { - return this; + return this } try { - JcrNodeDecorator parentDecoratedNode = new JcrNodeDecorator(this.parent); - return parentDecoratedNode.findVersionableAncestor(); + JcrNodeDecorator parentDecoratedNode = new JcrNodeDecorator(this.parent) + return parentDecoratedNode.findVersionableAncestor() } catch (ItemNotFoundException e) { - return null; + return null } } - /** - * mix:simpleVersionable cannot be checked in. Throws javax.jcr.UnsupportedRepositoryOperationException - * Checking here for mix:versionable only - * */ - private boolean isVersionable() throws RepositoryException { - return isNodeType(MIX_VERSIONABLE) + private boolean isVersionable() { + return isNodeType(MIX_VERSIONABLE) || isNodeType("mix:simpleVersionable") } /** From ca54409cdbfdd23dcbf1395862a95d33480b8d36 Mon Sep 17 00:00:00 2001 From: Jeff Bornemann Date: Tue, 23 Aug 2016 11:46:52 -0600 Subject: [PATCH 8/9] Some of Jeff's ideas on versionable node organization --- .../steps/jcrnodes/JcrNodesWriter.groovy | 2 +- .../grabbit/jcr/JcrNodeDecorator.groovy | 39 ++++++++++- .../grabbit/jcr/ProtoNodeDecorator.groovy | 66 ++----------------- .../grabbit/jcr/ProtoPropertyDecorator.groovy | 17 ++++- 4 files changed, 60 insertions(+), 64 deletions(-) diff --git a/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy b/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy index 952e46f..69923dd 100644 --- a/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy +++ b/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy @@ -70,7 +70,7 @@ class JcrNodesWriter implements ItemWriter, ItemWriteListener { void write(List nodeProtos) throws Exception { Session session = theSession() for (ProtoNode nodeProto : nodeProtos) { - new ProtoNodeDecorator(nodeProto).writeJcrNodesRecursively(session) + new ProtoNodeDecorator(nodeProto).writeToJcr(session) } } diff --git a/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy index 6c82562..f9a1074 100644 --- a/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy +++ b/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy @@ -20,6 +20,7 @@ import com.twcable.grabbit.proto.NodeProtos.Node.Builder as ProtoNodeBuilder import com.twcable.grabbit.proto.NodeProtos.Property as ProtoProperty import groovy.transform.CompileStatic import groovy.util.logging.Slf4j +import org.apache.jackrabbit.commons.JcrUtils import org.apache.jackrabbit.value.DateValue import javax.annotation.Nonnull @@ -29,7 +30,9 @@ import javax.jcr.Node as JCRNode import javax.jcr.Property import javax.jcr.Property as JcrProperty import javax.jcr.RepositoryException +import javax.jcr.Session import javax.jcr.nodetype.ItemDefinition +import javax.jcr.version.VersionException import static org.apache.jackrabbit.JcrConstants.* @@ -45,11 +48,41 @@ class JcrNodeDecorator { private Collection immediateChildNodes - JcrNodeDecorator(@Nonnull JCRNode node) { + JcrNodeDecorator(@Nonnull final JCRNode node) { if(!node) throw new IllegalArgumentException("node must not be null!") this.innerNode = node } + static JcrNodeDecorator createFromProtoNode(@Nonnull final ProtoNodeDecorator protoNode, @Nonnull final Session session) { + final JcrNodeDecorator theDecorator = new JcrNodeDecorator(getOrCreateNode(protoNode, session)) + final mandatoryNodes = protoNode.getMandatoryChildNodes() + if(mandatoryNodes && mandatoryNodes.size() > 0) { + mandatoryNodes.each { + it.writeToJcr(session) + } + } + //If a version exception is thrown, + try { + protoNode.writableProperties.each { it.writeToNode(innerNode) } + } + catch(VersionException ex) { + theDecorator.checkoutNode() + protoNode.writableProperties.each { it.writeToNode(innerNode) } + theDecorator.checkinNode() + } + theDecorator.setLastModified() + return theDecorator + } + + /** + * This method is rather succinct, but helps isolate this JcrUtils static method call + * so that we can get better test coverage. + * @param session to create or get the node path for + * @return the newly created, or found node + */ + private static JCRNode getOrCreateNode(ProtoNodeDecorator protoNode, Session session) { + JcrUtils.getOrCreateByPath(protoNode.name, protoNode.primaryType, session) + } /** * @return this node's immediate children, empty if none @@ -135,6 +168,10 @@ class JcrNodeDecorator { } } + void checkinNode() { + + } + /** * Finds out nearest versionable ancestor for a node and performs a checkout */ diff --git a/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy index f608044..dfc4609 100644 --- a/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy +++ b/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy @@ -56,71 +56,15 @@ class ProtoNodeDecorator { Collection getWritableProperties() { - protoProperties.findAll { !(it.name in [JCR_PRIMARYTYPE, JCR_MIXINTYPES]) } + protoProperties.findAll { !(it.name in [JCR_PRIMARYTYPE]) } } - /** - * This method writes a node with all the mandatory child node to the Jcr - * using current proto node properties - * @param session to write Jcr nodes - */ - void writeJcrNodesRecursively(Session session) { - JcrNodeDecorator decoratedJcrNode = writeToJcr(session) - decoratedJcrNode.setLastModified() - // This will processed all mandatory child nodes only - if(innerProtoNode.mandatoryChildNodeList && innerProtoNode.mandatoryChildNodeList.size() > 0) { - for(ProtoNode childProtoNode: innerProtoNode.mandatoryChildNodeList) { - new ProtoNodeDecorator(childProtoNode).writeJcrNodesRecursively(session) - } - } + List getMandatoryChildNodes() { + return mandatoryChildNodeList.collect { new ProtoNodeDecorator(it) } } - - private JcrNodeDecorator writeToJcr(@Nonnull Session session) { - final jcrNode = getOrCreateNode(session) - - JcrNodeDecorator decoratedJcrNode = new JcrNodeDecorator(jcrNode) - if (!decoratedJcrNode.isCheckedOut()) { - decoratedJcrNode.checkoutNode() - } - //Write mixin types first to avoid InvalidConstraintExceptions - final mixinProperty = getMixinProperty() - if(mixinProperty) { - addMixins(mixinProperty, jcrNode) - } - //Then add other properties - writableProperties.each { it.writeToNode(jcrNode) } - - return decoratedJcrNode - } - - - /** - * This method is rather succinct, but helps isolate this JcrUtils static method call - * so that we can get better test coverage. - * @param session to create or get the node path for - * @return the newly created, or found node - */ - JCRNode getOrCreateNode(Session session) { - JcrUtils.getOrCreateByPath(innerProtoNode.name, primaryType, session) - } - - - /** - * If a property can be added as a mixin, adds it to the given node - * @param property - * @param node - */ - private static void addMixins(ProtoPropertyDecorator property, JCRNode node) { - property.valuesList.each { ProtoValue value -> - if (node.canAddMixin(value.stringValue)) { - node.addMixin(value.stringValue) - log.debug "Added mixin ${value.stringValue} for : ${node.name}." - } - else { - log.warn "Encountered invalid mixin type while unmarshalling for Proto value : ${value}" - } - } + JcrNodeDecorator writeToJcr(@Nonnull Session session) { + return JcrNodeDecorator.createFromProtoNode(this, session) } } diff --git a/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy index eeb7a4e..8c5ee7a 100644 --- a/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy +++ b/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy @@ -44,7 +44,10 @@ class ProtoPropertyDecorator { void writeToNode(@Nonnull JCRNode node) { - if(primaryType || mixinType) throw new IllegalStateException("Refuse to write jcr:primaryType or jcr:mixinType as normal properties. These are not allowed") + if(primaryType) throw new IllegalStateException("Refuse to write jcr:primaryType. This can not be written after node creation") + if(mixinType) { + writeMixinTypeToNode(node) + } try { if (multiple) { node.setProperty(this.name, getPropertyValues(), this.type) @@ -72,6 +75,18 @@ class ProtoPropertyDecorator { } } + private void writeMixinTypeToNode(@Nonnull JCRNode node) { + valuesList.each { ProtoValue value -> + if(node.canAddMixin(value.stringValue)){ + node.addMixin(value.stringValue) + log.debug "Added mixin ${value.stringValue} for : ${node.name}." + } + else { + log.warn "Encountered invalid mixin type while unmarshalling for Proto value : ${value}" + } + } + } + boolean isPrimaryType() { innerProtoProperty.name == JCR_PRIMARYTYPE From a625115712a11e5922acb314c3f8223e9bf5e66e Mon Sep 17 00:00:00 2001 From: Vivek Date: Mon, 29 Aug 2016 14:38:59 +0530 Subject: [PATCH 9/9] some changes --- .../steps/jcrnodes/JcrNodesWriter.groovy | 3 +- .../grabbit/jcr/JcrNodeDecorator.groovy | 32 ++++++++++++------- .../grabbit/jcr/ProtoPropertyDecorator.groovy | 5 +-- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy b/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy index 69923dd..30e1a5a 100644 --- a/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy +++ b/src/main/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriter.groovy @@ -70,7 +70,8 @@ class JcrNodesWriter implements ItemWriter, ItemWriteListener { void write(List nodeProtos) throws Exception { Session session = theSession() for (ProtoNode nodeProto : nodeProtos) { - new ProtoNodeDecorator(nodeProto).writeToJcr(session) + ProtoNodeDecorator protoNodeDecorator = new ProtoNodeDecorator(nodeProto) + protoNodeDecorator.writeToJcr(session) } } diff --git a/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy index f9a1074..31c8501 100644 --- a/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy +++ b/src/main/groovy/com/twcable/grabbit/jcr/JcrNodeDecorator.groovy @@ -34,6 +34,7 @@ import javax.jcr.Session import javax.jcr.nodetype.ItemDefinition import javax.jcr.version.VersionException +import static javax.jcr.nodetype.NodeType.* import static org.apache.jackrabbit.JcrConstants.* @CompileStatic @@ -56,19 +57,19 @@ class JcrNodeDecorator { static JcrNodeDecorator createFromProtoNode(@Nonnull final ProtoNodeDecorator protoNode, @Nonnull final Session session) { final JcrNodeDecorator theDecorator = new JcrNodeDecorator(getOrCreateNode(protoNode, session)) final mandatoryNodes = protoNode.getMandatoryChildNodes() - if(mandatoryNodes && mandatoryNodes.size() > 0) { - mandatoryNodes.each { - it.writeToJcr(session) - } + mandatoryNodes?.each { + it.writeToJcr(session) } //If a version exception is thrown, try { protoNode.writableProperties.each { it.writeToNode(innerNode) } } catch(VersionException ex) { - theDecorator.checkoutNode() - protoNode.writableProperties.each { it.writeToNode(innerNode) } - theDecorator.checkinNode() + JcrNodeDecorator checkedOutNode = theDecorator.checkoutNode() + if (checkedOutNode) { + protoNode.writableProperties.each { it.writeToNode(innerNode) } + checkedOutNode.checkinNode() + } } theDecorator.setLastModified() return theDecorator @@ -168,23 +169,30 @@ class JcrNodeDecorator { } } - void checkinNode() { - + private void checkinNode() { + try { + this.session.workspace.versionManager.checkin(this.path) + } + catch (RepositoryException e) { + log.warn("Error checking in node ${this.path}") + } } /** * Finds out nearest versionable ancestor for a node and performs a checkout */ - void checkoutNode() { + private JcrNodeDecorator checkoutNode() { try { JcrNodeDecorator decoratedVersionableAncestor = findVersionableAncestor() if (decoratedVersionableAncestor && !decoratedVersionableAncestor.isCheckedOut()) { decoratedVersionableAncestor.session.workspace.versionManager.checkout(decoratedVersionableAncestor.path) + return decoratedVersionableAncestor } } - catch (Exception exception) { + catch (RepositoryException exception) { log.warn "Could not checkout node ${this.path}, ${exception.message}" } + return null } private JcrNodeDecorator findVersionableAncestor() { @@ -200,7 +208,7 @@ class JcrNodeDecorator { } private boolean isVersionable() { - return isNodeType(MIX_VERSIONABLE) || isNodeType("mix:simpleVersionable") + return mixinNodeTypes.any{it in [MIX_SIMPLE_VERSIONABLE, MIX_VERSIONABLE]} } /** diff --git a/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy index 8c5ee7a..43ca4dc 100644 --- a/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy +++ b/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy @@ -27,6 +27,7 @@ import javax.jcr.Node as JCRNode import javax.jcr.PropertyType import javax.jcr.Value import javax.jcr.ValueFormatException +import javax.jcr.version.VersionException import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE @@ -43,7 +44,7 @@ class ProtoPropertyDecorator { } - void writeToNode(@Nonnull JCRNode node) { + void writeToNode(@Nonnull JCRNode node) throws VersionException { if(primaryType) throw new IllegalStateException("Refuse to write jcr:primaryType. This can not be written after node creation") if(mixinType) { writeMixinTypeToNode(node) @@ -75,7 +76,7 @@ class ProtoPropertyDecorator { } } - private void writeMixinTypeToNode(@Nonnull JCRNode node) { + void writeMixinTypeToNode(@Nonnull JCRNode node) { valuesList.each { ProtoValue value -> if(node.canAddMixin(value.stringValue)){ node.addMixin(value.stringValue)