Merge branch 'develop' into projectIdeaSubmission

* develop:
  Fixed preferred supervisor database storage
  added functionality to order checklistTemplates and they are now added in the correct order
  Added so that only available supervisors are forwarded to matching strategy
  Changed so that availabily uses real object
  Added matcher and matching strategy
This commit is contained in:
Emil Siverhall 2011-12-04 19:47:52 +01:00
commit c32b77997e
20 changed files with 798 additions and 63 deletions

View File

@ -1 +1,2 @@
ALTER TABLE `worker_data` ADD `lastSuccessfulRun` DATETIME NOT NULL DEFAULT '2011-11-28 13:33:37' AFTER `lastRun`;
ALTER TABLE `worker_data` ADD `lastSuccessfulRun` DATETIME NOT NULL DEFAULT '2011-11-28 13:33:37' AFTER `lastRun`;
ALTER TABLE `checklist_template` ADD `templateNumber` INT NOT NULL DEFAULT '999'

View File

@ -34,12 +34,13 @@
<th class="rounded-left-top">Name</th>
<th>Categories</th>
<th>Questions</th>
<th></th>
<th class="rounded-right-top">Delete</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="4" class="rounded-foot">&nbsp;</td>
<td colspan="5" class="rounded-foot">&nbsp;</td>
</tr>
</tfoot>
<tbody>
@ -48,6 +49,15 @@
wicket:id="templateName"></span></a></span></td>
<td><span wicket:id="categories"></span></td>
<td><span wicket:id="templateOuestion"></span></td>
<td><div class="split-row">
<a href="#" wicket:id="moveUpLink"><img
wicket:id="upArrowImage" /></a>
</div>
<div class="split-row">
<a href="#" wicket:id="moveDownLink"><img
wicket:id="downArrowImage" alt="Down" title="Down" /></a>
</div>
</td>
<td><a href="#" wicket:id="delete">
<img wicket:id="deleteIcon" alt="Delete" title="Delete" />
</a></td>

View File

@ -58,8 +58,11 @@ public class AdminListCheckListTemplatePanel extends Panel{
private Form<CheckListTemplate> form;
private TextField<String> nameField;
private AjaxLink newLink;
private AjaxLink<Void> newLink;
private WebMarkupContainer container;
private int NO_NUMBER = 999;
private ListView<CheckListTemplate> checkListTemplates;
private int nrOfTemplates = 0;
private static final long serialVersionUID = 1L;
@ -78,6 +81,8 @@ public class AdminListCheckListTemplatePanel extends Panel{
dialog.add(tmpform);
add(dialog);
templateNumberSetup();
newLink = new AjaxLink<Void>("newLink") {
@ -118,6 +123,8 @@ public class AdminListCheckListTemplatePanel extends Panel{
tmp.setName(nameField.getModelObject());
tmp.setCategories(categoryPanel.getSelectedCategories());
List<CheckListTemplate> templates = checkListTemplateDao.findTemplates();
tmp.setTemplateNumber(templates.size()-1);
checkListTemplateDao.save(tmp);
target.addComponent(container);
dialog.close(target);
@ -144,16 +151,6 @@ public class AdminListCheckListTemplatePanel extends Panel{
};
add(newLink);
final IModel<List<CheckListTemplate>> checkListTemplateModel = new LoadableDetachableModel<List<CheckListTemplate>>() {
@ -161,13 +158,15 @@ public class AdminListCheckListTemplatePanel extends Panel{
@Override
protected List<CheckListTemplate> load() {
return checkListTemplateDao.findAll();
List<CheckListTemplate> templates = checkListTemplateDao.findTemplates();
nrOfTemplates = templates.size();
return templates;
}
};
container = new WebMarkupContainer("container");
container.setOutputMarkupId(true);
ListView<CheckListTemplate> checkListTemplates = new ListView<CheckListTemplate>("checkListTemplates", checkListTemplateModel) {
checkListTemplates = new ListView<CheckListTemplate>("checkListTemplates", checkListTemplateModel) {
private static final long serialVersionUID = 1L;
@ -183,6 +182,38 @@ public class AdminListCheckListTemplatePanel extends Panel{
MultiLineLabel categoriesLabel = new MultiLineLabel("categories", new Model<String>(labelMsg));
AjaxLink<Void> moveUpLink = new AjaxLink<Void>("moveUpLink") {
int itemPos = item.getModelObject().getTemplateNumber();
private static final long serialVersionUID = 1529565679210978293L;
@Override
public void onClick(AjaxRequestTarget target) {
swapTemplates(itemPos, itemPos - 1);
target.addComponent(container);
}
};
AjaxLink<Void> moveDownLink = new AjaxLink<Void>("moveDownLink") {
int itemPos = item.getModelObject().getTemplateNumber();
private static final long serialVersionUID = 1529565679210978293L;
@Override
public void onClick(AjaxRequestTarget target) {
swapTemplates(itemPos, itemPos + 1);
target.addComponent(container);
}
};
moveUpLink.add(new ImageObject("upArrowImage", ImageObject.THIRTYTWO + ImageObject.UPARROW));
moveDownLink.add(new ImageObject("downArrowImage", ImageObject.THIRTYTWO + ImageObject.DOWNARROW));
item.add(moveUpLink);
item.add(moveDownLink);
if(item.getModelObject().getTemplateNumber() == 0){
moveUpLink.setVisible(false);
}else if(item.getModelObject().getTemplateNumber() == (nrOfTemplates-1)){
moveDownLink.setVisible(false);
}
AjaxLink<Void> deleteLink = new AjaxLink<Void>("delete") {
@ -296,6 +327,28 @@ public class AdminListCheckListTemplatePanel extends Panel{
return labelMsg;
}
private void templateNumberSetup(){
List<CheckListTemplate> templates = checkListTemplateDao.findAll();
for(CheckListTemplate t : templates){
if(t.getTemplateNumber() == NO_NUMBER){
t.setTemplateNumber(templates.indexOf(t));
t = checkListTemplateDao.save(t);
}
}
}
private void swapTemplates(int index1, int index2){
List<CheckListTemplate> templates = checkListTemplateDao.findTemplates();
if(index1 >= 0 && index2 < templates.size()){
templates.get(index1).setTemplateNumber(index2);
templates.get(index2).setTemplateNumber(index1);
checkListTemplateDao.save(templates.get(index1));
checkListTemplateDao.save(templates.get(index2));
System.out.println("Swapped " + index1 + " and " + index2);
checkListTemplates.detach();
}
}
}

View File

@ -3,8 +3,13 @@
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<body>
<wicket:panel>
<a href=# wicket:id="addAllLink">Add Empirical Research Checklists</a>
<a href="#" wicket:id="infoLink"><img src="images/icons/24/help2.png" alt="Partner info"/></a>
<div wicket:id="listTemplatePanel"></div>
<a href=# wicket:id="addAllLink">Add all</a>
<div wicket:id="dialog">
<div class="info-box rounded-box last span-10" wicket:id="info"></div>
</div>
</wicket:panel>
</body>
</html>
</html>

View File

@ -1,27 +1,14 @@
package se.su.dsv.scipro.checklists.panels;
import java.util.List;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.EmptyPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.odlabs.wiquery.ui.dialog.Dialog;
import se.su.dsv.scipro.data.dao.interfaces.CheckListDao;
import se.su.dsv.scipro.data.dao.interfaces.CheckListTemplateDao;
import se.su.dsv.scipro.data.dao.interfaces.ProjectDao;
import se.su.dsv.scipro.data.dataobjects.CheckList;
import se.su.dsv.scipro.data.dataobjects.CheckListTemplate;
import se.su.dsv.scipro.data.dataobjects.Project;
import se.su.dsv.scipro.data.enums.CheckListRole;
import se.su.dsv.scipro.data.facade.ProjectFacade;
@ -40,8 +27,11 @@ public class SupervisorAddChecklistPanel extends Panel{
@SpringBean
private ProjectFacade facade;
private Dialog dialog;
public SupervisorAddChecklistPanel(String id, final PageParameters pp, final Project project) {
super(id);
dialogSetup();
AjaxLink<Void> addAllLink = new AjaxLink<Void>("addAllLink"){
@ -60,7 +50,32 @@ public class SupervisorAddChecklistPanel extends Panel{
add(new ListCheckListTemplatePanel("listTemplatePanel", pp, CheckListRole.SUPERVISOR));
add(addAllLink);
}
}
private void dialogSetup(){
dialog = new Dialog("dialog");
dialog.setModal(true);
dialog.setAutoOpen(false);
dialog.setWidth(500);
dialog.setHeight(300);
dialog.add(new Label("info", new Model<String>("test")));
add(dialog);
AjaxLink<Void> infoLink = new AjaxLink<Void>("infoLink"){
private static final long serialVersionUID = 1L;
@Override
public void onClick(AjaxRequestTarget target) {
dialog.replace(new Label("info", new Model<String>("Delete those checklists wich are not relevant for your thesis project.\n" +
"If you want other checklists then those avalible you can suggest them to thesissupport@dsv.su.se and they will be added to the pool. "+
"You can add checklists manually from the templates avalible on the right side by clicking the link.")));
target.addComponent(dialog);
dialog.setTitle("Checklist info");
dialog.open(target);
}
};
add(infoLink);
}
}

View File

@ -12,9 +12,10 @@ public interface CheckListTemplateDao extends Dao<CheckListTemplate> {
public List<CheckListTemplate> findTemplatesByCategory(String category);
public List<CheckListTemplate> findTemplates();
/* New methods */
List<CheckListTemplate> findTemplates(CheckListTemplateDao.Params params);
public List<CheckListTemplate> findTemplates(CheckListTemplateDao.Params params);
/* New methods */
long countTemplates(CheckListTemplateDao.Params params);

View File

@ -43,7 +43,8 @@ public class CheckListTemplateDaoJPAImp extends AbstractDaoJPAImp<CheckListTempl
String q = "select distinct clt " +
"from CheckListTemplate clt " +
"join clt.categories c " +
"where c.categoryName = :category";
"where c.categoryName = :category "+
"order by templateNumber";
TypedQuery<CheckListTemplate> query = em.createQuery(q, CheckListTemplate.class);
@ -58,6 +59,28 @@ public class CheckListTemplateDaoJPAImp extends AbstractDaoJPAImp<CheckListTempl
});
}
@Transactional
public List<CheckListTemplate> findTemplates() {
return getJpaTemplate().execute(new JpaCallback<List<CheckListTemplate>>() {
public List<CheckListTemplate> doInJpa(EntityManager em)
throws PersistenceException {
String q = "select clt " +
"from CheckListTemplate clt " +
"order by templateNumber";
TypedQuery<CheckListTemplate> query = em.createQuery(q, CheckListTemplate.class);
try {
return query.getResultList();
} catch (NoResultException e) {
return new ArrayList<CheckListTemplate>();
}
}
});
}
@Transactional( readOnly=true )
public List<CheckListTemplate> findTemplates(CheckListTemplateDao.Params params){
return getJpaTemplate().execute(

View File

@ -19,7 +19,7 @@ import javax.persistence.Table;
*/
@Entity
@Table(name="checklist_template")
public class CheckListTemplate extends DomainObject {
public class CheckListTemplate extends DomainObject implements Comparable<CheckListTemplate> {
private static final long serialVersionUID = 2959377496669050427L;
@ -30,6 +30,9 @@ public class CheckListTemplate extends DomainObject {
@Column(nullable=false)
private String name;
@Column
private int templateNumber;
@Lob
@ElementCollection
private List<String> questions = new ArrayList<String>(1);
@ -124,6 +127,14 @@ public class CheckListTemplate extends DomainObject {
this.categories = categories;
}
public int getTemplateNumber() {
return templateNumber;
}
public void setTemplateNumber(int templateNumber) {
this.templateNumber = templateNumber;
}
public void swapQuestions(int index1, int index2){
String index2Question = new String(questions.get(index2));
questions.set(index2, questions.get(index1));
@ -162,6 +173,13 @@ public class CheckListTemplate extends DomainObject {
return false;
}
@Override
public int compareTo(CheckListTemplate other) {
return this.templateNumber - other.templateNumber;
}
}

View File

@ -0,0 +1,61 @@
package se.su.dsv.scipro.match;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import se.su.dsv.scipro.match.dao.interfaces.ProjectIdeaDao;
import se.su.dsv.scipro.match.dao.interfaces.SupervisorDao;
import se.su.dsv.scipro.match.dataobject.ApplicationPeriod;
import se.su.dsv.scipro.match.dataobject.Availability;
import se.su.dsv.scipro.match.dataobject.Match;
import se.su.dsv.scipro.match.dataobject.ProjectIdea;
public class Matcher {
@Autowired
private SupervisorDao supervisorDao;
@Autowired
private ProjectIdeaDao projectIdeaDao;
private final MatchingStrategy matchingStrategy;
public Matcher(MatchingStrategy matchingStrategy) {
this.matchingStrategy = matchingStrategy;
}
public Result match(ApplicationPeriod applicationPeriod) {
List<Availability> supervisorAvailability =
supervisorDao.getSupervisorAvailability();
List<ProjectIdea> unmatchedProjectIdeas =
projectIdeaDao.getUnmatchedProjectIdeas();
List<Availability> supervisorAvailabilityOnlyAvailabe = new ArrayList<Availability>();
for (Availability availability : supervisorAvailability) {
if (availability.isAvailable()) {
supervisorAvailabilityOnlyAvailabe.add(availability);
}
}
return matchingStrategy.match(supervisorAvailabilityOnlyAvailabe, unmatchedProjectIdeas);
}
public static class Result {
public final List<Match> matches;
public final List<ProjectIdea> unmatched;
public Result(List<Match> matches, List<ProjectIdea> unmatched) {
this.matches = matches;
this.unmatched = unmatched;
}
@Override
public String toString() {
return "Result [matches=" + matches + ", unmatched=" + unmatched
+ "]";
}
}
}

View File

@ -0,0 +1,14 @@
package se.su.dsv.scipro.match;
import java.util.List;
import se.su.dsv.scipro.match.Matcher.Result;
import se.su.dsv.scipro.match.dataobject.Availability;
import se.su.dsv.scipro.match.dataobject.ProjectIdea;
public interface MatchingStrategy {
Result match(List<Availability> supervisorAvailability,
List<ProjectIdea> unmatchedProjectIdeas);
}

View File

@ -163,7 +163,7 @@ public class SupervisorDaoJPAImp extends AbstractDaoJPAImp<Supervisor>
private List<Availability> matchedProjectIdeas(EntityManager em) {
javax.persistence.Query query =
em.createQuery("SELECT NEW se.su.dsv.scipro.match.dataobject.Availability"
+ "(s.id, COUNT(m), pl, pi.projectClass) "
+ "(s, COUNT(m), pl, pi.projectClass) "
+ "FROM Match m JOIN m.supervisor s JOIN m.projectIdea pi JOIN s.capabilities.projectLimits pl "
+ "WHERE pi.match = m AND pi.projectClass = index(pl) AND m.status IN (:statuses) "
+ "GROUP BY s, pi.projectClass, pl, index(pl)");
@ -188,7 +188,7 @@ public class SupervisorDaoJPAImp extends AbstractDaoJPAImp<Supervisor>
private List<Availability> unmatchedProjectIdeas(EntityManager em) {
javax.persistence.Query query =
em.createQuery("SELECT NEW se.su.dsv.scipro.match.dataobject.Availability"
+ "(s.id, 0L, pl, index(pl)) "
+ "(s, 0L, pl, index(pl)) "
+ "FROM Match m RIGHT JOIN m.supervisor s JOIN s.capabilities.projectLimits pl LEFT JOIN m.projectIdea pi "
+ "WHERE m = NULL OR (pi.projectClass = index(pl) AND m.status NOT IN (:statuses))");

View File

@ -39,4 +39,32 @@ public class Author extends DomainObject {
return id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((user == null) ? 0 : user.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (getClass() != obj.getClass())
return false;
Author other = (Author) obj;
if (user == null) {
if (other.user != null)
return false;
} else if (!user.equals(other.user))
return false;
return true;
}
@Override
public String toString() {
return "Author [id=" + id + ", user=" + user + "]";
}
}

View File

@ -2,24 +2,37 @@ package se.su.dsv.scipro.match.dataobject;
import se.su.dsv.scipro.data.dataobjects.ProjectClass;
public class Availability {
private final Long supervisorId;
private final Long numMatched;
private final ProjectClass projectClass;
private final Integer numCapable;
private final Supervisor supervisor;
public Availability(Long supervisorId, Long numMatched, Integer numCapable, ProjectClass projectClass) {
this.supervisorId = supervisorId;
public Availability(Supervisor supervisor, Long numMatched, Integer numCapable, ProjectClass projectClass) {
this.supervisor = supervisor;
this.numMatched = numMatched;
this.numCapable = numCapable;
this.projectClass = projectClass;
}
public int getAvailability() {
return numCapable - numMatched.intValue();
}
public boolean isAvailable() {
return getAvailability() > 0;
}
public Supervisor getSupervisor() {
return supervisor;
}
public ProjectClass getProjectClass() {
return projectClass;
}
@Override
public String toString() {
return "Availability [supervisorId=" + supervisorId + ", numMatched="
return "Availability [supervisorId=" + supervisor + ", numMatched="
+ numMatched + ", projectClassId=" + projectClass
+ ", numCapable=" + numCapable + "]";
}
@ -37,7 +50,7 @@ public class Availability {
+ ((projectClass == null) ? 0 : projectClass.hashCode());
result =
prime * result
+ ((supervisorId == null) ? 0 : supervisorId.hashCode());
+ ((supervisor == null) ? 0 : supervisor.hashCode());
return result;
}
@ -65,10 +78,10 @@ public class Availability {
return false;
} else if (!projectClass.equals(other.projectClass))
return false;
if (supervisorId == null) {
if (other.supervisorId != null)
if (supervisor == null) {
if (other.supervisor != null)
return false;
} else if (!supervisorId.equals(other.supervisorId))
} else if (!supervisor.equals(other.supervisor))
return false;
return true;
}

View File

@ -1,5 +1,6 @@
package se.su.dsv.scipro.match.dataobject;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@ -11,8 +12,10 @@ import javax.persistence.Embeddable;
import javax.persistence.ManyToMany;
@Embeddable
public class Keywords {
public class Keywords implements Serializable {
private static final long serialVersionUID = 6019515679819483607L;
@ManyToMany(cascade = CascadeType.ALL)
private Set<Keyword> keywords = new HashSet<Keyword>(1);

View File

@ -144,8 +144,11 @@ public class Match extends DomainObject {
@Override
public String toString() {
return "Match [id=" + id + ", projectIdea=" + projectIdea.getId()
+ ", supervisor=" + supervisor.getId() + ", type=" + getType()
String projectIdeaId = projectIdea != null ? projectIdea.getId().toString() : null;
String supervisorId = supervisor != null ? supervisor.getId().toString() : null;
return "Match [id=" + id + ", projectIdea=" + projectIdeaId
+ ", supervisor=" + supervisorId + ", type=" + getType()
+ ", status=" + getStatus() + ", dateCreated=" + getDateCreated() + "]";
}

View File

@ -1,5 +1,6 @@
package se.su.dsv.scipro.match.dataobject;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@ -49,6 +50,7 @@ public class ProjectIdea extends DomainObject {
@ManyToMany
private List<Author> authors = new ArrayList<Author>();
@OneToOne
private Supervisor preferredSupervisor;
// Info about external supervisor, if having one
@ -199,6 +201,7 @@ public class ProjectIdea extends DomainObject {
if (getClass() != obj.getClass())
return false;
ProjectIdea other = (ProjectIdea) obj;
System.out.println("Authors "+ authors + " OTHER: "+ other.authors);
if (authors == null) {
if (other.authors != null)
return false;
@ -267,7 +270,10 @@ public class ProjectIdea extends DomainObject {
@Embeddable
public static class Watson {
public static class Watson implements Serializable {
private static final long serialVersionUID = 6425139094214449167L;
// Watson-box-data
@Column(nullable = false, length = 1024)
private String what = "";

View File

@ -1,5 +1,6 @@
package se.su.dsv.scipro.match.dataobject;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@ -109,7 +110,9 @@ public class Supervisor extends DomainObject {
}
public static class Capabilities {
public static class Capabilities implements Serializable {
private static final long serialVersionUID = -3561755898522270150L;
@ElementCollection
private Map<ProjectClass, Integer> projectLimits =

View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
default-autowire="byName">
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="testPersistenceUnit" />
<meta key="class" value="se.su.dsv.scipro.match.dataobject.KeyWordable"/>
</bean>
<!--
enable the configuration of transactional behavior based on
annotations
-->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="projectScheduleDao" class="se.su.dsv.scipro.data.dao.jpa.ProjectScheduleDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="userDao" class="se.su.dsv.scipro.data.dao.jpa.UserDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="userNameDao" class="se.su.dsv.scipro.data.dao.jpa.UserNameDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="projectScheduleEventDao" class="se.su.dsv.scipro.data.dao.jpa.ProjectScheduleEventDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="scheduleTemplateDao" class="se.su.dsv.scipro.data.dao.jpa.ScheduleTemplateDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="projectDao" class="se.su.dsv.scipro.data.dao.jpa.ProjectDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="roleDao" class="se.su.dsv.scipro.data.dao.jpa.RoleDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="projectClassDao" class="se.su.dsv.scipro.data.dao.jpa.ProjectClassDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="CheckListDao" class="se.su.dsv.scipro.data.dao.jpa.CheckListDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="FileDescriptionDao" class="se.su.dsv.scipro.data.dao.jpa.FileDescriptionDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="FileRepository" class="se.su.dsv.scipro.repository.FileRepositoryImpl">
</bean>
<bean id="projectScheduleFacade" class="se.su.dsv.scipro.activityplan.facade.ProjectScheduleFacade">
</bean>
<bean id="projectIdeaDao" class="se.su.dsv.scipro.match.dao.jpa.ProjectIdeaDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="applicationPeriodDao" class="se.su.dsv.scipro.match.dao.jpa.ApplicationPeriodDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="matchDao" class="se.su.dsv.scipro.match.dao.jpa.MatchDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="authorDao" class="se.su.dsv.scipro.match.dao.jpa.AuthorDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="supervisorDao" class="se.su.dsv.scipro.match.dao.jpa.SupervisorDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="keywordDao" class="se.su.dsv.scipro.match.dao.jpa.KeywordDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="keywordTypeDao" class="se.su.dsv.scipro.match.dao.jpa.KeywordTypeDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="languageDao" class="se.su.dsv.scipro.data.dao.jpa.LanguageDaoJPAImp">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>

View File

@ -0,0 +1,377 @@
package se.su.dsv.scipro.match;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import edu.emory.mathcs.backport.java.util.Arrays;
import se.su.dsv.scipro.data.dao.interfaces.LanguageDao;
import se.su.dsv.scipro.data.dao.interfaces.ProjectClassDao;
import se.su.dsv.scipro.data.dao.interfaces.RoleDao;
import se.su.dsv.scipro.data.dao.interfaces.UserDao;
import se.su.dsv.scipro.data.dao.interfaces.UsernameDao;
import se.su.dsv.scipro.data.dataobjects.Employee;
import se.su.dsv.scipro.data.dataobjects.Language;
import se.su.dsv.scipro.data.dataobjects.ProjectClass;
import se.su.dsv.scipro.data.dataobjects.Role;
import se.su.dsv.scipro.data.dataobjects.Student;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.data.dataobjects.Username;
import se.su.dsv.scipro.match.dao.interfaces.ApplicationPeriodDao;
import se.su.dsv.scipro.match.dao.interfaces.AuthorDao;
import se.su.dsv.scipro.match.dao.interfaces.KeywordTypeDao;
import se.su.dsv.scipro.match.dao.interfaces.MatchDao;
import se.su.dsv.scipro.match.dao.interfaces.ProjectIdeaDao;
import se.su.dsv.scipro.match.dao.interfaces.SupervisorDao;
import se.su.dsv.scipro.match.dataobject.ApplicationPeriod;
import se.su.dsv.scipro.match.dataobject.Author;
import se.su.dsv.scipro.match.dataobject.Availability;
import se.su.dsv.scipro.match.dataobject.Keyword;
import se.su.dsv.scipro.match.dataobject.KeywordType;
import se.su.dsv.scipro.match.dataobject.Match;
import se.su.dsv.scipro.match.dataobject.ProjectIdea;
import se.su.dsv.scipro.match.dataobject.Supervisor;
import se.su.dsv.scipro.match.Matcher.Result;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class TestMatcher {
@Autowired
private UserDao userDao;
@Autowired
private UsernameDao userNameDao;
@Autowired
private RoleDao roleDao;
@Autowired
private SupervisorDao supervisorDao;
@Autowired
private ProjectClassDao projectClassDao;
@Autowired
private ApplicationPeriodDao applicationPeriodDao;
@Autowired
private LanguageDao languageDao;
@Autowired
private KeywordTypeDao keywordTypeDao;
@Autowired
private MatchDao matchDao;
@Autowired
private AuthorDao authorDao;
@Autowired
private ProjectIdeaDao projectIdeaDao;
@Autowired
ApplicationContext applicationContext;
private User user1;
private Role role1;
private KeywordType standard;
private KeywordType other;
private Keyword key1;
private Keyword key2;
private KeywordType unit;
private Keyword key3;
private Set<Keyword> keywords;
private ProjectClass bachelor;
private ApplicationPeriod applicationPeriod;
private User user2;
private Role role2;
private ProjectClass master;
private Language swedish;
private Language english;
private HashSet<Language> allLanguages;
private HashSet<Language> swedishSet;
private User user3;
private Role role3;
private Username username1;
private Username username2;
private Username username3;
private Supervisor supervisor1;
private Supervisor supervisor2;
private Supervisor supervisor3;
private User user4;
private User student1;
private Role student1Role;
private ProjectIdea projectIdea1;
private Author student1Author;
private ProjectIdea projectIdea2;
private ProjectIdea projectIdea3;
private Matcher target;
private Match match1;
private Match match2;
private Match match3;
@Before
public void startTransaction() {
user1 = new User();
user1.setFirstName("User 1");
user1 = userDao.save(user1);
username1 = new Username();
username1.setUser(user1);
username1.setUserName("User1");
username1.setRealm("dsv");
username1 = userNameDao.save(username1);
role1 = new Employee();
role1.setUser(user1);
role1 = roleDao.save(role1);
user2 = new User();
user2.setFirstName("User 2");
user2 = userDao.save(user2);
username2 = new Username();
username2.setUser(user2);
username2.setUserName("User2");
username2.setRealm("dsv");
username2 = userNameDao.save(username2);
role2 = new Employee();
role2.setUser(user2);
role2 = roleDao.save(role2);
user3 = new User();
user3.setFirstName("Usa 3");
user3 = userDao.save(user3);
user4 = new User();
user4.setFirstName("sra 4");
user4 = userDao.save(user4);
username3 = new Username();
username3.setUser(user3);
username3.setUserName("Usa 3");
username3.setRealm("dsv");
username3 = userNameDao.save(username3);
role3 = new Employee();
role3.setUser(user3);
role3 = roleDao.save(role3);
student1 = new User();
student1.setFirstName("Student 1");
student1 = userDao.save(student1);
student1Role = new Student();
student1Role.setUser(student1);
student1Role = roleDao.save(student1Role);
student1Author = new Author();
student1Author.setUser(student1);
student1Author = authorDao.save(student1Author);
swedish = new Language("Svenska");
swedish = languageDao.save(swedish);
english = new Language("English");
english = languageDao.save(english);
allLanguages = new HashSet<Language>();
allLanguages.add(swedish);
allLanguages.add(english);
swedishSet = new HashSet<Language>();
swedishSet.add(swedish);
standard = new KeywordType("standard");
standard = keywordTypeDao.save(standard);
other = new KeywordType("other");
other = keywordTypeDao.save(other);
unit = new KeywordType("unit");
unit = keywordTypeDao.save(unit);
key1 = new Keyword("key 1", standard);
key2 = new Keyword("key 2", other);
key3 = new Keyword("key 3", unit);
keywords = new HashSet<Keyword>();
keywords.add(key1);
keywords.add(key2);
bachelor =
new ProjectClass(ProjectClass.BACHELOR, "Bachelor",
"Bachelor degree thesis project");
bachelor = projectClassDao.save(bachelor);
master =
new ProjectClass(ProjectClass.MASTER, "Master",
"Master degree thesis project");
master = projectClassDao.save(master);
applicationPeriod = new ApplicationPeriod("appl");
applicationPeriod = applicationPeriodDao.save(applicationPeriod);
supervisor1 = new Supervisor();
supervisor1.setUser(user1);
supervisor1.getCapabilities().setMaxProjects(bachelor, 1);
supervisor1 = supervisorDao.save(supervisor1);
supervisor2 = new Supervisor();
supervisor2.setUser(user2);
supervisor2.getCapabilities().setMaxProjects(bachelor, 1);
supervisor2 = supervisorDao.save(supervisor2);
supervisor3 = new Supervisor();
supervisor3.setUser(user3);
supervisor3.getCapabilities().setMaxProjects(bachelor, 1);
supervisor3 = supervisorDao.save(supervisor3);
projectIdea1 = new ProjectIdea();
projectIdea1.setTitle("Project idea 1");
projectIdea1.getAuthors().add(student1Author);
projectIdea1.setProjectClass(bachelor);
projectIdea1 = projectIdeaDao.save(projectIdea1);
projectIdea2 = new ProjectIdea();
projectIdea2.setTitle("Project idea 2");
projectIdea2.getAuthors().add(student1Author);
projectIdea2.setProjectClass(bachelor);
projectIdea2 = projectIdeaDao.save(projectIdea2);
projectIdea3 = new ProjectIdea();
projectIdea3.setTitle("Project idea 3");
projectIdea3.getAuthors().add(student1Author);
projectIdea3.setProjectClass(bachelor);
projectIdea3 = projectIdeaDao.save(projectIdea3);
target = new Matcher(new MatchAllStrategy());
applicationContext.getAutowireCapableBeanFactory().autowireBean(target);
match1 = new Match();
match1.setProjectIdea(projectIdea1);
match1.setType(Match.Type.AUTO);
match1.setStatus(Match.Status.PENDING);
match1.setSupervisor(supervisor1);
match1.setPoints(10);
match2 = new Match();
match2.setProjectIdea(projectIdea2);
match2.setType(Match.Type.AUTO);
match2.setStatus(Match.Status.PENDING);
match2.setPoints(10);
match2.setSupervisor(supervisor2);
match3 = new Match();
match3.setProjectIdea(projectIdea3);
match3.setType(Match.Type.AUTO);
match3.setStatus(Match.Status.PENDING);
match3.setPoints(10);
match3.setSupervisor(supervisor3);
}
@Test
@Transactional
@Rollback
public void testShouldMatchProjectIdeasSubmittedDuringTheApplicationPeriod()
throws Exception {
Result result = target.match(applicationPeriod);
Assert.assertEquals(Arrays
.asList(new Match[] { match1, match2, match3 }), result.matches);
Assert.assertEquals(new ArrayList<ProjectIdea>(), result.unmatched);
}
@Test
@Transactional
@Rollback
public void testShouldReturnAllProjectIdeasThatWereNotMatched()
throws Exception {
supervisor3.getCapabilities().setMaxProjects(bachelor, 0);
Result result = target.match(applicationPeriod);
Assert.assertEquals(Arrays.asList(new Match[] { match1, match2 }),
result.matches);
Assert.assertEquals(Arrays.asList(new ProjectIdea[] { projectIdea3 }),
result.unmatched);
}
private static class MatchAllStrategy implements MatchingStrategy {
@Override
public Result match(List<Availability> supervisorAvailability,
List<ProjectIdea> unmatchedProjectIdeas) {
List<ProjectIdea> unmatched = new ArrayList<ProjectIdea>();
List<Match> matches = new ArrayList<Match>();
Iterator<Availability> availabilityIterator =
supervisorAvailability.iterator();
for (ProjectIdea projectIdea : unmatchedProjectIdeas) {
if (availabilityIterator.hasNext()) {
Availability availability = availabilityIterator.next();
Match match = new Match();
match.setProjectIdea(projectIdea);
match.setStatus(Match.Status.PENDING);
match.setType(Match.Type.AUTO);
match.setSupervisor(availability.getSupervisor());
match.setPoints(10);
matches.add(match);
} else {
unmatched.add(projectIdea);
}
}
return new Result(matches, unmatched);
}
}
}

View File

@ -459,8 +459,8 @@ public class TestSupervisorDao {
List<Availability> availability = target.getSupervisorAvailability();
Assert
.assertEquals(Arrays.asList(new Availability[] {
new Availability(supervisor1.getId(), 0L, 3, bachelor),
new Availability(supervisor2.getId(), 0L, 1, bachelor)}),
new Availability(supervisor1, 0L, 3, bachelor),
new Availability(supervisor2, 0L, 1, bachelor)}),
availability);
}
@ -478,8 +478,8 @@ public class TestSupervisorDao {
List<Availability> availability = target.getSupervisorAvailability();
Assert
.assertEquals(Arrays.asList(new Availability[] {
new Availability(supervisor1.getId(), 1L, 3, bachelor),
new Availability(supervisor2.getId(), 0L, 1, bachelor)}),
new Availability(supervisor1, 1L, 3, bachelor),
new Availability(supervisor2, 0L, 1, bachelor)}),
availability);
}
@ -499,8 +499,8 @@ public class TestSupervisorDao {
List<Availability> availability = target.getSupervisorAvailability();
Assert
.assertEquals(Arrays.asList(new Availability[] {
new Availability(supervisor1.getId(), 1L, 3, bachelor),
new Availability(supervisor2.getId(), 0L, 1, bachelor)}),
new Availability(supervisor1, 1L, 3, bachelor),
new Availability(supervisor2, 0L, 1, bachelor)}),
availability);
}
@ -530,9 +530,9 @@ public class TestSupervisorDao {
List<Availability> availability = target.getSupervisorAvailability();
Assert
.assertEquals(Arrays.asList(new Availability[] {
new Availability(supervisor1.getId(), 1L, 3, bachelor),
new Availability(supervisor2.getId(), 1L, 1, bachelor),
new Availability(supervisor3.getId(), 1L, 1, bachelor)}),
new Availability(supervisor1, 1L, 3, bachelor),
new Availability(supervisor2, 1L, 1, bachelor),
new Availability(supervisor3, 1L, 1, bachelor)}),
availability);
}
@ -562,9 +562,9 @@ public class TestSupervisorDao {
List<Availability> availability = target.getSupervisorAvailability();
Assert
.assertEquals(Arrays.asList(new Availability[] {
new Availability(supervisor1.getId(), 0L, 3, bachelor),
new Availability(supervisor2.getId(), 0L, 1, bachelor),
new Availability(supervisor3.getId(), 0L, 1, bachelor)}),
new Availability(supervisor1, 0L, 3, bachelor),
new Availability(supervisor2, 0L, 1, bachelor),
new Availability(supervisor3, 0L, 1, bachelor)}),
availability);
}