diff --git a/citesphere/pom.xml b/citesphere/pom.xml
index 34fa7b238..ade3c00c6 100644
--- a/citesphere/pom.xml
+++ b/citesphere/pom.xml
@@ -24,7 +24,7 @@
6.2.32.2.6.RELEASE0.13
- 0.4
+ 0.61.24$2a$04$oQo44vqcDIFRoYKiAXoNheurzkwX9dcNmowvTX/hsWuBMwijqn44i
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/api/v1/user/JobInfoController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/api/v1/user/JobInfoController.java
index cab48f00c..e705b12cb 100644
--- a/citesphere/src/main/java/edu/asu/diging/citesphere/api/v1/user/JobInfoController.java
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/api/v1/user/JobInfoController.java
@@ -19,8 +19,10 @@
import edu.asu.diging.citesphere.core.model.jobs.IUploadJob;
import edu.asu.diging.citesphere.core.service.jobs.IUploadJobManager;
import edu.asu.diging.citesphere.core.service.jwt.IJobApiTokenContents;
+import edu.asu.diging.citesphere.core.service.oauth.InternalTokenManager;
import edu.asu.diging.citesphere.core.user.IUserManager;
import edu.asu.diging.citesphere.core.zotero.impl.ZoteroTokenManager;
+import edu.asu.diging.citesphere.user.IUser;
@Controller
public class JobInfoController extends BaseJobInfoController {
@@ -37,6 +39,8 @@ public class JobInfoController extends BaseJobInfoController {
@Autowired
private IExportTaskManager exportTaskManager;
+ @Autowired
+ private InternalTokenManager internalTokenManager;
@RequestMapping(value="/job/info")
public ResponseEntity getProfile(@RequestHeader HttpHeaders headers) {
@@ -62,6 +66,9 @@ public ResponseEntity getProfile(@RequestHeader HttpHeaders headers) {
// FIXME: ugly, needs better solution
if (job instanceof IUploadJob) {
node.put("groupId", ((IUploadJob)job).getCitationGroup());
+ node.put("collectionId", ((IUploadJob)job).getCitationCollection());
+ IUser user = userManager.findByUsername(job.getUsername());
+ node.put("giles", internalTokenManager.getAccessToken(user).getValue());
}
if (job instanceof IExportJob) {
IExportTask exportTask = exportTaskManager.get(((IExportJob)job).getTaskId());
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/jobs/IUploadJob.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/jobs/IUploadJob.java
index caf90a7c5..44b391197 100644
--- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/jobs/IUploadJob.java
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/jobs/IUploadJob.java
@@ -30,6 +30,10 @@ public interface IUploadJob extends IJob {
void setCitationGroup(String citationGroup);
String getCitationGroup();
+
+ String getCitationCollection();
+
+ void setCitationCollection(String citationCollection);
ICitationGroup getCitationGroupDetail();
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/jobs/impl/UploadJob.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/jobs/impl/UploadJob.java
index c1e776b85..bbddcff16 100644
--- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/jobs/impl/UploadJob.java
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/jobs/impl/UploadJob.java
@@ -14,6 +14,7 @@ public class UploadJob extends Job implements IUploadJob {
private long fileSize;
private String contentType;
private String citationGroup;
+ private String citationCollection;
@Transient
private ICitationGroup citationGroupDetail;
@@ -57,6 +58,14 @@ public void setCitationGroup(String citationGroup) {
this.citationGroup = citationGroup;
}
@Override
+ public String getCitationCollection() {
+ return citationCollection;
+ }
+ @Override
+ public void setCitationCollection(String citationCollection) {
+ this.citationCollection = citationCollection;
+ }
+ @Override
public ICitationGroup getCitationGroupDetail() {
return citationGroupDetail;
}
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationCollectionManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationCollectionManager.java
index b5fc7f03c..501b61947 100644
--- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationCollectionManager.java
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationCollectionManager.java
@@ -2,7 +2,10 @@
import java.util.List;
+import org.springframework.social.zotero.exception.ZoteroConnectionException;
+
import edu.asu.diging.citesphere.core.exceptions.GroupDoesNotExistException;
+import edu.asu.diging.citesphere.core.exceptions.ZoteroItemCreationFailedException;
import edu.asu.diging.citesphere.model.bib.ICitationCollection;
import edu.asu.diging.citesphere.model.bib.impl.CitationCollectionResult;
import edu.asu.diging.citesphere.user.IUser;
@@ -20,5 +23,8 @@ List getAllCollections(IUser user, String groupId, String p
throws GroupDoesNotExistException;
void deleteLocalGroupCollections(String groupId);
+
+ ICitationCollection createCollection(IUser user, String groupId, String collectionName, String parentCollection)
+ throws GroupDoesNotExistException, ZoteroItemCreationFailedException, ZoteroConnectionException;
}
\ No newline at end of file
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationCollectionManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationCollectionManager.java
index 45ce1bd39..3bd00d163 100644
--- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationCollectionManager.java
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationCollectionManager.java
@@ -7,9 +7,11 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
+import org.springframework.social.zotero.exception.ZoteroConnectionException;
import org.springframework.stereotype.Service;
import edu.asu.diging.citesphere.core.exceptions.GroupDoesNotExistException;
+import edu.asu.diging.citesphere.core.exceptions.ZoteroItemCreationFailedException;
import edu.asu.diging.citesphere.core.service.ICitationCollectionManager;
import edu.asu.diging.citesphere.core.zotero.IZoteroManager;
import edu.asu.diging.citesphere.data.bib.CitationCollectionRepository;
@@ -17,6 +19,7 @@
import edu.asu.diging.citesphere.data.bib.ICollectionMongoDao;
import edu.asu.diging.citesphere.model.bib.ICitationCollection;
import edu.asu.diging.citesphere.model.bib.ICitationGroup;
+import edu.asu.diging.citesphere.model.bib.impl.CitationCollection;
import edu.asu.diging.citesphere.model.bib.impl.CitationCollectionResult;
import edu.asu.diging.citesphere.user.IUser;
@@ -107,4 +110,22 @@ public ICitationCollection getCollection(IUser user, String groupId, String coll
public void deleteLocalGroupCollections(String groupId) {
collectionRepository.deleteByGroupId(groupId);
}
+
+ @Override
+ public ICitationCollection createCollection(IUser user, String groupId, String collectionName, String parentCollection)
+ throws GroupDoesNotExistException, ZoteroItemCreationFailedException, ZoteroConnectionException {
+ Optional groupOptional = groupRepository.findFirstByGroupId(new Long(groupId));
+ if (!groupOptional.isPresent()) {
+ throw new GroupDoesNotExistException("Group with id " + groupId + " does not exist.");
+ }
+ if(parentCollection != null) {
+ Optional collectionOptional = collectionRepository.findByKey(parentCollection);
+ if (!collectionOptional.isPresent()) {
+ throw new GroupDoesNotExistException("Collection with id " + parentCollection + " does not exist.");
+ }
+ }
+
+ ICitationCollection newCollection = zoteroManager.createCitationCollection(user, groupId, collectionName, parentCollection);
+ return collectionRepository.save((CitationCollection)newCollection);
+ }
}
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/IUploadCollectionJobManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/IUploadCollectionJobManager.java
new file mode 100644
index 000000000..a66667af6
--- /dev/null
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/IUploadCollectionJobManager.java
@@ -0,0 +1,16 @@
+package edu.asu.diging.citesphere.core.service.jobs;
+
+import java.util.List;
+
+import org.springframework.web.multipart.MultipartFile;
+
+import edu.asu.diging.citesphere.core.exceptions.GroupDoesNotExistException;
+import edu.asu.diging.citesphere.core.model.jobs.IUploadJob;
+import edu.asu.diging.citesphere.user.IUser;
+
+public interface IUploadCollectionJobManager {
+
+ List createUploadJob(IUser user, MultipartFile[] files, List fileBytes, String groupId, String collectionId) throws GroupDoesNotExistException;
+
+
+}
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/UploadCollectionJobManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/UploadCollectionJobManager.java
new file mode 100644
index 000000000..3842f1d25
--- /dev/null
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/UploadCollectionJobManager.java
@@ -0,0 +1,140 @@
+package edu.asu.diging.citesphere.core.service.jobs.impl;
+
+import java.time.OffsetDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.Transactional;
+
+import org.apache.tika.Tika;
+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.context.annotation.PropertySource;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import edu.asu.diging.citesphere.core.exceptions.FileStorageException;
+import edu.asu.diging.citesphere.core.exceptions.GroupDoesNotExistException;
+import edu.asu.diging.citesphere.core.exceptions.MessageCreationException;
+import edu.asu.diging.citesphere.core.kafka.IKafkaRequestProducer;
+import edu.asu.diging.citesphere.core.model.jobs.IUploadJob;
+import edu.asu.diging.citesphere.core.model.jobs.JobStatus;
+import edu.asu.diging.citesphere.core.model.jobs.impl.JobPhase;
+import edu.asu.diging.citesphere.core.model.jobs.impl.UploadJob;
+import edu.asu.diging.citesphere.core.repository.jobs.UploadJobRepository;
+import edu.asu.diging.citesphere.core.service.IGroupManager;
+import edu.asu.diging.citesphere.core.service.jobs.IUploadCollectionJobManager;
+import edu.asu.diging.citesphere.core.service.jwt.IJwtTokenService;
+import edu.asu.diging.citesphere.core.service.upload.IFileStorageManager;
+import edu.asu.diging.citesphere.messages.KafkaTopics;
+import edu.asu.diging.citesphere.messages.model.KafkaJobMessage;
+import edu.asu.diging.citesphere.model.bib.ICitationGroup;
+import edu.asu.diging.citesphere.user.IUser;
+
+@Service
+@Transactional
+@PropertySource("classpath:/config.properties")
+public class UploadCollectionJobManager implements IUploadCollectionJobManager {
+
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Value("${_job_page_size}")
+ private int jobPageSize;
+
+ @Autowired
+ private UploadJobRepository uploadJobRepository;
+
+ @Autowired
+ private IFileStorageManager fileManager;
+
+ @Autowired
+ private IKafkaRequestProducer kafkaProducer;
+
+ @Autowired
+ private IJwtTokenService tokenService;
+
+ @Autowired
+ private IGroupManager groupManager;
+
+ @Override
+ public List createUploadJob(IUser user, MultipartFile[] files, List fileBytes,
+ String groupId, String collectionId) throws GroupDoesNotExistException {
+ ICitationGroup group = groupManager.getGroup(user, groupId);
+ if (group == null) {
+ throw new GroupDoesNotExistException();
+ }
+
+ List jobs = new ArrayList<>();
+ int i = 0;
+ for (MultipartFile f : files) {
+ String filename = f.getOriginalFilename();
+
+ byte[] bytes = null;
+ UploadJob job = new UploadJob();
+ jobs.add(job);
+ job.setFilename(filename);
+ job.setCreatedOn(OffsetDateTime.now());
+ job.setUsername(user.getUsername());
+ job.setCitationGroup(groupId);
+ job.setCitationCollection(collectionId);
+ job.setPhases(new ArrayList<>());
+ try {
+ if (fileBytes != null && fileBytes.size() == files.length) {
+ bytes = fileBytes.get(i);
+ } else {
+ job.setStatus(JobStatus.FAILURE);
+ job.getPhases().add(new JobPhase(JobStatus.FAILURE,
+ "There is a mismatch between file metadata and file contents."));
+ continue;
+ }
+
+ if (bytes == null) {
+ job.setStatus(JobStatus.FAILURE);
+ job.getPhases().add(new JobPhase(JobStatus.FAILURE, "There is not file content."));
+ continue;
+ }
+ job = uploadJobRepository.save(job);
+ fileManager.saveFile(user.getUsername(), job.getId(), filename, bytes);
+
+ job.setStatus(JobStatus.PREPARED);
+ } catch (FileStorageException e) {
+ logger.error("Could not store file.", e);
+ job.setStatus(JobStatus.FAILURE);
+ job.getPhases().add(new JobPhase(JobStatus.FAILURE, e.getMessage()));
+ continue;
+ } finally {
+ i++;
+ uploadJobRepository.save(job);
+ }
+
+ String contentType = null;
+
+ if (bytes != null) {
+ Tika tika = new Tika();
+ contentType = tika.detect(bytes);
+ }
+
+ if (contentType == null) {
+ contentType = f.getContentType();
+ }
+
+ job.setContentType(contentType);
+ job.setFileSize(f.getSize());
+ uploadJobRepository.save(job);
+ String token = tokenService.generateJobApiToken(job);
+ try {
+ kafkaProducer.sendRequest(new KafkaJobMessage(token), KafkaTopics.COLLECTION_IMPORT_TOPIC);
+ } catch (MessageCreationException e) {
+ logger.error("Could not send Kafka message.", e);
+ job.setStatus(JobStatus.FAILURE);
+ job.getPhases().add(new JobPhase(JobStatus.FAILURE, e.getMessage()));
+ uploadJobRepository.save(job);
+ }
+ }
+
+ return jobs;
+ }
+
+}
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/IZoteroConnector.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/IZoteroConnector.java
index c552896cb..e5c26ec93 100644
--- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/IZoteroConnector.java
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/IZoteroConnector.java
@@ -85,4 +85,6 @@ void clearCollectionItemsCache(IUser user, String groupId, String collectionId,
Map> deleteMultipleItems(IUser user, String groupId, List citationKeys, Long citationVersion) throws ZoteroConnectionException, ZoteroHttpStatusException;
+ Collection createCitationCollection(IUser user, String groupId, String collectionName,
+ String parentCollection) throws ZoteroItemCreationFailedException, ZoteroConnectionException;
}
\ No newline at end of file
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/IZoteroManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/IZoteroManager.java
index 806ba0a67..3f7f42bbe 100644
--- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/IZoteroManager.java
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/IZoteroManager.java
@@ -81,4 +81,7 @@ CitationResults getCollectionItems(IUser user, String groupId, String collection
long getLatestGroupVersion(IUser user, String groupId);
Map> deleteMultipleItems(IUser user, String groupId, List citationKeys, Long citationVersion) throws ZoteroConnectionException, ZoteroHttpStatusException;
+
+ ICitationCollection createCitationCollection(IUser user, String groupId, String collectionName, String parentCollection) throws ZoteroItemCreationFailedException, ZoteroConnectionException;
+
}
\ No newline at end of file
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/impl/ZoteroConnector.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/impl/ZoteroConnector.java
index 9a865db9d..25180501c 100644
--- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/impl/ZoteroConnector.java
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/impl/ZoteroConnector.java
@@ -369,4 +369,29 @@ public Map> deleteMultipleItems(IUser user, S
Zotero zotero = getApi(user);
return zotero.getGroupsOperations().deleteMultipleItems(groupId, citationKeys, citationVersion);
}
+
+ @Override
+ public Collection createCitationCollection(IUser user, String groupId, String collectionName,
+ String parentCollection) throws ZoteroItemCreationFailedException, ZoteroConnectionException {
+ Zotero zotero = getApi(user);
+
+ ItemCreationResponse response = zotero.getGroupCollectionsOperations().createCollection(groupId, collectionName, parentCollection);
+
+ // let's give Zotero a minute to process
+ try {
+ TimeUnit.SECONDS.sleep(1);
+ } catch (InterruptedException e) {
+ logger.error("Could not sleep.", e);
+ // well if something goes wrong here, let's just ignore it
+ }
+
+ Map success = response.getSuccess();
+ if (success.isEmpty()) {
+ logger.error("Could not create collection: " + response.getFailed().get("0"));
+ throw new ZoteroItemCreationFailedException(response);
+ }
+
+ // since we only submitted one item, there should only be one in the map
+ return getCitationCollection(user, groupId, success.values().iterator().next());
+ }
}
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/impl/ZoteroManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/impl/ZoteroManager.java
index cf2236382..8b311f053 100644
--- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/impl/ZoteroManager.java
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/zotero/impl/ZoteroManager.java
@@ -538,4 +538,11 @@ public Map> deleteMultipleItems(IUser user, S
throws ZoteroConnectionException, ZoteroHttpStatusException {
return zoteroConnector.deleteMultipleItems(user, groupId, citationKeys, citationVersion);
}
+
+ @Override
+ public ICitationCollection createCitationCollection(IUser user, String groupId, String collectionName,
+ String parentCollection) throws ZoteroItemCreationFailedException, ZoteroConnectionException {
+ Collection collection = zoteroConnector.createCitationCollection(user, groupId, collectionName, parentCollection);
+ return collectionFactory.createCitationCollection(collection);
+ }
}
diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/jobs/ImportCollectionsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/jobs/ImportCollectionsController.java
new file mode 100644
index 000000000..feb6c837d
--- /dev/null
+++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/jobs/ImportCollectionsController.java
@@ -0,0 +1,149 @@
+package edu.asu.diging.citesphere.web.user.jobs;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.social.zotero.exception.ZoteroConnectionException;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import edu.asu.diging.citesphere.api.v1.model.impl.Collections;
+import edu.asu.diging.citesphere.api.v1.user.JsonUtil;
+import edu.asu.diging.citesphere.core.exceptions.GroupDoesNotExistException;
+import edu.asu.diging.citesphere.core.exceptions.ZoteroItemCreationFailedException;
+import edu.asu.diging.citesphere.core.model.jobs.IUploadJob;
+import edu.asu.diging.citesphere.core.service.ICitationCollectionManager;
+import edu.asu.diging.citesphere.core.service.ICitationManager;
+import edu.asu.diging.citesphere.core.service.IGroupManager;
+import edu.asu.diging.citesphere.core.service.jobs.IUploadCollectionJobManager;
+import edu.asu.diging.citesphere.model.bib.ICitationCollection;
+import edu.asu.diging.citesphere.model.bib.ICitationGroup;
+import edu.asu.diging.citesphere.user.IUser;
+import edu.asu.diging.citesphere.user.impl.User;
+
+@Controller
+public class ImportCollectionsController {
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Autowired
+ private IUploadCollectionJobManager jobManager;
+
+ @Autowired
+ private ICitationManager citationManager;
+
+ @Autowired
+ private ICitationCollectionManager collectionManager;
+
+ @Autowired
+ private IGroupManager groupManager;
+
+ @Autowired
+ private JsonUtil jsonUtil;
+
+ @RequestMapping(value = "/auth/import/collection", method = RequestMethod.GET)
+ public String show(Model model, Authentication authentication) {
+ model.addAttribute("groups", citationManager.getGroups((IUser)authentication.getPrincipal()));
+ return "auth/import/collection";
+ }
+
+ @RequestMapping(value = "/auth/import/collection/getgroupcollections", method = RequestMethod.GET)
+ public ResponseEntity getCollections( @RequestParam("groupId") String groupId, Authentication authentication) {
+ IUser user = (IUser)authentication.getPrincipal();
+
+ ICitationGroup group = groupManager.getGroup(user, groupId);
+ if (group == null) {
+ return new ResponseEntity(HttpStatus.NOT_FOUND);
+ }
+
+ Collections collectionResponse = new Collections();
+ collectionResponse.setGroup(jsonUtil.createGroup(group));
+ try {
+ collectionResponse.setCollections(
+ collectionManager.getAllCollections(user, groupId, null, "title", 20));
+ } catch (GroupDoesNotExistException e) {
+ logger.error("Could not create job because group does not exist.", e);
+ return new ResponseEntity(HttpStatus.BAD_REQUEST);
+ }
+ return new ResponseEntity(collectionResponse, HttpStatus.OK);
+ }
+
+ @RequestMapping(value = "/auth/import/collection", method = RequestMethod.POST)
+ public ResponseEntity uploadCollection(Principal principal, @RequestParam("group") String group,
+ @RequestParam("collectionId") String collectionId, @RequestParam("files") MultipartFile[] files) {
+
+ User user = null;
+ if (principal instanceof UsernamePasswordAuthenticationToken) {
+ user = (User) ((UsernamePasswordAuthenticationToken) principal)
+ .getPrincipal();
+ }
+
+ if (user == null) {
+ return new ResponseEntity(HttpStatus.UNAUTHORIZED);
+ }
+
+ List fileBytes = new ArrayList<>();
+ for (MultipartFile file : files) {
+ try {
+ fileBytes.add(file.getBytes());
+ } catch (IOException e) {
+ logger.error("Could not get file content from request.", e);
+ return new ResponseEntity("Could not get file content from request.", HttpStatus.BAD_REQUEST);
+ }
+ }
+
+ if (collectionId.equals("new")) {
+ try {
+ ICitationCollection collection = collectionManager.createCollection(user, group, files[0].getName(), null);
+ collectionId = collection.getKey();
+ } catch (GroupDoesNotExistException e) {
+ logger.error("Could not create job because group does not exist.", e);
+ return new ResponseEntity("Could not create job because group does not exist", HttpStatus.BAD_REQUEST);
+ } catch (ZoteroItemCreationFailedException e) {
+ logger.error("Zotero new collection creation failed.", e);
+ return new ResponseEntity("Zotero new collection creation failed.", HttpStatus.INTERNAL_SERVER_ERROR);
+ } catch (ZoteroConnectionException e) {
+ logger.error("Zotero connection failed.", e);
+ return new ResponseEntity("Zotero connection failed.", HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ List jobs;
+ try {
+ jobs = jobManager.createUploadJob(user, files, fileBytes, group, collectionId);
+ } catch (GroupDoesNotExistException e) {
+ logger.error("Could not create job because group does not exist.", e);
+ return new ResponseEntity(HttpStatus.BAD_REQUEST);
+ }
+
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode root = mapper.createObjectNode();
+ ArrayNode filesNode = root.putArray("jobs");
+ for (IUploadJob job : jobs) {
+ ObjectNode jobNode = mapper.createObjectNode();
+ jobNode.put("jobId", job.getId());
+ jobNode.put("filename", job.getFilename());
+ jobNode.put("status", job.getStatus().name());
+ filesNode.add(jobNode);
+ }
+ return new ResponseEntity(root.toString(), HttpStatus.OK);
+ }
+
+
+}
diff --git a/citesphere/src/main/webapp/WEB-INF/tiles-defs.xml b/citesphere/src/main/webapp/WEB-INF/tiles-defs.xml
index 82ad578d2..c2ad5b473 100644
--- a/citesphere/src/main/webapp/WEB-INF/tiles-defs.xml
+++ b/citesphere/src/main/webapp/WEB-INF/tiles-defs.xml
@@ -88,6 +88,9 @@
+
+
+
diff --git a/citesphere/src/main/webapp/WEB-INF/views/auth/import/collection.html b/citesphere/src/main/webapp/WEB-INF/views/auth/import/collection.html
new file mode 100644
index 000000000..6772618d4
--- /dev/null
+++ b/citesphere/src/main/webapp/WEB-INF/views/auth/import/collection.html
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Upload Collection
+
+
+
+
+
+ Import started! Head over to the job list to see the status of your import.
+
+
+
You can upload zip file with
+ bibliographical data in BibTex format including files.
+
+
Select files from your computer
+
+
+
+
Or drag and drop files below
+
Just drag and
+ drop files here
+
+
+
+
Processed files
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html b/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html
index db0d1104e..bda2bff20 100644
--- a/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html
+++ b/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html
@@ -90,6 +90,7 @@