package com.globant.katari.sample.time.application;
import java.util.Date;
import org.apache.commons.lang.Validate;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import com.globant.katari.hibernate.coreuser.domain.CoreUser;
import com.globant.katari.hibernate.coreuser.SecurityUtils;
import com.globant.katari.core.application.ValidatableCommand;
import com.globant.katari.sample.time.domain.Activity;
import com.globant.katari.sample.time.domain.Project;
import com.globant.katari.sample.time.domain.TimeEntry;
import com.globant.katari.sample.time.domain.TimePeriod;
import com.globant.katari.sample.time.domain.TimeRepository;
/** Save user command.
*
* The execution of this command saves a user into the user repository.
*
* @author nicolas.frontini
*/
public class SaveTimeEntryCommand implements ValidatableCommand<Void> {
/** The time repository.
*/
private TimeRepository timeRepository;
/** The id of the time entry.
*/
private long timeEntryId = 0;
/** The project name.
*/
private long projectId;
/** The activity name.
*/
private long activityId;
/** The start time.
*/
private String start = null;
/** The duration time.
*/
private int duration;
/** The comment.
*/
private String comment;
/** The date.
*/
private Date date = new Date();
/** The contructor with the time repository.
*
* @param theTimeRepository The time repository. It cannot be null.
*/
public SaveTimeEntryCommand(final TimeRepository theTimeRepository) {
Validate.notNull(theTimeRepository, "The time repository cannot be null");
timeRepository = theTimeRepository;
}
/** Returns the id of the time entry.
*
* @return Returns the time entry id.
*/
public long getTimeEntryId() {
return timeEntryId;
}
/** Sets the id of the time entry.
*
* @param theTimeEntryId The id of the time entry.
*/
public void setTimeEntryId(final long theTimeEntryId) {
timeEntryId = theTimeEntryId;
}
/** Returns the project id.
*
* @return the project id.
*/
public long getProjectId() {
return projectId;
}
/** Sets the project id.
*
* @param theProjectId The project id.
*/
public void setProjectId(final long theProjectId) {
projectId = theProjectId;
}
/** Returns the activity id.
*
* @return the activity id.
*/
public long getActivityId() {
return activityId;
}
/** Sets the project id.
*
* @param theActivityId The activity id.
*/
public void setActivityId(final long theActivityId) {
activityId = theActivityId;
}
/** Returns the start time.
*
* @return the start time.
*/
public String getStart() {
return start;
}
/** Sets the start time.
*
* @param theStart The start time. It cannot be null.
*/
public void setStart(final String theStart) {
Validate.notNull(theStart, "The start time cannot be null.");
start = theStart;
}
/** Returns the duration of the period in minutes.
*
* @return The duration of the period in minutes, greater than 0.
*/
public int getDuration() {
return duration;
}
/** Sets the duration time.
*
* @param theDuration The duration of the period in minutes, greater than 0.
*/
public void setDuration(final int theDuration) {
duration = theDuration;
}
/** Returns the comment of the time entry.
*
* @return the comment.
*/
public String getComment() {
return comment;
}
/** Sets the comment of the time entry.
*
* @param theComment The comment. It cannot be null.
*/
public void setComment(final String theComment) {
Validate.notNull(theComment, "The comment cannot be null.");
comment = theComment;
}
/** Returns the date of the time entry. The default date is the current date.
*
* @return The date of the time entry.
*/
public Date getDate() {
return new Date(date.getTime());
}
/** Sets the date of the time entry.
*
* @param theDate The date. It cannot be null.
*/
public void setDate(final Date theDate) {
Validate.notNull(theDate, "The date cannot be null.");
date = new Date(theDate.getTime());
}
/** Saves the domain time entry into the repository.
*
* @return It returns nothing.
*/
public Void execute() {
Activity activity = timeRepository.findActivity(getActivityId());
Project project = timeRepository.findProject(getProjectId());
if ((null == activity) || (null == project)) {
throw new RuntimeException("Project or Activity cannot be null.");
}
TimePeriod period = new TimePeriod(getStart(), getDuration());
TimeEntry timeEntry;
if (getTimeEntryId() == 0) {
CoreUser user = SecurityUtils.getCurrentUser();
timeEntry = new TimeEntry(activity, user, project,
getDate(), period, getComment());
} else {
timeEntry = timeRepository.findTimeEntry(getTimeEntryId());
timeEntry.modify(activity, project, period, getComment());
}
timeRepository.save(timeEntry);
return null;
}
/** Validates this command.
*
* @param errors Contextual state about the validation process. It can not be
* null.
*/
public void validate(final Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "projectId", "required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "activityId", "required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "comment", "required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "duration", "required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "date", "required");
if (getDuration() <= 0) {
errors.rejectValue("duration", "positive");
}
validateTimePeriod(errors);
}
/** Validates the time period.
*
* @param errors Contextual state about the validation process. It can not be
* null.
*/
private void validateTimePeriod(final Errors errors) {
if (start.indexOf(':') == -1) {
errors.rejectValue("start", "invalid.format");
} else {
String[] hoursAndMinutes = start.split(":");
if (2 != hoursAndMinutes.length) {
errors.rejectValue("start", "invalid.format");
} else {
try {
int hours = Integer.parseInt(hoursAndMinutes[0]);
int minutes = Integer.parseInt(hoursAndMinutes[1]);
if ((hours < 0) || (hours > TimePeriod.MAX_HOURS)) {
errors.rejectValue("start", "invalid.hour",
new Object[] {hours}, "");
}
if ((minutes < 0) || (minutes > TimePeriod.MAX_MINUTES)) {
errors.rejectValue("start", "invalid.minutes",
new Object[] {minutes}, "");
}
int endingMinutes = getEndingMinutes(hours, minutes, getDuration());
if (endingMinutes
> TimePeriod.DAY_DURATION * TimePeriod.HOUR_DURATION) {
errors.rejectValue("start", "invalid.period");
}
} catch (NumberFormatException e) {
errors.rejectValue("start", "invalid.format");
}
}
}
}
/** Utility method for calculating the ending minutes of an entry
* given its components.
*
* @param theStartHour The starting hour.
*
* @param theStartMinutes The starting minutes.
*
* @param theDuration The duration.
*
* @return The ending minutes (total) of this period.
*/
private static int getEndingMinutes(final int theStartHour,
final int theStartMinutes, final int theDuration) {
return theStartHour * TimePeriod.HOUR_DURATION
+ theStartMinutes + theDuration;
}
}