From 95e823af2548e5646e164d4714ac7c19ac2efac1 Mon Sep 17 00:00:00 2001 From: Manuel Rego Casasnovas Date: Thu, 13 Aug 2009 13:00:55 +0200 Subject: [PATCH] ItEr21S10CUAltaCalendarioLaboral: Creating BaseCalendar and ExceptionDay entities. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Óscar González Fernández Removed comment with information present at LocalDate --- .../calendars/daos/BaseCalendarDAO.java | 19 + .../calendars/daos/IBaseCalendarDAO.java | 8 + .../calendars/entities/BaseCalendar.java | 445 ++++++++++++++++++ .../calendars/entities/ExceptionDay.java | 54 +++ .../navalplanner-business-spring-config.xml | 3 + .../calendars/entities/Calendars.hbm.xml | 55 +++ ...valplanner-business-spring-config-test.xml | 3 + ...navalplanner-webapp-spring-config-test.xml | 3 + 8 files changed, 590 insertions(+) create mode 100644 navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/BaseCalendarDAO.java create mode 100644 navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/IBaseCalendarDAO.java create mode 100644 navalplanner-business/src/main/java/org/navalplanner/business/calendars/entities/BaseCalendar.java create mode 100644 navalplanner-business/src/main/java/org/navalplanner/business/calendars/entities/ExceptionDay.java create mode 100644 navalplanner-business/src/main/resources/org/navalplanner/business/calendars/entities/Calendars.hbm.xml diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/BaseCalendarDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/BaseCalendarDAO.java new file mode 100644 index 000000000..fb7918d78 --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/BaseCalendarDAO.java @@ -0,0 +1,19 @@ +package org.navalplanner.business.calendars.daos; + +import org.navalplanner.business.calendars.entities.BaseCalendar; +import org.navalplanner.business.common.daos.GenericDAOHibernate; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; + +/** + * DAO for {@link BaseCalendar} + * + * @author Manuel Rego Casasnovas + */ +@Repository +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class BaseCalendarDAO extends GenericDAOHibernate + implements IBaseCalendarDAO { + +} diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/IBaseCalendarDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/IBaseCalendarDAO.java new file mode 100644 index 000000000..f8294fde2 --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/IBaseCalendarDAO.java @@ -0,0 +1,8 @@ +package org.navalplanner.business.calendars.daos; + +import org.navalplanner.business.calendars.entities.BaseCalendar; +import org.navalplanner.business.common.daos.IGenericDAO; + +public interface IBaseCalendarDAO extends IGenericDAO { + +} diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/calendars/entities/BaseCalendar.java b/navalplanner-business/src/main/java/org/navalplanner/business/calendars/entities/BaseCalendar.java new file mode 100644 index 000000000..1be370209 --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/calendars/entities/BaseCalendar.java @@ -0,0 +1,445 @@ +package org.navalplanner.business.calendars.entities; + +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import org.joda.time.DateTime; +import org.joda.time.DateTimeConstants; +import org.joda.time.LocalDate; +import org.navalplanner.business.common.BaseEntity; +import org.navalplanner.business.common.IValidable; +import org.navalplanner.business.common.exceptions.ValidationException; + +/** + * Represents a calendar with some exception days. A calendar is valid till the + * expiring date, when the next calendar starts to be valid. + * + * On the other hand, a calendar could be derived, and the derived calendar + * could add or overwrite some exceptions of its parent calendar. + * + * + * @author Manuel Rego Casasnovas + */ +public class BaseCalendar extends BaseEntity implements IValidable { + + public static BaseCalendar create() { + BaseCalendar baseCalendar = new BaseCalendar(); + baseCalendar.setNewObject(true); + return baseCalendar; + } + + private String name; + + private Integer monday = -1; + private Integer tuesday = -1; + private Integer wednesday = -1; + private Integer thursday = -1; + private Integer friday = -1; + private Integer saturday = -1; + private Integer sunday = -1; + + private BaseCalendar parent; + + private BaseCalendar previousCalendar; + + private BaseCalendar nextCalendar; + + private LocalDate expiringDate; + + private Set exceptions = new HashSet(); + + /** + * Constructor for hibernate. Do not use! + */ + public BaseCalendar() { + + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setMonday(Integer monday) { + this.monday = monday; + } + + public Integer getMonday() { + if ((monday == -1) && (parent != null)) { + return parent.getMonday(); + } else { + return monday; + } + } + + public void setTuesday(Integer tuesday) { + this.tuesday = tuesday; + } + + public Integer getTuesday() { + if ((tuesday == -1) && (parent != null)) { + return parent.getTuesday(); + } else { + return tuesday; + } + } + + public void setWednesday(Integer wednesday) { + this.wednesday = wednesday; + } + + public Integer getWednesday() { + if ((wednesday == -1) && (parent != null)) { + return parent.getWednesday(); + } else { + return wednesday; + } + } + + public void setThursday(Integer thursday) { + this.thursday = thursday; + } + + public Integer getThursday() { + if ((thursday == -1) && (parent != null)) { + return parent.getThursday(); + } else { + return thursday; + } + } + + public void setFriday(Integer friday) { + this.friday = friday; + } + + public Integer getFriday() { + if ((friday == -1) && (parent != null)) { + return parent.getFriday(); + } else { + return friday; + } + } + + public void setSaturday(Integer saturday) { + this.saturday = saturday; + } + + public Integer getSaturday() { + if ((saturday == -1) && (parent != null)) { + return parent.getSaturday(); + } else { + return saturday; + } + } + + public void setSunday(Integer sunday) { + this.sunday = sunday; + } + + public Integer getSunday() { + if ((sunday == -1) && (parent != null)) { + return parent.getSunday(); + } else { + return sunday; + } + } + + public BaseCalendar getParent() { + return parent; + } + + public BaseCalendar getPreviousCalendar() { + return previousCalendar; + } + + public BaseCalendar getNextCalendar() { + return nextCalendar; + } + + public LocalDate getExpiringDate() { + return expiringDate; + } + + public Set getExceptions() { + Set exceptionDays = new HashSet(); + exceptionDays.addAll(exceptions); + + if (parent != null) { + for (ExceptionDay exceptionDay : parent.getExceptions()) { + if (!isExceptionDayAlreadyInExceptions(exceptionDay)) { + exceptionDays.add(exceptionDay); + } + } + } + + return Collections.unmodifiableSet(exceptionDays); + } + + private boolean isExceptionDayAlreadyInExceptions(ExceptionDay exceptionDay) { + for (ExceptionDay day : exceptions) { + if (day.getDate().equals(exceptionDay.getDate())) { + return true; + } + } + + return false; + } + + public void addExceptionDay(ExceptionDay day) + throws IllegalArgumentException { + if (isExceptionDayAlreadyInExceptions(day)) { + throw new IllegalArgumentException( + "This day is already in the exception days"); + } + exceptions.add(day); + } + + public void removeExceptionDay(Date date) throws IllegalArgumentException { + removeExceptionDay(new LocalDate(date)); + } + + public void removeExceptionDay(LocalDate date) + throws IllegalArgumentException { + + ExceptionDay day = getExceptionDay(date); + if (day == null) { + throw new IllegalArgumentException( + "There is not an exception day on that date"); + } + + exceptions.remove(day); + } + + public void updateExceptionDay(LocalDate date, Integer hours) + throws IllegalArgumentException { + removeExceptionDay(date); + ExceptionDay day = ExceptionDay.create(date, hours); + addExceptionDay(day); + } + + private ExceptionDay getExceptionDay(LocalDate date) { + for (ExceptionDay exceptionDay : exceptions) { + if (exceptionDay.getDate().equals(date)) { + return exceptionDay; + } + } + + return null; + } + + private boolean shouldUsePreviousCalendar(LocalDate date) { + return ((previousCalendar != null) && (date.compareTo(previousCalendar + .getExpiringDate()) < 0)); + } + + private boolean shouldUseNextCalendar(LocalDate date) { + if ((getExpiringDate() != null) + && (getExpiringDate().compareTo(date) <= 0)) { + if (nextCalendar == null) { + throw new RuntimeException("A next calendar should exist " + + "if current calendar has a expiring date fixed"); + } + + return true; + } + + return false; + } + + /** + * Returns the number of workable hours for a specific date depending on the + * calendar restrictions. + */ + public Integer getWorkableHours(Date date) { + return getWorkableHours(new LocalDate(date)); + } + + /** + * Returns the number of workable hours for a specific date depending on the + * calendar restrictions. + */ + public Integer getWorkableHours(LocalDate date) { + if (shouldUsePreviousCalendar(date)) { + return previousCalendar.getWorkableHours(date); + } else if (shouldUseNextCalendar(date)) { + return nextCalendar.getWorkableHours(date); + } + + for (ExceptionDay exceptionDay : getExceptions()) { + if (exceptionDay.getDate().equals(date)) { + return exceptionDay.getHours(); + } + } + + switch (date.getDayOfWeek()) { + case DateTimeConstants.MONDAY: + return getMonday(); + + case DateTimeConstants.TUESDAY: + return getTuesday(); + + case DateTimeConstants.WEDNESDAY: + return getWednesday(); + + case DateTimeConstants.THURSDAY: + return getThursday(); + + case DateTimeConstants.FRIDAY: + return getFriday(); + + case DateTimeConstants.SATURDAY: + return getSaturday(); + + case DateTimeConstants.SUNDAY: + return getSunday(); + + default: + throw new RuntimeException("Day of week out of range!"); + } + + } + + /** + * Returns the number of workable hours for a specific period depending on + * the calendar restrictions. + */ + public Integer getWorkableHours(Date initDate, Date endDate) { + return getWorkableHours(new LocalDate(initDate), new LocalDate(endDate)); + } + + /** + * Returns the number of workable hours for a specific period depending on + * the calendar restrictions. + */ + public Integer getWorkableHours(LocalDate init, LocalDate end) { + int total = 0; + + while (init.compareTo(end) <= 0) { + total += getWorkableHours(init); + init = init.plusDays(1); + } + + return total; + } + + /** + * Returns the number of workable hours for a specific week depending on the + * calendar restrictions. + */ + public Integer getWorkableHoursPerWeek(Date date) { + DateTime week = new DateTime(date); + DateTime init = week.dayOfWeek().withMinimumValue(); + DateTime end = week.dayOfWeek().withMaximumValue(); + + return getWorkableHours(init.toDate(), end.toDate()); + } + + /** + * Returns the number of workable hours for a specific week depending on the + * calendar restrictions. + */ + public Integer getWorkableHoursPerWeek(LocalDate date) { + LocalDate init = date.dayOfWeek().withMinimumValue(); + LocalDate end = date.dayOfWeek().withMaximumValue(); + + return getWorkableHours(init, end); + } + + @Override + public void checkValid() throws ValidationException { + if (parent == null) { + if ((monday == -1) || (thursday == -1) || (wednesday == -1) + || (tuesday == -1) || (friday == -1) || (saturday == -1) + || (sunday == -1)) { + throw new ValidationException( + "Daily hours could not have the default value " + + "if the calendar is not derivated"); + } + } + + if ((nextCalendar == null) && (expiringDate != null)) { + throw new ValidationException("A next calendar should exist " + + "if current calendar has a expiring date fixed"); + } + if ((nextCalendar != null) && (expiringDate == null)) { + throw new ValidationException("A expiring date should be fixed" + + "if current calendar has a next calendar"); + } + } + + /** + * Creates a new {@link BaseCalendar} derived from the current calendar. The + * new calendar will be the child of the current calendar. + * + * @return The derived calendar + */ + public BaseCalendar newDerivedCalendar() { + BaseCalendar derivedCalendar = create(); + derivedCalendar.parent = this; + return derivedCalendar; + } + + /** + * Creates a new version this {@link BaseCalendar} from the current moment. + * It makes that the current calendar expires in the current date. And the + * new calendar will be used from now onwards. + */ + public BaseCalendar newVersion() { + return newVersion(new LocalDate()); + } + + /** + * Creates a new version this {@link BaseCalendar} from the specific date. + * It makes that the current calendar expires in the specific date. And the + * new calendar will be used from that date onwards. + */ + public BaseCalendar newVersion(Date date) { + return newVersion(new LocalDate(date)); + } + + /** + * Creates a new version this {@link BaseCalendar} from the specific date. + * It makes that the current calendar expires in the specific date. And the + * new calendar will be used from that date onwards. + */ + public BaseCalendar newVersion(LocalDate date) { + if (nextCalendar != null) { + nextCalendar.newVersion(date); + } + + BaseCalendar nextCalendar = copy(); + + this.expiringDate = date; + + this.nextCalendar = nextCalendar; + nextCalendar.previousCalendar = this; + + return nextCalendar; + } + + private BaseCalendar copy() { + BaseCalendar copy = create(); + + copy.name = this.name; + + copy.monday = this.monday; + copy.tuesday = this.tuesday; + copy.wednesday = this.wednesday; + copy.thursday = this.thursday; + copy.friday = this.friday; + copy.saturday = this.saturday; + copy.sunday = this.sunday; + + copy.exceptions = new HashSet(this.exceptions); + + copy.parent = this.parent; + + return copy; + } + +} diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/calendars/entities/ExceptionDay.java b/navalplanner-business/src/main/java/org/navalplanner/business/calendars/entities/ExceptionDay.java new file mode 100644 index 000000000..0d8115c6c --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/calendars/entities/ExceptionDay.java @@ -0,0 +1,54 @@ +package org.navalplanner.business.calendars.entities; + +import java.util.Date; + +import org.joda.time.LocalDate; +import org.navalplanner.business.common.BaseEntity; + +/** + * Represents an exceptional day that has a different number of hours. For + * example, a bank holiday. + * + * It is used for the {@link BaseCalendar}. + * + * @author Manuel Rego Casasnovas + */ +public class ExceptionDay extends BaseEntity { + + public static ExceptionDay create(Date date, Integer hours) { + ExceptionDay exceptionDay = new ExceptionDay(new LocalDate(date), hours); + exceptionDay.setNewObject(true); + return exceptionDay; + } + + public static ExceptionDay create(LocalDate date, Integer hours) { + ExceptionDay exceptionDay = new ExceptionDay(date, hours); + exceptionDay.setNewObject(true); + return exceptionDay; + } + + private LocalDate date; + + private Integer hours; + + /** + * Constructor for hibernate. Do not use! + */ + public ExceptionDay() { + + } + + private ExceptionDay(LocalDate date, Integer hours) { + this.date = date; + this.hours = hours; + } + + public LocalDate getDate() { + return date; + } + + public Integer getHours() { + return hours; + } + +} diff --git a/navalplanner-business/src/main/resources/navalplanner-business-spring-config.xml b/navalplanner-business/src/main/resources/navalplanner-business-spring-config.xml index a31878e8b..674278780 100644 --- a/navalplanner-business/src/main/resources/navalplanner-business-spring-config.xml +++ b/navalplanner-business/src/main/resources/navalplanner-business-spring-config.xml @@ -40,6 +40,9 @@ org/navalplanner/business/workreports/entities/WorkReports.hbm.xml + + org/navalplanner/business/calendars/entities/Calendars.hbm.xml + diff --git a/navalplanner-business/src/main/resources/org/navalplanner/business/calendars/entities/Calendars.hbm.xml b/navalplanner-business/src/main/resources/org/navalplanner/business/calendars/entities/Calendars.hbm.xml new file mode 100644 index 000000000..064a0d67b --- /dev/null +++ b/navalplanner-business/src/main/resources/org/navalplanner/business/calendars/entities/Calendars.hbm.xml @@ -0,0 +1,55 @@ + + + + + + + + + 100 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 100 + + + + + + + + + + diff --git a/navalplanner-business/src/test/resources/navalplanner-business-spring-config-test.xml b/navalplanner-business/src/test/resources/navalplanner-business-spring-config-test.xml index b88d3f1fb..72d72df3f 100644 --- a/navalplanner-business/src/test/resources/navalplanner-business-spring-config-test.xml +++ b/navalplanner-business/src/test/resources/navalplanner-business-spring-config-test.xml @@ -47,6 +47,9 @@ org/navalplanner/business/planner/entities/ResourceAllocations.hbm.xml + + + org/navalplanner/business/calendars/entities/Calendars.hbm.xml TestEntities.hbm.xml diff --git a/navalplanner-webapp/src/test/resources/navalplanner-webapp-spring-config-test.xml b/navalplanner-webapp/src/test/resources/navalplanner-webapp-spring-config-test.xml index 8e6896099..4a5b37c06 100644 --- a/navalplanner-webapp/src/test/resources/navalplanner-webapp-spring-config-test.xml +++ b/navalplanner-webapp/src/test/resources/navalplanner-webapp-spring-config-test.xml @@ -48,6 +48,9 @@ org/navalplanner/business/planner/entities/ResourceAllocations.hbm.xml + + org/navalplanner/business/calendars/entities/Calendars.hbm.xml +