From c2fd4826a05af5a271934f83af71822727be4dc1 Mon Sep 17 00:00:00 2001
From: Christoph Thelen <christoph.thelen@mni.thm.de>
Date: Wed, 15 Oct 2014 16:27:59 +0200
Subject: [PATCH] Added request methods that return session list info

---
 .../arsnova/controller/SessionController.java |  35 ++++
 .../java/de/thm/arsnova/dao/CouchDBDao.java   | 149 ++++++++++++++++--
 .../java/de/thm/arsnova/dao/IDatabaseDao.java |   7 +
 .../java/de/thm/arsnova/entities/Session.java |   2 +-
 .../de/thm/arsnova/entities/SessionInfo.java  | 115 ++++++++++++++
 .../thm/arsnova/services/ISessionService.java |   5 +
 .../thm/arsnova/services/SessionService.java  |  49 +++++-
 .../de/thm/arsnova/dao/StubDatabaseDao.java   |  19 +++
 8 files changed, 363 insertions(+), 18 deletions(-)
 create mode 100644 src/main/java/de/thm/arsnova/entities/SessionInfo.java

diff --git a/src/main/java/de/thm/arsnova/controller/SessionController.java b/src/main/java/de/thm/arsnova/controller/SessionController.java
index ee59ec72..f8b22256 100644
--- a/src/main/java/de/thm/arsnova/controller/SessionController.java
+++ b/src/main/java/de/thm/arsnova/controller/SessionController.java
@@ -43,11 +43,14 @@ import org.springframework.web.bind.annotation.RestController;
 
 import de.thm.arsnova.connector.model.Course;
 import de.thm.arsnova.entities.Session;
+import de.thm.arsnova.entities.SessionInfo;
 import de.thm.arsnova.exceptions.UnauthorizedException;
 import de.thm.arsnova.services.ISessionService;
 import de.thm.arsnova.services.IUserService;
 import de.thm.arsnova.services.SessionService.SessionNameComparator;
+import de.thm.arsnova.services.SessionService.SessionInfoNameComparator;
 import de.thm.arsnova.services.SessionService.SessionShortNameComparator;
+import de.thm.arsnova.services.SessionService.SessionInfoShortNameComparator;
 import de.thm.arsnova.web.DeprecatedApi;
 
 @RestController
@@ -154,6 +157,38 @@ public class SessionController extends AbstractController {
 		return sessions;
 	}
 
+	/**
+	 * Returns a list of my own sessions with only the necessary information like name, keyword, or counters.
+	 * @param statusOnly The flag that has to be set in order to get this shortened list.
+	 * @param response
+	 * @return
+	 */
+	@RequestMapping(value = "/", method = RequestMethod.GET, params = "statusonly=true")
+	public final List<SessionInfo> getMySessions(
+			@RequestParam(value = "visitedonly", defaultValue = "false") final boolean visitedOnly,
+			@RequestParam(value = "sortby", defaultValue = "name") final String sortby,
+			final HttpServletResponse response
+			) {
+		List<SessionInfo> sessions;
+		if (!visitedOnly) {
+			sessions = sessionService.getMySessionsInfo();
+		} else {
+			sessions = sessionService.getMyVisitedSessionsInfo();
+		}
+
+		if (sessions == null || sessions.isEmpty()) {
+			response.setStatus(HttpServletResponse.SC_NO_CONTENT);
+			return null;
+		}
+
+		if (sortby != null && sortby.equals("shortname")) {
+			Collections.sort(sessions, new SessionInfoShortNameComparator());
+		} else {
+			Collections.sort(sessions, new SessionInfoNameComparator());
+		}
+		return sessions;
+	}
+
 	@RequestMapping(value = "/{sessionkey}/lock", method = RequestMethod.POST)
 	public final Session lockSession(
 			@PathVariable final String sessionkey,
diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
index 6fcc51c6..e4152ad2 100644
--- a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
+++ b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
@@ -26,7 +26,9 @@ import java.util.AbstractMap;
 import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import net.sf.ezmorph.Morpher;
 import net.sf.ezmorph.MorpherRegistry;
@@ -35,6 +37,7 @@ import net.sf.json.JSONArray;
 import net.sf.json.JSONObject;
 import net.sf.json.util.JSONUtils;
 
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -57,6 +60,7 @@ import de.thm.arsnova.entities.LoggedIn;
 import de.thm.arsnova.entities.PossibleAnswer;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
+import de.thm.arsnova.entities.SessionInfo;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.entities.VisitedSession;
 import de.thm.arsnova.exceptions.NotFoundException;
@@ -126,6 +130,98 @@ public class CouchDBDao implements IDatabaseDao {
 		return result;
 	}
 
+	@Override
+	public final List<SessionInfo> getMySessionsInfo(final User user) {
+		final List<Session> sessions = this.getMySessions(user);
+		return getInfosForSessions(sessions);
+	}
+
+	private List<SessionInfo> getInfosForSessions(final List<Session> sessions) {
+		final ExtendedView questionCountView = new ExtendedView("skill_question/count_by_session");
+		final ExtendedView answerCountView = new ExtendedView("skill_question/count_answers_by_session");
+		final ExtendedView interposedCountView = new ExtendedView("interposed_question/count_by_session_reading");
+		final ExtendedView interposedCountUserView = new ExtendedView("interposed_question/count_by_session_reading_for_creator");
+		questionCountView.setSessionIdKeys(sessions);
+		questionCountView.setGroup(true);
+		answerCountView.setSessionIdKeys(sessions);
+		answerCountView.setGroup(true);
+		List<String> interposedQueryKeys = new ArrayList<String>();
+		for (Session s : sessions) {
+			interposedQueryKeys.add("[\"" + s.get_id() + "\",\"unread\"]");
+		}
+		try {
+			interposedCountView.setKeys(URLEncoder.encode("["+StringUtils.join(interposedQueryKeys, ",")+"]", "UTF-8"));
+		} catch (UnsupportedEncodingException e) {
+			throw new RuntimeException(e);
+		}
+		interposedCountView.setGroup(true);
+		return getSessionInfoData(sessions, questionCountView, answerCountView, interposedCountView);
+	}
+
+	private List<SessionInfo> getInfosForVisitedSessions(final List<Session> sessions, final User user) {
+		final ExtendedView questionCountView = new ExtendedView("skill_question/count_by_session");
+		final ExtendedView answerCountView = new ExtendedView("skill_question/count_answers_by_session");
+		final ExtendedView interposedCountUserView = new ExtendedView("interposed_question/count_by_session_reading_for_creator");
+		questionCountView.setSessionIdKeys(sessions);
+		questionCountView.setGroup(true);
+		answerCountView.setSessionIdKeys(sessions);
+		answerCountView.setGroup(true);
+		List<String> interposedQueryKeys = new ArrayList<String>();
+		for (Session s : sessions) {
+			interposedQueryKeys.add("[\"" + s.get_id() + "\",\"" + user.getUsername() + "\",\"unread\"]");
+		}
+		try {
+			interposedCountUserView.setKeys(URLEncoder.encode("["+StringUtils.join(interposedQueryKeys, ",")+"]", "UTF-8"));
+		} catch (UnsupportedEncodingException e) {
+			throw new RuntimeException(e);
+		}
+		interposedCountUserView.setGroup(true);
+		return getSessionInfoData(sessions, questionCountView, answerCountView, interposedCountUserView);
+	}
+
+	private List<SessionInfo> getSessionInfoData(final List<Session> sessions,
+			final ExtendedView questionCountView,
+			final ExtendedView answerCountView,
+			final ExtendedView interposedCountView) {
+		final ViewResults questionCountViewResults = getDatabase().view(questionCountView);
+		final ViewResults answerCountViewResults = getDatabase().view(answerCountView);
+		final ViewResults interposedCountViewResults = getDatabase().view(interposedCountView);
+
+		Map<String, Integer> questionCountMap = new HashMap<String, Integer>();
+		for (final Document d : questionCountViewResults.getResults()) {
+			questionCountMap.put(d.getString("key"), d.getInt("value"));
+		}
+		Map<String, Integer> answerCountMap = new HashMap<String, Integer>();
+		for (final Document d : answerCountViewResults.getResults()) {
+			answerCountMap.put(d.getString("key"), d.getInt("value"));
+		}
+		Map<String, Integer> interposedCountMap = new HashMap<String, Integer>();
+		for (final Document d : interposedCountViewResults.getResults()) {
+			interposedCountMap.put(d.getJSONArray("key").getString(0), d.getInt("value"));
+		}
+		List<SessionInfo> sessionInfos = new ArrayList<SessionInfo>();
+		for (Session session : sessions) {
+			int numQuestions = 0;
+			int numAnswers = 0;
+			int numInterposed = 0;
+			if (questionCountMap.containsKey(session.get_id())) {
+				numQuestions = questionCountMap.get(session.get_id());
+			}
+			if (answerCountMap.containsKey(session.get_id())) {
+				numAnswers = answerCountMap.get(session.get_id());
+			}
+			if (interposedCountMap.containsKey(session.get_id())) {
+				numInterposed = interposedCountMap.get(session.get_id());
+			}
+			SessionInfo info = new SessionInfo(session);
+			info.setNumQuestions(numQuestions);
+			info.setNumAnswers(numAnswers);
+			info.setNumInterposed(numInterposed);
+			sessionInfos.add(info);
+		}
+		return sessionInfos;
+	}
+
 	@Override
 	public final List<Question> getSkillQuestions(final User user, final Session session) {
 		String viewName;
@@ -885,22 +981,22 @@ public class CouchDBDao implements IDatabaseDao {
 				allSessions.addAll(visitedSessions);
 			}
 		}
-		// Do these sessions still exist?
+		// Filter sessions that don't exist anymore, also filter my own sessions
 		final List<Session> result = new ArrayList<Session>();
-		final List<Session> deletedSessions = new ArrayList<Session>();
+		final List<Session> filteredSessions = new ArrayList<Session>();
 		for (final Session s : allSessions) {
 			try {
 				final Session session = getSessionFromKeyword(s.getKeyword());
-				if (session != null) {
+				if (session != null && !session.isCreator(user)) {
 					result.add(session);
 				} else {
-					deletedSessions.add(s);
+					filteredSessions.add(s);
 				}
 			} catch (final NotFoundException e) {
-				deletedSessions.add(s);
+				filteredSessions.add(s);
 			}
 		}
-		if (deletedSessions.isEmpty()) {
+		if (filteredSessions.isEmpty()) {
 			return result;
 		}
 		// Update document to remove sessions that don't exist anymore
@@ -928,6 +1024,12 @@ public class CouchDBDao implements IDatabaseDao {
 		return result;
 	}
 
+	@Override
+	public List<SessionInfo> getMyVisitedSessionsInfo(final User user) {
+		List<Session> sessions = this.getMyVisitedSessions(user);
+		return this.getInfosForVisitedSessions(sessions, user);
+	}
+
 	@Override
 	public Answer saveAnswer(final Answer answer, final User user) {
 		try {
@@ -1007,6 +1109,12 @@ public class CouchDBDao implements IDatabaseDao {
 		return result;
 	}
 
+	@Override
+	public List<SessionInfo> getCourseSessionsInfo(final List<Course> courses) {
+		List<Session> sessions = this.getCourseSessions(courses);
+		return getInfosForSessions(sessions);
+	}
+
 	private static class ExtendedView extends View {
 
 		private String keys;
@@ -1020,18 +1128,30 @@ public class CouchDBDao implements IDatabaseDao {
 		}
 
 		public void setCourseIdKeys(final List<Course> courses) {
-			if (courses.isEmpty()) {
+			List<String> courseIds = new ArrayList<String>();
+			for (Course c : courses) {
+				courseIds.add(c.getId());
+			}
+			setKeyList(courseIds);
+		}
+
+		public void setSessionIdKeys(final List<Session> sessions) {
+			List<String> sessionIds = new ArrayList<String>();
+			for (Session s : sessions) {
+				sessionIds.add(s.get_id());
+			}
+			setKeyList(sessionIds);
+		}
+
+		public void setKeyList(final List<String> keylist) {
+			if (keylist.isEmpty()) {
 				keys = "[]";
 				return;
 			}
 
 			final StringBuilder sb = new StringBuilder();
-			sb.append("[");
-			for (int i = 0; i < courses.size() - 1; i++) {
-				sb.append("\"" + courses.get(i).getId() + "\",");
-			}
-			sb.append("\"" + courses.get(courses.size() - 1).getId() + "\"");
-			sb.append("]");
+			// generates: ["<key>","<key>","<key>",...]
+			sb.append("[\"" + StringUtils.join(keylist, "\",\"") + "\"]");
 			try {
 				setKeys(URLEncoder.encode(sb.toString(), "UTF-8"));
 			} catch (final UnsupportedEncodingException e) {
@@ -1046,10 +1166,9 @@ public class CouchDBDao implements IDatabaseDao {
 				query.append(super.getQueryString());
 			}
 			if (keys != null) {
-				if (query.toString().isEmpty()) {
+				if (!query.toString().isEmpty()) {
 					query.append("&");
 				}
-
 				query.append("keys=" + keys);
 			}
 
diff --git a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
index 6287c0b2..84b9e16f 100644
--- a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
+++ b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
@@ -30,6 +30,7 @@ import de.thm.arsnova.entities.InterposedReadingCount;
 import de.thm.arsnova.entities.LoggedIn;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
+import de.thm.arsnova.entities.SessionInfo;
 import de.thm.arsnova.entities.User;
 
 public interface IDatabaseDao {
@@ -170,4 +171,10 @@ public interface IDatabaseDao {
 	int getLearningProgress(Session session);
 
 	SimpleEntry<Integer, Integer> getMyLearningProgress(Session session, User user);
+
+	List<SessionInfo> getMySessionsInfo(User user);
+
+	List<SessionInfo> getCourseSessionsInfo(List<Course> myCourses);
+
+	List<SessionInfo> getMyVisitedSessionsInfo(User currentUser);
 }
diff --git a/src/main/java/de/thm/arsnova/entities/Session.java b/src/main/java/de/thm/arsnova/entities/Session.java
index ff44e399..3e62ed48 100644
--- a/src/main/java/de/thm/arsnova/entities/Session.java
+++ b/src/main/java/de/thm/arsnova/entities/Session.java
@@ -148,6 +148,6 @@ public class Session implements Serializable {
 
 	@Override
 	public String toString() {
-		return "Session [keyword=" + keyword+ ", type=" + type + "]";
+		return "Session [keyword=" + keyword+ ", type=" + type + ", creator=" + creator + "]";
 	}
 }
diff --git a/src/main/java/de/thm/arsnova/entities/SessionInfo.java b/src/main/java/de/thm/arsnova/entities/SessionInfo.java
new file mode 100644
index 00000000..b1a0be9c
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/entities/SessionInfo.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2014 THM webMedia
+ *
+ * This file is part of ARSnova.
+ *
+ * ARSnova 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 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.entities;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SessionInfo {
+
+	private String name;
+	private String shortName;
+	private String keyword;
+	private boolean active;
+	private String courseType;
+	
+	private int numQuestions;
+	private int numAnswers;
+	private int numInterposed;
+	
+	public SessionInfo(Session session) {
+		this.name = session.getName();
+		this.shortName = session.getShortName();
+		this.keyword = session.getKeyword();
+		this.active = session.isActive();
+		this.courseType = session.getCourseType();
+	}
+	
+	public static List<SessionInfo> fromSessionList(List<Session> sessions) {
+		List<SessionInfo> infos = new ArrayList<SessionInfo>();
+		for (Session s : sessions) {
+			infos.add(new SessionInfo(s));
+		}
+		return infos;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getShortName() {
+		return shortName;
+	}
+
+	public void setShortName(String shortName) {
+		this.shortName = shortName;
+	}
+
+	public String getKeyword() {
+		return keyword;
+	}
+
+	public void setKeyword(String keyword) {
+		this.keyword = keyword;
+	}
+
+	public boolean isActive() {
+		return active;
+	}
+
+	public void setActive(boolean active) {
+		this.active = active;
+	}
+
+	public String getCourseType() {
+		return courseType;
+	}
+
+	public void setCourseType(String courseType) {
+		this.courseType = courseType;
+	}
+
+	public int getNumQuestions() {
+		return numQuestions;
+	}
+
+	public void setNumQuestions(int numQuestions) {
+		this.numQuestions = numQuestions;
+	}
+
+	public int getNumAnswers() {
+		return numAnswers;
+	}
+
+	public void setNumAnswers(int numAnswers) {
+		this.numAnswers = numAnswers;
+	}
+
+	public int getNumInterposed() {
+		return numInterposed;
+	}
+
+	public void setNumInterposed(int numInterposed) {
+		this.numInterposed = numInterposed;
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/services/ISessionService.java b/src/main/java/de/thm/arsnova/services/ISessionService.java
index 86f82373..a215b57a 100644
--- a/src/main/java/de/thm/arsnova/services/ISessionService.java
+++ b/src/main/java/de/thm/arsnova/services/ISessionService.java
@@ -25,6 +25,7 @@ import java.util.UUID;
 
 import de.thm.arsnova.connector.model.Course;
 import de.thm.arsnova.entities.Session;
+import de.thm.arsnova.entities.SessionInfo;
 
 public interface ISessionService {
 	Session getSession(String keyword);
@@ -54,4 +55,8 @@ public interface ISessionService {
 	int getLearningProgress(String sessionkey);
 
 	SimpleEntry<Integer, Integer> getMyLearningProgress(String sessionkey);
+
+	List<SessionInfo> getMySessionsInfo();
+
+	List<SessionInfo> getMyVisitedSessionsInfo();
 }
diff --git a/src/main/java/de/thm/arsnova/services/SessionService.java b/src/main/java/de/thm/arsnova/services/SessionService.java
index 0af3b5fb..c25b5d64 100644
--- a/src/main/java/de/thm/arsnova/services/SessionService.java
+++ b/src/main/java/de/thm/arsnova/services/SessionService.java
@@ -34,9 +34,11 @@ import org.springframework.stereotype.Service;
 
 import de.thm.arsnova.connector.client.ConnectorClient;
 import de.thm.arsnova.connector.model.Course;
+import de.thm.arsnova.connector.model.Courses;
 import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
+import de.thm.arsnova.entities.SessionInfo;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.exceptions.ForbiddenException;
 import de.thm.arsnova.exceptions.NotFoundException;
@@ -54,6 +56,15 @@ public class SessionService implements ISessionService {
 		}
 	}
 
+	public static class SessionInfoNameComparator implements Comparator<SessionInfo>, Serializable {
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public int compare(final SessionInfo session1, final SessionInfo session2) {
+			return session1.getName().compareToIgnoreCase(session2.getName());
+		}
+	}
+
 	public static class SessionShortNameComparator implements Comparator<Session>, Serializable {
 		private static final long serialVersionUID = 1L;
 
@@ -63,6 +74,15 @@ public class SessionService implements ISessionService {
 		}
 	}
 
+	public static class SessionInfoShortNameComparator implements Comparator<SessionInfo>, Serializable {
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public int compare(final SessionInfo session1, final SessionInfo session2) {
+			return session1.getShortName().compareToIgnoreCase(session2.getShortName());
+		}
+	}
+
 	@Autowired
 	private IDatabaseDao databaseDao;
 
@@ -128,14 +148,12 @@ public class SessionService implements ISessionService {
 				throw new ForbiddenException();
 			}
 		}
-
 		if (connectorClient != null && session.isCourseSession()) {
 			final String courseid = session.getCourseId();
 			if (!connectorClient.getMembership(userService.getCurrentUser().getUsername(), courseid).isMember()) {
 				throw new ForbiddenException();
 			}
 		}
-
 		return session;
 	}
 
@@ -151,6 +169,11 @@ public class SessionService implements ISessionService {
 				connectorClient.getCourses(userService.getCurrentUser().getUsername()).getCourse()
 				);
 
+		return combineSessions(mySessions, courseSessions);
+	}
+
+	private List<Session> combineSessions(final List<Session> mySessions,
+			final List<Session> courseSessions) {
 		final Map<String, Session> allAvailableSessions = new HashMap<String, Session>();
 
 		for (final Session session : mySessions) {
@@ -162,12 +185,34 @@ public class SessionService implements ISessionService {
 		return new ArrayList<Session>(allAvailableSessions.values());
 	}
 
+	@Override
+	@PreAuthorize("isAuthenticated()")
+	public final List<SessionInfo> getMySessionsInfo() {
+		final User user = userService.getCurrentUser();
+		final List<SessionInfo> mySessions = databaseDao.getMySessionsInfo(user);
+		if (connectorClient == null) {
+			return mySessions;
+		}
+
+		final List<Course> myCourses = connectorClient.getCourses(user.getUsername()).getCourse();
+		final List<SessionInfo> courseSessions = databaseDao.getCourseSessionsInfo(myCourses);
+		// assume that my sessions and my course sessions are distinct
+		mySessions.addAll(courseSessions);
+		return mySessions;
+	}
+
 	@Override
 	@PreAuthorize("isAuthenticated()")
 	public final List<Session> getMyVisitedSessions() {
 		return databaseDao.getMyVisitedSessions(userService.getCurrentUser());
 	}
 
+	@Override
+	@PreAuthorize("isAuthenticated()")
+	public final List<SessionInfo> getMyVisitedSessionsInfo() {
+		return databaseDao.getMyVisitedSessionsInfo(userService.getCurrentUser());
+	}
+
 	@Override
 	@PreAuthorize("isAuthenticated()")
 	public final Session saveSession(final Session session) {
diff --git a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
index d279fa8d..ec428ad3 100644
--- a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
+++ b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
@@ -33,6 +33,7 @@ import de.thm.arsnova.entities.InterposedReadingCount;
 import de.thm.arsnova.entities.LoggedIn;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
+import de.thm.arsnova.entities.SessionInfo;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.exceptions.ForbiddenException;
 import de.thm.arsnova.exceptions.NoContentException;
@@ -523,4 +524,22 @@ public class StubDatabaseDao implements IDatabaseDao {
 		// TODO Auto-generated method stub
 		return null;
 	}
+
+	@Override
+	public List<SessionInfo> getMySessionsInfo(User user) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public List<SessionInfo> getCourseSessionsInfo(List<Course> myCourses) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public List<SessionInfo> getMyVisitedSessionsInfo(User currentUser) {
+		// TODO Auto-generated method stub
+		return null;
+	}
 }
-- 
GitLab