Commit 57ec03af authored by Daniel Gerhardt's avatar Daniel Gerhardt

Separate MotD persistance code and migrate it to Ektorp

parent dfa598b3
......@@ -25,12 +25,15 @@ import de.thm.arsnova.connector.client.ConnectorClient;
import de.thm.arsnova.connector.client.ConnectorClientImpl;
import de.thm.arsnova.entities.DbUser;
import de.thm.arsnova.entities.LogEntry;
import de.thm.arsnova.entities.Motd;
import de.thm.arsnova.entities.serialization.CouchDbDocumentModule;
import de.thm.arsnova.entities.serialization.CouchDbObjectMapperFactory;
import de.thm.arsnova.entities.serialization.View;
import de.thm.arsnova.persistance.LogEntryRepository;
import de.thm.arsnova.persistance.MotdRepository;
import de.thm.arsnova.persistance.UserRepository;
import de.thm.arsnova.persistance.couchdb.CouchDbLogEntryRepository;
import de.thm.arsnova.persistance.couchdb.CouchDbMotdRepository;
import de.thm.arsnova.persistance.couchdb.CouchDbUserRepository;
import de.thm.arsnova.persistance.couchdb.InitializingCouchDbConnector;
import de.thm.arsnova.socket.ARSnovaSocket;
......@@ -276,6 +279,11 @@ public class AppConfig extends WebMvcConfigurerAdapter {
return new CouchDbLogEntryRepository(LogEntry.class, couchDbConnector(), false);
}
@Bean
public MotdRepository motdRepository() throws Exception {
return new CouchDbMotdRepository(Motd.class, couchDbConnector(), false);
}
@Bean
public UserRepository userRepository() throws Exception {
return new CouchDbUserRepository(DbUser.class, couchDbConnector(), false);
......
......@@ -33,6 +33,7 @@ import de.thm.arsnova.entities.transport.ImportExportSession.ImportExportQuestio
import de.thm.arsnova.events.NewAnswerEvent;
import de.thm.arsnova.exceptions.NotFoundException;
import de.thm.arsnova.persistance.LogEntryRepository;
import de.thm.arsnova.persistance.MotdRepository;
import de.thm.arsnova.services.ISessionService;
import net.sf.ezmorph.Morpher;
import net.sf.ezmorph.MorpherRegistry;
......@@ -59,8 +60,16 @@ import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.util.*;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
......@@ -90,9 +99,12 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
@Autowired
private ISessionService sessionService;
@Autowired
private LogEntryRepository dbLogger;
@Autowired
private MotdRepository motdRepo;
private String databaseHost;
private int databasePort;
private String databaseName;
......@@ -2439,7 +2451,7 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
if (withAnswers) {
importExportSession.setSessionInfo(this.calculateSessionInfo(importExportSession, session));
}
importExportSession.setMotds(getDatabaseDao().getMotdsForSession(session.getKeyword()));
importExportSession.setMotds(motdRepository.getMotdsForSession(session.getKeyword()));
return importExportSession;
}
......@@ -2553,156 +2565,6 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
return result;
}
@Override
public List<Motd> getAdminMotds() {
final View view = new View("motd/doc_by_audience_for_global");
return getMotds(view);
}
@Override
@Cacheable(cacheNames = "motds", key = "'all'")
public List<Motd> getMotdsForAll() {
final View view = new View("motd/doc_by_audience_for_global");
return getMotds(view);
}
@Override
@Cacheable(cacheNames = "motds", key = "'loggedIn'")
public List<Motd> getMotdsForLoggedIn() {
final View view = new View("motd/doc_by_audience_for_global");
view.setKey("loggedIn");
return getMotds(view);
}
@Override
@Cacheable(cacheNames = "motds", key = "'tutors'")
public List<Motd> getMotdsForTutors() {
final View view1 = new View("motd/doc_by_audience_for_global");
final View view2 = new View("motd/doc_by_audience_for_global");
view1.setKey("loggedIn");
view2.setKey("tutors");
final List<Motd> union = new ArrayList<>();
union.addAll(getMotds(view1));
union.addAll(getMotds(view2));
return union;
}
@Override
@Cacheable(cacheNames = "motds", key = "'students'")
public List<Motd> getMotdsForStudents() {
final View view1 = new View("motd/doc_by_audience_for_global");
final View view2 = new View("motd/doc_by_audience_for_global");
view1.setKey("loggedIn");
view2.setKey("students");
final List<Motd> union = new ArrayList<>();
union.addAll(getMotds(view1));
union.addAll(getMotds(view2));
return union;
}
@Override
@Cacheable(cacheNames = "motds", key = "('session').concat(#p0)")
public List<Motd> getMotdsForSession(final String sessionkey) {
final View view = new View("motd/doc_by_sessionkey");
view.setKey(sessionkey);
return getMotds(view);
}
@Override
public List<Motd> getMotds(View view) {
final ViewResults motddocs = this.getDatabase().view(view);
List<Motd> motdlist = new ArrayList<>();
for (final Document d : motddocs.getResults()) {
Motd motd = new Motd();
motd.set_id(d.getId());
motd.set_rev(d.getJSONObject("value").getString("_rev"));
motd.setMotdkey(d.getJSONObject("value").getString("motdkey"));
Date start = new Date(Long.parseLong(d.getJSONObject("value").getString("startdate")));
motd.setStartdate(start);
Date end = new Date(Long.parseLong(d.getJSONObject("value").getString("enddate")));
motd.setEnddate(end);
motd.setTitle(d.getJSONObject("value").getString("title"));
motd.setText(d.getJSONObject("value").getString("text"));
motd.setAudience(d.getJSONObject("value").getString("audience"));
motd.setSessionkey(d.getJSONObject("value").getString("sessionkey"));
motdlist.add(motd);
}
return motdlist;
}
@Override
public Motd getMotdByKey(String key) {
final View view = new View("motd/by_motdkey");
view.setIncludeDocs(true);
view.setKey(key);
Motd motd = new Motd();
ViewResults results = this.getDatabase().view(view);
for (final Document d : results.getResults()) {
motd.set_id(d.getId());
motd.set_rev(d.getJSONObject("doc").getString("_rev"));
motd.setMotdkey(d.getJSONObject("doc").getString("motdkey"));
Date start = new Date(Long.parseLong(d.getJSONObject("doc").getString("startdate")));
motd.setStartdate(start);
Date end = new Date(Long.parseLong(d.getJSONObject("doc").getString("enddate")));
motd.setEnddate(end);
motd.setTitle(d.getJSONObject("doc").getString("title"));
motd.setText(d.getJSONObject("doc").getString("text"));
motd.setAudience(d.getJSONObject("doc").getString("audience"));
motd.setSessionkey(d.getJSONObject("doc").getString("sessionkey"));
}
return motd;
}
@Override
@CacheEvict(cacheNames = "motds", key = "#p0.audience.concat(#p0.sessionkey)")
public Motd createOrUpdateMotd(Motd motd) {
try {
String id = motd.get_id();
String rev = motd.get_rev();
Document d = new Document();
if (null != id) {
d = database.getDocument(id, rev);
} else {
motd.setMotdkey(sessionService.generateKeyword());
d.put("motdkey", motd.getMotdkey());
}
d.put("type", "motd");
d.put("startdate", String.valueOf(motd.getStartdate().getTime()));
d.put("enddate", String.valueOf(motd.getEnddate().getTime()));
d.put("title", motd.getTitle());
d.put("text", motd.getText());
d.put("audience", motd.getAudience());
d.put("sessionId", motd.getSessionId());
d.put("sessionkey", motd.getSessionkey());
database.saveDocument(d, id);
motd.set_id(d.getId());
motd.set_rev(d.getRev());
return motd;
} catch (IOException e) {
logger.error("Could not save MotD {}.", motd, e);
}
return null;
}
@Override
@CacheEvict(cacheNames = "motds", key = "#p0.audience.concat(#p0.sessionkey)")
public void deleteMotd(Motd motd) {
try {
this.deleteDocument(motd.get_id());
} catch (IOException e) {
logger.error("Could not delete MotD {}.", motd.get_id(), e);
}
}
@Override
@Cacheable(cacheNames = "motdlist", key = "#p0")
public MotdList getMotdListForUser(final String username) {
......
......@@ -17,7 +17,6 @@
*/
package de.thm.arsnova.dao;
import com.fourspaces.couchdb.View;
import de.thm.arsnova.connector.model.Course;
import de.thm.arsnova.domain.CourseScore;
import de.thm.arsnova.entities.*;
......@@ -215,26 +214,6 @@ public interface IDatabaseDao {
<T> T getObjectFromId(String documentId, Class<T> klass);
List<Motd> getAdminMotds();
List<Motd> getMotdsForAll();
List<Motd> getMotdsForLoggedIn();
List<Motd> getMotdsForTutors();
List<Motd> getMotdsForStudents();
List<Motd> getMotdsForSession(final String sessionkey);
List<Motd> getMotds(View view);
Motd getMotdByKey(String key);
Motd createOrUpdateMotd(Motd motd);
void deleteMotd(Motd motd);
MotdList getMotdListForUser(final String username);
MotdList createOrUpdateMotdList(MotdList motdlist);
......
......@@ -17,6 +17,8 @@
*/
package de.thm.arsnova.entities;
import com.fasterxml.jackson.annotation.JsonView;
import de.thm.arsnova.entities.serialization.View;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -26,7 +28,7 @@ import java.util.Date;
* This class represents a message of the day.
*/
@ApiModel(value = "motd", description = "the message of the day entity")
public class Motd {
public class Motd implements Entity {
private String motdkey; //ID
private Date startdate;
......@@ -36,95 +38,115 @@ public class Motd {
private String audience;
private String sessionId;
private String sessionkey;
private String _id;
private String _rev;
private String id;
private String rev;
@ApiModelProperty(required = true, value = "the identification string")
@JsonView({View.Persistence.class, View.Public.class})
public String getMotdkey() {
return motdkey;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setMotdkey(final String key) {
motdkey = key;
}
@ApiModelProperty(required = true, value = "startdate for showing this message (timestamp format)")
@JsonView({View.Persistence.class, View.Public.class})
public Date getStartdate() {
return startdate;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setStartdate(final Date timestamp) {
startdate = timestamp;
}
@ApiModelProperty(required = true, value = "enddate for showing this message (timestamp format)")
@JsonView({View.Persistence.class, View.Public.class})
public Date getEnddate() {
return enddate;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setEnddate(final Date timestamp) {
enddate = timestamp;
}
@ApiModelProperty(required = true, value = "tite of the message")
@JsonView({View.Persistence.class, View.Public.class})
public String getTitle() {
return title;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setTitle(final String ttitle) {
title = ttitle;
}
@ApiModelProperty(required = true, value = "text of the message")
@JsonView({View.Persistence.class, View.Public.class})
public String getText() {
return text;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setText(final String ttext) {
text = ttext;
}
@ApiModelProperty(required = true, value = "defines the target audience for this motd (one of the following: 'student', 'tutor', 'loggedIn', 'all')")
@JsonView({View.Persistence.class, View.Public.class})
public String getAudience() {
return audience;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setAudience(String a) {
audience = a;
}
@JsonView({View.Persistence.class, View.Public.class})
public String getSessionId() {
return sessionId;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
@ApiModelProperty(required = true, value = "when audience equals session, the sessionkey referes to the session the messages belong to")
@JsonView({View.Persistence.class, View.Public.class})
public String getSessionkey() {
return sessionkey;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setSessionkey(String a) {
sessionkey = a;
}
@ApiModelProperty(required = true, value = "the couchDB ID")
public String get_id() {
return _id;
@JsonView({View.Persistence.class, View.Public.class})
public String getId() {
return id;
}
public void set_id(final String id) {
_id = id;
@JsonView({View.Persistence.class, View.Public.class})
public void setId(final String id) {
this.id = id;
}
public void set_rev(final String rev) {
_rev = rev;
@JsonView({View.Persistence.class, View.Public.class})
public void setRevision(final String rev) {
this.rev = rev;
}
public String get_rev() {
return _rev;
@JsonView({View.Persistence.class, View.Public.class})
public String getRevision() {
return rev;
}
@Override
......
......@@ -23,6 +23,8 @@ import com.fasterxml.jackson.databind.util.Converter;
import de.thm.arsnova.entities.DbUser;
import de.thm.arsnova.entities.Entity;
import de.thm.arsnova.entities.LogEntry;
import de.thm.arsnova.entities.Motd;
import java.util.HashMap;
import java.util.Map;
......@@ -32,6 +34,7 @@ public class CouchDbTypeFieldConverter implements Converter<Class<? extends Enti
{
typeMapping.put(LogEntry.class, "log");
typeMapping.put(DbUser.class, "userdetails");
typeMapping.put(Motd.class, "motd");
}
@Override
......
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2017 The ARSnova Team
*
* ARSnova Backend 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.
*
* ARSnova Backend 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.thm.arsnova.persistance;
import de.thm.arsnova.entities.Motd;
import java.util.List;
public interface MotdRepository {
List<Motd> getAdminMotds();
List<Motd> getMotdsForAll();
List<Motd> getMotdsForLoggedIn();
List<Motd> getMotdsForTutors();
List<Motd> getMotdsForStudents();
List<Motd> getMotdsForSession(final String sessionkey);
Motd getMotdByKey(String key);
Motd createOrUpdateMotd(Motd motd);
boolean deleteMotd(Motd motd);
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2017 The ARSnova Team
*
* ARSnova Backend 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.
*
* ARSnova Backend 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.thm.arsnova.persistance.couchdb;
import de.thm.arsnova.entities.Motd;
import de.thm.arsnova.persistance.MotdRepository;
import de.thm.arsnova.services.ISessionService;
import org.ektorp.CouchDbConnector;
import org.ektorp.support.CouchDbRepositorySupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import java.util.ArrayList;
import java.util.List;
public class CouchDbMotdRepository extends CouchDbRepositorySupport<Motd> implements MotdRepository {
private static final Logger logger = LoggerFactory.getLogger(CouchDbMotdRepository.class);
@Autowired
private ISessionService sessionService;
public CouchDbMotdRepository(Class<Motd> type, CouchDbConnector db, boolean createIfNotExists) {
super(type, db, createIfNotExists);
}
@Override
public List<Motd> getAdminMotds() {
return getMotds("by_audience_for_global", null);
}
@Override
@Cacheable(cacheNames = "motds", key = "'all'")
public List<Motd> getMotdsForAll() {
return getMotds("by_audience_for_global", "all");
}
@Override
@Cacheable(cacheNames = "motds", key = "'loggedIn'")
public List<Motd> getMotdsForLoggedIn() {
return getMotds("by_audience_for_global", "loggedIn");
}
@Override
@Cacheable(cacheNames = "motds", key = "'tutors'")
public List<Motd> getMotdsForTutors() {
final List<Motd> union = new ArrayList<>();
union.addAll(getMotds("by_audience_for_global", "loggedIn"));
union.addAll(getMotds("by_audience_for_global", "tutors"));
return union;
}
@Override
@Cacheable(cacheNames = "motds", key = "'students'")
public List<Motd> getMotdsForStudents() {
final List<Motd> union = new ArrayList<>();
union.addAll(getMotds("by_audience_for_global", "loggedIn"));
union.addAll(getMotds("by_audience_for_global", "students"));
return union;
}
@Override
@Cacheable(cacheNames = "motds", key = "('session').concat(#p0)")
public List<Motd> getMotdsForSession(final String sessionkey) {
return getMotds("by_sessionkey", sessionkey);
}
private List<Motd> getMotds(String viewName, String key) {
return queryView(viewName, key);
}
@Override
public Motd getMotdByKey(String key) {
List<Motd> motd = queryView("by_motdkey", key);
return motd.get(0);
}
@Override
@CacheEvict(cacheNames = "motds", key = "#p0.audience.concat(#p0.sessionkey)")
public Motd createOrUpdateMotd(Motd motd) {
String id = motd.getId();
String rev = motd.getRevision();
if (null != id) {
Motd oldMotd = get(id);
motd.setMotdkey(oldMotd.getMotdkey());
update(motd);
} else {
motd.setMotdkey(sessionService.generateKeyword());
add(motd);
}
return motd;
}
@Override
@CacheEvict(cacheNames = "motds", key = "#p0.audience.concat(#p0.sessionkey)")
public boolean deleteMotd(Motd motd) {
return db.delete(motd) != null;
}
}
......@@ -23,6 +23,7 @@ import de.thm.arsnova.entities.MotdList;
import de.thm.arsnova.entities.Session;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.exceptions.BadRequestException;
import de.thm.arsnova.persistance.MotdRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
......@@ -47,6 +48,9 @@ public class MotdService implements IMotdService {
@Autowired
private ISessionService sessionService;
@Autowired
private MotdRepository motdRepository;
public void setDatabaseDao(final IDatabaseDao databaseDao) {
this.databaseDao = databaseDao;
}
......@@ -54,31 +58,31 @@ public class MotdService implements IMotdService {
@Override
@PreAuthorize("isAuthenticated()")
public Motd getMotd(final String key) {
return databaseDao.getMotdByKey(key);
return motdRepository.getMotdByKey(key);
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(1,'motd','admin')")
public List<Motd> getAdminMotds() {
return databaseDao.getAdminMotds();
return motdRepository.getAdminMotds();
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#sessionkey, 'session', 'owner')")
public List<Motd> getAllSessionMotds(final String sessionkey) {
return databaseDao.getMotdsForSession(sessionkey);
return motdRepository.getMotdsForSession(sessionkey);
}
@Override
public List<Motd> getCurrentMotds(final Date clientdate, final String audience, final String sessionkey) {
final List<Motd> motds;
switch (audience) {
case "all": motds = databaseDao.getMotdsForAll(); break;
case "loggedIn": motds = databaseDao.getMotdsForLoggedIn(); break;
case "students": motds = databaseDao.getMotdsForStudents(); break;
case "tutors": motds = databaseDao.getMotdsForTutors(); break;
case "session": motds = databaseDao.getMotdsForSession(sessionkey); break;
default: motds = databaseDao.getMotdsForAll(); break;
case "all": motds = motdRepository.getMotdsForAll(); break;
case "loggedIn": motds = motdRepository.getMotdsForLoggedIn(); break;
case "students": motds = motdRepository.getMotdsForStudents(); break;
case "tutors": motds = motdRepository.getMotdsForTutors(); break;
case "session": motds = motdRepository.getMotdsForSession(sessionkey); break;
default: motds = motdRepository.getMotdsForAll(); break;
}
return filterMotdsByDate(motds, clientdate);
}
......@@ -144,26 +148,26 @@ public class MotdService implements IMotdService {
private Motd createOrUpdateMotd(final Motd motd) {
if (motd.getMotdkey() != null) {
Motd oldMotd = databaseDao.getMotdByKey(motd.getMotdkey());
if (!(motd.get_id().equals(oldMotd.get_id()) && motd.getSessionkey().equals(oldMotd.getSessionkey())
Motd oldMotd = motdRepository.getMotdByKey(motd.getMotdkey());
if (!(motd.getId().equals(oldMotd.getId()) && motd.getSessionkey().equals(oldMotd.getSessionkey())
&& motd.getAudience().equals(oldMotd.getAudience()))) {
throw new BadRequestException();
}
}
return databaseDao.createOrUpdateMotd(motd);
return motdRepository.createOrUpdateMotd(motd);
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(1,'motd','admin')")
public void deleteMotd(Motd motd) {
databaseDao.deleteMotd(motd);
motdRepository.deleteMotd(motd);
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#sessionkey, 'session', 'owner')")
public void deleteSessionMotd(final String sessionkey, Motd motd) {
databaseDao.deleteMotd(motd);
motdRepository.deleteMotd(motd);
}
@Override
......
......@@ -632,64 +632,6 @@ public class StubDatabaseDao implements IDatabaseDao {
return null;
}
@Override
public List<Motd> getAdminMotds() {
// TODO Auto-generated method stub
return null;
}
@Override
public List<Motd> getMotdsForAll() {
// TODO Auto-generated method stub
return null;
}
@Override
public List<Motd> getMotdsForLoggedIn() {
// TODO Auto-generated method stub
return null;
}
@Override
public List<Motd>