Leveraging WebReports to assist with merging Content Server Folders



Often when dealing with data migrations or acquisitions you may face the challenge of merging two folders inside of Content Server. Currently Content Server doesn’t have a great way of handling folder merges, especially if folders you need to merge are not simply filled with flat files.

To work around this, we can build a series of LiveReports and WebReports that can be leveraged to perform a comparison of folder names and move objects from one location to the other based on their name. This does come with the caveat that we’re presuming that documents with identical names are the same. We could expand these workflows to leverage some custom oScript tags to perform a MD5, or SHA256. However, for this use case we’re going to presume they’re the same.

To start off we need to build a LiveReport that will be able to determine all the folders that exist in our Source Folder that do not exist in our destination folder. This is a rather simple query returning the DataID and the Name. You will need to change the LiveReport to an “Auto LiveReport” and configure the two input parameters to be a source and destination folder.

select dataid, name from dtree where parentid=%1 and subtype=0
AND name NOT IN (select name from dtree where parentid=%2)

We will then join this to a WebReport that takes this output and adds in some Markup so we can turn it into an Assoc. Create a new WebReport and set it’s source to the LiveReport we just created.

{[LL_WEBREPORT_STARTROW /]{[LL_REPTAG_1 /],"[LL_REPTAG_2 /]"}[LL_WEBREPORT_ENDROW /]}

We can now quickly test our WebReport and run it. We should be prompted to input two folders, and then it should output a list of folders that exist in the Source folder that do not exist in the Destination folder.

Next we need to build another LiveReport that will return the matching DataID’s for folders with the same name. This will be similar to the LiveReport above where we needed to configure two input parameters for the source and destination, and set the LiveReport to be an “Auto LiveReport”. We can leverage the below SQL to return the DataID’s of folders that have matching names.

WITH
dtree1 as (select dataid, name from dtree where parentid=%1 and subtype=0),
dtree2 as (select dataid, name from dtree where parentid=%2 and subtype=0)
select dtree1.name, dtree1.dataid, dtree2.dataid
from dtree1, dtree2
where dtree1.name=dtree2.name

Now we can run this LiveReport against a set of small test folders and confirm that only Folders with identical names DataID’s are returned. Again now we’re going to build a WebReport to leverage this data.

{[LL_WEBREPORT_STARTROW /]{[LL_REPTAG_2 /],[LL_REPTAG_3 /]}[LL_WEBREPORT_ENDROW /]}

In this WebReport we discard the Name that was returned and only return the matching pair of DataID’s. Now that these two WebReports have been created, lets start on our final sub-WebReport which will be leveraged to return the children of our matched folders.

Create a third (and final) LiveReport, this one is very simple where we’re going to get back the Name and DataID of the children of a specific folder.

select name, dataid from DTreeCore where parentid = %1

Now we’re going to create another very simple WebReport with that LiveReport as it’s source. In theory we could have leveraged a WebReport tag to determine the children, however that is more expensive due to permissions checking that occurs. In this scenario we’re presuming you have permissions to all of the items you are attempting to move, and that this report is limited to Administrators.

{[LL_WEBREPORT_STARTROW /]{"[LL_REPTAG_1 /]",[LL_REPTAG_2 /]} [LL_WEBREPORT_ENDROW /]}

Now lets bring our three sub-WebReports together with our larger master WebReport. This report will leverage all the WebReports we have just created to execute moves on the unique items. You will have to update the DataID’s where mentioned to the WebReports created. Also this WebReport leverages two parameters: source, and dest. These were defined to be two containers and I used the same parameter names for all of the LiveReports above. You may have to adjust the WebReport to use inputlabel1 and inputlabel2 if you left things as the default.

[/*
WebReport tool to merge folders.
Written by James Hewitt
Date: Jan 21, 2020

Known Limitations:
- This is not designed as a recursive move tool. If the selected source contains a folder, which contains a folder which has a name conflict then the object will not be moved.
- This tool does NOT compare contents. It compares names of objects. If there is a collision it presumes the file is already in that location.
*/]

[/* Call WebReport to build Assoc of dataID's with identical matching names. */]
[LL_REPTAG_'WR1DataID' RUNSWR:source:"[LL_REPTAG_&source /]":dest"[LL_REPTAG_&dest /]" ASSOCACTION:CREATE SETVAR:SOURCELIST /]
[/* Call WebReport to build Assoc of dataID's of items that exist in the Source Folder but do not exist in the Dest Folder */]
[LL_REPTAG_'WR2DataID' RUNSWR:source:"[LL_REPTAG_&source /]":dest"[LL_REPTAG_&dest /]" ASSOCACTION:CREATE SETVAR:UNIQFOLDER /]


<H1>Starting Parent Folder Move</H1>
<hr />
[/* Iterate through the Assoc and move each top level folder that does not exist in the Dest */]
[LL_WEBREPORT_FOR DATA:[LL_REPTAG_!UNIQFOLDER /] VAR:sf /]
[LL_REPTAG_!sf LIST:1 NODEACTION:MOVE:"[LL_REPTAG_&dest /]":UNIQUEONLY ONERROR:LONG SETVAR:ERR /]
[LL_WEBREPORT_IF "[LL_REPTAG_!ERR /]" == "" /]
<b>Moving parent folder:</b> [LL_REPTAG_!sf LIST:2 /] To [LL_REPTAG_&dest /] <br />
[LL_WEBREPORT_ENDIF /]
[LL_WEBREPORT_ENDFOR /]


[/* Iterate through the Assoc and fire a SubWebReport for each match to find the children. */]
<h1>Starting Subfolder item move.</h1>
[LL_WEBREPORT_FOR DATA:[LL_REPTAG_!SOURCELIST /] VAR:s /]
<hr>
<b>Moving unique children from Folder:</b> [LL_REPTAG_!s LIST:1 /] <br />
[LL_REPTAG_'WR3DataID' RUNSWR:parent:"[LL_REPTAG_!s LIST:1 /]" ASSOCACTION:CREATE SETVAR:MOVEME /]
[/* Iterate through the Assoc of the children and move uniquely named objects */]
[LL_WEBREPORT_FOR DATA:[LL_REPTAG_!MOVEME /] VAR:m /]
[LL_REPTAG_!m LIST:2 NODEACTION:MOVE:"[LL_REPTAG_!s LIST:2 /]":UNIQUEONLY ONERROR:LONG SETVAR:ERR /]
[LL_WEBREPORT_IF "[LL_REPTAG_!ERR /]" == "" /]
<b>Moving:</b> [LL_REPTAG_!m LIST:1 /] To [LL_REPTAG_!s LIST:2 /] <br />
[LL_WEBREPORT_ENDIF /]
[LL_WEBREPORT_ENDFOR /]
<hr>

[LL_WEBREPORT_ENDFOR /]
[LL_WEBREPORT_STARTROW /]
[LL_WEBREPORT_ENDROW /]

With this final WebReport created, and the ID’s updated we can run this against a test folder and confirm that everything moves as expected. We can leverage this same logic to perform other tasks such as comparing two different folder structures to simply highlight what is different. Additionally more logic could be added to handle more recursive folder strucutures, however caution should be leveraged when attempting to do that as you may end up in a looping scenario.

Back to post listing