diff --git a/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java b/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java index b6f7456d07..6c0d059f00 100644 --- a/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java +++ b/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java @@ -173,30 +173,28 @@ public abstract class AbstractNodeImporter implements NodeImporter return(result); } - protected final int importImportableItemFile(NodeRef nodeRef, ImportableItem importableItem, MetadataLoader.Metadata metadata) + protected final int importImportableItemFile(NodeRef nodeRef, ImportableItem importableItem, MetadataLoader.Metadata metadata, NodeState nodeState) { int result = 0; if (importableItem.hasVersionEntries()) { - // If cm:versionable isn't listed as one of the aspects for this node, add it - cm:versionable is required for nodes that have versions - if (!metadata.getAspects().contains(ContentModel.ASPECT_VERSIONABLE)) - { - if (logger.isWarnEnabled()) logger.warn("Metadata for file '" + getFileName(importableItem.getHeadRevision().getContentFile()) + "' was missing the cm:versionable aspect, yet it has " + importableItem.getVersionEntries().size() + " versions. Adding cm:versionable."); - metadata.addAspect(ContentModel.ASPECT_VERSIONABLE); - } - - result = importContentVersions(nodeRef, importableItem); + result = importContentVersions(nodeRef, importableItem, nodeState); } else { + if (nodeState == NodeState.REPLACED) + { + nodeService.removeAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE); + } + importContentAndMetadata(nodeRef, importableItem.getHeadRevision(), metadata); } return(result); } - protected final int importContentVersions(NodeRef nodeRef, ImportableItem importableItem) + protected final int importContentVersions(NodeRef nodeRef, ImportableItem importableItem, NodeState nodeState) { int result = 0; Map versionProperties = new HashMap(); @@ -206,6 +204,11 @@ public abstract class AbstractNodeImporter implements NodeImporter //versionProperties.put(ContentModel.PROP_VERSION_LABEL.toPrefixString(), String.valueOf(versionEntry.getVersion())); versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR); // Load every version as a major version for now - see http://code.google.com/p/alfresco-bulk-filesystem-import/issues/detail?id=84 + if(nodeState == NodeState.REPLACED) + { + versionService.deleteVersionHistory(nodeRef); + } + for (final ImportableItem.VersionedContentAndMetadata versionEntry : importableItem.getVersionEntries()) { MetadataLoader.Metadata metadata = loadMetadata(versionEntry); @@ -220,6 +223,13 @@ public abstract class AbstractNodeImporter implements NodeImporter if (logger.isDebugEnabled()) logger.debug("Creating head revision of node " + nodeRef.toString()); ImportableItem.ContentAndMetadata contentAndMetadata = importableItem.getHeadRevision(); MetadataLoader.Metadata metadata = loadMetadata(contentAndMetadata); + + // If cm:versionable isn't listed as one of the aspects for this node, add it - cm:versionable is required for nodes that have versions + if (!metadata.getAspects().contains(ContentModel.ASPECT_VERSIONABLE)) + { + if (logger.isWarnEnabled()) logger.warn("Metadata for file '" + getFileName(importableItem.getHeadRevision().getContentFile()) + "' was missing the cm:versionable aspect, yet it has " + importableItem.getVersionEntries().size() + " versions. Adding cm:versionable."); + metadata.addAspect(ContentModel.ASPECT_VERSIONABLE); + } importContentAndMetadata(nodeRef, importableItem.getHeadRevision(), metadata); versionService.createVersion(nodeRef, versionProperties); @@ -248,7 +258,7 @@ public abstract class AbstractNodeImporter implements NodeImporter nodeRef = fileFolderService.searchSimple(target, nodeName); - // If we didn't find an existing item, create a new node in the repo. + // If we didn't find an existing item, create a new node in the repo. if (nodeRef == null) { // But only if the content file exists - we don't create new nodes based on metadata-only importableItems diff --git a/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java b/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java index 94e2ac0cbf..ac99fae1a0 100644 --- a/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java +++ b/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java @@ -125,7 +125,7 @@ public class StreamingNodeImporterFactory extends AbstractNodeImporterFactory } else { - numVersionProperties = importImportableItemFile(result, importableItem, metadata); + numVersionProperties = importImportableItemFile(result, importableItem, metadata, nodeState); } importStatus.incrementNodesWritten(importableItem, isDirectory, nodeState, metadata.getProperties().size() + 4, numVersionProperties); diff --git a/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java b/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java index 4bf28cbab7..38393c8efa 100644 --- a/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java +++ b/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java @@ -375,4 +375,215 @@ public class BulkImportTest extends AbstractBulkImportTests assertEquals("This is version 1 of fileWithVersions.txt.", contentReader.getContentString()); } + /** + * MNT-9067: bulkimport "Replace existing files" option does not work when versioning is enabled + * + * @throws Throwable + */ + @Test + public void testMNT9067() throws Throwable + { + txn = transactionService.getUserTransaction(); + txn.begin(); + + NodeRef folderNode = topLevelFolder.getNodeRef(); + + //initial import + try + { + NodeImporter nodeImporter = streamingNodeImporterFactory.getNodeImporter(ResourceUtils.getFile("classpath:bulkimport3/initial")); + BulkImportParameters bulkImportParameters = new BulkImportParameters(); + bulkImportParameters.setTarget(folderNode); + bulkImportParameters.setReplaceExisting(true); + bulkImportParameters.setDisableRulesService(true); + bulkImportParameters.setBatchSize(40); + bulkImporter.bulkImport(bulkImportParameters, nodeImporter); + } + catch(Throwable e) + { + fail(e.getMessage()); + } + + txn.commit(); + txn = transactionService.getUserTransaction(); + txn.begin(); + + System.out.println(bulkImporter.getStatus()); + assertEquals(false, bulkImporter.getStatus().inProgress()); + + List files = getFiles(folderNode, null); + assertEquals("One file is expected to be imported:", 1, files.size()); + FileInfo file = files.get(0); + assertEquals("File name is not equal:", "fileWithVersions.txt", file.getName()); + + NodeRef fileNodeRef = file.getNodeRef(); + assertTrue("Imported file should be versioned:", versionService.isVersioned(fileNodeRef)); + + VersionHistory history = versionService.getVersionHistory(fileNodeRef); + assertEquals("Imported file should have 4 versions:", 4, history.getAllVersions().size()); + + + //replace versioned file with new versioned file + try + { + NodeImporter nodeImporter = streamingNodeImporterFactory.getNodeImporter(ResourceUtils.getFile("classpath:bulkimport3/replace_with_versioned")); + BulkImportParameters bulkImportParameters = new BulkImportParameters(); + bulkImportParameters.setTarget(folderNode); + bulkImportParameters.setReplaceExisting(true); + bulkImportParameters.setDisableRulesService(true); + bulkImportParameters.setBatchSize(40); + bulkImporter.bulkImport(bulkImportParameters, nodeImporter); + } + catch(Throwable e) + { + fail(e.getMessage()); + } + + System.out.println(bulkImporter.getStatus()); + assertEquals(false, bulkImporter.getStatus().inProgress()); + + txn.commit(); + txn = transactionService.getUserTransaction(); + txn.begin(); + + files = getFiles(folderNode, null); + assertEquals("One file is expected to be imported:", 1, files.size()); + file = files.get(0); + assertEquals("File name is not equal:", "fileWithVersions.txt", file.getName()); + + fileNodeRef = file.getNodeRef(); + assertTrue("Imported file should be versioned:", versionService.isVersioned(fileNodeRef)); + + history = versionService.getVersionHistory(fileNodeRef); + assertNotNull(history); + + + assertEquals("Imported file should have 5 versions:", 5, history.getAllVersions().size()); + + Version[] versions = history.getAllVersions().toArray(new Version[5]); + + //compare the content of each version + ContentReader contentReader; + contentReader = this.contentService.getReader(versions[0].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals("This is the final version of replaced on import fileWithVersions.txt.", contentReader.getContentString()); + + contentReader = this.contentService.getReader(versions[1].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals("This is version 4 of replaced on import fileWithVersions.txt.", contentReader.getContentString()); + + contentReader = this.contentService.getReader(versions[2].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals("This is version 3 of replaced on import fileWithVersions.txt.", contentReader.getContentString()); + + contentReader = this.contentService.getReader(versions[3].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals("This is version 2 of replaced on import fileWithVersions.txt.", contentReader.getContentString()); + + contentReader = this.contentService.getReader(versions[4].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals("This is version 1 of replaced on import fileWithVersions.txt.", contentReader.getContentString()); + + txn.commit(); + txn = transactionService.getUserTransaction(); + txn.begin(); + + //import non versioned file + try + { + NodeImporter nodeImporter = streamingNodeImporterFactory.getNodeImporter(ResourceUtils.getFile("classpath:bulkimport3/replace_with_non_versioned")); + BulkImportParameters bulkImportParameters = new BulkImportParameters(); + bulkImportParameters.setTarget(folderNode); + bulkImportParameters.setReplaceExisting(true); + bulkImportParameters.setDisableRulesService(true); + bulkImportParameters.setBatchSize(40); + bulkImporter.bulkImport(bulkImportParameters, nodeImporter); + } + catch(Throwable e) + { + fail(e.getMessage()); + } + + txn.commit(); + txn = transactionService.getUserTransaction(); + txn.begin(); + + System.out.println(bulkImporter.getStatus()); + assertEquals(false, bulkImporter.getStatus().inProgress()); + + files = getFiles(folderNode, null); + assertEquals("One file is expected to be imported:", 1, files.size()); + file = files.get(0); + assertEquals("File name is not equal:", "fileWithVersions.txt", file.getName()); + + fileNodeRef = file.getNodeRef(); + assertTrue("Imported file should be non versioned:", !versionService.isVersioned(fileNodeRef)); + + contentReader = this.contentService.getReader(fileNodeRef, ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals("This is non versioned fileWithVersions.txt.", contentReader.getContentString()); + + txn.commit(); + txn = transactionService.getUserTransaction(); + txn.begin(); + + //use initial file again to replace non versioned file + try + { + NodeImporter nodeImporter = streamingNodeImporterFactory.getNodeImporter(ResourceUtils.getFile("classpath:bulkimport3/initial")); + BulkImportParameters bulkImportParameters = new BulkImportParameters(); + bulkImportParameters.setTarget(folderNode); + bulkImportParameters.setReplaceExisting(true); + bulkImportParameters.setDisableRulesService(true); + bulkImportParameters.setBatchSize(40); + bulkImporter.bulkImport(bulkImportParameters, nodeImporter); + } + catch(Throwable e) + { + fail(e.getMessage()); + } + + txn.commit(); + txn = transactionService.getUserTransaction(); + txn.begin(); + + System.out.println(bulkImporter.getStatus()); + assertEquals(false, bulkImporter.getStatus().inProgress()); + + files = getFiles(folderNode, null); + assertEquals("One file is expected to be imported:", 1, files.size()); + file = files.get(0); + assertEquals("File name is not equal:", "fileWithVersions.txt", file.getName()); + + fileNodeRef = file.getNodeRef(); + assertTrue("Imported file should be versioned:", versionService.isVersioned(fileNodeRef)); + + history = versionService.getVersionHistory(fileNodeRef); + assertNotNull(history); + + + assertEquals("Imported file should have 4 versions:", 4, history.getAllVersions().size()); + + versions = history.getAllVersions().toArray(new Version[4]); + + //compare the content of each version + + contentReader = this.contentService.getReader(versions[0].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals("This is the final version of fileWithVersions.txt.", contentReader.getContentString()); + + contentReader = this.contentService.getReader(versions[1].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals("This is version 3 of fileWithVersions.txt.", contentReader.getContentString()); + + contentReader = this.contentService.getReader(versions[2].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals("This is version 2 of fileWithVersions.txt.", contentReader.getContentString()); + + contentReader = this.contentService.getReader(versions[3].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals("This is version 1 of fileWithVersions.txt.", contentReader.getContentString()); + + } + } diff --git a/source/test-resources/bulkimport3/initial/fileWithVersions.txt b/source/test-resources/bulkimport3/initial/fileWithVersions.txt new file mode 100644 index 0000000000..26409c0858 --- /dev/null +++ b/source/test-resources/bulkimport3/initial/fileWithVersions.txt @@ -0,0 +1 @@ +This is the final version of fileWithVersions.txt. \ No newline at end of file diff --git a/source/test-resources/bulkimport3/initial/fileWithVersions.txt.v1 b/source/test-resources/bulkimport3/initial/fileWithVersions.txt.v1 new file mode 100644 index 0000000000..443c2590e9 --- /dev/null +++ b/source/test-resources/bulkimport3/initial/fileWithVersions.txt.v1 @@ -0,0 +1 @@ +This is version 1 of fileWithVersions.txt. \ No newline at end of file diff --git a/source/test-resources/bulkimport3/initial/fileWithVersions.txt.v2 b/source/test-resources/bulkimport3/initial/fileWithVersions.txt.v2 new file mode 100644 index 0000000000..6f7c5ea9a8 --- /dev/null +++ b/source/test-resources/bulkimport3/initial/fileWithVersions.txt.v2 @@ -0,0 +1 @@ +This is version 2 of fileWithVersions.txt. \ No newline at end of file diff --git a/source/test-resources/bulkimport3/initial/fileWithVersions.txt.v3 b/source/test-resources/bulkimport3/initial/fileWithVersions.txt.v3 new file mode 100644 index 0000000000..9e50bb55a4 --- /dev/null +++ b/source/test-resources/bulkimport3/initial/fileWithVersions.txt.v3 @@ -0,0 +1 @@ +This is version 3 of fileWithVersions.txt. \ No newline at end of file diff --git a/source/test-resources/bulkimport3/replace_with_non_versioned/fileWithVersions.txt b/source/test-resources/bulkimport3/replace_with_non_versioned/fileWithVersions.txt new file mode 100644 index 0000000000..13bff5254c --- /dev/null +++ b/source/test-resources/bulkimport3/replace_with_non_versioned/fileWithVersions.txt @@ -0,0 +1 @@ +This is non versioned fileWithVersions.txt. \ No newline at end of file diff --git a/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt b/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt new file mode 100644 index 0000000000..1b6b7f9ccb --- /dev/null +++ b/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt @@ -0,0 +1 @@ +This is the final version of replaced on import fileWithVersions.txt. \ No newline at end of file diff --git a/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v1 b/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v1 new file mode 100644 index 0000000000..30e7b014d3 --- /dev/null +++ b/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v1 @@ -0,0 +1 @@ +This is version 1 of replaced on import fileWithVersions.txt. \ No newline at end of file diff --git a/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v2 b/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v2 new file mode 100644 index 0000000000..50c2926bae --- /dev/null +++ b/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v2 @@ -0,0 +1 @@ +This is version 2 of replaced on import fileWithVersions.txt. \ No newline at end of file diff --git a/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v3 b/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v3 new file mode 100644 index 0000000000..521f9e3448 --- /dev/null +++ b/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v3 @@ -0,0 +1 @@ +This is version 3 of replaced on import fileWithVersions.txt. \ No newline at end of file diff --git a/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v4 b/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v4 new file mode 100644 index 0000000000..7b1fba00b8 --- /dev/null +++ b/source/test-resources/bulkimport3/replace_with_versioned/fileWithVersions.txt.v4 @@ -0,0 +1 @@ +This is version 4 of replaced on import fileWithVersions.txt. \ No newline at end of file