Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
SOLVED

Groovy Script for copying node and its child node from one path to another

Avatar

Level 4

Dear All,

 

I have written below groovy script for copying whole content and its child content from path (/content/dam/projects/we-retail/communities) to the path (/content/we-retail/pagehub).

 

My requirement is , I have source path called /content/dam/projects/we-retail/communities and contains lots of child communities with child nodes. And I want to copy all child nodes under /content/dam/projects/we-retail/communities to the destination path  /content/we-retail/pagehub

 

subnaik_0-1679364622837.png

 

Here my destination path is below.

 

subnaik_1-1679365125259.png

 

The issue is here that content is copying in the CRXDE , but pages are coming blank , as shown below.

 

subnaik_2-1679365229188.png

 

********************* MY Grovy Script *************************

import org.apache.jackrabbit.commons.JcrUtils
// Groovy Script to create folder pagehubs if it is not present and copy communities content to pagehub
import com.day.cq.commons.jcr.JcrUtil;

String pageHubDestinationPath = "/content/we-retail/pagehub";

if(!getResource(pageHubDestinationPath)){
JcrUtil.createPath(pageHubDestinationPath,"sling:OrderedFolder",session); //create folder pagehub inside we-retail if the folder does not exist.
Resource res = getResource(pageHubDestinationPath);
if(res){
ModifiableValueMap resMVM = res.adaptTo(ModifiableValueMap.class);
resMVM.put("jcr:title","pagehub"); // add title pagehub
println "Resource created: $pageHubDestinationPath";
session.save();
}
}
else{
//if folder pagehub exists no need to create new folder and read all the communities folder and copy inside pagehubs
println "Folder already exist1233: $pageHubDestinationPath"
}

String communitiesSourcePath = "/content/dam/projects/we-retail/communities";
println("session ==== " + session);
Workspace workspace = session.getWorkspace();
Resource communitiesCustomRes = resourceResolver.getResource(communitiesSourcePath);
println("communitiesCustomRes === " + communitiesCustomRes);
if(communitiesSourcePath != null) {
Iterator<Resource> iterator = communitiesCustomRes.listChildren()
while(iterator.hasNext()) {
Resource childResource= iterator.next()
childNode = childResource.adaptTo(Node.class)
String childnodeName = childNode.getName();

//println("childnodeName === " + childnodeName)
String communitiesSourcePath1 = communitiesSourcePath +"/"+ childnodeName;
//println("source path ===== " + communitiesSourcePath1 )
String destinationPath = "/content/we-retail/pagehub/" + childnodeName;
println("destinationPath path ===== " + destinationPath )
workspace.copy(communitiesSourcePath1, destinationPath);
session.save();

}
}

 
 

 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

@subnaik in that case you can simply remove unwanted nodes from the structure after copy operation. You can check below script.

  1. Create root folder (/content/we-retail/pagehub) if it does not exists.
  2. Copy entire content from /content/dam/projects/we-retail/communities to /content/we-retail/pagehub
  3. Remove unwanted nodes from structure that is result of the copy. Everything what is not a sling:Folder or sling:OrderedFolder will be removed. You can change the condition if you want to keep more types.

As a result you will get copy of folder structure only.

 

import com.day.cq.commons.jcr.JcrUtil

def pageHubDestinationPath = "/content/we-retail/pagehub";
def sourceRootNode = getNode("/content/dam/projects/we-retail/communities")

def pageHubDestinationNode = JcrUtil.createPath(pageHubDestinationPath, "sling:OrderedFolder", "sling:OrderedFolder", session, true)

// create copy of entire strucutre
sourceRootNode?.getNodes()?.each { childNode ->
    JcrUtil.copy(childNode, pageHubDestinationNode, null)
    session.save()
}

cleanNodes(pageHubDestinationNode)

def cleanNodes(def node) {
    if (node?.getPrimaryNodeType()?.isNodeType("sling:Folder")) {
        node?.getNodes()?.each { childNode ->
            // removing nodes recursively
            cleanNodes(childNode)
        }
    } else {
        def nodePath = node?.getPath()
        println "Removing node ${nodePath}"
        session.removeItem(nodePath)
        session.save()
    }
}

 

View solution in original post

5 Replies

Avatar

Level 4

NOTE - Here my source folder contains all Content Fragment and trying to copy content fragment model to site structure.

Avatar

Level 2

Can you try following script once

 

import javax.jcr.*
import org.apache.sling.api.resource.ResourceResolver
import org.apache.sling.api.resource.ResourceResolverFactory
import org.apache.sling.api.resource.ModifiableValueMap

// Define the source and destination paths
def sourcePath = "/content/dam/projects/we-retail/communities"
def destinationPath = "/content/we-retail/pagehub"

// Get a ResourceResolver to perform the copy operation
ResourceResolver resolver = sling.getService(ResourceResolverFactory).getServiceResourceResolver(null)

try {
// Get the source node and its child nodes
def sourceNode = resolver.getResource(sourcePath)
def sourceChildren = sourceNode.getChildren()

// Get the destination node and create it if it doesn't exist
def destinationNode = resolver.getResource(destinationPath)
if (destinationNode == null) {
def parentPath = destinationPath.substring(0, destinationPath.lastIndexOf('/'))
def parentNode = resolver.getResource(parentPath)
destinationNode = resolver.create(parentNode, destinationPath.substring(parentPath.length() + 1), sourceNode.getValueMap())
}

// Copy the properties from the source node to the destination node
def sourceProperties = sourceNode.getValueMap()
def destinationProperties = destinationNode.adaptTo(ModifiableValueMap.class)
for (String propertyName : sourceProperties.keySet()) {
destinationProperties.put(propertyName, sourceProperties.get(propertyName))
}
destinationProperties.save()

// Copy the child nodes recursively
for (def child : sourceChildren) {
def childPath = child.getPath().replace(sourcePath, destinationPath)
def childNode = resolver.create(destinationNode, child.getName(), child.getValueMap())
copyNode(child, childNode, childPath, resolver)
}

resolver.commit()
log.info("Successfully copied node from ${sourcePath} to ${destinationPath}")
} catch (Exception e) {
log.error("Error copying node from ${sourcePath} to ${destinationPath}: ${e.message}", e)
resolver.rollback()
}

def copyNode(sourceNode, destinationNode, destinationPath, resolver) {
// Copy the properties from the source node to the destination node
def sourceProperties = sourceNode.getValueMap()
def destinationProperties = destinationNode.adaptTo(ModifiableValueMap.class)
for (String propertyName : sourceProperties.keySet()) {
destinationProperties.put(propertyName, sourceProperties.get(propertyName))
}
destinationProperties.save()

// Copy the child nodes recursively
for (def child : sourceNode.getChildren()) {
def childPath = child.getPath().replace(sourcePath, destinationPath)
def childNode = resolver.create(destinationNode, child.getName(), child.getValueMap())
copyNode(child, childNode, childPath, resolver)
}
}

Avatar

Community Advisor

Hi @subnaik,

What you see is correct behavior. Your script is not a problem, as you already confirmed in crx you can see that nodes structure was copied correctly. The issue is that you are trying to display Assets (content fragment is an Asset) under sites view (/sites.html)

This will not work by design, sites view has been prepared to display Pages - nodes with cq:Page primary type, it also supports folders (sling:Folder, nt:folder)

I am not sure what is the purpose of the operation you are conducting, but it looks it is against the way how AEM has been designed.

Assets should be stored under /content/dam and you can use dedicated console to manage them - assets.html

Avatar

Level 4

Hi @lukasz-m and @KajalInamdarEy Thanks for the reply..

 

I am not sure what is the purpose of the operation you are conducting, but it looks it is against the way how AEM has been designed.

 

Here my purpose is that only copy the folder structure from source path to destination path. I want the same folder structure in destination path, but not any contents/nodes...But while copying it is copying all folders with contents.

Avatar

Correct answer by
Community Advisor

@subnaik in that case you can simply remove unwanted nodes from the structure after copy operation. You can check below script.

  1. Create root folder (/content/we-retail/pagehub) if it does not exists.
  2. Copy entire content from /content/dam/projects/we-retail/communities to /content/we-retail/pagehub
  3. Remove unwanted nodes from structure that is result of the copy. Everything what is not a sling:Folder or sling:OrderedFolder will be removed. You can change the condition if you want to keep more types.

As a result you will get copy of folder structure only.

 

import com.day.cq.commons.jcr.JcrUtil

def pageHubDestinationPath = "/content/we-retail/pagehub";
def sourceRootNode = getNode("/content/dam/projects/we-retail/communities")

def pageHubDestinationNode = JcrUtil.createPath(pageHubDestinationPath, "sling:OrderedFolder", "sling:OrderedFolder", session, true)

// create copy of entire strucutre
sourceRootNode?.getNodes()?.each { childNode ->
    JcrUtil.copy(childNode, pageHubDestinationNode, null)
    session.save()
}

cleanNodes(pageHubDestinationNode)

def cleanNodes(def node) {
    if (node?.getPrimaryNodeType()?.isNodeType("sling:Folder")) {
        node?.getNodes()?.each { childNode ->
            // removing nodes recursively
            cleanNodes(childNode)
        }
    } else {
        def nodePath = node?.getPath()
        println "Removing node ${nodePath}"
        session.removeItem(nodePath)
        session.save()
    }
}