package fi.otavanopisto.pyramus.domainmodel.base;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PersistenceException;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.DocumentId;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.FieldBridge;
import org.hibernate.search.annotations.FullTextFilterDef;
import org.hibernate.search.annotations.FullTextFilterDefs;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import org.hibernate.search.annotations.SortableField;
import org.hibernate.search.annotations.Store;
import fi.otavanopisto.pyramus.domainmodel.students.Sex;
import fi.otavanopisto.pyramus.domainmodel.students.Student;
import fi.otavanopisto.pyramus.domainmodel.users.StaffMember;
import fi.otavanopisto.pyramus.domainmodel.users.User;
import fi.otavanopisto.pyramus.persistence.search.CollectionBridge;
import fi.otavanopisto.pyramus.persistence.search.filters.StudentIdFilterFactory;
import fi.otavanopisto.security.ContextReference;
@Entity
@Indexed
@FullTextFilterDefs (
@FullTextFilterDef (
name="StudentIdFilter",
impl=StudentIdFilterFactory.class
)
)
public class Person implements ContextReference {
/**
* Returns unique identifier for this Person
*
* @return unique id of this Person
*/
public Long getId() {
return id;
}
@SuppressWarnings("unused")
private void setVersion(Long version) {
this.version = version;
}
public Long getVersion() {
return version;
}
/**
* Sets birthday for this Person
*
* @param birthday
* New birthday
*/
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
/**
* Returns birthday given for this Person
*
* @return birthday
*/
public Date getBirthday() {
return birthday;
}
/**
* Sets social security number for this Person
*
* @param socialSecurityNumber
* New social security number
*/
public void setSocialSecurityNumber(String socialSecurityNumber) {
this.socialSecurityNumber = socialSecurityNumber;
}
/**
* Returns social security number given for this Person
*
* @return social security number
*/
public String getSocialSecurityNumber() {
return socialSecurityNumber;
}
/**
* Returns sex given for this Person
*
* @return sex
*/
public Sex getSex() {
return sex;
}
/**
* Sets the sex of this Person
*
* @param sex
* New sex
*/
public void setSex(Sex sex) {
this.sex = sex;
}
public List<StaffMember> getStaffMembers() {
List<User> users = getUsers();
List<StaffMember> staffMembers = new ArrayList<>();
for (User user : users) {
if (user instanceof StaffMember)
staffMembers.add((StaffMember) user);
}
return staffMembers;
}
public List<Student> getStudents() {
List<User> users = getUsers();
List<Student> students = new ArrayList<>();
for (User user : users) {
if (user instanceof Student)
students.add((Student) user);
}
return students;
}
public void addUser(User user) {
if (!this.getUsers().contains(user)) {
user.setPerson(this);
getUsers().add(user);
} else {
throw new PersistenceException("Student is already in this Person");
}
}
public void removeUser(User user) {
// TODO: should probably do something with defaultuser too
if (this.getUsers().contains(user)) {
user.setPerson(null);
getUsers().remove(user);
} else {
throw new PersistenceException("Student is not in this Person");
}
}
@Transient
public Student getLatestStudent() {
List<Student> students = new ArrayList<>();
if (this.getUsers() != null) {
for (Student student : this.getStudents()) {
if (!student.getArchived())
students.add(student);
}
/**
* Ordering study programmes as follows
* 1. studies that have start date but no end date (ongoing)
* 2. studies that have no start nor end date
* 3. studies that have ended
* 4. studies that are archived
* 5. other
*/
Collections.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int o1Value = getLatestStudentOrderValue(o1);
int o2Value = getLatestStudentOrderValue(o2);
if (o1Value == o2Value) {
Date o1StudyStart = o1.getStudyStartDate();
Date o2StudyStart = o2.getStudyStartDate();
return o1StudyStart != null && o2StudyStart != null ? o2StudyStart.compareTo(o1StudyStart) : 0;
}
return o1Value < o2Value ? -1 : 1;
}
private int getLatestStudentOrderValue(Student student) {
if (student.getArchived()) {
return 4;
}
if (student.getStudyStartDate() != null && student.getStudyEndDate() == null) {
return 1;
}
if (student.getStudyStartDate() == null && student.getStudyEndDate() == null) {
return 2;
}
if (student.getStudyEndDate() != null) {
return 3;
}
return 5;
}
});
}
return students.isEmpty() ? null : students.get(0);
}
public void setBasicInfo(String basicInfo) {
this.basicInfo = basicInfo;
}
public String getBasicInfo() {
return basicInfo;
}
private StaffMember getStaffMember() {
List<StaffMember> staffMembers = getStaffMembers();
return !staffMembers.isEmpty() ? staffMembers.get(0) : null;
}
@Transient
@Field(analyze = Analyze.NO, store = Store.NO)
@SortableField
public String getLastNameSortable() {
Student student = getLatestStudent();
StaffMember staffMember = getStaffMember();
return student != null ? student.getLastName() : staffMember != null ? staffMember.getLastName() : "";
}
@Transient
@Field(analyze = Analyze.NO, store = Store.NO)
@SortableField
public String getFirstNameSortable() {
Student student = getLatestStudent();
StaffMember staffMember = getStaffMember();
return student != null ? student.getFirstName() : staffMember != null ? staffMember.getFirstName() : "";
}
@Transient
@Field
public String getInactiveFirstNames() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
if (student.getFirstName() != null) {
results.add(student.getFirstName());
}
}
}
return setToString(results);
}
@Transient
@Field
public String getInactiveLastNames() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
if (student.getLastName() != null) {
results.add(student.getLastName());
}
}
}
return setToString(results);
}
@Transient
@Field
public String getInactiveNicknames() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
if (student.getNickname() != null) {
results.add(student.getNickname());
}
}
}
return setToString(results);
}
@Transient
@Field
public String getInactiveEducations() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
if (student.getEducation() != null) {
results.add(student.getEducation());
}
}
}
return setToString(results);
}
@Transient
@Field(analyze = Analyze.NO)
@FieldBridge(impl = CollectionBridge.class)
public Set<String> getInactiveEmails() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
for (Email email : student.getContactInfo().getEmails()) {
if (email.getAddress() != null) {
results.add(email.getAddress());
}
}
}
}
return results;
}
@Transient
@Field
public String getInactiveStreetAddresses() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
for (Address address : student.getContactInfo().getAddresses()) {
if (address.getStreetAddress() != null) {
results.add(address.getStreetAddress());
}
}
}
}
return setToString(results);
}
@Transient
@Field
public String getInactivePostalCodes() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
for (Address address : student.getContactInfo().getAddresses()) {
if (address.getPostalCode() != null) {
results.add(address.getPostalCode());
}
}
}
}
return setToString(results);
}
/**
* Returns whether this abstract student contains at least one non-archived student who has got his
* study end date set and that date is in the past.
*
* @return <code>true</code> if this abstract student contains at least one inactive student, otherwise <code>false</code>
*/
@Transient
@Field
public String getInactive() {
String result = Boolean.FALSE.toString();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
result = Boolean.TRUE.toString();
break;
}
}
return result;
}
@Transient
@Field
public String getInactiveCities() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
for (Address address : student.getContactInfo().getAddresses()) {
if (address.getCity() != null) {
results.add(address.getCity());
}
}
}
}
return setToString(results);
}
@Transient
@Field
public String getInactiveCountries() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
for (Address address : student.getContactInfo().getAddresses()) {
if (address.getCountry() != null) {
results.add(address.getCountry());
}
}
}
}
return setToString(results);
}
@Transient
@Field
public String getInactivePhones() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
for (PhoneNumber phoneNumber : student.getContactInfo().getPhoneNumbers()) {
results.add(phoneNumber.getNumber());
}
}
}
return setToString(results);
}
@Transient
@Field
public String getInactiveLodgings() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
if (student.getLodging() != null) {
results.add(student.getLodging().toString());
}
}
}
return setToString(results);
}
@Transient
@Field
public String getInactiveStudyProgrammeIds() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
if (student.getStudyProgramme() != null)
results.add(student.getStudyProgramme().getId().toString());
}
}
return setToString(results);
}
@Transient
@Field
public String getInactiveLanguageIds() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
if (student.getLanguage() != null)
results.add(student.getLanguage().getId().toString());
}
}
return setToString(results);
}
@Transient
@Field
public String getInactiveMunicipalityIds() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
if (student.getMunicipality() != null)
results.add(student.getMunicipality().getId().toString());
}
}
return results.toString();
}
@Transient
@Field
public String getInactiveNationalityIds() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
if (student.getNationality() != null)
results.add(student.getNationality().getId().toString());
}
}
return setToString(results);
}
@Transient
@Field
public String getActiveFirstNames() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
if (student.getFirstName() != null) {
results.add(student.getFirstName());
}
}
}
return setToString(results);
}
@Transient
@Field
public String getActiveLastNames() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
if (student.getLastName() != null) {
results.add(student.getLastName());
}
}
}
return setToString(results);
}
@Transient
@Field
public String getActiveNicknames() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
if (student.getNickname() != null) {
results.add(student.getNickname());
}
}
}
return setToString(results);
}
@Transient
@Field
public String getActiveEducations() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
if (student.getEducation() != null) {
results.add(student.getEducation());
}
}
}
return setToString(results);
}
@Transient
@Field(analyze = Analyze.NO)
@FieldBridge(impl = CollectionBridge.class)
public Set<String> getActiveEmails() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
for (Email email : student.getContactInfo().getEmails()) {
if (email.getAddress() != null) {
results.add(email.getAddress());
}
}
}
}
return results;
}
@Transient
@Field
public String getActiveStreetAddresses() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
for (Address address : student.getContactInfo().getAddresses()) {
if (address.getStreetAddress() != null) {
results.add(address.getStreetAddress());
}
}
}
}
return setToString(results);
}
@Transient
@Field
public String getActivePostalCodes() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
for (Address address : student.getContactInfo().getAddresses()) {
if (address.getPostalCode() != null) {
results.add(address.getPostalCode());
}
}
}
}
return setToString(results);
}
/**
* Returns whether this abstract student contains at least one non-archived student who hasn't got his
* study end date set or it has been set but it is in the future.
*
* @return <code>true</code> if this abstract student contains at least one active student, otherwise <code>false</code>
*/
@Transient
@Field
public String getActive() {
String result = Boolean.FALSE.toString();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
result = Boolean.TRUE.toString();
break;
}
}
return result;
}
// TODO: Naming conventions pls
@Transient
@Field
public String getStaff() {
StaffMember staffMember = getStaffMember();
return new Boolean(staffMember != null).toString();
}
@Transient
@Field
public String getActiveCities() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
for (Address address : student.getContactInfo().getAddresses()) {
if (address.getCity() != null) {
results.add(address.getCity());
}
}
}
}
return setToString(results);
}
@Transient
@Field
public String getActiveCountries() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
for (Address address : student.getContactInfo().getAddresses()) {
if (address.getCountry() != null) {
results.add(address.getCountry());
}
}
}
}
return setToString(results);
}
@Transient
@Field
public String getActivePhones() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
for (PhoneNumber phoneNumber : student.getContactInfo().getPhoneNumbers()) {
results.add(phoneNumber.getNumber());
}
}
}
return setToString(results);
}
@Transient
@Field
public String getActiveLodgings() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
if (student.getLodging() != null) {
results.add(student.getLodging().toString());
}
}
}
return setToString(results);
}
@Transient
@Field
public String getActiveStudyProgrammeIds() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
if (student.getStudyProgramme() != null)
results.add(student.getStudyProgramme().getId().toString());
}
}
return setToString(results);
}
@Transient
@Field
public String getActiveLanguageIds() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
if (student.getLanguage() != null)
results.add(student.getLanguage().getId().toString());
}
}
return setToString(results);
}
@Transient
@Field
public String getActiveMunicipalityIds() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
if (student.getMunicipality() != null)
results.add(student.getMunicipality().getId().toString());
}
}
return setToString(results);
}
@Transient
@Field
public String getActiveNationalityIds() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
if (student.getNationality() != null)
results.add(student.getNationality().getId().toString());
}
}
return setToString(results);
}
@Transient
@Field
public String getActiveTags() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && student.getActive()) {
for (Tag tag : student.getTags()) {
results.add(tag.getText());
}
}
}
return setToString(results);
}
/**
* Returns whether this abstract student contains at least one student who has got his/her
* study end date set or it has been set but it is in the future.
*
* @return <code>true</code> if this abstract student contains at least one active student, otherwise <code>false</code>
*/
@Transient
@Field
public String getInactiveTags() {
Set<String> results = new HashSet<>();
for (Student student : getStudents()) {
if (!student.getArchived() && !student.getActive()) {
for (Tag tag : student.getTags()) {
results.add(tag.getText());
}
}
}
return setToString(results);
}
@Transient
@Field
public String getStaffMemberFirstNames() {
Set<String> results = new HashSet<>();
for (StaffMember staffMember : getStaffMembers()) {
String s = staffMember.getFirstName();
if (s != null) {
results.add(s);
}
}
return setToString(results);
}
@Transient
@Field
public String getStaffMemberLastNames() {
Set<String> results = new HashSet<>();
for (StaffMember staffMember : getStaffMembers()) {
String s = staffMember.getLastName();
if (s != null) {
results.add(s);
}
}
return setToString(results);
}
@Transient
@Field(analyze = Analyze.NO)
@FieldBridge(impl = CollectionBridge.class)
public Set<String> getStaffMemberEmails() {
Set<String> results = new HashSet<>();
for (StaffMember staffMember : getStaffMembers()) {
for (Email email : staffMember.getContactInfo().getEmails()) {
String s = email.getAddress();
if (s != null) {
results.add(s);
}
}
}
return results;
}
@Transient
@Field
public String getStaffMemberTitles() {
Set<String> results = new HashSet<>();
for (StaffMember staffMember : getStaffMembers()) {
String s = staffMember.getTitle();
if (s != null) {
results.add(s);
}
}
return setToString(results);
}
@Transient
@Field
public String getStaffMemberRoles() {
Set<String> results = new HashSet<>();
for (StaffMember staffMember : getStaffMembers()) {
String s = staffMember.getRole().toString();
if (s != null) {
results.add(s);
}
}
return setToString(results);
}
@Transient
@Field
public String getStaffMemberTags() {
Set<String> results = new HashSet<>();
for (StaffMember staffMember : getStaffMembers()) {
for (Tag tag : staffMember.getTags()) {
String s = tag.getText();
if (s != null) {
results.add(s);
}
}
}
return setToString(results);
}
@Transient
@Field
public String getStaffMemberPhones() {
Set<String> results = new HashSet<>();
for (StaffMember staffMember : getStaffMembers()) {
for (PhoneNumber number : staffMember.getContactInfo().getPhoneNumbers()) {
String s = number.getNumber();
if (s != null) {
results.add(s);
}
}
}
return setToString(results);
}
@Transient
@Field
public String getStaffMemberStreetAddresses() {
Set<String> results = new HashSet<>();
for (StaffMember staffMember : getStaffMembers()) {
for (Address address : staffMember.getContactInfo().getAddresses()) {
String s = address.getStreetAddress();
if (s != null) {
results.add(s);
}
}
}
return setToString(results);
}
@Transient
@Field
public String getStaffMemberPostalCodes() {
Set<String> results = new HashSet<>();
for (StaffMember staffMember : getStaffMembers()) {
for (Address address : staffMember.getContactInfo().getAddresses()) {
String s = address.getPostalCode();
if (s != null) {
results.add(s);
}
}
}
return setToString(results);
}
@Transient
@Field
public String getStaffMemberCities() {
Set<String> results = new HashSet<>();
for (StaffMember staffMember : getStaffMembers()) {
for (Address address : staffMember.getContactInfo().getAddresses()) {
String s = address.getCity();
if (s != null) {
results.add(s);
}
}
}
return setToString(results);
}
@Transient
@Field
public String getStaffMemberCountries() {
Set<String> results = new HashSet<>();
for (StaffMember staffMember : getStaffMembers()) {
for (Address address : staffMember.getContactInfo().getAddresses()) {
String s = address.getCountry();
if (s != null) {
results.add(s);
}
}
}
return setToString(results);
}
private String setToString(Set<String> set) {
StringBuilder sb = new StringBuilder();
Iterator<String> i = set.iterator();
while (i.hasNext()) {
sb.append(i.next());
if (i.hasNext()) {
sb.append(' ');
}
}
return sb.toString();
}
public Boolean getSecureInfo() {
return secureInfo;
}
public void setSecureInfo(Boolean secureInfo) {
this.secureInfo = secureInfo;
}
private List<User> getUsers() {
return users;
}
@SuppressWarnings("unused")
private void setUsers(List<User> users) {
this.users = users;
}
public User getDefaultUser() {
return defaultUser;
}
public void setDefaultUser(User defaultUser) {
this.defaultUser = defaultUser;
}
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "Person")
@TableGenerator(name = "Person", allocationSize=1, table = "hibernate_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_next_hi_value")
@DocumentId
private Long id;
@Version
@Column(nullable = false)
private Long version;
@Column
@Temporal(value = TemporalType.DATE)
private Date birthday;
@Column
@Field(store = Store.NO)
private String socialSecurityNumber;
@Column
@Enumerated (EnumType.STRING)
@Field(store = Store.NO)
private Sex sex;
@NotNull
@Column (nullable = false)
@Field
private Boolean secureInfo = Boolean.FALSE;
@Lob
@Basic(fetch = FetchType.LAZY)
@Column
private String basicInfo;
@OneToMany
@JoinColumn(name = "person_id")
@IndexedEmbedded
private List<User> users = new ArrayList<>();
@OneToOne
private User defaultUser;
}