package com.aperture_software.glados_wiki.services;
import com.aperture_software.glados_wiki.entities.FileEntry;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: jhyun
* Date: 13. Nov. 16
* Time: 11:07
*/
@Service
public class FileStoreService {
private static Logger LOG = LoggerFactory.getLogger(FileStoreService.class);
@Autowired
private GridFS gridFS;
private DBObject createQuery(Optional<String> searchTerm, final Optional<String> creator, final boolean isAdmin) {
BasicDBList rootAndClauses = new BasicDBList();
//
if (false == isAdmin) {
if (creator.isPresent()) {
/* private == false || (private == true && creator == myself). */
BasicDBList l = new BasicDBList();
l.add(new BasicDBObject("metadata.private", false));
//
BasicDBList l2 = new BasicDBList();
l2.add(new BasicDBObject("metadata.private", true));
l2.add(new BasicDBObject("metadata.creator", creator.get()));
l.add(new BasicDBObject("$and", l2));
//
rootAndClauses.add(new BasicDBObject("$or", l));
} else {
rootAndClauses.add(new BasicDBObject("metadata.private", false));
}
}
//
if (searchTerm.isPresent()) {
BasicDBObject qRegex = new BasicDBObject();
qRegex.put("$regex", searchTerm.get());
qRegex.put("$options", "i");
//
BasicDBList l = new BasicDBList();
l.add(new BasicDBObject("metadata.description", qRegex));
l.add(new BasicDBObject("filename", qRegex));
rootAndClauses.add(new BasicDBObject("$or", l));
}
//
DBObject q = new BasicDBObject();
if (rootAndClauses.size() > 0) {
q = new BasicDBObject("$and", rootAndClauses);
}
//
return q;
}
public int count(Optional<String> searchTerm, final Optional<String> creator, final boolean isAdmin) {
GridFS gf = gridFS;
DBObject q = createQuery(searchTerm, creator, isAdmin);
return gf.getFileList(q).count();
}
public List<FileEntry> list(Optional<String> searchTerm, int offset, int limit, final Optional<String> creator, final boolean isAdmin) {
GridFS gf = gridFS;
DBObject q = createQuery(searchTerm, creator, isAdmin);
DBObject sort = new BasicDBObject("uploadDate", -1);
List<DBObject> l = gf.getFileList(q, sort)
.skip(offset).limit(limit)
.toArray();
DbObjectToGridFsDbFile f = new DbObjectToGridFsDbFile();
GridFSDBFileToFileEntry g = new GridFSDBFileToFileEntry();
return Lists.transform(l, Functions.compose(g, f));
}
public Optional<FileEntry> loadFileEntry(ObjectId id) {
GridFS gf = gridFS;
GridFSDBFile f2 = gf.find(id);
if (f2 == null) {
return Optional.absent();
} else {
return Optional.of(new GridFSDBFileToFileEntry().apply(f2));
}
}
public InputStream getInputStream(ObjectId id) {
GridFS gf = gridFS;
GridFSDBFile f = gf.find(id);
return f.getInputStream();
}
public boolean exists(ObjectId id) {
GridFS gf = gridFS;
GridFSDBFile f = gf.find(id);
return f != null;
}
public boolean delete(ObjectId id) {
GridFS gf = gridFS;
GridFSDBFile f = gf.find(id);
if (f != null) {
gf.remove(id);
return true;
} else {
return false;
}
}
public Optional<FileEntry> save(final String name, final String mime,
final String creator, final boolean privateFile, final String description,
InputStream in) {
GridFS gf = gridFS;
GridFSInputFile f = gf.createFile(in);
f.setFilename(name);
f.setContentType(mime);
//
DBObject metadata = f.getMetaData();
if (metadata == null) {
metadata = new BasicDBObject();
f.setMetaData(metadata);
}
metadata.put("creator", creator);
metadata.put("private", privateFile);
metadata.put("description", description);
//
f.save();
//
return this.loadFileEntry((ObjectId) f.getId());
}
public static class GridFSDBFileToFileEntry implements Function<GridFSDBFile, FileEntry> {
@Override
public FileEntry apply(GridFSDBFile input) {
FileEntry fe = new FileEntry();
fe.setId((ObjectId) input.getId());
fe.setName(input.getFilename());
fe.setSize(input.getLength());
fe.setMime(input.getContentType());
fe.setCtime(input.getUploadDate());
//
DBObject metadata = input.getMetaData();
if (null != metadata) {
fe.setCreator((String) metadata.get("creator"));
fe.setPrivateFile((Boolean) metadata.get("private"));
fe.setDescription((String) metadata.get("description"));
}
//
return fe;
}
}
public static class DbObjectToGridFsDbFile implements Function<DBObject, GridFSDBFile> {
@Override
public GridFSDBFile apply(DBObject input) {
return (GridFSDBFile) input;
}
}
}