/*
* This file is part of anycook. The new internet cookbook
* Copyright (C) 2014 Jan Graßegger
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 [http://www.gnu.org/licenses/].
*/
package de.anycook.db.drafts.mongo;
import com.mongodb.client.MongoCollection;
import de.anycook.db.drafts.RecipeDraftsStore;
import de.anycook.drafts.RecipeDraft;
import de.anycook.drafts.RecipeDraftWrapper;
import de.anycook.newrecipe.DraftNumberProvider;
import org.bson.Document;
import org.bson.types.ObjectId;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* @author Jan Graßegger <jan@anycook.de>
*/
public class MongoDBRecipeDraftsStore extends Mongo implements RecipeDraftsStore, AutoCloseable {
private MongoCollection<Document> coll;
public MongoDBRecipeDraftsStore() {
super();
coll = getCollection("recipedrafts");
}
@Override
public List<RecipeDraft> getDrafts(final int user_id) throws IOException {
//language=JavaScript 1.6
String map = "function(){var percentage = 0;\n"
+ " for(var key in this) {\n"
+ " percentage++;\n"
+ " }\n"
+ " percentage/=14;\n"
+ " var out = { \n"
+ " _id : this._id,\n"
+ " percentage : percentage,\n"
+ " timestamp : this.timestamp\n"
+ " };\n"
+ " \n"
+ " if (this.name) {\n"
+ " out.name = this.name;\n"
+ " }\n"
+ " \n"
+ " if (this.description) {\n"
+ " out.description = this.description;\n"
+ " }\n"
+ " \n"
+ " if (this.image) {\n"
+ " out.image = this.image;\n"
+ " }\n"
+ " \n"
+ " emit(this._id, out);\n"
+ "}";
//language=JavaScript 1.6
String reduce = "function(key, values) {\n"
+ " return values.map(function(value) {\n"
+ " return value.value;\n"
+ " });\n"
+ "}";
Document query = getQuery(user_id);
return coll.mapReduce(map, reduce, RecipeDraftWrapper.class).filter(query)
.map(RecipeDraftWrapper::getRecipeDraft).into(new ArrayList<>());
}
@Override
public RecipeDraft getDraft(final String draft_id, final int user_id)
throws DraftNotFoundException {
final Document query = getQuery(user_id, draft_id);
final RecipeDraft draft = coll.find(query, RecipeDraft.class).iterator().tryNext();
if (draft == null) {
throw new DraftNotFoundException(draft_id, user_id);
}
return draft;
}
@Override
public int countDrafts(final int userId) {
final Document query = getQuery(userId);
return (int) coll.count(query);
}
@Override
public String newDraft(final int userId) throws SQLException {
final long time = System.currentTimeMillis();
final Document obj = new Document("userId", userId)
.append("timestamp", time);
coll.insertOne(obj);
final ObjectId id = obj.getObjectId("_id");
DraftNumberProvider.INSTANCE.wakeUpSuspended(userId);
return id.toString();
}
@Override
public void updateDraft(final String id, final RecipeDraft data) {
update(data, data.getUserId(), id);
}
private void update(final RecipeDraft updateObj, final int user_id, final String draft_id) {
final Document query = getQuery(user_id, draft_id);
final Document set = new Document("$set", updateObj);
coll.findOneAndUpdate(query, set);
}
@Override
public void deleteDraft(final String id, final int userId) throws SQLException {
final Document query = getQuery(userId, id);
coll.findOneAndDelete(query);
DraftNumberProvider.INSTANCE.wakeUpSuspended(userId);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
coll = null;
}
private static Document getQuery(int userId) {
return new Document("userId", userId);
}
private static Document getQuery(int userId, String draftId) {
return new Document("_id", new ObjectId(draftId)).append("userId", userId);
}
}