mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-15 15:02:20 +00:00
Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
af995f1087 | ||
|
2cfcd3dfa7 | ||
|
89e09b0162 | ||
|
495808b172 | ||
|
57060af84b | ||
|
60261aafd1 | ||
|
8dad225394 | ||
|
5cc21c55e7 | ||
|
c71aaf7537 | ||
|
b7d16ac915 | ||
|
1a436b06e4 | ||
|
be02be5a8b | ||
|
a674e574c5 | ||
|
aacaa62ff9 | ||
|
371bd1543d | ||
|
4cb16f046f | ||
|
2fb7de9ace | ||
|
ed972c79d7 | ||
|
0f3e2dc4cc | ||
|
4e7d0ccae3 | ||
|
1b5636a339 | ||
|
164ce720af | ||
|
258738e3dd | ||
|
fefd937c89 | ||
|
91f9467a99 | ||
|
97b1515f7c | ||
|
7f235f1e2b | ||
|
109bdeee0f | ||
|
7c97f49574 | ||
|
2088b8b553 | ||
|
280a873cb6 | ||
|
9683c18448 | ||
|
21b36a7100 | ||
|
96481daae1 | ||
|
7ef573699b |
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -9,6 +9,6 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
</project>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<organization>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
14
pom.xml
14
pom.xml
@@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Alfresco Community Repo Parent</name>
|
||||
|
||||
@@ -51,14 +51,14 @@
|
||||
<dependency.alfresco-server-root.version>7.0.2</dependency.alfresco-server-root.version>
|
||||
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
|
||||
<dependency.activiti.version>5.23.0</dependency.activiti.version>
|
||||
<dependency.alfresco-transform-core.version>5.2.2-A.4</dependency.alfresco-transform-core.version>
|
||||
<dependency.alfresco-transform-service.version>4.2.2-A.2</dependency.alfresco-transform-service.version>
|
||||
<dependency.alfresco-transform-core.version>5.2.2</dependency.alfresco-transform-core.version>
|
||||
<dependency.alfresco-transform-service.version>4.2.2</dependency.alfresco-transform-service.version>
|
||||
<dependency.alfresco-greenmail.version>7.1</dependency.alfresco-greenmail.version>
|
||||
<dependency.acs-event-model.version>1.0.11</dependency.acs-event-model.version>
|
||||
|
||||
<dependency.aspectj.version>1.9.22.1</dependency.aspectj.version>
|
||||
<dependency.spring.version>6.2.8</dependency.spring.version>
|
||||
<dependency.spring-security.version>6.3.9</dependency.spring-security.version>
|
||||
<dependency.spring.version>6.2.11</dependency.spring.version>
|
||||
<dependency.spring-security.version>6.4.11</dependency.spring-security.version>
|
||||
<dependency.antlr.version>3.5.3</dependency.antlr.version>
|
||||
<dependency.jackson.version>2.17.2</dependency.jackson.version>
|
||||
<dependency.cxf.version>4.1.2</dependency.cxf.version>
|
||||
@@ -115,7 +115,7 @@
|
||||
<dependency.jakarta-json-path.version>2.9.0</dependency.jakarta-json-path.version>
|
||||
<dependency.json-smart.version>2.5.2</dependency.json-smart.version>
|
||||
<alfresco.googledrive.version>4.1.0</alfresco.googledrive.version>
|
||||
<alfresco.aos-module.version>3.3.0</alfresco.aos-module.version>
|
||||
<alfresco.aos-module.version>3.4.0</alfresco.aos-module.version>
|
||||
<alfresco.api-explorer.version>25.2.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
|
||||
|
||||
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
|
||||
@@ -154,7 +154,7 @@
|
||||
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
||||
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
||||
<tag>25.3.0.45</tag>
|
||||
<tag>25.3.0.56</tag>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -51,6 +51,14 @@ function main()
|
||||
}
|
||||
}
|
||||
|
||||
var contentChanged = false;
|
||||
if (itemKind === "node") {
|
||||
contentChanged = metadataExtractAction.isContentChanged(itemId,repoFormData);
|
||||
}
|
||||
if(logger.isLoggingEnabled() && contentChanged) {
|
||||
logger.log("Content has been changed");
|
||||
}
|
||||
|
||||
var persistedObject = null;
|
||||
try
|
||||
{
|
||||
@@ -83,9 +91,50 @@ function main()
|
||||
|
||||
return;
|
||||
}
|
||||
if (itemKind === "node") {
|
||||
checkAndExtractNodeMetadata(persistedObject, itemId, contentChanged);
|
||||
}
|
||||
|
||||
model.persistedObject = persistedObject.toString();
|
||||
model.message = "Successfully persisted form for item [" + itemKind + "]" + itemId;
|
||||
}
|
||||
|
||||
function checkAndExtractNodeMetadata(persistedObject, itemId, isContentChanged) {
|
||||
var nodeRefStr = toNodeRefString(persistedObject, itemId);
|
||||
var node = search.findNode(nodeRefStr);
|
||||
|
||||
if (node == null) {
|
||||
if (logger.isLoggingEnabled()) {
|
||||
logger.log("Node not found: " + nodeRefStr);
|
||||
}
|
||||
} else if(isContentChanged) {
|
||||
extractMetadata(node, isContentChanged);
|
||||
} else {
|
||||
if (logger.isLoggingEnabled()) {
|
||||
logger.log("Content not changed, skipping metadata extraction for node: " + nodeRefStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function extractMetadata(file, isContentChanged) {
|
||||
var emAction = metadataExtractAction.create(isContentChanged);
|
||||
if (emAction) {
|
||||
// readOnly=false, newTransaction=false
|
||||
emAction.execute(file, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
function toNodeRefString(persistedObject, itemId) {
|
||||
// Prefer the NodeRef returned by saveForm (when kind=node).
|
||||
if (persistedObject instanceof Packages.org.alfresco.service.cmr.repository.NodeRef) {
|
||||
return persistedObject.toString();
|
||||
}
|
||||
// If the client passed a full noderef, keep it.
|
||||
if (itemId && itemId.indexOf("://") !== -1) {
|
||||
return itemId;
|
||||
}
|
||||
// Otherwise assume SpacesStore UUID.
|
||||
return "workspace://SpacesStore/" + itemId;
|
||||
}
|
||||
main();
|
@@ -1,85 +1,92 @@
|
||||
<#macro renderParent node indent=" ">
|
||||
<#escape x as jsonUtils.encodeJSONString(x)>
|
||||
${indent}"parent":
|
||||
${indent}{
|
||||
<#if (node != rootNode) && node.parent??>
|
||||
<@renderParent node.parent indent+" " />
|
||||
</#if>
|
||||
${indent}"type": "${node.typeShort}",
|
||||
${indent}"isContainer": ${node.isContainer?string},
|
||||
${indent}"name": "${node.properties.name!""}",
|
||||
${indent}"title": "${node.properties.title!""}",
|
||||
${indent}"description": "${node.properties.description!""}",
|
||||
<#if node.properties.modified??>${indent}"modified": "${xmldate(node.properties.modified)}",</#if>
|
||||
<#if node.properties.modifier??>${indent}"modifier": "${node.properties.modifier}",</#if>
|
||||
${indent}"displayPath": "${node.displayPath!""}",
|
||||
${indent}"qnamePath": "${node.qnamePath!""}",
|
||||
<#if node.aspects??>
|
||||
${indent}"aspects":
|
||||
${indent}[
|
||||
<#list node.aspects as aspect>
|
||||
"${shortQName(aspect)}"
|
||||
<#if aspect_has_next>,</#if>
|
||||
</#list>
|
||||
|
||||
${indent}],
|
||||
</#if>
|
||||
${indent}"nodeRef": "${node.nodeRef}"
|
||||
${indent}},
|
||||
</#escape>
|
||||
</#macro>
|
||||
|
||||
<#macro pickerResultsJSON results>
|
||||
<#escape x as jsonUtils.encodeJSONString(x)>
|
||||
{
|
||||
"data":
|
||||
{
|
||||
<#if parent??>
|
||||
<@renderParent parent />
|
||||
</#if>
|
||||
"items":
|
||||
[
|
||||
<#list results as row>
|
||||
<#if row.item.hasPermission("Read")>
|
||||
{
|
||||
"type": "${row.item.typeShort}",
|
||||
"parentType": "${row.item.parentTypeShort!""}",
|
||||
"isContainer": ${row.item.isContainer?string},
|
||||
<#if row.container??>"container": "${row.container!""}",</#if>
|
||||
"name": "${row.item.properties.name!""}",
|
||||
<#if row.item.aspects??>
|
||||
"aspects": [
|
||||
<#list row.item.aspects as aspect>
|
||||
"${shortQName(aspect)}"
|
||||
<#if aspect_has_next>,</#if>
|
||||
</#list>
|
||||
],
|
||||
</#if>
|
||||
"title":<#if row.item.properties["lnk:title"]??>"${row.item.properties["lnk:title"]}",
|
||||
<#elseif row.item.properties["ia:whatEvent"]??>"${row.item.properties["ia:whatEvent"]}",
|
||||
<#else>"${row.item.properties.title!""}",</#if>
|
||||
"description": "${row.item.properties.description!""}",
|
||||
<#if row.item.properties.modified??>"modified": "${xmldate(row.item.properties.modified)}",</#if>
|
||||
<#if row.item.properties.modifier??>"modifier": "${row.item.properties.modifier}",</#if>
|
||||
<#if row.item.siteShortName??>"site": "${row.item.siteShortName}",</#if>
|
||||
<#if row.item.properties["ia:fromDate"]??>"fromDate": "${xmldate(row.item.properties["ia:fromDate"])}",</#if>
|
||||
"displayPath": "${row.item.displayPath!""}",
|
||||
"qnamePath": "${row.item.qnamePath!""}",
|
||||
<#if row.item.typeShort != "cm:person" && row.item.typeShort != "cm:authorityContainer">
|
||||
"userAccess":
|
||||
{
|
||||
"create": ${row.item.hasPermission("CreateChildren")?string},
|
||||
"edit": ${row.item.hasPermission("Write")?string},
|
||||
"delete": ${row.item.hasPermission("Delete")?string}
|
||||
},
|
||||
</#if>
|
||||
"nodeRef": "${row.item.nodeRef}"<#if row.selectable?exists>,
|
||||
"selectable" : ${row.selectable?string}</#if>
|
||||
}<#if row_has_next>,</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
]
|
||||
}
|
||||
}
|
||||
</#escape>
|
||||
<#macro renderParent node indent=" ">
|
||||
<#escape x as jsonUtils.encodeJSONString(x)>
|
||||
${indent}"parent":
|
||||
${indent}{
|
||||
<#if (node != rootNode) && node.parent??>
|
||||
<@renderParent node.parent indent+" " />
|
||||
</#if>
|
||||
${indent}"type": "${node.typeShort}",
|
||||
${indent}"isContainer": ${node.isContainer?string},
|
||||
${indent}"name": "${node.properties.name!""}",
|
||||
${indent}"title": "${node.properties.title!""}",
|
||||
${indent}"description": "${node.properties.description!""}",
|
||||
<#if node.properties.modified??>${indent}"modified": "${xmldate(node.properties.modified)}",</#if>
|
||||
<#if node.properties.modifier??>${indent}"modifier": "${node.properties.modifier}",</#if>
|
||||
${indent}"displayPath": "${node.displayPath!""}",
|
||||
${indent}"qnamePath": "${node.qnamePath!""}",
|
||||
<#if node.aspects??>
|
||||
${indent}"aspects":
|
||||
${indent}[
|
||||
<#list node.aspects as aspect>
|
||||
"${shortQName(aspect)}"
|
||||
<#if aspect_has_next>,</#if>
|
||||
</#list>
|
||||
|
||||
${indent}],
|
||||
</#if>
|
||||
${indent}"nodeRef": "${node.nodeRef}"
|
||||
${indent}},
|
||||
</#escape>
|
||||
</#macro>
|
||||
|
||||
<#macro pickerResultsJSON results>
|
||||
<#escape x as jsonUtils.encodeJSONString(x)>
|
||||
{
|
||||
"data":
|
||||
{
|
||||
<#if parent??>
|
||||
<@renderParent parent />
|
||||
</#if>
|
||||
"items":
|
||||
[
|
||||
<#list results as row>
|
||||
{
|
||||
"type": "${row.item.typeShort}",
|
||||
"parentType": "${row.item.parentTypeShort!""}",
|
||||
"isContainer": ${row.item.isContainer?string},
|
||||
<#if row.container??>"container": "${row.container!""}",</#if>
|
||||
<#if row.item.properties?? && row.item.properties.name??>
|
||||
"name": "${row.item.properties.name!""}",
|
||||
<#else>
|
||||
"name": "${(row.item.name)!row.item?string!""}",
|
||||
</#if>
|
||||
<#if row.item.aspects??>
|
||||
"aspects": [
|
||||
<#list row.item.aspects as aspect>
|
||||
"${shortQName(aspect)}"
|
||||
<#if aspect_has_next>,</#if>
|
||||
</#list>
|
||||
],
|
||||
</#if>
|
||||
<#if row.item.properties??>
|
||||
"title":<#if row.item.properties["lnk:title"]??>"${row.item.properties["lnk:title"]}",
|
||||
<#elseif row.item.properties["ia:whatEvent"]??>"${row.item.properties["ia:whatEvent"]}",
|
||||
<#else>"${row.item.properties.title!""}",</#if>
|
||||
"description": "${row.item.properties.description!""}",
|
||||
<#else>
|
||||
"title": "${(row.item.name)!row.item?string!""}",
|
||||
"description": "",
|
||||
</#if>
|
||||
<#if row.item.properties.modified??>"modified": "${xmldate(row.item.properties.modified)}",</#if>
|
||||
<#if row.item.properties.modifier??>"modifier": "${row.item.properties.modifier}",</#if>
|
||||
<#if row.item.siteShortName??>"site": "${row.item.siteShortName}",</#if>
|
||||
<#if row.item.properties["ia:fromDate"]??>"fromDate": "${xmldate(row.item.properties["ia:fromDate"])}",</#if>
|
||||
"displayPath": "${row.item.displayPath!""}",
|
||||
"qnamePath": "${row.item.qnamePath!""}",
|
||||
<#if row.item.typeShort != "cm:person" && row.item.typeShort != "cm:authorityContainer">
|
||||
"userAccess":
|
||||
{
|
||||
"create": ${row.item.hasPermission("CreateChildren")?string},
|
||||
"edit": ${row.item.hasPermission("Write")?string},
|
||||
"delete": ${row.item.hasPermission("Delete")?string}
|
||||
},
|
||||
</#if>
|
||||
"nodeRef": "${row.item.nodeRef}"<#if row.selectable?exists>,
|
||||
"selectable" : ${row.selectable?string}</#if>
|
||||
}<#if row_has_next>,</#if>
|
||||
</#list>
|
||||
]
|
||||
}
|
||||
}
|
||||
</#escape>
|
||||
</#macro>
|
@@ -2,7 +2,7 @@ function extractMetadata(file)
|
||||
{
|
||||
// Extract metadata - via repository action for now.
|
||||
// This should use the MetadataExtracter API to fetch properties, allowing for possible failures.
|
||||
var emAction = actions.create("extract-metadata");
|
||||
var emAction = metadataExtractAction.create(true);
|
||||
if (emAction != null)
|
||||
{
|
||||
// Call using readOnly = false, newTransaction = false
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>25.3.0.45</version>
|
||||
<version>25.3.0.56</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.action.evaluator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.cmr.action.ParameterDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* Content change condition evaluator implementation. Required only in Scripted Actions to allow determination if content has changed. <br>
|
||||
* Usage in {@link org.alfresco.repo.jscript.MetaDataExtractAction#create(boolean)}
|
||||
*
|
||||
* @author Sayan Bhattacharya
|
||||
*/
|
||||
|
||||
public class CompareContentConditionEvaluator extends ActionConditionEvaluatorAbstractBase
|
||||
{
|
||||
/**
|
||||
* Evaluator constants
|
||||
*/
|
||||
public static final String NAME = "compare-content";
|
||||
public static final String PARAM_IS_CONTENT_CHANGED = "isContentChanged";
|
||||
|
||||
/**
|
||||
* @see ActionConditionEvaluatorAbstractBase#evaluateImpl(ActionCondition, NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public boolean evaluateImpl(ActionCondition ruleCondition, NodeRef actionedUponNodeRef)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(List)
|
||||
*/
|
||||
@Override
|
||||
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
|
||||
{
|
||||
// No parameters to add
|
||||
}
|
||||
|
||||
}
|
@@ -51,12 +51,14 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.evaluator.CompareContentConditionEvaluator;
|
||||
import org.alfresco.repo.content.metadata.AbstractMappingMetadataExtracter;
|
||||
import org.alfresco.repo.content.metadata.AsynchronousExtractor;
|
||||
import org.alfresco.repo.content.metadata.MetadataExtracter;
|
||||
@@ -403,6 +405,7 @@ public class ContentMetadataExtracter extends ActionExecuterAbstractBase
|
||||
((AbstractMappingMetadataExtracter) extracter).setEnableStringTagging(enableStringTagging);
|
||||
}
|
||||
|
||||
MetadataExtracter.OverwritePolicy overwritePolicy = determineOverwritePolicy(ruleAction);
|
||||
// Get all the node's properties
|
||||
Map<QName, Serializable> nodeProperties = nodeService.getProperties(actionedUponNodeRef);
|
||||
|
||||
@@ -415,7 +418,7 @@ public class ContentMetadataExtracter extends ActionExecuterAbstractBase
|
||||
modifiedProperties = extracter.extract(
|
||||
actionedUponNodeRef,
|
||||
reader,
|
||||
/* OverwritePolicy.PRAGMATIC, */
|
||||
overwritePolicy,
|
||||
nodeProperties);
|
||||
}
|
||||
catch (Throwable e)
|
||||
@@ -456,6 +459,21 @@ public class ContentMetadataExtracter extends ActionExecuterAbstractBase
|
||||
stringTaggingSeparators);
|
||||
}
|
||||
|
||||
private MetadataExtracter.OverwritePolicy determineOverwritePolicy(Action ruleAction)
|
||||
{
|
||||
return Optional.ofNullable(ruleAction.getActionConditions())
|
||||
.flatMap(conditions -> conditions.stream()
|
||||
.filter(e -> CompareContentConditionEvaluator.NAME.equals(e.getActionConditionDefinitionName()))
|
||||
.findAny()
|
||||
.map(e -> {
|
||||
Serializable contentChanged = e.getParameterValue(CompareContentConditionEvaluator.PARAM_IS_CONTENT_CHANGED);
|
||||
return Boolean.TRUE.equals(contentChanged)
|
||||
? MetadataExtracter.OverwritePolicy.EAGER
|
||||
: MetadataExtracter.OverwritePolicy.PRAGMATIC;
|
||||
}))
|
||||
.orElse(MetadataExtracter.OverwritePolicy.PRAGMATIC);
|
||||
}
|
||||
|
||||
public static void addExtractedMetadataToNode(NodeRef actionedUponNodeRef, Map<QName, Serializable> nodeProperties,
|
||||
Map<QName, Serializable> modifiedProperties,
|
||||
NodeService nodeService, DictionaryService dictionaryService,
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -102,6 +102,7 @@ import org.alfresco.service.namespace.QName;
|
||||
* @author Jesper Steen Møller
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
@SuppressWarnings("PMD.CyclomaticComplexity")
|
||||
@AlfrescoPublicApi
|
||||
abstract public class AbstractMappingMetadataExtracter implements MetadataExtracter, MetadataEmbedder, BeanNameAware, ApplicationContextAware
|
||||
{
|
||||
@@ -1118,6 +1119,15 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
return extract(nodeRef, reader, overwritePolicy, destination, mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Map<QName, Serializable> extract(NodeRef nodeRef, ContentReader reader, OverwritePolicy overwritePolicy, Map<QName, Serializable> destination)
|
||||
{
|
||||
return extract(nodeRef, reader, overwritePolicy, destination, mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -1154,7 +1164,7 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
// Check that the content has some meat
|
||||
if (reader.getSize() > 0 && reader.exists())
|
||||
{
|
||||
rawMetadata = extractRaw(nodeRef, reader, getLimits(reader.getMimetype()));
|
||||
rawMetadata = extractRaw(nodeRef, reader, getLimits(reader.getMimetype()), overwritePolicy);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2002,7 +2012,7 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception wrapper to handle exceeded limits imposed by {@link MetadataExtracterLimits} {@link AbstractMappingMetadataExtracter#extractRaw(NodeRef, ContentReader, MetadataExtracterLimits)}
|
||||
* Exception wrapper to handle exceeded limits imposed by {@link MetadataExtracterLimits} {@link AbstractMappingMetadataExtracter#extractRaw(NodeRef, ContentReader, MetadataExtracterLimits,OverwritePolicy)}
|
||||
*/
|
||||
private class LimitExceededException extends Exception
|
||||
{
|
||||
@@ -2032,7 +2042,7 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
* All exception conditions can be handled.
|
||||
*/
|
||||
private Map<String, Serializable> extractRaw(NodeRef nodeRef,
|
||||
ContentReader reader, MetadataExtracterLimits limits) throws Throwable
|
||||
ContentReader reader, MetadataExtracterLimits limits, OverwritePolicy overwritePolicy) throws Throwable
|
||||
{
|
||||
if (reader.getSize() > limits.getMaxDocumentSizeMB() * MEGABYTE_SIZE)
|
||||
{
|
||||
@@ -2059,6 +2069,12 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
}
|
||||
}
|
||||
|
||||
return extractRawInThread(nodeRef, reader, limits, overwritePolicy);
|
||||
}
|
||||
|
||||
protected Map<String, Serializable> extractRawInThread(NodeRef nodeRef, ContentReader reader, MetadataExtracterLimits limits, OverwritePolicy policy)
|
||||
throws Throwable
|
||||
{
|
||||
return extractRawInThread(nodeRef, reader, limits);
|
||||
}
|
||||
|
||||
|
@@ -93,6 +93,9 @@ public class AsynchronousExtractor extends AbstractMappingMetadataExtracter
|
||||
private static final String METADATA = "metadata";
|
||||
private static final Map<String, Serializable> EMPTY_METADATA = Collections.emptyMap();
|
||||
|
||||
private static final OverwritePolicy DEFAULT_OVERWRITE_POLICY = OverwritePolicy.PRAGMATIC;
|
||||
private OverwritePolicy extractOverwritePolicy = DEFAULT_OVERWRITE_POLICY;
|
||||
|
||||
private final ObjectMapper jsonObjectMapper = new ObjectMapper();
|
||||
|
||||
private NodeService nodeService;
|
||||
@@ -260,9 +263,9 @@ public class AsynchronousExtractor extends AbstractMappingMetadataExtracter
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Serializable> extractRawInThread(NodeRef nodeRef, ContentReader reader, MetadataExtracterLimits limits)
|
||||
throws Throwable
|
||||
protected Map<String, Serializable> extractRawInThread(NodeRef nodeRef, ContentReader reader, MetadataExtracterLimits limits, OverwritePolicy overwritePolicy) throws Throwable
|
||||
{
|
||||
this.extractOverwritePolicy = overwritePolicy != null ? overwritePolicy : DEFAULT_OVERWRITE_POLICY;
|
||||
Map<String, String> options = getExtractOptions(nodeRef, reader, limits);
|
||||
transformInBackground(nodeRef, reader, MIMETYPE_METADATA_EXTRACT, EXTRACT, options);
|
||||
return EMPTY_METADATA;
|
||||
@@ -461,7 +464,7 @@ public class AsynchronousExtractor extends AbstractMappingMetadataExtracter
|
||||
}
|
||||
|
||||
// Remove well know entries from the map that drive how the real metadata is applied.
|
||||
OverwritePolicy overwritePolicy = removeOverwritePolicy(metadata, "sys:overwritePolicy", OverwritePolicy.PRAGMATIC);
|
||||
OverwritePolicy overwritePolicy = removeOverwritePolicy(metadata, "sys:overwritePolicy", extractOverwritePolicy);
|
||||
Boolean enableStringTagging = removeBoolean(metadata, "sys:enableStringTagging", false);
|
||||
Boolean carryAspectProperties = removeBoolean(metadata, "sys:carryAspectProperties", true);
|
||||
List<String> stringTaggingSeparators = removeTaggingSeparators(metadata, "sys:stringTaggingSeparators",
|
||||
|
@@ -404,6 +404,24 @@ public interface MetadataExtracter extends ContentWorker
|
||||
return extract(reader, destination);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identical to {@link #extract(ContentReader, OverwritePolicy ,Map)} but with the addition of the {@code NodeRef} being acted on. By default, the method without the {@code NodeRef} is called.
|
||||
*
|
||||
* @param nodeRef
|
||||
* the node being acted on.
|
||||
* @param reader
|
||||
* the source of the content
|
||||
* @param destination
|
||||
* the map of properties to populate (essentially a return value)
|
||||
* @return Returns a map of all properties on the destination map that were added or modified. If the return map is empty, then no properties were modified.
|
||||
* @throws ContentIOException
|
||||
* if a detectable error occurs
|
||||
*/
|
||||
default Map<QName, Serializable> extract(NodeRef nodeRef, ContentReader reader, OverwritePolicy overwritePolicy, Map<QName, Serializable> destination)
|
||||
{
|
||||
return extract(reader, overwritePolicy, destination);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identical to {@link #extract(ContentReader, OverwritePolicy, Map, Map)} but with the addition of the {@code NodeRef} being acted on. By default, the method without the {@code NodeRef} is called.
|
||||
*
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -97,19 +97,26 @@ public abstract class EventConsolidator<REF extends EntityRef, RES extends Resou
|
||||
* @return the {@link RepoEvent} instance
|
||||
*/
|
||||
public RepoEvent<DataAttributes<RES>> getRepoEvent(EventInfo eventInfo)
|
||||
{
|
||||
final RepoEvent.Builder<DataAttributes<RES>> builder = RepoEvent.builder();
|
||||
|
||||
configureRepoEventBuilder(builder, eventInfo);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected void configureRepoEventBuilder(RepoEvent.Builder<DataAttributes<RES>> builder, EventInfo eventInfo)
|
||||
{
|
||||
EventType eventType = getDerivedEvent();
|
||||
|
||||
DataAttributes<RES> eventData = buildEventData(eventInfo, resource, eventType);
|
||||
|
||||
return RepoEvent.<DataAttributes<RES>> builder()
|
||||
.setId(eventInfo.getId())
|
||||
builder.setId(eventInfo.getId())
|
||||
.setSource(eventInfo.getSource())
|
||||
.setTime(eventInfo.getTimestamp())
|
||||
.setType(eventType.getType())
|
||||
.setData(eventData)
|
||||
.setDataschema(EventJSONSchema.getSchemaV1(eventType))
|
||||
.build();
|
||||
.setDataschema(EventJSONSchema.getSchemaV1(eventType));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -4,21 +4,21 @@
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
@@ -34,7 +34,7 @@ import org.alfresco.service.cmr.action.ActionService;
|
||||
|
||||
/**
|
||||
* Scripted Action service for describing and executing actions against Nodes.
|
||||
*
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public final class Actions extends BaseScopableProcessorExtension
|
||||
@@ -44,7 +44,7 @@ public final class Actions extends BaseScopableProcessorExtension
|
||||
|
||||
/**
|
||||
* Set the service registry
|
||||
*
|
||||
*
|
||||
* @param serviceRegistry
|
||||
* the service registry
|
||||
*/
|
||||
@@ -55,7 +55,7 @@ public final class Actions extends BaseScopableProcessorExtension
|
||||
|
||||
/**
|
||||
* Gets the list of registered action names
|
||||
*
|
||||
*
|
||||
* @return the registered action names
|
||||
*/
|
||||
public String[] getRegistered()
|
||||
@@ -73,7 +73,7 @@ public final class Actions extends BaseScopableProcessorExtension
|
||||
|
||||
/**
|
||||
* Create an Action
|
||||
*
|
||||
*
|
||||
* @param actionName
|
||||
* the action name
|
||||
* @return the action
|
||||
|
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.jscript;
|
||||
|
||||
import org.apache.commons.lang3.Strings;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.evaluator.CompareContentConditionEvaluator;
|
||||
import org.alfresco.repo.forms.FormData;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.cmr.action.ActionDefinition;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* JavaScript wrapper for the "extract-metadata" action.
|
||||
* <p>
|
||||
* This class provides a scriptable interface to trigger metadata extraction actions within the Alfresco repository.</br>
|
||||
* It is similar to {@link Actions} class but is dedicated to metadata extraction functionality.
|
||||
*
|
||||
* </br>
|
||||
*
|
||||
* @author Sayan Bhattacharya
|
||||
*/
|
||||
public final class MetaDataExtractAction extends BaseScopableProcessorExtension
|
||||
{
|
||||
private static final Log LOG = LogFactory.getLog(MetaDataExtractAction.class);
|
||||
|
||||
private final static String ACTION_NAME = "extract-metadata";
|
||||
|
||||
private ContentService contentService;
|
||||
|
||||
private ServiceRegistry services;
|
||||
|
||||
/**
|
||||
* Set the service registry
|
||||
*
|
||||
* @param serviceRegistry
|
||||
* the service registry
|
||||
*/
|
||||
public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
||||
{
|
||||
this.services = serviceRegistry;
|
||||
}
|
||||
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new metadata extraction action instance
|
||||
*
|
||||
* @param setActionContext
|
||||
* if true, sets the action context to "scriptaction".
|
||||
* @return the newly created action
|
||||
*/
|
||||
|
||||
public ScriptAction create(boolean isContentChanged)
|
||||
{
|
||||
ScriptAction scriptAction = null;
|
||||
ActionService actionService = services.getActionService();
|
||||
ActionDefinition actionDef = actionService.getActionDefinition(ACTION_NAME);
|
||||
if (actionDef != null)
|
||||
{
|
||||
Action action = actionService.createAction(ACTION_NAME);
|
||||
|
||||
ActionCondition actionCondition = actionService.createActionCondition(CompareContentConditionEvaluator.NAME);
|
||||
actionCondition.setParameterValue(CompareContentConditionEvaluator.PARAM_IS_CONTENT_CHANGED, isContentChanged);
|
||||
action.addActionCondition(actionCondition);
|
||||
|
||||
scriptAction = new ScriptAction(this.services, action, actionDef);
|
||||
scriptAction.setScope(getScope());
|
||||
}
|
||||
return scriptAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the content has been updated in the form data compared to the existing content of the node.
|
||||
*
|
||||
* @param itemId
|
||||
* @param formData
|
||||
* @return true if content has changed, false otherwise
|
||||
*/
|
||||
public boolean isContentChanged(String itemId, FormData formData)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
NodeRef nodeRef = NodeRef.isNodeRef(itemId) ? new NodeRef(itemId) : parseNodeRef(itemId);
|
||||
if (nodeRef == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
||||
String contentString = reader.getContentString();
|
||||
FormData.FieldData fieldData = formData.getFieldData("prop_cm_content");
|
||||
|
||||
if (fieldData == null || fieldData.getValue() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
String propCmContent = String.valueOf(fieldData.getValue());
|
||||
return !Strings.CS.equals(contentString, propCmContent);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("Unable to determine if content has changed for node: " + itemId, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private NodeRef parseNodeRef(String itemId)
|
||||
{
|
||||
String[] parts = itemId.split("/");
|
||||
return (parts.length == 3) ? new NodeRef(parts[0], parts[1], parts[2]) : null;
|
||||
}
|
||||
|
||||
}
|
@@ -237,6 +237,12 @@
|
||||
<bean id="no-condition" class="org.alfresco.repo.action.evaluator.NoConditionEvaluator" parent="action-condition-evaluator">
|
||||
</bean>
|
||||
|
||||
<bean id="compare-content" class="org.alfresco.repo.action.evaluator.CompareContentConditionEvaluator" parent="action-condition-evaluator">
|
||||
<property name="publicCondition">
|
||||
<value>false</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="compare-property-value" class="org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator" parent="action-condition-evaluator">
|
||||
<property name="nodeService">
|
||||
<ref bean="nodeService" />
|
||||
|
@@ -104,6 +104,17 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="metadataExtractServiceScript" parent="baseJavaScriptExtension"
|
||||
class="org.alfresco.repo.jscript.MetaDataExtractAction">
|
||||
<property name="extensionName">
|
||||
<value>metadataExtractAction</value>
|
||||
</property>
|
||||
<property name="contentService" ref="ContentService" />
|
||||
<property name="serviceRegistry">
|
||||
<ref bean="ServiceRegistry"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="imapScript" parent="baseJavaScriptExtension" class="org.alfresco.repo.jscript.Imap">
|
||||
<property name="extensionName">
|
||||
<value>imap</value>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2017 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -66,6 +66,7 @@ import org.alfresco.util.testing.category.NonBuildTests;
|
||||
org.alfresco.repo.importer.FileImporterTest.class,
|
||||
org.alfresco.repo.importer.ImporterComponentTest.class,
|
||||
org.alfresco.repo.jscript.PeopleTest.class,
|
||||
org.alfresco.repo.jscript.MetaDataExtractActionTest.class,
|
||||
org.alfresco.repo.jscript.RhinoScriptTest.class,
|
||||
|
||||
// needs a clean DB to run
|
||||
|
@@ -28,6 +28,7 @@ package org.alfresco.repo.action.executer;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -46,6 +47,8 @@ import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.content.metadata.AbstractMappingMetadataExtracter;
|
||||
import org.alfresco.repo.content.metadata.MetadataExtracterRegistry;
|
||||
import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
|
||||
import org.alfresco.repo.jscript.MetaDataExtractAction;
|
||||
import org.alfresco.repo.jscript.ScriptAction;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
@@ -74,6 +77,10 @@ public class ContentMetadataExtracterTest extends BaseSpringTest
|
||||
protected static final String QUICK_DESCRIPTION = "Pangram, fox, dog, Gym class featuring a brown fox and lazy dog";
|
||||
protected static final String QUICK_CREATOR = "Nevin Nollop";
|
||||
|
||||
protected static final String QUICK_UPDATED_TITLE = "The hot dog is eaten by the city fox";
|
||||
protected static final String QUICK_UPDATED_DESCRIPTION = "Pangram, fox, dog, Gym class featuring only brown fox";
|
||||
protected static final String QUICK_UPDATED_CREATOR = "Friday";
|
||||
|
||||
private NodeService nodeService;
|
||||
private ContentService contentService;
|
||||
private MetadataExtracterRegistry registry;
|
||||
@@ -84,6 +91,8 @@ public class ContentMetadataExtracterTest extends BaseSpringTest
|
||||
|
||||
private ContentMetadataExtracter executer;
|
||||
|
||||
private MetaDataExtractAction extractAction;
|
||||
|
||||
private final static String ID = GUID.generate();
|
||||
|
||||
@Before
|
||||
@@ -116,6 +125,9 @@ public class ContentMetadataExtracterTest extends BaseSpringTest
|
||||
|
||||
// Get the executer instance
|
||||
this.executer = (ContentMetadataExtracter) this.applicationContext.getBean("extract-metadata");
|
||||
|
||||
// get the js script action
|
||||
this.extractAction = (MetaDataExtractAction) this.applicationContext.getBean("metadataExtractServiceScript");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -351,4 +363,45 @@ public class ContentMetadataExtracterTest extends BaseSpringTest
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsingScriptAction_WhenContentChanged() throws Exception
|
||||
{
|
||||
|
||||
// update the content
|
||||
ContentWriter cw = this.contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||
cw.setMimetype(MimetypeMap.MIMETYPE_PDF);
|
||||
cw.putContent(AbstractContentTransformerTest.loadNamedQuickTestFile("quickupdated.pdf"));
|
||||
|
||||
// Make the nodeRef visible to other transactions as it will need to be in async requests
|
||||
TestTransaction.flagForCommit();
|
||||
TestTransaction.end();
|
||||
|
||||
// Execute the action
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() {
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
ScriptAction action = extractAction.create(true);
|
||||
action.execute(nodeRef, false, false);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Need to wait for the async extract
|
||||
await().pollInSameThread()
|
||||
.atMost(Duration.ofSeconds(100))
|
||||
.until(() -> nodeService.getProperty(nodeRef, ContentModel.PROP_DESCRIPTION), Objects::nonNull);
|
||||
|
||||
// Check that the properties have been preserved, but that description has been set
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() {
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
assertEquals(QUICK_UPDATED_TITLE, nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE));
|
||||
assertEquals(QUICK_UPDATED_CREATOR, nodeService.getProperty(nodeRef, ContentModel.PROP_AUTHOR));
|
||||
|
||||
assertEquals(QUICK_UPDATED_DESCRIPTION, nodeService.getProperty(nodeRef, ContentModel.PROP_DESCRIPTION));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2005 Jesper Steen Møller
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.jscript;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.alfresco.repo.forms.FormData;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.cmr.action.ActionDefinition;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
|
||||
public class MetaDataExtractActionTest
|
||||
{
|
||||
|
||||
@Test
|
||||
public void testIsContentChangedReturnsTrue()
|
||||
{
|
||||
MetaDataExtractAction action = new MetaDataExtractAction();
|
||||
ContentService contentService = Mockito.mock(ContentService.class);
|
||||
ContentReader reader = Mockito.mock(ContentReader.class);
|
||||
FormData formData = Mockito.mock(FormData.class);
|
||||
FormData.FieldData fieldData = Mockito.mock(FormData.FieldData.class);
|
||||
|
||||
String nodeRefStr = "workspace://SpacesStore/abc/def";
|
||||
Mockito.when(contentService.getReader(Mockito.any(), Mockito.any())).thenReturn(reader);
|
||||
Mockito.when(reader.getContentString()).thenReturn("oldContent");
|
||||
Mockito.when(formData.getFieldData("prop_cm_content")).thenReturn(fieldData);
|
||||
Mockito.when(fieldData.getValue()).thenReturn("newContent");
|
||||
|
||||
action.setContentService(contentService);
|
||||
|
||||
boolean result = action.isContentChanged(nodeRefStr, formData);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsContentChangedReturnsFalse()
|
||||
{
|
||||
MetaDataExtractAction action = new MetaDataExtractAction();
|
||||
ContentService contentService = Mockito.mock(ContentService.class);
|
||||
ContentReader reader = Mockito.mock(ContentReader.class);
|
||||
FormData formData = Mockito.mock(FormData.class);
|
||||
FormData.FieldData fieldData = Mockito.mock(FormData.FieldData.class);
|
||||
|
||||
String nodeRefStr = "workspace://SpacesStore/abc/def";
|
||||
Mockito.when(contentService.getReader(Mockito.any(), Mockito.any())).thenReturn(reader);
|
||||
Mockito.when(reader.getContentString()).thenReturn("sameContent");
|
||||
Mockito.when(formData.getFieldData("prop_cm_content")).thenReturn(fieldData);
|
||||
Mockito.when(fieldData.getValue()).thenReturn("sameContent");
|
||||
|
||||
action.setContentService(contentService);
|
||||
|
||||
boolean result = action.isContentChanged(nodeRefStr, formData);
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateWhenContentChangedReturnsScriptAction()
|
||||
{
|
||||
MetaDataExtractAction action = new MetaDataExtractAction();
|
||||
|
||||
ServiceRegistry serviceRegistry = Mockito.mock(ServiceRegistry.class);
|
||||
ActionService actionService = Mockito.mock(ActionService.class);
|
||||
ActionDefinition actionDefinition = Mockito.mock(ActionDefinition.class);
|
||||
Action alfrescoAction = Mockito.mock(Action.class);
|
||||
ActionCondition actionCondition = Mockito.mock(ActionCondition.class);
|
||||
|
||||
Mockito.when(serviceRegistry.getActionService()).thenReturn(actionService);
|
||||
Mockito.when(actionService.getActionDefinition(Mockito.anyString())).thenReturn(actionDefinition);
|
||||
Mockito.when(actionService.createAction(Mockito.anyString())).thenReturn(alfrescoAction);
|
||||
Mockito.when(actionService.createActionCondition(Mockito.anyString())).thenReturn(actionCondition);
|
||||
|
||||
action.setServiceRegistry(serviceRegistry);
|
||||
|
||||
ScriptAction result = action.create(true);
|
||||
|
||||
assertNotNull("ScriptAction should not be null when content has changed", result);
|
||||
}
|
||||
}
|
BIN
repository/src/test/resources/quick/quickupdated.pdf
Normal file
BIN
repository/src/test/resources/quick/quickupdated.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user