public static Grade grade(int grade) {
	Grade gradeEntity = new Grade.Builder(grade, "").build();
	gradeEntity.setId(grade);
	return gradeEntity;
} public static SchoolYear schoolYearFirstTermStarted() {
	return schoolYear(-1, 1, 1, 2);
} public static SchoolYear schoolYearSecondTermEnded() {
	return schoolYear(-9, -8, -7, -6);
} public static SchoolYear schoolYearSecondTermStarted() {
	return schoolYear(-3, -2, -1, 1);
} public static Student studentInGrade(int grade) {
	Grade gradeEntity = new Grade.Builder(grade, "").build();
	gradeEntity.setId(grade);
	Student student = new Student.Builder(rInt(), rStr(), rStr(), null,
			gradeEntity).build();
	return student;
} public static TeachingMaterial teachingMaterialInBothTermsOfGrade(int grade) {
	TeachingMaterial teachingMaterial = new TeachingMaterial.Builder(
			category(), rStr(), null, todayPlusDays(-20)).fromGrade(grade)
			.fromTerm(Term.FIRST).toGrade(grade).toTerm(Term.SECOND)
			.build();
	return teachingMaterial;
} public static TeachingMaterial teachingMaterialInFirstTermOfGrade(int grade) {
	TeachingMaterial teachingMaterial = new TeachingMaterial.Builder(
			category(), rStr(), null, todayPlusDays(-20)).fromGrade(grade)
			.fromTerm(Term.FIRST).toGrade(grade).toTerm(Term.FIRST).build();
	return teachingMaterial;
} public static TeachingMaterial teachingMaterialInSecondTermOfGrade(int grade) {
	TeachingMaterial teachingMaterial = new TeachingMaterial.Builder(
			category(), rStr(), null, todayPlusDays(-20)).fromGrade(grade)
			.fromTerm(Term.SECOND).toGrade(grade).toTerm(Term.SECOND)
			.build();
	return teachingMaterial;
} public class GuiceJUnitRunner extends BlockJUnit4ClassRunner {
	private Injector injector;

	/**
	 * Specifies the Guice {@link Module} classes which should be used when
	 * injecting a JUnit test class
	 */
	@Target(ElementType.TYPE)
	@Retention(RetentionPolicy.RUNTIME)
	@Inherited
	public @interface GuiceModules {
		public Class<? extends Module>[] value();
	}

	/**
	 * Initialise {@link Runner}, configure Guice using the {@link Module}s
	 * configured in the {@link GuiceModules} annotation, inject members into
	 * test class
	 * 
	 * @param testClass
	 *            JUnit test class
	 * @throws InitializationError
	 *             thrown when an error occurs during the initialisation of
	 *             Guice modules or injection of members
	 */
	public GuiceJUnitRunner(Class<?> testClass) throws InitializationError {
		super(testClass);
		Set<Class<? extends Module>> moduleClasses = getModuleClassesFor(testClass);
		injector = createInjectorFor(moduleClasses);
	}

	@Override
	public Object createTest() throws Exception {
		Object object = super.createTest();
		injector.injectMembers(object);
		return object;
	}

	/**
	 * Creates a Guice {@link Injector} with a given {@link Set} of
	 * {@link Module} classes
	 * 
	 * @param moduleClasses
	 *            {@link Set} of {@link Module} classes
	 * @return a Guice {@link Injector} with the specified modules
	 * @throws InitializationError
	 *             thrown when an error occurs instantiating the {@link Module}
	 *             class
	 */
	private Injector createInjectorFor(
			Set<Class<? extends Module>> moduleClasses)
			throws InitializationError {
		Set<Module> modules = new HashSet<>();
		for (Class<?> moduleClass : moduleClasses) {
			try {
				modules.add((Module) moduleClass.newInstance());
			} catch (InstantiationException | IllegalAccessException e) {
				throw new InitializationError(e);
			}
		}
		return Guice.createInjector(modules);
	}

	/**
	 * Reads the {@link Module} classes configured in a {@link GuiceModules}
	 * annotation of the test class
	 * 
	 * @param testClass
	 *            class with the {@link GuiceModules} annotation
	 * @return a {@link Set} of Guice {@link Module} classes
	 * @throws InitializationError
	 *             thrown when no {@link GuiceModules} annotation is present
	 */
	private Set<Class<? extends Module>> getModuleClassesFor(Class<?> testClass)
			throws InitializationError {
		GuiceModules annotation = testClass.getAnnotation(GuiceModules.class);
		if (annotation == null)
			throw new InitializationError(
					"Missing @GuiceModules annotation for unit test '"
							+ testClass.getName() + "'");
		return new HashSet<>(Arrays.asList(annotation.value()));
	}
} public class TestModuleWithoutSingletons extends AbstractModule {

	@Override
	protected void configure() {
		install(new JpaPersistModule("testPersistModule"));
		
		bind(new TypeLiteral<DAO<BorrowedMaterial>>() {}).to(new TypeLiteral<DAOImpl<BorrowedMaterial>>() {});
		bind(new TypeLiteral<DAO<Category>>() {}).to(new TypeLiteral<DAOImpl<Category>>() {});
		bind(new TypeLiteral<DAO<Dunning>>() {}).to(new TypeLiteral<DAOImpl<Dunning>>() {});
		bind(new TypeLiteral<DAO<Grade>>() {}).to(new TypeLiteral<DAOImpl<Grade>>() {});
		bind(new TypeLiteral<DAO<Parent>>() {}).to(new TypeLiteral<DAOImpl<Parent>>() {});
		bind(new TypeLiteral<DAO<SchoolYear>>() {}).to(new TypeLiteral<DAOImpl<SchoolYear>>() {});
		bind(new TypeLiteral<DAO<Student>>() {}).to(new TypeLiteral<DAOImpl<Student>>() {});
		bind(new TypeLiteral<DAO<TeachingMaterial>>() {}).to(new TypeLiteral<DAOImpl<TeachingMaterial>>() {});
		bind(new TypeLiteral<DAO<User>>() {}).to(new TypeLiteral<DAOImpl<User>>() {});
		bind(new TypeLiteral<DAO<SettingsEntry>>() {}).to(new TypeLiteral<DAOImpl<SettingsEntry>>() {});
	}
} public interface DAO<EntityType extends Entity> {

	/**
	 * Should an event be fired?
	 */
	public enum FireUpdateEvent { YES, NO }

	/**
	 * Persist the indicated entity to database, don't fire an update event
	 * 
	 * @param entity
	 * @return the primary key
	 */
	EntityType insert(EntityType entity);

	/**
	 * Persist the indicated entity to database, fire an update event when 
	 * {@link FireUpdateEvent.YES} is passed
	 * 
	 * @param entity
	 * @param fireUpdateEvent
	 * @return the primary key
	 */
	EntityType insert(EntityType entity, FireUpdateEvent fireUpdateEvent);
	
	/**
	 * Persist the indicated entity {@link Collection} to database, don't fire an update event
	 * 
	 * @param entity
	 * @return the primary key
	 */
	Collection<EntityType> insert(Collection<EntityType> entities);
	
	/**
	 * Persist the indicated entity {@link Collection} to database, fire an update event when 
	 * {@link FireUpdateEvent.YES} is passed
	 * 
	 * @param entity
	 * @param fireUpdateEvent
	 * @return the primary key
	 */
	Collection<EntityType> insert(Collection<EntityType> entities, FireUpdateEvent fireUpdateEvent);

	/**
	 * Update indicated entity to database, don't fire an update event
	 * 
	 * @param entity
	 */
	void update(EntityType entity);

	/**
	 * Update indicated entity to database, fire an update event when 
	 * {@link FireUpdateEvent.YES} is passed
	 * 
	 * @param entity
	 * @param fireUpdateEvent
	 */
	void update(EntityType entity, FireUpdateEvent fireUpdateEvent);

	/**
	 * Update indicated entity {@link Collection} to database, don't fire an update event
	 * 
	 * @param entity
	 */
	void update(Collection<EntityType> entities);
	
	/**
	 * Update indicated entity {@link Collection} to database, fire an update event when 
	 * {@link FireUpdateEvent.YES} is passed
	 * 
	 * @param entity
	 * @param fireUpdateEvent
	 */
	void update(Collection<EntityType> entities, FireUpdateEvent fireUpdateEvent);
	
	/**
	 * Delete indicated entity from database, don't fire an update event
	 * 
	 * @param entity
	 */
	void delete(EntityType entity);

	/**
	 * Delete indicated entity from database, fire an update event when 
	 * {@link FireUpdateEvent.YES} is passed
	 * 
	 * @param entity
	 * @param fireUpdateEvent
	 */
	void delete(EntityType entity, FireUpdateEvent fireUpdateEvent);

	/**
	 * Delete indicated entity {@link Collection} from database, don't fire an update event
	 * 
	 * @param entity
	 */
	void delete(Collection<EntityType> entities);
	
	/**
	 * Delete indicated entity {@link Collection} from database, fire an update event when 
	 * {@link FireUpdateEvent.YES} is passed
	 * 
	 * @param entity
	 * @param fireUpdateEvent
	 */
	void delete(Collection<EntityType> entities, FireUpdateEvent fireUpdateEvent);
	
	/**
	 * Return the entity class
	 * 
	 * @return entity
	 */
	Class<EntityType> getEntityClass();

	/**
	 * Get the entity manager
	 * 
	 * @return entity
	 */
	EntityManager getEntityManager();

	/**
	 * Retrieve an object using indicated ID
	 * 
	 * @param id
	 * @return entity
	 */
	EntityType find(final Object id);

	/**
	 * Retrieve all entities of the type indicated by the {@link DAO}
	 * 
	 * @return {@link Collection} of entities
	 */
	List<EntityType> findAll();

	/**
	 * Retrieve all entities of the type indicated by the {@link DAO} with the
	 * given {@link Criteria}
	 * 
	 * @param criteriaArray
	 *            - {@link Criterion}s, separated by commas
	 * @return {@link Collection} of entities
	 */
	List<EntityType> findAllWithCriteria(Criterion... criteriaArray);

	/**
	 * Retrieve all entities of the type indicated by the {@link DAO} with the
	 * given {@link Criteria} in the given {@link Order}
	 * 
	 * @param order
	 * 			  - {@link Order}
	 * @param criteriaArray
	 *            - {@link Criterion}s, separated by commas
	 * @return {@link Collection} of entities
	 */
	List<EntityType> findAllWithCriteria(Order order, Criterion... criteriaArray);
	
	/**
	 * Retrieve <b>a single entity</b> of the type indicated by the {@link DAO}
	 * with the given {@link Criteria}. Only use this method when you are sure
	 * there is only one entity retrieved from the database - this just frees
	 * you from the hassle of getting the first and only element out of a
	 * {@link Collection}
	 * 
	 * @param criteriaArray
	 *            - {@link Criterion}s, separated by commas
	 * @return <b>a single entity</b> if the amount of entities
	 *         found in the database is greater than 0, otherwise <i>null</i>
	 */
	EntityType findSingleWithCriteria(Criterion... criteriaArray);
	
	/**
	 * Retrieve <b>a single entity</b> of the type indicated by the {@link DAO}
	 * with the given {@link Criteria} in the given {@link Order}. 
	 * Only use this method when you are sure
	 * there is only one entity retrieved from the database - this just frees
	 * you from the hassle of getting the first and only element out of a
	 * {@link Collection}
	 * 
	 * @param order
	 * 			  - {@link Order}
	 * @param criteriaArray
	 *            - {@link Criterion}s, separated by commas
	 * @return <b>a single entity</b> if the amount of entities
	 *         found in the database is greater than 0, otherwise <i>null</i>
	 */
	EntityType findSingleWithCriteria(Order order, Criterion... criteriaArray);
	
	
	/**
	 * Fire an update event
	 */
	void fireUpdateEvent();
} @Entity
@Table(name="borrowedMaterial")
public class BorrowedMaterial implements de.dhbw.humbuch.model.entity.Entity, Serializable, Comparable<BorrowedMaterial> {
	private static final long serialVersionUID = -7956138735111492455L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;
	
	@ManyToOne(fetch=FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
	@JoinColumn(name="studentId", referencedColumnName="id")
	private Student student;
	
	@ManyToOne(fetch=FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
	@JoinColumn(name="teachingMaterialId", referencedColumnName="id")
	private TeachingMaterial teachingMaterial;
	
	private Date borrowFrom;
	private Date borrowUntil;
	private Date returnDate;
	private boolean received;
	
	/**
	 * Required by Hibernate.<p>
	 * Use the {@link Builder} instead.
	 * 
	 * @see Builder
	 */
	@Deprecated
	public BorrowedMaterial() {}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Student getStudent() {
		return student;
	}

	public void setStudent(Student student) {
		this.student = student;
	}

	public TeachingMaterial getTeachingMaterial() {
		return teachingMaterial;
	}

	public void setTeachingMaterial(TeachingMaterial teachingMaterial) {
		this.teachingMaterial = teachingMaterial;
	}

	public Date getBorrowFrom() {
		return borrowFrom;
	}

	public void setBorrowFrom(Date borrowFrom) {
		this.borrowFrom = borrowFrom;
	}

	public Date getBorrowUntil() {
		return borrowUntil;
	}

	public void setBorrowUntil(Date borrowUntil) {
		this.borrowUntil = borrowUntil;
	}

	public Date getReturnDate() {
		return returnDate;
	}

	public void setReturnDate(Date returnDate) {
		this.returnDate = returnDate;
	}

	public boolean isReceived() {
		return received;
	}
	
	public boolean isReturned() {
		return getReturnDate() != null ? true : false;
	}
	
	public void setReceived(boolean received) {
		this.received = received;
	}

	public static class Builder {
		private final Student student;
		private final TeachingMaterial teachingMaterial;
		private final Date borrowFrom;
		
		private Date borrowUntil;
		private Date returnDate;
		private boolean received;
		
		public Builder(Student student, TeachingMaterial teachingMaterial, Date borrowFrom) {
			this.student = student;
			this.teachingMaterial = teachingMaterial;
			this.borrowFrom = borrowFrom;
		}
		
		public Builder borrowUntil(Date borrowUntil) {
			this.borrowUntil = borrowUntil;
			return this;
		}
		
		public Builder returnDate(Date returnDate) {
			this.returnDate = returnDate;
			return this;
		}
		
		public Builder received(boolean received) {
			this.received = received;
			return this;
		}
		
		public BorrowedMaterial build() {
			return new BorrowedMaterial(this);
		}
	}
	
	private BorrowedMaterial(Builder builder) {
		this.student = builder.student;
		this.teachingMaterial = builder.teachingMaterial;
		this.borrowFrom = builder.borrowFrom;
		
		this.borrowUntil = builder.borrowUntil;
		this.returnDate = builder.returnDate;
		this.received = builder.received;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof BorrowedMaterial))
			return false;
		BorrowedMaterial other = (BorrowedMaterial) obj;
		if (getId() != other.getId())
			return false;
		return true;
	}

	@Override
	public int compareTo(BorrowedMaterial o) {
		int compareResult = getTeachingMaterial().compareTo(o.getTeachingMaterial());
		if(compareResult != 0) {
			return compareResult;
		}
		
		return Integer.compare(hashCode(), o.hashCode());
	}
	
} @Entity
@Table(name="grade")
public class Grade implements de.dhbw.humbuch.model.entity.Entity, Serializable, Comparable<Grade> {
	private static final long serialVersionUID = 227472334995076701L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;
	
	private int grade;
	
	@Column(name="suffix")
	private String suffix;
	
	private String teacher;
	
	@OneToMany(mappedBy="grade")
	private List<Student> students = new ArrayList<>();

	/**
	 * Required by Hibernate.<p>
	 * Use the {@link Builder} instead.
	 * 
	 * @see Builder
	 */
	@Deprecated
	public Grade() {}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getGrade() {
		return grade;
	}

	public void setGrade(int grade) {
		this.grade = grade;
	}

	public String getSuffix() {
		return suffix;
	}

	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}

	public List<Student> getStudents() {
		return students;
	}

	public void setStudents(List<Student> students) {
		this.students = students;
	}

	public String getTeacher() {
		return teacher;
	}

	public void setTeacher(String teacher) {
		this.teacher = teacher;
	}
	
	public static class Builder {
		private final int grade;
		private final String suffix;
		
		private String teacher;
		
		public Builder(String gradeString){
			String[] splittedString = splitBetweenCharsAndDigits(gradeString);
			this.grade = Integer.parseInt(splittedString[0]);
			this.suffix = splittedString[1];
		}
		
		public Builder(int grade, String suffix) {
			this.grade = grade;
			this.suffix = suffix;
		}
		
		public Builder teacher(String teacher) {
			this.teacher = teacher;
			return this;
		}
		
		public Grade build() {
			return new Grade(this);
		}
		
		private static String[] splitBetweenCharsAndDigits(String str){	
			return str.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
		}
	}
	
	private Grade(Builder builder) {
		grade = builder.grade;
		suffix = builder.suffix;
		
		teacher = builder.teacher;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Grade))
			return false;
		Grade other = (Grade) obj;
		if (getId() != other.getId())
			return false;
		return true;
	}

	@Override
	public String toString() {
		return grade + suffix;
	}

	@Override
	public int compareTo(Grade o) {
		int compareResult = Integer.compare(getGrade(), o.getGrade());
		if(compareResult != 0) {
			return compareResult;
		}
		
		compareResult = getSuffix().compareTo(o.getSuffix());
		if(compareResult != 0) {
			return compareResult;
		}
		
		return Integer.compare(hashCode(), o.hashCode());
	}
	
} @Entity
@Table(name="schoolYear")
public class SchoolYear implements de.dhbw.humbuch.model.entity.Entity, Serializable, Comparable<SchoolYear> {
	private static final long serialVersionUID = -3752454317452902743L;

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private int id;
	
	private String year;
	private Date fromDate;
	private Date toDate;
	private Date endFirstTerm;
	private Date beginSecondTerm;
	
	/**
	 * Required by Hibernate.<p>
	 * Use the {@link Builder} instead.
	 * 
	 * @see Builder
	 */
	@Deprecated
	public SchoolYear() {}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getYear() {
		return year;
	}

	public void setYear(String year) {
		this.year = year;
	}

	public Date getFromDate() {
		return fromDate;
	}

	public void setFromDate(Date fromDate) {
		this.fromDate = fromDate;
	}

	public Date getToDate() {
		return toDate;
	}

	public void setToDate(Date toDate) {
		this.toDate = toDate;
	}

	public Date getEndFirstTerm() {
		return endFirstTerm;
	}

	public void setEndFirstTerm(Date endFirstTerm) {
		this.endFirstTerm = endFirstTerm;
	}

	public Date getBeginSecondTerm() {
		return beginSecondTerm;
	}

	public void setBeginSecondTerm(Date beginSecondTerm) {
		this.beginSecondTerm = beginSecondTerm;
	}
	
	public Date getEndOf(Term term) {
		return term == Term.FIRST ? getEndFirstTerm() : getToDate();
	}
	
	public Term getRecentlyActiveTerm() {
		return getBeginSecondTerm().after(new Date()) ? Term.FIRST : Term.SECOND;
	}
	
	public boolean isActive() {
		Date today = new Date();
		return getFromDate().before(today) && getToDate().after(today) ? true : false;
	}
	
	public enum Term {
		FIRST("1. Halbjahr"),
		SECOND("2. Halbjahr");
		
		private String value;
		
		private Term(String value) {
			this.value = value;
		}
		
		@Override
		public String toString() {
			return value;
		}
	}
	
	public static class Builder {
		private final String year;
		private final Date fromDate;
		private final Date toDate;
		
		private Date endFirstTerm;
		private Date beginSecondTerm;
		
		public Builder(String year, Date fromDate, Date toDate) {
			this.year = year;
			this.fromDate = fromDate;
			this.toDate = toDate;
		}
		
		public Builder endFirstTerm(Date endFirstTerm) {
			this.endFirstTerm = endFirstTerm;
			return this;
		}
		
		public Builder beginSecondTerm(Date beginSecondTerm) {
			this.beginSecondTerm = beginSecondTerm;
			return this;
		}
		
		public SchoolYear build() {
			return new SchoolYear(this);
		}
	}
	
	private SchoolYear(Builder builder) {
		this.year = builder.year;
		this.fromDate = builder.fromDate;
		this.toDate = builder.toDate;

		this.endFirstTerm = builder.endFirstTerm;
		this.beginSecondTerm = builder.beginSecondTerm;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof SchoolYear))
			return false;
		SchoolYear other = (SchoolYear) obj;
		if (getId() != other.getId())
			return false;
		return true;
	}

	@Override
	public int compareTo(SchoolYear o) {
		int compareResult = getFromDate().compareTo(o.getFromDate());
		if(compareResult != 0) {
			return compareResult;
		}
		
		return Integer.compare(hashCode(), o.hashCode());
	}
	
} @Entity
@Table(name="student")
public class Student implements de.dhbw.humbuch.model.entity.Entity, Serializable, Comparable<Student> {
	private static final long serialVersionUID = -3020872456290703528L;

	@Id
	private int id;
	
	@ManyToOne(fetch=FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
	@JoinColumn(name="gradeId", referencedColumnName="id")
	private Grade grade;
	private String lastname;
	private String firstname;
	private Date birthday;
	private String gender;
	private boolean leavingSchool;
	
	@OneToMany(mappedBy="student", fetch=FetchType.LAZY)
	private List<BorrowedMaterial> borrowedMaterials = new ArrayList<BorrowedMaterial>();

	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(
			name="borrowedMaterial",
			joinColumns={@JoinColumn(name="studentId", referencedColumnName="id")},
			inverseJoinColumns={@JoinColumn(name="teachingMaterialId", referencedColumnName="id")})
	private Collection<TeachingMaterial> teachingMaterials = new HashSet<>();
	
	@ElementCollection(targetClass=Subject.class)
	@Enumerated(EnumType.STRING)
	@CollectionTable(name="studentSubject", joinColumns = @JoinColumn(name="studentId"))
	@Column(name="subject")
	private Set<Subject> profile = EnumSet.noneOf(Subject.class);
	
	@ManyToOne(fetch=FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
	@JoinColumn(name="parentId", referencedColumnName="id")
	private Parent parent;
	
	@OneToMany(mappedBy="student", fetch=FetchType.LAZY)
	private List<Dunning> dunnings = new ArrayList<Dunning>();
	
	/**
	 * Required by Hibernate.<p>
	 * Use the {@link Builder} instead.
	 * 
	 * @see Builder
	 */
	@Deprecated
	public Student() {}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Grade getGrade() {
		return grade;
	}

	public void setGrade(Grade grade) {
		this.grade = grade;
	}

	public String getLastname() {
		return lastname;
	}

	public void setLastname(String lastname) {
		this.lastname = lastname;
	}

	public String getFirstname() {
		return firstname;
	}

	public void setFirstname(String firstname) {
		this.firstname = firstname;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public Parent getParent() {
		return parent;
	}

	public void setParent(Parent parent) {
		this.parent = parent;
	}

	public List<BorrowedMaterial> getBorrowedMaterials() {
		return borrowedMaterials;
	}

	public void setBorrowedMaterials(List<BorrowedMaterial> borrowedMaterials) {
		this.borrowedMaterials = borrowedMaterials;
	}
	
	public Collection<TeachingMaterial> getTeachingMaterials() {
		return teachingMaterials;
	}

	public Set<Subject> getProfile() {
		return profile;
	}

	public void setProfile(Set<Subject> profile) {
		this.profile = profile;
	}
	
	public void addSubject(Subject subject) {
		getProfile().add(subject);
	}
	
	public boolean hasSubject(Subject subject) {
		return getProfile().contains(subject);
	}
	
	public boolean isLeavingSchool() {
		return leavingSchool;
	}

	public void setLeavingSchool(boolean leavingSchool) {
		this.leavingSchool = leavingSchool;
	}
	
	public List<Dunning> getDunnings() {
		return dunnings;
	}

	public List<BorrowedMaterial> getUnreceivedBorrowedList() {
		List<BorrowedMaterial> unreceivedBorrowedMaterials = new ArrayList<BorrowedMaterial>();
		for (BorrowedMaterial borrowedMaterial : getBorrowedMaterials()) {
			if(!borrowedMaterial.isReceived()) {
				unreceivedBorrowedMaterials.add(borrowedMaterial);
			}
		}
		
		return unreceivedBorrowedMaterials;
	}
	
	public List<BorrowedMaterial> getReceivedBorrowedMaterials() {
		List<BorrowedMaterial> receivedBorrowedMaterials = getBorrowedMaterials();
		receivedBorrowedMaterials.removeAll(getUnreceivedBorrowedList());
		
		return receivedBorrowedMaterials;
	}
	
	public List<BorrowedMaterial> getUnreturnedBorrowedMaterials() {
		List<BorrowedMaterial> unreturnedBorrowedMaterials = new ArrayList<BorrowedMaterial>();
		
		for(BorrowedMaterial borrowedMaterial : getReceivedBorrowedMaterials()) {
			if(borrowedMaterial.getReturnDate() == null) {
				unreturnedBorrowedMaterials.add(borrowedMaterial);
			}
		}
		
		return unreturnedBorrowedMaterials;
	}
	
	public boolean hasUnreceivedBorrowedMaterials() {
		for(BorrowedMaterial borrowedMaterial : getBorrowedMaterials()) {
			if(!borrowedMaterial.isReceived()) {
				return true;
			}
		}
		
		return false;
	}
	
	public void copyDataFrom(Student student) {
		setBirthday(student.getBirthday());
		setFirstname(student.getFirstname());
		setGender(student.getGender());
		setGrade(student.getGrade());
		setLastname(student.getLastname());
		setParent(student.getParent());
		setProfile(student.getProfile());
	}

	public static class Builder {
		private final int id;
		private final String firstname;
		private final String lastname;
		private final Date birthday;
		private final Grade grade;
		
		private String gender;
		private List<BorrowedMaterial> borrowedList = new ArrayList<BorrowedMaterial>();
		private Set<Subject> profile = EnumSet.noneOf(Subject.class);
		private Parent parent;
		private boolean leavingSchool;
		
		public Builder(int id, String firstname, String lastname, Date birthday, Grade grade) {
			this.id = id;
			this.firstname = firstname;
			this.lastname = lastname;
			this.birthday = birthday;
			this.grade = grade;
		}
		
		public Builder gender(String gender) {
			this.gender = gender;
			return this;
		}
		
		public Builder borrowedList(List<BorrowedMaterial> borrowedList) {
			this.borrowedList = borrowedList;
			return this;
		}
		
		public Builder profile(Set<Subject> profile) {
			this.profile = profile;
			return this;
		}
		
		public Builder parent(Parent parent) {
			this.parent = parent;
			return this;
		}
		
		public Builder leavingSchool(boolean leavingSchool){
			this.leavingSchool = leavingSchool;
			return this;
		}
		
		public Student build() {
			return new Student(this);
		}
	}
	
	private Student(Builder builder) {
		id = builder.id;
		firstname = builder.firstname;
		lastname = builder.lastname;
		birthday = builder.birthday;
		grade = builder.grade;
		leavingSchool = builder.leavingSchool;
		
		gender = builder.gender;
		borrowedMaterials = builder.borrowedList;
		profile = builder.profile;
		parent = builder.parent;
		
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Student))
			return false;
		Student other = (Student) obj;
		if (getId() != other.getId())
			return false;
		return true;
	}

	@Override
	public int compareTo(Student o) {
		int compareResult = getLastname().compareTo(o.getLastname());
		if(compareResult != 0) {
			return compareResult;
		}
		
		compareResult = getFirstname().compareTo(o.getFirstname());
		if(compareResult != 0) {
			return compareResult;
		}
		
		return Integer.compare(hashCode(), o.hashCode());
	}
} @Entity
@Table(name="teachingMaterial")
public class TeachingMaterial implements de.dhbw.humbuch.model.entity.Entity, Serializable, Comparable<TeachingMaterial> {
	private static final long serialVersionUID = -6153270685462221761L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;
	
	@ManyToOne(fetch=FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
	@JoinColumn(name="categoryId", referencedColumnName="id")
	private Category category;
	
	@ElementCollection(targetClass=Subject.class)
	@Enumerated(EnumType.STRING)
	@CollectionTable(name="teachingMaterialSubject", joinColumns = @JoinColumn(name="teachingMaterialId"))
	@Column(name="subject")
	private Set<Subject> profile = EnumSet.noneOf(Subject.class);
	
	private String name;
	private String producer;
	private String identifyingNumber;
	private double price;
	private String comment;
	
	private int fromGrade;
	private int toGrade;
	
	@Enumerated(EnumType.ORDINAL)
	private Term fromTerm = Term.FIRST;
	
	@Enumerated(EnumType.ORDINAL)
	private Term toTerm = Term.SECOND;
	
	private Date validFrom;
	private Date validUntil;
	
	/**
	 * Required by Hibernate.<p>
	 * Use the {@link Builder} instead.
	 * 
	 * @see Builder
	 */
	@Deprecated
	public TeachingMaterial() {}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Category getCategory() {
		return category;
	}

	public void setCategory(Category category) {
		this.category = category;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getProducer() {
		return producer;
	}

	public void setProducer(String producer) {
		this.producer = producer;
	}

	public String getIdentifyingNumber() {
		return identifyingNumber;
	}

	public void setIdentifyingNumber(String identifyingNumber) {
		this.identifyingNumber = identifyingNumber;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public String getComment() {
		return comment;
	}

	public void setComment(String comment) {
		this.comment = comment;
	}

	public int getFromGrade() {
		return fromGrade;
	}

	public void setFromGrade(int fromGrade) {
		this.fromGrade = fromGrade;
	}

	public int getToGrade() {
		return toGrade;
	}

	public void setToGrade(int toGrade) {
		this.toGrade = toGrade;
	}

	public Term getFromTerm() {
		return fromTerm;
	}

	public void setFromTerm(Term fromTerm) {
		this.fromTerm = fromTerm;
	}

	public Term getToTerm() {
		return toTerm;
	}

	public void setToTerm(Term toTerm) {
		this.toTerm = toTerm;
	}

	public Date getValidFrom() {
		return validFrom;
	}

	public void setValidFrom(Date validFrom) {
		this.validFrom = validFrom;
	}

	public Date getValidUntil() {
		return validUntil;
	}

	public void setValidUntil(Date validUntil) {
		this.validUntil = validUntil;
	}

	public Set<Subject> getProfile() {
		return profile;
	}

	public void setProfile(Set<Subject> profile) {
		this.profile = profile;
	}

	public void addSubject(Subject subject) {
		getProfile().add(subject);
	}
	
	public boolean hasSubject(Subject subject) {
		return getProfile().contains(subject);
	}
	
	public static class Builder {
		private final Category category;
		private final String name;
		private final String identifyingNumber;
		private final Date validFrom;
		
		private Set<Subject> profile;
		private String producer;
		private double price;
		private String comment;
		private int fromGrade;
		private int toGrade;
		private Term fromTerm;
		private Term toTerm;
		private Date validUntil;
		
		public Builder(Category category, String name, String identifyingNumber, Date validFrom) {
			this.category = category;
			this.name = name;
			this.identifyingNumber = identifyingNumber;
			this.validFrom = validFrom;
			this.fromTerm = Term.FIRST;
			this.toTerm = Term.SECOND;
		}
		
		public Builder profile(Set<Subject> profile) {
			this.profile = profile;
			return this;
		}
		
		public Builder producer(String producer) {
			this.producer = producer;
			return this;
		}
		
		public Builder price(double price) {
			this.price = price;
			return this;
		}
		
		public Builder comment(String comment) {
			this.comment = comment;
			return this;
		}
		
		public Builder fromGrade(int fromGrade) {
			this.fromGrade = fromGrade;
			return this;
		}
		
		public Builder toGrade(int toGrade) {
			this.toGrade = toGrade;
			return this;
		}
		
		public Builder fromTerm(Term fromTerm) {
			this.fromTerm = fromTerm;
			return this;
		}
		
		public Builder toTerm(Term toTerm) {
			this.toTerm = toTerm;
			return this;
		}
		
		public Builder validUntil(Date validUntil) {
			this.validUntil = validUntil;
			return this;
		}
		
		public TeachingMaterial build() {
			return new TeachingMaterial(this);
		}
	}
	
	private TeachingMaterial(Builder builder) {
		this.category = builder.category;
		this.name = builder.name;
		this.identifyingNumber = builder.identifyingNumber;
		this.validFrom = builder.validFrom;
		
		this.profile = builder.profile;
		this.producer = builder.producer;
		this.price = builder.price;
		this.comment = builder.comment;
		this.fromGrade = builder.fromGrade;
		this.toGrade = builder.toGrade;
		this.fromTerm = builder.fromTerm;
		this.toTerm = builder.toTerm;
		this.validUntil = builder.validUntil;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof TeachingMaterial))
			return false;
		TeachingMaterial other = (TeachingMaterial) obj;
		if (getId() != other.getId())
			return false;
		return true;
	}

	@Override
	public int compareTo(TeachingMaterial o) {
		int compareResult = getName().compareTo(o.getName());
		if(compareResult != 0) {
			return compareResult;
		}
		
		return Integer.compare(hashCode(), o.hashCode());
	}
	
} public class TestPersistenceInitialiser {
	private final static Logger LOG = LoggerFactory
			.getLogger(TestPersistenceInitialiser.class);

	@Inject
	public TestPersistenceInitialiser(PersistService persistService) {
		try {
			persistService.start();
			LOG.info("persistService started...");
		} catch (IllegalStateException e) {
			LOG.info("persistService already started...");
		}
	}
}
import static de.dhbw.humbuch.test.TestUtils.grade;
import static de.dhbw.humbuch.test.TestUtils.schoolYearFirstTermStarted;
import static de.dhbw.humbuch.test.TestUtils.schoolYearSecondTermEnded;
import static de.dhbw.humbuch.test.TestUtils.schoolYearSecondTermStarted;
import static de.dhbw.humbuch.test.TestUtils.studentInGrade;
import static de.dhbw.humbuch.test.TestUtils.teachingMaterialInBothTermsOfGrade;
import static de.dhbw.humbuch.test.TestUtils.teachingMaterialInFirstTermOfGrade;
import static de.dhbw.humbuch.test.TestUtils.teachingMaterialInSecondTermOfGrade;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import de.dhbw.humbuch.guice.GuiceJUnitRunner;
import de.dhbw.humbuch.guice.GuiceJUnitRunner.GuiceModules;
import de.dhbw.humbuch.guice.TestModuleWithoutSingletons;
import de.dhbw.humbuch.model.DAO;
import de.dhbw.humbuch.model.entity.BorrowedMaterial;
import de.dhbw.humbuch.model.entity.Grade;
import de.dhbw.humbuch.model.entity.SchoolYear;
import de.dhbw.humbuch.model.entity.Student;
import de.dhbw.humbuch.model.entity.TeachingMaterial;
import de.dhbw.humbuch.model.entity.TestPersistenceInitialiser;
package de.dhbw.humbuch.viewmodel;







@RunWith(GuiceJUnitRunner.class)
@GuiceModules({ TestModuleWithoutSingletons.class })
public class LendingViewModelTest extends BaseTest {

	private final static Logger LOG = LoggerFactory
			.getLogger(LendingViewModelTest.class);

	private LendingViewModel vm;
	private DAO<Grade> daoGrade;
	private DAO<Student> daoStudent;
	private DAO<SchoolYear> daoSchoolYear;