Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix issue #1609 by checking if there are 7 weekend days in a row #1688

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,23 @@ of the License, or (at your option) any later version.
* @author bard
*/
abstract class GPCalendarBase implements GPCalendarCalc {

static final int MAX_WEEKEND_DAYS = 7;

private final List<GPCalendarListener> myListeners = Lists.newArrayList();
private String myName;
private String myId;

@Override
public String getID() {
return myId == null ? myName : myId;
}

@Override
public String getName() {
return myName;
}

@Override
public void setName(String name) {
myName = name;
Expand Down Expand Up @@ -94,39 +97,47 @@ public Date findClosest(Date time, TimeUnit timeUnit, MoveDirection direction, D
}

public Date findClosest(Date time, TimeUnit timeUnit, MoveDirection direction, DayType dayType, Date limit) {
return doFindClosest(time, timeUnit, direction, dayType, limit);
return doFindClosest(time, timeUnit, direction, dayType, limit, MAX_WEEKEND_DAYS);
}

protected Date doFindClosest(Date time, DateFrameable framer, MoveDirection direction, DayType dayType, Date limit) {

protected Date doFindClosest(Date time, DateFrameable framer, MoveDirection direction, DayType findDayType, Date dateLimit, int maxWeekendDays) {
if (maxWeekendDays == 0) {
throw new UnsupportedOperationException("Error: all days are configured as 'weekend day'. That's not meaningful. Please, configure at least one day as non-weekend.");
}
Date nextUnitStart = direction == GPCalendarCalc.MoveDirection.FORWARD ? framer.adjustRight(time)
: framer.jumpLeft(time);
int nextUnitMask = getDayMask(nextUnitStart);
switch (dayType) {
case WORKING:
if ((nextUnitMask & DayMask.WORKING) == DayMask.WORKING) {
return nextUnitStart;
}
break;
case WEEKEND:
case HOLIDAY:
case NON_WORKING:
if ((nextUnitMask & DayMask.WORKING) == 0) {
return nextUnitStart;
}
break;
default:
assert false : "Should not be here";
if ((nextUnitMask & DayMask.WEEKEND) == DayMask.WEEKEND) {
maxWeekendDays--;
} else {
maxWeekendDays = MAX_WEEKEND_DAYS;
}
if (limit != null) {
if (direction == MoveDirection.FORWARD && nextUnitStart.compareTo(limit) >= 0
|| direction == MoveDirection.BACKWARD && nextUnitStart.compareTo(limit) <= 0) {
switch (findDayType) {
case WORKING:
if ((nextUnitMask & DayMask.WORKING) == DayMask.WORKING) {
return nextUnitStart;
}
break;
case WEEKEND:
case HOLIDAY:
case NON_WORKING:
if ((nextUnitMask & DayMask.WORKING) == 0) {
return nextUnitStart;
}
break;
default:
assert false : "Should not be here";
}
if (dateLimit != null) {
if (direction == MoveDirection.FORWARD && nextUnitStart.compareTo(dateLimit) >= 0
|| direction == MoveDirection.BACKWARD && nextUnitStart.compareTo(dateLimit) <= 0) {
return null;
}
}
return doFindClosest(nextUnitStart, framer, direction, dayType, limit);
return doFindClosest(nextUnitStart, framer, direction, findDayType, dateLimit, maxWeekendDays);
}


@Override
public void addListener(GPCalendarListener listener) {
myListeners.add(listener);
Expand All @@ -141,5 +152,6 @@ protected void fireCalendarChanged() {
}
}
}

public abstract int getDayMask(Date date);
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public List<GPCalendarActivity> getActivities(Date startDate, final Date endDate
boolean isWeekendState = (getDayMask(curDayStart) & DayMask.WORKING) == 0;
while (curDayStart.before(endDate)) {
Date changeStateDayStart = doFindClosest(curDayStart, myFramer, MoveDirection.FORWARD,
isWeekendState ? DayType.WORKING : DayType.NON_WORKING, endDate);
isWeekendState ? DayType.WORKING : DayType.NON_WORKING, endDate, MAX_WEEKEND_DAYS);
if (changeStateDayStart == null) {
changeStateDayStart = endDate;
}
Expand Down Expand Up @@ -214,7 +214,7 @@ public Date findClosestWorkingTime(Date time) {
if ((dayMask & DayMask.WORKING) == DayMask.WORKING) {
return time;
}
return doFindClosest(time, myFramer, MoveDirection.FORWARD, DayType.WORKING, null);
return doFindClosest(time, myFramer, MoveDirection.FORWARD, DayType.WORKING, null, MAX_WEEKEND_DAYS);
}

private boolean isPublicHoliDay(Date curDayStart) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,24 @@
import java.util.List;
import java.util.Locale;

import biz.ganttproject.core.calendar.CalendarEvent.Type;
import biz.ganttproject.core.calendar.GPCalendar.DayMask;
import biz.ganttproject.core.calendar.GPCalendar.DayType;
import biz.ganttproject.core.time.CalendarFactory;

import biz.ganttproject.core.time.GanttCalendar;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

import junit.framework.TestCase;
import org.junit.Assert;

import static biz.ganttproject.core.calendar.GPCalendar.DayType.WEEKEND;
import static java.util.Calendar.*;

/**
* Tests for {@link WeekendsCalendarImpl} class.
* Tests for {@link WeekendCalendarImpl} class.
*
* @author dbarashev (Dmitry Barashev)
*/
Expand Down Expand Up @@ -130,4 +134,29 @@ public void testOneOffWorkingWeekend() {
assertEquals(0, calendar.getDayMask(CalendarFactory.createGanttCalendar(2014, 0, 11).getTime()) & DayMask.WORKING);
assertEquals(DayMask.WEEKEND, calendar.getDayMask(CalendarFactory.createGanttCalendar(2014, 0, 11).getTime()) & DayMask.WEEKEND);
}

/**
* @see <a href="https://github.com/bardsoftware/ganttproject/issues/1609>
* Issue 1609: Weird failures if all days are weekend days
* </a>
*/
public void test_When_AllDaysAreWeekend_then_aUnsupportedOperationExceptionPreventsStackOverflow() {
WeekendCalendarImpl calendar = new WeekendCalendarImpl();
calendar.setWeekDayType(MONDAY, WEEKEND);
calendar.setWeekDayType(TUESDAY, WEEKEND);
calendar.setWeekDayType(WEDNESDAY, WEEKEND);
calendar.setWeekDayType(THURSDAY, WEEKEND);
calendar.setWeekDayType(FRIDAY, WEEKEND);
calendar.setWeekDayType(SATURDAY, WEEKEND);
calendar.setWeekDayType(SUNDAY, WEEKEND);
calendar.setPublicHolidays(TEST_EVENTS);

GanttCalendar helper = CalendarFactory.createGanttCalendar(2014, JANUARY, 0);
try {
calendar.findClosestWorkingTime(helper.getTime());
Assert.fail("Expected to get an UnsupportedOperationException");
} catch (UnsupportedOperationException exception) {
assertNotNull(exception.getMessage());
}
}
}