Skip to content
Snippets Groups Projects
Commit afa8b592 authored by Julian Dehne's avatar Julian Dehne
Browse files

feat: implemented a central management class that allows for a project to be changed to a new phase

parent eadc5fbf
No related branches found
No related tags found
No related merge requests found
Showing
with 240 additions and 331 deletions
......@@ -170,6 +170,10 @@
<artifactId>commonmark</artifactId>
<version>0.11.0</version>
</dependency>
<!-- state rules -->
</dependencies>
</project>
\ No newline at end of file
......@@ -3,13 +3,24 @@ package unipotsdam.gf.config;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import unipotsdam.gf.core.management.Management;
import unipotsdam.gf.core.management.ManagementImpl;
import unipotsdam.gf.interfaces.ICommunication;
import unipotsdam.gf.core.states.PhasesImpl;
import unipotsdam.gf.interfaces.*;
import unipotsdam.gf.modules.assessment.controller.service.PeerAssessment;
import unipotsdam.gf.modules.assessment.controller.service.PeerAssessmentDummy;
import unipotsdam.gf.modules.communication.service.CommunicationDummyService;
import unipotsdam.gf.modules.journal.DummyJournalImpl;
import unipotsdam.gf.modules.journal.model.Journal;
import unipotsdam.gf.modules.journal.service.DummyJournalService;
import unipotsdam.gf.modules.peer2peerfeedback.DummyFeedback;
public class GFApplicationBinder extends AbstractBinder {
@Override
protected void configure() {
bind(CommunicationDummyService.class).to(ICommunication.class);
bind(ManagementImpl.class).to(Management.class);
bind(DummyFeedback.class).to(Feedback.class);
bind(DummyJournalImpl.class).to(IJournal.class);
bind(PeerAssessmentDummy.class).to(IPeerAssessment.class);
bind(PhasesImpl.class).to(IPhases.class);
}
}
......@@ -7,7 +7,7 @@ public class GFDatabaseConfig {
public static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
public static final String DB_URL = "jdbc:mysql://localhost";
// Database credentials
public static final String USER = "root";
public static final String PASS = "";
public static final String USER = "root2";
public static final String PASS = "voyager2";
public static final String DB_NAME = "fltrail";
}
......@@ -64,7 +64,8 @@ public class ManagementImpl implements Management {
"INSERT INTO projects (`id`, `password`, `active`, `timecreated`, `author`, "
+ "`adminPassword`, `token`, `phase`) values (?,?,?,?,?,?,?,?)";
connect.issueInsertOrDeleteStatement(mysqlRequest, project.getId(), project.getPassword(), project.isActive(),
project.getTimecreated(), project.getAuthor(), project.getAdminPassword(), token);
project.getTimecreated(), project.getAuthor(), project.getAdminPassword(), token, project.getPhase()
== null ? ProjectPhase.CourseCreation : project.getPhase());
connect.close();
}
......@@ -136,11 +137,15 @@ public class ManagementImpl implements Management {
connect.connect();
VereinfachtesResultSet vereinfachtesResultSet = connect.issueSelectStatement(query, project.getId());
while (!vereinfachtesResultSet.isLast()) {
vereinfachtesResultSet.next();
User user = getUserFromResultSet(vereinfachtesResultSet);
String token = vereinfachtesResultSet.getString("token");
user.setToken(token);
result.add(user);
Boolean next = vereinfachtesResultSet.next();
if (next) {
User user = getUserFromResultSet(vereinfachtesResultSet);
String token = vereinfachtesResultSet.getString("token");
user.setToken(token);
result.add(user);
} else {
break;
}
}
connect.close();
return result;
......
......@@ -32,7 +32,7 @@ public class Project {
this.adminPassword = adminPassword;
this.timecreated = Timestamp.valueOf(LocalDateTime.now(ZoneId.of("UTC")));
// default starting at course creation if new
this.setPhase(ProjectPhase.CourseCreationPhase);
this.setPhase(ProjectPhase.CourseCreation);
}
public String getPhase() {
......
......@@ -9,6 +9,8 @@ import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
// TODO: please move this to a view package at the top of the hierarchy as this is not part of the user package
public class Menu extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
PageContext pageContext = (PageContext) getJspContext();
......
package unipotsdam.gf.core.management.user;
import unipotsdam.gf.core.management.ManagementImpl;
import unipotsdam.gf.interfaces.ICommunication;
import unipotsdam.gf.modules.communication.service.CommunicationDummyService;
import javax.annotation.ManagedBean;
import javax.inject.Inject;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.net.URI;
import java.net.URISyntaxException;
@Path("/user")
@ManagedBean
public class UserService {
@Inject
private ICommunication communicationService;
/**
* creates a user with given credentials
*
* @param name
* @param password
* @param email
* @param isStudent
* @return
* @throws URISyntaxException
*/
// This method is called if HTML is request
@POST
@Produces(MediaType.TEXT_HTML)
@Path("/create")
public Response createUser(@FormParam("name") String name, @FormParam("password") String password,
@FormParam("email") String email, @FormParam("isStudent") String isStudent)
throws URISyntaxException {
ManagementImpl management = new ManagementImpl();
User user = new User(name, password, email, isStudent == null);
return login(true, user);
}
/**
* checks if a user exists in order to log him in
*
* @param name
* @param password
* @param email
* @return
* @throws URISyntaxException
*/
// This method is called if HTML is request
@POST
@Produces(MediaType.TEXT_HTML)
@Path("/exists")
public Response existsUser(@FormParam("name") String name, @FormParam("password") String password,
@FormParam("email") String email)
throws URISyntaxException {
ManagementImpl management = new ManagementImpl();
User user = new User(name, password, email, null);
ICommunication iCommunication = new CommunicationDummyService();
boolean isLoggedIn = iCommunication.loginUser(user);
if (isLoggedIn) {
return login(false, user);
} else {
return loginError();
}
}
/**
* if create User is true, the user is created and logged in if he does not exist
*
* @param createUser
* @param user
* @return
* @throws URISyntaxException
*/
protected Response login(boolean createUser, User user) throws URISyntaxException {
ManagementImpl management = new ManagementImpl();
if (management.exists(user)) {
if (!createUser) {
<<<<<<< HEAD
ManagementImpl m = new ManagementImpl();
String token = m.getUserToken(user);
user = m.getUser(token);
=======
boolean successfulLogin = communicationService.loginUser(user);
management.update(user);
if (!successfulLogin) {
return loginError();
}
>>>>>>> 9bbae0ff75b2597ab35479a24d47c12e7a4cc0fd
return redirectToProjectPage(user, management);
}
String existsUrl = "../register.jsp?userExists=true";
return forwardToLocation(existsUrl);
} else {
if (createUser) {
boolean isRegisteredAndLoggedIn = communicationService.registerAndLoginUser(user);
if (!isRegisteredAndLoggedIn) {
return registrationError();
}
management.create(user, null);
} else {
String existsUrl = "../index.jsp?userExists=false";
return forwardToLocation(existsUrl);
}
ManagementImpl m = new ManagementImpl();
String token = m.getUserToken(user);
user = m.getUser(token); //todo: write query to get user isStudent
return redirectToProjectPage(user, management);
}
}
private Response registrationError() throws URISyntaxException {
String existsUrl = "../register.jsp?registrationError=true";
return forwardToLocation(existsUrl);
}
private Response loginError() throws URISyntaxException {
String existsUrl = "../index.jsp?loginError=true";
return forwardToLocation(existsUrl);
}
/**
* helper function for redirecting to the right project page
*
* @param user
* @param management
* @return
* @throws URISyntaxException
*/
private Response redirectToProjectPage(User user, ManagementImpl management) throws URISyntaxException {
String successUrl;
if (user.getStudent() != null && user.getStudent()) {
successUrl = "../pages/overview-student.html?token=";
} else {
successUrl = "../pages/overview-docent.html?token=";
}
successUrl += management.getUserToken(user);
return forwardToLocation(successUrl);
}
/**
* * helper function for redirecting to a new page
*
* @param existsUrl
* @return
* @throws URISyntaxException
*/
private Response forwardToLocation(String existsUrl) throws URISyntaxException {
return Response.seeOther(new URI(existsUrl)).build();
}
}
package unipotsdam.gf.core.states;
import unipotsdam.gf.core.management.user.User;
public class DosserUploadTask extends Task {
public DosserUploadTask(User owner) {
super(owner);
}
@Override
public String getTaskMessage() {
return null;
}
@Override
protected String getTaskUrl() {
return null;
}
}
package unipotsdam.gf.core.states;
import unipotsdam.gf.core.management.user.User;
public class PeerAssessmentTask extends Task {
public PeerAssessmentTask(User owner) {
super(owner);
}
@Override
public String getTaskMessage() {
return null;
}
@Override
protected String getTaskUrl() {
return null;
}
}
package unipotsdam.gf.core.states;
import unipotsdam.gf.core.management.user.User;
public class PeerFeedbackTask extends Task {
public PeerFeedbackTask(User owner) {
super(owner);
}
@Override
public String getTaskMessage() {
// TODO implement
return null;
}
@Override
protected String getTaskUrl() {
// TODO implement
return null;
}
}
package unipotsdam.gf.core.states;
import unipotsdam.gf.core.database.mysql.MysqlConnect;
import unipotsdam.gf.core.management.project.Project;
import unipotsdam.gf.interfaces.*;
import unipotsdam.gf.view.Messages;
import javax.annotation.ManagedBean;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Created by dehne on 31.05.2018.
* This class should be used to manage changing the phases in a central location
* it has dependencies to most modules, as they are required to check the constraints
* when changing between phases
*/
@ManagedBean
public class PhasesImpl implements IPhases {
@Inject
private IPeerAssessment iPeerAssessment;
@Inject
private Feedback feedback;
@Inject
private ICommunication iCommunication;
@Inject
private IJournal iJournal;
public PhasesImpl() {
}
/**
* use this if you don't know how dependency injection works
* @param iPeerAssessment
* @param feedback
* @param iCommunication
* @param iJournal
*/
public PhasesImpl(IPeerAssessment iPeerAssessment, Feedback feedback, ICommunication iCommunication, IJournal iJournal) {
this.iPeerAssessment = iPeerAssessment;
this.feedback = feedback;
this.iCommunication = iCommunication;
this.iJournal = iJournal;
}
@Override
public void endPhase(ProjectPhase currentPhase, Project project) {
switch (currentPhase) {
case CourseCreation:
// saving the state
saveState(project,getNextPhase(currentPhase));
break;
case GroupFormation:
// inform users about the formed groups, optionally giving them a hint on what happens next
iCommunication.sendMessageToUsers(project, Messages.GroupFormation(project));
saveState(project,getNextPhase(currentPhase));
break;
case DossierFeedback:
// check if everybody has uploaded a dossier
Boolean feedbacksGiven = feedback.checkFeedbackConstraints(project);
if (!feedbacksGiven) {
feedback.assigningMissingFeedbackTasks(project);
} else {
// send a message to the users informing them about the start of the new phase
iCommunication.sendMessageToUsers(project, Messages.NewFeedbackTask(project));
saveState(project,getNextPhase(currentPhase));
}
break;
case Execution:
// check if the portfolios have been prepared for evaluation (relevant entries selected)
Boolean portfoliosReady = iJournal.getPortfoliosForEvaluationPrepared(project);
if (portfoliosReady) {
// inform users about the end of the phase
iCommunication.sendMessageToUsers(project, Messages.AssessmentPhaseStarted(project));
saveState(project,getNextPhase(currentPhase));
} else {
iJournal.assignMissingPortfolioTasks(project);
}
break;
case Assessment:
closeProject();
break;
}
}
private void closeProject() {
// TODO implement
}
ProjectPhase getNextPhase(ProjectPhase projectPhase) {
switch (projectPhase) {
case CourseCreation:
return ProjectPhase.GroupFormation;
case GroupFormation:
return ProjectPhase.DossierFeedback;
case DossierFeedback:
return ProjectPhase.Execution;
case Execution:
return ProjectPhase.Assessment;
case Assessment:
return ProjectPhase.Projectfinished;
}
return null;
}
private void saveState(Project project, ProjectPhase currentPhase) {
assert project.getId() != null;
MysqlConnect connect = new MysqlConnect();
connect.connect();
String mysqlRequest = "UPDATE `projects` SET `phase`=? WHERE id=? LIMIT 1";
connect.issueUpdateStatement(mysqlRequest, currentPhase.name(), project.getId());
connect.close();
}
}
package unipotsdam.gf.core.states;
public enum ProjectPhase {
CourseCreationPhase,
GroupFormationPhase,
DossierFeedbackPhase,
ExecutionPhase,
AssessmentPhase
CourseCreation, GroupFormation, DossierFeedback, Execution, Assessment,
Projectfinished
}
package unipotsdam.gf.core.states;
import unipotsdam.gf.core.management.user.User;
import unipotsdam.gf.interfaces.ICommunication;
import unipotsdam.gf.modules.communication.model.Message;
import javax.inject.Inject;
public class States {
@Inject
ICommunication iCommunication;
public void endPhase(ProjectPhase currentPhase) {
// TODO implement
// calculate reaction
// if no problem change phase
// if problem send message
// and start recovery process
}
private void sendProblemMessage(String message, User user) {
iCommunication.sendSingleMessage(new Message(null, message),user);
}
}
package unipotsdam.gf.core.states;
import unipotsdam.gf.core.management.user.User;
import unipotsdam.gf.interfaces.ICommunication;
import unipotsdam.gf.modules.communication.model.Message;
import javax.inject.Inject;
public abstract class Task {
@Inject
ICommunication iCommunication;
// the user who has to do the task
protected User owner;
public Task(User owner) {
this.owner = owner;
}
public abstract String getTaskMessage();
public void start() {
sendTaskMessage();
save();
}
private void save() {
String name = getClass().getName(); // this returns the runtime name of the subclass i.e. PeerAssessmentTask
String url = getTaskUrl();
}
/**
* should be a relative path like
* /dossiers/upload
* /peerfeedback/{userId}/give
* /peerassessment/{userId}/give
* or similar
*
* @return
*/
protected abstract String getTaskUrl();
public void sendTaskMessage() {
iCommunication.sendSingleMessage(new Message(null, getTaskMessage()), owner);
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}
}
package unipotsdam.gf.interfaces;
import unipotsdam.gf.core.management.project.Project;
import unipotsdam.gf.core.management.user.User;
import unipotsdam.gf.modules.peer2peerfeedback.Peer2PeerFeedback;
import java.*;
......@@ -51,4 +52,12 @@ public interface Feedback {
int countFeedback(User student);
/**
* TODO implement check in DB that everybody has given feedback
* @param project
* @return
*/
Boolean checkFeedbackConstraints(Project project);
void assigningMissingFeedbackTasks(Project project);
}
package unipotsdam.gf.interfaces;
import unipotsdam.gf.core.management.project.Project;
import unipotsdam.gf.core.management.user.User;
import unipotsdam.gf.modules.communication.model.Message;
import unipotsdam.gf.modules.communication.model.chat.ChatMessage;
......@@ -85,5 +86,9 @@ public interface ICommunication {
String getChatRoomLink(String userToken, String projectToken, String groupToken);
// TODO implement as Email or whatever
void sendSingleMessage(Message message, User user);
// TODO implement as Email or whatever
void sendMessageToUsers(Project project, String message);
}
package unipotsdam.gf.interfaces;
import unipotsdam.gf.core.management.project.Project;
import unipotsdam.gf.modules.assessment.controller.model.StudentIdentifier;
/**
......@@ -16,4 +17,16 @@ public interface IJournal {
*/
String exportJournal (StudentIdentifier student);
/**
* check if all students have prepared their portfolios to be evaluated
* @return
* @param project
*/
Boolean getPortfoliosForEvaluationPrepared(Project project);
/**
* find out, who hasn't prepared their portfolio for evaluation and send message or highlight in view
* @param project
*/
void assignMissingPortfolioTasks(Project project);
}
package unipotsdam.gf.interfaces;
import unipotsdam.gf.core.management.project.Project;
import unipotsdam.gf.core.states.ProjectPhase;
public interface IPhases {
/**
* switch from one phase to the next
* @param projectPhase
* @param project
*/
public void endPhase(ProjectPhase projectPhase, Project project);
}
......@@ -2,6 +2,7 @@ package unipotsdam.gf.modules.communication.service;
import unipotsdam.gf.config.Constants;
import unipotsdam.gf.core.management.Management;
import unipotsdam.gf.core.management.project.Project;
import unipotsdam.gf.core.management.user.User;
import unipotsdam.gf.interfaces.ICommunication;
import unipotsdam.gf.modules.communication.model.Message;
......@@ -106,6 +107,12 @@ public class CommunicationDummyService implements ICommunication {
System.out.println("sending email with message: "+ message.getMessage() + " to: "+ user.getEmail());
}
@Override
public void sendMessageToUsers(Project project, String message) {
// TODO implement as email or directed message, popup after login or whatever
System.out.println("sending email with message: "+ message + " to: "+ project.getId());
}
// TODO: remove after done implementing
// just for postman testing
public User getUser() {
......
package unipotsdam.gf.modules.journal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import unipotsdam.gf.core.management.project.Project;
import unipotsdam.gf.interfaces.IJournal;
import unipotsdam.gf.modules.assessment.controller.model.StudentIdentifier;
import unipotsdam.gf.modules.journal.service.DummyJournalService;
public class DummyJournalImpl implements IJournal {
private Logger log = LoggerFactory.getLogger(DummyJournalImpl.class);
@Override
public String exportJournal(StudentIdentifier student) {
// TODO Impl was macht das hier?
return null;
}
@Override
public Boolean getPortfoliosForEvaluationPrepared(Project project) {
log.debug("checking fake constraints for the portfolio evaluation");
return false;
}
@Override
public void assignMissingPortfolioTasks(Project project) {
log.debug("assigning fake MissingPortfolioTasks");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment