diff --git a/ccm-core/src/main/java/org/libreccm/categorization/CategorizationImExporter.java b/ccm-core/src/main/java/org/libreccm/categorization/CategorizationImExporter.java
index 71da7369d..a69d2ddd4 100644
--- a/ccm-core/src/main/java/org/libreccm/categorization/CategorizationImExporter.java
+++ b/ccm-core/src/main/java/org/libreccm/categorization/CategorizationImExporter.java
@@ -19,9 +19,12 @@
package org.libreccm.categorization;
import org.libreccm.imexport.AbstractEntityImExporter;
-import org.libreccm.imexport.DependsOn;
+import org.libreccm.imexport.Exportable;
import org.libreccm.imexport.Processes;
+import java.util.HashSet;
+import java.util.Set;
+
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
@@ -31,19 +34,27 @@ import javax.transaction.Transactional;
* @author Jens Pelzetter
*/
@Processes(Categorization.class)
-@DependsOn({Category.class})
public class CategorizationImExporter
extends AbstractEntityImExporter {
@Inject
- private EntityManager entityManager;
-
+ private EntityManager entityManager;
+
@Override
protected Class getEntityClass() {
return Categorization.class;
}
+ @Override
+ protected Set> getRequiredEntities() {
+
+ final Set> entities = new HashSet<>();
+ entities.add(Category.class);
+
+ return entities;
+ }
+
@Override
@Transactional(Transactional.TxType.REQUIRED)
protected void saveImportedEntity(final Categorization entity) {
diff --git a/ccm-core/src/main/java/org/libreccm/categorization/CategoryImExporter.java b/ccm-core/src/main/java/org/libreccm/categorization/CategoryImExporter.java
index 48ada50b2..477fc0fb2 100644
--- a/ccm-core/src/main/java/org/libreccm/categorization/CategoryImExporter.java
+++ b/ccm-core/src/main/java/org/libreccm/categorization/CategoryImExporter.java
@@ -19,9 +19,12 @@
package org.libreccm.categorization;
import org.libreccm.imexport.AbstractEntityImExporter;
-import org.libreccm.imexport.DependsOn;
+import org.libreccm.imexport.Exportable;
import org.libreccm.imexport.Processes;
+import java.util.HashSet;
+import java.util.Set;
+
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
@@ -32,7 +35,6 @@ import javax.transaction.Transactional;
*/
@RequestScoped
@Processes(Category.class)
-@DependsOn({Domain.class})
public class CategoryImExporter extends AbstractEntityImExporter {
@Inject
@@ -44,6 +46,15 @@ public class CategoryImExporter extends AbstractEntityImExporter {
return Category.class;
}
+ @Override
+ protected Set> getRequiredEntities() {
+
+ final Set> entities = new HashSet<>();
+ entities.add(Domain.class);
+
+ return entities;
+ }
+
@Override
@Transactional(Transactional.TxType.REQUIRED)
protected void saveImportedEntity(final Category entity) {
diff --git a/ccm-core/src/main/java/org/libreccm/imexport/AbstractEntityImExporter.java b/ccm-core/src/main/java/org/libreccm/imexport/AbstractEntityImExporter.java
index 25f569aa4..019a3355d 100644
--- a/ccm-core/src/main/java/org/libreccm/imexport/AbstractEntityImExporter.java
+++ b/ccm-core/src/main/java/org/libreccm/imexport/AbstractEntityImExporter.java
@@ -22,6 +22,9 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
+import java.util.Set;
+
+import javax.enterprise.context.RequestScoped;
/**
* Base class for importers/exporters. Implementations must be annotated with
@@ -37,8 +40,35 @@ public abstract class AbstractEntityImExporter {
private final ObjectMapper objectMapper = new ObjectMapper();
+ /**
+ * Returns the Entity class which is handled by the implementation. This
+ * should be the same values than the class in the {@link Proceesses}
+ * annotation. This duplication is necessary because we need the value in
+ * qualifier annotation to be able to request an implementation for a
+ * specific class from the CDI container. But we can't access the
+ * annotations in a portable way in the rest of the code because CDI
+ * containers usually create a {@link java.lang.reflect.Proxy} class and
+ * there is no portable way to unproxy a class.
+ *
+ * @return The Entity class which is handled by the implementation.
+ */
protected abstract Class getEntityClass();
+ /**
+ * A set of entities which should be processed before this implementation is
+ * used. We can't use an annotation for this because we can't access the
+ * annotations in a portable way in the rest of the code because CDI
+ * containers usually create a {@link java.lang.reflect.Proxy} class and
+ * there is no portable way to unproxy a class.
+ *
+ *
+ * @return A {@link Set} of exportable entity classes which should be
+ * processed before the entities which are processed by this
+ * implementation. If the implementation has no dependencies an
+ * empty {@link Set} should be returned.
+ */
+ protected abstract Set> getRequiredEntities();
+
public T importEntity(final String data) throws ImportExpection {
try {
diff --git a/ccm-core/src/main/java/org/libreccm/imexport/EntityImExporterTreeManager.java b/ccm-core/src/main/java/org/libreccm/imexport/EntityImExporterTreeManager.java
index 327163d5f..70806ea4f 100644
--- a/ccm-core/src/main/java/org/libreccm/imexport/EntityImExporterTreeManager.java
+++ b/ccm-core/src/main/java/org/libreccm/imexport/EntityImExporterTreeManager.java
@@ -50,7 +50,8 @@ final class EntityImExporterTreeManager {
.getLogger(EntityImExporterTreeManager.class);
/**
- * Initialises the tree with the provided list of {@link AbstractEntityImExporter}s.
+ * Initialises the tree with the provided list of
+ * {@link AbstractEntityImExporter}s.
*
* @param imExporters The available {@link AbstractEntityImExporter}s.
*
@@ -72,13 +73,12 @@ final class EntityImExporterTreeManager {
final Map nodes = imExporters
.stream()
.map(EntityImExporterTreeNode::new)
- .collect(Collectors
- .toMap(
- node -> node
- .getEntityImExporter()
- .getClass()
- .getAnnotation(Processes.class).value().getName(),
- node -> node));
+ .collect(Collectors.toMap(
+ node -> node
+ .getEntityImExporter()
+ .getClass()
+ .getAnnotation(Processes.class).value().getName(),
+ node -> node));
//Add the dependency relations to the nodes
for (final AbstractEntityImExporter> imExporter : imExporters) {
diff --git a/ccm-core/src/main/java/org/libreccm/imexport/ImportExport.java b/ccm-core/src/main/java/org/libreccm/imexport/ImportExport.java
index 37ea323f8..4bbdf5414 100644
--- a/ccm-core/src/main/java/org/libreccm/imexport/ImportExport.java
+++ b/ccm-core/src/main/java/org/libreccm/imexport/ImportExport.java
@@ -43,8 +43,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped;
@@ -139,8 +137,8 @@ public class ImportExport {
}
} catch (FileAccessException
- | FileAlreadyExistsException
- | InsufficientPermissionsException ex) {
+ | FileAlreadyExistsException
+ | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
@@ -197,7 +195,7 @@ public class ImportExport {
filename));
filesArrayBuilder.add(filename);
} catch (FileAccessException
- | InsufficientPermissionsException ex) {
+ | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
@@ -248,8 +246,8 @@ public class ImportExport {
importName));
}
} catch (FileAccessException
- | FileDoesNotExistException
- | InsufficientPermissionsException ex) {
+ | FileDoesNotExistException
+ | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
@@ -262,8 +260,7 @@ public class ImportExport {
final EntityImExporterTreeManager treeManager
= new EntityImExporterTreeManager();
final List tree = treeManager
- .generateTree(
- imExportersList);
+ .generateTree(imExportersList);
final List orderedNodes = treeManager
.orderImExporters(tree);
@@ -323,9 +320,9 @@ public class ImportExport {
entityImExporter));
} catch (IOException
- | FileDoesNotExistException
- | FileAccessException
- | InsufficientPermissionsException ex) {
+ | FileDoesNotExistException
+ | FileAccessException
+ | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
@@ -353,10 +350,10 @@ public class ImportExport {
imExporter.importEntity(data);
} catch (IOException
- | FileDoesNotExistException
- | FileAccessException
- | InsufficientPermissionsException
- | ImportExpection ex) {
+ | FileDoesNotExistException
+ | FileAccessException
+ | InsufficientPermissionsException
+ | ImportExpection ex) {
throw new UnexpectedErrorException(ex);
}
@@ -368,8 +365,8 @@ public class ImportExport {
try {
importArchivePaths = ccmFiles.listFiles("imports");
} catch (FileAccessException
- | FileDoesNotExistException
- | InsufficientPermissionsException ex) {
+ | FileDoesNotExistException
+ | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
@@ -442,9 +439,9 @@ public class ImportExport {
onServer,
types);
} catch (IOException
- | FileAccessException
- | FileDoesNotExistException
- | InsufficientPermissionsException ex) {
+ | FileAccessException
+ | FileDoesNotExistException
+ | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
diff --git a/ccm-core/src/main/java/org/libreccm/security/GroupMembershipImExporter.java b/ccm-core/src/main/java/org/libreccm/security/GroupMembershipImExporter.java
index dc4fe0b82..9c42b7254 100644
--- a/ccm-core/src/main/java/org/libreccm/security/GroupMembershipImExporter.java
+++ b/ccm-core/src/main/java/org/libreccm/security/GroupMembershipImExporter.java
@@ -19,9 +19,12 @@
package org.libreccm.security;
import org.libreccm.imexport.AbstractEntityImExporter;
-import org.libreccm.imexport.DependsOn;
+import org.libreccm.imexport.Exportable;
import org.libreccm.imexport.Processes;
+import java.util.HashSet;
+import java.util.Set;
+
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
@@ -31,7 +34,6 @@ import javax.transaction.Transactional;
* @author Jens Pelzetter
*/
@Processes(GroupMembership.class)
-@DependsOn({User.class, Group.class})
public class GroupMembershipImExporter extends AbstractEntityImExporter {
@Inject
@@ -41,7 +43,16 @@ public class GroupMembershipImExporter extends AbstractEntityImExporter getEntityClass() {
return GroupMembership.class;
-
+ }
+
+ @Override
+ protected Set> getRequiredEntities() {
+
+ final Set> entities = new HashSet<>();
+ entities.add(User.class);
+ entities.add(Group.class);
+
+ return entities;
}
@Override
diff --git a/ccm-core/src/main/java/org/libreccm/security/User.java b/ccm-core/src/main/java/org/libreccm/security/User.java
index 3b2fc667d..e34c1a932 100644
--- a/ccm-core/src/main/java/org/libreccm/security/User.java
+++ b/ccm-core/src/main/java/org/libreccm/security/User.java
@@ -272,7 +272,7 @@ public class User extends Party implements Serializable, Exportable {
}
protected void setEmailAddresses(final List emailAddresses) {
- this.emailAddresses = emailAddresses;
+ this.emailAddresses = new ArrayList<>(emailAddresses);
}
public void addEmailAddress(final EmailAddress emailAddress) {
@@ -313,7 +313,7 @@ public class User extends Party implements Serializable, Exportable {
protected void setGroupMemberships(
final Set groupMemberships) {
- this.groupMemberships = groupMemberships;
+ this.groupMemberships = new HashSet<>(groupMemberships);
}
protected void addGroupMembership(final GroupMembership groupMembership) {
diff --git a/ccm-core/src/main/java/org/libreccm/workflow/AssignableTaskImExporter.java b/ccm-core/src/main/java/org/libreccm/workflow/AssignableTaskImExporter.java
index e7db689c1..aa3e9e75c 100644
--- a/ccm-core/src/main/java/org/libreccm/workflow/AssignableTaskImExporter.java
+++ b/ccm-core/src/main/java/org/libreccm/workflow/AssignableTaskImExporter.java
@@ -19,9 +19,12 @@
package org.libreccm.workflow;
import org.libreccm.imexport.AbstractEntityImExporter;
-import org.libreccm.imexport.DependsOn;
+import org.libreccm.imexport.Exportable;
import org.libreccm.imexport.Processes;
+import java.util.HashSet;
+import java.util.Set;
+
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
@@ -33,7 +36,6 @@ import javax.transaction.Transactional;
*/
@RequestScoped
@Processes(AssignableTask.class)
-@DependsOn(Workflow.class)
public class AssignableTaskImExporter
extends AbstractEntityImExporter {
@@ -45,6 +47,15 @@ public class AssignableTaskImExporter
return AssignableTask.class;
}
+ @Override
+ protected Set> getRequiredEntities() {
+
+ final Set> entities = new HashSet<>();
+ entities.add(Workflow.class);
+
+ return entities;
+ }
+
@Override
@Transactional(Transactional.TxType.REQUIRED)
protected void saveImportedEntity(final AssignableTask entity) {
diff --git a/ccm-core/src/test/java/org/libreccm/imexport/UserImportTest.java b/ccm-core/src/test/java/org/libreccm/imexport/UserImportTest.java
new file mode 100644
index 000000000..c543313bd
--- /dev/null
+++ b/ccm-core/src/test/java/org/libreccm/imexport/UserImportTest.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2018 LibreCCM Foundation.
+ *
+ * This library 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 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package org.libreccm.imexport;
+
+import static org.libreccm.testutils.DependenciesHelpers.*;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.junit.InSequence;
+import org.jboss.arquillian.persistence.CleanupUsingScript;
+import org.jboss.arquillian.persistence.CreateSchema;
+import org.jboss.arquillian.persistence.PersistenceTest;
+import org.jboss.arquillian.persistence.ShouldMatchDataSet;
+import org.jboss.arquillian.persistence.TestExecutionPhase;
+import org.jboss.arquillian.persistence.UsingDataSet;
+import org.jboss.arquillian.transaction.api.annotation.TransactionMode;
+import org.jboss.arquillian.transaction.api.annotation.Transactional;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.libreccm.configuration.ConfigurationManager;
+import org.libreccm.core.UnexpectedErrorException;
+import org.libreccm.files.CcmFilesConfiguration;
+import org.libreccm.security.UserRepository;
+import org.libreccm.tests.categories.IntegrationTest;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URISyntaxException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@Category(IntegrationTest.class)
+@RunWith(Arquillian.class)
+@PersistenceTest
+@Transactional(TransactionMode.COMMIT)
+@CreateSchema("create_ccm_core_schema.sql")
+@CleanupUsingScript(value = {"cleanup.sql"},
+ phase = TestExecutionPhase.BEFORE)
+public class UserImportTest {
+
+ private static final String IMPORT_MANIFEST_SOURCE = "/imports"
+ + "/org.libreccm.imexport.UserImportTest"
+ + "/ccm-export.json";
+ private static final String IMPORT_DATA_SOURCE = "/imports"
+ + "/org.libreccm.imexport.UserImportTest"
+ + "/org.libreccm.security.User"
+ + "/7cb9aba4-8071-4f27-af19-096e1473d050.json";
+
+ private static final String TMP_DIR = System.getProperty("java.io.tmpdir");
+ private static final String CCM_TESTS_DIR = TMP_DIR + "/ccm-tests";
+ private static final String IMPORTS_DIR = CCM_TESTS_DIR + "/imports";
+ private static final String USER_IMPORT_TEST_DIR = IMPORTS_DIR
+ + "/org.libreccm.imexport.UserImportTest";
+ private static final String IMPORT_DATA_DIR = USER_IMPORT_TEST_DIR
+ + "/org.libreccm.security.User";
+
+ @Inject
+ private ConfigurationManager confManager;
+
+ @Inject
+ private ImportExport importExport;
+
+ @Inject
+ private UserRepository userRepository;
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ public UserImportTest() {
+
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() throws IOException, URISyntaxException {
+
+ final CcmFilesConfiguration filesConf = confManager
+ .findConfiguration(CcmFilesConfiguration.class);
+ filesConf.setDataPath(CCM_TESTS_DIR);
+
+// final Path tmpDirPath = Paths.get(TMP_DIR);
+ final Path ccmTestsDirPath = Paths.get(CCM_TESTS_DIR);
+ final Path importsPath = Paths.get(IMPORTS_DIR);
+ final Path userImportsTestDirPath = Paths.get(USER_IMPORT_TEST_DIR);
+ final Path importDataPath = Paths.get(IMPORT_DATA_DIR);
+
+ if (Files.exists(ccmTestsDirPath)) {
+ Files.walkFileTree(ccmTestsDirPath, new DeleteDirectoryVisitor());
+ }
+
+ Files.createDirectory(ccmTestsDirPath);
+ Files.createDirectory(importsPath);
+ Files.createDirectory(userImportsTestDirPath);
+ Files.createDirectory(importDataPath);
+
+ final InputStream manifestInputStream = getClass()
+ .getResourceAsStream(IMPORT_MANIFEST_SOURCE);
+ final InputStream user1DataInputStream = getClass()
+ .getResourceAsStream(IMPORT_DATA_SOURCE);
+
+ final Path manifestTargetPath = userImportsTestDirPath
+ .resolve("ccm-export.json");
+ final Path user1DataTargetPath = importDataPath
+ .resolve("7cb9aba4-8071-4f27-af19-096e1473d050.json");
+
+ copy(manifestInputStream, manifestTargetPath);
+ copy(user1DataInputStream, user1DataTargetPath);
+ }
+
+ private void copy(final InputStream source, final Path destination) {
+
+ try (final OutputStream outputStream = new FileOutputStream(
+ destination.toFile())) {
+
+ int data = source.read();
+ while (data != -1) {
+ outputStream.write(data);
+ data = source.read();
+ }
+ } catch (IOException ex) {
+ throw new UnexpectedErrorException(ex);
+ }
+ }
+
+ @After
+ public void tearDown() throws IOException {
+
+ final Path ccmTestsDirPath = Paths.get(CCM_TESTS_DIR);
+ Files.walkFileTree(ccmTestsDirPath, new DeleteDirectoryVisitor());
+ }
+
+ private class DeleteDirectoryVisitor extends SimpleFileVisitor {
+
+ @Override
+ public FileVisitResult visitFile(
+ final Path file, final BasicFileAttributes attrs)
+ throws IOException {
+
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(
+ final Path dir, final IOException exc)
+ throws IOException {
+
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
+ }
+
+ }
+
+ @Deployment
+ public static WebArchive createDeployment() {
+ return ShrinkWrap
+ .create(WebArchive.class,
+ "LibreCCM-org.libreccm.imexport.UserImportTest.war")
+ .addPackage(org.libreccm.cdi.utils.CdiUtil.class.getPackage())
+ .addPackage(org.libreccm.core.CcmObject.class.getPackage())
+ .addPackage(org.libreccm.categorization.Categorization.class
+ .getPackage())
+ .addPackage(org.libreccm.configuration.Configuration.class
+ .getPackage())
+ .addPackage(org.libreccm.files.CcmFiles.class.getPackage())
+ .addPackage(org.libreccm.l10n.LocalizedString.class.getPackage())
+ .addPackage(org.libreccm.imexport.Exportable.class.getPackage())
+ .addPackage(org.libreccm.jpa.EntityManagerProducer.class
+ .getPackage())
+ .addPackage(org.libreccm.jpa.utils.MimeTypeConverter.class
+ .getPackage())
+ .addPackage(org.libreccm.security.User.class.getPackage())
+ .addPackage(org.libreccm.web.CcmApplication.class.getPackage())
+ .addPackage(org.libreccm.workflow.Workflow.class.getPackage())
+ .addPackage(org.libreccm.testutils.EqualsVerifier.class
+ .getPackage())
+ .addPackage(org.libreccm.tests.categories.IntegrationTest.class
+ .getPackage())
+ .addClass(com.arsdigita.kernel.security.SecurityConfig.class)
+ .addClass(com.arsdigita.kernel.KernelConfig.class)
+ .addAsLibraries(getModuleDependencies())
+ .addAsResource("configs/shiro.ini", "shiro.ini")
+ .addAsResource("imports", "imports")
+ .addAsResource("test-persistence.xml",
+ "META-INF/persistence.xml")
+ .addAsWebInfResource("test-web.xml", "web.xml")
+ .addAsWebInfResource("META-INF/beans.xml", "beans.xml");
+ }
+
+ @Test
+ @InSequence(100)
+ public void checkIfFilesAreAvailable() {
+
+ final Path importDataPath = Paths.get(
+ TMP_DIR,
+ "ccm-tests",
+ "imports",
+ "org.libreccm.imexport.UserImportTest");
+ final Path manifestPath = importDataPath.resolve("ccm-export.json");
+ final Path typeDirPath = importDataPath
+ .resolve("org.libreccm.security.User");
+ final Path dataFile1Path = typeDirPath
+ .resolve("7cb9aba4-8071-4f27-af19-096e1473d050.json");
+
+ assertThat(String.format("Path %s does not exist.",
+ manifestPath.toString()),
+ Files.exists(manifestPath),
+ is(true));
+ assertThat(String.format("Path %s does not exist.",
+ typeDirPath.toString()),
+ Files.exists(typeDirPath),
+ is(true));
+ assertThat(String.format("Path %s does not exist.",
+ dataFile1Path.toString()),
+ Files.exists(dataFile1Path),
+ is(true));
+ }
+
+ @Test
+ @InSequence(150)
+ public void importsAvailable() {
+
+ final List imports = importExport
+ .listAvailableImportArchivies();
+
+ assertThat(imports.size(), is(1));
+ }
+
+ @Test
+ @UsingDataSet("datasets/org/libreccm/imexport/UserImportTest/data.yml")
+ @ShouldMatchDataSet(value = "datasets/org/libreccm/imexport/UserImportTest"
+ + "/after-import-single-user.yml",
+ excludeColumns = {"party_id"}
+ )
+ @InSequence(200)
+ public void importSingleUser() {
+
+ importExport.importEntities("org.libreccm.imexport.UserImportTest");
+ }
+
+}
diff --git a/ccm-core/src/test/resources/datasets/org/libreccm/imexport/UserImportTest/after-import-single-user.yml b/ccm-core/src/test/resources/datasets/org/libreccm/imexport/UserImportTest/after-import-single-user.yml
new file mode 100644
index 000000000..4637a94b1
--- /dev/null
+++ b/ccm-core/src/test/resources/datasets/org/libreccm/imexport/UserImportTest/after-import-single-user.yml
@@ -0,0 +1,60 @@
+ccm_core.parties:
+ # John Doe
+ - party_id: -10
+ uuid: 631be113-7e86-453d-9f8b-8cb6cb6df268
+ name: jdoe
+ # Max Muster
+ - party_id: -20
+ uuid: 3a61d302-97a5-4e46-bbc9-8d716f7c54c4
+ name: mmuster
+ # Joe Public
+ - party_id: -30
+ uuid: 7d5ad4a7-c2bd-4e49-8716-0bfb40413c75
+ name: joe
+ # Jane Doe
+ - party_id: -40
+ uuid: 7cb9aba4-8071-4f27-af19-096e1473d050
+ name: janedoe
+ccm_core.users:
+ # John Doe
+ - banned: false
+ bouncing: false
+ email_address: john.doe@example.com
+ family_name: Doe
+ given_name: John
+ party_id: -10
+ # foo123
+ password: $shiro1$SHA-512$500000$7xkDcZUN0/whJInHIvGsDw==$WhelBVmJU/cLV7lAkMOrE5B/mqCW0bUuid1WX+xBwzzAaekC5bYn9eeOFGJWhiDgmaC50ZCUmM96/iGsRoc4uA==
+ password_reset_required: false
+ verified: true
+ # Max Mustermann
+ - banned: false
+ bouncing: false
+ email_address: max.mustermann@example.org
+ family_name: Mustermann
+ given_name: Max
+ party_id: -20
+ # foo123
+ password: $shiro1$SHA-512$500000$Y7CnccN1h25sR7KCElMOXg==$CVLWBhetodaEzzhDfGjRcCFZtSW02xOnjH7xhBx0lbxO66grKIt6LWmXoUhLEydce1JZ7cbzNLYOxIwwTeqi5Q==
+ password_reset_required: false
+ verified: true
+ # Joe Public
+ - banned: false
+ bouncing: false
+ email_address: joe.public@example.com
+ family_name: Public
+ given_name: Joe
+ party_id: -30
+ password: $shiro1$SHA-512$500000$RUCYXAQt+XzUmj3x8oG5gw==$qU+lX160Jc6sNUOI9X85wlf2lzn4/hLJNURtjmw9LOYJ7vAqUFFmhyNCMxpzuHIpzeMELr+A0XReoSmtcZnOOw==
+ password_reset_required: false
+ verified: true
+ # Jane Doe
+ - banned: false
+ bouncing: false
+ email_address: jane.doe@libreccm.example
+ family_name: Doe
+ given_name: Jane
+ party_id: -40
+ password: ofafodafa
+ password_reset_required: false
+ verified: true
diff --git a/ccm-core/src/test/resources/datasets/org/libreccm/imexport/UserImportTest/data.yml b/ccm-core/src/test/resources/datasets/org/libreccm/imexport/UserImportTest/data.yml
new file mode 100644
index 000000000..d1e7891d5
--- /dev/null
+++ b/ccm-core/src/test/resources/datasets/org/libreccm/imexport/UserImportTest/data.yml
@@ -0,0 +1,46 @@
+ccm_core.parties:
+ # John Doe
+ - party_id: -10
+ uuid: 631be113-7e86-453d-9f8b-8cb6cb6df268
+ name: jdoe
+ # Max Muster
+ - party_id: -20
+ uuid: 3a61d302-97a5-4e46-bbc9-8d716f7c54c4
+ name: mmuster
+ # Joe Public
+ - party_id: -30
+ uuid: 7d5ad4a7-c2bd-4e49-8716-0bfb40413c75
+ name: joe
+ccm_core.users:
+ # John Doe
+ - banned: false
+ bouncing: false
+ email_address: john.doe@example.com
+ family_name: Doe
+ given_name: John
+ party_id: -10
+ # foo123
+ password: $shiro1$SHA-512$500000$7xkDcZUN0/whJInHIvGsDw==$WhelBVmJU/cLV7lAkMOrE5B/mqCW0bUuid1WX+xBwzzAaekC5bYn9eeOFGJWhiDgmaC50ZCUmM96/iGsRoc4uA==
+ password_reset_required: false
+ verified: true
+ # Max Mustermann
+ - banned: false
+ bouncing: false
+ email_address: max.mustermann@example.org
+ family_name: Mustermann
+ given_name: Max
+ party_id: -20
+ # foo123
+ password: $shiro1$SHA-512$500000$Y7CnccN1h25sR7KCElMOXg==$CVLWBhetodaEzzhDfGjRcCFZtSW02xOnjH7xhBx0lbxO66grKIt6LWmXoUhLEydce1JZ7cbzNLYOxIwwTeqi5Q==
+ password_reset_required: false
+ verified: true
+ # Joe Public
+ - banned: false
+ bouncing: false
+ email_address: joe.public@example.com
+ family_name: Public
+ given_name: Joe
+ party_id: -30
+ password: $shiro1$SHA-512$500000$RUCYXAQt+XzUmj3x8oG5gw==$qU+lX160Jc6sNUOI9X85wlf2lzn4/hLJNURtjmw9LOYJ7vAqUFFmhyNCMxpzuHIpzeMELr+A0XReoSmtcZnOOw==
+ password_reset_required: false
+ verified: true
diff --git a/ccm-core/src/test/resources/imports/org.libreccm.imexport.UserImportTest/ccm-export.json b/ccm-core/src/test/resources/imports/org.libreccm.imexport.UserImportTest/ccm-export.json
new file mode 100644
index 000000000..283cd452e
--- /dev/null
+++ b/ccm-core/src/test/resources/imports/org.libreccm.imexport.UserImportTest/ccm-export.json
@@ -0,0 +1,13 @@
+{
+ "created": "2018-11-18T12:00:00",
+ "onServer": "tests.libreccm.example",
+ "types": [
+ "org.libreccm.security.User"
+ ],
+ "enities": {
+ "org.libreccm.security.User": [
+ "7cb9aba4-8071-4f27-af19-096e1473d050"
+ ]
+ }
+}
+
diff --git a/ccm-core/src/test/resources/imports/org.libreccm.imexport.UserImportTest/org.libreccm.security.User/7cb9aba4-8071-4f27-af19-096e1473d050.json b/ccm-core/src/test/resources/imports/org.libreccm.imexport.UserImportTest/org.libreccm.security.User/7cb9aba4-8071-4f27-af19-096e1473d050.json
new file mode 100644
index 000000000..cc5af3c63
--- /dev/null
+++ b/ccm-core/src/test/resources/imports/org.libreccm.imexport.UserImportTest/org.libreccm.security.User/7cb9aba4-8071-4f27-af19-096e1473d050.json
@@ -0,0 +1,15 @@
+{
+ "id": 4345,
+ "uuid": "7cb9aba4-8071-4f27-af19-096e1473d050",
+ "name": "janedoe",
+ "givenName": "Jane",
+ "familyName": "Doe",
+ "primaryEmailAddress": {
+ "address": "jane.doe@libreccm.example",
+ "bouncing": false,
+ "verified": true
+ },
+ "banned": false,
+ "password": "ofafodafa",
+ "passwordResetRequired": false
+}
\ No newline at end of file