initial checkin
This commit is contained in:
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Maven
|
||||||
|
target
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
|
||||||
|
# Eclipse
|
||||||
|
.settings
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.factorypath
|
||||||
|
.vscode
|
||||||
|
|
88
pom.xml
Normal file
88
pom.xml
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
|
<artifactId>bulk-platform-module</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>bulk ACS Platform Module</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
|
||||||
|
<alfresco.sdk.version>4.2.0</alfresco.sdk.version>
|
||||||
|
<alfresco.platform.version>6.2.0-ga</alfresco.platform.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.alfresco</groupId>
|
||||||
|
<artifactId>acs-community-packaging</artifactId>
|
||||||
|
<version>${alfresco.platform.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- Very popular, but not required, dependency -->
|
||||||
|
<!-- Provided as an example -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.alfresco</groupId>
|
||||||
|
<artifactId>alfresco-repository</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.swagger</groupId>
|
||||||
|
<artifactId>swagger-jaxrs</artifactId>
|
||||||
|
<version>1.6.2</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>io.repaint.maven</groupId>
|
||||||
|
<artifactId>tiles-maven-plugin</artifactId>
|
||||||
|
<version>2.26</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<tiles>
|
||||||
|
<!-- Documentation: https://bitbucket.org/inteligr8/ootbee-beedk/src/stable/beedk-acs-platform-self-rad-tile -->
|
||||||
|
<tile>com.inteligr8.ootbee:beedk-acs-platform-self-rad-tile:[1.0.0,2.0.0)</tile>
|
||||||
|
<!-- Documentation: https://bitbucket.org/inteligr8/ootbee-beedk/src/stable/beedk-acs-platform-module-tile -->
|
||||||
|
<tile>com.inteligr8.ootbee:beedk-acs-platform-module-tile:[1.0.0,2.0.0)</tile>
|
||||||
|
<!-- Documentation: https://bitbucket.org/inteligr8/ootbee-beedk/src/stable/beedk-acs-platform-self-it-tile
|
||||||
|
<tile>com.inteligr8.ootbee:beedk-acs-platform-self-it-tile:[1.0.0,2.0.0)</tile> -->
|
||||||
|
</tiles>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>inteligr8-releases</id>
|
||||||
|
<url>http://repos.inteligr8.com/nexus/repository/inteligr8-public</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>alfresco-public</id>
|
||||||
|
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>inteligr8-releases</id>
|
||||||
|
<url>http://repos.inteligr8.com/nexus/repository/inteligr8-public</url>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
</project>
|
74
rad.ps1
Normal file
74
rad.ps1
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
|
||||||
|
function discoverArtifactId {
|
||||||
|
$script:ARTIFACT_ID=(mvn -q -Dexpression=project"."artifactId -DforceStdout help:evaluate)
|
||||||
|
}
|
||||||
|
|
||||||
|
function rebuild {
|
||||||
|
echo "Rebuilding project ..."
|
||||||
|
mvn process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
function start_ {
|
||||||
|
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||||
|
mvn -Drad process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
function start_log {
|
||||||
|
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||||
|
mvn -Drad "-Ddocker.showLogs" process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop_ {
|
||||||
|
discoverArtifactId
|
||||||
|
echo "Stopping Docker containers that supported rapid application development ..."
|
||||||
|
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||||
|
echo "Stopping containers ..."
|
||||||
|
docker container stop (docker container ls -q --filter name=${ARTIFACT_ID}-*)
|
||||||
|
echo "Removing containers ..."
|
||||||
|
docker container rm (docker container ls -aq --filter name=${ARTIFACT_ID}-*)
|
||||||
|
}
|
||||||
|
|
||||||
|
function tail_logs {
|
||||||
|
param (
|
||||||
|
$container
|
||||||
|
)
|
||||||
|
|
||||||
|
discoverArtifactId
|
||||||
|
docker container logs -f (docker container ls -q --filter name=${ARTIFACT_ID}-${container})
|
||||||
|
}
|
||||||
|
|
||||||
|
function list {
|
||||||
|
discoverArtifactId
|
||||||
|
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($args[0]) {
|
||||||
|
"start" {
|
||||||
|
start_
|
||||||
|
}
|
||||||
|
"start_log" {
|
||||||
|
start_log
|
||||||
|
}
|
||||||
|
"stop" {
|
||||||
|
stop_
|
||||||
|
}
|
||||||
|
"restart" {
|
||||||
|
stop_
|
||||||
|
start_
|
||||||
|
}
|
||||||
|
"rebuild" {
|
||||||
|
rebuild
|
||||||
|
}
|
||||||
|
"tail" {
|
||||||
|
tail_logs $args[1]
|
||||||
|
}
|
||||||
|
"containers" {
|
||||||
|
list
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
echo "Usage: .\rad.ps1 [ start | start_log | stop | restart | rebuild | tail {container} | containers ]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Completed!"
|
||||||
|
|
71
rad.sh
Normal file
71
rad.sh
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
discoverArtifactId() {
|
||||||
|
ARTIFACT_ID=`mvn -q -Dexpression=project.artifactId -DforceStdout help:evaluate`
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuild() {
|
||||||
|
echo "Rebuilding project ..."
|
||||||
|
mvn process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||||
|
mvn -Drad process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
start_log() {
|
||||||
|
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||||
|
mvn -Drad -Ddocker.showLogs process-classes
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
discoverArtifactId
|
||||||
|
echo "Stopping Docker containers that supported rapid application development ..."
|
||||||
|
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||||
|
echo "Stopping containers ..."
|
||||||
|
docker container stop `docker container ls -q --filter name=${ARTIFACT_ID}-*`
|
||||||
|
echo "Removing containers ..."
|
||||||
|
docker container rm `docker container ls -aq --filter name=${ARTIFACT_ID}-*`
|
||||||
|
}
|
||||||
|
|
||||||
|
tail_logs() {
|
||||||
|
discoverArtifactId
|
||||||
|
docker container logs -f `docker container ls -q --filter name=${ARTIFACT_ID}-$1`
|
||||||
|
}
|
||||||
|
|
||||||
|
list() {
|
||||||
|
discoverArtifactId
|
||||||
|
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
start_log)
|
||||||
|
start_log
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
rebuild)
|
||||||
|
rebuild
|
||||||
|
;;
|
||||||
|
tail)
|
||||||
|
tail_logs $2
|
||||||
|
;;
|
||||||
|
containers)
|
||||||
|
list
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: ./rad.sh [ start | start_log | stop | restart | rebuild | tail {container} | containers ]"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "Completed!"
|
||||||
|
|
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.inteligr8.alfresco.bulk;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.policy.BehaviourFilter;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
|
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.apache.tika.Tika;
|
||||||
|
import org.apache.tika.config.TikaConfig;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.extensions.webscripts.AbstractWebScript;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.inteligr8.alfresco.bulk.model.ContentDataBody;
|
||||||
|
|
||||||
|
public abstract class AbstractNodesWebScript extends AbstractWebScript {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@Value("${inteligr8.bulk.enableTika:false}")
|
||||||
|
private boolean enableTika;
|
||||||
|
|
||||||
|
@Value("${inteligr8.bulk.allowOctetStream:false}")
|
||||||
|
protected boolean allowOctetStream;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected ContentService contentService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected DictionaryService dictionaryService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected MimetypeService mimeTypeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected NamespaceService namespaceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected NodeService nodeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected BehaviourFilter behaviorFilter;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected TransactionService txService;
|
||||||
|
|
||||||
|
protected final ObjectMapper om = new ObjectMapper();
|
||||||
|
|
||||||
|
protected final Collection<MediaType> jsonMediaTypes =
|
||||||
|
MediaType.parseMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON_VALUE, "applicatin/*+json"));
|
||||||
|
|
||||||
|
protected List<ContentDataBody> wrapContents(ContentDataBody contentData, List<ContentDataBody> contents) {
|
||||||
|
List<ContentDataBody> allcontents = new ArrayList<>(contents == null ? 1 : (contents.size() + 1));
|
||||||
|
if (contentData != null)
|
||||||
|
allcontents.add(contentData);
|
||||||
|
if (contents != null)
|
||||||
|
allcontents.addAll(contents);
|
||||||
|
return allcontents;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateRequest(List<?> nodes) {
|
||||||
|
if (nodes == null || nodes.isEmpty())
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "At least one node is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String determineMimeType(QName contentPropName, ContentReader creader, String name) {
|
||||||
|
if (this.enableTika) {
|
||||||
|
this.logger.trace("Using Tika to detect the MIME type: {} => {}", creader.getContentUrl(), name);
|
||||||
|
|
||||||
|
try {
|
||||||
|
InputStream istream = creader.getContentInputStream();
|
||||||
|
try {
|
||||||
|
Tika tika = new Tika(TikaConfig.getDefaultConfig());
|
||||||
|
String mimeType = tika.detect(istream, name);
|
||||||
|
this.logger.trace("Tika detected MIME type: {} => {}", creader.getContentUrl(), mimeType);
|
||||||
|
|
||||||
|
if (!MediaType.APPLICATION_OCTET_STREAM_VALUE.equals(mimeType))
|
||||||
|
return mimeType;
|
||||||
|
} finally {
|
||||||
|
istream.close();
|
||||||
|
}
|
||||||
|
} catch (IOException ie) {
|
||||||
|
this.logger.warn("Tika MIME detection failed: {}: {}", creader.getContentUrl(), ie.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!contentPropName.equals(ContentModel.PROP_CONTENT)) {
|
||||||
|
this.logger.debug("Unable to auto-detect a content property other than the default 'cm:content': {}", contentPropName);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos = name.lastIndexOf('.');
|
||||||
|
if (pos < 0) {
|
||||||
|
this.logger.debug("Unable to auto-detect a MIME type without a filename extension: {}", name);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String extension = name.substring(pos+1);
|
||||||
|
String mimeType = this.mimeTypeService.getMimetype(extension);
|
||||||
|
this.logger.debug("Detected file extension and MIME type: {} => {}", extension, mimeType);
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.inteligr8.alfresco.bulk;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.extensions.surf.util.Content;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.inteligr8.alfresco.bulk.model.AssociationBody;
|
||||||
|
import com.inteligr8.alfresco.bulk.model.ChildAssociationBody;
|
||||||
|
import com.inteligr8.alfresco.bulk.model.ContentDataBody;
|
||||||
|
import com.inteligr8.alfresco.bulk.model.NodeBodyCreateExt;
|
||||||
|
|
||||||
|
@Component(value = "webscript.com.inteligr8.alfresco.bulk.createNodes.post")
|
||||||
|
public class CreateNodesWebScript extends AbstractNodesWebScript {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException {
|
||||||
|
this.logger.trace("execute()");
|
||||||
|
|
||||||
|
String folderNodeId = req.getServiceMatch().getTemplateVars().get("folderNodeId");
|
||||||
|
|
||||||
|
MediaType contentType = this.validateAndGetContentType(req.getContentType());
|
||||||
|
boolean multipart = MediaType.MULTIPART_FORM_DATA.equals(contentType);
|
||||||
|
|
||||||
|
List<String> createdNodeIds;
|
||||||
|
if (multipart) {
|
||||||
|
throw new WebScriptException(HttpStatus.NOT_IMPLEMENTED.value(), "This service does not yet support multipart content");
|
||||||
|
} else {
|
||||||
|
List<NodeBodyCreateExt> nodes = this.parseRequest(req.getContent());
|
||||||
|
this.validateRequest(nodes);
|
||||||
|
|
||||||
|
createdNodeIds = this.createNodes(folderNodeId, nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.setStatus(HttpStatus.OK.value());
|
||||||
|
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
|
res.setContentEncoding("utf-8");
|
||||||
|
this.om.writeValue(res.getWriter(), createdNodeIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> createNodes(String parentNodeId, List<NodeBodyCreateExt> nodes) {
|
||||||
|
RetryingTransactionCallback<Object> rtcallback = new RetryingTransactionCallback<Object>() {
|
||||||
|
@Override
|
||||||
|
public Object execute() {
|
||||||
|
NodeRef parentNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, parentNodeId);
|
||||||
|
if (!nodeService.exists(parentNodeRef))
|
||||||
|
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The folder node could not be found: {}", parentNodeId);
|
||||||
|
if (!dictionaryService.isSubClass(nodeService.getType(parentNodeRef), ContentModel.TYPE_FOLDER))
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "The parent node must be a folder: {}", parentNodeId);
|
||||||
|
|
||||||
|
// allow cm:created/cm:modified to override
|
||||||
|
behaviorFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||||
|
|
||||||
|
List<String> createdNodeIds = new LinkedList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (NodeBodyCreateExt node : nodes) {
|
||||||
|
String nodeId = createNode(parentNodeRef, node);
|
||||||
|
if (nodeId != null)
|
||||||
|
createdNodeIds.add(nodeId);
|
||||||
|
}
|
||||||
|
} catch (WebScriptException wse) {
|
||||||
|
return wse;
|
||||||
|
}
|
||||||
|
|
||||||
|
behaviorFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||||
|
|
||||||
|
return createdNodeIds;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object response = this.txService.getRetryingTransactionHelper().doInTransaction(rtcallback, false, false);
|
||||||
|
if (response instanceof WebScriptException)
|
||||||
|
throw (WebScriptException) response;
|
||||||
|
return (List<String>) response;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String createNode(NodeRef parentNodeRef, NodeBodyCreateExt incomingNode) {
|
||||||
|
this.logger.debug("Attempting to create node: {} in {}", incomingNode.getName(), parentNodeRef);
|
||||||
|
|
||||||
|
Map<? extends String, ? extends Serializable> incomingProps = (Map<? extends String, ? extends Serializable>) incomingNode.getProperties();
|
||||||
|
|
||||||
|
String name = incomingNode.getName();
|
||||||
|
if (name == null) {
|
||||||
|
name = incomingProps == null ? null : (String) incomingProps.get(ContentModel.PROP_NAME.toPrefixString(this.namespaceService));
|
||||||
|
if (name == null)
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "A name or 'cm:name' property is required");
|
||||||
|
}
|
||||||
|
this.logger.trace("Using name: {}", name);
|
||||||
|
|
||||||
|
boolean hasContent = incomingNode.getContentData() != null || (incomingNode.getContents() != null && !incomingNode.getContents().isEmpty());
|
||||||
|
QName nodeType = incomingNode.getNodeType() == null
|
||||||
|
? (hasContent ? ContentModel.TYPE_CONTENT : ContentModel.TYPE_FOLDER)
|
||||||
|
: QName.createQName(incomingNode.getNodeType(), this.namespaceService);
|
||||||
|
this.logger.trace("Using node type: {}", nodeType);
|
||||||
|
|
||||||
|
Map<QName, Serializable> props = null;
|
||||||
|
if (incomingProps != null) {
|
||||||
|
props = new HashMap<>(incomingProps.size()+1);
|
||||||
|
for (Entry<? extends String, ? extends Serializable> prop : incomingProps.entrySet()) {
|
||||||
|
QName propName = QName.createQName(prop.getKey(), this.namespaceService);
|
||||||
|
props.put(propName, prop.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (incomingNode.getName() != null)
|
||||||
|
props.put(ContentModel.PROP_NAME, name);
|
||||||
|
|
||||||
|
// audit is disable, so initialize if not set
|
||||||
|
if (!props.containsKey(ContentModel.PROP_CREATED))
|
||||||
|
props.put(ContentModel.PROP_CREATED, new Date());
|
||||||
|
if (!props.containsKey(ContentModel.PROP_MODIFIED))
|
||||||
|
props.put(ContentModel.PROP_MODIFIED, new Date());
|
||||||
|
if (!props.containsKey(ContentModel.PROP_CREATOR))
|
||||||
|
props.put(ContentModel.PROP_CREATOR, AuthenticationUtil.getFullyAuthenticatedUser());
|
||||||
|
if (!props.containsKey(ContentModel.PROP_MODIFIER))
|
||||||
|
props.put(ContentModel.PROP_MODIFIER, AuthenticationUtil.getFullyAuthenticatedUser());
|
||||||
|
}
|
||||||
|
this.logger.trace("Using properties: {}", props.keySet());
|
||||||
|
|
||||||
|
QName assocType = incomingNode.getAssociation() == null
|
||||||
|
? ContentModel.ASSOC_CONTAINS
|
||||||
|
: QName.createQName(incomingNode.getAssociation().getAssocType(), this.namespaceService);
|
||||||
|
QName qname = QName.createQNameWithValidLocalName(NamespaceService.CONTENT_MODEL_1_0_URI, name);
|
||||||
|
this.logger.trace("Using parent association type and name: {} => {}", props.keySet(), qname);
|
||||||
|
|
||||||
|
ChildAssociationRef parentRef = this.nodeService.createNode(parentNodeRef, assocType, qname, nodeType, props);
|
||||||
|
NodeRef nodeRef = parentRef.getChildRef();
|
||||||
|
this.logger.debug("Created node: {}", nodeRef);
|
||||||
|
|
||||||
|
this.addNodeAspects(nodeRef, incomingNode.getAspectNames());
|
||||||
|
this.addNodeAssociations(nodeRef, incomingNode.getTargets());
|
||||||
|
this.addNodeSecondaryAssociations(nodeRef, incomingNode.getSecondaryChildren());
|
||||||
|
this.addNodeContents(nodeRef, this.wrapContents(incomingNode.getContentData(), incomingNode.getContents()), name);
|
||||||
|
|
||||||
|
return nodeRef.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int addNodeAspects(NodeRef nodeRef, List<String> incomingAspects) {
|
||||||
|
int changes = 0;
|
||||||
|
if (incomingAspects == null)
|
||||||
|
return changes;
|
||||||
|
|
||||||
|
this.logger.debug("Adding aspects: {}: {}", nodeRef, incomingAspects);
|
||||||
|
|
||||||
|
for (String aspectName : incomingAspects) {
|
||||||
|
QName aspectQName = QName.createQName(aspectName, this.namespaceService);
|
||||||
|
this.nodeService.addAspect(nodeRef, aspectQName, null);
|
||||||
|
changes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int addNodeAssociations(NodeRef nodeRef, List<AssociationBody> incomingAssocs) {
|
||||||
|
int changes = 0;
|
||||||
|
if (incomingAssocs == null)
|
||||||
|
return changes;
|
||||||
|
|
||||||
|
this.logger.debug("Adding associations: {}: {}", nodeRef, incomingAssocs);
|
||||||
|
|
||||||
|
for (AssociationBody assoc : incomingAssocs) {
|
||||||
|
NodeRef targetNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, assoc.getTargetId());
|
||||||
|
QName assocType = QName.createQName(assoc.getAssocType(), this.namespaceService);
|
||||||
|
this.nodeService.createAssociation(nodeRef, targetNodeRef, assocType);
|
||||||
|
changes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int addNodeSecondaryAssociations(NodeRef nodeRef, List<ChildAssociationBody> incomingAssocs) {
|
||||||
|
int changes = 0;
|
||||||
|
if (incomingAssocs == null)
|
||||||
|
return changes;
|
||||||
|
|
||||||
|
this.logger.debug("Adding child associations: {}: {}", nodeRef, incomingAssocs);
|
||||||
|
|
||||||
|
for (ChildAssociationBody assoc : incomingAssocs) {
|
||||||
|
NodeRef childNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, assoc.getChildId());
|
||||||
|
ChildAssociationRef childParentRef = this.nodeService.getPrimaryParent(childNodeRef);
|
||||||
|
QName assocType = QName.createQName(assoc.getAssocType(), this.namespaceService);
|
||||||
|
this.nodeService.addChild(nodeRef, childNodeRef, assocType, childParentRef.getQName());
|
||||||
|
changes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int addNodeContents(NodeRef nodeRef, List<ContentDataBody> incomingContents, String name) {
|
||||||
|
int changes = 0;
|
||||||
|
if (incomingContents.isEmpty())
|
||||||
|
return changes;
|
||||||
|
|
||||||
|
Set<QName> contentPropsProcessed = new HashSet<>();
|
||||||
|
|
||||||
|
for (ContentDataBody content : incomingContents) {
|
||||||
|
QName contentPropName = content.getPropertyName() == null ?
|
||||||
|
ContentModel.PROP_CONTENT :
|
||||||
|
QName.createQName(content.getPropertyName(), this.namespaceService);
|
||||||
|
if (!contentPropsProcessed.add(contentPropName))
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "The same content property was specified more than once on a node: " + nodeRef);
|
||||||
|
if (content.getContentUrl() == null)
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "In-place node creation requires a content URL: " + nodeRef);
|
||||||
|
|
||||||
|
// this will allow us to get the size without opening a stream
|
||||||
|
// it may also be used to determine the MIME type
|
||||||
|
ContentReader creader = this.contentService.getRawReader(content.getContentUrl());
|
||||||
|
|
||||||
|
if (content.getMimeType() == null) {
|
||||||
|
String mimeType = this.determineMimeType(contentPropName, creader, name);
|
||||||
|
if (mimeType == null)
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "In-place node creation requires a MIME type: " + nodeRef);
|
||||||
|
if (!this.allowOctetStream && mimeType.equals(MediaType.APPLICATION_OCTET_STREAM_VALUE))
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "MIME type '" + mimeType + "' is not allowed by configuration of this module");
|
||||||
|
|
||||||
|
content.setMimeType(mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentData contentData = new ContentData(content.getContentUrl(),
|
||||||
|
content.getMimeType(), creader.getSize(), content.getEncoding(), Locale.getDefault());
|
||||||
|
|
||||||
|
this.nodeService.setProperty(nodeRef, contentPropName, contentData);
|
||||||
|
changes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MediaType validateAndGetContentType(String contentType) {
|
||||||
|
contentType = StringUtils.trimToNull(contentType);
|
||||||
|
this.logger.debug("Received content type: {}", contentType);
|
||||||
|
|
||||||
|
if (contentType == null)
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "A content type is required");
|
||||||
|
|
||||||
|
MediaType incomingMediaType = MediaType.parseMediaType(contentType);
|
||||||
|
for (MediaType jsonMediaType : this.jsonMediaTypes) {
|
||||||
|
if (jsonMediaType.includes(incomingMediaType)) {
|
||||||
|
return MediaType.APPLICATION_JSON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MediaType.MULTIPART_FORM_DATA.equals(incomingMediaType))
|
||||||
|
return incomingMediaType;
|
||||||
|
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "A JSON or multipart content type is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<NodeBodyCreateExt> parseRequest(Content content) throws IOException {
|
||||||
|
this.logger.debug("Received content of size: {}", content.getSize());
|
||||||
|
InputStream istream = content.getInputStream();
|
||||||
|
try {
|
||||||
|
return this.om.readValue(istream, new TypeReference<List<NodeBodyCreateExt>>() {});
|
||||||
|
} finally {
|
||||||
|
istream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.inteligr8.alfresco.bulk;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.extensions.surf.util.Content;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.inteligr8.alfresco.bulk.model.AssociationBody;
|
||||||
|
import com.inteligr8.alfresco.bulk.model.ContentDataBody;
|
||||||
|
import com.inteligr8.alfresco.bulk.model.NodeBodyUpdateExt;
|
||||||
|
import com.inteligr8.alfresco.bulk.model.PermissionsBodyUpdate;
|
||||||
|
|
||||||
|
@Component(value = "webscript.com.inteligr8.alfresco.bulk.updateNodes.put")
|
||||||
|
public class UpdateNodesWebScript extends AbstractNodesWebScript {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException {
|
||||||
|
this.logger.trace("execute()");
|
||||||
|
|
||||||
|
this.validateContentType(req.getContentType());
|
||||||
|
|
||||||
|
List<NodeBodyUpdateExt> nodes = this.parseRequest(req.getContent());
|
||||||
|
this.validateRequest(nodes);
|
||||||
|
|
||||||
|
List<String> updatedNodeIds = this.updateNodes(nodes);
|
||||||
|
|
||||||
|
res.setStatus(HttpStatus.OK.value());
|
||||||
|
res.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
|
res.setContentEncoding("utf-8");
|
||||||
|
this.om.writeValue(res.getWriter(), updatedNodeIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> updateNodes(List<NodeBodyUpdateExt> nodes) {
|
||||||
|
RetryingTransactionCallback<Object> rtcallback = new RetryingTransactionCallback<Object>() {
|
||||||
|
@Override
|
||||||
|
public Object execute() {
|
||||||
|
List<String> updatedNodeIds = new LinkedList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (NodeBodyUpdateExt node : nodes) {
|
||||||
|
if (updateNode(node))
|
||||||
|
updatedNodeIds.add(node.getId());
|
||||||
|
}
|
||||||
|
} catch (WebScriptException wse) {
|
||||||
|
return wse;
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedNodeIds;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object response = this.txService.getRetryingTransactionHelper().doInTransaction(rtcallback, false, false);
|
||||||
|
if (response instanceof WebScriptException)
|
||||||
|
throw (WebScriptException) response;
|
||||||
|
return (List<String>) response;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean updateNode(NodeBodyUpdateExt node) {
|
||||||
|
NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, node.getId());
|
||||||
|
this.logger.debug("Attempting to update node: {}", nodeRef);
|
||||||
|
|
||||||
|
if (!this.nodeService.exists(nodeRef))
|
||||||
|
throw new WebScriptException(HttpStatus.NOT_FOUND.value(), "The node could not be found: {}", node.getId());
|
||||||
|
|
||||||
|
this.updateNodeAspects(nodeRef, node.getAspectNames());
|
||||||
|
this.updateNodeType(nodeRef, node.getNodeType());
|
||||||
|
this.updateNodeProperties(nodeRef, node.getName(), node.getProperties(), node.isRemoveUnspecifiedProperties());
|
||||||
|
this.updateNodeAssociations(nodeRef, node.getTargets());
|
||||||
|
this.updateNodeContents(nodeRef, this.wrapContents(node.getContentData(), node.getContents()));
|
||||||
|
this.updateNodePermissions(nodeRef, node.getPermissions());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int updateNodeAspects(NodeRef nodeRef, List<String> incomingAspects) {
|
||||||
|
int changes = 0;
|
||||||
|
if (incomingAspects == null)
|
||||||
|
return changes;
|
||||||
|
|
||||||
|
Set<QName> currentAspects = this.nodeService.getAspects(nodeRef);
|
||||||
|
this.logger.trace("Reconciling aspects: {}: {} => {}", nodeRef, currentAspects, incomingAspects);
|
||||||
|
|
||||||
|
for (String aspectName : incomingAspects) {
|
||||||
|
QName aspectQName = QName.createQName(aspectName, this.namespaceService);
|
||||||
|
if (!currentAspects.remove(aspectQName)) {
|
||||||
|
this.logger.debug("Adding aspect: {}: {}", nodeRef, aspectQName);
|
||||||
|
this.nodeService.addAspect(nodeRef, aspectQName, null);
|
||||||
|
changes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (QName aspectQName : currentAspects) {
|
||||||
|
this.logger.debug("Removing aspect: {}: {}", nodeRef, aspectQName);
|
||||||
|
this.nodeService.removeAspect(nodeRef, aspectQName);
|
||||||
|
changes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean updateNodeType(NodeRef nodeRef, String incomingNodeTypeName) {
|
||||||
|
if (incomingNodeTypeName == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QName currentNodeType = this.nodeService.getType(nodeRef);
|
||||||
|
this.logger.trace("Reconciling node type: {}: {} => {}", nodeRef, currentNodeType, incomingNodeTypeName);
|
||||||
|
|
||||||
|
QName incomingNodeType = QName.createQName(incomingNodeTypeName, this.namespaceService);
|
||||||
|
if (!currentNodeType.equals(incomingNodeType)) {
|
||||||
|
this.logger.debug("Changing node type: {}: {}", nodeRef, incomingNodeType);
|
||||||
|
this.nodeService.setType(nodeRef, incomingNodeType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateNodeProperties(NodeRef nodeRef, String incomingName, Map<String, String> incomingProps, boolean removeUnspecProps) {
|
||||||
|
if (incomingName == null && incomingProps == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Map<QName, Serializable> props;
|
||||||
|
if (incomingProps == null) {
|
||||||
|
props = new HashMap<>(1);
|
||||||
|
} else {
|
||||||
|
props = new HashMap<>(incomingProps.size()+1);
|
||||||
|
for (Entry<String, String> prop : incomingProps.entrySet()) {
|
||||||
|
QName propName = QName.createQName(prop.getKey(), this.namespaceService);
|
||||||
|
props.put(propName, prop.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (incomingName != null)
|
||||||
|
props.put(ContentModel.PROP_NAME, incomingName);
|
||||||
|
|
||||||
|
this.logger.debug("Changing properties: {}: {}", nodeRef, props.keySet());
|
||||||
|
this.nodeService.addProperties(nodeRef, props);
|
||||||
|
|
||||||
|
if (removeUnspecProps) {
|
||||||
|
Map<QName, Serializable> currentProps = this.nodeService.getProperties(nodeRef);
|
||||||
|
for (QName propName : props.keySet())
|
||||||
|
currentProps.remove(propName);
|
||||||
|
|
||||||
|
for (QName propName : currentProps.keySet()) {
|
||||||
|
this.logger.trace("Removing unspecified property: {}: {}", nodeRef, propName);
|
||||||
|
this.nodeService.removeProperty(nodeRef, propName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int updateNodeAssociations(NodeRef nodeRef, List<AssociationBody> incomingAssocs) {
|
||||||
|
int changes = 0;
|
||||||
|
if (incomingAssocs == null)
|
||||||
|
return changes;
|
||||||
|
|
||||||
|
Set<AssociationRef> currentAssocRefs = new HashSet<>(this.nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL));
|
||||||
|
this.logger.trace("Reconciling associations: {}: {} => {}", nodeRef, currentAssocRefs, incomingAssocs);
|
||||||
|
|
||||||
|
for (AssociationBody assoc : incomingAssocs) {
|
||||||
|
NodeRef targetNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, assoc.getTargetId());
|
||||||
|
QName assocType = QName.createQName(assoc.getAssocType(), this.namespaceService);
|
||||||
|
AssociationRef incomingAssocRef = new AssociationRef(nodeRef, assocType, targetNodeRef);
|
||||||
|
|
||||||
|
if (!currentAssocRefs.remove(incomingAssocRef)) {
|
||||||
|
this.logger.debug("Adding association: {}: {}", nodeRef, incomingAssocRef);
|
||||||
|
this.nodeService.createAssociation(nodeRef, targetNodeRef, assocType);
|
||||||
|
changes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AssociationRef assocRef : currentAssocRefs) {
|
||||||
|
this.logger.debug("Removing association: {}: {}", nodeRef, assocRef);
|
||||||
|
this.nodeService.removeAssociation(assocRef.getSourceRef(), assocRef.getTargetRef(), assocRef.getTypeQName());
|
||||||
|
changes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int updateNodeContents(NodeRef nodeRef, List<ContentDataBody> incomingContents) {
|
||||||
|
int changes = 0;
|
||||||
|
if (incomingContents.isEmpty())
|
||||||
|
return changes;
|
||||||
|
|
||||||
|
Set<QName> contentPropsProcessed = new HashSet<>();
|
||||||
|
|
||||||
|
for (ContentDataBody content : incomingContents) {
|
||||||
|
QName contentPropName = content.getPropertyName() == null ?
|
||||||
|
ContentModel.PROP_CONTENT :
|
||||||
|
QName.createQName(content.getPropertyName(), this.namespaceService);
|
||||||
|
if (!contentPropsProcessed.add(contentPropName))
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "The same content property was specified more than once on a node: " + nodeRef);
|
||||||
|
|
||||||
|
Object contentObj = this.nodeService.getProperty(nodeRef, contentPropName);
|
||||||
|
if (contentObj == null) {
|
||||||
|
throw new WebScriptException(HttpStatus.NOT_IMPLEMENTED.value(), "An update does not yet support new content");
|
||||||
|
} else if (!(contentObj instanceof ContentData)) {
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "A content property does not hold content data: " + contentPropName);
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentData contentData = (ContentData) contentObj;
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
if (content.getMimeType() != null && !content.getMimeType().equals(contentData.getMimetype())) {
|
||||||
|
if (!this.allowOctetStream && content.getMimeType().equals(MediaType.APPLICATION_OCTET_STREAM_VALUE))
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "MIME type '" + content.getMimeType() + "' is not allowed by configuration of this module");
|
||||||
|
|
||||||
|
this.logger.debug("Changing content MIME type: {}: {}", nodeRef, content.getMimeType());
|
||||||
|
contentData = ContentData.setMimetype(contentData, content.getMimeType());
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content.getEncoding() != null && !content.getEncoding().equals(contentData.getEncoding())) {
|
||||||
|
this.logger.debug("Changing content encoding: {}: {}", nodeRef, content.getEncoding());
|
||||||
|
contentData = ContentData.setEncoding(contentData, content.getEncoding());
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
this.nodeService.setProperty(nodeRef, contentPropName, contentData);
|
||||||
|
changes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int updateNodePermissions(NodeRef nodeRef, PermissionsBodyUpdate incomingPermissions) {
|
||||||
|
int changes = 0;
|
||||||
|
if (incomingPermissions == null)
|
||||||
|
return changes;
|
||||||
|
|
||||||
|
throw new WebScriptException(HttpStatus.NOT_IMPLEMENTED.value(), "An update does not yet support permissions");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateContentType(String contentType) {
|
||||||
|
contentType = StringUtils.trimToNull(contentType);
|
||||||
|
this.logger.debug("Received content type: {}", contentType);
|
||||||
|
|
||||||
|
if (contentType == null)
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "A content type is required");
|
||||||
|
|
||||||
|
MediaType incomingMediaType = MediaType.parseMediaType(contentType);
|
||||||
|
for (MediaType jsonMediaType : this.jsonMediaTypes) {
|
||||||
|
if (jsonMediaType.includes(incomingMediaType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new WebScriptException(HttpStatus.BAD_REQUEST.value(), "A JSON content type is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<NodeBodyUpdateExt> parseRequest(Content content) throws IOException {
|
||||||
|
this.logger.debug("Received content of size: {}", content.getSize());
|
||||||
|
InputStream istream = content.getInputStream();
|
||||||
|
try {
|
||||||
|
return this.om.readValue(istream, new TypeReference<List<NodeBodyUpdateExt>>() {});
|
||||||
|
} finally {
|
||||||
|
istream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,73 @@
|
|||||||
|
package com.inteligr8.alfresco.bulk.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class AssociationBody {
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true, value = "")
|
||||||
|
private String targetId = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true, value = "")
|
||||||
|
private String assocType = null;
|
||||||
|
/**
|
||||||
|
* Get targetId
|
||||||
|
* @return targetId
|
||||||
|
**/
|
||||||
|
@JsonProperty("targetId")
|
||||||
|
public String getTargetId() {
|
||||||
|
return targetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetId(String targetId) {
|
||||||
|
this.targetId = targetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssociationBody targetId(String targetId) {
|
||||||
|
this.targetId = targetId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get assocType
|
||||||
|
* @return assocType
|
||||||
|
**/
|
||||||
|
@JsonProperty("assocType")
|
||||||
|
public String getAssocType() {
|
||||||
|
return assocType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssocType(String assocType) {
|
||||||
|
this.assocType = assocType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssociationBody assocType(String assocType) {
|
||||||
|
this.assocType = assocType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("class AssociationBody {\n");
|
||||||
|
|
||||||
|
sb.append(" targetId: ").append(toIndentedString(targetId)).append("\n");
|
||||||
|
sb.append(" assocType: ").append(toIndentedString(assocType)).append("\n");
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given object to string with each line indented by 4 spaces
|
||||||
|
* (except the first line).
|
||||||
|
*/
|
||||||
|
private static String toIndentedString(java.lang.Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return o.toString().replace("\n", "\n ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,73 @@
|
|||||||
|
package com.inteligr8.alfresco.bulk.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class ChildAssociationBody {
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true, value = "")
|
||||||
|
private String childId = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true, value = "")
|
||||||
|
private String assocType = null;
|
||||||
|
/**
|
||||||
|
* Get childId
|
||||||
|
* @return childId
|
||||||
|
**/
|
||||||
|
@JsonProperty("childId")
|
||||||
|
public String getChildId() {
|
||||||
|
return childId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChildId(String childId) {
|
||||||
|
this.childId = childId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChildAssociationBody childId(String childId) {
|
||||||
|
this.childId = childId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get assocType
|
||||||
|
* @return assocType
|
||||||
|
**/
|
||||||
|
@JsonProperty("assocType")
|
||||||
|
public String getAssocType() {
|
||||||
|
return assocType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssocType(String assocType) {
|
||||||
|
this.assocType = assocType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChildAssociationBody assocType(String assocType) {
|
||||||
|
this.assocType = assocType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("class ChildAssociationBody {\n");
|
||||||
|
|
||||||
|
sb.append(" childId: ").append(toIndentedString(childId)).append("\n");
|
||||||
|
sb.append(" assocType: ").append(toIndentedString(assocType)).append("\n");
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given object to string with each line indented by 4 spaces
|
||||||
|
* (except the first line).
|
||||||
|
*/
|
||||||
|
private static String toIndentedString(java.lang.Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return o.toString().replace("\n", "\n ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,73 @@
|
|||||||
|
package com.inteligr8.alfresco.bulk.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class ContentDataBody {
|
||||||
|
|
||||||
|
@JsonProperty(defaultValue = "cm:content")
|
||||||
|
private String propertyName;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private String mimeType;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private String encoding;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private String contentUrl;
|
||||||
|
|
||||||
|
public String getPropertyName() {
|
||||||
|
return propertyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyName(String propertyName) {
|
||||||
|
this.propertyName = propertyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentDataBody propertyName(String propertyName) {
|
||||||
|
this.propertyName = propertyName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeType() {
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMimeType(String mimeType) {
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentDataBody mimeType(String mimeType) {
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEncoding() {
|
||||||
|
return encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEncoding(String encoding) {
|
||||||
|
this.encoding = encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentDataBody encoding(String encoding) {
|
||||||
|
this.encoding = encoding;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentUrl() {
|
||||||
|
return contentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentUrl(String contentUrl) {
|
||||||
|
this.contentUrl = contentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentDataBody contentUrl(String contentUrl) {
|
||||||
|
this.contentUrl = contentUrl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,230 @@
|
|||||||
|
package com.inteligr8.alfresco.bulk.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class NodeBodyCreate {
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true, value = "The name must not contain spaces or the following special characters: * \" < > \\ / ? : and |. The character . must not be used at the end of the name. ")
|
||||||
|
/**
|
||||||
|
* The name must not contain spaces or the following special characters: * \" < > \\ / ? : and |. The character . must not be used at the end of the name.
|
||||||
|
**/
|
||||||
|
private String name = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true, value = "")
|
||||||
|
private String nodeType = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private List<String> aspectNames = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private Map<String, String> properties = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private String relativePath = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private NodeBodyCreateAssociation association = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private List<ChildAssociationBody> secondaryChildren = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private List<AssociationBody> targets = null;
|
||||||
|
/**
|
||||||
|
* The name must not contain spaces or the following special characters: * \" < > \\ / ? : and |. The character . must not be used at the end of the name.
|
||||||
|
* @return name
|
||||||
|
**/
|
||||||
|
@JsonProperty("name")
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get nodeType
|
||||||
|
* @return nodeType
|
||||||
|
**/
|
||||||
|
@JsonProperty("nodeType")
|
||||||
|
public String getNodeType() {
|
||||||
|
return nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeType(String nodeType) {
|
||||||
|
this.nodeType = nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate nodeType(String nodeType) {
|
||||||
|
this.nodeType = nodeType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get aspectNames
|
||||||
|
* @return aspectNames
|
||||||
|
**/
|
||||||
|
@JsonProperty("aspectNames")
|
||||||
|
public List<String> getAspectNames() {
|
||||||
|
return aspectNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAspectNames(List<String> aspectNames) {
|
||||||
|
this.aspectNames = aspectNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate aspectNames(List<String> aspectNames) {
|
||||||
|
this.aspectNames = aspectNames;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate addAspectNamesItem(String aspectNamesItem) {
|
||||||
|
this.aspectNames.add(aspectNamesItem);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get properties
|
||||||
|
* @return properties
|
||||||
|
**/
|
||||||
|
@JsonProperty("properties")
|
||||||
|
public Map<String, String> getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperties(Map<String, String> properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate properties(Map<String, String> properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate putPropertiesItem(String key, String propertiesItem) {
|
||||||
|
this.properties.put(key, propertiesItem);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get relativePath
|
||||||
|
* @return relativePath
|
||||||
|
**/
|
||||||
|
@JsonProperty("relativePath")
|
||||||
|
public String getRelativePath() {
|
||||||
|
return relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRelativePath(String relativePath) {
|
||||||
|
this.relativePath = relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate relativePath(String relativePath) {
|
||||||
|
this.relativePath = relativePath;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get association
|
||||||
|
* @return association
|
||||||
|
**/
|
||||||
|
@JsonProperty("association")
|
||||||
|
public NodeBodyCreateAssociation getAssociation() {
|
||||||
|
return association;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssociation(NodeBodyCreateAssociation association) {
|
||||||
|
this.association = association;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate association(NodeBodyCreateAssociation association) {
|
||||||
|
this.association = association;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get secondaryChildren
|
||||||
|
* @return secondaryChildren
|
||||||
|
**/
|
||||||
|
@JsonProperty("secondaryChildren")
|
||||||
|
public List<ChildAssociationBody> getSecondaryChildren() {
|
||||||
|
return secondaryChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecondaryChildren(List<ChildAssociationBody> secondaryChildren) {
|
||||||
|
this.secondaryChildren = secondaryChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate secondaryChildren(List<ChildAssociationBody> secondaryChildren) {
|
||||||
|
this.secondaryChildren = secondaryChildren;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate addSecondaryChildrenItem(ChildAssociationBody secondaryChildrenItem) {
|
||||||
|
this.secondaryChildren.add(secondaryChildrenItem);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get targets
|
||||||
|
* @return targets
|
||||||
|
**/
|
||||||
|
@JsonProperty("targets")
|
||||||
|
public List<AssociationBody> getTargets() {
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargets(List<AssociationBody> targets) {
|
||||||
|
this.targets = targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate targets(List<AssociationBody> targets) {
|
||||||
|
this.targets = targets;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreate addTargetsItem(AssociationBody targetsItem) {
|
||||||
|
this.targets.add(targetsItem);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("class NodeBodyCreate {\n");
|
||||||
|
|
||||||
|
sb.append(" name: ").append(toIndentedString(name)).append("\n");
|
||||||
|
sb.append(" nodeType: ").append(toIndentedString(nodeType)).append("\n");
|
||||||
|
sb.append(" aspectNames: ").append(toIndentedString(aspectNames)).append("\n");
|
||||||
|
sb.append(" properties: ").append(toIndentedString(properties)).append("\n");
|
||||||
|
sb.append(" relativePath: ").append(toIndentedString(relativePath)).append("\n");
|
||||||
|
sb.append(" association: ").append(toIndentedString(association)).append("\n");
|
||||||
|
sb.append(" secondaryChildren: ").append(toIndentedString(secondaryChildren)).append("\n");
|
||||||
|
sb.append(" targets: ").append(toIndentedString(targets)).append("\n");
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given object to string with each line indented by 4 spaces
|
||||||
|
* (except the first line).
|
||||||
|
*/
|
||||||
|
private static String toIndentedString(java.lang.Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return o.toString().replace("\n", "\n ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,51 @@
|
|||||||
|
package com.inteligr8.alfresco.bulk.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class NodeBodyCreateAssociation {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private String assocType = null;
|
||||||
|
/**
|
||||||
|
* Get assocType
|
||||||
|
* @return assocType
|
||||||
|
**/
|
||||||
|
@JsonProperty("assocType")
|
||||||
|
public String getAssocType() {
|
||||||
|
return assocType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssocType(String assocType) {
|
||||||
|
this.assocType = assocType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreateAssociation assocType(String assocType) {
|
||||||
|
this.assocType = assocType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("class NodeBodyCreateAssociation {\n");
|
||||||
|
|
||||||
|
sb.append(" assocType: ").append(toIndentedString(assocType)).append("\n");
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given object to string with each line indented by 4 spaces
|
||||||
|
* (except the first line).
|
||||||
|
*/
|
||||||
|
private static String toIndentedString(java.lang.Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return o.toString().replace("\n", "\n ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,49 @@
|
|||||||
|
package com.inteligr8.alfresco.bulk.model;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
@NotThreadSafe
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class NodeBodyCreateExt extends NodeBodyCreate {
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private ContentDataBody contentData;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private List<ContentDataBody> contents;
|
||||||
|
|
||||||
|
public ContentDataBody getContentData() {
|
||||||
|
return contentData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentData(ContentDataBody contentData) {
|
||||||
|
this.contentData = contentData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreateExt contentData(ContentDataBody contentData) {
|
||||||
|
this.contentData = contentData;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ContentDataBody> getContents() {
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContents(List<ContentDataBody> contents) {
|
||||||
|
this.contents = contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyCreateExt addContent(ContentDataBody contentData) {
|
||||||
|
if (this.contents == null)
|
||||||
|
this.contents = new LinkedList<>();
|
||||||
|
this.contents.add(contentData);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,154 @@
|
|||||||
|
package com.inteligr8.alfresco.bulk.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class NodeBodyUpdate {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "The name must not contain spaces or the following special characters: * \" < > \\ / ? : and |. The character . must not be used at the end of the name. ")
|
||||||
|
/**
|
||||||
|
* The name must not contain spaces or the following special characters: * \" < > \\ / ? : and |. The character . must not be used at the end of the name.
|
||||||
|
**/
|
||||||
|
private String name = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private String nodeType = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private List<String> aspectNames = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private Map<String, String> properties = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private PermissionsBodyUpdate permissions = null;
|
||||||
|
/**
|
||||||
|
* The name must not contain spaces or the following special characters: * \" < > \\ / ? : and |. The character . must not be used at the end of the name.
|
||||||
|
* @return name
|
||||||
|
**/
|
||||||
|
@JsonProperty("name")
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdate name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get nodeType
|
||||||
|
* @return nodeType
|
||||||
|
**/
|
||||||
|
@JsonProperty("nodeType")
|
||||||
|
public String getNodeType() {
|
||||||
|
return nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeType(String nodeType) {
|
||||||
|
this.nodeType = nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdate nodeType(String nodeType) {
|
||||||
|
this.nodeType = nodeType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get aspectNames
|
||||||
|
* @return aspectNames
|
||||||
|
**/
|
||||||
|
@JsonProperty("aspectNames")
|
||||||
|
public List<String> getAspectNames() {
|
||||||
|
return aspectNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAspectNames(List<String> aspectNames) {
|
||||||
|
this.aspectNames = aspectNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdate aspectNames(List<String> aspectNames) {
|
||||||
|
this.aspectNames = aspectNames;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdate addAspectNamesItem(String aspectNamesItem) {
|
||||||
|
this.aspectNames.add(aspectNamesItem);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get properties
|
||||||
|
* @return properties
|
||||||
|
**/
|
||||||
|
@JsonProperty("properties")
|
||||||
|
public Map<String, String> getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperties(Map<String, String> properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdate properties(Map<String, String> properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdate putPropertiesItem(String key, String propertiesItem) {
|
||||||
|
this.properties.put(key, propertiesItem);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get permissions
|
||||||
|
* @return permissions
|
||||||
|
**/
|
||||||
|
@JsonProperty("permissions")
|
||||||
|
public PermissionsBodyUpdate getPermissions() {
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermissions(PermissionsBodyUpdate permissions) {
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdate permissions(PermissionsBodyUpdate permissions) {
|
||||||
|
this.permissions = permissions;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("class NodeBodyUpdate {\n");
|
||||||
|
|
||||||
|
sb.append(" name: ").append(toIndentedString(name)).append("\n");
|
||||||
|
sb.append(" nodeType: ").append(toIndentedString(nodeType)).append("\n");
|
||||||
|
sb.append(" aspectNames: ").append(toIndentedString(aspectNames)).append("\n");
|
||||||
|
sb.append(" properties: ").append(toIndentedString(properties)).append("\n");
|
||||||
|
sb.append(" permissions: ").append(toIndentedString(permissions)).append("\n");
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given object to string with each line indented by 4 spaces
|
||||||
|
* (except the first line).
|
||||||
|
*/
|
||||||
|
private static String toIndentedString(java.lang.Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return o.toString().replace("\n", "\n ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,99 @@
|
|||||||
|
package com.inteligr8.alfresco.bulk.model;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
@NotThreadSafe
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class NodeBodyUpdateExt extends NodeBodyUpdate {
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private ContentDataBody contentData;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private List<ContentDataBody> contents;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private List<AssociationBody> targets;
|
||||||
|
|
||||||
|
@JsonProperty(defaultValue = "false")
|
||||||
|
private boolean removeUnspecifiedProperties;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdateExt id(String id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentDataBody getContentData() {
|
||||||
|
return contentData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentData(ContentDataBody contentData) {
|
||||||
|
this.contentData = contentData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdateExt contentData(ContentDataBody contentData) {
|
||||||
|
this.contentData = contentData;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ContentDataBody> getContents() {
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContents(List<ContentDataBody> contents) {
|
||||||
|
this.contents = contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdateExt addContent(ContentDataBody contentData) {
|
||||||
|
if (this.contents == null)
|
||||||
|
this.contents = new LinkedList<>();
|
||||||
|
this.contents.add(contentData);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AssociationBody> getTargets() {
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargets(List<AssociationBody> targets) {
|
||||||
|
this.targets = targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdateExt addTarget(AssociationBody target) {
|
||||||
|
if (this.targets == null)
|
||||||
|
this.targets = new LinkedList<>();
|
||||||
|
this.targets.add(target);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRemoveUnspecifiedProperties() {
|
||||||
|
return removeUnspecifiedProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemoveUnspecifiedProperties(boolean removeUnspecifiedProperties) {
|
||||||
|
this.removeUnspecifiedProperties = removeUnspecifiedProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeBodyUpdateExt removeUnspecifiedProperties(boolean removeUnspecifiedProperties) {
|
||||||
|
this.removeUnspecifiedProperties = removeUnspecifiedProperties;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,134 @@
|
|||||||
|
package com.inteligr8.alfresco.bulk.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import javax.xml.bind.annotation.XmlEnum;
|
||||||
|
import javax.xml.bind.annotation.XmlEnumValue;
|
||||||
|
import javax.xml.bind.annotation.XmlType;
|
||||||
|
|
||||||
|
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class PermissionElement {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private String authorityId = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private String name = null;
|
||||||
|
|
||||||
|
|
||||||
|
@XmlType(name="AccessStatusEnum")
|
||||||
|
@XmlEnum(String.class)
|
||||||
|
public enum AccessStatusEnum {
|
||||||
|
|
||||||
|
@XmlEnumValue("ALLOWED") ALLOWED(String.valueOf("ALLOWED")), @XmlEnumValue("DENIED") DENIED(String.valueOf("DENIED"));
|
||||||
|
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
AccessStatusEnum (String v) {
|
||||||
|
value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AccessStatusEnum fromValue(String v) {
|
||||||
|
for (AccessStatusEnum b : AccessStatusEnum.values()) {
|
||||||
|
if (String.valueOf(b.value).equals(v)) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private AccessStatusEnum accessStatus = AccessStatusEnum.ALLOWED;
|
||||||
|
/**
|
||||||
|
* Get authorityId
|
||||||
|
* @return authorityId
|
||||||
|
**/
|
||||||
|
@JsonProperty("authorityId")
|
||||||
|
public String getAuthorityId() {
|
||||||
|
return authorityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthorityId(String authorityId) {
|
||||||
|
this.authorityId = authorityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionElement authorityId(String authorityId) {
|
||||||
|
this.authorityId = authorityId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get name
|
||||||
|
* @return name
|
||||||
|
**/
|
||||||
|
@JsonProperty("name")
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionElement name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get accessStatus
|
||||||
|
* @return accessStatus
|
||||||
|
**/
|
||||||
|
@JsonProperty("accessStatus")
|
||||||
|
public String getAccessStatus() {
|
||||||
|
if (accessStatus == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return accessStatus.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccessStatus(AccessStatusEnum accessStatus) {
|
||||||
|
this.accessStatus = accessStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionElement accessStatus(AccessStatusEnum accessStatus) {
|
||||||
|
this.accessStatus = accessStatus;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("class PermissionElement {\n");
|
||||||
|
|
||||||
|
sb.append(" authorityId: ").append(toIndentedString(authorityId)).append("\n");
|
||||||
|
sb.append(" name: ").append(toIndentedString(name)).append("\n");
|
||||||
|
sb.append(" accessStatus: ").append(toIndentedString(accessStatus)).append("\n");
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given object to string with each line indented by 4 spaces
|
||||||
|
* (except the first line).
|
||||||
|
*/
|
||||||
|
private static String toIndentedString(java.lang.Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return o.toString().replace("\n", "\n ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,79 @@
|
|||||||
|
package com.inteligr8.alfresco.bulk.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class PermissionsBodyUpdate {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private Boolean isInheritanceEnabled = null;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private List<PermissionElement> locallySet = null;
|
||||||
|
/**
|
||||||
|
* Get isInheritanceEnabled
|
||||||
|
* @return isInheritanceEnabled
|
||||||
|
**/
|
||||||
|
@JsonProperty("isInheritanceEnabled")
|
||||||
|
public Boolean isIsInheritanceEnabled() {
|
||||||
|
return isInheritanceEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsInheritanceEnabled(Boolean isInheritanceEnabled) {
|
||||||
|
this.isInheritanceEnabled = isInheritanceEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionsBodyUpdate isInheritanceEnabled(Boolean isInheritanceEnabled) {
|
||||||
|
this.isInheritanceEnabled = isInheritanceEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get locallySet
|
||||||
|
* @return locallySet
|
||||||
|
**/
|
||||||
|
@JsonProperty("locallySet")
|
||||||
|
public List<PermissionElement> getLocallySet() {
|
||||||
|
return locallySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocallySet(List<PermissionElement> locallySet) {
|
||||||
|
this.locallySet = locallySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionsBodyUpdate locallySet(List<PermissionElement> locallySet) {
|
||||||
|
this.locallySet = locallySet;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionsBodyUpdate addLocallySetItem(PermissionElement locallySetItem) {
|
||||||
|
this.locallySet.add(locallySetItem);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("class PermissionsBodyUpdate {\n");
|
||||||
|
|
||||||
|
sb.append(" isInheritanceEnabled: ").append(toIndentedString(isInheritanceEnabled)).append("\n");
|
||||||
|
sb.append(" locallySet: ").append(toIndentedString(locallySet)).append("\n");
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given object to string with each line indented by 4 spaces
|
||||||
|
* (except the first line).
|
||||||
|
*/
|
||||||
|
private static String toIndentedString(java.lang.Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return o.toString().replace("\n", "\n ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,18 @@
|
|||||||
|
<!-- Documentation: https://docs.alfresco.com/content-services/6.2/develop/reference/web-scripts-ref -->
|
||||||
|
<webscript>
|
||||||
|
<shortname>Create Nodes</shortname>
|
||||||
|
<description><![CDATA[
|
||||||
|
<p>This REST API creates a set of nodes in a single transaction.
|
||||||
|
It extends the NodeBodyCreate model of the ACS Public REST API for maximum reusability.
|
||||||
|
The extension allows for creation of associations and in-place content specification.</p>
|
||||||
|
<p>As with any bulk transaction, if this operation fails on any one node, all changes will rollback.</p>
|
||||||
|
<p>TODO</p>
|
||||||
|
]]></description>
|
||||||
|
|
||||||
|
<url>/inteligr8/bulk/node/{folderNodeId}/nodes</url>
|
||||||
|
<url>/inteligr8/bulk/nodes/{folderNodeId}</url>
|
||||||
|
<format default="json"></format>
|
||||||
|
|
||||||
|
<authentication>user</authentication>
|
||||||
|
<family>Inteligr8 Bulk</family>
|
||||||
|
</webscript>
|
@@ -0,0 +1,18 @@
|
|||||||
|
<!-- Documentation: https://docs.alfresco.com/content-services/6.2/develop/reference/web-scripts-ref -->
|
||||||
|
<webscript>
|
||||||
|
<shortname>Update Nodes</shortname>
|
||||||
|
<description><![CDATA[
|
||||||
|
<p>This REST API updates a set of nodes in a single transaction.
|
||||||
|
It extends the NodeBodyUpdate model of the ACS Public REST API for maximum reusability.
|
||||||
|
The extension allows for updates to associations and content meta-data.
|
||||||
|
It also supports the update of node types, regardless of whether the update follows the specialization hierarchy.</p>
|
||||||
|
<p>As with any bulk transaction, if this operation fails on any one node, all changes will rollback.</p>
|
||||||
|
<p>TODO</p>
|
||||||
|
]]></description>
|
||||||
|
|
||||||
|
<url>/inteligr8/bulk/nodes</url>
|
||||||
|
<format default="json"></format>
|
||||||
|
|
||||||
|
<authentication>user</authentication>
|
||||||
|
<family>Inteligr8 Bulk</family>
|
||||||
|
</webscript>
|
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
# Enable to use Tika to synchronously detect the MIME type when MIME type is not provided
|
||||||
|
# This opens a stream to the binary file and reads at least part of it to help determine the MIME type
|
||||||
|
# This will slow down imports when the filename extension may be enough to determine the MIME type
|
||||||
|
inteligr8.bulk.enableTika=false
|
||||||
|
|
||||||
|
# Enable to allow content to be undetermined, which means the MIME type would be 'application/octet-stream'.
|
||||||
|
inteligr8.bulk.allowOctetStream=false
|
@@ -0,0 +1 @@
|
|||||||
|
log4j.logger.com.inteligr8.alfresco.bulk=info
|
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
|
||||||
|
<!-- Use this file for beans to be loaded in whatever order Alfresco/Spring decides -->
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||||
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||||
|
|
||||||
|
<!-- Enable Spring annotation scanning for classes in package -->
|
||||||
|
<context:component-scan base-package="com.inteligr8.alfresco.bulk" />
|
||||||
|
|
||||||
|
</beans>
|
@@ -0,0 +1,4 @@
|
|||||||
|
module.id=${project.artifactId}
|
||||||
|
module.title=${project.name}
|
||||||
|
module.description=${project.description}
|
||||||
|
module.version=${project.version}
|
@@ -0,0 +1,8 @@
|
|||||||
|
# Module debugging
|
||||||
|
log4j.logger.com.inteligr8.alfresco.bulk=trace
|
||||||
|
|
||||||
|
# WebScript debugging
|
||||||
|
log4j.logger.org.springframework.extensions.webscripts.ScriptLogger=debug
|
||||||
|
|
||||||
|
# non-WebScript JavaScript execution debugging
|
||||||
|
log4j.logger.org.alfresco.repo.jscript.ScriptLogger=debug
|
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<beans>
|
||||||
|
<!--
|
||||||
|
To support hot reloading of server side Javascript files in Share, we have to turn on development mode.
|
||||||
|
This setting will tell the Rhinoscript Processor not to compile and cache the JS files.
|
||||||
|
Cool, we can now change server side JS files and have the changes picked up,
|
||||||
|
without having to restart or refresh web scripts.
|
||||||
|
|
||||||
|
But… Due to a known bug in the Surf framework (ALF-9970) this will break the admin consoles in Share.
|
||||||
|
|
||||||
|
Override this bean and disable javascript compilation so that webscripts can be hot reloaded.
|
||||||
|
We have changed the 'compile' property from true to false.
|
||||||
|
-->
|
||||||
|
<bean id="javaScriptProcessor" class="org.alfresco.repo.jscript.RhinoScriptProcessor" init-method="register">
|
||||||
|
<property name="name">
|
||||||
|
<value>javascript</value>
|
||||||
|
</property>
|
||||||
|
<property name="extension">
|
||||||
|
<value>js</value>
|
||||||
|
</property>
|
||||||
|
<!-- Do not "compile javascript and cache compiled scripts" -->
|
||||||
|
<property name="compile">
|
||||||
|
<value>false</value>
|
||||||
|
</property>
|
||||||
|
<!-- allow sharing of sealed scopes for performance -->
|
||||||
|
<!-- disable to give each script it's own new scope which can be extended -->
|
||||||
|
<property name="shareSealedScopes">
|
||||||
|
<value>true</value>
|
||||||
|
</property>
|
||||||
|
<property name="scriptService">
|
||||||
|
<ref bean="scriptService"/>
|
||||||
|
</property>
|
||||||
|
<!-- Creates ScriptNodes which require the ServiceRegistry -->
|
||||||
|
<property name="serviceRegistry">
|
||||||
|
<ref bean="ServiceRegistry"/>
|
||||||
|
</property>
|
||||||
|
<property name="storeUrl">
|
||||||
|
<value>${spaces.store}</value>
|
||||||
|
</property>
|
||||||
|
<property name="storePath">
|
||||||
|
<value>${spaces.company_home.childname}</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
|
</beans>
|
Reference in New Issue
Block a user