/**
* Copyright (C) 2012 KRM Associates, Inc. healtheme@krminc.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.krminc.phr.domain;
import com.krminc.phr.core.UserConfig;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* User entity class.
*
* @author Daniel Shaw (dshaw.com)
*/
@Entity
@Table(name = "user_users")
@NamedQueries({
@NamedQuery(name = "User.findAll", query = "SELECT u FROM User u"),
@NamedQuery(name = "User.findByUserId", query = "SELECT u FROM User u WHERE u.userId = :userId"),
@NamedQuery(name = "User.findByUsername", query = "SELECT u FROM User u WHERE u.username = :username"),
@NamedQuery(name = "User.findByTitle", query = "SELECT u FROM User u WHERE u.title = :title"),
@NamedQuery(name = "User.findByFirstName", query = "SELECT u FROM User u WHERE u.firstName = :firstName"),
@NamedQuery(name = "User.findByMiddleName", query = "SELECT u FROM User u WHERE u.middleName = :middleName"),
@NamedQuery(name = "User.findByLastName", query = "SELECT u FROM User u WHERE u.lastName = :lastName"),
@NamedQuery(name = "User.findBySuffix", query = "SELECT u FROM User u WHERE u.suffix = :suffix"),
@NamedQuery(name = "User.findByPreferredName", query = "SELECT u FROM User u WHERE u.preferredName = :preferredName"),
@NamedQuery(name = "User.findByEmail", query = "SELECT u FROM User u WHERE u.email = :email"),
@NamedQuery(name = "User.findByActive", query = "SELECT u FROM User u WHERE u.active = :active"),
@NamedQuery(name = "User.findByDateCreated", query = "SELECT u FROM User u WHERE u.dateCreated = :dateCreated"),
@NamedQuery(name = "User.findByLastLogin", query = "SELECT u FROM User u WHERE u.lastLogin = :lastLogin"),
/* --- Custom Queries --- */
@NamedQuery(name = "User.findUserIdByUsername", query = "SELECT u.userId FROM User u WHERE u.username = :username"),
@NamedQuery(name = "User.findUsernameByUserId", query = "SELECT u.username FROM User u WHERE u.userId = :userId"),
@NamedQuery(name = "User.findFullnameByUserId", query = "SELECT u.firstName, u.lastName FROM User u WHERE u.userId = :userId"),
@NamedQuery(name = "User.countAll", query = "SELECT COUNT(u) FROM User u"),
@NamedQuery(name = "User.updateLoggedInTime", query = "UPDATE User u SET u.lastLogin = CURRENT_TIMESTAMP WHERE u.userId = :userId"),
@NamedQuery(name = "User.updateLoggedInTotal", query = "UPDATE User u SET u.totalLogin = u.totalLogin + 1 WHERE u.userId = :userId")
})
public class User implements Serializable {
private static final long serialVersionUID = 20091123L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "user_id", nullable = false)
private Long userId;
@Basic(optional = false)
@Column(name = "username", nullable = false, length = 64)
private String username;
@Basic(optional = false)
@Column(name = "password", length = 256)
private String password;
@Column(name = "title", length = 10)
private String title;
@Basic(optional = false)
@Column(name = "first_name", nullable = false, length = 100)
private String firstName;
@Column(name = "middle_name", length = 50)
private String middleName;
@Basic(optional = false)
@Column(name = "last_name", nullable = false, length = 50)
private String lastName;
@Column(name = "suffix", length = 10)
private String suffix;
@Column(name = "preferred_name", length = 50)
private String preferredName;
@Column(name = "telnum_home", length = 25)
private String telnumHome;
@Column(name = "telnum_work", length = 25)
private String telnumWork;
@Column(name = "telnum_mobile", length = 25)
private String telnumMobile;
@Column(name = "faxnum", length = 25)
private String faxnum;
@Column(name = "email", length = 200)
private String email;
@Column(name = "question1_id", nullable = false)
private int question1Id;
@Column(name = "question1_answer", nullable = false, length = 50)
private String question1Answer;
@Column(name = "question2_id", nullable = false)
private int question2Id;
@Column(name = "question2_answer", nullable = false, length = 50)
private String question2Answer;
@Column(name="active")
protected Boolean active;
@Basic(optional = false)
@Column(name="requires_reset")
protected Boolean requiresReset;
@Basic(optional = false)
@Column(name = "date_created", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date dateCreated;
@Column(name = "last_login", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date lastLogin;
@Column(name = "total_login", nullable = false)
private Integer totalLogin;
//03112010 new lockout & failed attempt mappings
@Basic(optional = false)
@Column(name="is_locked_out")
protected Boolean isLockedOut;
@Column(name = "lockout_begin", nullable = true)
@Temporal(TemporalType.TIMESTAMP)
private Date lockoutBegin;
@Basic(optional = false)
@Column(name = "failed_password_attempts", nullable = false)
private int failedPasswordAttempts;
@Column(name = "failed_password_window_start", nullable = true)
@Temporal(TemporalType.TIMESTAMP)
private Date failedPasswordWindowStart;
@Basic(optional = false)
@Column(name = "failed_answer_attempts", nullable = false)
private int failedAnswerAttempts;
@Column(name = "failed_answer_window_start", nullable = true)
@Temporal(TemporalType.TIMESTAMP)
private Date failedAnswerWindowStart;
@Basic(optional = true, fetch=FetchType.LAZY)
@Lob
@Column(name = "user_image", nullable = true)
private byte[] userImage;
//FKs
@OneToMany(fetch=FetchType.EAGER)
@JoinTable(
name = "user_roles",
joinColumns=@JoinColumn(name="username", referencedColumnName="username"),
inverseJoinColumns=@JoinColumn(name="username", referencedColumnName="username"))
private List<UserRole> roles;
@OneToMany(cascade=CascadeType.PERSIST, mappedBy = "user")
@JoinColumn(name = "user_id", referencedColumnName = "user_id")
private List<Address> addresses;
//@OneToMany(cascade=CascadeType.PERSIST, mappedBy = "user")
@ManyToMany(cascade = CascadeType.ALL) //(cascade=CascadeType.PERSIST, mappedBy = "userList")
@JoinTable(name="user_users_rec_healthrecord",
joinColumns = {
@JoinColumn(name = "user_id") //, referencedColumnName = "user_user_id")
}, inverseJoinColumns = {
@JoinColumn(name="rec_id")
}
)
private List<HealthRecord> healthRecords;
transient final Logger logger = LoggerFactory.getLogger(User.class);
public User() {
}
public User(Long userId) {
this.userId = userId;
}
public User(Long userId, String username, String firstName, String middleName, String lastName) {
this.userId = userId;
this.username = username;
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
this.requiresReset = true;
this.active = true;
this.isLockedOut = false;
}
// TODO: Setup Builder pattern for this.
public User(Long userId, String username, String password, String firstName, String middleName, String lastName) {
this.userId = userId;
this.username = username;
this.setPassword(password); // to ensure password is hashed.
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
this.requiresReset = true;
this.active = true;
this.isLockedOut = false;
}
/**
* Constructor for user enrollment form.
*
* @param username
* @param firstName
* @param middleName
* @param lastName
* @param dateCreated
*/
public User(String username, String firstName, String middleName, String lastName, Date dateCreated) {
this.username = username;
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
this.dateCreated = dateCreated;
this.requiresReset = true;
this.active = true;
this.isLockedOut = false;
}
/**
* Constructor for user enrollment form.
*
* @param username
* @param password
* @param firstName
* @param middleName
* @param lastName
* @param dateCreated
*/
public User(String username, String password, String firstName, String middleName, String lastName, Date dateCreated) {
this.username = username;
this.setPassword(password); // to ensure password is hashed.
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
this.dateCreated = dateCreated;
this.requiresReset = true;
this.active = true;
this.isLockedOut = false;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = DigestUtils.sha512Hex(password);
}
public Boolean testPassword(String testPassword) {
return (this.password.equals(DigestUtils.sha512Hex(testPassword)));
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public String getPreferredName() {
return preferredName;
}
public void setPreferredName(String preferredName) {
this.preferredName = preferredName;
}
public String getFaxnum() {
return faxnum;
}
public void setFaxnum(String faxnum) {
this.faxnum = faxnum;
}
public String getTelnumHome() {
return telnumHome;
}
public void setTelnumHome(String telnumHome) {
this.telnumHome = telnumHome;
}
public String getTelnumMobile() {
return telnumMobile;
}
public void setTelnumMobile(String telnumMobile) {
this.telnumMobile = telnumMobile;
}
public String getTelnumWork() {
return telnumWork;
}
public void setTelnumWork(String telnumWork) {
this.telnumWork = telnumWork;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getQuestion1Id() {
return question1Id;
}
public void setQuestion1Id(int question1Id) {
this.question1Id = question1Id;
}
public String getQuestion1Answer() {
return question1Answer;
}
public void setQuestion1Answer(String question1Answer) {
this.question1Answer = question1Answer;
}
public int getQuestion2Id() {
return question2Id;
}
public void setQuestion2Id(int question2Id) {
this.question2Id = question2Id;
}
public String getQuestion2Answer() {
return question2Answer;
}
public void setQuestion2Answer(String question2Answer) {
this.question2Answer = question2Answer;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
public Boolean getRequiresReset() {
return requiresReset;
}
public void setRequiresReset(Boolean requiresReset) {
this.requiresReset = requiresReset;
}
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
public Date getLastLogin() {
return lastLogin;
}
public Integer getTotalLogin() {
return totalLogin;
}
public void setTotalLogin(Integer total) {
this.totalLogin = total;
}
public void setLastLogin(Date lastLogin) {
this.lastLogin = lastLogin;
}
//03112010 new lockout & failed attempt methods
public int getFailedAnswerAttempts() {
return failedAnswerAttempts;
}
public void setFailedAnswerAttempts(int failedAnswerAttempts) {
this.failedAnswerAttempts = failedAnswerAttempts;
}
public Date getFailedAnswerWindowStart() {
return failedAnswerWindowStart;
}
public void setFailedAnswerWindowStart(Date failedAnswerWindowStart) {
this.failedAnswerWindowStart = failedAnswerWindowStart;
}
public int getFailedPasswordAttempts() {
return failedPasswordAttempts;
}
public void setFailedPasswordAttempts(int failedPasswordAttempts) {
this.failedPasswordAttempts = failedPasswordAttempts;
}
public Date getFailedPasswordWindowStart() {
return failedPasswordWindowStart;
}
public void setFailedPasswordWindowStart(Date failedPasswordWindowStart) {
this.failedPasswordWindowStart = failedPasswordWindowStart;
}
public Boolean getIsLockedOut() {
return isLockedOut;
}
public void setIsLockedOut(Boolean isLockedOut) {
this.isLockedOut = isLockedOut;
}
public Date getLastLockout() {
return lockoutBegin;
}
public void setLastLockout(Date lastLockout) {
this.lockoutBegin = lastLockout;
}
// TODO: Apply to API.
public List<UserRole> getRoles() {
return roles;
}
public void setRoles(List<UserRole> roles) {
this.roles = roles;
}
/**
* @return whether user is a patient.
*/
public boolean isPatient() {
for (UserRole role : roles) {
if (role.getRole().equals(UserConfig.ROLE_PATIENT)) {
return true;
}
}
return false;
}
/**
* JSP compatible getter for isPatient().
* @return whether user is patient.
*/
public boolean getIsPatient() {
return isPatient();
}
public List<Address> getAddresses() {
return addresses;
}
public void setAddresses(List<Address> addresses) {
for (Address address : addresses) {
address.setUser(this);
}
this.addresses = addresses;
}
public Address getPrimaryAddress() {
for(Address address : addresses) {
if (address.getPrimaryAddress()) {
return address;
}
}
// if no address is found, return an empty object.
return new Address();
}
public int getAddressCount() {
return getAddresses().size();
}
public List<HealthRecord> getHealthRecords() {
return healthRecords;
}
public void setHealthRecords(List<HealthRecord> healthRecords) {
this.healthRecords = healthRecords;
}
public HealthRecord getPrimaryHealthRecord() {
for(HealthRecord healthRecord : healthRecords) {
if (healthRecord.isPrimary()) {
return healthRecord;
}
}
// blank health record
return new HealthRecord();
}
public int getHealthRecordCount() {
return getHealthRecords().size();
}
public boolean authorizedToAccessHealthRecord(HealthRecord healthRecord) {
return authorizedToAccessHealthRecord(healthRecord.getHealthRecordId());
}
public boolean authorizedToAccessHealthRecord(Long healthRecordId) {
for (HealthRecord healthRecord : healthRecords) {
logger.debug(
"Scanning to see if userid {} has access to recid {}",
this.userId, healthRecord.getHealthRecordId()
);
if (healthRecordId.equals(healthRecord.getHealthRecordId())) {
logger.debug(
"Attempting to allow access by userid {} to recid {}",
this.userId, healthRecord.getHealthRecordId()
);
return true;
}
}
logger.error(
"Disallowing access by userid {} to recid {}",
this.userId, healthRecordId
);
return false;
}
public byte[] getUserImage() {
return userImage;
}
public void setUserImage(java.io.InputStream userImage) {
ArrayList<Byte> list = new ArrayList<Byte>();
int s;
//loop through each byte of input image
try {
while ((s = userImage.read()) != -1) {
list.add((byte) s);
}
}
catch (IOException e) {
list.clear();
}
//copy from arraylist to ORM-pleasing byte array
byte[] b = new byte[list.size()];
for (int i = 0; i < b.length; i++) {
b[i] = list.get(i);
}
if (list.size() > 0) {
this.userImage = b;
} else {
this.userImage = null;
}
}
@Override
public int hashCode() {
int hash = 0;
hash += (userId != null ? userId.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof User)) {
return false;
}
User other = (User) object;
if ((this.userId == null && other.userId != null) || (this.userId != null && !this.userId.equals(other.userId))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.krminc.phr.domain.User[userId=" + userId + " username=" + username + "]";
}
}