Groovy DocumentsInfoScript

Overview

The DocumentsInfoScript is an updater script that logs information about documents selected by a specified XPath query.

Functionality

This script locates documents in the repository and logs their name, type, path, and publication workflow properties. The level of detail in the output depends on the verbosity parameter.

XPath Query Examples

Set an XPath query that selects only one variant type per document to ensure accurate document counts.

  • To select published documents under myroot:
content/documents/myroot//element(*, hippo:document)[@hippostd:stateSummary = 'live' and @hippostd:state = 'published']
  • To select unpublished and new documents under myroot:
content/documents/myroot//element(*, hippo:document)[@hippostd:stateSummary != 'live' and @hippostd:state = 'unpublished']

Alternatively, you can query for handles. The script will attempt to select the published variant, falling back to the unpublished variant if necessary:

content/documents/myroot//element(*, hippo:handle)

You can also select the parent nodes of documents:

content/documents/myroot//element(*, hippo:document)/..

Parameters

The script uses the verbosity parameter to control the level of detail in the log output:

{"verbosity":  0} 
  • 0 (default): Outputs only a summary with the number of documents per type.
  • 1: Outputs the name, type, and path for each document, plus the summary.
  • 2: Outputs the name, type, path, publication workflow properties for each document, plus the summary.

Script

package org.hippoecm.frontend.plugins.cms.admin.updater import org.hippoecm.repository.HippoStdNodeType import org.hippoecm.repository.HippoStdPubWfNodeType import org.hippoecm.repository.api.HippoNodeType import org.onehippo.repository.update.BaseNodeUpdateVisitor import org.onehippo.repository.util.JcrConstants import javax.jcr.Node import javax.jcr.NodeIterator import javax.jcr.Session /** * Find documents and output their type, name, path and publication workflow properties. * * Parameter: * verbosity: 0 (default) only a summary of numbers of documents, per type * 1 per document the name, type, path, plus the summary * 2 per document the name, type, path, publication workflow properties, plus the summary * * XPath: * 1) preferably query for documents, making sure only one type of the variant is selected to get correct count. * * E.g. published documents below myroot * content/documents/myroot//element(*, hippo:document)[@hippostd:stateSummary = 'live' and @hippostd:state = 'published'] * E.g. unpublished/new documents below myroot * content/documents/myroot//element(*, hippo:document)[@hippostd:stateSummary != 'live' and @hippostd:state = 'unpublished'] * * 2) alternatively query for handle, where the published document variant will be taken, with fallback to the unpublished. * content/documents/myroot//element(*, hippo:handle) * or * content/documents/myroot//element(*, hippo:document)/.. */ class DocumentsInfoScript extends BaseNodeUpdateVisitor { Integer verbosity = 0 List<DocumentInfo> documents = new ArrayList<DocumentInfo>() Map<String,Integer> documentTypes = new HashMap<>() void initialize(Session session) { String v = parametersMap.get("verbosity") if (v != null) { verbosity = Integer.parseInt(v) } log.info "DocumentsInfoScript initialized with parameter verbosity=${verbosity}" } boolean doUpdate(Node node) { log.debug "Visiting node ${node.path} of type ${node.primaryNodeType.name}" Node handle Node document if (node.isNodeType(HippoNodeType.NT_DOCUMENT) && !node.isNodeType(HippoStdNodeType.NT_FOLDER)) { document = node handle = document.parent } else if (node.isNodeType(HippoNodeType.NT_HANDLE)) { handle = node document = getDocument(handle) } if ((handle == null) || (document == null)) { log.debug "No handle/document can be determined from node ${node.path} of type ${node.primaryNodeType.name}" return false } String documentName = handle.name if (handle.isNodeType(HippoNodeType.NT_NAMED)) { documentName = handle.getProperty(HippoNodeType.HIPPO_NAME).string } if (document != null) { String primaryType = document.getProperty(JcrConstants.JCR_PRIMARY_TYPE).string String creator = "unknown" String creationDate = "unknown" String lastModifiedBy = "unknown" String lastModificationDate = "unknown" String publicationDate = "unknown" if (document.hasProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_CREATED_BY)) { creator = document.getProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_CREATED_BY).string } if (document.hasProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_CREATION_DATE)) { creationDate = document.getProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_CREATION_DATE).string } if (document.hasProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_LAST_MODIFIED_BY)) { lastModifiedBy = document.getProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_LAST_MODIFIED_BY).string } if (document.hasProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_LAST_MODIFIED_DATE)) { lastModificationDate = document.getProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_LAST_MODIFIED_DATE).string } if (document.hasProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_PUBLICATION_DATE)) { publicationDate = document.getProperty(HippoStdPubWfNodeType.HIPPOSTDPUBWF_PUBLICATION_DATE).string } documents.add(new DocumentInfo(primaryType, documentName, handle.path, creator, creationDate, lastModifiedBy, lastModificationDate, publicationDate)) increaseDocumentTypeCount(primaryType) return true } return false } Node getDocument(final Node handle) { Node published = null Node unpublished = null NodeIterator it = handle.getNodes(handle.name) while (it.hasNext()) { Node variant = it.nextNode() if (variant.hasProperty(HippoStdNodeType.HIPPOSTD_STATE)) { String state = variant.getProperty(HippoStdNodeType.HIPPOSTD_STATE).getString() if (HippoStdNodeType.PUBLISHED == state) { published = variant } else if (HippoStdNodeType.UNPUBLISHED == state) { unpublished = variant } } } return (published != null) ? published : unpublished } void increaseDocumentTypeCount(final String docType) { Integer count = documentTypes.get(docType) documentTypes.put(docType, (count == null) ? 1 : ++count) } void logOutput() { final StringBuilder sb = new StringBuilder() if ((verbosity > 0) && (documents.size() > 0)) { if (verbosity > 1) { sb.append("Detailed document information (name, type, creator, creation date, last modified by, last modification date, publication date, path):\n") for (DocumentInfo info : documents) { sb.append(" ").append(info.name).append(", ") sb.append(info.primaryType).append(", ") sb.append(info.creator).append(", ") sb.append(info.creationDate).append(", ") sb.append(info.lastModifiedBy).append(", ") sb.append(info.lastModificationDate).append(", ") sb.append(info.publicationDate).append(", ") sb.append(info.path).append("\n") } } else { sb.append("Document information (name, type, path):\n") for (DocumentInfo info : documents) { sb.append(" ").append(info.name).append(", ") sb.append(info.primaryType).append(", ") sb.append(info.path).append("\n") } } } sb.append("DocumentsInfoScript summary: ").append(documents.size()).append(" documents found.\n") Iterator types = documentTypes.keySet().iterator() while (types.hasNext()) { String type = types.next() sb.append(" ").append(documentTypes.get(type)).append(" documents of type ").append(type).append("\n") } log.info(sb.toString()) } void destroy() { logOutput() } /** * Information about a found document. */ class DocumentInfo { String primaryType String name String creator String creationDate String lastModifiedBy String lastModificationDate String publicationDate String path DocumentInfo(final String primaryType, final String name, final String path, final String creator, final String creationDate, final String lastModifiedBy, final String lastModificationDate, final String publicationDate) { this.primaryType = primaryType this.name = name this.path = path this.creator = creator this.creationDate = creationDate this.lastModifiedBy = lastModifiedBy this.lastModificationDate = lastModificationDate this.publicationDate = publicationDate } } boolean undoUpdate(Node node) { throw new UnsupportedOperationException('Updater does not implement undoUpdate method') } }
Share Feedback
Page: /build/content-updates/groovy-documentsinfoscript
Section: Build
Category *
Groovy DocumentsInfoScript | Bloomreach Content Documentation