Update Commons Lang.
Code refactoring.
This commit is contained in:
parent
3852c49972
commit
5d2cb8683c
44 changed files with 1992 additions and 1858 deletions
|
|
@ -112,8 +112,8 @@
|
|||
<artifactId>commons-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-collections</groupId>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
package org.zkoss.ganttz;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.zkoss.ganttz.extensions.ICommand;
|
||||
import org.zkoss.ganttz.extensions.IContext;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
|
|
@ -31,8 +31,7 @@ import org.zkoss.zul.Button;
|
|||
|
||||
class CommandContextualized<T> {
|
||||
|
||||
public static <T> CommandContextualized<T> create(ICommand<T> command,
|
||||
IContext<T> context) {
|
||||
public static <T> CommandContextualized<T> create(ICommand<T> command, IContext<T> context) {
|
||||
return new CommandContextualized<T>(command, context);
|
||||
}
|
||||
|
||||
|
|
@ -52,28 +51,31 @@ class CommandContextualized<T> {
|
|||
}
|
||||
|
||||
Button toButton() {
|
||||
if (button != null) {
|
||||
if ( button != null ) {
|
||||
return button;
|
||||
}
|
||||
|
||||
Button result = new Button();
|
||||
if (StringUtils.isEmpty(command.getImage())) {
|
||||
if ( StringUtils.isEmpty(command.getImage()) ) {
|
||||
result.setLabel(command.getName());
|
||||
} else {
|
||||
result.setImage(command.getImage());
|
||||
result.setTooltiptext(command.getName());
|
||||
}
|
||||
if (command.isDisabled()) {
|
||||
|
||||
if ( command.isDisabled() ) {
|
||||
result.setDisabled(true);
|
||||
} else {
|
||||
result.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
doAction();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
button = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,15 +19,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
package org.zkoss.ganttz;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
import org.apache.commons.lang.math.Fraction;
|
||||
import org.apache.commons.lang3.math.Fraction;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.joda.time.LocalDate;
|
||||
|
|
@ -43,16 +41,13 @@ public class DatesMapperOnInterval implements IDatesMapper {
|
|||
public DatesMapperOnInterval(int horizontalSize, Interval interval) {
|
||||
this.horizontalSize = horizontalSize;
|
||||
this.interval = interval;
|
||||
this.millisecondsPerPixel = interval.getLengthBetween().getMillis()
|
||||
/ horizontalSize;
|
||||
this.pixelsPerDay = Fraction.getFraction(horizontalSize, interval
|
||||
.getDaysBetween().getDays());
|
||||
this.millisecondsPerPixel = interval.getLengthBetween().getMillis() / horizontalSize;
|
||||
this.pixelsPerDay = Fraction.getFraction(horizontalSize, interval.getDaysBetween().getDays());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate toDate(int pixels) {
|
||||
int daysInto = Fraction.getFraction(pixels, 1).divideBy(pixelsPerDay)
|
||||
.intValue();
|
||||
int daysInto = Fraction.getFraction(pixels, 1).divideBy(pixelsPerDay).intValue();
|
||||
return getInterval().getStart().plusDays(daysInto);
|
||||
}
|
||||
|
||||
|
|
@ -71,29 +66,29 @@ public class DatesMapperOnInterval implements IDatesMapper {
|
|||
|
||||
private int toPixels(Fraction proportion) {
|
||||
try {
|
||||
return proportion.multiplyBy(Fraction.getFraction(horizontalSize, 1))
|
||||
.intValue();
|
||||
return proportion.multiplyBy(Fraction.getFraction(horizontalSize, 1)).intValue();
|
||||
} catch (ArithmeticException e) {
|
||||
double d = Math.log10(horizontalSize);
|
||||
int scale = (int) d + 1;
|
||||
|
||||
BigDecimal quotient = new BigDecimal(proportion.getNumerator())
|
||||
.divide(new BigDecimal(proportion.getDenominator()), scale,
|
||||
RoundingMode.HALF_UP);
|
||||
return quotient.multiply(new BigDecimal(horizontalSize))
|
||||
.intValue();
|
||||
.divide(new BigDecimal(proportion.getDenominator()), scale, RoundingMode.HALF_UP);
|
||||
|
||||
return quotient.multiply(new BigDecimal(horizontalSize)).intValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int toPixels(ReadableDuration duration) {
|
||||
DateTime end = getInterval().getStart().toDateTimeAtStartOfDay()
|
||||
.plus(duration);
|
||||
DateTime end = getInterval().getStart().toDateTimeAtStartOfDay().plus(duration);
|
||||
|
||||
return toPixels(getProportion(end));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int toPixelsAbsolute(long milliseconds) {
|
||||
DateTime date = new DateTime(milliseconds);
|
||||
|
||||
return this.toPixels(getProportion(date));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import java.beans.PropertyChangeEvent;
|
|||
import java.beans.PropertyChangeListener;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.zkoss.ganttz.data.Dependency;
|
||||
import org.zkoss.ganttz.data.DependencyType;
|
||||
import org.zkoss.ganttz.data.GanttDate;
|
||||
|
|
@ -62,13 +62,13 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
|||
|
||||
private boolean violated = false;
|
||||
|
||||
public DependencyComponent(TaskComponent source, TaskComponent destination,
|
||||
Dependency dependency) {
|
||||
public DependencyComponent(TaskComponent source, TaskComponent destination, Dependency dependency) {
|
||||
Validate.notNull(dependency);
|
||||
Validate.notNull(source);
|
||||
Validate.notNull(destination);
|
||||
Validate.isTrue(source.getTask() == dependency.getSource());
|
||||
Validate.isTrue(destination.getTask() == dependency.getDestination());
|
||||
|
||||
this.type = dependency.getType();
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
|
|
@ -76,8 +76,7 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
|||
}
|
||||
|
||||
private void sendCSSUpdate() {
|
||||
response("constraintViolated", new AuInvoke(DependencyComponent.this,
|
||||
"setCSSClass", getCSSClass()));
|
||||
response("constraintViolated", new AuInvoke(DependencyComponent.this, "setCSSClass", getCSSClass()));
|
||||
}
|
||||
|
||||
public String getCSSClass() {
|
||||
|
|
@ -88,9 +87,10 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
|||
|
||||
@Override
|
||||
public void afterCompose() {
|
||||
if (listenerAdded) {
|
||||
if ( listenerAdded ) {
|
||||
return;
|
||||
}
|
||||
|
||||
listener = new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
|
|
@ -98,11 +98,11 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
|||
redrawDependency();
|
||||
}
|
||||
};
|
||||
|
||||
this.source.getTask().addFundamentalPropertiesChangeListener(listener);
|
||||
this.destination.getTask().addFundamentalPropertiesChangeListener(listener);
|
||||
|
||||
violationListener = Constraint
|
||||
.onlyOnZKExecution(new IConstraintViolationListener<GanttDate>() {
|
||||
violationListener = Constraint.onlyOnZKExecution(new IConstraintViolationListener<GanttDate>() {
|
||||
|
||||
@Override
|
||||
public void constraintViolated(Constraint<GanttDate> constraint, GanttDate value) {
|
||||
|
|
@ -116,16 +116,17 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
|||
sendCSSUpdate();
|
||||
}
|
||||
});
|
||||
this.dependency.addConstraintViolationListener(violationListener,
|
||||
Mode.RECEIVE_PENDING);
|
||||
|
||||
this.dependency.addConstraintViolationListener(violationListener, Mode.RECEIVE_PENDING);
|
||||
|
||||
listenerAdded = true;
|
||||
}
|
||||
|
||||
public void removeChangeListeners() {
|
||||
if (!listenerAdded) {
|
||||
if ( !listenerAdded ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.source.getTask().removePropertyChangeListener(listener);
|
||||
this.destination.getTask().removePropertyChangeListener(listener);
|
||||
listenerAdded = false;
|
||||
|
|
@ -169,6 +170,7 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
|||
public boolean contains(Task task) {
|
||||
Task sourceTask = getSource().getTask();
|
||||
Task destinationTask = getDestination().getTask();
|
||||
|
||||
return task.equals(sourceTask) || task.equals(destinationTask);
|
||||
}
|
||||
|
||||
|
|
@ -191,8 +193,8 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
|||
public boolean hasSameSourceAndDestination(Dependency dependency) {
|
||||
Task sourceTask = source.getTask();
|
||||
Task destinationTask = destination.getTask();
|
||||
return sourceTask.equals(dependency.getSource())
|
||||
&& destinationTask.equals(dependency.getDestination());
|
||||
|
||||
return sourceTask.equals(dependency.getSource()) && destinationTask.equals(dependency.getDestination());
|
||||
}
|
||||
|
||||
protected void renderProperties(ContentRenderer renderer) throws IOException{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
package org.zkoss.ganttz;
|
||||
|
||||
import org.apache.commons.lang.math.Fraction;
|
||||
import org.apache.commons.lang3.math.Fraction;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.ReadableDuration;
|
||||
import org.zkoss.ganttz.util.Interval;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import java.util.Arrays;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.joda.time.LocalDate;
|
||||
|
|
@ -71,8 +71,6 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
LeftTasksTreeRow getAboveRow();
|
||||
}
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(LeftTasksTreeRow.class);
|
||||
|
||||
private final Task task;
|
||||
|
||||
private Label nameLabel;
|
||||
|
|
@ -101,20 +99,22 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
|
||||
private final IDisabilityConfiguration disabilityConfiguration;
|
||||
|
||||
public static LeftTasksTreeRow create(
|
||||
IDisabilityConfiguration disabilityConfiguration, Task bean,
|
||||
ILeftTasksTreeNavigator taskDetailnavigator, Planner planner) {
|
||||
return new LeftTasksTreeRow(disabilityConfiguration, bean,
|
||||
taskDetailnavigator, planner);
|
||||
public static LeftTasksTreeRow create(IDisabilityConfiguration disabilityConfiguration,
|
||||
Task bean,
|
||||
ILeftTasksTreeNavigator taskDetailnavigator,
|
||||
Planner planner) {
|
||||
|
||||
return new LeftTasksTreeRow(disabilityConfiguration, bean, taskDetailnavigator, planner);
|
||||
}
|
||||
|
||||
private LeftTasksTreeRow(IDisabilityConfiguration disabilityConfiguration,
|
||||
Task task, ILeftTasksTreeNavigator leftTasksTreeNavigator,
|
||||
Planner planner) {
|
||||
Task task,
|
||||
ILeftTasksTreeNavigator leftTasksTreeNavigator,
|
||||
Planner planner) {
|
||||
|
||||
this.disabilityConfiguration = disabilityConfiguration;
|
||||
this.task = task;
|
||||
this.dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locales
|
||||
.getCurrent());
|
||||
this.dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locales.getCurrent());
|
||||
this.leftTasksTreeNavigator = leftTasksTreeNavigator;
|
||||
this.planner = planner;
|
||||
}
|
||||
|
|
@ -143,13 +143,14 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
* the component that has received focus
|
||||
*/
|
||||
public void userWantsDateBox(Component component) {
|
||||
if (component == startDateTextBox) {
|
||||
if (canChangeStartDate()) {
|
||||
if ( component == startDateTextBox ) {
|
||||
if ( canChangeStartDate() ) {
|
||||
createDateBox(startDateTextBox);
|
||||
}
|
||||
}
|
||||
if (component == endDateTextBox) {
|
||||
if (canChangeEndDate()) {
|
||||
|
||||
if ( component == endDateTextBox ) {
|
||||
if ( canChangeEndDate() ) {
|
||||
createDateBox(endDateTextBox);
|
||||
}
|
||||
}
|
||||
|
|
@ -185,7 +186,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
|
||||
public void focusGoUp(int position) {
|
||||
LeftTasksTreeRow aboveDetail = leftTasksTreeNavigator.getAboveRow();
|
||||
if (aboveDetail != null) {
|
||||
if ( aboveDetail != null ) {
|
||||
aboveDetail.receiveFocus(position);
|
||||
}
|
||||
}
|
||||
|
|
@ -200,7 +201,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
|
||||
public void focusGoDown(int position) {
|
||||
LeftTasksTreeRow belowDetail = leftTasksTreeNavigator.getBelowRow();
|
||||
if (belowDetail != null) {
|
||||
if ( belowDetail != null ) {
|
||||
belowDetail.receiveFocus(position);
|
||||
} else {
|
||||
getListDetails().getGoingDownInLastArrowCommand().doAction();
|
||||
|
|
@ -212,6 +213,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
while (!(current instanceof LeftTasksTree)) {
|
||||
current = current.getParent();
|
||||
}
|
||||
|
||||
return (LeftTasksTree) current;
|
||||
}
|
||||
|
||||
|
|
@ -220,13 +222,15 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
List<Textbox> textBoxes = getTextBoxes();
|
||||
int position = textBoxes.indexOf(textbox);
|
||||
switch (navigation) {
|
||||
case UP:
|
||||
case UP:
|
||||
focusGoUp(position);
|
||||
break;
|
||||
case DOWN:
|
||||
|
||||
case DOWN:
|
||||
focusGoDown(position);
|
||||
break;
|
||||
default:
|
||||
|
||||
default:
|
||||
throw new RuntimeException("case not covered: " + navigation);
|
||||
}
|
||||
}
|
||||
|
|
@ -261,7 +265,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
}
|
||||
|
||||
private void registerTextboxesListeners() {
|
||||
if (disabilityConfiguration.isTreeEditable()) {
|
||||
if ( disabilityConfiguration.isTreeEditable() ) {
|
||||
registerKeyboardListener(nameBox);
|
||||
registerOnChange(nameBox);
|
||||
registerKeyboardListener(startDateTextBox);
|
||||
|
|
@ -275,9 +279,9 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
|
||||
private void findComponents(Treerow row) {
|
||||
List<Object> rowChildren = row.getChildren();
|
||||
List<Treecell> treeCells = ComponentsFinder.findComponentsOfType(Treecell.class,
|
||||
rowChildren);
|
||||
List<Treecell> treeCells = ComponentsFinder.findComponentsOfType(Treecell.class, rowChildren);
|
||||
assert treeCells.size() == 4;
|
||||
|
||||
findComponentsForNameCell(treeCells.get(0));
|
||||
findComponentsForStartDateCell(treeCells.get(1));
|
||||
findComponentsForEndDateCell(treeCells.get(2));
|
||||
|
|
@ -286,12 +290,11 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
|
||||
private static Textbox findTextBoxOfCell(Treecell treecell) {
|
||||
List<Object> children = treecell.getChildren();
|
||||
return ComponentsFinder.findComponentsOfType(Textbox.class, children)
|
||||
.get(0);
|
||||
return ComponentsFinder.findComponentsOfType(Textbox.class, children).get(0);
|
||||
}
|
||||
|
||||
private void findComponentsForNameCell(Treecell treecell) {
|
||||
if (disabilityConfiguration.isTreeEditable()) {
|
||||
if ( disabilityConfiguration.isTreeEditable() ) {
|
||||
nameBox = (Textbox) treecell.getChildren().get(0);
|
||||
} else {
|
||||
nameLabel = (Label) treecell.getChildren().get(0);
|
||||
|
|
@ -318,8 +321,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
});
|
||||
}
|
||||
|
||||
private void registerOnChangeDatebox(final Datebox datebox,
|
||||
final Textbox textbox) {
|
||||
private void registerOnChangeDatebox(final Datebox datebox, final Textbox textbox) {
|
||||
datebox.addEventListener("onChange", new EventListener() {
|
||||
|
||||
@Override
|
||||
|
|
@ -351,7 +353,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
}
|
||||
|
||||
private void findComponentsForStartDateCell(Treecell treecell) {
|
||||
if (disabilityConfiguration.isTreeEditable()) {
|
||||
if ( disabilityConfiguration.isTreeEditable() ) {
|
||||
startDateTextBox = findTextBoxOfCell(treecell);
|
||||
} else {
|
||||
startDateLabel = (Label) treecell.getChildren().get(0);
|
||||
|
|
@ -359,7 +361,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
}
|
||||
|
||||
private void findComponentsForEndDateCell(Treecell treecell) {
|
||||
if (disabilityConfiguration.isTreeEditable()) {
|
||||
if ( disabilityConfiguration.isTreeEditable() ) {
|
||||
endDateTextBox = findTextBoxOfCell(treecell);
|
||||
} else {
|
||||
endDateLabel = (Label) treecell.getChildren().get(0);
|
||||
|
|
@ -369,8 +371,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
private void findComponentsForStatusCell(Treecell treecell) {
|
||||
List<Object> children = treecell.getChildren();
|
||||
|
||||
Hlayout hlayout = ComponentsFinder.findComponentsOfType(Hlayout.class,
|
||||
children).get(0);
|
||||
Hlayout hlayout = ComponentsFinder.findComponentsOfType(Hlayout.class, children).get(0);
|
||||
|
||||
hoursStatusDiv = (Div) hlayout.getChildren().get(0);
|
||||
// there is a <label> "/" between the divs
|
||||
|
|
@ -389,15 +390,18 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
}
|
||||
|
||||
public void updateBean(Component updatedComponent) {
|
||||
if (updatedComponent == getNameBox()) {
|
||||
if ( updatedComponent == getNameBox() ) {
|
||||
|
||||
task.setName(getNameBox().getValue());
|
||||
if (StringUtils.isEmpty(getNameBox().getValue())) {
|
||||
|
||||
if ( StringUtils.isEmpty(getNameBox().getValue()) ) {
|
||||
getNameBox().setValue(task.getName());
|
||||
}
|
||||
} else if (updatedComponent == getStartDateTextBox()) {
|
||||
|
||||
} else if ( updatedComponent == getStartDateTextBox() ) {
|
||||
|
||||
try {
|
||||
final Date begin = dateFormat.parse(getStartDateTextBox()
|
||||
.getValue());
|
||||
final Date begin = dateFormat.parse(getStartDateTextBox().getValue());
|
||||
task.doPositionModifications(new IModifications() {
|
||||
|
||||
@Override
|
||||
|
|
@ -408,23 +412,26 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
} catch (ParseException e) {
|
||||
// Do nothing as textbox is rested in the next sentence
|
||||
}
|
||||
getStartDateTextBox().setValue(
|
||||
dateFormat.format(task.getBeginDate().toDayRoundedDate()));
|
||||
} else if (updatedComponent == getEndDateTextBox()) {
|
||||
|
||||
getStartDateTextBox().setValue(dateFormat.format(task.getBeginDate().toDayRoundedDate()));
|
||||
|
||||
} else if ( updatedComponent == getEndDateTextBox() ) {
|
||||
|
||||
try {
|
||||
Date newEnd = dateFormat.parse(getEndDateTextBox().getValue());
|
||||
task.resizeTo(LocalDate.fromDateFields(newEnd));
|
||||
} catch (ParseException e) {
|
||||
// Do nothing as textbox is rested in the next sentence
|
||||
}
|
||||
getEndDateTextBox().setValue(
|
||||
asString(task.getEndDate().toDayRoundedDate()));
|
||||
|
||||
getEndDateTextBox().setValue(asString(task.getEndDate().toDayRoundedDate()));
|
||||
}
|
||||
|
||||
planner.updateTooltips();
|
||||
}
|
||||
|
||||
private void updateComponents() {
|
||||
if (disabilityConfiguration.isTreeEditable()) {
|
||||
if ( disabilityConfiguration.isTreeEditable() ) {
|
||||
getNameBox().setValue(task.getName());
|
||||
getNameBox().setDisabled(!canRenameTask());
|
||||
getNameBox().setTooltiptext(task.getName());
|
||||
|
|
@ -432,42 +439,35 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
getStartDateTextBox().setDisabled(!canChangeStartDate());
|
||||
getEndDateTextBox().setDisabled(!canChangeEndDate());
|
||||
|
||||
getStartDateTextBox().setValue(
|
||||
asString(task.getBeginDate().toDayRoundedDate()));
|
||||
getEndDateTextBox().setValue(
|
||||
asString(task.getEndDate().toDayRoundedDate()));
|
||||
getStartDateTextBox().setValue(asString(task.getBeginDate().toDayRoundedDate()));
|
||||
getEndDateTextBox().setValue(asString(task.getEndDate().toDayRoundedDate()));
|
||||
} else {
|
||||
nameLabel.setValue(task.getName());
|
||||
nameLabel.setTooltiptext(task.getName());
|
||||
nameLabel.setSclass("clickable-rows");
|
||||
|
||||
nameLabel.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||
@Override
|
||||
public void onEvent(Event arg0) throws Exception {
|
||||
Executions.getCurrent().sendRedirect(
|
||||
"/planner/index.zul;order="
|
||||
+ task.getProjectCode());
|
||||
Executions.getCurrent().sendRedirect("/planner/index.zul;order=" + task.getProjectCode());
|
||||
}
|
||||
});
|
||||
startDateLabel.setValue(asString(task.getBeginDate()
|
||||
.toDayRoundedDate()));
|
||||
endDateLabel.setValue(asString(task.getEndDate()
|
||||
.toDayRoundedDate()));
|
||||
}
|
||||
setHoursStatus(task.getProjectHoursStatus(),
|
||||
task.getTooltipTextForProjectHoursStatus());
|
||||
|
||||
setBudgetStatus(task.getProjectBudgetStatus(),
|
||||
task.getTooltipTextForProjectBudgetStatus());
|
||||
startDateLabel.setValue(asString(task.getBeginDate().toDayRoundedDate()));
|
||||
endDateLabel.setValue(asString(task.getEndDate().toDayRoundedDate()));
|
||||
}
|
||||
|
||||
setHoursStatus(task.getProjectHoursStatus(), task.getTooltipTextForProjectHoursStatus());
|
||||
|
||||
setBudgetStatus(task.getProjectBudgetStatus(), task.getTooltipTextForProjectBudgetStatus());
|
||||
}
|
||||
|
||||
private boolean canChangeStartDate() {
|
||||
return disabilityConfiguration.isMovingTasksEnabled()
|
||||
&& task.canBeExplicitlyMoved();
|
||||
return disabilityConfiguration.isMovingTasksEnabled() && task.canBeExplicitlyMoved();
|
||||
}
|
||||
|
||||
private boolean canChangeEndDate() {
|
||||
return disabilityConfiguration.isResizingTasksEnabled()
|
||||
&& task.canBeExplicitlyResized();
|
||||
return disabilityConfiguration.isResizingTasksEnabled() && task.canBeExplicitlyResized();
|
||||
}
|
||||
|
||||
private boolean canRenameTask() {
|
||||
|
|
@ -508,29 +508,31 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
|
||||
private String getProjectStatusSclass(ProjectStatusEnum status) {
|
||||
String cssClass;
|
||||
|
||||
switch (status) {
|
||||
case MARGIN_EXCEEDED:
|
||||
case MARGIN_EXCEEDED:
|
||||
cssClass = "status-red";
|
||||
break;
|
||||
case WITHIN_MARGIN:
|
||||
|
||||
case WITHIN_MARGIN:
|
||||
cssClass = "status-orange";
|
||||
break;
|
||||
case AS_PLANNED:
|
||||
default:
|
||||
|
||||
case AS_PLANNED:
|
||||
|
||||
default:
|
||||
cssClass = "status-green";
|
||||
}
|
||||
|
||||
return cssClass;
|
||||
}
|
||||
|
||||
private void onProjectStatusClick(Component statucComp) {
|
||||
if (!disabilityConfiguration.isTreeEditable()) {
|
||||
if ( !disabilityConfiguration.isTreeEditable() ) {
|
||||
statucComp.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||
@Override
|
||||
public void onEvent(Event arg0) throws Exception {
|
||||
Executions.getCurrent()
|
||||
.sendRedirect(
|
||||
"/planner/index.zul;order="
|
||||
+ task.getProjectCode());
|
||||
Executions.getCurrent().sendRedirect("/planner/index.zul;order=" + task.getProjectCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import java.util.Date;
|
|||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Days;
|
||||
import org.joda.time.Duration;
|
||||
|
|
@ -40,7 +40,6 @@ import org.zkoss.ganttz.data.ITaskFundamentalProperties.IUpdatablePosition;
|
|||
import org.zkoss.ganttz.data.Milestone;
|
||||
import org.zkoss.ganttz.data.Task;
|
||||
import org.zkoss.ganttz.data.Task.IReloadResourcesTextRequested;
|
||||
import org.zkoss.ganttz.data.TaskContainer;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener;
|
||||
import org.zkoss.ganttz.util.WeakReferencedListeners.Mode;
|
||||
|
|
@ -81,88 +80,91 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
private PropertyChangeListener showingMoneyCostBarPropertyListener;
|
||||
|
||||
public static TaskComponent asTaskComponent(Task task,
|
||||
IDisabilityConfiguration disabilityConfiguration,
|
||||
boolean isTopLevel) {
|
||||
IDisabilityConfiguration disabilityConfiguration,
|
||||
boolean isTopLevel) {
|
||||
final TaskComponent result;
|
||||
if (task.isContainer()) {
|
||||
result = TaskContainerComponent.asTask((TaskContainer) task,
|
||||
disabilityConfiguration);
|
||||
} else if (task instanceof Milestone) {
|
||||
|
||||
if ( task.isContainer() ) {
|
||||
result = TaskContainerComponent.asTask(task, disabilityConfiguration);
|
||||
|
||||
} else if ( task instanceof Milestone ) {
|
||||
result = new MilestoneComponent(task, disabilityConfiguration);
|
||||
|
||||
} else {
|
||||
result = new TaskComponent(task, disabilityConfiguration);
|
||||
}
|
||||
result.isTopLevel = isTopLevel;
|
||||
|
||||
return TaskRow.wrapInRow(result);
|
||||
}
|
||||
|
||||
public static TaskComponent asTaskComponent(Task task,
|
||||
IDisabilityConfiguration disabilityConfiguration) {
|
||||
public static TaskComponent asTaskComponent(Task task, IDisabilityConfiguration disabilityConfiguration) {
|
||||
return asTaskComponent(task, disabilityConfiguration, true);
|
||||
}
|
||||
|
||||
private IReloadResourcesTextRequested reloadResourcesTextRequested;
|
||||
|
||||
public TaskComponent(Task task,
|
||||
IDisabilityConfiguration disabilityConfiguration) {
|
||||
public TaskComponent(Task task, IDisabilityConfiguration disabilityConfiguration) {
|
||||
setHeight(HEIGHT_PER_TASK + "px");
|
||||
setContext("idContextMenuTaskAssignment");
|
||||
this.task = task;
|
||||
setClass(calculateCSSClass());
|
||||
setId(UUID.randomUUID().toString());
|
||||
this.disabilityConfiguration = disabilityConfiguration;
|
||||
taskViolationListener = Constraint
|
||||
.onlyOnZKExecution(new IConstraintViolationListener<GanttDate>() {
|
||||
taskViolationListener = Constraint.onlyOnZKExecution(new IConstraintViolationListener<GanttDate>() {
|
||||
|
||||
@Override
|
||||
public void constraintViolated(Constraint<GanttDate> constraint,
|
||||
GanttDate value) {
|
||||
public void constraintViolated(Constraint<GanttDate> constraint, GanttDate value) {
|
||||
// TODO mark graphically task as violated
|
||||
}
|
||||
|
||||
@Override
|
||||
public void constraintSatisfied(Constraint<GanttDate> constraint,
|
||||
GanttDate value) {
|
||||
public void constraintSatisfied(Constraint<GanttDate> constraint, GanttDate value) {
|
||||
// TODO mark graphically dependency as not violated
|
||||
}
|
||||
});
|
||||
this.task.addConstraintViolationListener(taskViolationListener,
|
||||
Mode.RECEIVE_PENDING);
|
||||
});
|
||||
|
||||
this.task.addConstraintViolationListener(taskViolationListener, Mode.RECEIVE_PENDING);
|
||||
reloadResourcesTextRequested = new IReloadResourcesTextRequested() {
|
||||
|
||||
@Override
|
||||
public void reloadResourcesTextRequested() {
|
||||
if (canShowResourcesText()) {
|
||||
if ( canShowResourcesText() ) {
|
||||
smartUpdate("resourcesText", getResourcesText());
|
||||
}
|
||||
|
||||
String cssClass = calculateCSSClass();
|
||||
|
||||
response("setClass", new AuInvoke(TaskComponent.this,
|
||||
"setClass", cssClass));
|
||||
response("setClass", new AuInvoke(TaskComponent.this, "setClass", cssClass));
|
||||
|
||||
// FIXME: Refactorize to another listener
|
||||
// FIXME: Refactor to another listener
|
||||
updateDeadline();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.task.addReloadListener(reloadResourcesTextRequested);
|
||||
|
||||
setAuService(new AuService(){
|
||||
|
||||
public boolean service(AuRequest request, boolean everError){
|
||||
String command = request.getCommand();
|
||||
final TaskComponent ta;
|
||||
|
||||
if (command.equals("onUpdatePosition")){
|
||||
if ( command.equals("onUpdatePosition") ){
|
||||
ta = retrieveTaskComponent(request);
|
||||
|
||||
ta.doUpdatePosition(
|
||||
toInteger(retrieveData(request, "left")),
|
||||
toInteger(retrieveData(request, "top")));
|
||||
toInteger(retrieveData(request, "left"))
|
||||
);
|
||||
|
||||
Events.postEvent(new Event(getId(), ta, request.getData()));
|
||||
|
||||
return true;
|
||||
}
|
||||
if (command.equals("onUpdateWidth")){
|
||||
|
||||
if ( command.equals("onUpdateWidth") ){
|
||||
ta = retrieveTaskComponent(request);
|
||||
|
||||
ta.doUpdateSize(toInteger(retrieveData(request, "width")));
|
||||
|
|
@ -170,7 +172,8 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
|
||||
return true;
|
||||
}
|
||||
if (command.equals("onAddDependency")){
|
||||
|
||||
if ( command.equals("onAddDependency") ){
|
||||
ta = retrieveTaskComponent(request);
|
||||
|
||||
ta.doAddDependency((String) retrieveData(request, "dependencyId"));
|
||||
|
|
@ -178,6 +181,7 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -188,9 +192,8 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
private TaskComponent retrieveTaskComponent(AuRequest request){
|
||||
final TaskComponent ta = (TaskComponent) request.getComponent();
|
||||
|
||||
if (ta == null) {
|
||||
throw new UiException(MZk.ILLEGAL_REQUEST_COMPONENT_REQUIRED,
|
||||
this);
|
||||
if ( ta == null ) {
|
||||
throw new UiException(MZk.ILLEGAL_REQUEST_COMPONENT_REQUIRED, this);
|
||||
}
|
||||
|
||||
return ta;
|
||||
|
|
@ -198,9 +201,8 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
|
||||
private Object retrieveData(AuRequest request, String key){
|
||||
Object value = request.getData().get(key);
|
||||
if ( value == null)
|
||||
throw new UiException(MZk.ILLEGAL_REQUEST_WRONG_DATA,
|
||||
new Object[] { key, this });
|
||||
if ( value == null )
|
||||
throw new UiException(MZk.ILLEGAL_REQUEST_WRONG_DATA, new Object[] { key, this });
|
||||
|
||||
return value;
|
||||
}
|
||||
|
|
@ -209,27 +211,29 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
|
||||
/* Generate CSS class attribute depending on task properties */
|
||||
protected String calculateCSSClass() {
|
||||
String cssClass = isSubcontracted() ? "box subcontracted-task"
|
||||
: "box standard-task";
|
||||
String cssClass = isSubcontracted() ? "box subcontracted-task" : "box standard-task";
|
||||
cssClass += isResizingTasksEnabled() ? " yui-resize" : "";
|
||||
if (isContainer()) {
|
||||
|
||||
if ( isContainer() ) {
|
||||
cssClass += task.isExpanded() ? " expanded" : " closed ";
|
||||
cssClass += task.isInCriticalPath() && !task.isExpanded() ? " critical"
|
||||
: "";
|
||||
cssClass += task.isInCriticalPath() && !task.isExpanded() ? " critical" : "";
|
||||
|
||||
} else {
|
||||
cssClass += task.isInCriticalPath() ? " critical" : "";
|
||||
if (!task.canBeExplicitlyMoved()) {
|
||||
if ( !task.canBeExplicitlyMoved() ) {
|
||||
cssClass += " fixed";
|
||||
}
|
||||
}
|
||||
|
||||
cssClass += " " + task.getAssignedStatus();
|
||||
if (task.isLimiting()) {
|
||||
cssClass += task.isLimitingAndHasDayAssignments() ? " limiting-assigned "
|
||||
: " limiting-unassigned ";
|
||||
if ( task.isLimiting() ) {
|
||||
cssClass += task.isLimitingAndHasDayAssignments() ? " limiting-assigned " : " limiting-unassigned ";
|
||||
}
|
||||
if (task.isRoot() && task.belongsClosedProject()) {
|
||||
|
||||
if ( task.isRoot() && task.belongsClosedProject() ) {
|
||||
cssClass += " project-closed ";
|
||||
}
|
||||
|
||||
return cssClass;
|
||||
}
|
||||
|
||||
|
|
@ -243,7 +247,7 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
|
||||
public final void afterCompose() {
|
||||
updateProperties();
|
||||
if (propertiesListener == null) {
|
||||
if ( propertiesListener == null ) {
|
||||
propertiesListener = new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
|
|
@ -252,52 +256,52 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
}
|
||||
};
|
||||
}
|
||||
this.task
|
||||
.addFundamentalPropertiesChangeListener(propertiesListener);
|
||||
|
||||
if (showingAdvancePropertyListener == null) {
|
||||
this.task.addFundamentalPropertiesChangeListener(propertiesListener);
|
||||
|
||||
if ( showingAdvancePropertyListener == null ) {
|
||||
showingAdvancePropertyListener = new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (isInPage() && !(task instanceof Milestone)) {
|
||||
if ( isInPage() && !(task instanceof Milestone) ) {
|
||||
updateCompletionAdvance();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
this.task
|
||||
.addAdvancesPropertyChangeListener(showingAdvancePropertyListener);
|
||||
|
||||
if (showingReportedHoursPropertyListener == null) {
|
||||
this.task.addAdvancesPropertyChangeListener(showingAdvancePropertyListener);
|
||||
|
||||
if ( showingReportedHoursPropertyListener == null ) {
|
||||
showingReportedHoursPropertyListener = new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (isInPage() && !(task instanceof Milestone)) {
|
||||
if ( isInPage() && !(task instanceof Milestone) ) {
|
||||
updateCompletionReportedHours();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
this.task
|
||||
.addReportedHoursPropertyChangeListener(showingReportedHoursPropertyListener);
|
||||
|
||||
if (showingMoneyCostBarPropertyListener == null) {
|
||||
this.task.addReportedHoursPropertyChangeListener(showingReportedHoursPropertyListener);
|
||||
|
||||
if ( showingMoneyCostBarPropertyListener == null ) {
|
||||
showingMoneyCostBarPropertyListener = new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (isInPage() && !(task instanceof Milestone)) {
|
||||
if ( isInPage() && !(task instanceof Milestone) ) {
|
||||
updateCompletionMoneyCostBar();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
this.task
|
||||
.addMoneyCostBarPropertyChangeListener(showingMoneyCostBarPropertyListener);
|
||||
|
||||
if (criticalPathPropertyListener == null) {
|
||||
this.task.addMoneyCostBarPropertyChangeListener(showingMoneyCostBarPropertyListener);
|
||||
|
||||
if ( criticalPathPropertyListener == null ) {
|
||||
criticalPathPropertyListener = new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
|
|
@ -307,8 +311,8 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
|
||||
};
|
||||
}
|
||||
this.task
|
||||
.addCriticalPathPropertyChangeListener(criticalPathPropertyListener);
|
||||
|
||||
this.task.addCriticalPathPropertyChangeListener(criticalPathPropertyListener);
|
||||
|
||||
updateClass();
|
||||
}
|
||||
|
|
@ -328,15 +332,14 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
private transient PropertyChangeListener propertiesListener;
|
||||
private IConstraintViolationListener<GanttDate> taskViolationListener;
|
||||
|
||||
// FIXME Bug #1270
|
||||
private String progressType;
|
||||
|
||||
public TaskRow getRow() {
|
||||
if (getParent() == null) {
|
||||
if ( getParent() == null ) {
|
||||
throw new IllegalStateException(
|
||||
"the TaskComponent should have been wraped by a "
|
||||
+ TaskRow.class.getName());
|
||||
"the TaskComponent should have been wraped by a " + TaskRow.class.getName());
|
||||
}
|
||||
|
||||
return (TaskRow) getParent();
|
||||
}
|
||||
|
||||
|
|
@ -353,19 +356,19 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
}
|
||||
|
||||
public boolean isResizingTasksEnabled() {
|
||||
return (disabilityConfiguration != null)
|
||||
&& disabilityConfiguration.isResizingTasksEnabled()
|
||||
&& !task.isSubcontracted() && task.canBeExplicitlyResized();
|
||||
return (disabilityConfiguration != null) &&
|
||||
disabilityConfiguration.isResizingTasksEnabled() &&
|
||||
!task.isSubcontracted() && task.canBeExplicitlyResized();
|
||||
}
|
||||
|
||||
public boolean isMovingTasksEnabled() {
|
||||
return (disabilityConfiguration != null)
|
||||
&& disabilityConfiguration.isMovingTasksEnabled()
|
||||
&& task.canBeExplicitlyMoved();
|
||||
return (disabilityConfiguration != null) &&
|
||||
disabilityConfiguration.isMovingTasksEnabled() &&
|
||||
task.canBeExplicitlyMoved();
|
||||
}
|
||||
|
||||
|
||||
void doUpdatePosition(int leftX, int topY) {
|
||||
void doUpdatePosition(int leftX) {
|
||||
GanttDate startBeforeMoving = this.task.getBeginDate();
|
||||
final LocalDate newPosition = getMapper().toDate(leftX);
|
||||
this.task.doPositionModifications(new IModifications() {
|
||||
|
|
@ -375,24 +378,23 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
position.moveTo(GanttDate.createFrom(newPosition));
|
||||
}
|
||||
});
|
||||
boolean remainsInOriginalPosition = this.task.getBeginDate().equals(
|
||||
startBeforeMoving);
|
||||
if (remainsInOriginalPosition) {
|
||||
|
||||
boolean remainsInOriginalPosition = this.task.getBeginDate().equals(startBeforeMoving);
|
||||
if ( remainsInOriginalPosition ) {
|
||||
updateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
void doUpdateSize(int size) {
|
||||
DateTime end = new DateTime(this.task.getBeginDate()
|
||||
.toDayRoundedDate().getTime()).plus(getMapper().toDuration(
|
||||
size));
|
||||
DateTime end =
|
||||
new DateTime(this.task.getBeginDate().toDayRoundedDate().getTime()).plus(getMapper().toDuration(size));
|
||||
|
||||
this.task.resizeTo(end.toLocalDate());
|
||||
updateProperties();
|
||||
}
|
||||
|
||||
void doAddDependency(String destinyTaskId) {
|
||||
getTaskList().addDependency(this,
|
||||
((TaskComponent) getFellow(destinyTaskId)));
|
||||
getTaskList().addDependency(this, ((TaskComponent) getFellow(destinyTaskId)));
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
|
|
@ -401,11 +403,11 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
|
||||
public void setColor(String color) {
|
||||
|
||||
if ((color != null) && (color.length() == 0)) {
|
||||
if ( (color != null) && (color.length() == 0) ) {
|
||||
color = null;
|
||||
}
|
||||
|
||||
if (!Objects.equals(_color, color)) {
|
||||
if ( !Objects.equals(_color, color) ) {
|
||||
_color = color;
|
||||
}
|
||||
}
|
||||
|
|
@ -415,13 +417,12 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
* of the style
|
||||
*/
|
||||
protected void renderProperties(ContentRenderer renderer) throws IOException{
|
||||
if(getColor() != null)
|
||||
setStyle("background-color : " + getColor());
|
||||
if( getColor() != null ) setStyle("background-color : " + getColor());
|
||||
|
||||
setWidgetAttribute("movingTasksEnabled",((Boolean)isMovingTasksEnabled()).toString());
|
||||
setWidgetAttribute("movingTasksEnabled", ((Boolean)isMovingTasksEnabled()).toString());
|
||||
setWidgetAttribute("resizingTasksEnabled", ((Boolean)isResizingTasksEnabled()).toString());
|
||||
|
||||
/*We can't use setStyle because of restrictions
|
||||
/* We can't use setStyle because of restrictions
|
||||
* involved with UiVisualizer#getResponses and the
|
||||
* smartUpdate method (when the request is asynchronous) */
|
||||
render(renderer, "style", "position : absolute");
|
||||
|
|
@ -461,9 +462,10 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
}
|
||||
|
||||
public void updateProperties() {
|
||||
if (!isInPage()) {
|
||||
if ( !isInPage() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
setLeft("0");
|
||||
setLeft(this.task.getBeginDate().toPixels(getMapper()) + "px");
|
||||
updateWidth();
|
||||
|
|
@ -483,23 +485,27 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
|
||||
private void updateDeadline() {
|
||||
// Task mark is placed after midnight date of the deadline day
|
||||
if (task.getDeadline() != null) {
|
||||
if ( task.getDeadline() != null ) {
|
||||
|
||||
String position = (getMapper().toPixels(
|
||||
LocalDate.fromDateFields(task.getDeadline()).plusDays(1)) - HALF_DEADLINE_MARK)
|
||||
+ "px";
|
||||
LocalDate.fromDateFields(task.getDeadline()).plusDays(1)) - HALF_DEADLINE_MARK) + "px";
|
||||
|
||||
response(null, new AuInvoke(this, "moveDeadline", position));
|
||||
|
||||
} else {
|
||||
// Move deadline out of visible area
|
||||
response(null, new AuInvoke(this, "moveDeadline","-100px"));
|
||||
}
|
||||
|
||||
if (task.getConsolidatedline() != null) {
|
||||
int pixels = getMapper().toPixels(
|
||||
LocalDate.fromDateFields(task.getConsolidatedline()
|
||||
.toDayRoundedDate()))
|
||||
if ( task.getConsolidatedline() != null ) {
|
||||
|
||||
int pixels = getMapper()
|
||||
.toPixels(LocalDate.fromDateFields(task.getConsolidatedline().toDayRoundedDate()))
|
||||
- CONSOLIDATED_MARK_HALF_WIDTH;
|
||||
|
||||
String position = pixels + "px";
|
||||
response(null, new AuInvoke(this, "moveConsolidatedline", position));
|
||||
|
||||
} else {
|
||||
// Move consolidated line out of visible area
|
||||
response(null, new AuInvoke(this, "moveConsolidatedline", "-100px"));
|
||||
|
|
@ -507,43 +513,45 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
}
|
||||
|
||||
public void updateCompletionIfPossible() {
|
||||
if (task instanceof Milestone) {
|
||||
if ( task instanceof Milestone ) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateCompletionReportedHours();
|
||||
updateCompletionMoneyCostBar();
|
||||
updateCompletionAdvance();
|
||||
}
|
||||
|
||||
public void updateCompletionReportedHours() {
|
||||
if (task.isShowingReportedHours()) {
|
||||
if ( task.isShowingReportedHours() ) {
|
||||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||
String widthHoursAdvancePercentage = pixelsFromStartUntil(
|
||||
startPixels,
|
||||
this.task.getHoursAdvanceBarEndDate()) + "px";
|
||||
response(null, new AuInvoke(this, "resizeCompletionAdvance",
|
||||
widthHoursAdvancePercentage));
|
||||
|
||||
String widthHoursAdvancePercentage =
|
||||
pixelsFromStartUntil(startPixels, this.task.getHoursAdvanceBarEndDate()) + "px";
|
||||
|
||||
response(null, new AuInvoke(this, "resizeCompletionAdvance", widthHoursAdvancePercentage));
|
||||
|
||||
Date firstTimesheetDate = task.getFirstTimesheetDate();
|
||||
Date lastTimesheetDate = task.getLastTimesheetDate();
|
||||
if (firstTimesheetDate != null && lastTimesheetDate != null) {
|
||||
|
||||
if ( firstTimesheetDate != null && lastTimesheetDate != null ) {
|
||||
|
||||
Duration firstDuration = Days.daysBetween(
|
||||
task.getBeginDateAsLocalDate(),
|
||||
LocalDate.fromDateFields(firstTimesheetDate))
|
||||
.toStandardDuration();
|
||||
LocalDate.fromDateFields(firstTimesheetDate)).toStandardDuration();
|
||||
|
||||
int pixelsFirst = getMapper().toPixels(firstDuration);
|
||||
String positionFirst = pixelsFirst + "px";
|
||||
|
||||
Duration lastDuration = Days
|
||||
.daysBetween(
|
||||
task.getBeginDateAsLocalDate(),
|
||||
LocalDate.fromDateFields(lastTimesheetDate)
|
||||
.plusDays(1)).toStandardDuration();
|
||||
Duration lastDuration = Days.daysBetween(
|
||||
task.getBeginDateAsLocalDate(),
|
||||
LocalDate.fromDateFields(lastTimesheetDate).plusDays(1)).toStandardDuration();
|
||||
|
||||
int pixelsLast = getMapper().toPixels(lastDuration);
|
||||
String positionLast = pixelsLast + "px";
|
||||
|
||||
response(null, new AuInvoke(this, "showTimsheetDateMarks",
|
||||
positionFirst, positionLast));
|
||||
response(null, new AuInvoke(this, "showTimsheetDateMarks", positionFirst, positionLast));
|
||||
|
||||
} else {
|
||||
response(null, new AuInvoke(this, "hideTimsheetDateMarks"));
|
||||
}
|
||||
|
|
@ -555,44 +563,38 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
}
|
||||
|
||||
public void updateCompletionMoneyCostBar() {
|
||||
if (task.isShowingMoneyCostBar()) {
|
||||
if ( task.isShowingMoneyCostBar() ) {
|
||||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||
int endPixels = this.task.getEndDate().toPixels(getMapper());
|
||||
int widthPixels = (int) ((endPixels - startPixels) * this.task
|
||||
.getMoneyCostBarPercentage().doubleValue());
|
||||
int widthPixels = (int) ((endPixels - startPixels) * this.task.getMoneyCostBarPercentage().doubleValue());
|
||||
String widthMoneyCostBar = widthPixels + "px";
|
||||
response(null, new AuInvoke(this, "resizeCompletionMoneyCostBar",
|
||||
widthMoneyCostBar));
|
||||
response(null, new AuInvoke(this, "resizeCompletionMoneyCostBar", widthMoneyCostBar));
|
||||
|
||||
} else {
|
||||
response(null, new AuInvoke(this, "resizeCompletionMoneyCostBar",
|
||||
"0px"));
|
||||
response(null, new AuInvoke(this, "resizeCompletionMoneyCostBar", "0px"));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCompletionAdvance() {
|
||||
if (task.isShowingAdvances()) {
|
||||
if ( task.isShowingAdvances() ) {
|
||||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||
String widthAdvancePercentage = pixelsFromStartUntil(startPixels,
|
||||
this.task.getAdvanceBarEndDate()) + "px";
|
||||
response(null, new AuInvoke(this, "resizeCompletion2Advance",
|
||||
widthAdvancePercentage));
|
||||
String widthAdvancePercentage = pixelsFromStartUntil(startPixels, this.task.getAdvanceBarEndDate()) + "px";
|
||||
response(null, new AuInvoke(this, "resizeCompletion2Advance", widthAdvancePercentage));
|
||||
} else {
|
||||
response(null,
|
||||
new AuInvoke(this, "resizeCompletion2Advance", "0px"));
|
||||
response(null, new AuInvoke(this, "resizeCompletion2Advance", "0px"));
|
||||
}
|
||||
}
|
||||
|
||||
public void updateCompletion(String progressType) {
|
||||
if (task.isShowingAdvances()) {
|
||||
if ( task.isShowingAdvances() ) {
|
||||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||
|
||||
String widthAdvancePercentage = pixelsFromStartUntil(startPixels,
|
||||
this.task.getAdvanceBarEndDate(progressType)) + "px";
|
||||
response(null, new AuInvoke(this, "resizeCompletion2Advance",
|
||||
widthAdvancePercentage));
|
||||
String widthAdvancePercentage =
|
||||
pixelsFromStartUntil(startPixels, this.task.getAdvanceBarEndDate(progressType)) + "px";
|
||||
|
||||
response(null, new AuInvoke(this, "resizeCompletion2Advance", widthAdvancePercentage));
|
||||
} else {
|
||||
response(null,
|
||||
new AuInvoke(this, "resizeCompletion2Advance", "0px"));
|
||||
response(null, new AuInvoke(this, "resizeCompletion2Advance", "0px"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -603,12 +605,10 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
}
|
||||
|
||||
public void updateTooltipText() {
|
||||
// FIXME Bug #1270
|
||||
this.progressType = null;
|
||||
}
|
||||
|
||||
public void updateTooltipText(String progressType) {
|
||||
// FIXME Bug #1270
|
||||
this.progressType = progressType;
|
||||
}
|
||||
|
||||
|
|
@ -635,8 +635,7 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
}
|
||||
|
||||
public String getTooltipText() {
|
||||
// FIXME Bug #1270
|
||||
if (progressType == null) {
|
||||
if ( progressType == null ) {
|
||||
return task.getTooltipText();
|
||||
} else {
|
||||
return task.updateTooltipText(progressType);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.apache.commons.lang.math.Fraction;
|
||||
import org.apache.commons.lang3.math.Fraction;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.zkoss.ganttz.adapters.IDisabilityConfiguration;
|
||||
import org.zkoss.ganttz.data.Dependency;
|
||||
|
|
@ -75,7 +75,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
|
||||
private FilterAndParentExpandedPredicates predicate;
|
||||
|
||||
private Set<Task> visibleTasks = new HashSet<Task>();
|
||||
private Set<Task> visibleTasks = new HashSet<>();
|
||||
|
||||
private Map<Task, TaskComponent> taskComponentByTask;
|
||||
|
||||
|
|
@ -86,9 +86,10 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
List<? extends CommandOnTaskContextualized<?>> commandsOnTasksContextualized,
|
||||
IDisabilityConfiguration disabilityConfiguration,
|
||||
FilterAndParentExpandedPredicates predicate) {
|
||||
|
||||
this.context = context;
|
||||
this.doubleClickCommand = doubleClickCommand;
|
||||
this.currentTotalTasks = new ArrayList<Task>(tasks);
|
||||
this.currentTotalTasks = new ArrayList<>(tasks);
|
||||
this.commandsOnTasksContextualized = commandsOnTasksContextualized;
|
||||
this.disabilityConfiguration = disabilityConfiguration;
|
||||
this.predicate = predicate;
|
||||
|
|
@ -103,7 +104,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
}
|
||||
|
||||
public List<Task> getAllTasks() {
|
||||
return new ArrayList<Task>(currentTotalTasks);
|
||||
return new ArrayList<>(currentTotalTasks);
|
||||
}
|
||||
|
||||
public static TaskList createFor(
|
||||
|
|
@ -112,20 +113,26 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
List<? extends CommandOnTaskContextualized<?>> commandsOnTasksContextualized,
|
||||
IDisabilityConfiguration disabilityConfiguration,
|
||||
FilterAndParentExpandedPredicates predicate) {
|
||||
TaskList result = new TaskList(context, doubleClickCommand, context
|
||||
.getDiagramGraph().getTopLevelTasks(),
|
||||
commandsOnTasksContextualized, disabilityConfiguration,
|
||||
|
||||
TaskList result = new TaskList(
|
||||
context,
|
||||
doubleClickCommand,
|
||||
context.getDiagramGraph().getTopLevelTasks(),
|
||||
commandsOnTasksContextualized,
|
||||
disabilityConfiguration,
|
||||
predicate);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<DependencyComponent> asDependencyComponents(Collection<? extends Dependency> dependencies) {
|
||||
List<DependencyComponent> result = new ArrayList<DependencyComponent>();
|
||||
List<DependencyComponent> result = new ArrayList<>();
|
||||
for (Dependency dependency : dependencies) {
|
||||
result.add(new DependencyComponent(taskComponentByTask
|
||||
.get(dependency.getSource()), taskComponentByTask
|
||||
.get(dependency.getDestination()), dependency));
|
||||
result.add(new DependencyComponent(
|
||||
taskComponentByTask.get(dependency.getSource()),
|
||||
taskComponentByTask.get(dependency.getDestination()), dependency));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -133,11 +140,14 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
return asDependencyComponents(Arrays.asList(dependency)).get(0);
|
||||
}
|
||||
|
||||
private synchronized void addTaskComponent(TaskRow beforeThis, final TaskComponent taskComponent, boolean relocate) {
|
||||
private synchronized void addTaskComponent(TaskRow beforeThis, final TaskComponent taskComponent,
|
||||
boolean relocate) {
|
||||
|
||||
insertBefore(taskComponent.getRow(), beforeThis);
|
||||
addContextMenu(taskComponent);
|
||||
addListenerForTaskComponentEditForm(taskComponent);
|
||||
taskComponent.afterCompose();
|
||||
|
||||
if ( relocate ) {
|
||||
getGanttPanel().adjustZoomColumnsHeight();
|
||||
}
|
||||
|
|
@ -145,12 +155,14 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
|
||||
public void addTasks(Position position, Collection<? extends Task> newTasks) {
|
||||
createAndPublishComponentsIfNeeded(newTasks);
|
||||
if (position.isAppendToTop()) {
|
||||
|
||||
if ( position.isAppendToTop() ) {
|
||||
currentTotalTasks.addAll(newTasks);
|
||||
} else if (position.isAtTop()) {
|
||||
} else if ( position.isAtTop() ) {
|
||||
final int insertionPosition = position.getInsertionPosition();
|
||||
currentTotalTasks.addAll(insertionPosition, newTasks);
|
||||
}
|
||||
|
||||
// if the position is children of some already existent task when
|
||||
// reloading it will be added if the predicate tells so
|
||||
reload(true);
|
||||
|
|
@ -159,7 +171,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
public TaskComponent find(Task task) {
|
||||
List<TaskComponent> taskComponents = getTaskComponents();
|
||||
for (TaskComponent taskComponent : taskComponents) {
|
||||
if (taskComponent.getTask().equals(task)) {
|
||||
if ( taskComponent.getTask().equals(task) ) {
|
||||
return taskComponent;
|
||||
}
|
||||
}
|
||||
|
|
@ -196,13 +208,14 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
}
|
||||
|
||||
protected List<TaskComponent> getTaskComponents() {
|
||||
ArrayList<TaskComponent> result = new ArrayList<TaskComponent>();
|
||||
ArrayList<TaskComponent> result = new ArrayList<>();
|
||||
for (Object child : getChildren()) {
|
||||
if (child instanceof TaskRow) {
|
||||
if ( child instanceof TaskRow ) {
|
||||
TaskRow row = (TaskRow) child;
|
||||
result.add(row.getChild());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -218,42 +231,44 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
}
|
||||
|
||||
private void publishOriginalTasksAsComponents() {
|
||||
taskComponentByTask = new HashMap<Task, TaskComponent>();
|
||||
taskComponentByTask = new HashMap<>();
|
||||
createAndPublishComponentsIfNeeded(currentTotalTasks);
|
||||
}
|
||||
|
||||
private List<TaskComponent> createAndPublishComponentsIfNeeded(
|
||||
Collection<? extends Task> newTasks) {
|
||||
if (predicate.isFilterContainers()) {
|
||||
List<Task> taskLeafs = new ArrayList<Task>();
|
||||
private List<TaskComponent> createAndPublishComponentsIfNeeded(Collection<? extends Task> newTasks) {
|
||||
if ( predicate.isFilterContainers() ) {
|
||||
List<Task> taskLeafs = new ArrayList<>();
|
||||
for (Task task : newTasks) {
|
||||
taskLeafs.addAll(task.getAllTaskLeafs());
|
||||
}
|
||||
newTasks = taskLeafs;
|
||||
}
|
||||
|
||||
List<TaskComponent> result = new ArrayList<TaskComponent>();
|
||||
List<TaskComponent> result = new ArrayList<>();
|
||||
for (Task task : newTasks) {
|
||||
TaskComponent taskComponent = taskComponentByTask.get(task);
|
||||
if (taskComponent == null) {
|
||||
taskComponent = TaskComponent.asTaskComponent(task,
|
||||
disabilityConfiguration);
|
||||
|
||||
if ( taskComponent == null ) {
|
||||
taskComponent = TaskComponent.asTaskComponent(task, disabilityConfiguration);
|
||||
taskComponent.publishTaskComponents(taskComponentByTask);
|
||||
}
|
||||
if (task.isContainer()) {
|
||||
|
||||
if ( task.isContainer() ) {
|
||||
addExpandListenerTo((TaskContainer) task);
|
||||
}
|
||||
result.add(taskComponent);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<TaskContainer, IExpandListener> autoRemovedListers = new WeakHashMap<TaskContainer, IExpandListener>();
|
||||
private Map<TaskContainer, IExpandListener> autoRemovedListers = new WeakHashMap<>();
|
||||
|
||||
private void addExpandListenerTo(TaskContainer container) {
|
||||
if (autoRemovedListers.containsKey(container)) {
|
||||
if ( autoRemovedListers.containsKey(container) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
IExpandListener expandListener = new IExpandListener() {
|
||||
|
||||
@Override
|
||||
|
|
@ -261,12 +276,13 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
reload(true);
|
||||
}
|
||||
};
|
||||
|
||||
container.addExpandListener(expandListener);
|
||||
autoRemovedListers.put(container, expandListener);
|
||||
}
|
||||
|
||||
private void registerZoomLevelChangedListener() {
|
||||
if (zoomLevelChangedListener == null) {
|
||||
if ( zoomLevelChangedListener == null ) {
|
||||
zoomLevelChangedListener = new IZoomLevelChangedListener() {
|
||||
@Override
|
||||
public void zoomLevelChanged(ZoomLevel detailLevel) {
|
||||
|
|
@ -281,12 +297,11 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
}
|
||||
|
||||
public LocalDate toDate(int pixels, Fraction pixelsPerDay, Interval interval) {
|
||||
int daysInto = Fraction.getFraction(pixels, 1).divideBy(pixelsPerDay)
|
||||
.intValue();
|
||||
int daysInto = Fraction.getFraction(pixels, 1).divideBy(pixelsPerDay).intValue();
|
||||
return interval.getStart().plusDays(daysInto);
|
||||
}
|
||||
|
||||
private Map<TaskComponent, Menupopup> contextMenus = new HashMap<TaskComponent, Menupopup>();
|
||||
private Map<TaskComponent, Menupopup> contextMenus = new HashMap<>();
|
||||
|
||||
private Menupopup getContextMenuFor(TaskComponent taskComponent) {
|
||||
if ( contextMenus.get(taskComponent) == null ) {
|
||||
|
|
@ -295,7 +310,6 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
if ( disabilityConfiguration.isAddingDependenciesEnabled() ) {
|
||||
menuBuilder.item(_("Add Dependency"), "/common/img/ico_dependency.png",
|
||||
new ItemAction<TaskComponent>() {
|
||||
|
||||
@Override
|
||||
public void onEvent(TaskComponent choosen, Event event) {
|
||||
choosen.addDependency();
|
||||
|
|
@ -308,10 +322,13 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
menuBuilder.item(command.getName(), command.getIcon(), command.toItemAction());
|
||||
}
|
||||
}
|
||||
|
||||
Menupopup result = menuBuilder.createWithoutSettingContext();
|
||||
contextMenus.put(taskComponent, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return contextMenus.get(taskComponent);
|
||||
}
|
||||
|
||||
|
|
@ -330,16 +347,16 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
public void remove(Task task) {
|
||||
currentTotalTasks.remove(task);
|
||||
for (TaskComponent taskComponent : getTaskComponents()) {
|
||||
if (taskComponent.getTask().equals(task)) {
|
||||
if ( taskComponent.getTask().equals(task) ) {
|
||||
taskComponent.remove();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addDependency(TaskComponent source, TaskComponent destination) {
|
||||
context.addDependency(new Dependency(source.getTask(), destination
|
||||
.getTask(), DependencyType.END_START));
|
||||
context.addDependency(new Dependency(source.getTask(), destination.getTask(), DependencyType.END_START));
|
||||
}
|
||||
|
||||
public IDisabilityConfiguration getDisabilityConfiguration() {
|
||||
|
|
@ -347,7 +364,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
}
|
||||
|
||||
private void reload(boolean relocate) {
|
||||
ArrayList<Task> tasksPendingToAdd = new ArrayList<Task>();
|
||||
ArrayList<Task> tasksPendingToAdd = new ArrayList<>();
|
||||
reload(currentTotalTasks, tasksPendingToAdd, relocate);
|
||||
addPendingTasks(tasksPendingToAdd, null, relocate);
|
||||
getGanttPanel().getDependencyList().redrawDependencies();
|
||||
|
|
@ -358,6 +375,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
if ( visibleTasks.contains(task) ) {
|
||||
addPendingTasks(tasksPendingToAdd, rowFor(task), relocate);
|
||||
}
|
||||
|
||||
final boolean isShown = visibleTasks.contains(task);
|
||||
|
||||
if ( predicate.accepts(task) != isShown ) {
|
||||
|
|
@ -367,6 +385,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
tasksPendingToAdd.add(task);
|
||||
}
|
||||
}
|
||||
|
||||
if ( task instanceof TaskContainer ) {
|
||||
reload(task.getTasks(), tasksPendingToAdd, relocate);
|
||||
}
|
||||
|
|
@ -389,6 +408,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
|||
if ( tasksPendingToAdd.isEmpty() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (TaskComponent each : createAndPublishComponentsIfNeeded(tasksPendingToAdd)) {
|
||||
addTaskComponent(insertBefore, each, relocate);
|
||||
visibleTasks.add(each.getTask());
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.zkoss.ganttz.Planner;
|
||||
import org.zkoss.ganttz.data.GanttDate;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph.IGraphChangeListener;
|
||||
|
|
@ -53,15 +53,15 @@ import org.zkoss.zk.ui.Component;
|
|||
public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
||||
|
||||
public interface IPrintAction {
|
||||
public void doPrint();
|
||||
void doPrint();
|
||||
|
||||
public void doPrint(Map<String, String> parameters);
|
||||
void doPrint(Map<String, String> parameters);
|
||||
|
||||
public void doPrint(HashMap<String, String> parameters, Planner planner);
|
||||
void doPrint(HashMap<String, String> parameters, Planner planner);
|
||||
}
|
||||
|
||||
public interface IReloadChartListener {
|
||||
public void reloadChart();
|
||||
void reloadChart();
|
||||
}
|
||||
|
||||
private static class NullCommand<T> implements ICommand<T> {
|
||||
|
|
@ -123,13 +123,13 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
|||
|
||||
private List<? extends T> data;
|
||||
|
||||
private List<ICommand<T>> globalCommands = new ArrayList<ICommand<T>>();
|
||||
private List<ICommand<T>> globalCommands = new ArrayList<>();
|
||||
|
||||
private List<ICommandOnTask<T>> commandsOnTasks = new ArrayList<ICommandOnTask<T>>();
|
||||
private List<ICommandOnTask<T>> commandsOnTasks = new ArrayList<>();
|
||||
|
||||
private ICommand<T> goingDownInLastArrowCommand = new NullCommand<T>();
|
||||
private ICommand<T> goingDownInLastArrowCommand = new NullCommand<>();
|
||||
|
||||
private ICommandOnTask<T> doubleClickCommand = new NullCommandOnTask<T>();
|
||||
private ICommandOnTask<T> doubleClickCommand = new NullCommandOnTask<>();
|
||||
|
||||
private Component chartComponent;
|
||||
|
||||
|
|
@ -167,26 +167,25 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
|||
|
||||
// private String identifier = null;
|
||||
|
||||
private IDetailItemModificator firstLevelModificators = SeveralModificators
|
||||
.empty();
|
||||
private IDetailItemModificator firstLevelModificators = SeveralModificators.empty();
|
||||
|
||||
private IDetailItemModificator secondLevelModificators = SeveralModificators
|
||||
.empty();
|
||||
private IDetailItemModificator secondLevelModificators = SeveralModificators.empty();
|
||||
|
||||
private List<IReloadChartListener> reloadChartListeners = new ArrayList<IReloadChartListener>();
|
||||
private List<IReloadChartListener> reloadChartListeners = new ArrayList<>();
|
||||
|
||||
private IPrintAction printAction;
|
||||
|
||||
private boolean expandPlanningViewCharts;
|
||||
|
||||
private final List<IGraphChangeListener> preGraphChangeListeners = new ArrayList<IGraphChangeListener>();
|
||||
private final List<IGraphChangeListener> preGraphChangeListeners = new ArrayList<>();
|
||||
|
||||
private final List<IGraphChangeListener> postGraphChangeListeners = new ArrayList<IGraphChangeListener>();
|
||||
private final List<IGraphChangeListener> postGraphChangeListeners = new ArrayList<>();
|
||||
|
||||
private boolean scheduleBackwards = false;
|
||||
|
||||
public PlannerConfiguration(IAdapterToTaskFundamentalProperties<T> adapter,
|
||||
IStructureNavigator<T> navigator, List<? extends T> data) {
|
||||
IStructureNavigator<T> navigator,
|
||||
List<? extends T> data) {
|
||||
this.adapter = adapter;
|
||||
this.navigator = navigator;
|
||||
this.data = data;
|
||||
|
|
@ -234,8 +233,7 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
|||
this.notAfterThan = GanttDate.createFrom(notAfterThan);
|
||||
}
|
||||
|
||||
public void setGoingDownInLastArrowCommand(
|
||||
ICommand<T> goingDownInLastArrowCommand) {
|
||||
public void setGoingDownInLastArrowCommand(ICommand<T> goingDownInLastArrowCommand) {
|
||||
Validate.notNull(goingDownInLastArrowCommand);
|
||||
this.goingDownInLastArrowCommand = goingDownInLastArrowCommand;
|
||||
}
|
||||
|
|
@ -293,11 +291,11 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
|||
this.editingDatesEnabled = editingDatesEnabled;
|
||||
}
|
||||
|
||||
public static List<Constraint<GanttDate>> getStartConstraintsGiven(
|
||||
GanttDate notBeforeThan) {
|
||||
if (notBeforeThan != null) {
|
||||
public static List<Constraint<GanttDate>> getStartConstraintsGiven(GanttDate notBeforeThan) {
|
||||
if ( notBeforeThan != null ) {
|
||||
return Collections.singletonList(biggerOrEqualThan(notBeforeThan));
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
|
@ -305,11 +303,11 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
|||
return getStartConstraintsGiven(notBeforeThan);
|
||||
}
|
||||
|
||||
public static List<Constraint<GanttDate>> getEndConstraintsGiven(
|
||||
GanttDate notAfterThan) {
|
||||
if (notAfterThan != null) {
|
||||
public static List<Constraint<GanttDate>> getEndConstraintsGiven(GanttDate notAfterThan) {
|
||||
if ( notAfterThan != null ) {
|
||||
return Collections.singletonList(lessOrEqualThan(notAfterThan));
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
|
@ -401,20 +399,16 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
|||
return secondLevelModificators;
|
||||
}
|
||||
|
||||
public void setSecondLevelModificators(
|
||||
IDetailItemModificator... secondLevelModificators) {
|
||||
this.secondLevelModificators = SeveralModificators
|
||||
.create(secondLevelModificators);
|
||||
public void setSecondLevelModificators(IDetailItemModificator... secondLevelModificators) {
|
||||
this.secondLevelModificators = SeveralModificators.create(secondLevelModificators);
|
||||
}
|
||||
|
||||
public IDetailItemModificator getFirstLevelModificators() {
|
||||
return firstLevelModificators;
|
||||
}
|
||||
|
||||
public void setFirstLevelModificators(
|
||||
IDetailItemModificator... firstLevelModificators) {
|
||||
this.firstLevelModificators = SeveralModificators
|
||||
.create(firstLevelModificators);
|
||||
public void setFirstLevelModificators(IDetailItemModificator... firstLevelModificators) {
|
||||
this.firstLevelModificators = SeveralModificators.create(firstLevelModificators);
|
||||
}
|
||||
|
||||
public void addReloadChartListener(IReloadChartListener reloadChartListener) {
|
||||
|
|
@ -437,21 +431,21 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
|||
}
|
||||
|
||||
public void print() {
|
||||
if (!isPrintEnabled()) {
|
||||
if ( !isPrintEnabled() ) {
|
||||
throw new UnsupportedOperationException("print not supported");
|
||||
}
|
||||
printAction.doPrint();
|
||||
}
|
||||
|
||||
public void print(Map<String, String> parameters) {
|
||||
if (!isPrintEnabled()) {
|
||||
if ( !isPrintEnabled() ) {
|
||||
throw new UnsupportedOperationException("print not supported");
|
||||
}
|
||||
printAction.doPrint(parameters);
|
||||
}
|
||||
|
||||
public void print(HashMap<String, String> parameters, Planner planner) {
|
||||
if (!isPrintEnabled()) {
|
||||
if ( !isPrintEnabled() ) {
|
||||
throw new UnsupportedOperationException("print not supported");
|
||||
}
|
||||
printAction.doPrint(parameters, planner);
|
||||
|
|
@ -466,18 +460,16 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
|||
return expandPlanningViewCharts;
|
||||
}
|
||||
|
||||
public void addPreGraphChangeListener(
|
||||
IGraphChangeListener preGraphChangeListener) {
|
||||
public void addPreGraphChangeListener(IGraphChangeListener preGraphChangeListener) {
|
||||
Validate.notNull(preGraphChangeListener);
|
||||
if (!preGraphChangeListeners.contains(preGraphChangeListener)) {
|
||||
if ( !preGraphChangeListeners.contains(preGraphChangeListener) ) {
|
||||
preGraphChangeListeners.add(preGraphChangeListener);
|
||||
}
|
||||
}
|
||||
|
||||
public void addPostGraphChangeListener(
|
||||
IGraphChangeListener postGraphChangeListener) {
|
||||
public void addPostGraphChangeListener(IGraphChangeListener postGraphChangeListener) {
|
||||
Validate.notNull(postGraphChangeListener);
|
||||
if (!postGraphChangeListeners.contains(postGraphChangeListener)) {
|
||||
if ( !postGraphChangeListeners.contains(postGraphChangeListener) ) {
|
||||
postGraphChangeListeners.add(postGraphChangeListener);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.zkoss.ganttz.data.DependencyType.Point;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener;
|
||||
|
|
@ -42,12 +42,14 @@ public class Dependency implements IDependency<Task> {
|
|||
|
||||
public static List<Constraint<GanttDate>> getConstraintsFor(
|
||||
ConstraintCalculator<Task> calculator,
|
||||
Collection<Dependency> dependencies, Point pointBeingModified) {
|
||||
List<Constraint<GanttDate>> result = new ArrayList<Constraint<GanttDate>>();
|
||||
Collection<Dependency> dependencies,
|
||||
Point pointBeingModified) {
|
||||
|
||||
List<Constraint<GanttDate>> result = new ArrayList<>();
|
||||
for (Dependency each : dependencies) {
|
||||
result.addAll(each.withViolationNotification(calculator
|
||||
.getConstraints(each, pointBeingModified)));
|
||||
result.addAll(each.withViolationNotification(calculator.getConstraints(each, pointBeingModified)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -59,60 +61,62 @@ public class Dependency implements IDependency<Task> {
|
|||
|
||||
private final boolean visible;
|
||||
|
||||
private ConstraintViolationNotificator<GanttDate> violationsNotificator = ConstraintViolationNotificator
|
||||
.create();
|
||||
private ConstraintViolationNotificator<GanttDate> violationsNotificator = ConstraintViolationNotificator.create();
|
||||
|
||||
public Dependency(Task source, Task destination,
|
||||
DependencyType type, boolean visible) {
|
||||
if (source == null) {
|
||||
public Dependency(Task source, Task destination, DependencyType type, boolean visible) {
|
||||
if ( source == null ) {
|
||||
throw new IllegalArgumentException("source cannot be null");
|
||||
}
|
||||
if (destination == null) {
|
||||
|
||||
if ( destination == null ) {
|
||||
throw new IllegalArgumentException("destination cannot be null");
|
||||
}
|
||||
if (type == null) {
|
||||
|
||||
if ( type == null ) {
|
||||
throw new IllegalArgumentException("type cannot be null");
|
||||
}
|
||||
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
this.type = type;
|
||||
this.visible = visible;
|
||||
}
|
||||
|
||||
public Dependency(Task source, Task destination,
|
||||
DependencyType type) {
|
||||
public Dependency(Task source, Task destination, DependencyType type) {
|
||||
this(source, destination, type, true);
|
||||
}
|
||||
|
||||
private List<Constraint<GanttDate>> withViolationNotification(
|
||||
List<Constraint<GanttDate>> original) {
|
||||
private List<Constraint<GanttDate>> withViolationNotification(List<Constraint<GanttDate>> original) {
|
||||
return violationsNotificator.withListener(original);
|
||||
}
|
||||
|
||||
public void addConstraintViolationListener(
|
||||
IConstraintViolationListener<GanttDate> listener, Mode mode) {
|
||||
public void addConstraintViolationListener(IConstraintViolationListener<GanttDate> listener, Mode mode) {
|
||||
violationsNotificator.addConstraintViolationListener(listener, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder().append(source).append(destination).append(
|
||||
type).toHashCode();
|
||||
return new HashCodeBuilder().append(source).append(destination).append(type).toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
if ( this == obj ) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
|
||||
if ( obj == null ) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
|
||||
if ( getClass() != obj.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Dependency other = (Dependency) obj;
|
||||
return new EqualsBuilder().append(this.destination, other.destination)
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(this.destination, other.destination)
|
||||
.append(this.source, other.source)
|
||||
.append(this.type, other.type).isEquals();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.zkoss.ganttz.IDatesMapper;
|
||||
|
||||
|
|
@ -60,16 +60,18 @@ import org.zkoss.ganttz.IDatesMapper;
|
|||
public abstract class GanttDate implements Comparable<GanttDate> {
|
||||
|
||||
public static LocalDateBased createFrom(Date date) {
|
||||
if (date == null) {
|
||||
if ( date == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return createFrom(LocalDate.fromDateFields(date));
|
||||
}
|
||||
|
||||
public static LocalDateBased createFrom(LocalDate localDate) {
|
||||
if (localDate == null) {
|
||||
if ( localDate == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new LocalDateBased(localDate);
|
||||
}
|
||||
|
||||
|
|
@ -83,13 +85,15 @@ public abstract class GanttDate implements Comparable<GanttDate> {
|
|||
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
if ( obj == this ) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof GanttDate) {
|
||||
|
||||
if ( obj instanceof GanttDate ) {
|
||||
GanttDate other = (GanttDate) obj;
|
||||
return isEqualsTo(other);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -99,13 +103,12 @@ public abstract class GanttDate implements Comparable<GanttDate> {
|
|||
public abstract int hashCode();
|
||||
|
||||
public interface ICases<R> {
|
||||
public R on(LocalDateBased localDateBased);
|
||||
R on(LocalDateBased localDateBased);
|
||||
|
||||
public R on(CustomDate customType);
|
||||
R on(CustomDate customType);
|
||||
}
|
||||
|
||||
public static abstract class Cases<T extends CustomDate, R> implements
|
||||
ICases<R> {
|
||||
public static abstract class Cases<T extends CustomDate, R> implements ICases<R> {
|
||||
|
||||
private final Class<T> klass;
|
||||
|
||||
|
|
@ -243,6 +246,7 @@ public abstract class GanttDate implements Comparable<GanttDate> {
|
|||
@Override
|
||||
public int compareTo(GanttDate o) {
|
||||
return o.byCases(new ICases<Integer>() {
|
||||
|
||||
@Override
|
||||
public Integer on(LocalDateBased localDateBased) {
|
||||
return compareToLocalDate(localDateBased.localDate);
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ import java.util.Map;
|
|||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jgrapht.DirectedGraph;
|
||||
|
|
@ -197,7 +197,6 @@ public class GanttDiagramGraph<V, D extends IDependency<V>> implements ICritical
|
|||
@Override
|
||||
public void setEndDateFor(Task task, final GanttDate newEnd) {
|
||||
task.doPositionModifications(new IModifications() {
|
||||
|
||||
@Override
|
||||
public void doIt(IUpdatablePosition position) {
|
||||
position.setEndDate(newEnd);
|
||||
|
|
@ -213,7 +212,6 @@ public class GanttDiagramGraph<V, D extends IDependency<V>> implements ICritical
|
|||
@Override
|
||||
public void setStartDateFor(Task task, final GanttDate newStart) {
|
||||
task.doPositionModifications(new IModifications() {
|
||||
|
||||
@Override
|
||||
public void doIt(IUpdatablePosition position) {
|
||||
position.setBeginDate(newStart);
|
||||
|
|
@ -247,8 +245,11 @@ public class GanttDiagramGraph<V, D extends IDependency<V>> implements ICritical
|
|||
|
||||
public static class GanttZKDiagramGraph extends GanttDiagramGraph<Task, Dependency> {
|
||||
|
||||
private GanttZKDiagramGraph(boolean scheduleBackwards, List<Constraint<GanttDate>> globalStartConstraints,
|
||||
List<Constraint<GanttDate>> globalEndConstraints, boolean dependenciesConstraintsHavePriority) {
|
||||
private GanttZKDiagramGraph(
|
||||
boolean scheduleBackwards,
|
||||
List<Constraint<GanttDate>> globalStartConstraints,
|
||||
List<Constraint<GanttDate>> globalEndConstraints,
|
||||
boolean dependenciesConstraintsHavePriority) {
|
||||
|
||||
super(scheduleBackwards, GANTTZK_ADAPTER, globalStartConstraints, globalEndConstraints,
|
||||
dependenciesConstraintsHavePriority);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
/**
|
||||
* Represents a position for a task <br />
|
||||
|
|
@ -40,13 +40,13 @@ public abstract class Position {
|
|||
* @param positionInParent
|
||||
* @return a {@link Position} specified by the params
|
||||
*/
|
||||
public static Position createPosition(
|
||||
List<? extends TaskContainer> parents, int positionInParent) {
|
||||
public static Position createPosition(List<? extends TaskContainer> parents, int positionInParent) {
|
||||
Validate.notEmpty(parents);
|
||||
Validate.noNullElements(parents);
|
||||
Validate.isTrue(positionInParent >= 0);
|
||||
Task firstParent = parents.get(0);
|
||||
Validate.isTrue(positionInParent < firstParent.getTasks().size());
|
||||
|
||||
return new ChildPosition(parents, positionInParent);
|
||||
}
|
||||
|
||||
|
|
@ -115,9 +115,10 @@ public abstract class Position {
|
|||
* @return
|
||||
*/
|
||||
public Position down(TaskContainer current, int positionInParent) {
|
||||
List<TaskContainer> ancestors = new ArrayList<TaskContainer>();
|
||||
List<TaskContainer> ancestors = new ArrayList<>();
|
||||
ancestors.add(current);
|
||||
ancestors.addAll(getAncestors());
|
||||
|
||||
return new ChildPosition(ancestors, positionInParent);
|
||||
}
|
||||
|
||||
|
|
@ -127,11 +128,12 @@ public abstract class Position {
|
|||
private static class ChildPosition extends Position {
|
||||
|
||||
private final List<? extends TaskContainer> parents;
|
||||
|
||||
private TaskContainer parent;
|
||||
|
||||
ChildPosition(List<? extends TaskContainer> parents,
|
||||
int positionInParent) {
|
||||
ChildPosition(List<? extends TaskContainer> parents, int positionInParent) {
|
||||
super(positionInParent);
|
||||
|
||||
this.parents = parents;
|
||||
this.parent = parents.get(0);
|
||||
}
|
||||
|
|
@ -153,8 +155,7 @@ public abstract class Position {
|
|||
|
||||
@Override
|
||||
public Position pop() {
|
||||
return new ChildPosition(parents.subList(0, parents.size() - 1),
|
||||
getInsertionPosition());
|
||||
return new ChildPosition(parents.subList(0, parents.size() - 1), getInsertionPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import java.util.Collections;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.joda.time.Duration;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.ReadableDuration;
|
||||
|
|
@ -56,28 +56,22 @@ import org.zkoss.ganttz.util.WeakReferencedListeners.Mode;
|
|||
public abstract class Task implements ITaskFundamentalProperties {
|
||||
|
||||
public interface IReloadResourcesTextRequested {
|
||||
public void reloadResourcesTextRequested();
|
||||
void reloadResourcesTextRequested();
|
||||
}
|
||||
|
||||
private List<IReloadResourcesTextRequested> reloadRequestedListeners = new ArrayList<IReloadResourcesTextRequested>();
|
||||
private List<IReloadResourcesTextRequested> reloadRequestedListeners = new ArrayList<>();
|
||||
|
||||
private PropertyChangeSupport fundamentalPropertiesListeners = new PropertyChangeSupport(
|
||||
this);
|
||||
private PropertyChangeSupport fundamentalPropertiesListeners = new PropertyChangeSupport(this);
|
||||
|
||||
private PropertyChangeSupport visibilityProperties = new PropertyChangeSupport(
|
||||
this);
|
||||
private PropertyChangeSupport visibilityProperties = new PropertyChangeSupport(this);
|
||||
|
||||
private PropertyChangeSupport criticalPathProperty = new PropertyChangeSupport(
|
||||
this);
|
||||
private PropertyChangeSupport criticalPathProperty = new PropertyChangeSupport(this);
|
||||
|
||||
private PropertyChangeSupport advancesProperty = new PropertyChangeSupport(
|
||||
this);
|
||||
private PropertyChangeSupport advancesProperty = new PropertyChangeSupport(this);
|
||||
|
||||
private PropertyChangeSupport reportedHoursProperty = new PropertyChangeSupport(
|
||||
this);
|
||||
private PropertyChangeSupport reportedHoursProperty = new PropertyChangeSupport(this);
|
||||
|
||||
private PropertyChangeSupport moneyCostBarProperty = new PropertyChangeSupport(
|
||||
this);
|
||||
private PropertyChangeSupport moneyCostBarProperty = new PropertyChangeSupport(this);
|
||||
|
||||
private final ITaskFundamentalProperties fundamentalProperties;
|
||||
|
||||
|
|
@ -91,32 +85,31 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
|
||||
private boolean showingMoneyCostBar = false;
|
||||
|
||||
private ConstraintViolationNotificator<GanttDate> violationNotificator = ConstraintViolationNotificator
|
||||
.create();
|
||||
private ConstraintViolationNotificator<GanttDate> violationNotificator = ConstraintViolationNotificator.create();
|
||||
|
||||
private IDependenciesEnforcerHook dependenciesEnforcerHook = GanttDiagramGraph
|
||||
.doNothingHook();
|
||||
private IDependenciesEnforcerHook dependenciesEnforcerHook = GanttDiagramGraph.doNothingHook();
|
||||
|
||||
private final INotificationAfterDependenciesEnforcement notifyDates = new INotificationAfterDependenciesEnforcement() {
|
||||
private final INotificationAfterDependenciesEnforcement notifyDates =
|
||||
new INotificationAfterDependenciesEnforcement() {
|
||||
@Override
|
||||
public void onStartDateChange(GanttDate previousStart, GanttDate previousEnd, GanttDate newStart) {
|
||||
|
||||
@Override
|
||||
public void onStartDateChange(GanttDate previousStart,
|
||||
GanttDate previousEnd, GanttDate newStart) {
|
||||
fundamentalPropertiesListeners.firePropertyChange("beginDate",
|
||||
previousStart, fundamentalProperties.getBeginDate());
|
||||
fireEndDate(previousEnd);
|
||||
}
|
||||
fundamentalPropertiesListeners.firePropertyChange(
|
||||
"beginDate", previousStart, fundamentalProperties.getBeginDate());
|
||||
|
||||
@Override
|
||||
public void onEndDateChange(GanttDate previousEnd, GanttDate newEnd) {
|
||||
fireEndDate(previousEnd);
|
||||
}
|
||||
fireEndDate(previousEnd);
|
||||
}
|
||||
|
||||
private void fireEndDate(GanttDate previousEnd) {
|
||||
fundamentalPropertiesListeners.firePropertyChange("endDate",
|
||||
previousEnd, fundamentalProperties.getEndDate());
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public void onEndDateChange(GanttDate previousEnd, GanttDate newEnd) {
|
||||
fireEndDate(previousEnd);
|
||||
}
|
||||
|
||||
private void fireEndDate(GanttDate previousEnd) {
|
||||
fundamentalPropertiesListeners.firePropertyChange(
|
||||
"endDate", previousEnd, fundamentalProperties.getEndDate());
|
||||
}
|
||||
};
|
||||
|
||||
public Task(ITaskFundamentalProperties fundamentalProperties) {
|
||||
this.fundamentalProperties = fundamentalProperties;
|
||||
|
|
@ -124,13 +117,11 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
|
||||
@Override
|
||||
public List<Constraint<GanttDate>> getStartConstraints() {
|
||||
return violationNotificator.withListener(fundamentalProperties
|
||||
.getStartConstraints());
|
||||
return violationNotificator.withListener(fundamentalProperties.getStartConstraints());
|
||||
}
|
||||
|
||||
public List<Constraint<GanttDate>> getEndConstraints() {
|
||||
return violationNotificator.withListener(fundamentalProperties
|
||||
.getEndConstraints());
|
||||
return violationNotificator.withListener(fundamentalProperties.getEndConstraints());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -149,13 +140,13 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
|
||||
@Override
|
||||
public void setEndDate(GanttDate value) {
|
||||
if (value == null) {
|
||||
if ( value == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
GanttDate previousEnd = fundamentalProperties.getEndDate();
|
||||
getFundamentalPropertiesPosition().setEndDate(value);
|
||||
dependenciesEnforcerHook.setNewEnd(previousEnd,
|
||||
fundamentalProperties.getEndDate());
|
||||
dependenciesEnforcerHook.setNewEnd(previousEnd, fundamentalProperties.getEndDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -163,8 +154,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
GanttDate previousValue = fundamentalProperties.getBeginDate();
|
||||
GanttDate previousEnd = fundamentalProperties.getEndDate();
|
||||
getFundamentalPropertiesPosition().setBeginDate(newStart);
|
||||
dependenciesEnforcerHook.setStartDate(previousValue, previousEnd,
|
||||
newStart);
|
||||
dependenciesEnforcerHook.setStartDate(previousValue, previousEnd, newStart);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -179,20 +169,18 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
GanttDate previousStart = getBeginDate();
|
||||
GanttDate previousEnd = getEndDate();
|
||||
getFundamentalPropertiesPosition().moveTo(date);
|
||||
dependenciesEnforcerHook.setStartDate(previousStart, previousEnd,
|
||||
date);
|
||||
dependenciesEnforcerHook.setStartDate(previousStart, previousEnd, date);
|
||||
}
|
||||
|
||||
private IUpdatablePosition getFundamentalPropertiesPosition() {
|
||||
final IUpdatablePosition[] result = new IUpdatablePosition[1];
|
||||
fundamentalProperties.doPositionModifications(new IModifications() {
|
||||
|
||||
@Override
|
||||
public void doIt(IUpdatablePosition position) {
|
||||
result[0] = position;
|
||||
}
|
||||
});
|
||||
assert result[0] != null;
|
||||
|
||||
return result[0];
|
||||
}
|
||||
};
|
||||
|
|
@ -203,8 +191,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
|
||||
public abstract boolean isExpanded() throws UnsupportedOperationException;
|
||||
|
||||
public abstract List<Task> getTasks()
|
||||
throws UnsupportedOperationException;
|
||||
public abstract List<Task> getTasks() throws UnsupportedOperationException;
|
||||
|
||||
public boolean isVisible() {
|
||||
return visible;
|
||||
|
|
@ -213,8 +200,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
public void setVisible(boolean visible) {
|
||||
boolean previousValue = this.visible;
|
||||
this.visible = visible;
|
||||
visibilityProperties.firePropertyChange("visible", previousValue,
|
||||
this.visible);
|
||||
visibilityProperties.firePropertyChange("visible", previousValue, this.visible);
|
||||
}
|
||||
|
||||
public boolean isInCriticalPath() {
|
||||
|
|
@ -224,15 +210,13 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
public void setInCriticalPath(boolean inCriticalPath) {
|
||||
boolean previousValue = this.inCriticalPath;
|
||||
this.inCriticalPath = inCriticalPath;
|
||||
criticalPathProperty.firePropertyChange("inCriticalPath",
|
||||
previousValue, this.inCriticalPath);
|
||||
criticalPathProperty.firePropertyChange("inCriticalPath", previousValue, this.inCriticalPath);
|
||||
}
|
||||
|
||||
public void setShowingAdvances(boolean showingAdvances) {
|
||||
boolean previousValue = this.showingAdvances;
|
||||
this.showingAdvances = showingAdvances;
|
||||
advancesProperty.firePropertyChange("showingAdvances", previousValue,
|
||||
this.showingAdvances);
|
||||
advancesProperty.firePropertyChange("showingAdvances", previousValue, this.showingAdvances);
|
||||
}
|
||||
|
||||
public boolean isShowingAdvances() {
|
||||
|
|
@ -242,8 +226,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
public void setShowingReportedHours(boolean showingReportedHours) {
|
||||
boolean previousValue = this.showingReportedHours;
|
||||
this.showingReportedHours = showingReportedHours;
|
||||
reportedHoursProperty.firePropertyChange("showingReportedHours",
|
||||
previousValue, this.showingReportedHours);
|
||||
reportedHoursProperty.firePropertyChange("showingReportedHours", previousValue, this.showingReportedHours);
|
||||
}
|
||||
|
||||
public boolean isShowingReportedHours() {
|
||||
|
|
@ -253,8 +236,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
public void setShowingMoneyCostBar(boolean showingMoneyCostBar) {
|
||||
boolean previousValue = this.showingMoneyCostBar;
|
||||
this.showingMoneyCostBar = showingMoneyCostBar;
|
||||
moneyCostBarProperty.firePropertyChange("showingMoneyCostBar",
|
||||
previousValue, this.showingMoneyCostBar);
|
||||
moneyCostBarProperty.firePropertyChange("showingMoneyCostBar", previousValue, this.showingMoneyCostBar);
|
||||
}
|
||||
|
||||
public boolean isShowingMoneyCostBar() {
|
||||
|
|
@ -268,12 +250,10 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
public void setName(String name) {
|
||||
String previousValue = fundamentalProperties.getName();
|
||||
fundamentalProperties.setName(name);
|
||||
fundamentalPropertiesListeners.firePropertyChange("name",
|
||||
previousValue, name);
|
||||
fundamentalPropertiesListeners.firePropertyChange("name", previousValue, name);
|
||||
}
|
||||
|
||||
public void registerDependenciesEnforcerHook(
|
||||
IDependenciesEnforcerHookFactory<Task> factory) {
|
||||
public void registerDependenciesEnforcerHook(IDependenciesEnforcerHookFactory<Task> factory) {
|
||||
Validate.notNull(factory);
|
||||
dependenciesEnforcerHook = factory.create(this, notifyDates);
|
||||
Validate.notNull(dependenciesEnforcerHook);
|
||||
|
|
@ -288,52 +268,42 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
}
|
||||
|
||||
public long getLengthMilliseconds() {
|
||||
return getEndDate().toDayRoundedDate().getTime()
|
||||
- getBeginDate().toDayRoundedDate().getTime();
|
||||
return getEndDate().toDayRoundedDate().getTime() - getBeginDate().toDayRoundedDate().getTime();
|
||||
}
|
||||
|
||||
public ReadableDuration getLength() {
|
||||
return new Duration(getBeginDate().toDayRoundedDate().getTime(),
|
||||
getEndDate().toDayRoundedDate().getTime());
|
||||
return new Duration(getBeginDate().toDayRoundedDate().getTime(), getEndDate().toDayRoundedDate().getTime());
|
||||
}
|
||||
|
||||
public void addVisibilityPropertiesChangeListener(
|
||||
PropertyChangeListener listener) {
|
||||
public void addVisibilityPropertiesChangeListener(PropertyChangeListener listener) {
|
||||
this.visibilityProperties.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void addCriticalPathPropertyChangeListener(
|
||||
PropertyChangeListener listener) {
|
||||
public void addCriticalPathPropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.criticalPathProperty.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void addAdvancesPropertyChangeListener(
|
||||
PropertyChangeListener listener) {
|
||||
public void addAdvancesPropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.advancesProperty.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void addReportedHoursPropertyChangeListener(
|
||||
PropertyChangeListener listener) {
|
||||
public void addReportedHoursPropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.reportedHoursProperty.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void addMoneyCostBarPropertyChangeListener(
|
||||
PropertyChangeListener listener) {
|
||||
public void addMoneyCostBarPropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.moneyCostBarProperty.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void addFundamentalPropertiesChangeListener(
|
||||
PropertyChangeListener listener) {
|
||||
public void addFundamentalPropertiesChangeListener(PropertyChangeListener listener) {
|
||||
this.fundamentalPropertiesListeners.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.fundamentalPropertiesListeners
|
||||
.removePropertyChangeListener(listener);
|
||||
this.fundamentalPropertiesListeners.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removeVisibilityPropertiesChangeListener(
|
||||
PropertyChangeListener listener) {
|
||||
public void removeVisibilityPropertiesChangeListener(PropertyChangeListener listener) {
|
||||
this.visibilityProperties.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
|
|
@ -344,16 +314,15 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
|
||||
@Override
|
||||
public List<Constraint<GanttDate>> getCurrentLengthConstraint() {
|
||||
if (isContainer()) {
|
||||
if ( isContainer() ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return violationNotificator.withListener(fundamentalProperties
|
||||
.getCurrentLengthConstraint());
|
||||
|
||||
return violationNotificator.withListener(fundamentalProperties.getCurrentLengthConstraint());
|
||||
}
|
||||
|
||||
public Constraint<GanttDate> getEndDateBiggerThanStartDate() {
|
||||
return violationNotificator
|
||||
.withListener(biggerOrEqualThan(getBeginDate()));
|
||||
return violationNotificator.withListener(biggerOrEqualThan(getBeginDate()));
|
||||
}
|
||||
|
||||
public String getNotes() {
|
||||
|
|
@ -363,16 +332,17 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
public void setNotes(String notes) {
|
||||
String previousValue = fundamentalProperties.getNotes();
|
||||
this.fundamentalProperties.setNotes(notes);
|
||||
fundamentalPropertiesListeners.firePropertyChange("notes",
|
||||
previousValue, this.fundamentalProperties.getNotes());
|
||||
|
||||
fundamentalPropertiesListeners.firePropertyChange(
|
||||
"notes", previousValue, this.fundamentalProperties.getNotes());
|
||||
}
|
||||
|
||||
public void resizeTo(final LocalDate date) {
|
||||
if (date.compareTo(getBeginDateAsLocalDate()) < 0) {
|
||||
if ( date.compareTo(getBeginDateAsLocalDate()) < 0 ) {
|
||||
return;
|
||||
}
|
||||
doPositionModifications(new IModifications() {
|
||||
|
||||
doPositionModifications(new IModifications() {
|
||||
@Override
|
||||
public void doIt(IUpdatablePosition position) {
|
||||
position.resizeTo(GanttDate.createFrom(date));
|
||||
|
|
@ -447,8 +417,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
public void setDeadline(Date date) {
|
||||
Date previousValue = fundamentalProperties.getDeadline();
|
||||
fundamentalProperties.setDeadline(date);
|
||||
fundamentalPropertiesListeners.firePropertyChange("deadline",
|
||||
previousValue, date);
|
||||
fundamentalPropertiesListeners.firePropertyChange("deadline", previousValue, date);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -456,19 +425,16 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
return fundamentalProperties.getConsolidatedline();
|
||||
}
|
||||
|
||||
public void addConstraintViolationListener(
|
||||
IConstraintViolationListener<GanttDate> listener, Mode mode) {
|
||||
public void addConstraintViolationListener(IConstraintViolationListener<GanttDate> listener, Mode mode) {
|
||||
violationNotificator.addConstraintViolationListener(listener, mode);
|
||||
}
|
||||
|
||||
public void addReloadListener(
|
||||
IReloadResourcesTextRequested reloadResourcesTextRequested) {
|
||||
public void addReloadListener(IReloadResourcesTextRequested reloadResourcesTextRequested) {
|
||||
Validate.notNull(reloadResourcesTextRequested);
|
||||
this.reloadRequestedListeners.add(reloadResourcesTextRequested);
|
||||
}
|
||||
|
||||
public void removeReloadListener(
|
||||
IReloadResourcesTextRequested reloadResourcesTextRequested) {
|
||||
public void removeReloadListener(IReloadResourcesTextRequested reloadResourcesTextRequested) {
|
||||
this.reloadRequestedListeners.remove(reloadResourcesTextRequested);
|
||||
}
|
||||
|
||||
|
|
@ -481,8 +447,8 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
public static void reloadResourcesText(IContextWithPlannerTask<?> context) {
|
||||
Task task = context.getTask();
|
||||
task.reloadResourcesText();
|
||||
List<? extends TaskContainer> parents = context.getMapper().getParents(
|
||||
task);
|
||||
List<? extends TaskContainer> parents = context.getMapper().getParents(task);
|
||||
|
||||
for (TaskContainer each : parents) {
|
||||
each.reloadResourcesText();
|
||||
}
|
||||
|
|
@ -545,8 +511,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
}
|
||||
|
||||
public void updateSizeDueToDateChanges(GanttDate previousStart, GanttDate previousEnd) {
|
||||
dependenciesEnforcerHook.setStartDate(previousStart, previousEnd,
|
||||
getBeginDate());
|
||||
dependenciesEnforcerHook.setStartDate(previousStart, previousEnd, getBeginDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -565,10 +530,8 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
}
|
||||
|
||||
public void firePropertyChangeForTaskDates() {
|
||||
fundamentalPropertiesListeners.firePropertyChange("beginDate", null,
|
||||
getBeginDate());
|
||||
fundamentalPropertiesListeners.firePropertyChange("endDate", null,
|
||||
getEndDate());
|
||||
fundamentalPropertiesListeners.firePropertyChange("beginDate", null, getBeginDate());
|
||||
fundamentalPropertiesListeners.firePropertyChange("endDate", null, getEndDate());
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
|
|
|
|||
|
|
@ -23,22 +23,19 @@ package org.zkoss.ganttz.data.constraint;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
/**
|
||||
* @author Óscar González Fernández
|
||||
*
|
||||
*/
|
||||
public class ConstraintOnComparableValues<T extends Comparable<T>> extends
|
||||
Constraint<T> {
|
||||
public class ConstraintOnComparableValues<T extends Comparable<T>> extends Constraint<T> {
|
||||
|
||||
public static <T extends Comparable<T>> Constraint<T> biggerOrEqualThan(
|
||||
T value) {
|
||||
public static <T extends Comparable<T>> Constraint<T> biggerOrEqualThan(T value) {
|
||||
return instantiate(ComparisonType.BIGGER_OR_EQUAL_THAN, value);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> Constraint<T> lessOrEqualThan(
|
||||
T value) {
|
||||
public static <T extends Comparable<T>> Constraint<T> lessOrEqualThan(T value) {
|
||||
return instantiate(ComparisonType.LESS_OR_EQUAL_THAN, value);
|
||||
}
|
||||
|
||||
|
|
@ -46,11 +43,11 @@ public class ConstraintOnComparableValues<T extends Comparable<T>> extends
|
|||
return instantiate(ComparisonType.EQUAL_TO, value);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> Constraint<T> instantiate(
|
||||
ComparisonType type, T value) {
|
||||
if (value == null) {
|
||||
public static <T extends Comparable<T>> Constraint<T> instantiate(ComparisonType type, T value) {
|
||||
if ( value == null ) {
|
||||
return Constraint.voidConstraint();
|
||||
}
|
||||
|
||||
return new ConstraintOnComparableValues<T>(type, value);
|
||||
}
|
||||
|
||||
|
|
@ -70,21 +67,28 @@ public class ConstraintOnComparableValues<T extends Comparable<T>> extends
|
|||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected T applyConstraintTo(T value) {
|
||||
if (value == null) {
|
||||
if ( value == null ) {
|
||||
return comparisonValue;
|
||||
}
|
||||
|
||||
switch (comparisonType) {
|
||||
case LESS_OR_EQUAL_THAN:
|
||||
return min(comparisonValue, value);
|
||||
case LESS_OR_EQUAL_THAN_RIGHT_FLOATING:
|
||||
case BIGGER_OR_EQUAL_THAN_LEFT_FLOATING:
|
||||
return comparisonValue;
|
||||
case BIGGER_OR_EQUAL_THAN:
|
||||
return max(comparisonValue, value);
|
||||
case EQUAL_TO:
|
||||
return comparisonValue;
|
||||
default:
|
||||
throw new RuntimeException("can't handle "+comparisonType);
|
||||
|
||||
case LESS_OR_EQUAL_THAN:
|
||||
return min(comparisonValue, value);
|
||||
|
||||
case LESS_OR_EQUAL_THAN_RIGHT_FLOATING:
|
||||
|
||||
case BIGGER_OR_EQUAL_THAN_LEFT_FLOATING:
|
||||
return comparisonValue;
|
||||
|
||||
case BIGGER_OR_EQUAL_THAN:
|
||||
return max(comparisonValue, value);
|
||||
|
||||
case EQUAL_TO:
|
||||
return comparisonValue;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("can't handle "+comparisonType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,16 +103,22 @@ public class ConstraintOnComparableValues<T extends Comparable<T>> extends
|
|||
@Override
|
||||
public boolean isSatisfiedBy(T value) {
|
||||
switch (comparisonType) {
|
||||
case LESS_OR_EQUAL_THAN:
|
||||
case LESS_OR_EQUAL_THAN_RIGHT_FLOATING:
|
||||
return value.compareTo(comparisonValue) <= 0;
|
||||
case BIGGER_OR_EQUAL_THAN:
|
||||
case BIGGER_OR_EQUAL_THAN_LEFT_FLOATING:
|
||||
return value.compareTo(comparisonValue) >= 0;
|
||||
case EQUAL_TO:
|
||||
return value.compareTo(comparisonValue) == 0;
|
||||
default:
|
||||
throw new RuntimeException("can't handle " + comparisonType);
|
||||
|
||||
case LESS_OR_EQUAL_THAN:
|
||||
|
||||
case LESS_OR_EQUAL_THAN_RIGHT_FLOATING:
|
||||
return value.compareTo(comparisonValue) <= 0;
|
||||
|
||||
case BIGGER_OR_EQUAL_THAN:
|
||||
|
||||
case BIGGER_OR_EQUAL_THAN_LEFT_FLOATING:
|
||||
return value.compareTo(comparisonValue) >= 0;
|
||||
|
||||
case EQUAL_TO:
|
||||
return value.compareTo(comparisonValue) == 0;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("can't handle " + comparisonType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
package org.zkoss.ganttz.data.resourceload;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
public class LoadLevel {
|
||||
|
||||
|
|
@ -33,18 +33,21 @@ public class LoadLevel {
|
|||
return percentage == 0;
|
||||
}
|
||||
},
|
||||
|
||||
SOME_LOAD {
|
||||
@Override
|
||||
public boolean contains(int percentage) {
|
||||
return percentage > 0 && percentage < 100;
|
||||
}
|
||||
},
|
||||
|
||||
FULL_LOAD {
|
||||
@Override
|
||||
public boolean contains(int percentage) {
|
||||
return percentage == 100;
|
||||
}
|
||||
},
|
||||
|
||||
OVERLOAD {
|
||||
@Override
|
||||
public boolean contains(int percentage) {
|
||||
|
|
@ -55,10 +58,11 @@ public class LoadLevel {
|
|||
protected abstract boolean contains(int percentage);
|
||||
public static Category categoryFor(int percentage) {
|
||||
for (Category category : values()) {
|
||||
if (category.contains(percentage)) {
|
||||
if ( category.contains(percentage) ) {
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("couldn't handle " + percentage);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ import java.util.Collections;
|
|||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.zkoss.ganttz.data.GanttDate;
|
||||
|
|
@ -47,14 +47,20 @@ public class LoadPeriod {
|
|||
|
||||
private final String assignedEffort;
|
||||
|
||||
public LoadPeriod(GanttDate start, GanttDate end, String availableEffort,
|
||||
String assignedEffort, LoadLevel loadLevel) {
|
||||
public LoadPeriod(
|
||||
GanttDate start,
|
||||
GanttDate end,
|
||||
String availableEffort,
|
||||
String assignedEffort,
|
||||
LoadLevel loadLevel) {
|
||||
|
||||
Validate.notNull(start);
|
||||
Validate.notNull(end);
|
||||
Validate.notNull(loadLevel);
|
||||
Validate.notNull(availableEffort);
|
||||
Validate.notNull(assignedEffort);
|
||||
Validate.isTrue(start.compareTo(end) <= 0);
|
||||
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.loadLevel = loadLevel;
|
||||
|
|
@ -80,27 +86,28 @@ public class LoadPeriod {
|
|||
* @throws IllegalArgumentException
|
||||
* if some of the LoadPeriod overlaps
|
||||
*/
|
||||
public static List<LoadPeriod> sort(
|
||||
Collection<? extends LoadPeriod> notOverlappingPeriods)
|
||||
public static List<LoadPeriod> sort(Collection<? extends LoadPeriod> notOverlappingPeriods)
|
||||
throws IllegalArgumentException {
|
||||
ArrayList<LoadPeriod> result = new ArrayList<LoadPeriod>(
|
||||
notOverlappingPeriods);
|
||||
|
||||
ArrayList<LoadPeriod> result = new ArrayList<>(notOverlappingPeriods);
|
||||
Collections.sort(result, new Comparator<LoadPeriod>() {
|
||||
|
||||
@Override
|
||||
public int compare(LoadPeriod o1, LoadPeriod o2) {
|
||||
if (o1.overlaps(o2)) {
|
||||
if ( o1.overlaps(o2) ) {
|
||||
LOG.warn(o1 + " overlaps with " + o2);
|
||||
throw new IllegalArgumentException(o1 + " overlaps with "
|
||||
+ o2);
|
||||
throw new IllegalArgumentException(o1 + " overlaps with " + o2);
|
||||
}
|
||||
|
||||
int comparison = o1.start.compareTo(o2.start);
|
||||
if (comparison != 0) {
|
||||
if ( comparison != 0 ) {
|
||||
return comparison;
|
||||
}
|
||||
|
||||
return o1.end.compareTo(o2.end);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import java.util.Comparator;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.commons.collections.ComparatorUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.zkoss.ganttz.data.GanttDate;
|
||||
import org.zkoss.ganttz.util.Interval;
|
||||
|
|
@ -35,20 +35,19 @@ import org.zkoss.ganttz.util.Interval;
|
|||
public class LoadTimeLine {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final Comparator<GanttDate> nullSafeComparator = ComparatorUtils
|
||||
.nullLowComparator(ComparatorUtils.naturalComparator());
|
||||
private static final Comparator<GanttDate> nullSafeComparator =
|
||||
ComparatorUtils.nullLowComparator(ComparatorUtils.naturalComparator());
|
||||
|
||||
public static Comparator<LoadTimeLine> byStartAndEndDate() {
|
||||
return new Comparator<LoadTimeLine>() {
|
||||
|
||||
@Override
|
||||
public int compare(LoadTimeLine o1, LoadTimeLine o2) {
|
||||
int result = nullSafeComparator.compare(o1.getStartPeriod(),
|
||||
o2.getStartPeriod());
|
||||
if (result == 0) {
|
||||
return nullSafeComparator.compare(o1.getEndPeriod(),
|
||||
o2.getEndPeriod());
|
||||
int result = nullSafeComparator.compare(o1.getStartPeriod(), o2.getStartPeriod());
|
||||
if ( result == 0 ) {
|
||||
return nullSafeComparator.compare(o1.getEndPeriod(), o2.getEndPeriod());
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
|
@ -63,40 +62,43 @@ public class LoadTimeLine {
|
|||
|
||||
private final List<LoadTimeLine> children;
|
||||
|
||||
public LoadTimeLine(String conceptName, List<LoadPeriod> loadPeriods,
|
||||
TimeLineRole<?> role) {
|
||||
public LoadTimeLine(String conceptName,
|
||||
List<LoadPeriod> loadPeriods,
|
||||
TimeLineRole<?> role) {
|
||||
|
||||
Validate.notEmpty(conceptName);
|
||||
Validate.notNull(loadPeriods);
|
||||
|
||||
this.loadPeriods = LoadPeriod.sort(loadPeriods);
|
||||
this.conceptName = conceptName;
|
||||
this.type = "";
|
||||
this.timeLineRole = role;
|
||||
this.children = Collections
|
||||
.unmodifiableList(new ArrayList<LoadTimeLine>());
|
||||
this.children = Collections.unmodifiableList(new ArrayList<LoadTimeLine>());
|
||||
}
|
||||
|
||||
public LoadTimeLine(String conceptName, List<LoadPeriod> loadPeriods,
|
||||
String type, TimeLineRole<?> role) {
|
||||
public LoadTimeLine(String conceptName, List<LoadPeriod> loadPeriods, String type, TimeLineRole<?> role) {
|
||||
Validate.notEmpty(conceptName);
|
||||
Validate.notNull(loadPeriods);
|
||||
|
||||
this.loadPeriods = LoadPeriod.sort(loadPeriods);
|
||||
this.conceptName = conceptName;
|
||||
this.timeLineRole = role;
|
||||
this.type = type;
|
||||
this.children = Collections
|
||||
.unmodifiableList(new ArrayList<LoadTimeLine>());
|
||||
this.children = Collections.unmodifiableList(new ArrayList<LoadTimeLine>());
|
||||
}
|
||||
|
||||
public LoadTimeLine(LoadTimeLine main, List<LoadTimeLine> children) {
|
||||
Validate.notEmpty(main.getConceptName());
|
||||
Validate.notNull(main.getLoadPeriods());
|
||||
|
||||
this.loadPeriods = LoadPeriod.sort(main.getLoadPeriods());
|
||||
this.conceptName = main.getConceptName();
|
||||
this.timeLineRole = main.getRole();
|
||||
this.type = main.getType();
|
||||
|
||||
Validate.notNull(children);
|
||||
this.children = Collections
|
||||
.unmodifiableList(new ArrayList<LoadTimeLine>(children));
|
||||
|
||||
this.children = Collections.unmodifiableList(new ArrayList<>(children));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -121,9 +123,10 @@ public class LoadTimeLine {
|
|||
}
|
||||
|
||||
public GanttDate getStartPeriod() {
|
||||
if (isEmpty()) {
|
||||
if ( isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getFirst().getStart();
|
||||
}
|
||||
|
||||
|
|
@ -132,9 +135,10 @@ public class LoadTimeLine {
|
|||
}
|
||||
|
||||
public GanttDate getEndPeriod() {
|
||||
if (isEmpty()) {
|
||||
if ( isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getLast().getEnd();
|
||||
}
|
||||
|
||||
|
|
@ -145,38 +149,46 @@ public class LoadTimeLine {
|
|||
public static Interval getIntervalFrom(List<LoadTimeLine> timeLines) {
|
||||
GanttDate start = null;
|
||||
GanttDate end = null;
|
||||
|
||||
for (LoadTimeLine loadTimeLine : timeLines) {
|
||||
if(!loadTimeLine.isEmpty()) {
|
||||
if( !loadTimeLine.isEmpty() ) {
|
||||
Validate.notNull(loadTimeLine.getStart());
|
||||
start = min(start, loadTimeLine.getStart());
|
||||
Validate.notNull(loadTimeLine.getEnd());
|
||||
end = max(end, loadTimeLine.getEnd());
|
||||
}
|
||||
}
|
||||
if (timeLines.isEmpty() || start == null || end == null) {
|
||||
|
||||
if ( timeLines.isEmpty() || start == null || end == null ) {
|
||||
LocalDate localDateNow = new LocalDate();
|
||||
|
||||
return new Interval(localDateNow, localDateNow.plusYears(5));
|
||||
}
|
||||
|
||||
return new Interval(start.toLocalDate(), end.asExclusiveEnd());
|
||||
}
|
||||
|
||||
private static GanttDate max(GanttDate one, GanttDate other) {
|
||||
if (one == null) {
|
||||
if ( one == null ) {
|
||||
return other;
|
||||
}
|
||||
if (other == null) {
|
||||
|
||||
if ( other == null ) {
|
||||
return one;
|
||||
}
|
||||
|
||||
return one.compareTo(other) > 0 ? one : other;
|
||||
}
|
||||
|
||||
private static GanttDate min(GanttDate one, GanttDate other) {
|
||||
if (one == null) {
|
||||
if ( one == null ) {
|
||||
return other;
|
||||
}
|
||||
if (other == null) {
|
||||
|
||||
if ( other == null ) {
|
||||
return one;
|
||||
}
|
||||
|
||||
return one.compareTo(other) < 0 ? one : other;
|
||||
}
|
||||
|
||||
|
|
@ -189,35 +201,39 @@ public class LoadTimeLine {
|
|||
}
|
||||
|
||||
public List<LoadTimeLine> getAllChildren() {
|
||||
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
|
||||
List<LoadTimeLine> result = new ArrayList<>();
|
||||
for (LoadTimeLine child : children) {
|
||||
result.add(child);
|
||||
result.addAll(child.getAllChildren());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public GanttDate getStart() {
|
||||
GanttDate result = getStartPeriod();
|
||||
|
||||
for (LoadTimeLine loadTimeLine : getChildren()) {
|
||||
GanttDate start = loadTimeLine.getStart();
|
||||
if (start != null) {
|
||||
result = result == null || result.compareTo(start) > 0 ? start
|
||||
: result;
|
||||
|
||||
if ( start != null ) {
|
||||
result = result == null || result.compareTo(start) > 0 ? start : result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public GanttDate getEnd() {
|
||||
GanttDate result = getEndPeriod();
|
||||
|
||||
for (LoadTimeLine loadTimeLine : getChildren()) {
|
||||
GanttDate end = loadTimeLine.getEnd();
|
||||
if (end != null) {
|
||||
result = result == null || result.compareTo(end) < 0 ? end
|
||||
: result;
|
||||
if ( end != null ) {
|
||||
result = result == null || result.compareTo(end) < 0 ? end : result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
package org.zkoss.ganttz.extensions;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import static org.zkoss.ganttz.i18n.I18nHelper._;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.zkoss.ganttz.IChartVisibilityChangedListener;
|
||||
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
|
||||
|
|
@ -53,14 +53,15 @@ import org.zkoss.zul.SimpleListModel;
|
|||
import org.zkoss.zul.api.Combobox;
|
||||
import org.zkoss.zul.api.Listbox;
|
||||
import org.zkoss.zul.api.South;
|
||||
|
||||
public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||
|
||||
public interface IToolbarCommand {
|
||||
public void doAction();
|
||||
void doAction();
|
||||
|
||||
public String getLabel();
|
||||
String getLabel();
|
||||
|
||||
public String getImage();
|
||||
String getImage();
|
||||
}
|
||||
|
||||
private TimeTrackerComponent timeTrackerComponent;
|
||||
|
|
@ -81,8 +82,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
|
||||
private final Component componentOnWhichGiveFeedback;
|
||||
|
||||
private WeakReferencedListeners<IFilterChangedListener> zoomListeners = WeakReferencedListeners
|
||||
.create();
|
||||
private WeakReferencedListeners<IFilterChangedListener> zoomListeners = WeakReferencedListeners.create();
|
||||
|
||||
private Listbox listZoomLevels;
|
||||
|
||||
|
|
@ -98,14 +98,14 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
private final PaginationType paginationType;
|
||||
|
||||
private WeakReferencedListeners<IPaginationFilterChangedListener> nameFilterListener =
|
||||
WeakReferencedListeners.create();
|
||||
WeakReferencedListeners.create();
|
||||
|
||||
private Component loadChart;
|
||||
|
||||
private boolean visibleChart = true;
|
||||
|
||||
private WeakReferencedListeners<IChartVisibilityChangedListener> chartVisibilityListeners = WeakReferencedListeners
|
||||
.create();
|
||||
private WeakReferencedListeners<IChartVisibilityChangedListener> chartVisibilityListeners =
|
||||
WeakReferencedListeners.create();
|
||||
|
||||
private final boolean expandResourceLoadViewCharts;
|
||||
|
||||
|
|
@ -113,12 +113,17 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
|
||||
private Component secondOptionalFilter;
|
||||
|
||||
public ResourcesLoadPanel(List<LoadTimeLine> groups,
|
||||
TimeTracker timeTracker, Component componentOnWhichGiveFeedback,
|
||||
boolean expandResourceLoadViewCharts, PaginationType paginationType) {
|
||||
public ResourcesLoadPanel(
|
||||
List<LoadTimeLine> groups,
|
||||
TimeTracker timeTracker,
|
||||
Component componentOnWhichGiveFeedback,
|
||||
boolean expandResourceLoadViewCharts,
|
||||
PaginationType paginationType) {
|
||||
|
||||
this.componentOnWhichGiveFeedback = componentOnWhichGiveFeedback;
|
||||
this.expandResourceLoadViewCharts = expandResourceLoadViewCharts;
|
||||
this.paginationType = paginationType;
|
||||
|
||||
init(groups, timeTracker);
|
||||
}
|
||||
|
||||
|
|
@ -138,17 +143,19 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
|
||||
public ListModel getFilters() {
|
||||
String[] filters = new String[] { FILTER_RESOURCES, FILTER_CRITERIA };
|
||||
|
||||
return new SimpleListModel(filters);
|
||||
}
|
||||
|
||||
public void setFilter(String filterby) {
|
||||
if (filterby.equals(FILTER_RESOURCES)) {
|
||||
if ( filterby.equals(FILTER_RESOURCES) ) {
|
||||
this.filterbyResources = true;
|
||||
this.feedBackMessage = _("showing resources");
|
||||
} else {
|
||||
this.filterbyResources = false;
|
||||
this.feedBackMessage = _("showing criteria");
|
||||
}
|
||||
|
||||
refreshNameFilter = true;
|
||||
filterByNamePosition = 0;
|
||||
invalidatingChangeHappenedWithFeedback();
|
||||
|
|
@ -159,19 +166,17 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
}
|
||||
|
||||
private void invalidatingChangeHappenedWithFeedback() {
|
||||
LongOperationFeedback.execute(componentOnWhichGiveFeedback,
|
||||
new ILongOperation() {
|
||||
LongOperationFeedback.execute(componentOnWhichGiveFeedback, new ILongOperation() {
|
||||
@Override
|
||||
public void doAction() {
|
||||
applyFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAction() {
|
||||
applyFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getFeedBackMessage();
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public String getName() {
|
||||
return getFeedBackMessage();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String getFeedBackMessage() {
|
||||
|
|
@ -179,13 +184,12 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
}
|
||||
|
||||
private void applyFilter() {
|
||||
zoomListeners
|
||||
.fireEvent(new IListenerNotification<IFilterChangedListener>() {
|
||||
@Override
|
||||
public void doNotify(IFilterChangedListener listener) {
|
||||
listener.filterChanged(getFilter());
|
||||
}
|
||||
});
|
||||
zoomListeners.fireEvent(new IListenerNotification<IFilterChangedListener>() {
|
||||
@Override
|
||||
public void doNotify(IFilterChangedListener listener) {
|
||||
listener.filterChanged(getFilter());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addFilterListener(IFilterChangedListener listener) {
|
||||
|
|
@ -193,9 +197,13 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
}
|
||||
|
||||
public ListModel getZoomLevels() {
|
||||
ZoomLevel[] selectableZoomlevels = { ZoomLevel.DETAIL_ONE,
|
||||
ZoomLevel.DETAIL_TWO, ZoomLevel.DETAIL_THREE,
|
||||
ZoomLevel.DETAIL_FOUR, ZoomLevel.DETAIL_FIVE };
|
||||
ZoomLevel[] selectableZoomlevels = {
|
||||
ZoomLevel.DETAIL_ONE,
|
||||
ZoomLevel.DETAIL_TWO,
|
||||
ZoomLevel.DETAIL_THREE,
|
||||
ZoomLevel.DETAIL_FOUR,
|
||||
ZoomLevel.DETAIL_FIVE };
|
||||
|
||||
return new SimpleListModel(selectableZoomlevels);
|
||||
}
|
||||
|
||||
|
|
@ -239,6 +247,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
Component toolbar = getToolbar();
|
||||
resetToolbar(toolbar);
|
||||
Separator separator = getSeparator();
|
||||
|
||||
for (IToolbarCommand c : commands) {
|
||||
toolbar.insertBefore(asButton(c), separator);
|
||||
}
|
||||
|
|
@ -246,8 +255,8 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
|
||||
private void resetToolbar(Component toolbar) {
|
||||
List<Component> children = toolbar.getChildren();
|
||||
List<Button> buttons = ComponentsFinder.findComponentsOfType(
|
||||
Button.class, children);
|
||||
List<Button> buttons = ComponentsFinder.findComponentsOfType(Button.class, children);
|
||||
|
||||
for (Button b : buttons) {
|
||||
toolbar.removeChild(b);
|
||||
}
|
||||
|
|
@ -255,63 +264,66 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
|
||||
private Button asButton(final IToolbarCommand c) {
|
||||
Button result = new Button();
|
||||
|
||||
result.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
c.doAction();
|
||||
}
|
||||
});
|
||||
if (!StringUtils.isEmpty(c.getImage())) {
|
||||
|
||||
if ( !StringUtils.isEmpty(c.getImage()) ) {
|
||||
result.setImage(c.getImage());
|
||||
result.setTooltiptext(c.getLabel());
|
||||
} else {
|
||||
result.setLabel(c.getLabel());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Separator getSeparator() {
|
||||
List<Component> children = getToolbar().getChildren();
|
||||
Separator separator = ComponentsFinder.findComponentsOfType(
|
||||
Separator.class, children).get(0);
|
||||
Separator separator = ComponentsFinder.findComponentsOfType(Separator.class, children).get(0);
|
||||
|
||||
return separator;
|
||||
}
|
||||
|
||||
private Component getToolbar() {
|
||||
Component toolbar = getFellow("toolbar");
|
||||
|
||||
return toolbar;
|
||||
}
|
||||
|
||||
private MutableTreeModel<LoadTimeLine> createModelForTree() {
|
||||
MutableTreeModel<LoadTimeLine> result = MutableTreeModel
|
||||
.create(LoadTimeLine.class);
|
||||
MutableTreeModel<LoadTimeLine> result = MutableTreeModel.create(LoadTimeLine.class);
|
||||
for (LoadTimeLine loadTimeLine : this.getGroupsToShow()) {
|
||||
result.addToRoot(loadTimeLine);
|
||||
result = addNodes(result, loadTimeLine);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private MutableTreeModel<LoadTimeLine> addNodes(
|
||||
MutableTreeModel<LoadTimeLine> tree, LoadTimeLine parent) {
|
||||
if (!parent.getChildren().isEmpty()) {
|
||||
private MutableTreeModel<LoadTimeLine> addNodes(MutableTreeModel<LoadTimeLine> tree, LoadTimeLine parent) {
|
||||
if ( !parent.getChildren().isEmpty() ) {
|
||||
tree.add(parent, parent.getChildren());
|
||||
|
||||
for (LoadTimeLine loadTimeLine : parent.getChildren()) {
|
||||
tree = addNodes(tree, loadTimeLine);
|
||||
}
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
private TimeTrackerComponent timeTrackerForResourcesLoadPanel(
|
||||
TimeTracker timeTracker) {
|
||||
private TimeTrackerComponent timeTrackerForResourcesLoadPanel(TimeTracker timeTracker) {
|
||||
return new TimeTrackerComponent(timeTracker) {
|
||||
@Override
|
||||
protected void scrollHorizontalPercentage(int daysDisplacement) {
|
||||
response("", new AuInvoke(resourceLoadList,
|
||||
"scroll_horizontal", daysDisplacement + ""));
|
||||
response("", new AuInvoke(resourceLoadList, "scroll_horizontal", daysDisplacement + ""));
|
||||
moveCurrentPositionScroll();
|
||||
}
|
||||
|
||||
|
|
@ -321,20 +333,18 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
LocalDate previousStart = getPreviousStart();
|
||||
|
||||
// get the current data
|
||||
int diffDays = getTimeTrackerComponent().getDiffDays(
|
||||
previousStart);
|
||||
int diffDays = getTimeTrackerComponent().getDiffDays(previousStart);
|
||||
double pixelPerDay = getTimeTrackerComponent().getPixelPerDay();
|
||||
|
||||
response("move_scroll", new AuInvoke(resourceLoadList,
|
||||
"move_scroll", "" + diffDays, "" + pixelPerDay));
|
||||
response("move_scroll", new AuInvoke(resourceLoadList, "move_scroll", "" + diffDays, "" + pixelPerDay));
|
||||
}
|
||||
|
||||
protected void updateCurrentDayScroll() {
|
||||
double previousPixelPerDay = getTimeTracker().getMapper()
|
||||
.getPixelsPerDay().doubleValue();
|
||||
double previousPixelPerDay = getTimeTracker().getMapper().getPixelsPerDay().doubleValue();
|
||||
|
||||
response("update_day_scroll", new AuInvoke(resourceLoadList,
|
||||
"update_day_scroll", "" + previousPixelPerDay));
|
||||
response(
|
||||
"update_day_scroll",
|
||||
new AuInvoke(resourceLoadList, "update_day_scroll", "" + previousPixelPerDay));
|
||||
|
||||
}
|
||||
};
|
||||
|
|
@ -354,11 +364,12 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
|
||||
// Insert additional filters if any
|
||||
Component additionalFilter = getFirstOptionalFilter();
|
||||
if(additionalFilter != null) {
|
||||
if( additionalFilter != null ) {
|
||||
getFellow("additionalFilterInsertionPoint1").appendChild(additionalFilter);
|
||||
}
|
||||
|
||||
additionalFilter = getSecondOptionalFilter();
|
||||
if(additionalFilter != null) {
|
||||
if( additionalFilter != null ) {
|
||||
getFellow("additionalFilterInsertionPoint2").appendChild(additionalFilter);
|
||||
}
|
||||
|
||||
|
|
@ -367,10 +378,10 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
listZoomLevels = (Listbox) getFellow("listZoomLevels");
|
||||
listZoomLevels.setSelectedIndex(timeTracker.getDetailLevel().ordinal());
|
||||
|
||||
if(paginationType == PaginationType.INTERNAL_PAGINATION && refreshNameFilter) {
|
||||
if( paginationType == PaginationType.INTERNAL_PAGINATION && refreshNameFilter ) {
|
||||
setupNameFilter();
|
||||
}
|
||||
else if(paginationType == PaginationType.NONE) {
|
||||
else if( paginationType == PaginationType.NONE ) {
|
||||
getFellow("filterByNameCombo").setVisible(false);
|
||||
getFellow("filterByNameLabel").setVisible(false);
|
||||
}
|
||||
|
|
@ -406,8 +417,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
}
|
||||
|
||||
private TimeTrackerComponent createTimeTrackerHeader() {
|
||||
return new TimeTrackerComponent(
|
||||
timeTracker) {
|
||||
return new TimeTrackerComponent(timeTracker) {
|
||||
|
||||
@Override
|
||||
protected void scrollHorizontalPercentage(int pixelsDisplacement) {
|
||||
|
|
@ -415,20 +425,15 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
|
||||
@Override
|
||||
protected void moveCurrentPositionScroll() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateCurrentDayScroll() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void addSeeScheduledOfListener(
|
||||
ISeeScheduledOfListener seeScheduledOfListener) {
|
||||
public void addSeeScheduledOfListener(ISeeScheduledOfListener seeScheduledOfListener) {
|
||||
leftPane.addSeeScheduledOfListener(seeScheduledOfListener);
|
||||
resourceLoadList.addSeeScheduledOfListener(seeScheduledOfListener);
|
||||
}
|
||||
|
|
@ -438,19 +443,19 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
filterByNameCombo.getChildren().clear();
|
||||
int size = groups.size();
|
||||
|
||||
if(size > numberOfGroupsByName) {
|
||||
if( size > numberOfGroupsByName ) {
|
||||
int position = 0;
|
||||
|
||||
while(position < size) {
|
||||
String firstName = groups.get(position).getConceptName();
|
||||
String lastName;
|
||||
int newPosition = position + numberOfGroupsByName;
|
||||
if(newPosition - 1 < size) {
|
||||
lastName = groups.get(newPosition - 1)
|
||||
.getConceptName();
|
||||
|
||||
if( newPosition - 1 < size ) {
|
||||
lastName = groups.get(newPosition - 1).getConceptName();
|
||||
}
|
||||
else {
|
||||
lastName = groups.get(size - 1)
|
||||
.getConceptName();
|
||||
lastName = groups.get(size - 1).getConceptName();
|
||||
}
|
||||
|
||||
Comboitem item = new Comboitem();
|
||||
|
|
@ -478,34 +483,34 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
* @return
|
||||
*/
|
||||
private List<LoadTimeLine> getGroupsToShow() {
|
||||
if(paginationType != PaginationType.INTERNAL_PAGINATION ||
|
||||
filterByNamePosition == -1) {
|
||||
if( paginationType != PaginationType.INTERNAL_PAGINATION || filterByNamePosition == -1 ) {
|
||||
return groups;
|
||||
}
|
||||
int endPosition =
|
||||
(filterByNamePosition + numberOfGroupsByName < groups.size())?
|
||||
filterByNamePosition + numberOfGroupsByName :
|
||||
groups.size();
|
||||
|
||||
boolean condition = (filterByNamePosition + numberOfGroupsByName < groups.size());
|
||||
int endPosition = condition ? filterByNamePosition + numberOfGroupsByName : groups.size();
|
||||
|
||||
return groups.subList(filterByNamePosition, endPosition);
|
||||
}
|
||||
|
||||
public void onSelectFilterByName(Combobox comboByName) {
|
||||
if (comboByName.getSelectedItemApi() == null) {
|
||||
if ( comboByName.getSelectedItemApi() == null ) {
|
||||
resetComboByName(comboByName);
|
||||
} else {
|
||||
Integer filterByNamePosition = (Integer) comboByName
|
||||
.getSelectedItemApi().getValue();
|
||||
if (paginationType != PaginationType.NONE) {
|
||||
this.filterByNamePosition = filterByNamePosition.intValue();
|
||||
Integer filterByNamePosition = (Integer) comboByName.getSelectedItemApi().getValue();
|
||||
|
||||
if ( paginationType != PaginationType.NONE ) {
|
||||
this.filterByNamePosition = filterByNamePosition;
|
||||
this.lastSelectedName = comboByName.getSelectedIndex();
|
||||
this.feedBackMessage = _("filtering by name");
|
||||
|
||||
changeNameFilterWithFeedback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetComboByName(Combobox comboByName) {
|
||||
if (this.lastSelectedName == -1) {
|
||||
if ( this.lastSelectedName == -1 ) {
|
||||
comboByName.setSelectedIndex(0);
|
||||
} else {
|
||||
comboByName.setSelectedIndex(this.lastSelectedName);
|
||||
|
|
@ -514,24 +519,26 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
}
|
||||
|
||||
private void changeNameFilterWithFeedback() {
|
||||
LongOperationFeedback.execute(componentOnWhichGiveFeedback,
|
||||
new ILongOperation() {
|
||||
|
||||
LongOperationFeedback.execute(componentOnWhichGiveFeedback, new ILongOperation() {
|
||||
@Override
|
||||
public void doAction() {
|
||||
if(paginationType == PaginationType.INTERNAL_PAGINATION) {
|
||||
if( paginationType == PaginationType.INTERNAL_PAGINATION ) {
|
||||
|
||||
//if the pagination is internal, we are in charge of repainting the graph
|
||||
treeModel = createModelForTree();
|
||||
|
||||
timeTrackerComponent = timeTrackerForResourcesLoadPanel(timeTracker);
|
||||
resourceLoadList = new ResourceLoadList(timeTracker, treeModel);
|
||||
leftPane = new ResourceLoadLeftPane(treeModel, resourceLoadList);
|
||||
}
|
||||
|
||||
nameFilterListener.fireEvent(new IListenerNotification<IPaginationFilterChangedListener>() {
|
||||
@Override
|
||||
public void doNotify(IPaginationFilterChangedListener listener) {
|
||||
listener.filterChanged(filterByNamePosition);
|
||||
}
|
||||
});
|
||||
|
||||
afterCompose();
|
||||
}
|
||||
|
||||
|
|
@ -544,36 +551,31 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
|
||||
public void setInternalPaginationDisabled(boolean disabled) {
|
||||
Combobox combo = ((Combobox) getFellow("filterByNameCombo"));
|
||||
if (combo != null && combo.isDisabled() != disabled) {
|
||||
filterByNamePosition = disabled? -1 :
|
||||
((Integer)combo.getSelectedItemApi().getValue()).intValue();
|
||||
if ( combo != null && combo.isDisabled() != disabled ) {
|
||||
filterByNamePosition = disabled? -1 : (Integer) combo.getSelectedItemApi().getValue();
|
||||
combo.setDisabled(disabled);
|
||||
}
|
||||
}
|
||||
|
||||
public void addPaginationFilterListener(
|
||||
IPaginationFilterChangedListener iFilterChangedListener) {
|
||||
public void addPaginationFilterListener(IPaginationFilterChangedListener iFilterChangedListener) {
|
||||
nameFilterListener.addListener(iFilterChangedListener);
|
||||
}
|
||||
|
||||
public void changeChartVisibility(boolean visible) {
|
||||
visibleChart = visible;
|
||||
chartVisibilityListeners
|
||||
.fireEvent(new IListenerNotification<IChartVisibilityChangedListener>() {
|
||||
@Override
|
||||
public void doNotify(
|
||||
IChartVisibilityChangedListener listener) {
|
||||
listener.chartVisibilityChanged(visibleChart);
|
||||
}
|
||||
});
|
||||
chartVisibilityListeners.fireEvent(new IListenerNotification<IChartVisibilityChangedListener>() {
|
||||
@Override
|
||||
public void doNotify(IChartVisibilityChangedListener listener) {
|
||||
listener.chartVisibilityChanged(visibleChart);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isVisibleChart() {
|
||||
return visibleChart;
|
||||
}
|
||||
|
||||
public void addChartVisibilityListener(
|
||||
IChartVisibilityChangedListener chartVisibilityChangedListener) {
|
||||
public void addChartVisibilityListener(IChartVisibilityChangedListener chartVisibilityChangedListener) {
|
||||
chartVisibilityListeners.addListener(chartVisibilityChangedListener);
|
||||
}
|
||||
|
||||
|
|
@ -586,9 +588,10 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
}
|
||||
|
||||
public Combobox getPaginationFilterCombobox() {
|
||||
if(paginationType == PaginationType.EXTERNAL_PAGINATION) {
|
||||
if( paginationType == PaginationType.EXTERNAL_PAGINATION ) {
|
||||
return (Combobox) getFellow("filterByNameCombo");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -606,7 +609,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
/**
|
||||
* Disables pagination. Shows all the LoadTimeLine objects received.
|
||||
*/
|
||||
NONE;
|
||||
NONE
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.zkoss.web.servlet.http.HttpServlet;
|
||||
|
||||
/**
|
||||
|
|
@ -49,20 +49,16 @@ public class CallbackServlet extends HttpServlet {
|
|||
|
||||
private static final String MAPPING = "/callback/";
|
||||
|
||||
private static final long CLEANING_PERIOD_MILLIS = 1000 * 60 * 1; // one
|
||||
// minute
|
||||
// minutes
|
||||
private static final long CLEANING_PERIOD_MILLIS = 1000 * 60; // one minute
|
||||
|
||||
private static Random random = new Random();
|
||||
|
||||
private static ConcurrentMap<String, IHandler> handlersCallbacks = new ConcurrentHashMap<String, IHandler>();
|
||||
private static ConcurrentMap<String, IHandler> handlersCallbacks = new ConcurrentHashMap<>();
|
||||
|
||||
private static Timer cleaningTimer = new Timer(true);
|
||||
|
||||
public interface IServletRequestHandler {
|
||||
public void handle(HttpServletRequest request,
|
||||
HttpServletResponse response) throws ServletException,
|
||||
IOException;
|
||||
void handle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
|
||||
}
|
||||
|
||||
public enum DisposalMode {
|
||||
|
|
@ -72,26 +68,24 @@ public class CallbackServlet extends HttpServlet {
|
|||
return new WeakReferencedHandler(handler);
|
||||
}
|
||||
},
|
||||
|
||||
AFTER_TEN_MINUTES {
|
||||
@Override
|
||||
public IHandler create(IServletRequestHandler handler) {
|
||||
return new BasedOnExpirationTimeHandler(handler,
|
||||
tenMinutesInMillis);
|
||||
return new BasedOnExpirationTimeHandler(handler, tenMinutesInMillis);
|
||||
}
|
||||
};
|
||||
|
||||
private static final long tenMinutesInMillis = TimeUnit.MILLISECONDS
|
||||
.convert(10, TimeUnit.MINUTES);
|
||||
private static final long tenMinutesInMillis = TimeUnit.MILLISECONDS.convert(10, TimeUnit.MINUTES);
|
||||
|
||||
public abstract IHandler create(
|
||||
IServletRequestHandler handler);
|
||||
public abstract IHandler create(IServletRequestHandler handler);
|
||||
}
|
||||
|
||||
private interface IHandler {
|
||||
|
||||
abstract boolean hasExpired();
|
||||
boolean hasExpired();
|
||||
|
||||
abstract IServletRequestHandler getHandler();
|
||||
IServletRequestHandler getHandler();
|
||||
}
|
||||
|
||||
private static class BasedOnExpirationTimeHandler implements IHandler {
|
||||
|
|
@ -101,9 +95,9 @@ public class CallbackServlet extends HttpServlet {
|
|||
private final long creationTime;
|
||||
private final long expirationTimeMilliseconds;
|
||||
|
||||
public BasedOnExpirationTimeHandler(IServletRequestHandler handler,
|
||||
long expirationTimeMilliseconds) {
|
||||
public BasedOnExpirationTimeHandler(IServletRequestHandler handler, long expirationTimeMilliseconds) {
|
||||
Validate.notNull(handler);
|
||||
|
||||
this.handler = handler;
|
||||
this.creationTime = System.currentTimeMillis();
|
||||
this.expirationTimeMilliseconds = expirationTimeMilliseconds;
|
||||
|
|
@ -125,7 +119,7 @@ public class CallbackServlet extends HttpServlet {
|
|||
private final WeakReference<IServletRequestHandler> handler;
|
||||
|
||||
WeakReferencedHandler(IServletRequestHandler handler) {
|
||||
this.handler = new WeakReference<IServletRequestHandler>(handler);
|
||||
this.handler = new WeakReference<>(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -140,40 +134,44 @@ public class CallbackServlet extends HttpServlet {
|
|||
|
||||
}
|
||||
|
||||
public static String registerAndCreateURLFor(HttpServletRequest request,
|
||||
IServletRequestHandler handler) {
|
||||
return registerAndCreateURLFor(request, handler,
|
||||
DisposalMode.AFTER_TEN_MINUTES);
|
||||
public static String registerAndCreateURLFor(HttpServletRequest request, IServletRequestHandler handler) {
|
||||
return registerAndCreateURLFor(request, handler, DisposalMode.AFTER_TEN_MINUTES);
|
||||
}
|
||||
|
||||
public static String registerAndCreateURLFor(HttpServletRequest request,
|
||||
IServletRequestHandler handler, DisposalMode disposalMode) {
|
||||
public static String registerAndCreateURLFor(HttpServletRequest request, IServletRequestHandler handler,
|
||||
DisposalMode disposalMode) {
|
||||
|
||||
return registerAndCreateURLFor(request, handler, true, disposalMode);
|
||||
}
|
||||
|
||||
public static String registerAndCreateURLFor(HttpServletRequest request,
|
||||
IServletRequestHandler handler, boolean withContextPath) {
|
||||
return registerAndCreateURLFor(request, handler, withContextPath,
|
||||
DisposalMode.AFTER_TEN_MINUTES);
|
||||
public static String registerAndCreateURLFor(HttpServletRequest request, IServletRequestHandler handler,
|
||||
boolean withContextPath) {
|
||||
|
||||
return registerAndCreateURLFor(request, handler, withContextPath, DisposalMode.AFTER_TEN_MINUTES);
|
||||
}
|
||||
|
||||
public static String registerAndCreateURLFor(HttpServletRequest request,
|
||||
IServletRequestHandler handler, boolean withContextPath,
|
||||
DisposalMode disposalMode) {
|
||||
IServletRequestHandler handler,
|
||||
boolean withContextPath,
|
||||
DisposalMode disposalMode) {
|
||||
Validate.notNull(disposalMode);
|
||||
|
||||
// theoretically could be an infinite loop, could be improved.
|
||||
String generatedKey = "";
|
||||
String generatedKey;
|
||||
|
||||
IHandler toBeRegistered = disposalMode.create(handler);
|
||||
do {
|
||||
generatedKey = generateKey();
|
||||
} while (handlersCallbacks.putIfAbsent(generatedKey, toBeRegistered) != null);
|
||||
|
||||
return buildURLFromKey(request, generatedKey, withContextPath);
|
||||
}
|
||||
|
||||
private static synchronized String buildURLFromKey(
|
||||
HttpServletRequest request, String generatedKey,
|
||||
boolean withContextPath) {
|
||||
private static synchronized String buildURLFromKey(HttpServletRequest request, String generatedKey,
|
||||
boolean withContextPath) {
|
||||
|
||||
String contextPath = withContextPath ? request.getContextPath() : "";
|
||||
|
||||
return contextPath + MAPPING + generatedKey;
|
||||
}
|
||||
|
||||
|
|
@ -182,9 +180,10 @@ public class CallbackServlet extends HttpServlet {
|
|||
}
|
||||
|
||||
private static String getId(String pathInfo) {
|
||||
if (pathInfo.startsWith("/")) {
|
||||
if ( pathInfo.startsWith("/") ) {
|
||||
return pathInfo.substring(1);
|
||||
}
|
||||
|
||||
return pathInfo;
|
||||
}
|
||||
|
||||
|
|
@ -199,14 +198,15 @@ public class CallbackServlet extends HttpServlet {
|
|||
}
|
||||
|
||||
private static List<String> findExpired() {
|
||||
ArrayList<Entry<String, IHandler>> handlersList = new ArrayList<Entry<String, IHandler>>(
|
||||
handlersCallbacks.entrySet());
|
||||
List<String> expired = new ArrayList<String>();
|
||||
ArrayList<Entry<String, IHandler>> handlersList = new ArrayList<>(handlersCallbacks.entrySet());
|
||||
List<String> expired = new ArrayList<>();
|
||||
|
||||
for (Entry<String, IHandler> entry : handlersList) {
|
||||
if (entry.getValue().hasExpired()) {
|
||||
if ( entry.getValue().hasExpired() ) {
|
||||
expired.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
return expired;
|
||||
}
|
||||
|
||||
|
|
@ -217,8 +217,7 @@ public class CallbackServlet extends HttpServlet {
|
|||
}
|
||||
|
||||
private void scheduleTimer() {
|
||||
cleaningTimer.schedule(cleaningTask(), CLEANING_PERIOD_MILLIS,
|
||||
CLEANING_PERIOD_MILLIS);
|
||||
cleaningTimer.schedule(cleaningTask(), CLEANING_PERIOD_MILLIS, CLEANING_PERIOD_MILLIS);
|
||||
}
|
||||
|
||||
private TimerTask cleaningTask() {
|
||||
|
|
@ -231,11 +230,11 @@ public class CallbackServlet extends HttpServlet {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String callbackId = getId(req.getPathInfo());
|
||||
IServletRequestHandler handler = handlerFor(callbackId);
|
||||
if (handler == null) {
|
||||
|
||||
if ( handler == null ) {
|
||||
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
} else {
|
||||
handler.handle(req, resp);
|
||||
|
|
@ -244,6 +243,7 @@ public class CallbackServlet extends HttpServlet {
|
|||
|
||||
private IServletRequestHandler handlerFor(String callbackId) {
|
||||
IHandler h = handlersCallbacks.get(callbackId);
|
||||
|
||||
return h != null ? h.getHandler() : null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,32 +27,36 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zul.Row;
|
||||
import org.zkoss.zul.RowRenderer;
|
||||
|
||||
public class OnColumnsRowRenderer<C, T> implements RowRenderer {
|
||||
|
||||
public static <C, T> OnColumnsRowRenderer<C, T> create(
|
||||
ICellForDetailItemRenderer<C, T> cellRenderer, Collection<C> columns) {
|
||||
public static <C, T> OnColumnsRowRenderer<C, T> create(ICellForDetailItemRenderer<C, T> cellRenderer,
|
||||
Collection<C> columns) {
|
||||
|
||||
return create(inferGenericType(cellRenderer), cellRenderer, columns);
|
||||
}
|
||||
|
||||
public static <C, T> OnColumnsRowRenderer<C, T> create(Class<T> type,
|
||||
ICellForDetailItemRenderer<C, T> cellRenderer, Collection<C> columns) {
|
||||
return new OnColumnsRowRenderer<C, T>(type, cellRenderer, columns);
|
||||
ICellForDetailItemRenderer<C, T> cellRenderer,
|
||||
Collection<C> columns) {
|
||||
|
||||
return new OnColumnsRowRenderer<>(type, cellRenderer, columns);
|
||||
}
|
||||
|
||||
private static <T> Class<T> inferGenericType(
|
||||
ICellForDetailItemRenderer<?, T> renderer) {
|
||||
private static <T> Class<T> inferGenericType(ICellForDetailItemRenderer<?, T> renderer) {
|
||||
ParameterizedType parametrizedType = findRenderererInterfaceType(renderer);
|
||||
Type[] actualTypeArguments = parametrizedType.getActualTypeArguments();
|
||||
final int genericTypePosition = 1;
|
||||
Type type = actualTypeArguments[genericTypePosition];
|
||||
if (!isActualType(type)) {
|
||||
|
||||
if ( !isActualType(type) ) {
|
||||
informCannotBeInferred(renderer);
|
||||
}
|
||||
|
||||
return (Class<T>) actualTypeArguments[genericTypePosition];
|
||||
}
|
||||
|
||||
|
|
@ -60,39 +64,41 @@ public class OnColumnsRowRenderer<C, T> implements RowRenderer {
|
|||
return t instanceof Class;
|
||||
}
|
||||
|
||||
private static ParameterizedType findRenderererInterfaceType(
|
||||
ICellForDetailItemRenderer<?, ?> renderer) {
|
||||
private static ParameterizedType findRenderererInterfaceType(ICellForDetailItemRenderer<?, ?> renderer) {
|
||||
Type[] genericInterfaces = renderer.getClass().getGenericInterfaces();
|
||||
|
||||
for (Type type : genericInterfaces) {
|
||||
if (isTypeForInterface(type, ICellForDetailItemRenderer.class)) {
|
||||
if (type instanceof ParameterizedType) {
|
||||
|
||||
if ( isTypeForInterface(type, ICellForDetailItemRenderer.class) ) {
|
||||
|
||||
if ( type instanceof ParameterizedType ) {
|
||||
return (ParameterizedType) type;
|
||||
} else {
|
||||
informCannotBeInferred(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("shouldn't reach here. Uncovered case for "
|
||||
+ renderer);
|
||||
|
||||
throw new RuntimeException("shouldn't reach here. Uncovered case for " + renderer);
|
||||
}
|
||||
|
||||
private static boolean isTypeForInterface(Type type,
|
||||
Class<?> interfaceBeingSearched) {
|
||||
if (type instanceof ParameterizedType) {
|
||||
private static boolean isTypeForInterface(Type type, Class<?> interfaceBeingSearched) {
|
||||
if ( type instanceof ParameterizedType ) {
|
||||
ParameterizedType p = (ParameterizedType) type;
|
||||
Type rawType = p.getRawType();
|
||||
|
||||
return rawType.equals(interfaceBeingSearched);
|
||||
}
|
||||
|
||||
return type.equals(interfaceBeingSearched);
|
||||
}
|
||||
|
||||
private static void informCannotBeInferred(
|
||||
ICellForDetailItemRenderer<?, ?> renderer) {
|
||||
private static void informCannotBeInferred(ICellForDetailItemRenderer<?, ?> renderer) {
|
||||
throw new IllegalArgumentException(
|
||||
"the generic type cannot be inferred "
|
||||
+ "if actual type parameters are not declared "
|
||||
+ "or implements the raw interface: "
|
||||
+ renderer.getClass().getName());
|
||||
"the generic type cannot be inferred " +
|
||||
"if actual type parameters are not declared " +
|
||||
"or implements the raw interface: " +
|
||||
renderer.getClass().getName());
|
||||
}
|
||||
|
||||
private final List<C> columns;
|
||||
|
|
@ -100,22 +106,24 @@ public class OnColumnsRowRenderer<C, T> implements RowRenderer {
|
|||
private Class<T> type;
|
||||
|
||||
private OnColumnsRowRenderer(Class<T> type,
|
||||
ICellForDetailItemRenderer<C, T> cellRenderer, Collection<C> columns) {
|
||||
ICellForDetailItemRenderer<C, T> cellRenderer,
|
||||
Collection<C> columns) {
|
||||
Validate.notNull(type);
|
||||
Validate.notNull(columns);
|
||||
Validate.notNull(cellRenderer);
|
||||
Validate.noNullElements(columns);
|
||||
|
||||
this.cellRenderer = cellRenderer;
|
||||
this.columns = new ArrayList<C>(columns);
|
||||
this.columns = new ArrayList<>(columns);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Row row, Object data) {
|
||||
if (!type.isInstance(data)) {
|
||||
throw new IllegalArgumentException(data + " is not instance of "
|
||||
+ type);
|
||||
if ( !type.isInstance(data) ) {
|
||||
throw new IllegalArgumentException(data + " is not instance of " + type);
|
||||
}
|
||||
|
||||
for (C item : columns) {
|
||||
Component child = cellRenderer.cellFor(item, type.cast(data));
|
||||
child.setParent(row);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import java.beans.PropertyChangeListener;
|
|||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.zkoss.ganttz.DatesMapperOnInterval;
|
||||
import org.zkoss.ganttz.IDatesMapper;
|
||||
|
|
@ -50,22 +50,19 @@ public class TimeTracker {
|
|||
|
||||
public interface IDetailItemFilter {
|
||||
|
||||
public Collection<DetailItem> selectsFirstLevel(
|
||||
Collection<DetailItem> firstLevelDetails);
|
||||
Collection<DetailItem> selectsFirstLevel(Collection<DetailItem> firstLevelDetails);
|
||||
|
||||
public Collection<DetailItem> selectsSecondLevel(
|
||||
Collection<DetailItem> secondLevelDetails);
|
||||
Collection<DetailItem> selectsSecondLevel(Collection<DetailItem> secondLevelDetails);
|
||||
|
||||
public Interval getCurrentPaginationInterval();
|
||||
Interval getCurrentPaginationInterval();
|
||||
|
||||
public void resetInterval();
|
||||
void resetInterval();
|
||||
|
||||
}
|
||||
|
||||
private ZoomLevel detailLevel = ZoomLevel.DETAIL_ONE;
|
||||
|
||||
private WeakReferencedListeners<IZoomLevelChangedListener> zoomListeners = WeakReferencedListeners
|
||||
.create();
|
||||
private WeakReferencedListeners<IZoomLevelChangedListener> zoomListeners = WeakReferencedListeners.create();
|
||||
|
||||
private IDatesMapper datesMapper = null;
|
||||
|
||||
|
|
@ -90,35 +87,38 @@ public class TimeTracker {
|
|||
}
|
||||
|
||||
public TimeTracker(Interval interval, ZoomLevel zoomLevel, Component parent) {
|
||||
this(interval, zoomLevel, SeveralModificators.empty(),
|
||||
SeveralModificators.empty(), parent);
|
||||
this(interval, zoomLevel, SeveralModificators.empty(), SeveralModificators.empty(), parent);
|
||||
}
|
||||
|
||||
public TimeTracker(Interval interval, Component componentOnWhichGiveFeedback) {
|
||||
this(interval, SeveralModificators.empty(),
|
||||
SeveralModificators.empty(), componentOnWhichGiveFeedback);
|
||||
this(interval, SeveralModificators.empty(), SeveralModificators.empty(), componentOnWhichGiveFeedback);
|
||||
}
|
||||
|
||||
public TimeTracker(Interval interval,
|
||||
public TimeTracker(
|
||||
Interval interval,
|
||||
IDetailItemModificator firstLevelModificator,
|
||||
IDetailItemModificator secondLevelModificator,
|
||||
Component componentOnWhichGiveFeedback) {
|
||||
|
||||
Validate.notNull(interval);
|
||||
Validate.notNull(firstLevelModificator);
|
||||
Validate.notNull(secondLevelModificator);
|
||||
Validate.notNull(componentOnWhichGiveFeedback);
|
||||
|
||||
this.interval = interval;
|
||||
this.firstLevelModificator = firstLevelModificator;
|
||||
this.secondLevelModificator = secondLevelModificator;
|
||||
this.componentOnWhichGiveFeedback = componentOnWhichGiveFeedback;
|
||||
}
|
||||
|
||||
public TimeTracker(Interval interval, ZoomLevel zoomLevel,
|
||||
public TimeTracker(
|
||||
Interval interval,
|
||||
ZoomLevel zoomLevel,
|
||||
IDetailItemModificator firstLevelModificator,
|
||||
IDetailItemModificator secondLevelModificator,
|
||||
Component componentOnWhichGiveFeedback) {
|
||||
this(interval, firstLevelModificator, secondLevelModificator,
|
||||
componentOnWhichGiveFeedback);
|
||||
|
||||
this(interval, firstLevelModificator, secondLevelModificator, componentOnWhichGiveFeedback);
|
||||
detailLevel = zoomLevel;
|
||||
}
|
||||
|
||||
|
|
@ -136,60 +136,58 @@ public class TimeTracker {
|
|||
}
|
||||
|
||||
public Collection<DetailItem> getDetailsFirstLevel() {
|
||||
if (detailsFirstLevelCached == null) {
|
||||
detailsFirstLevelCached = getTimeTrackerState()
|
||||
.getFirstLevelDetails(interval);
|
||||
if ( detailsFirstLevelCached == null ) {
|
||||
detailsFirstLevelCached = getTimeTrackerState().getFirstLevelDetails(interval);
|
||||
}
|
||||
|
||||
return filterFirstLevel(detailsFirstLevelCached);
|
||||
}
|
||||
|
||||
private Collection<DetailItem> filterFirstLevel(
|
||||
Collection<DetailItem> firstLevelDetails) {
|
||||
if (filter == null) {
|
||||
private Collection<DetailItem> filterFirstLevel(Collection<DetailItem> firstLevelDetails) {
|
||||
if ( filter == null ) {
|
||||
return firstLevelDetails;
|
||||
}
|
||||
|
||||
return filter.selectsFirstLevel(firstLevelDetails);
|
||||
}
|
||||
|
||||
public Collection<DetailItem> getDetailsSecondLevel() {
|
||||
if (detailsSecondLevelCached == null) {
|
||||
detailsSecondLevelCached = getTimeTrackerState()
|
||||
.getSecondLevelDetails(interval);
|
||||
if ( detailsSecondLevelCached == null ) {
|
||||
detailsSecondLevelCached = getTimeTrackerState().getSecondLevelDetails(interval);
|
||||
}
|
||||
|
||||
return filterSecondLevel(detailsSecondLevelCached);
|
||||
}
|
||||
|
||||
private Collection<DetailItem> filterSecondLevel(
|
||||
Collection<DetailItem> secondLevelDetails) {
|
||||
if (filter == null) {
|
||||
private Collection<DetailItem> filterSecondLevel(Collection<DetailItem> secondLevelDetails) {
|
||||
if ( filter == null ) {
|
||||
return secondLevelDetails;
|
||||
}
|
||||
|
||||
return filter.selectsSecondLevel(secondLevelDetails);
|
||||
}
|
||||
|
||||
private Interval realIntervalCached;
|
||||
|
||||
public Interval getRealInterval() {
|
||||
if (realIntervalCached == null) {
|
||||
realIntervalCached = getTimeTrackerState().getRealIntervalFor(
|
||||
interval);
|
||||
if ( realIntervalCached == null ) {
|
||||
realIntervalCached = getTimeTrackerState().getRealIntervalFor(interval);
|
||||
}
|
||||
|
||||
return realIntervalCached;
|
||||
}
|
||||
|
||||
public TimeTrackerState getTimeTrackerState() {
|
||||
return detailLevel.getTimeTrackerState(firstLevelModificator,
|
||||
secondLevelModificator);
|
||||
return detailLevel.getTimeTrackerState(firstLevelModificator, secondLevelModificator);
|
||||
}
|
||||
|
||||
private void fireZoomChanged() {
|
||||
zoomListeners
|
||||
.fireEvent(new IListenerNotification<IZoomLevelChangedListener>() {
|
||||
@Override
|
||||
public void doNotify(IZoomLevelChangedListener listener) {
|
||||
listener.zoomLevelChanged(detailLevel);
|
||||
}
|
||||
});
|
||||
zoomListeners.fireEvent(new IListenerNotification<IZoomLevelChangedListener>() {
|
||||
@Override
|
||||
public void doNotify(IZoomLevelChangedListener listener) {
|
||||
listener.zoomLevelChanged(detailLevel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public int getHorizontalSize() {
|
||||
|
|
@ -197,6 +195,7 @@ public class TimeTracker {
|
|||
for (DetailItem detailItem : getDetailsSecondLevel()) {
|
||||
horizontalSize += detailItem.getSize();
|
||||
}
|
||||
|
||||
return horizontalSize;
|
||||
}
|
||||
|
||||
|
|
@ -212,15 +211,14 @@ public class TimeTracker {
|
|||
}
|
||||
|
||||
public IDatesMapper getMapper() {
|
||||
if (datesMapper == null) {
|
||||
if (filter == null) {
|
||||
datesMapper = new DatesMapperOnInterval(getHorizontalSize(),
|
||||
getRealInterval());
|
||||
if ( datesMapper == null ) {
|
||||
if ( filter == null ) {
|
||||
datesMapper = new DatesMapperOnInterval(getHorizontalSize(), getRealInterval());
|
||||
} else {
|
||||
datesMapper = new DatesMapperOnInterval(getHorizontalSize(),
|
||||
filter.getCurrentPaginationInterval());
|
||||
datesMapper = new DatesMapperOnInterval(getHorizontalSize(), filter.getCurrentPaginationInterval());
|
||||
}
|
||||
}
|
||||
|
||||
return datesMapper;
|
||||
}
|
||||
|
||||
|
|
@ -230,19 +228,17 @@ public class TimeTracker {
|
|||
}
|
||||
|
||||
private void invalidatingChangeHappenedWithFeedback() {
|
||||
LongOperationFeedback.execute(componentOnWhichGiveFeedback,
|
||||
new ILongOperation() {
|
||||
LongOperationFeedback.execute(componentOnWhichGiveFeedback, new ILongOperation() {
|
||||
@Override
|
||||
public void doAction() {
|
||||
invalidatingChangeHappened();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAction() {
|
||||
invalidatingChangeHappened();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return _("changing zoom");
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public String getName() {
|
||||
return _("changing zoom");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setZoomLevel(ZoomLevel zoomLevel) {
|
||||
|
|
@ -261,40 +257,38 @@ public class TimeTracker {
|
|||
}
|
||||
|
||||
public void trackPosition(final Task task) {
|
||||
task
|
||||
.addFundamentalPropertiesChangeListener(new PropertyChangeListener() {
|
||||
task.addFundamentalPropertiesChangeListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
updateIntervalIfNeeded(task);
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
updateIntervalIfNeeded(task);
|
||||
}
|
||||
});
|
||||
updateIntervalIfNeeded(task);
|
||||
}
|
||||
|
||||
private void updateIntervalIfNeeded(Task task) {
|
||||
if (registeredFirstTask == false) {
|
||||
if ( !registeredFirstTask ) {
|
||||
registeredFirstTask = true;
|
||||
interval = new Interval(startMinusTwoWeeks(task),
|
||||
endPlusOneMonth(task));
|
||||
interval = new Interval(startMinusTwoWeeks(task), endPlusOneMonth(task));
|
||||
invalidatingChangeHappened();
|
||||
} else {
|
||||
LocalDate newStart = interval.getStart();
|
||||
LocalDate newFinish = interval.getFinish();
|
||||
|
||||
boolean changed = false;
|
||||
if (interval.getStart().compareTo(startMinusTwoWeeks(task)) > 0) {
|
||||
|
||||
if ( interval.getStart().compareTo(startMinusTwoWeeks(task) ) > 0) {
|
||||
newStart = startMinusTwoWeeks(task);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (interval.getFinish()
|
||||
.compareTo(endPlusOneMonth(task)) < 0) {
|
||||
if ( interval.getFinish().compareTo(endPlusOneMonth(task)) < 0 ) {
|
||||
newFinish = endPlusOneMonth(task);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
if ( changed ) {
|
||||
interval = new Interval(newStart, newFinish);
|
||||
invalidatingChangeHappened();
|
||||
}
|
||||
|
|
@ -302,39 +296,43 @@ public class TimeTracker {
|
|||
}
|
||||
|
||||
private Date max(Date date1, Date date2) {
|
||||
if (date1 == null) {
|
||||
if ( date1 == null ) {
|
||||
return date2;
|
||||
}
|
||||
if (date2 == null) {
|
||||
if ( date2 == null ) {
|
||||
return date1;
|
||||
}
|
||||
|
||||
return date1.compareTo(date2) > 0 ? date1 : date2;
|
||||
}
|
||||
|
||||
private Date min(Date date1, Date date2) {
|
||||
if (date1 == null) {
|
||||
if ( date1 == null ) {
|
||||
return date2;
|
||||
}
|
||||
if (date2 == null) {
|
||||
|
||||
if ( date2 == null ) {
|
||||
return date1;
|
||||
}
|
||||
|
||||
return date1.compareTo(date2) <= 0 ? date1 : date2;
|
||||
}
|
||||
|
||||
private LocalDate endPlusOneMonth(Task task) {
|
||||
Date taskEnd = max(task.getEndDate().toDayRoundedDate(),
|
||||
task.getDeadline());
|
||||
Date taskEnd = max(task.getEndDate().toDayRoundedDate(), task.getDeadline());
|
||||
|
||||
return new LocalDate(taskEnd).plusMonths(1);
|
||||
}
|
||||
|
||||
private LocalDate startMinusTwoWeeks(Task task) {
|
||||
// the deadline could be before the start
|
||||
Date start = min(task.getBeginDate().toDayRoundedDate(),
|
||||
task.getDeadline());
|
||||
Date start = min(task.getBeginDate().toDayRoundedDate(), task.getDeadline());
|
||||
|
||||
// the last consolidated value could be before the start
|
||||
if (task.getConsolidatedline() != null) {
|
||||
if ( task.getConsolidatedline() != null ) {
|
||||
start = min(start, task.getConsolidatedline().toDayRoundedDate());
|
||||
}
|
||||
|
||||
return new LocalDate(start).minusWeeks(2);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
/**
|
||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
|
|
@ -35,26 +35,22 @@ import org.apache.commons.lang.Validate;
|
|||
public class SeveralModificators implements IDetailItemModificator {
|
||||
|
||||
public static IDetailItemModificator empty() {
|
||||
return new SeveralModificators(Collections
|
||||
.<IDetailItemModificator> emptyList());
|
||||
return new SeveralModificators(Collections.<IDetailItemModificator> emptyList());
|
||||
}
|
||||
|
||||
public static IDetailItemModificator create(
|
||||
IDetailItemModificator... modificators) {
|
||||
public static IDetailItemModificator create(IDetailItemModificator... modificators) {
|
||||
return new SeveralModificators(Arrays.asList(modificators));
|
||||
}
|
||||
|
||||
public static IDetailItemModificator create(
|
||||
Collection<? extends IDetailItemModificator> modificators) {
|
||||
public static IDetailItemModificator create(Collection<? extends IDetailItemModificator> modificators) {
|
||||
return new SeveralModificators(modificators);
|
||||
}
|
||||
|
||||
private final List<IDetailItemModificator> modificators;
|
||||
|
||||
private SeveralModificators(
|
||||
Collection<? extends IDetailItemModificator> modificators) {
|
||||
private SeveralModificators(Collection<? extends IDetailItemModificator> modificators) {
|
||||
Validate.noNullElements(modificators);
|
||||
this.modificators = new ArrayList<IDetailItemModificator>(modificators);
|
||||
this.modificators = new ArrayList<>(modificators);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -63,6 +59,7 @@ public class SeveralModificators implements IDetailItemModificator {
|
|||
for (IDetailItemModificator each : modificators) {
|
||||
result = each.applyModificationsTo(result, z);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ package org.zkoss.ganttz.timetracker.zoom;
|
|||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.ReadablePeriod;
|
||||
|
||||
|
|
@ -30,16 +30,17 @@ import org.joda.time.ReadablePeriod;
|
|||
* @author Óscar González Fernández
|
||||
*
|
||||
*/
|
||||
public abstract class TimeTrackerStateWithSubintervalsFitting extends
|
||||
TimeTrackerState {
|
||||
public abstract class TimeTrackerStateWithSubintervalsFitting extends TimeTrackerState {
|
||||
|
||||
protected TimeTrackerStateWithSubintervalsFitting(
|
||||
IDetailItemModificator firstLevelModificator,
|
||||
IDetailItemModificator secondLevelModificator) {
|
||||
|
||||
super(firstLevelModificator, secondLevelModificator);
|
||||
}
|
||||
|
||||
private final class PeriodicalGenerator extends LazyGenerator<LocalDate> {
|
||||
|
||||
private final ReadablePeriod period;
|
||||
|
||||
private PeriodicalGenerator(LocalDate first, ReadablePeriod period) {
|
||||
|
|
@ -55,8 +56,7 @@ public abstract class TimeTrackerStateWithSubintervalsFitting extends
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<LocalDate> getPeriodsFirstLevelGenerator(
|
||||
final LocalDate start) {
|
||||
protected Iterator<LocalDate> getPeriodsFirstLevelGenerator(final LocalDate start) {
|
||||
return new PeriodicalGenerator(start, getPeriodFirstLevel());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.zkoss.ganttz.util;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
|
@ -29,8 +26,8 @@ import static java.util.Arrays.asList;
|
|||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang.math.Fraction;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.math.Fraction;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Days;
|
||||
import org.joda.time.Duration;
|
||||
|
|
@ -54,13 +51,15 @@ public class Interval {
|
|||
Validate.notNull(startInclusive);
|
||||
Validate.notNull(endExclusive);
|
||||
Validate.isTrue(endExclusive.isAfter(startInclusive));
|
||||
|
||||
this.startInclusive = startInclusive;
|
||||
this.endExclusive = endExclusive;
|
||||
|
||||
this.lengthBetween = new Duration(
|
||||
this.startInclusive.toDateTimeAtStartOfDay(),
|
||||
this.endExclusive.toDateTimeAtStartOfDay());
|
||||
this.daysBetween = Days.daysBetween(this.startInclusive,
|
||||
this.endExclusive);
|
||||
|
||||
this.daysBetween = Days.daysBetween(this.startInclusive, this.endExclusive);
|
||||
}
|
||||
|
||||
public Days getDaysBetween() {
|
||||
|
|
@ -80,10 +79,9 @@ public class Interval {
|
|||
}
|
||||
|
||||
public Fraction getProportion(DateTime date) {
|
||||
Days fromStartToDate = Days.daysBetween(startInclusive,
|
||||
date.toLocalDate());
|
||||
Fraction result = Fraction.getFraction(fromStartToDate.getDays(),
|
||||
this.daysBetween.getDays());
|
||||
Days fromStartToDate = Days.daysBetween(startInclusive, date.toLocalDate());
|
||||
Fraction result = Fraction.getFraction(fromStartToDate.getDays(), this.daysBetween.getDays());
|
||||
|
||||
try {
|
||||
return result.add(inTheDayIncrement(date));
|
||||
} catch (ArithmeticException e) {
|
||||
|
|
@ -94,18 +92,17 @@ public class Interval {
|
|||
private Fraction inTheDayIncrement(DateTime date) {
|
||||
DateTime atStartOfDay = date.toLocalDate().toDateTimeAtStartOfDay();
|
||||
Duration duration = new Duration(atStartOfDay, date);
|
||||
double result = ((double) duration.getMillis())
|
||||
/ lengthBetween.getMillis();
|
||||
double result = ((double) duration.getMillis()) / lengthBetween.getMillis();
|
||||
|
||||
return Fraction.getFraction(result);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Interval coalesce(Interval otherInterval) {
|
||||
Validate.notNull(otherInterval);
|
||||
LocalDate minStart = Collections.min(asList(startInclusive,
|
||||
otherInterval.startInclusive));
|
||||
LocalDate maxEnd = Collections.max(asList(endExclusive,
|
||||
otherInterval.endExclusive));
|
||||
LocalDate minStart = Collections.min(asList(startInclusive, otherInterval.startInclusive));
|
||||
LocalDate maxEnd = Collections.max(asList(endExclusive, otherInterval.endExclusive));
|
||||
|
||||
return new Interval(minStart, maxEnd);
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ import java.util.concurrent.Executors;
|
|||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
|
|
@ -46,8 +46,7 @@ import org.zkoss.zk.ui.util.Clients;
|
|||
*/
|
||||
public class LongOperationFeedback {
|
||||
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(LongOperationFeedback.class);
|
||||
private static final Log LOG = LogFactory.getLog(LongOperationFeedback.class);
|
||||
|
||||
public interface ILongOperation {
|
||||
void doAction() throws Exception;
|
||||
|
|
@ -62,12 +61,11 @@ public class LongOperationFeedback {
|
|||
}
|
||||
};
|
||||
|
||||
public static void execute(final Component component,
|
||||
final ILongOperation longOperation) {
|
||||
public static void execute(final Component component, final ILongOperation longOperation) {
|
||||
Validate.notNull(component);
|
||||
Validate.notNull(longOperation);
|
||||
|
||||
if (alreadyInside.get()) {
|
||||
if ( alreadyInside.get() ) {
|
||||
dispatchActionDirectly(longOperation);
|
||||
return;
|
||||
}
|
||||
|
|
@ -88,10 +86,10 @@ public class LongOperationFeedback {
|
|||
});
|
||||
}
|
||||
|
||||
public static void executeLater(final Component component,
|
||||
final Runnable runnable) {
|
||||
public static void executeLater(final Component component, final Runnable runnable) {
|
||||
Validate.notNull(runnable);
|
||||
Validate.notNull(component);
|
||||
|
||||
final String eventName = generateEventName();
|
||||
component.addEventListener(eventName, new EventListener() {
|
||||
|
||||
|
|
@ -105,11 +103,11 @@ public class LongOperationFeedback {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
Events.echoEvent(eventName, component, null);
|
||||
}
|
||||
|
||||
private static void dispatchActionDirectly(
|
||||
final ILongOperation longOperation) {
|
||||
private static void dispatchActionDirectly(final ILongOperation longOperation) {
|
||||
try {
|
||||
longOperation.doAction();
|
||||
} catch (Exception e) {
|
||||
|
|
@ -125,11 +123,11 @@ public class LongOperationFeedback {
|
|||
}
|
||||
|
||||
public interface IDesktopUpdatesEmitter<T> {
|
||||
public void doUpdate(T value);
|
||||
void doUpdate(T value);
|
||||
}
|
||||
|
||||
public interface IDesktopUpdate {
|
||||
public void doUpdate();
|
||||
void doUpdate();
|
||||
}
|
||||
|
||||
public static IDesktopUpdate and(final IDesktopUpdate... desktopUpdates) {
|
||||
|
|
@ -145,11 +143,10 @@ public class LongOperationFeedback {
|
|||
}
|
||||
|
||||
public interface IBackGroundOperation<T> {
|
||||
public void doOperation(IDesktopUpdatesEmitter<T> desktopUpdateEmitter);
|
||||
void doOperation(IDesktopUpdatesEmitter<T> desktopUpdateEmitter);
|
||||
}
|
||||
|
||||
private static final ExecutorService executor = Executors
|
||||
.newCachedThreadPool();
|
||||
private static final ExecutorService executor = Executors.newCachedThreadPool();
|
||||
|
||||
public static <T> IDesktopUpdatesEmitter<T> doNothingEmitter() {
|
||||
return new IDesktopUpdatesEmitter<T>() {
|
||||
|
|
@ -164,16 +161,13 @@ public class LongOperationFeedback {
|
|||
* {@link IDesktopUpdate} objects that can update desktop state. Trying to
|
||||
* update the components in any other way would fail
|
||||
*/
|
||||
public static void progressive(final Desktop desktop,
|
||||
final IBackGroundOperation<IDesktopUpdate> operation) {
|
||||
progressive(desktop, operation,
|
||||
new IDesktopUpdatesEmitter<IDesktopUpdate>() {
|
||||
|
||||
@Override
|
||||
public void doUpdate(IDesktopUpdate update) {
|
||||
update.doUpdate();
|
||||
}
|
||||
});
|
||||
public static void progressive(final Desktop desktop, final IBackGroundOperation<IDesktopUpdate> operation) {
|
||||
progressive(desktop, operation, new IDesktopUpdatesEmitter<IDesktopUpdate>() {
|
||||
@Override
|
||||
public void doUpdate(IDesktopUpdate update) {
|
||||
update.doUpdate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -182,15 +176,17 @@ public class LongOperationFeedback {
|
|||
* {@link IDesktopUpdatesEmitter} that handle these objects is necessary.
|
||||
* Trying to update the components in any other way would fail.
|
||||
*/
|
||||
public static <T> void progressive(final Desktop desktop,
|
||||
public static <T> void progressive(
|
||||
final Desktop desktop,
|
||||
final IBackGroundOperation<T> operation,
|
||||
final IDesktopUpdatesEmitter<T> emitter) {
|
||||
|
||||
desktop.enableServerPush(true);
|
||||
executor.execute(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
IBackGroundOperation<T> operationWithAsyncUpates = withAsyncUpates(
|
||||
operation, desktop);
|
||||
IBackGroundOperation<T> operationWithAsyncUpates = withAsyncUpates(operation, desktop);
|
||||
operationWithAsyncUpates.doOperation(emitter);
|
||||
} catch (Exception e) {
|
||||
LOG.error("error executing background operation", e);
|
||||
|
|
@ -204,14 +200,16 @@ public class LongOperationFeedback {
|
|||
private static <T> IBackGroundOperation<T> withAsyncUpates(
|
||||
final IBackGroundOperation<T> backgroundOperation,
|
||||
final Desktop desktop) {
|
||||
return new IBackGroundOperation<T>() {
|
||||
|
||||
return new IBackGroundOperation<T>() {
|
||||
@Override
|
||||
public void doOperation(
|
||||
IDesktopUpdatesEmitter<T> originalEmitter) {
|
||||
NotBlockingDesktopUpdates<T> notBlockingDesktopUpdates = new NotBlockingDesktopUpdates<T>(
|
||||
desktop, originalEmitter);
|
||||
public void doOperation(IDesktopUpdatesEmitter<T> originalEmitter) {
|
||||
|
||||
NotBlockingDesktopUpdates<T> notBlockingDesktopUpdates =
|
||||
new NotBlockingDesktopUpdates<T>(desktop, originalEmitter);
|
||||
|
||||
Future<?> future = executor.submit(notBlockingDesktopUpdates);
|
||||
|
||||
try {
|
||||
backgroundOperation.doOperation(notBlockingDesktopUpdates);
|
||||
} finally {
|
||||
|
|
@ -230,15 +228,13 @@ public class LongOperationFeedback {
|
|||
};
|
||||
}
|
||||
|
||||
private static class NotBlockingDesktopUpdates<T> implements
|
||||
IDesktopUpdatesEmitter<T>, Runnable {
|
||||
private static class NotBlockingDesktopUpdates<T> implements IDesktopUpdatesEmitter<T>, Runnable {
|
||||
|
||||
private BlockingQueue<EndOrValue<T>> queue = new LinkedBlockingQueue<EndOrValue<T>>();
|
||||
private BlockingQueue<EndOrValue<T>> queue = new LinkedBlockingQueue<>();
|
||||
private final IDesktopUpdatesEmitter<T> original;
|
||||
private final Desktop desktop;
|
||||
|
||||
NotBlockingDesktopUpdates(Desktop desktop,
|
||||
IDesktopUpdatesEmitter<T> original) {
|
||||
NotBlockingDesktopUpdates(Desktop desktop, IDesktopUpdatesEmitter<T> original) {
|
||||
this.original = original;
|
||||
this.desktop = desktop;
|
||||
}
|
||||
|
|
@ -254,40 +250,48 @@ public class LongOperationFeedback {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
List<T> batch = new ArrayList<T>();
|
||||
List<T> batch = new ArrayList<>();
|
||||
|
||||
while (true) {
|
||||
batch.clear();
|
||||
EndOrValue<T> current = null;
|
||||
EndOrValue<T> current;
|
||||
|
||||
try {
|
||||
current = queue.take();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (current.isEnd()) {
|
||||
|
||||
if ( current.isEnd() ) {
|
||||
return;
|
||||
}
|
||||
if (!desktop.isAlive() || !desktop.isServerPushEnabled()) {
|
||||
|
||||
if ( !desktop.isAlive() || !desktop.isServerPushEnabled() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Executions.activate(desktop);
|
||||
} catch (Exception e) {
|
||||
LOG.error("unable to access desktop", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
original.doUpdate(current.getValue());
|
||||
while ((current = queue.poll()) != null) {
|
||||
if (current.isEnd()) {
|
||||
|
||||
if ( current.isEnd() ) {
|
||||
break;
|
||||
}
|
||||
|
||||
batch.add(current.getValue());
|
||||
original.doUpdate(current.getValue());
|
||||
}
|
||||
} finally {
|
||||
Executions.deactivate(desktop);
|
||||
}
|
||||
if (current != null && current.isEnd()) {
|
||||
if ( current != null && current.isEnd() ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -297,11 +301,11 @@ public class LongOperationFeedback {
|
|||
|
||||
private static abstract class EndOrValue<T> {
|
||||
public static <T> EndOrValue<T> end() {
|
||||
return new End<T>();
|
||||
return new End<>();
|
||||
}
|
||||
|
||||
public static <T> EndOrValue<T> value(T value) {
|
||||
return new Value<T>(value);
|
||||
return new Value<>(value);
|
||||
}
|
||||
|
||||
public abstract boolean isEnd();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
package org.zkoss.ganttz.util;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.zkoss.zk.ui.Desktop;
|
||||
import org.zkoss.zk.ui.Executions;
|
||||
|
||||
|
|
@ -37,6 +37,7 @@ public class OnZKDesktopRegistry<T> {
|
|||
|
||||
public OnZKDesktopRegistry(Class<T> klass) {
|
||||
Validate.notNull(klass);
|
||||
|
||||
this.klass = klass;
|
||||
this.attributeName = klass.getName() + "_locator";
|
||||
}
|
||||
|
|
@ -51,6 +52,7 @@ public class OnZKDesktopRegistry<T> {
|
|||
|
||||
public boolean isRegistered() {
|
||||
Object result = get();
|
||||
|
||||
return result != null;
|
||||
}
|
||||
|
||||
|
|
@ -59,10 +61,10 @@ public class OnZKDesktopRegistry<T> {
|
|||
}
|
||||
|
||||
public T retrieve() throws IllegalStateException {
|
||||
if (!isRegistered()) {
|
||||
throw new IllegalStateException("no " + klass.getSimpleName()
|
||||
+ " registered");
|
||||
if ( !isRegistered() ) {
|
||||
throw new IllegalStateException("no " + klass.getSimpleName() + " registered");
|
||||
}
|
||||
|
||||
return klass.cast(get());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
package org.zkoss.ganttz.util;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
/**
|
||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
|
|
@ -38,7 +38,7 @@ public abstract class PreAndPostNotReentrantActionsWrapper {
|
|||
|
||||
public void doAction(IAction action) {
|
||||
Validate.notNull(action);
|
||||
if (inside.get()) {
|
||||
if ( inside.get() ) {
|
||||
action.doAction();
|
||||
} else {
|
||||
executeWithPreAndPostActions(action);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
public class WeakReferencedListeners<T> {
|
||||
|
||||
|
|
@ -38,10 +38,10 @@ public class WeakReferencedListeners<T> {
|
|||
}
|
||||
|
||||
public static <T> WeakReferencedListeners<T> create() {
|
||||
return new WeakReferencedListeners<T>();
|
||||
return new WeakReferencedListeners<>();
|
||||
}
|
||||
|
||||
private LinkedList<WeakReference<T>> listeners = new LinkedList<WeakReference<T>>();
|
||||
private LinkedList<WeakReference<T>> listeners = new LinkedList<>();
|
||||
|
||||
private WeakReferencedListeners() {
|
||||
|
||||
|
|
@ -58,13 +58,13 @@ public class WeakReferencedListeners<T> {
|
|||
public synchronized void addListener(T listener, Mode mode) {
|
||||
Validate.notNull(listener);
|
||||
|
||||
if (getActiveListeners().isEmpty() && mode == Mode.RECEIVE_PENDING) {
|
||||
if ( getActiveListeners().isEmpty() && mode == Mode.RECEIVE_PENDING ) {
|
||||
notifyPendingOfNotificationTo(listener);
|
||||
}
|
||||
listeners.add(new WeakReference<T>(listener));
|
||||
}
|
||||
|
||||
private List<IListenerNotification<? super T>> pendingOfNotification = new ArrayList<WeakReferencedListeners.IListenerNotification<? super T>>();
|
||||
private List<IListenerNotification<? super T>> pendingOfNotification = new ArrayList<>();
|
||||
|
||||
private void notifyPendingOfNotificationTo(T listener) {
|
||||
for (IListenerNotification<? super T> each : pendingOfNotification) {
|
||||
|
|
@ -73,30 +73,31 @@ public class WeakReferencedListeners<T> {
|
|||
pendingOfNotification.clear();
|
||||
}
|
||||
|
||||
public synchronized void fireEvent(
|
||||
IListenerNotification<? super T> notification) {
|
||||
public synchronized void fireEvent(IListenerNotification<? super T> notification) {
|
||||
List<T> active = getActiveListeners();
|
||||
|
||||
for (T listener : active) {
|
||||
notification.doNotify(listener);
|
||||
}
|
||||
|
||||
if (active.isEmpty()) {
|
||||
if ( active.isEmpty() ) {
|
||||
pendingOfNotification.add(notification);
|
||||
}
|
||||
}
|
||||
|
||||
private List<T> getActiveListeners() {
|
||||
ListIterator<WeakReference<T>> listIterator = listeners.listIterator();
|
||||
List<T> result = new ArrayList<T>();
|
||||
List<T> result = new ArrayList<>();
|
||||
|
||||
while (listIterator.hasNext()) {
|
||||
T listener = listIterator.next().get();
|
||||
if (listener == null) {
|
||||
if ( listener == null ) {
|
||||
listIterator.remove();
|
||||
} else {
|
||||
result.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,8 +50,7 @@ public class LoadPeriodTest {
|
|||
}
|
||||
|
||||
private void givenExampleLoadPeriod(LocalDate start, LocalDate end) {
|
||||
givenExampleLoadPeriod(GanttDate.createFrom(start),
|
||||
GanttDate.createFrom(end));
|
||||
givenExampleLoadPeriod(GanttDate.createFrom(start), GanttDate.createFrom(end));
|
||||
}
|
||||
|
||||
private void givenExampleLoadPeriod(GanttDate start, GanttDate end) {
|
||||
|
|
@ -59,16 +58,13 @@ public class LoadPeriodTest {
|
|||
givenExampleLoadPeriod(start, end, loadLevel);
|
||||
}
|
||||
|
||||
private void givenExampleLoadPeriod(GanttDate start, GanttDate end,
|
||||
LoadLevel loadLevel) {
|
||||
loadPeriod = new LoadPeriod(start, end, totalHours, assignedHours,
|
||||
loadLevel);
|
||||
private void givenExampleLoadPeriod(GanttDate start, GanttDate end, LoadLevel loadLevel) {
|
||||
loadPeriod = new LoadPeriod(start, end, totalHours, assignedHours, loadLevel);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void aLoadPeriodMustHaveAStartDate() {
|
||||
new LoadPeriod(null, GanttDate.createFrom(new LocalDate()), totalHours,
|
||||
assignedHours, correctLoadLevel());
|
||||
new LoadPeriod(null, GanttDate.createFrom(new LocalDate()), totalHours, assignedHours, correctLoadLevel());
|
||||
}
|
||||
|
||||
private static final String totalHours = "100";
|
||||
|
|
@ -79,26 +75,33 @@ public class LoadPeriodTest {
|
|||
return new LoadLevel(40);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void aLoadPeriodMustHaveAnEndDate() {
|
||||
new LoadPeriod(GanttDate.createFrom(new LocalDate()), null, totalHours,
|
||||
assignedHours, correctLoadLevel());
|
||||
new LoadPeriod(GanttDate.createFrom(new LocalDate()), null, totalHours, assignedHours, correctLoadLevel());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void theEndDateCantBeBeforeTheStartDate() {
|
||||
LocalDate start = new LocalDate(2009, 10, 4);
|
||||
LocalDate end = new LocalDate(2009, 10, 3);
|
||||
new LoadPeriod(GanttDate.createFrom(start), GanttDate.createFrom(end),
|
||||
totalHours, assignedHours, correctLoadLevel());
|
||||
|
||||
new LoadPeriod(
|
||||
GanttDate.createFrom(start),
|
||||
GanttDate.createFrom(end),
|
||||
totalHours, assignedHours,
|
||||
correctLoadLevel());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theEndDateCanBeTheSameThanTheStartDate() {
|
||||
LocalDate start = new LocalDate(2009, 10, 4);
|
||||
LocalDate end = new LocalDate(2009, 10, 4);
|
||||
new LoadPeriod(GanttDate.createFrom(start), GanttDate.createFrom(end),
|
||||
totalHours, assignedHours, correctLoadLevel());
|
||||
|
||||
new LoadPeriod(
|
||||
GanttDate.createFrom(start),
|
||||
GanttDate.createFrom(end),
|
||||
totalHours, assignedHours,
|
||||
correctLoadLevel());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -115,8 +118,8 @@ public class LoadPeriodTest {
|
|||
|
||||
@Test
|
||||
public void twoLoadPeriodOverlapCanOverlap() {
|
||||
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009,
|
||||
12, 1));
|
||||
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009, 12, 1));
|
||||
|
||||
assertTrue(loadPeriod.overlaps(create(2009, 11, 2, 2009, 11, 3)));
|
||||
assertTrue(loadPeriod.overlaps(create(2009, 10, 30, 2009, 11, 2)));
|
||||
assertTrue(loadPeriod.overlaps(create(2009, 10, 20, 2009, 12, 2)));
|
||||
|
|
@ -128,31 +131,31 @@ public class LoadPeriodTest {
|
|||
@Test
|
||||
// [start, end)
|
||||
public void startInclusiveButEndExclusive() {
|
||||
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009,
|
||||
12, 1));
|
||||
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009, 12, 1));
|
||||
|
||||
assertFalse(loadPeriod.overlaps(create(2009, 12, 1, 2009, 12, 3)));
|
||||
assertFalse(loadPeriod.overlaps(create(2009, 10, 1, 2009, 11, 1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pointDontOverlap() {
|
||||
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009,
|
||||
12, 1));
|
||||
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009, 12, 1));
|
||||
assertFalse(loadPeriod.overlaps(create(2009, 11, 1, 2009, 11, 1)));
|
||||
}
|
||||
|
||||
private static LoadPeriod create(int startYear, int startMonth,
|
||||
int startDay, int endYear, int endMonth, int endDay) {
|
||||
return new LoadPeriod(GanttDate.createFrom(new LocalDate(startYear,
|
||||
startMonth, startDay)), GanttDate.createFrom(new LocalDate(
|
||||
endYear, endMonth, endDay)), totalHours,
|
||||
assignedHours, correctLoadLevel());
|
||||
private static LoadPeriod create(
|
||||
int startYear, int startMonth, int startDay, int endYear, int endMonth, int endDay) {
|
||||
|
||||
return new LoadPeriod(
|
||||
GanttDate.createFrom(new LocalDate(startYear, startMonth, startDay)),
|
||||
GanttDate.createFrom(new LocalDate(endYear, endMonth, endDay)),
|
||||
totalHours, assignedHours,
|
||||
correctLoadLevel());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void loadPeriodsThatOverlapCannotBeSorted() {
|
||||
LoadPeriod.sort(Arrays.asList(create(2009, 4, 10, 2010, 1, 12), create(
|
||||
2009, 4, 11, 2011, 1, 20)));
|
||||
LoadPeriod.sort(Arrays.asList(create(2009, 4, 10, 2010, 1, 12), create(2009, 4, 11, 2011, 1, 20)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -164,15 +167,16 @@ public class LoadPeriodTest {
|
|||
|
||||
@Test
|
||||
public void aZeroDaysLoadPeriodStartingTheSameDateThanANoZeroDaysLoadPeriodGoesAfter() {
|
||||
givenUnsortedListOfPeriods(create(2009, 4, 10, 2010, 1, 12), create(
|
||||
2009, 4, 10, 2009, 4, 10));
|
||||
givenUnsortedListOfPeriods(create(2009, 4, 10, 2010, 1, 12), create(2009, 4, 10, 2009, 4, 10));
|
||||
List<LoadPeriod> sorted = LoadPeriod.sort(unsortedList);
|
||||
thenIsSorted(sorted);
|
||||
}
|
||||
|
||||
private void givenUnsortedListOfPeriods() {
|
||||
givenUnsortedListOfPeriods(create(2009, 4, 10, 2010, 1, 12), create(
|
||||
2010, 1, 12, 2010, 1, 12), create(2010, 2, 13, 2010, 5, 7),
|
||||
givenUnsortedListOfPeriods(
|
||||
create(2009, 4, 10, 2010, 1, 12),
|
||||
create(2010, 1, 12, 2010, 1, 12),
|
||||
create(2010, 2, 13, 2010, 5, 7),
|
||||
create(2009, 3, 5, 2009, 3, 10));
|
||||
}
|
||||
|
||||
|
|
@ -182,18 +186,19 @@ public class LoadPeriodTest {
|
|||
|
||||
private void thenIsSorted(List<LoadPeriod> sorted) {
|
||||
ListIterator<LoadPeriod> listIterator = sorted.listIterator();
|
||||
LoadPeriod previous = null;
|
||||
LoadPeriod previous;
|
||||
LoadPeriod current = null;
|
||||
|
||||
while (listIterator.hasNext()) {
|
||||
previous = current;
|
||||
current = listIterator.next();
|
||||
if (previous != null) {
|
||||
if ( previous != null ) {
|
||||
assertFalse(current.getStart().compareTo(previous.getEnd()) < 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void aLoadPeriodMustHaveANotNullLoadLevel() {
|
||||
givenExampleLoadPeriod();
|
||||
new LoadPeriod(start, end, totalHours, assignedHours, null);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ public class LoadTimelineTest {
|
|||
private LoadTimeLine loadTimeLine;
|
||||
private String conceptName;
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void aLoadTimelineMustHaveANotNullName() {
|
||||
new LoadTimeLine(null, Collections.<LoadPeriod> emptyList(), null);
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ public class LoadTimelineTest {
|
|||
new LoadTimeLine("", Collections.<LoadPeriod> emptyList(), null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void aLoadTimelineCannotHaveNullLoadPeriods() {
|
||||
new LoadTimeLine("bla", null, null);
|
||||
}
|
||||
|
|
@ -62,30 +62,34 @@ public class LoadTimelineTest {
|
|||
|
||||
private void givenValidLoadTimeLine() {
|
||||
conceptName = "bla";
|
||||
loadTimeLine = new LoadTimeLine(conceptName,
|
||||
loadTimeLine = new LoadTimeLine(
|
||||
conceptName,
|
||||
Arrays.asList(new LoadPeriod(GanttDate
|
||||
.createFrom(new LocalDate(2009, 10, 5)), GanttDate
|
||||
.createFrom(new LocalDate(2009, 10, 11)), "100", "20",
|
||||
new LoadLevel(20))), null);
|
||||
new LoadLevel(20))),
|
||||
null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aLoadTimelineWithZeroLoadPeriodsIsEmpty() {
|
||||
LoadTimeLine timeline = new LoadTimeLine("bla", Collections
|
||||
.<LoadPeriod> emptyList(), null);
|
||||
LoadTimeLine timeline = new LoadTimeLine("bla", Collections.<LoadPeriod> emptyList(), null);
|
||||
assertTrue(timeline.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aLoadTimelineSortsItsReceivedPeriods() {
|
||||
LoadPeriod l1 = new LoadPeriod(GanttDate.createFrom(new LocalDate(2009,
|
||||
10, 5)), GanttDate.createFrom(new LocalDate(2009, 10, 11)),
|
||||
LoadPeriod l1 = new LoadPeriod(
|
||||
GanttDate.createFrom(new LocalDate(2009, 10, 5)),
|
||||
GanttDate.createFrom(new LocalDate(2009, 10, 11)),
|
||||
"100", "20", new LoadLevel(20));
|
||||
LoadPeriod l2 = new LoadPeriod(GanttDate.createFrom(new LocalDate(2009,
|
||||
5, 3)), GanttDate.createFrom(new LocalDate(2009, 6, 3)), "100",
|
||||
"20", new LoadLevel(20));
|
||||
LoadTimeLine loadTimeLine = new LoadTimeLine("bla", Arrays.asList(l1,
|
||||
l2), null);
|
||||
|
||||
LoadPeriod l2 = new LoadPeriod(
|
||||
GanttDate.createFrom(new LocalDate(2009, 5, 3)),
|
||||
GanttDate.createFrom(new LocalDate(2009, 6, 3)),
|
||||
"100", "20", new LoadLevel(20));
|
||||
|
||||
LoadTimeLine loadTimeLine = new LoadTimeLine("bla", Arrays.asList(l1, l2), null);
|
||||
|
||||
List<LoadPeriod> loadPeriods = loadTimeLine.getLoadPeriods();
|
||||
assertThat(loadPeriods.get(0), sameInstance(l2));
|
||||
|
|
@ -94,12 +98,16 @@ public class LoadTimelineTest {
|
|||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void theLoadPeriodsMustNotOverlap() {
|
||||
LoadPeriod l1 = new LoadPeriod(GanttDate.createFrom(new LocalDate(2009,
|
||||
10, 5)), GanttDate.createFrom(new LocalDate(2009, 10, 11)),
|
||||
LoadPeriod l1 = new LoadPeriod(
|
||||
GanttDate.createFrom(new LocalDate(2009, 10, 5)),
|
||||
GanttDate.createFrom(new LocalDate(2009, 10, 11)),
|
||||
"100", "20", new LoadLevel(20));
|
||||
LoadPeriod l2 = new LoadPeriod(GanttDate.createFrom(new LocalDate(2009,
|
||||
5, 3)), GanttDate.createFrom(new LocalDate(2009, 10, 10)),
|
||||
|
||||
LoadPeriod l2 = new LoadPeriod(
|
||||
GanttDate.createFrom(new LocalDate(2009, 5, 3)),
|
||||
GanttDate.createFrom(new LocalDate(2009, 10, 10)),
|
||||
"100", "20", new LoadLevel(20));
|
||||
|
||||
new LoadTimeLine("bla", Arrays.asList(l1, l2), null);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,8 +47,7 @@ public class OnColumnsRowRendererTest {
|
|||
|
||||
}
|
||||
|
||||
private static class CellRenderer implements
|
||||
ICellForDetailItemRenderer<DetailItem, Data> {
|
||||
private static class CellRenderer implements ICellForDetailItemRenderer<DetailItem, Data> {
|
||||
|
||||
@Override
|
||||
public Component cellFor(DetailItem item, Data data) {
|
||||
|
|
@ -57,8 +56,7 @@ public class OnColumnsRowRendererTest {
|
|||
|
||||
}
|
||||
|
||||
private static class CellRendererNotInferable<T> implements
|
||||
ICellForDetailItemRenderer<DetailItem, T> {
|
||||
private static class CellRendererNotInferable<T> implements ICellForDetailItemRenderer<DetailItem, T> {
|
||||
|
||||
@Override
|
||||
public Component cellFor(DetailItem item, T data) {
|
||||
|
|
@ -75,20 +73,19 @@ public class OnColumnsRowRendererTest {
|
|||
|
||||
private List<Data> data;
|
||||
|
||||
private void givenOnDetailItemsRowRenderer(
|
||||
ICellForDetailItemRenderer<DetailItem, Data> cellRenderer) {
|
||||
if (detailItems == null) {
|
||||
private void givenOnDetailItemsRowRenderer(ICellForDetailItemRenderer<DetailItem, Data> cellRenderer) {
|
||||
if ( detailItems == null ) {
|
||||
givenDetailItems();
|
||||
}
|
||||
rowRenderer = OnColumnsRowRenderer.create(Data.class, cellRenderer,
|
||||
detailItems);
|
||||
rowRenderer = OnColumnsRowRenderer.create(Data.class, cellRenderer, detailItems);
|
||||
}
|
||||
|
||||
private void givenDetailItems() {
|
||||
detailItems = new ArrayList<DetailItem>();
|
||||
detailItems = new ArrayList<>();
|
||||
start = new LocalDate(2010, 1, 1).toDateMidnight().toDateTime();
|
||||
DateTime current = start;
|
||||
Period period = Period.months(2);
|
||||
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
DateTime end = current.plus(period);
|
||||
DetailItem detail = new DetailItem(200, i + "", current, end);
|
||||
|
|
@ -98,62 +95,55 @@ public class OnColumnsRowRendererTest {
|
|||
}
|
||||
|
||||
private void givenData() {
|
||||
data = new ArrayList<Data>();
|
||||
data = new ArrayList<>();
|
||||
data.add(new Data());
|
||||
data.add(new Data());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void itNeedsNotNullDetailItems() {
|
||||
OnColumnsRowRenderer.create(Data.class, createStub(), null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void itNeedsNotNullCellRenderer() {
|
||||
OnColumnsRowRenderer.create(Data.class, null,
|
||||
new ArrayList<DetailItem>());
|
||||
OnColumnsRowRenderer.create(Data.class, null, new ArrayList<DetailItem>());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void itNeedsTheTypeAsClass() {
|
||||
OnColumnsRowRenderer.create(null, createStub(),
|
||||
new ArrayList<DetailItem>());
|
||||
OnColumnsRowRenderer.create(null, createStub(), new ArrayList<DetailItem>());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void itCanHaveEmptyDetailItems() {
|
||||
OnColumnsRowRenderer.create(Data.class, createStub(),
|
||||
new ArrayList<DetailItem>());
|
||||
OnColumnsRowRenderer.create(Data.class, createStub(), new ArrayList<DetailItem>());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void itCanInferTheGenericType() {
|
||||
OnColumnsRowRenderer.create(new CellRenderer(),
|
||||
new ArrayList<DetailItem>());
|
||||
OnColumnsRowRenderer.create(new CellRenderer(), new ArrayList<DetailItem>());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void ifComesFromRawTypeIsNotInferrable() {
|
||||
OnColumnsRowRenderer.create(createStub(),
|
||||
new ArrayList<DetailItem>());
|
||||
OnColumnsRowRenderer.create(createStub(), new ArrayList<DetailItem>());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void ifItNotShowsTheActualTypeIsNotInferrable() {
|
||||
OnColumnsRowRenderer.create(new CellRendererNotInferable<Data>(),
|
||||
new ArrayList<DetailItem>());
|
||||
OnColumnsRowRenderer.create(new CellRendererNotInferable<Data>(), new ArrayList<DetailItem>());
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void noDetailItemCanBeNull() {
|
||||
OnColumnsRowRenderer.create(Data.class, createStub(),
|
||||
new ArrayList<DetailItem>() {
|
||||
{
|
||||
add(new DetailItem(300, "bla"));
|
||||
add(null);
|
||||
}
|
||||
});
|
||||
OnColumnsRowRenderer.create(Data.class, createStub(), new ArrayList<DetailItem>() {
|
||||
{
|
||||
add(new DetailItem(300, "bla"));
|
||||
add(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
|
|
@ -193,6 +183,7 @@ public class OnColumnsRowRendererTest {
|
|||
}
|
||||
}
|
||||
replay(mock);
|
||||
|
||||
return mock;
|
||||
}
|
||||
|
||||
|
|
@ -209,17 +200,16 @@ public class OnColumnsRowRendererTest {
|
|||
verify(labelMock);
|
||||
}
|
||||
|
||||
private Label expectTheCreatedLabelIsAddedToTheRow(
|
||||
ICellForDetailItemRenderer<DetailItem, Data> mock) {
|
||||
private Label expectTheCreatedLabelIsAddedToTheRow(ICellForDetailItemRenderer<DetailItem, Data> mock) {
|
||||
Label labelMock = createStrictMock(Label.class);
|
||||
for (Data d : data) {
|
||||
for (DetailItem item : detailItems) {
|
||||
expect(mock.cellFor(isA(DetailItem.class), isA(Data.class)))
|
||||
.andReturn(labelMock);
|
||||
for (Data ignored1 : data) {
|
||||
for (DetailItem ignored2 : detailItems) {
|
||||
expect(mock.cellFor(isA(DetailItem.class), isA(Data.class))).andReturn(labelMock);
|
||||
labelMock.setParent(isA(Row.class));
|
||||
}
|
||||
}
|
||||
replay(mock, labelMock);
|
||||
|
||||
return labelMock;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,12 +53,15 @@ public class AvailabilityTimeLine {
|
|||
@Override
|
||||
public final int compareTo(DatePoint obj) {
|
||||
Validate.notNull(obj);
|
||||
if (obj instanceof FixedPoint) {
|
||||
if ( obj instanceof FixedPoint ) {
|
||||
return compareTo((FixedPoint) obj);
|
||||
} else if (obj instanceof EndOfTime) {
|
||||
|
||||
} else if ( obj instanceof EndOfTime ) {
|
||||
return compareTo((EndOfTime) obj);
|
||||
} else if (obj instanceof StartOfTime) {
|
||||
|
||||
} else if ( obj instanceof StartOfTime ) {
|
||||
return compareTo((StartOfTime) obj);
|
||||
|
||||
} else {
|
||||
throw new RuntimeException("unknown subclass for " + obj);
|
||||
}
|
||||
|
|
@ -69,15 +72,19 @@ public class AvailabilityTimeLine {
|
|||
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
if (!(obj instanceof DatePoint)) {
|
||||
if ( !(obj instanceof DatePoint) ) {
|
||||
return false;
|
||||
}
|
||||
if (obj instanceof FixedPoint) {
|
||||
|
||||
if ( obj instanceof FixedPoint ) {
|
||||
return equalTo((FixedPoint) obj);
|
||||
} else if (obj instanceof EndOfTime) {
|
||||
|
||||
} else if ( obj instanceof EndOfTime ) {
|
||||
return equalTo((EndOfTime) obj);
|
||||
} else if (obj instanceof StartOfTime) {
|
||||
|
||||
} else if ( obj instanceof StartOfTime ) {
|
||||
return equalTo((StartOfTime) obj);
|
||||
|
||||
} else {
|
||||
throw new RuntimeException("unknown subclass for " + obj);
|
||||
}
|
||||
|
|
@ -142,6 +149,7 @@ public class AvailabilityTimeLine {
|
|||
|
||||
public static LocalDate tryExtract(DatePoint start) {
|
||||
FixedPoint point = (FixedPoint) start;
|
||||
|
||||
return point.getDate();
|
||||
}
|
||||
}
|
||||
|
|
@ -243,8 +251,7 @@ public class AvailabilityTimeLine {
|
|||
}
|
||||
}
|
||||
|
||||
public static class Interval implements
|
||||
Comparable<Interval> {
|
||||
public static class Interval implements Comparable<Interval> {
|
||||
|
||||
/**
|
||||
* Creates an interval. Null values can be provided.
|
||||
|
|
@ -256,10 +263,9 @@ public class AvailabilityTimeLine {
|
|||
* @return an interval from start to end
|
||||
*/
|
||||
public static Interval create(LocalDate start, LocalDate end) {
|
||||
DatePoint startPoint = start == null ? new StartOfTime()
|
||||
: new FixedPoint(start);
|
||||
DatePoint endPoint = end == null ? new EndOfTime()
|
||||
: new FixedPoint(end);
|
||||
DatePoint startPoint = start == null ? new StartOfTime() : new FixedPoint(start);
|
||||
DatePoint endPoint = end == null ? new EndOfTime() : new FixedPoint(end);
|
||||
|
||||
return new Interval(startPoint, endPoint);
|
||||
}
|
||||
|
||||
|
|
@ -272,13 +278,11 @@ public class AvailabilityTimeLine {
|
|||
}
|
||||
|
||||
public static Interval to(LocalDate date) {
|
||||
return new Interval(StartOfTime.create(), new FixedPoint(
|
||||
date));
|
||||
return new Interval(StartOfTime.create(), new FixedPoint(date));
|
||||
}
|
||||
|
||||
static Interval point(LocalDate start) {
|
||||
return new Interval(new FixedPoint(start), new FixedPoint(start
|
||||
.plusDays(1)));
|
||||
return new Interval(new FixedPoint(start), new FixedPoint(start.plusDays(1)));
|
||||
}
|
||||
|
||||
private final DatePoint start;
|
||||
|
|
@ -300,17 +304,17 @@ public class AvailabilityTimeLine {
|
|||
|
||||
@Override
|
||||
public int compareTo(Interval other) {
|
||||
return this.start.compareTo(other.start) * 2
|
||||
- this.end.compareTo(other.end);
|
||||
return this.start.compareTo(other.start) * 2 - this.end.compareTo(other.end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Interval) {
|
||||
if ( obj instanceof Interval ) {
|
||||
Interval other = (Interval) obj;
|
||||
return start.equals(other.getStart())
|
||||
&& end.equals(other.getEnd());
|
||||
|
||||
return start.equals(other.getStart()) && end.equals(other.getEnd());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -324,35 +328,32 @@ public class AvailabilityTimeLine {
|
|||
}
|
||||
|
||||
private boolean includes(FixedPoint point) {
|
||||
return start.equals(point) || start.compareTo(point) <= 0
|
||||
&& point.compareTo(end) < 0;
|
||||
return start.equals(point) || start.compareTo(point) <= 0 && point.compareTo(end) < 0;
|
||||
}
|
||||
|
||||
public boolean overlaps(Interval other) {
|
||||
return start.compareTo(other.end) <= 0
|
||||
&& end.compareTo(other.start) >= 0;
|
||||
return start.compareTo(other.end) <= 0 && end.compareTo(other.start) >= 0;
|
||||
}
|
||||
|
||||
public Interval intersect(Interval other) {
|
||||
Validate.isTrue(overlaps(other));
|
||||
|
||||
return new Interval(max(start, other.start), min(end, other.end));
|
||||
}
|
||||
|
||||
public Interval coalesce(Interval other) {
|
||||
if (!overlaps(other)) {
|
||||
throw new IllegalArgumentException(
|
||||
"in order to coalesce two intervals must overlap");
|
||||
if ( !overlaps(other) ) {
|
||||
throw new IllegalArgumentException("in order to coalesce two intervals must overlap");
|
||||
}
|
||||
return new Interval(min(start, other.start), max(end,
|
||||
other.end));
|
||||
return new Interval(min(start, other.start), max(end, other.end));
|
||||
}
|
||||
|
||||
private DatePoint min(DatePoint... values) {
|
||||
return (DatePoint) Collections.min(Arrays.asList(values));
|
||||
return Collections.min(Arrays.asList(values));
|
||||
}
|
||||
|
||||
private DatePoint max(DatePoint... values) {
|
||||
return (DatePoint) Collections.max(Arrays.asList(values));
|
||||
return Collections.max(Arrays.asList(values));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -362,7 +363,7 @@ public class AvailabilityTimeLine {
|
|||
}
|
||||
|
||||
public interface IVetoer {
|
||||
public boolean isValid(LocalDate date);
|
||||
boolean isValid(LocalDate date);
|
||||
}
|
||||
|
||||
public static AvailabilityTimeLine allValid() {
|
||||
|
|
@ -372,6 +373,7 @@ public class AvailabilityTimeLine {
|
|||
public static AvailabilityTimeLine createAllInvalid() {
|
||||
AvailabilityTimeLine result = new AvailabilityTimeLine();
|
||||
result.allInvalid();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -385,7 +387,7 @@ public class AvailabilityTimeLine {
|
|||
|
||||
private IVetoer vetoer = NO_VETOER;
|
||||
|
||||
private List<Interval> invalids = new ArrayList<Interval>();
|
||||
private List<Interval> invalids = new ArrayList<>();
|
||||
|
||||
private AvailabilityTimeLine() {
|
||||
}
|
||||
|
|
@ -395,23 +397,27 @@ public class AvailabilityTimeLine {
|
|||
}
|
||||
|
||||
private boolean isValidBasedOnInvaidIntervals(LocalDate date) {
|
||||
if (invalids.isEmpty()) {
|
||||
if ( invalids.isEmpty() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Interval possibleInterval = findPossibleIntervalFor(date);
|
||||
|
||||
return possibleInterval == null || !possibleInterval.includes(date);
|
||||
}
|
||||
|
||||
private Interval findPossibleIntervalFor(LocalDate date) {
|
||||
Interval point = Interval.point(date);
|
||||
int binarySearch = Collections.binarySearch(invalids, point);
|
||||
if (binarySearch >= 0) {
|
||||
|
||||
if ( binarySearch >= 0) {
|
||||
return invalids.get(binarySearch);
|
||||
} else {
|
||||
int insertionPoint = insertionPoint(binarySearch);
|
||||
if (insertionPoint == 0) {
|
||||
if ( insertionPoint == 0 ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return invalids.get(insertionPoint - 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -439,10 +445,11 @@ public class AvailabilityTimeLine {
|
|||
}
|
||||
|
||||
private void insert(Interval toBeInserted) {
|
||||
if (invalids.isEmpty()) {
|
||||
if ( invalids.isEmpty() ) {
|
||||
invalids.add(toBeInserted);
|
||||
return;
|
||||
}
|
||||
|
||||
toBeInserted = coalesceWithAdjacent(toBeInserted);
|
||||
int insertionPoint = insertBeforeAllAdjacent(toBeInserted);
|
||||
removeAdjacent(insertionPoint, toBeInserted);
|
||||
|
|
@ -456,12 +463,14 @@ public class AvailabilityTimeLine {
|
|||
*/
|
||||
private int findInsertionPosition(Interval interval) {
|
||||
int binarySearch = Collections.binarySearch(invalids, interval);
|
||||
|
||||
return insertionPoint(binarySearch);
|
||||
}
|
||||
|
||||
private int insertBeforeAllAdjacent(Interval toBeInserted) {
|
||||
int insertionPoint = findInsertionPosition(toBeInserted);
|
||||
invalids.add(insertionPoint, toBeInserted);
|
||||
|
||||
return insertionPoint;
|
||||
}
|
||||
|
||||
|
|
@ -471,39 +480,43 @@ public class AvailabilityTimeLine {
|
|||
for (Interval each : adjacent) {
|
||||
result = result.coalesce(each);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Interval> getAdjacent(Interval toBeInserted) {
|
||||
final int insertionPoint = findInsertionPosition(toBeInserted);
|
||||
List<Interval> result = new ArrayList<Interval>();
|
||||
List<Interval> result = new ArrayList<>();
|
||||
assert insertionPoint <= invalids.size();
|
||||
|
||||
for (int i = insertionPoint - 1; i >= 0 && at(i).overlaps(toBeInserted); i--) {
|
||||
result.add(at(i));
|
||||
}
|
||||
for (int i = insertionPoint; i < invalids.size()
|
||||
&& at(i).overlaps(toBeInserted); i++) {
|
||||
|
||||
for (int i = insertionPoint; i < invalids.size() && at(i).overlaps(toBeInserted); i++) {
|
||||
result.add(at(i));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Interval> intersectWithAdjacent(Interval interval) {
|
||||
List<Interval> result = new ArrayList<Interval>();
|
||||
List<Interval> result = new ArrayList<>();
|
||||
List<Interval> adjacent = getAdjacent(interval);
|
||||
|
||||
for (Interval each : adjacent) {
|
||||
assert interval.overlaps(each);
|
||||
result.add(interval.intersect(each));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void removeAdjacent(int insertionPoint, Interval inserted) {
|
||||
ListIterator<Interval> listIterator = invalids
|
||||
.listIterator(insertionPoint + 1);
|
||||
ListIterator<Interval> listIterator = invalids.listIterator(insertionPoint + 1);
|
||||
while (listIterator.hasNext()) {
|
||||
Interval next = listIterator.next();
|
||||
if (!next.overlaps(inserted)) {
|
||||
if ( !next.overlaps(inserted) ) {
|
||||
break;
|
||||
}
|
||||
listIterator.remove();
|
||||
|
|
@ -515,14 +528,12 @@ public class AvailabilityTimeLine {
|
|||
}
|
||||
|
||||
private int insertionPoint(int binarySearchResult) {
|
||||
return binarySearchResult < 0 ? (-binarySearchResult) - 1
|
||||
: binarySearchResult;
|
||||
return binarySearchResult < 0 ? (-binarySearchResult) - 1 : binarySearchResult;
|
||||
}
|
||||
|
||||
public void invalidAt(LocalDate intervalStart, LocalDate intervalEnd) {
|
||||
if (intervalStart.isAfter(intervalEnd)) {
|
||||
throw new IllegalArgumentException(
|
||||
"end must be equal or after start");
|
||||
if ( intervalStart.isAfter(intervalEnd) ) {
|
||||
throw new IllegalArgumentException("end must be equal or after start");
|
||||
}
|
||||
insert(Interval.create(intervalStart, intervalEnd));
|
||||
}
|
||||
|
|
@ -540,11 +551,11 @@ public class AvailabilityTimeLine {
|
|||
inserting(result, invalids);
|
||||
inserting(result, another.invalids);
|
||||
result.setVetoer(and(this.vetoer, another.vetoer));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IVetoer and(final IVetoer a,
|
||||
final IVetoer b) {
|
||||
private static IVetoer and(final IVetoer a, final IVetoer b) {
|
||||
return new IVetoer() {
|
||||
@Override
|
||||
public boolean isValid(LocalDate date) {
|
||||
|
|
@ -556,27 +567,30 @@ public class AvailabilityTimeLine {
|
|||
public AvailabilityTimeLine or(AvailabilityTimeLine another) {
|
||||
List<Interval> intersections = doIntersections(this, another);
|
||||
AvailabilityTimeLine result = AvailabilityTimeLine.allValid();
|
||||
|
||||
for (Interval each : intersections) {
|
||||
boolean fromStartOfTime = each.getStart().equals(
|
||||
StartOfTime.create());
|
||||
boolean fromStartOfTime = each.getStart().equals(StartOfTime.create());
|
||||
boolean untilEndOfTime = each.getEnd().equals(EndOfTime.create());
|
||||
if (fromStartOfTime && untilEndOfTime) {
|
||||
|
||||
if ( fromStartOfTime && untilEndOfTime ) {
|
||||
result.allInvalid();
|
||||
} else if (fromStartOfTime) {
|
||||
|
||||
} else if ( fromStartOfTime ) {
|
||||
result.invalidUntil(FixedPoint.tryExtract(each.getEnd()));
|
||||
} else if (untilEndOfTime) {
|
||||
|
||||
} else if ( untilEndOfTime ) {
|
||||
result.invalidFrom(FixedPoint.tryExtract(each.getStart()));
|
||||
|
||||
} else {
|
||||
result.invalidAt(FixedPoint.tryExtract(each.getStart()),
|
||||
FixedPoint.tryExtract(each.getEnd()));
|
||||
result.invalidAt(FixedPoint.tryExtract(each.getStart()), FixedPoint.tryExtract(each.getEnd()));
|
||||
}
|
||||
}
|
||||
result.setVetoer(or(this.vetoer, another.vetoer));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IVetoer or(final IVetoer a,
|
||||
final IVetoer b) {
|
||||
private static IVetoer or(final IVetoer a, final IVetoer b) {
|
||||
return new IVetoer() {
|
||||
@Override
|
||||
public boolean isValid(LocalDate date) {
|
||||
|
|
@ -585,12 +599,12 @@ public class AvailabilityTimeLine {
|
|||
};
|
||||
}
|
||||
|
||||
private static List<Interval> doIntersections(AvailabilityTimeLine one,
|
||||
AvailabilityTimeLine another) {
|
||||
List<Interval> result = new ArrayList<Interval>();
|
||||
private static List<Interval> doIntersections(AvailabilityTimeLine one, AvailabilityTimeLine another) {
|
||||
List<Interval> result = new ArrayList<>();
|
||||
for (Interval each : one.invalids) {
|
||||
result.addAll(another.intersectWithAdjacent(each));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -601,19 +615,22 @@ public class AvailabilityTimeLine {
|
|||
}
|
||||
|
||||
public List<Interval> getValidPeriods() {
|
||||
List<Interval> result = new ArrayList<Interval>();
|
||||
List<Interval> result = new ArrayList<>();
|
||||
DatePoint previous = StartOfTime.create();
|
||||
|
||||
for (Interval each : invalids) {
|
||||
DatePoint invalidStart = each.start;
|
||||
if (!invalidStart.equals(StartOfTime.create())
|
||||
&& !invalidStart.equals(EndOfTime.create())) {
|
||||
if ( !invalidStart.equals(StartOfTime.create()) && !invalidStart.equals(EndOfTime.create()) ) {
|
||||
result.add(new Interval(previous, invalidStart));
|
||||
}
|
||||
|
||||
previous = each.getEnd();
|
||||
}
|
||||
if (!previous.equals(EndOfTime.create())) {
|
||||
|
||||
if ( !previous.equals(EndOfTime.create()) ) {
|
||||
result.add(new Interval(previous, EndOfTime.create()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ public class Dependency extends BaseEntity {
|
|||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
START_START {
|
||||
@Override
|
||||
public boolean modifiesDestinationStart() {
|
||||
|
|
@ -61,6 +62,7 @@ public class Dependency extends BaseEntity {
|
|||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
END_END {
|
||||
@Override
|
||||
public boolean modifiesDestinationStart() {
|
||||
|
|
@ -72,6 +74,7 @@ public class Dependency extends BaseEntity {
|
|||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
START_END {
|
||||
@Override
|
||||
public boolean modifiesDestinationStart() {
|
||||
|
|
@ -89,12 +92,12 @@ public class Dependency extends BaseEntity {
|
|||
public abstract boolean modifiesDestinationEnd();
|
||||
}
|
||||
|
||||
public static Dependency create(TaskElement origin,
|
||||
TaskElement destination, Type type) {
|
||||
public static Dependency create(TaskElement origin, TaskElement destination, Type type) {
|
||||
Dependency dependency = new Dependency(origin, destination, type);
|
||||
dependency.setNewObject(true);
|
||||
origin.add(dependency);
|
||||
destination.add(dependency);
|
||||
|
||||
return dependency;
|
||||
}
|
||||
|
||||
|
|
@ -117,8 +120,8 @@ public class Dependency extends BaseEntity {
|
|||
Validate.notNull(origin);
|
||||
Validate.notNull(destination);
|
||||
Validate.notNull(type);
|
||||
Validate.isTrue(!origin.equals(destination),
|
||||
"a dependency must have a different origin than destination");
|
||||
Validate.isTrue(!origin.equals(destination), "a dependency must have a different origin than destination");
|
||||
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
this.type = type;
|
||||
|
|
@ -145,8 +148,7 @@ public class Dependency extends BaseEntity {
|
|||
}
|
||||
|
||||
public boolean isDependencyBetweenLimitedAllocatedTasks() {
|
||||
return getOrigin().hasLimitedResourceAllocation() &&
|
||||
getDestination().hasLimitedResourceAllocation();
|
||||
return getOrigin().hasLimitedResourceAllocation() && getDestination().hasLimitedResourceAllocation();
|
||||
}
|
||||
|
||||
public boolean hasLimitedQueueDependencyAssociated() {
|
||||
|
|
@ -155,14 +157,18 @@ public class Dependency extends BaseEntity {
|
|||
|
||||
public Date getDateFromOrigin() {
|
||||
switch (type) {
|
||||
case END_START:
|
||||
case END_END:
|
||||
return origin.getEndDate();
|
||||
case START_END:
|
||||
case START_START:
|
||||
return origin.getStartDate();
|
||||
default:
|
||||
throw new RuntimeException("unexpected type");
|
||||
case END_START:
|
||||
|
||||
case END_END:
|
||||
return origin.getEndDate();
|
||||
|
||||
case START_END:
|
||||
|
||||
case START_START:
|
||||
return origin.getStartDate();
|
||||
|
||||
default:
|
||||
throw new RuntimeException("unexpected type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import org.joda.time.LocalDate;
|
|||
* @author Diego Pino García <dpino@igalia.com>
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*
|
||||
* Assignment function by stretches.
|
||||
* Assignment function by stretches.
|
||||
*
|
||||
*/
|
||||
public class StretchesFunction extends AssignmentFunction {
|
||||
|
|
@ -58,48 +58,48 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
|
||||
private boolean consolidated = false;
|
||||
|
||||
public static Interval create(BigDecimal loadProportion, LocalDate start,
|
||||
LocalDate end, boolean consolidated) {
|
||||
public static Interval create(BigDecimal loadProportion, LocalDate start, LocalDate end, boolean consolidated) {
|
||||
Interval result = create(loadProportion, start, end);
|
||||
result.consolidated(consolidated);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Interval create(BigDecimal loadProportion, LocalDate start,
|
||||
LocalDate end) {
|
||||
public static Interval create(BigDecimal loadProportion, LocalDate start, LocalDate end) {
|
||||
return new Interval(loadProportion, start, end);
|
||||
}
|
||||
|
||||
public Interval(BigDecimal loadProportion, LocalDate start,
|
||||
LocalDate end) {
|
||||
public Interval(BigDecimal loadProportion, LocalDate start, LocalDate end) {
|
||||
Validate.notNull(loadProportion);
|
||||
Validate.isTrue(loadProportion.signum() >= 0);
|
||||
Validate.notNull(end);
|
||||
this.loadProportion = loadProportion.setScale(2,
|
||||
RoundingMode.HALF_UP);
|
||||
|
||||
this.loadProportion = loadProportion.setScale(2, RoundingMode.HALF_UP);
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public static double[] getHoursPointsFor(int totalHours,
|
||||
List<Interval> intervalsDefinedByStreches) {
|
||||
public static double[] getHoursPointsFor(int totalHours, List<Interval> intervalsDefinedByStreches) {
|
||||
double[] result = new double[intervalsDefinedByStreches.size()];
|
||||
int i = 0;
|
||||
int accumulated = 0;
|
||||
|
||||
for (Interval each : intervalsDefinedByStreches) {
|
||||
accumulated += each.getHoursFor(totalHours);
|
||||
result[i++] = accumulated;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double[] getDayPointsFor(LocalDate start,
|
||||
List<Interval> intervalsDefinedByStreches) {
|
||||
public static double[] getDayPointsFor(LocalDate start, List<Interval> intervalsDefinedByStreches) {
|
||||
double[] result = new double[intervalsDefinedByStreches.size()];
|
||||
int i = 0;
|
||||
|
||||
for (Interval each : intervalsDefinedByStreches) {
|
||||
result[i++] = Days.daysBetween(start, each.getEnd()).getDays();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -120,8 +120,7 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
}
|
||||
|
||||
public int getHoursFor(int totalHours) {
|
||||
return loadProportion.multiply(new BigDecimal(totalHours))
|
||||
.intValue();
|
||||
return loadProportion.multiply(new BigDecimal(totalHours)).intValue();
|
||||
}
|
||||
|
||||
public LocalDate getStartFor(LocalDate allocationStart) {
|
||||
|
|
@ -129,41 +128,43 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
}
|
||||
|
||||
private void apply(ResourceAllocation<?> resourceAllocation,
|
||||
LocalDate startInclusive, LocalDate taskEnd,
|
||||
int intervalHours) {
|
||||
LocalDate startInclusive,
|
||||
int intervalHours) {
|
||||
|
||||
Validate.isTrue(!isConsolidated());
|
||||
resourceAllocation.withPreviousAssociatedResources()
|
||||
.onInterval(getStartFor(startInclusive), getEnd())
|
||||
.allocateHours(intervalHours);
|
||||
.onInterval(getStartFor(startInclusive), getEnd()).allocateHours(intervalHours);
|
||||
}
|
||||
|
||||
public static void apply(ResourceAllocation<?> allocation,
|
||||
List<Interval> intervalsDefinedByStreches,
|
||||
LocalDate allocationStart, LocalDate allocationEnd,
|
||||
int totalHours) {
|
||||
if (intervalsDefinedByStreches.isEmpty()) {
|
||||
List<Interval> intervalsDefinedByStreches,
|
||||
LocalDate allocationStart,
|
||||
int totalHours) {
|
||||
|
||||
if ( intervalsDefinedByStreches.isEmpty() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Validate.isTrue(totalHours == allocation.getNonConsolidatedHours());
|
||||
|
||||
int[] hoursPerInterval = getHoursPerInterval(
|
||||
intervalsDefinedByStreches, totalHours);
|
||||
int[] hoursPerInterval = getHoursPerInterval(intervalsDefinedByStreches, totalHours);
|
||||
int remainder = totalHours - sum(hoursPerInterval);
|
||||
hoursPerInterval[0] += remainder;
|
||||
int i = 0;
|
||||
|
||||
for (Interval interval : intervalsDefinedByStreches) {
|
||||
interval.apply(allocation, allocationStart, allocationEnd,
|
||||
hoursPerInterval[i++]);
|
||||
interval.apply(allocation, allocationStart, hoursPerInterval[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
private static int[] getHoursPerInterval(
|
||||
List<Interval> intervalsDefinedByStreches, int totalHours) {
|
||||
private static int[] getHoursPerInterval(List<Interval> intervalsDefinedByStreches, int totalHours) {
|
||||
int[] hoursPerInterval = new int[intervalsDefinedByStreches.size()];
|
||||
int i = 0;
|
||||
|
||||
for (Interval each : intervalsDefinedByStreches) {
|
||||
hoursPerInterval[i++] = each.getHoursFor(totalHours);
|
||||
}
|
||||
|
||||
return hoursPerInterval;
|
||||
}
|
||||
|
||||
|
|
@ -172,6 +173,7 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
for (int each : hoursPerInterval) {
|
||||
result += each;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +191,7 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
|
||||
}
|
||||
|
||||
private List<Stretch> stretches = new ArrayList<Stretch>();
|
||||
private List<Stretch> stretches = new ArrayList<>();
|
||||
|
||||
private StretchesFunctionTypeEnum type;
|
||||
|
||||
|
|
@ -203,7 +205,7 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
private ResourceAllocation<?> resourceAllocation;
|
||||
|
||||
public static StretchesFunction create() {
|
||||
return (StretchesFunction) create(new StretchesFunction());
|
||||
return create(new StretchesFunction());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -214,23 +216,28 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
}
|
||||
|
||||
public static List<Interval> intervalsFor(ResourceAllocation<?> allocation,
|
||||
Collection<? extends Stretch> streches) {
|
||||
ArrayList<Interval> result = new ArrayList<Interval>();
|
||||
LocalDate previous = null, stretchDate = null;
|
||||
BigDecimal sumOfProportions = BigDecimal.ZERO, loadedProportion = BigDecimal.ZERO;
|
||||
Collection<? extends Stretch> streches) {
|
||||
|
||||
ArrayList<Interval> result = new ArrayList<>();
|
||||
LocalDate previous = null;
|
||||
LocalDate stretchDate;
|
||||
|
||||
BigDecimal sumOfProportions = BigDecimal.ZERO;
|
||||
BigDecimal loadedProportion;
|
||||
|
||||
for (Stretch each : streches) {
|
||||
stretchDate = each.getDateIn(allocation);
|
||||
loadedProportion = each.getAmountWorkPercentage().subtract(
|
||||
sumOfProportions);
|
||||
if (loadedProportion.signum() < 0) {
|
||||
loadedProportion = each.getAmountWorkPercentage().subtract(sumOfProportions);
|
||||
|
||||
if ( loadedProportion.signum() < 0 ) {
|
||||
loadedProportion = BigDecimal.ZERO;
|
||||
}
|
||||
result.add(Interval.create(loadedProportion, previous,
|
||||
stretchDate, each.isConsolidated()));
|
||||
|
||||
result.add(Interval.create(loadedProportion, previous, stretchDate, each.isConsolidated()));
|
||||
sumOfProportions = each.getAmountWorkPercentage();
|
||||
previous = stretchDate;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -245,6 +252,7 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
result.desiredType = desiredType;
|
||||
result.consolidatedStretch = consolidatedStretch;
|
||||
result.resourceAllocation = resourceAllocation;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -257,29 +265,30 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
}
|
||||
|
||||
public List<Stretch> getStretchesDefinedByUser() {
|
||||
return Collections.unmodifiableList(Stretch
|
||||
.sortByLengthPercentage(stretches));
|
||||
return Collections.unmodifiableList(Stretch.sortByLengthPercentage(stretches));
|
||||
}
|
||||
|
||||
@Valid
|
||||
public List<Stretch> getStretches() {
|
||||
List<Stretch> result = new ArrayList<Stretch>();
|
||||
List<Stretch> result = new ArrayList<>();
|
||||
result.add(getFirstStretch());
|
||||
result.addAll(stretches);
|
||||
result.add(getLastStretch());
|
||||
return Collections.unmodifiableList(Stretch
|
||||
.sortByLengthPercentage(result));
|
||||
|
||||
return Collections.unmodifiableList(Stretch.sortByLengthPercentage(result));
|
||||
}
|
||||
|
||||
private Stretch getLastStretch() {
|
||||
Stretch result = Stretch.create(BigDecimal.ONE, BigDecimal.ONE);
|
||||
result.readOnly(true);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Stretch getFirstStretch() {
|
||||
Stretch result = Stretch.create(BigDecimal.ZERO, BigDecimal.ZERO);
|
||||
result.readOnly(true);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -313,67 +322,74 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
return getStretchesPlusConsolidated().size() > 2;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "A stretch has lower or equal values than the "
|
||||
+ "previous stretch")
|
||||
@AssertTrue(message = "A stretch has lower or equal values than the previous stretch")
|
||||
public boolean isStretchesOrderConstraint() {
|
||||
List<Stretch> stretchesPlusConsolidated = getStretchesPlusConsolidated();
|
||||
if (stretchesPlusConsolidated.isEmpty()) {
|
||||
if ( stretchesPlusConsolidated.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator<Stretch> iterator = stretchesPlusConsolidated.iterator();
|
||||
Stretch previous = iterator.next();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Stretch current = iterator.next();
|
||||
if (current.getLengthPercentage().compareTo(
|
||||
previous.getLengthPercentage()) <= 0) {
|
||||
if ( current.getLengthPercentage().compareTo(previous.getLengthPercentage()) <= 0 ) {
|
||||
return false;
|
||||
}
|
||||
if (current.getAmountWorkPercentage().compareTo(
|
||||
previous.getAmountWorkPercentage()) <= 0) {
|
||||
|
||||
if ( current.getAmountWorkPercentage().compareTo(previous.getAmountWorkPercentage()) <= 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
previous = current;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<Stretch> getStretchesPlusConsolidated() {
|
||||
List<Stretch> result = new ArrayList<Stretch>();
|
||||
List<Stretch> result = new ArrayList<>();
|
||||
result.addAll(getStretches());
|
||||
if (consolidatedStretch != null) {
|
||||
|
||||
if ( consolidatedStretch != null ) {
|
||||
result.add(consolidatedStretch);
|
||||
}
|
||||
return Collections.unmodifiableList(Stretch
|
||||
.sortByLengthPercentage(result));
|
||||
|
||||
return Collections.unmodifiableList(Stretch.sortByLengthPercentage(result));
|
||||
}
|
||||
|
||||
@AssertTrue(message = "Last stretch should have one hundred percent "
|
||||
+ "length and one hundred percent of work percentage")
|
||||
@AssertTrue(message = "Last stretch should have one hundred percent " +
|
||||
"length and one hundred percent of work percentage")
|
||||
public boolean isOneHundredPercentConstraint() {
|
||||
List<Stretch> stretches = getStretchesPlusConsolidated();
|
||||
if (stretches.isEmpty()) {
|
||||
if ( stretches.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Stretch lastStretch = stretches.get(stretches.size() - 1);
|
||||
if (lastStretch.getLengthPercentage().compareTo(BigDecimal.ONE) != 0) {
|
||||
if ( lastStretch.getLengthPercentage().compareTo(BigDecimal.ONE) != 0 ) {
|
||||
return false;
|
||||
}
|
||||
if (lastStretch.getAmountWorkPercentage().compareTo(BigDecimal.ONE) != 0) {
|
||||
|
||||
if ( lastStretch.getAmountWorkPercentage().compareTo(BigDecimal.ONE) != 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(ResourceAllocation<?> resourceAllocation) {
|
||||
if (!resourceAllocation.hasAssignments()) {
|
||||
if ( !resourceAllocation.hasAssignments() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Is 100% consolidated
|
||||
if (resourceAllocation.getFirstNonConsolidatedDate() == null) {
|
||||
if ( resourceAllocation.getFirstNonConsolidatedDate() == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.resourceAllocation = resourceAllocation;
|
||||
getDesiredType().applyTo(resourceAllocation, this);
|
||||
type = getDesiredType();
|
||||
|
|
@ -381,7 +397,7 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
if (StretchesFunctionTypeEnum.INTERPOLATED.equals(type)) {
|
||||
if ( StretchesFunctionTypeEnum.INTERPOLATED.equals(type) ) {
|
||||
return AssignmentFunctionName.INTERPOLATION.toString();
|
||||
} else {
|
||||
return AssignmentFunctionName.STRETCHES.toString();
|
||||
|
|
@ -389,25 +405,27 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
}
|
||||
|
||||
public List<Interval> getIntervalsDefinedByStreches() {
|
||||
List<Stretch> stretches = stretchesFor(type);
|
||||
if (stretches.isEmpty()) {
|
||||
List<Stretch> stretches = stretchesFor();
|
||||
if ( stretches.isEmpty() ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
checkStretchesSumOneHundredPercent();
|
||||
|
||||
return intervalsFor(resourceAllocation, stretches);
|
||||
}
|
||||
|
||||
private List<Stretch> stretchesFor(StretchesFunctionTypeEnum type) {
|
||||
return (getDesiredType().equals(StretchesFunctionTypeEnum.INTERPOLATED)) ? getStretchesPlusConsolidated()
|
||||
: getStretches();
|
||||
private List<Stretch> stretchesFor() {
|
||||
boolean condition = (getDesiredType().equals(StretchesFunctionTypeEnum.INTERPOLATED));
|
||||
|
||||
return condition ? getStretchesPlusConsolidated() : getStretches();
|
||||
}
|
||||
|
||||
private void checkStretchesSumOneHundredPercent() {
|
||||
List<Stretch> stretches = getStretchesPlusConsolidated();
|
||||
BigDecimal sumOfProportions = stretches.isEmpty() ? BigDecimal.ZERO
|
||||
: last(stretches).getAmountWorkPercentage();
|
||||
BigDecimal sumOfProportions = stretches.isEmpty() ? BigDecimal.ZERO : last(stretches).getAmountWorkPercentage();
|
||||
BigDecimal left = calculateLeftFor(sumOfProportions);
|
||||
if (!left.equals(BigDecimal.ZERO)) {
|
||||
|
||||
if ( !left.equals(BigDecimal.ZERO) ) {
|
||||
throw new IllegalStateException(_("Stretches must sum 100%"));
|
||||
}
|
||||
}
|
||||
|
|
@ -415,6 +433,7 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
private BigDecimal calculateLeftFor(BigDecimal sumOfProportions) {
|
||||
BigDecimal left = BigDecimal.ONE.subtract(sumOfProportions);
|
||||
left = left.signum() <= 0 ? BigDecimal.ZERO : left;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ public enum StretchesFunctionTypeEnum {
|
|||
LocalDate startInclusive, LocalDate endExclusive,
|
||||
int totalHours) {
|
||||
|
||||
Interval.apply(allocation, intervalsDefinedByStreches, startInclusive, endExclusive, totalHours);
|
||||
Interval.apply(allocation, intervalsDefinedByStreches, startInclusive, totalHours);
|
||||
}
|
||||
},
|
||||
INTERPOLATED {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -55,11 +55,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
@Repository
|
||||
@Scope(BeanDefinition.SCOPE_SINGLETON)
|
||||
@Transactional
|
||||
public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
||||
IResourceDAO {
|
||||
|
||||
@Autowired
|
||||
private IScenarioManager scenarioManager;
|
||||
public class ResourceDAO extends IntegrationEntityDAO<Resource> implements IResourceDAO {
|
||||
|
||||
@Override
|
||||
public List<Worker> getWorkers() {
|
||||
|
|
@ -71,10 +67,11 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
|||
List<Worker> list = getWorkers();
|
||||
for (Iterator<Worker> iterator = list.iterator(); iterator.hasNext();) {
|
||||
Worker worker = iterator.next();
|
||||
if (worker.isReal()) {
|
||||
if ( worker.isReal() ) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
|
@ -83,10 +80,11 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
|||
List<Worker> list = getWorkers();
|
||||
for (Iterator<Worker> iterator = list.iterator(); iterator.hasNext();) {
|
||||
Worker worker = iterator.next();
|
||||
if (worker.isVirtual()) {
|
||||
if ( worker.isVirtual() ) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
|
@ -97,15 +95,13 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
|||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public List<Resource> getAllLimitingResources() {
|
||||
return getSession().createCriteria(Resource.class).add(
|
||||
Restrictions.eq("limitingResource", true)).list();
|
||||
return getSession().createCriteria(Resource.class).add(Restrictions.eq("limitingResource", true)).list();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public List<Resource> getAllNonLimitingResources() {
|
||||
return getSession().createCriteria(Resource.class).add(
|
||||
Restrictions.eq("limitingResource", false)).list();
|
||||
return getSession().createCriteria(Resource.class).add(Restrictions.eq("limitingResource", false)).list();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -115,82 +111,95 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
|||
|
||||
@Override
|
||||
public List<Resource> getRealResources() {
|
||||
List<Resource> list = new ArrayList<Resource>();
|
||||
List<Resource> list = new ArrayList<>();
|
||||
list.addAll(getRealWorkers());
|
||||
list.addAll(getMachines());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Resource resource) {
|
||||
if (resource instanceof Worker || resource instanceof Machine) {
|
||||
if (resource.isLimitingResource() && resource.getLimitingResourceQueue() == null) {
|
||||
if ( resource instanceof Worker || resource instanceof Machine ) {
|
||||
if ( resource.isLimitingResource() && resource.getLimitingResourceQueue() == null ) {
|
||||
resource.setLimitingResourceQueue(LimitingResourceQueue.create());
|
||||
}
|
||||
}
|
||||
|
||||
super.save(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<HoursWorkedPerResourceDTO> getWorkingHoursPerWorker(
|
||||
List<Resource> resources, List<Label> labels,
|
||||
LabelFilterType labelFilterType, List<Criterion> criterions,
|
||||
List<Resource> resources,
|
||||
List<Label> labels,
|
||||
LabelFilterType labelFilterType,
|
||||
List<Criterion> criterions,
|
||||
Date startingDate,
|
||||
Date endingDate) {
|
||||
|
||||
String strQuery = "SELECT new org.libreplan.business.reports.dtos.HoursWorkedPerResourceDTO(resource, wrl) "
|
||||
+ "FROM Resource resource, WorkReportLine wrl "
|
||||
+ "LEFT OUTER JOIN wrl.resource wrlresource "
|
||||
+ "WHERE wrlresource.id = resource.id ";
|
||||
String strQuery =
|
||||
"SELECT new org.libreplan.business.reports.dtos.HoursWorkedPerResourceDTO(resource, wrl) " +
|
||||
"FROM Resource resource, WorkReportLine wrl " +
|
||||
"LEFT OUTER JOIN wrl.resource wrlresource " +
|
||||
"WHERE wrlresource.id = resource.id ";
|
||||
|
||||
// Set date range
|
||||
if (startingDate != null && endingDate != null) {
|
||||
if ( startingDate != null && endingDate != null ) {
|
||||
strQuery += "AND wrl.date BETWEEN :startingDate AND :endingDate ";
|
||||
}
|
||||
if (startingDate != null && endingDate == null) {
|
||||
|
||||
if ( startingDate != null && endingDate == null ) {
|
||||
strQuery += "AND wrl.date >= :startingDate ";
|
||||
}
|
||||
if (startingDate == null && endingDate != null) {
|
||||
|
||||
if ( startingDate == null && endingDate != null ) {
|
||||
strQuery += "AND wrl.date <= :endingDate ";
|
||||
}
|
||||
|
||||
// Set workers
|
||||
if (resources != null && !resources.isEmpty()) {
|
||||
if ( resources != null && !resources.isEmpty() ) {
|
||||
strQuery += "AND resource IN (:resources) ";
|
||||
}
|
||||
|
||||
// Set labels
|
||||
if (labels != null && !labels.isEmpty()) {
|
||||
if ( labels != null && !labels.isEmpty() ) {
|
||||
switch (labelFilterType) {
|
||||
case ORDER_ELEMENT:
|
||||
strQuery += " AND ( EXISTS (FROM wrl.orderElement.labels as etq WHERE etq IN (:labels)) "
|
||||
+ "OR EXISTS (FROM wrl.workReport.orderElement.labels as etqwr WHERE etqwr IN (:labels)) ) ";
|
||||
break;
|
||||
case WORK_REPORT:
|
||||
strQuery += " AND ( EXISTS (FROM wrl.labels as etq WHERE etq IN (:labels)) "
|
||||
+ "OR EXISTS (FROM wrl.workReport.labels as etqwr WHERE etqwr IN (:labels)) ) ";
|
||||
break;
|
||||
case BOTH:
|
||||
strQuery += " AND ( EXISTS (FROM wrl.labels as etq WHERE etq IN (:labels)) "
|
||||
+ "OR EXISTS (FROM wrl.workReport.labels as etqwr WHERE etqwr IN (:labels)) ) "
|
||||
+ "AND ( EXISTS (FROM wrl.orderElement.labels as etq WHERE etq IN (:labels)) "
|
||||
+ "OR EXISTS (FROM wrl.workReport.orderElement.labels as etqwr WHERE etqwr IN (:labels)) ) ";
|
||||
break;
|
||||
case ANY:
|
||||
default:
|
||||
strQuery += " AND ( ( EXISTS (FROM wrl.labels as etq WHERE etq IN (:labels)) "
|
||||
+ "OR EXISTS (FROM wrl.workReport.labels as etqwr WHERE etqwr IN (:labels)) ) "
|
||||
+ "OR ( EXISTS (FROM wrl.orderElement.labels as etq WHERE etq IN (:labels)) "
|
||||
+ "OR EXISTS (FROM wrl.workReport.orderElement.labels as etqwr WHERE etqwr IN (:labels)) ) ) ";
|
||||
break;
|
||||
case ORDER_ELEMENT:
|
||||
strQuery += " AND ( EXISTS (FROM wrl.orderElement.labels as etq WHERE etq IN (:labels)) " +
|
||||
"OR EXISTS (FROM wrl.workReport.orderElement.labels as etqwr WHERE etqwr IN (:labels)) ) ";
|
||||
break;
|
||||
|
||||
case WORK_REPORT:
|
||||
strQuery += " AND ( EXISTS (FROM wrl.labels as etq WHERE etq IN (:labels)) " +
|
||||
"OR EXISTS (FROM wrl.workReport.labels as etqwr WHERE etqwr IN (:labels)) ) ";
|
||||
break;
|
||||
|
||||
case BOTH:
|
||||
strQuery += " AND ( EXISTS (FROM wrl.labels as etq WHERE etq IN (:labels)) " +
|
||||
"OR EXISTS (FROM wrl.workReport.labels as etqwr WHERE etqwr IN (:labels)) ) " +
|
||||
"AND ( EXISTS (FROM wrl.orderElement.labels as etq WHERE etq IN (:labels)) " +
|
||||
"OR EXISTS (FROM wrl.workReport.orderElement.labels as etqwr WHERE etqwr IN (:labels)) ) ";
|
||||
break;
|
||||
|
||||
case ANY:
|
||||
|
||||
default:
|
||||
strQuery += " AND ( ( EXISTS (FROM wrl.labels as etq WHERE etq IN (:labels)) " +
|
||||
"OR EXISTS (FROM wrl.workReport.labels as etqwr WHERE etqwr IN (:labels)) ) " +
|
||||
"OR ( EXISTS (FROM wrl.orderElement.labels as etq WHERE etq IN (:labels)) " +
|
||||
"OR EXISTS (FROM wrl.workReport.orderElement.labels as etqwr WHERE etqwr " +
|
||||
"IN (:labels)) ) ) ";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set Criterions
|
||||
if (criterions != null && !criterions.isEmpty()) {
|
||||
strQuery += " AND EXISTS (FROM resource.criterionSatisfactions as satisfaction "
|
||||
+ " WHERE satisfaction.criterion IN (:criterions)) ";
|
||||
if ( criterions != null && !criterions.isEmpty() ) {
|
||||
strQuery +=
|
||||
" AND EXISTS (FROM resource.criterionSatisfactions as satisfaction " +
|
||||
" WHERE satisfaction.criterion IN (:criterions)) ";
|
||||
}
|
||||
|
||||
// Order by
|
||||
|
|
@ -198,22 +207,24 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
|||
|
||||
// Set parameters
|
||||
Query query = getSession().createQuery(strQuery);
|
||||
if (startingDate != null) {
|
||||
if ( startingDate != null ) {
|
||||
query.setParameter("startingDate", startingDate);
|
||||
}
|
||||
if (endingDate != null) {
|
||||
|
||||
if ( endingDate != null ) {
|
||||
query.setParameter("endingDate", endingDate);
|
||||
}
|
||||
if (resources != null && !resources.isEmpty()) {
|
||||
|
||||
if ( resources != null && !resources.isEmpty() ) {
|
||||
query.setParameterList("resources", resources);
|
||||
}
|
||||
|
||||
if (labels != null && !labels.isEmpty()) {
|
||||
if ( labels != null && !labels.isEmpty() ) {
|
||||
query.setParameterList("labels", labels);
|
||||
}
|
||||
if (criterions != null && !criterions.isEmpty()) {
|
||||
query.setParameterList("criterions",
|
||||
Criterion.withAllDescendants(criterions));
|
||||
|
||||
if ( criterions != null && !criterions.isEmpty() ) {
|
||||
query.setParameterList("criterions", Criterion.withAllDescendants(criterions));
|
||||
}
|
||||
|
||||
// Get result
|
||||
|
|
@ -221,52 +232,55 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<HoursWorkedPerWorkerInAMonthDTO> getWorkingHoursPerWorker(
|
||||
Integer year, Integer month) {
|
||||
public List<HoursWorkedPerWorkerInAMonthDTO> getWorkingHoursPerWorker(Integer year, Integer month) {
|
||||
|
||||
String strQuery = "SELECT wrlresource.id, SUM(wrl.effort) "
|
||||
+ "FROM WorkReportLine wrl "
|
||||
+ "LEFT OUTER JOIN wrl.resource wrlresource ";
|
||||
String strQuery =
|
||||
"SELECT wrlresource.id, SUM(wrl.effort) " +
|
||||
"FROM WorkReportLine wrl " +
|
||||
"LEFT OUTER JOIN wrl.resource wrlresource ";
|
||||
|
||||
if (year != null) {
|
||||
if ( year != null ) {
|
||||
strQuery += "WHERE YEAR(wrl.date) = :year ";
|
||||
}
|
||||
if (month != null) {
|
||||
|
||||
if ( month != null ) {
|
||||
strQuery += "AND MONTH(wrl.date) = :month ";
|
||||
}
|
||||
|
||||
strQuery += "GROUP BY wrlresource.id, MONTH(wrl.date) ";
|
||||
|
||||
Query query = getSession().createQuery(strQuery);
|
||||
if (year != null) {
|
||||
if ( year != null ) {
|
||||
query.setParameter("year", year);
|
||||
}
|
||||
if (month != null) {
|
||||
|
||||
if ( month != null ) {
|
||||
query.setParameter("month", month);
|
||||
}
|
||||
|
||||
List<HoursWorkedPerWorkerInAMonthDTO> result = toDTO(query.list());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number getRowCount() {
|
||||
return (Number) getSession().createCriteria(Resource.class).setProjection(Projections.rowCount()).uniqueResult();
|
||||
return (Number) getSession()
|
||||
.createCriteria(Resource.class).setProjection(Projections.rowCount()).uniqueResult();
|
||||
}
|
||||
|
||||
private List<HoursWorkedPerWorkerInAMonthDTO> toDTO(List<Object> rows) {
|
||||
List<HoursWorkedPerWorkerInAMonthDTO> result = new ArrayList<HoursWorkedPerWorkerInAMonthDTO>();
|
||||
List<HoursWorkedPerWorkerInAMonthDTO> result = new ArrayList<>();
|
||||
|
||||
for (Object row: rows) {
|
||||
Object[] columns = (Object[]) row;
|
||||
Resource resource = (Resource) findExistingEntity((Long) columns[0]);
|
||||
EffortDuration effort = EffortDuration.seconds(((Long) columns[1])
|
||||
.intValue());
|
||||
Resource resource = findExistingEntity((Long) columns[0]);
|
||||
EffortDuration effort = EffortDuration.seconds(((Long) columns[1]).intValue());
|
||||
|
||||
HoursWorkedPerWorkerInAMonthDTO dto = new HoursWorkedPerWorkerInAMonthDTO(
|
||||
resource, effort);
|
||||
HoursWorkedPerWorkerInAMonthDTO dto = new HoursWorkedPerWorkerInAMonthDTO(resource, effort);
|
||||
result.add(dto);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import org.joda.time.LocalDate;
|
|||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
*/
|
||||
public abstract class Interval {
|
||||
|
||||
protected final LocalDate start;
|
||||
|
||||
protected final LocalDate end;
|
||||
|
|
@ -45,21 +46,24 @@ public abstract class Interval {
|
|||
|
||||
public static Interval range(LocalDate start, LocalDate end) {
|
||||
Validate.notNull(start, "start date must be not null");
|
||||
if (end == null) {
|
||||
if ( end == null ) {
|
||||
return from(start);
|
||||
}
|
||||
if (start.equals(end)) {
|
||||
|
||||
if ( start.equals(end) ) {
|
||||
return point(start);
|
||||
}
|
||||
|
||||
return new Range(start, end);
|
||||
}
|
||||
|
||||
protected Interval(LocalDate start, LocalDate end) {
|
||||
Validate.notNull(start, "start date must be not null");
|
||||
if (end != null) {
|
||||
Validate.isTrue(start.compareTo(end) <= 0,
|
||||
"start date must be equal or before than end date");
|
||||
|
||||
if ( end != null ) {
|
||||
Validate.isTrue(start.compareTo(end) <= 0, "start date must be equal or before than end date");
|
||||
}
|
||||
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
|
@ -68,11 +72,12 @@ public abstract class Interval {
|
|||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Interval) {
|
||||
if ( obj instanceof Interval ) {
|
||||
Interval interval = (Interval) obj;
|
||||
return dateEquals(start, interval.start)
|
||||
&& dateEquals(end, interval.end);
|
||||
|
||||
return dateEquals(start, interval.start) && dateEquals(end, interval.end);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -82,8 +87,7 @@ public abstract class Interval {
|
|||
}
|
||||
|
||||
private boolean dateEquals(LocalDate date1, LocalDate date2) {
|
||||
return date1 == date2
|
||||
|| (date1 != null && date2 != null && date1.equals(date2));
|
||||
return date1 == date2 || (date1 != null && date2 != null && date1.equals(date2));
|
||||
}
|
||||
|
||||
public abstract boolean includes(Interval included);
|
||||
|
|
@ -108,6 +112,7 @@ class Range extends Interval {
|
|||
|
||||
Range(LocalDate start, LocalDate end) {
|
||||
super(start, end);
|
||||
|
||||
Validate.notNull(start);
|
||||
Validate.notNull(end);
|
||||
}
|
||||
|
|
@ -119,36 +124,39 @@ class Range extends Interval {
|
|||
|
||||
@Override
|
||||
public boolean includes(Interval included) {
|
||||
if (included instanceof Point) {
|
||||
if ( included instanceof Point ) {
|
||||
Point point = (Point) included;
|
||||
|
||||
return point.overlapsWith(this);
|
||||
}
|
||||
return start.compareTo(included.start) <= 0 && included.end != null
|
||||
&& end.isAfter(included.end);
|
||||
|
||||
return start.compareTo(included.start) <= 0 && included.end != null && end.isAfter(included.end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean overlapsWith(Interval interval) {
|
||||
if (interval instanceof Point) {
|
||||
if ( interval instanceof Point ) {
|
||||
Point point = (Point) interval;
|
||||
|
||||
return point.overlapsWith(this);
|
||||
}
|
||||
if (interval instanceof OpenEndedInterval) {
|
||||
|
||||
if ( interval instanceof OpenEndedInterval ) {
|
||||
return interval.overlapsWith(this);
|
||||
}
|
||||
return interval.start.compareTo(this.end) < 0
|
||||
&& this.start.compareTo(interval.end) < 0;
|
||||
|
||||
return interval.start.compareTo(this.end) < 0 && this.start.compareTo(interval.end) < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("[").append(start).append(", ").append(end)
|
||||
.append(")").toString();
|
||||
return new StringBuilder("[").append(start).append(", ").append(end).append(")").toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class OpenEndedInterval extends Interval {
|
||||
|
||||
OpenEndedInterval(LocalDate start) {
|
||||
super(start, null);
|
||||
}
|
||||
|
|
@ -165,8 +173,7 @@ class OpenEndedInterval extends Interval {
|
|||
|
||||
@Override
|
||||
public boolean overlapsWith(Interval interval) {
|
||||
return start.isBefore(interval.start) || interval.end == null
|
||||
|| start.isBefore(interval.end);
|
||||
return start.isBefore(interval.start) || interval.end == null || start.isBefore(interval.end);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -198,8 +205,7 @@ class Point extends Interval {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder().append("[").append(start).append(")")
|
||||
.toString();
|
||||
return new StringBuilder().append("[").append(start).append(")").toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -38,19 +38,22 @@ public class Task extends BaseEntity {
|
|||
|
||||
public static final String RESOURCE = "resource";
|
||||
|
||||
public static final String ORDER_ELEMENT = "orderElement";
|
||||
|
||||
public static Task create() {
|
||||
Task workReportLine = new Task();
|
||||
workReportLine.setNewObject(true);
|
||||
|
||||
return workReportLine;
|
||||
}
|
||||
|
||||
public static Task create(Integer numHours, Resource resource,
|
||||
OrderElement orderElement, Set<Criterion> criterions) {
|
||||
Task workReportLine = new Task(numHours, resource,
|
||||
orderElement, criterions);
|
||||
public static Task create(
|
||||
Integer numHours,
|
||||
Resource resource,
|
||||
OrderElement orderElement,
|
||||
Set<Criterion> criterions) {
|
||||
|
||||
Task workReportLine = new Task(numHours, resource, orderElement, criterions);
|
||||
workReportLine.setNewObject(true);
|
||||
|
||||
return workReportLine;
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +67,7 @@ public class Task extends BaseEntity {
|
|||
|
||||
private WorkReport workReport;
|
||||
|
||||
private Set<Criterion> criterions = new HashSet<Criterion>();
|
||||
private Set<Criterion> criterions = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Constructor for hibernate. Do not use!
|
||||
|
|
@ -73,8 +76,7 @@ public class Task extends BaseEntity {
|
|||
|
||||
}
|
||||
|
||||
private Task(Integer numHours, Resource resource,
|
||||
OrderElement orderElement, Set<Criterion> criterions) {
|
||||
private Task(Integer numHours, Resource resource, OrderElement orderElement, Set<Criterion> criterions) {
|
||||
this.numHours = numHours;
|
||||
this.resource = resource;
|
||||
this.orderElement = orderElement;
|
||||
|
|
@ -106,7 +108,7 @@ public class Task extends BaseEntity {
|
|||
}
|
||||
|
||||
public Set<Criterion> getCriterions() {
|
||||
return new HashSet<Criterion>(criterions);
|
||||
return new HashSet<>(criterions);
|
||||
}
|
||||
|
||||
public void setCriterions(Set<Criterion> criterions) {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ import org.springframework.stereotype.Component;
|
|||
* @author Diego Pino García <dpino@igalia.com>
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*
|
||||
* Model for UI operations related to Order Dashboard View
|
||||
* Model for UI operations related to Order Dashboard View
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
|
|
@ -70,43 +70,35 @@ public class DashboardModel implements IDashboardModel {
|
|||
@Autowired
|
||||
private IOrderResourceLoadCalculator resourceLoadCalculator;
|
||||
|
||||
/* Parameters */
|
||||
public final static int EA_STRETCHES_PERCENTAGE_STEP = 10;
|
||||
public final static int EA_STRETCHES_MIN_VALUE = -100;
|
||||
public final static int EA_STRETCHES_MAX_VALUE = 150;
|
||||
public final static int LTC_NUMBER_OF_INTERVALS = 10;
|
||||
|
||||
/* To be calculated */
|
||||
public static double LTC_STRETCHES_STEP = 0;
|
||||
public static double LTC_STRETCHES_MIN_VALUE = 0;
|
||||
public static double LTC_STRETCHES_MAX_VALUE = 0;
|
||||
|
||||
private Order currentOrder;
|
||||
|
||||
private List<TaskElement> criticalPath;
|
||||
|
||||
private Integer taskCount = null;
|
||||
|
||||
private final Map<TaskStatusEnum, BigDecimal> taskStatusStats;
|
||||
|
||||
private final Map<TaskDeadlineViolationStatusEnum, BigDecimal> taskDeadlineViolationStatusStats;
|
||||
|
||||
private BigDecimal marginWithDeadLine;
|
||||
|
||||
private Integer absoluteMarginWithDeadLine;
|
||||
|
||||
public DashboardModel() {
|
||||
taskStatusStats = new EnumMap<TaskStatusEnum, BigDecimal>(
|
||||
TaskStatusEnum.class);
|
||||
taskDeadlineViolationStatusStats = new EnumMap<TaskDeadlineViolationStatusEnum, BigDecimal>(
|
||||
TaskDeadlineViolationStatusEnum.class);
|
||||
taskStatusStats = new EnumMap<>(TaskStatusEnum.class);
|
||||
taskDeadlineViolationStatusStats = new EnumMap<>(TaskDeadlineViolationStatusEnum.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentOrder(PlanningState planningState, List<TaskElement> criticalPath) {
|
||||
final Order order = planningState.getOrder();
|
||||
|
||||
resourceLoadCalculator.setOrder(order,
|
||||
planningState.getAssignmentsCalculator());
|
||||
resourceLoadCalculator.setOrder(order, planningState.getAssignmentsCalculator());
|
||||
this.currentOrder = order;
|
||||
this.criticalPath = criticalPath;
|
||||
this.taskCount = null;
|
||||
if (tasksAvailable()) {
|
||||
|
||||
if ( tasksAvailable() ) {
|
||||
this.calculateGlobalProgress();
|
||||
this.calculateTaskStatusStatistics();
|
||||
this.calculateTaskViolationStatusStatistics();
|
||||
|
|
@ -139,26 +131,23 @@ public class DashboardModel implements IDashboardModel {
|
|||
/* Progress KPI: "Deadline violation" */
|
||||
@Override
|
||||
public BigDecimal getPercentageOfOnScheduleTasks() {
|
||||
return taskDeadlineViolationStatusStats
|
||||
.get(TaskDeadlineViolationStatusEnum.ON_SCHEDULE);
|
||||
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.ON_SCHEDULE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getPercentageOfTasksWithViolatedDeadline() {
|
||||
return taskDeadlineViolationStatusStats
|
||||
.get(TaskDeadlineViolationStatusEnum.DEADLINE_VIOLATED);
|
||||
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.DEADLINE_VIOLATED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getPercentageOfTasksWithNoDeadline() {
|
||||
return taskDeadlineViolationStatusStats
|
||||
.get(TaskDeadlineViolationStatusEnum.NO_DEADLINE);
|
||||
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.NO_DEADLINE);
|
||||
}
|
||||
|
||||
/* Progress KPI: "Global Progress of the Project" */
|
||||
private void calculateGlobalProgress() {
|
||||
TaskGroup rootTask = getRootTask();
|
||||
if (rootTask == null) {
|
||||
if ( rootTask == null ) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
rootTask.updateCriticalPathProgress(criticalPath);
|
||||
|
|
@ -170,8 +159,7 @@ public class DashboardModel implements IDashboardModel {
|
|||
}
|
||||
|
||||
private BigDecimal asPercentage(BigDecimal value) {
|
||||
return value != null ? value.multiply(BigDecimal.valueOf(100))
|
||||
: BigDecimal.ZERO;
|
||||
return value != null ? value.multiply(BigDecimal.valueOf(100)) : BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -181,8 +169,7 @@ public class DashboardModel implements IDashboardModel {
|
|||
|
||||
@Override
|
||||
public BigDecimal getExpectedAdvancePercentageByHours() {
|
||||
return asPercentage(getRootTask()
|
||||
.getTheoreticalProgressByNumHoursForAllTasksUntilNow());
|
||||
return asPercentage(getRootTask().getTheoreticalProgressByNumHoursForAllTasksUntilNow());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -192,8 +179,7 @@ public class DashboardModel implements IDashboardModel {
|
|||
|
||||
@Override
|
||||
public BigDecimal getExpectedCriticalPathProgressByNumHours() {
|
||||
return asPercentage(getRootTask()
|
||||
.getTheoreticalProgressByNumHoursForCriticalPathUntilNow());
|
||||
return asPercentage(getRootTask().getTheoreticalProgressByNumHoursForCriticalPathUntilNow());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -203,8 +189,7 @@ public class DashboardModel implements IDashboardModel {
|
|||
|
||||
@Override
|
||||
public BigDecimal getExpectedCriticalPathProgressByDuration() {
|
||||
return asPercentage(getRootTask()
|
||||
.getTheoreticalProgressByDurationForCriticalPathUntilNow());
|
||||
return asPercentage(getRootTask().getTheoreticalProgressByDurationForCriticalPathUntilNow());
|
||||
}
|
||||
|
||||
/* Time KPI: Margin with deadline */
|
||||
|
|
@ -214,29 +199,26 @@ public class DashboardModel implements IDashboardModel {
|
|||
}
|
||||
|
||||
private void calculateMarginWithDeadLine() {
|
||||
if (this.getRootTask() == null) {
|
||||
if ( this.getRootTask() == null ) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
if (this.currentOrder.getDeadline() == null) {
|
||||
|
||||
if ( this.currentOrder.getDeadline() == null ) {
|
||||
this.marginWithDeadLine = null;
|
||||
return;
|
||||
}
|
||||
|
||||
TaskGroup rootTask = getRootTask();
|
||||
LocalDate endDate = TaskElement.maxDate(rootTask.getChildren())
|
||||
.asExclusiveEnd();
|
||||
Days orderDuration = Days.daysBetween(
|
||||
TaskElement.minDate(rootTask.getChildren()).getDate(), endDate);
|
||||
LocalDate endDate = TaskElement.maxDate(rootTask.getChildren()).asExclusiveEnd();
|
||||
Days orderDuration = Days.daysBetween(TaskElement.minDate(rootTask.getChildren()).getDate(), endDate);
|
||||
|
||||
LocalDate deadLineAsLocalDate = LocalDate.fromDateFields(currentOrder
|
||||
.getDeadline());
|
||||
Days deadlineOffset = Days.daysBetween(endDate,
|
||||
deadLineAsLocalDate.plusDays(1));
|
||||
LocalDate deadLineAsLocalDate = LocalDate.fromDateFields(currentOrder.getDeadline());
|
||||
Days deadlineOffset = Days.daysBetween(endDate, deadLineAsLocalDate.plusDays(1));
|
||||
|
||||
BigDecimal outcome = new BigDecimal(deadlineOffset.getDays(),
|
||||
MathContext.DECIMAL32);
|
||||
this.marginWithDeadLine = outcome.divide(
|
||||
new BigDecimal(orderDuration.getDays()), 8,
|
||||
BigDecimal.ROUND_HALF_EVEN);
|
||||
BigDecimal outcome = new BigDecimal(deadlineOffset.getDays(), MathContext.DECIMAL32);
|
||||
|
||||
this.marginWithDeadLine =
|
||||
outcome.divide(new BigDecimal(orderDuration.getDays()), 8, BigDecimal.ROUND_HALF_EVEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -248,13 +230,15 @@ public class DashboardModel implements IDashboardModel {
|
|||
TaskElement rootTask = getRootTask();
|
||||
Date deadline = currentOrder.getDeadline();
|
||||
|
||||
if (rootTask == null) {
|
||||
if ( rootTask == null ) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
if (deadline == null) {
|
||||
|
||||
if ( deadline == null ) {
|
||||
this.absoluteMarginWithDeadLine = null;
|
||||
return;
|
||||
}
|
||||
|
||||
absoluteMarginWithDeadLine = daysBetween(
|
||||
TaskElement.maxDate(rootTask.getChildren()).asExclusiveEnd(),
|
||||
LocalDate.fromDateFields(deadline).plusDays(1));
|
||||
|
|
@ -277,16 +261,19 @@ public class DashboardModel implements IDashboardModel {
|
|||
@Override
|
||||
public Map<Interval, Integer> calculateTaskCompletion() {
|
||||
List<Double> deviations = getTaskLagDeviations();
|
||||
|
||||
return calculateHistogramIntervals(deviations, 6, 1);
|
||||
}
|
||||
|
||||
private List<Double> getTaskLagDeviations() {
|
||||
if (this.getRootTask() == null) {
|
||||
if ( this.getRootTask() == null ) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
|
||||
CalculateFinishedTasksLagInCompletionVisitor visitor = new CalculateFinishedTasksLagInCompletionVisitor();
|
||||
TaskElement rootTask = getRootTask();
|
||||
rootTask.acceptVisitor(visitor);
|
||||
|
||||
return visitor.getDeviations();
|
||||
}
|
||||
|
||||
|
|
@ -318,18 +305,19 @@ public class DashboardModel implements IDashboardModel {
|
|||
@Override
|
||||
public Map<Interval, Integer> calculateEstimationAccuracy() {
|
||||
List<Double> deviations = getEstimationAccuracyDeviations();
|
||||
|
||||
return calculateHistogramIntervals(deviations, 6, 10);
|
||||
}
|
||||
|
||||
private Map<Interval, Integer> calculateHistogramIntervals(
|
||||
List<Double> values, int intervalsNumber, int intervalMinimumSize) {
|
||||
Map<Interval, Integer> result = new LinkedHashMap<Interval, Integer>();
|
||||
private Map<Interval, Integer> calculateHistogramIntervals(List<Double> values, int intervalsNumber,
|
||||
int intervalMinimumSize) {
|
||||
Map<Interval, Integer> result = new LinkedHashMap<>();
|
||||
|
||||
int totalMinimumSize = intervalsNumber * intervalMinimumSize;
|
||||
int halfSize = totalMinimumSize / 2;
|
||||
|
||||
double maxDouble, minDouble;
|
||||
if (values.isEmpty()) {
|
||||
if ( values.isEmpty() ) {
|
||||
minDouble = -halfSize;
|
||||
maxDouble = halfSize;
|
||||
} else {
|
||||
|
|
@ -339,39 +327,34 @@ public class DashboardModel implements IDashboardModel {
|
|||
|
||||
// If min and max are between -halfSize and +halfSize, set -halfSize as
|
||||
// min and +halfSize as max
|
||||
if (minDouble >= -halfSize && maxDouble <= halfSize) {
|
||||
if ( minDouble >= -halfSize && maxDouble <= halfSize ) {
|
||||
minDouble = -halfSize;
|
||||
maxDouble = halfSize;
|
||||
}
|
||||
|
||||
// If the difference between min and max is less than totalMinimumSize,
|
||||
// decrease min
|
||||
// and increase max till get that difference
|
||||
boolean changeMin = true;
|
||||
while (maxDouble - minDouble < totalMinimumSize) {
|
||||
if (changeMin) {
|
||||
minDouble -= intervalMinimumSize;
|
||||
} else {
|
||||
maxDouble += intervalMinimumSize;
|
||||
}
|
||||
minDouble -= intervalMinimumSize;
|
||||
}
|
||||
|
||||
// Round min and max properly depending on decimal part or not
|
||||
int min;
|
||||
double minDecimalPart = minDouble - (int) minDouble;
|
||||
if (minDouble >= 0) {
|
||||
if ( minDouble >= 0 ) {
|
||||
min = (int) (minDouble - minDecimalPart);
|
||||
} else {
|
||||
min = (int) (minDouble - minDecimalPart);
|
||||
if (minDecimalPart != 0) {
|
||||
if ( minDecimalPart != 0 ) {
|
||||
min--;
|
||||
}
|
||||
}
|
||||
|
||||
int max;
|
||||
double maxDecimalPart = maxDouble - (int) maxDouble;
|
||||
if (maxDouble >= 0) {
|
||||
if ( maxDouble >= 0 ) {
|
||||
max = (int) (maxDouble - maxDecimalPart);
|
||||
if (maxDecimalPart != 0) {
|
||||
if ( maxDecimalPart != 0 ) {
|
||||
max++;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -387,10 +370,11 @@ public class DashboardModel implements IDashboardModel {
|
|||
for (int i = 0; i < intervalsNumber; i++) {
|
||||
int to = from + (int) delta;
|
||||
// Fix to depending on decimal part if it's not the last interval
|
||||
if (deltaDecimalPart == 0 && i != (intervalsNumber - 1)) {
|
||||
if ( deltaDecimalPart == 0 && i != (intervalsNumber - 1) ) {
|
||||
to--;
|
||||
}
|
||||
result.put(new Interval(from, to), Integer.valueOf(0));
|
||||
|
||||
result.put(new Interval(from, to), 0);
|
||||
|
||||
from = to + 1;
|
||||
}
|
||||
|
|
@ -398,23 +382,25 @@ public class DashboardModel implements IDashboardModel {
|
|||
// Construct map with number of tasks for each interval
|
||||
final Set<Interval> intervals = result.keySet();
|
||||
for (Double each : values) {
|
||||
Interval interval = Interval.containingValue(
|
||||
intervals, each);
|
||||
if (interval != null) {
|
||||
Interval interval = Interval.containingValue(intervals, each);
|
||||
if ( interval != null ) {
|
||||
Integer value = result.get(interval);
|
||||
result.put(interval, value + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Double> getEstimationAccuracyDeviations() {
|
||||
if (this.getRootTask() == null) {
|
||||
if ( this.getRootTask() == null ) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
|
||||
CalculateFinishedTasksEstimationDeviationVisitor visitor = new CalculateFinishedTasksEstimationDeviationVisitor();
|
||||
TaskElement rootTask = getRootTask();
|
||||
rootTask.acceptVisitor(visitor);
|
||||
|
||||
return visitor.getDeviations();
|
||||
}
|
||||
|
||||
|
|
@ -427,13 +413,13 @@ public class DashboardModel implements IDashboardModel {
|
|||
this.max = max;
|
||||
}
|
||||
|
||||
public static Interval containingValue(
|
||||
Collection<Interval> intervals, double value) {
|
||||
public static Interval containingValue(Collection<Interval> intervals, double value) {
|
||||
for (Interval each : intervals) {
|
||||
if (each.includes(value)) {
|
||||
if ( each.includes(value) ) {
|
||||
return each;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -452,20 +438,25 @@ public class DashboardModel implements IDashboardModel {
|
|||
public Map<TaskStatusEnum, Integer> calculateTaskStatus() {
|
||||
AccumulateTasksStatusVisitor visitor = new AccumulateTasksStatusVisitor();
|
||||
TaskElement rootTask = getRootTask();
|
||||
if (this.getRootTask() == null) {
|
||||
|
||||
if ( this.getRootTask() == null ) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
|
||||
resetTasksStatusInGraph();
|
||||
rootTask.acceptVisitor(visitor);
|
||||
|
||||
return visitor.getTaskStatusData();
|
||||
}
|
||||
|
||||
private void calculateTaskStatusStatistics() {
|
||||
AccumulateTasksStatusVisitor visitor = new AccumulateTasksStatusVisitor();
|
||||
TaskElement rootTask = getRootTask();
|
||||
if (this.getRootTask() == null) {
|
||||
|
||||
if ( this.getRootTask() == null ) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
|
||||
resetTasksStatusInGraph();
|
||||
rootTask.acceptVisitor(visitor);
|
||||
Map<TaskStatusEnum, Integer> count = visitor.getTaskStatusData();
|
||||
|
|
@ -475,21 +466,21 @@ public class DashboardModel implements IDashboardModel {
|
|||
private void calculateTaskViolationStatusStatistics() {
|
||||
AccumulateTasksDeadlineStatusVisitor visitor = new AccumulateTasksDeadlineStatusVisitor();
|
||||
TaskElement rootTask = getRootTask();
|
||||
if (this.getRootTask() == null) {
|
||||
|
||||
if ( this.getRootTask() == null ) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
|
||||
rootTask.acceptVisitor(visitor);
|
||||
Map<TaskDeadlineViolationStatusEnum, Integer> count = visitor
|
||||
.getTaskDeadlineViolationStatusData();
|
||||
Map<TaskDeadlineViolationStatusEnum, Integer> count = visitor.getTaskDeadlineViolationStatusData();
|
||||
mapAbsoluteValuesToPercentages(count, taskDeadlineViolationStatusStats);
|
||||
}
|
||||
|
||||
private <T> void mapAbsoluteValuesToPercentages(Map<T, Integer> source,
|
||||
Map<T, BigDecimal> dest) {
|
||||
private <T> void mapAbsoluteValuesToPercentages(Map<T, Integer> source, Map<T, BigDecimal> dest) {
|
||||
int totalTasks = countTasksInAResultMap(source);
|
||||
for (Map.Entry<T, Integer> entry : source.entrySet()) {
|
||||
BigDecimal percentage;
|
||||
if (totalTasks == 0) {
|
||||
if ( totalTasks == 0 ) {
|
||||
percentage = BigDecimal.ZERO;
|
||||
|
||||
} else {
|
||||
|
|
@ -511,18 +502,18 @@ public class DashboardModel implements IDashboardModel {
|
|||
}
|
||||
|
||||
private int countTasksInAResultMap(Map<? extends Object, Integer> map) {
|
||||
/*
|
||||
* It's only needed to count the number of tasks once each time setOrder
|
||||
* is called.
|
||||
*/
|
||||
if (this.taskCount != null) {
|
||||
|
||||
// It's only needed to count the number of tasks once each time setOrder is called.
|
||||
if ( this.taskCount != null ) {
|
||||
return this.taskCount.intValue();
|
||||
}
|
||||
|
||||
int sum = 0;
|
||||
for (Object count : map.values()) {
|
||||
sum += (Integer) count;
|
||||
}
|
||||
this.taskCount = new Integer(sum);
|
||||
this.taskCount = sum;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
|
@ -534,36 +525,32 @@ public class DashboardModel implements IDashboardModel {
|
|||
@Override
|
||||
public BigDecimal getOvertimeRatio() {
|
||||
EffortDuration totalLoad = sumAll(resourceLoadCalculator.getAllLoad());
|
||||
EffortDuration overload = sumAll(resourceLoadCalculator
|
||||
.getAllOverload());
|
||||
return overload.dividedByAndResultAsBigDecimal(totalLoad).setScale(2,
|
||||
RoundingMode.HALF_UP);
|
||||
EffortDuration overload = sumAll(resourceLoadCalculator.getAllOverload());
|
||||
|
||||
return overload.dividedByAndResultAsBigDecimal(totalLoad).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
private EffortDuration sumAll(
|
||||
ContiguousDaysLine<EffortDuration> contiguousDays) {
|
||||
private EffortDuration sumAll(ContiguousDaysLine<EffortDuration> contiguousDays) {
|
||||
EffortDuration result = EffortDuration.zero();
|
||||
Iterator<OnDay<EffortDuration>> iterator = contiguousDays
|
||||
.iterator();
|
||||
Iterator<OnDay<EffortDuration>> iterator = contiguousDays.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
OnDay<EffortDuration> value = iterator.next();
|
||||
EffortDuration effort = value.getValue();
|
||||
result = EffortDuration.sum(result, effort);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getAvailabilityRatio() {
|
||||
EffortDuration totalLoad = sumAll(resourceLoadCalculator.getAllLoad());
|
||||
EffortDuration overload = sumAll(resourceLoadCalculator
|
||||
.getAllOverload());
|
||||
EffortDuration overload = sumAll(resourceLoadCalculator.getAllOverload());
|
||||
EffortDuration load = totalLoad.minus(overload);
|
||||
EffortDuration capacity = sumAll(resourceLoadCalculator.getMaxCapacityOnResources());
|
||||
|
||||
EffortDuration capacity = sumAll(resourceLoadCalculator
|
||||
.getMaxCapacityOnResources());
|
||||
return BigDecimal.ONE.setScale(2, RoundingMode.HALF_UP).subtract(
|
||||
load.dividedByAndResultAsBigDecimal(capacity));
|
||||
return BigDecimal.ONE.setScale(2, RoundingMode.HALF_UP).subtract(load.dividedByAndResultAsBigDecimal(capacity));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,8 +79,7 @@ import org.zkoss.zul.api.Popup;
|
|||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PersonalTimesheetController extends GenericForwardComposer
|
||||
implements IPersonalTimesheetController {
|
||||
public class PersonalTimesheetController extends GenericForwardComposer implements IPersonalTimesheetController {
|
||||
|
||||
private final static String EFFORT_DURATION_TEXTBOX_WIDTH = "30px";
|
||||
private final static String TOTAL_DURATION_TEXTBOX_WIDTH = "50px";
|
||||
|
|
@ -142,29 +141,32 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
initPersonalTimesheetDates();
|
||||
|
||||
switch (personalTimesheetRow.getType()) {
|
||||
case ORDER_ELEMENT:
|
||||
renderOrderElementRow(row,
|
||||
personalTimesheetRow.getOrderElemement());
|
||||
break;
|
||||
case OTHER:
|
||||
renderOtherRow(row);
|
||||
break;
|
||||
case CAPACITY:
|
||||
renderCapacityRow(row);
|
||||
break;
|
||||
case TOTAL:
|
||||
renderTotalRow(row);
|
||||
break;
|
||||
case EXTRA:
|
||||
renderExtraRow(row);
|
||||
case ORDER_ELEMENT:
|
||||
renderOrderElementRow(row, personalTimesheetRow.getOrderElemement());
|
||||
break;
|
||||
|
||||
// This is the last row so we can load the info in the summary
|
||||
updateSummary();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException(
|
||||
"Unknown PersonalTimesheetRow type: "
|
||||
+ personalTimesheetRow.getType());
|
||||
case OTHER:
|
||||
renderOtherRow(row);
|
||||
break;
|
||||
|
||||
case CAPACITY:
|
||||
renderCapacityRow(row);
|
||||
break;
|
||||
|
||||
case TOTAL:
|
||||
renderTotalRow(row);
|
||||
break;
|
||||
|
||||
case EXTRA:
|
||||
renderExtraRow(row);
|
||||
|
||||
// This is the last row so we can load the info in the summary
|
||||
updateSummary();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException(
|
||||
"Unknown PersonalTimesheetRow type: " + personalTimesheetRow.getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -174,81 +176,78 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private void renderOrderElementRow(Row row, OrderElement orderElement) {
|
||||
Util.appendLabel(row, personalTimesheetModel.getOrder(orderElement)
|
||||
.getName());
|
||||
Util.appendLabel(row, personalTimesheetModel.getOrder(orderElement).getName());
|
||||
Util.appendLabel(row, orderElement.getName());
|
||||
|
||||
appendInputsForDays(row, orderElement);
|
||||
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||
appendOtherColumn(row, orderElement);
|
||||
}
|
||||
|
||||
appendTotalColumn(row, orderElement);
|
||||
}
|
||||
|
||||
private void appendInputsForDays(Row row,
|
||||
final OrderElement orderElement) {
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
private void appendInputsForDays(Row row, final OrderElement orderElement) {
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||
final LocalDate textboxDate = day;
|
||||
|
||||
final Textbox textbox = new Textbox();
|
||||
textbox.setHflex("true");
|
||||
|
||||
Util.bind(textbox, new Util.Getter<String>() {
|
||||
@Override
|
||||
public String get() {
|
||||
EffortDuration effortDuration = personalTimesheetModel
|
||||
.getEffortDuration(orderElement, textboxDate);
|
||||
return effortDurationToString(effortDuration);
|
||||
}
|
||||
}, new Util.Setter<String>() {
|
||||
@Override
|
||||
public void set(String value) {
|
||||
EffortDuration effortDuration = effortDurationFromString(value);
|
||||
if (effortDuration == null) {
|
||||
throw new WrongValueException(textbox,
|
||||
_("Invalid Effort Duration"));
|
||||
}
|
||||
personalTimesheetModel.setEffortDuration(orderElement,
|
||||
textboxDate, effortDuration);
|
||||
markAsModified(textbox);
|
||||
updateTotals(orderElement, textboxDate);
|
||||
}
|
||||
Util.bind(
|
||||
textbox,
|
||||
new Util.Getter<String>() {
|
||||
@Override
|
||||
public String get() {
|
||||
|
||||
private void updateTotals(OrderElement orderElement,
|
||||
LocalDate date) {
|
||||
updateTotalColumn(orderElement);
|
||||
updateTotalRow(date);
|
||||
updateExtraRow(date);
|
||||
updateTotalColumn();
|
||||
updateTotalExtraColumn();
|
||||
updateSummary();
|
||||
}
|
||||
EffortDuration effortDuration =
|
||||
personalTimesheetModel.getEffortDuration(orderElement, textboxDate);
|
||||
|
||||
});
|
||||
return effortDurationToString(effortDuration);
|
||||
}
|
||||
},
|
||||
new Util.Setter<String>() {
|
||||
@Override
|
||||
public void set(String value) {
|
||||
EffortDuration effortDuration = effortDurationFromString(value);
|
||||
|
||||
if ( effortDuration == null ) {
|
||||
throw new WrongValueException(textbox, _("Invalid Effort Duration"));
|
||||
}
|
||||
|
||||
personalTimesheetModel.setEffortDuration(orderElement, textboxDate, effortDuration);
|
||||
markAsModified(textbox);
|
||||
updateTotals(orderElement, textboxDate);
|
||||
}
|
||||
|
||||
private void updateTotals(OrderElement orderElement, LocalDate date) {
|
||||
updateTotalColumn(orderElement);
|
||||
updateTotalRow(date);
|
||||
updateExtraRow(date);
|
||||
updateTotalColumn();
|
||||
updateTotalExtraColumn();
|
||||
updateSummary();
|
||||
}
|
||||
});
|
||||
|
||||
EventListener openPersonalTimesheetPopup = new EventListener() {
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
openPersonalTimesheetPopup(textbox,
|
||||
orderElement, textboxDate);
|
||||
openPersonalTimesheetPopup(textbox, orderElement, textboxDate);
|
||||
}
|
||||
|
||||
};
|
||||
textbox.addEventListener(Events.ON_DOUBLE_CLICK,
|
||||
openPersonalTimesheetPopup);
|
||||
textbox.addEventListener(Events.ON_OK,
|
||||
openPersonalTimesheetPopup);
|
||||
|
||||
if (personalTimesheetModel
|
||||
.wasModified(orderElement, textboxDate)) {
|
||||
textbox.addEventListener(Events.ON_DOUBLE_CLICK, openPersonalTimesheetPopup);
|
||||
textbox.addEventListener(Events.ON_OK, openPersonalTimesheetPopup);
|
||||
|
||||
if ( personalTimesheetModel.wasModified(orderElement, textboxDate) ) {
|
||||
markAsModified(textbox);
|
||||
}
|
||||
|
||||
Cell cell = getCenteredCell(textbox);
|
||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
if ( personalTimesheetModel.getResourceCapacity(day).isZero() ) {
|
||||
setBackgroundNonCapacityCell(cell);
|
||||
}
|
||||
row.appendChild(cell);
|
||||
|
|
@ -256,64 +255,71 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
|
||||
}
|
||||
|
||||
private void openPersonalTimesheetPopup(Textbox textbox,
|
||||
OrderElement orderElement, LocalDate textboxDate) {
|
||||
Textbox toFocus = setupPersonalTimesheetPopup(textbox,
|
||||
orderElement, textboxDate);
|
||||
private void openPersonalTimesheetPopup(Textbox textbox, OrderElement orderElement, LocalDate textboxDate) {
|
||||
Textbox toFocus = setupPersonalTimesheetPopup(textbox, orderElement, textboxDate);
|
||||
personalTimesheetPopup.open(textbox, "after_start");
|
||||
toFocus.setFocus(true);
|
||||
}
|
||||
|
||||
private Textbox setupPersonalTimesheetPopup(final Textbox textbox,
|
||||
final OrderElement orderElement, final LocalDate textboxDate) {
|
||||
private Textbox setupPersonalTimesheetPopup(final Textbox textbox, final OrderElement orderElement,
|
||||
final LocalDate textboxDate) {
|
||||
|
||||
personalTimesheetPopupTask.setValue(orderElement.getName());
|
||||
personalTimesheetPopupDate.setValue(textboxDate.toString());
|
||||
|
||||
personalTimesheetPopupEffort.getChildren().clear();
|
||||
Textbox effortTextbox = Util.bind(new Textbox(),
|
||||
|
||||
Textbox effortTextbox = Util.bind(
|
||||
new Textbox(),
|
||||
new Util.Getter<String>() {
|
||||
@Override
|
||||
public String get() {
|
||||
EffortDuration effortDuration = personalTimesheetModel
|
||||
.getEffortDuration(orderElement, textboxDate);
|
||||
return effortDurationToString(effortDuration);
|
||||
}
|
||||
}, new Util.Setter<String>() {
|
||||
@Override
|
||||
public void set(String value) {
|
||||
EffortDuration effortDuration = effortDurationFromString(value);
|
||||
if (effortDuration == null) {
|
||||
throw new WrongValueException(
|
||||
personalTimesheetPopupEffort,
|
||||
_("Invalid Effort Duration"));
|
||||
}
|
||||
Events.sendEvent(new InputEvent(Events.ON_CHANGE, textbox,
|
||||
value));
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public String get() {
|
||||
|
||||
EffortDuration effortDuration =
|
||||
personalTimesheetModel.getEffortDuration(orderElement, textboxDate);
|
||||
|
||||
return effortDurationToString(effortDuration);
|
||||
}
|
||||
},
|
||||
new Util.Setter<String>() {
|
||||
@Override
|
||||
public void set(String value) {
|
||||
EffortDuration effortDuration = effortDurationFromString(value);
|
||||
|
||||
if ( effortDuration == null ) {
|
||||
throw new WrongValueException(
|
||||
personalTimesheetPopupEffort, _("Invalid Effort Duration"));
|
||||
}
|
||||
|
||||
Events.sendEvent(new InputEvent(Events.ON_CHANGE, textbox, value));
|
||||
}
|
||||
});
|
||||
|
||||
addOnOkEventToClosePopup(effortTextbox);
|
||||
personalTimesheetPopupEffort.appendChild(effortTextbox);
|
||||
|
||||
personalTimesheetPopupFinished.getChildren().clear();
|
||||
Checkbox finishedCheckbox = Util.bind(new Checkbox(),
|
||||
|
||||
Checkbox finishedCheckbox = Util.bind(
|
||||
new Checkbox(),
|
||||
new Util.Getter<Boolean>() {
|
||||
@Override
|
||||
public Boolean get() {
|
||||
return personalTimesheetModel.isFinished(
|
||||
orderElement, textboxDate);
|
||||
return personalTimesheetModel.isFinished(orderElement, textboxDate);
|
||||
}
|
||||
}, new Util.Setter<Boolean>() {
|
||||
},
|
||||
new Util.Setter<Boolean>() {
|
||||
@Override
|
||||
public void set(Boolean value) {
|
||||
personalTimesheetModel.setFinished(orderElement,
|
||||
textboxDate, value);
|
||||
personalTimesheetModel.setFinished(orderElement, textboxDate, value);
|
||||
markAsModified(textbox);
|
||||
}
|
||||
});
|
||||
if (!finishedCheckbox.isChecked()) {
|
||||
finishedCheckbox.setDisabled(personalTimesheetModel
|
||||
.isFinished(orderElement));
|
||||
|
||||
if ( !finishedCheckbox.isChecked() ) {
|
||||
finishedCheckbox.setDisabled(personalTimesheetModel.isFinished(orderElement));
|
||||
}
|
||||
|
||||
addOnOkEventToClosePopup(finishedCheckbox);
|
||||
personalTimesheetPopupFinished.appendChild(finishedCheckbox);
|
||||
|
||||
|
|
@ -321,8 +327,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private boolean addOnOkEventToClosePopup(Component component) {
|
||||
return component.addEventListener(Events.ON_OK,
|
||||
new EventListener() {
|
||||
return component.addEventListener(Events.ON_OK, new EventListener() {
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
closePersonalTimesheetPopup();
|
||||
|
|
@ -346,13 +351,10 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private void updateTotalColumn(OrderElement orderElement) {
|
||||
EffortDuration effort = personalTimesheetModel
|
||||
.getEffortDuration(orderElement);
|
||||
effort = effort.plus(personalTimesheetModel
|
||||
.getOtherEffortDuration(orderElement));
|
||||
EffortDuration effort = personalTimesheetModel.getEffortDuration(orderElement);
|
||||
effort = effort.plus(personalTimesheetModel.getOtherEffortDuration(orderElement));
|
||||
|
||||
Textbox textbox = (Textbox) timesheet
|
||||
.getFellow(getTotalRowTextboxId(orderElement));
|
||||
Textbox textbox = (Textbox) timesheet.getFellow(getTotalRowTextboxId(orderElement));
|
||||
textbox.setValue(effortDurationToString(effort));
|
||||
}
|
||||
|
||||
|
|
@ -373,12 +375,13 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private void appendTotalForDays(Row row) {
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||
Cell cell = getCenteredCell(getDisabledTextbox(getTotalColumnTextboxId(day)));
|
||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
|
||||
if ( personalTimesheetModel.getResourceCapacity(day).isZero() ) {
|
||||
setBackgroundNonCapacityCell(cell);
|
||||
}
|
||||
|
||||
row.appendChild(cell);
|
||||
|
||||
updateTotalRow(day);
|
||||
|
|
@ -386,33 +389,29 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private void updateTotalRow(LocalDate date) {
|
||||
EffortDuration effort = personalTimesheetModel
|
||||
.getEffortDuration(date);
|
||||
effort = effort.plus(personalTimesheetModel
|
||||
.getOtherEffortDuration(date));
|
||||
EffortDuration effort = personalTimesheetModel.getEffortDuration(date);
|
||||
effort = effort.plus(personalTimesheetModel.getOtherEffortDuration(date));
|
||||
|
||||
Textbox textbox = (Textbox) timesheet
|
||||
.getFellow(getTotalColumnTextboxId(date));
|
||||
Textbox textbox = (Textbox) timesheet.getFellow(getTotalColumnTextboxId(date));
|
||||
textbox.setValue(effortDurationToString(effort));
|
||||
}
|
||||
|
||||
private void appendTotalColumn(Row row) {
|
||||
Cell totalCell = getCenteredCell(getDisabledTextbox(getTotalTextboxId()));
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
|
||||
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||
totalCell.setColspan(2);
|
||||
}
|
||||
|
||||
row.appendChild(totalCell);
|
||||
updateTotalColumn();
|
||||
}
|
||||
|
||||
private void updateTotalColumn() {
|
||||
EffortDuration effort = personalTimesheetModel
|
||||
.getTotalEffortDuration();
|
||||
effort = effort.plus(personalTimesheetModel
|
||||
.getTotalOtherEffortDuration());
|
||||
EffortDuration effort = personalTimesheetModel.getTotalEffortDuration();
|
||||
effort = effort.plus(personalTimesheetModel.getTotalOtherEffortDuration());
|
||||
|
||||
Textbox textbox = (Textbox) timesheet
|
||||
.getFellow(getTotalTextboxId());
|
||||
Textbox textbox = (Textbox) timesheet.getFellow(getTotalTextboxId());
|
||||
textbox.setValue(effortDurationToString(effort));
|
||||
}
|
||||
|
||||
|
|
@ -424,23 +423,21 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
private void appendOtherForDaysAndTotal(Row row) {
|
||||
EffortDuration totalOther = EffortDuration.zero();
|
||||
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
EffortDuration other = personalTimesheetModel
|
||||
.getOtherEffortDuration(day);
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||
EffortDuration other = personalTimesheetModel.getOtherEffortDuration(day);
|
||||
|
||||
Cell cell = getCenteredCell(getDisabledTextbox(
|
||||
getOtherColumnTextboxId(day), other));
|
||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
Cell cell = getCenteredCell(getDisabledTextbox(getOtherColumnTextboxId(day), other));
|
||||
|
||||
if ( personalTimesheetModel.getResourceCapacity(day).isZero() ) {
|
||||
setBackgroundNonCapacityCell(cell);
|
||||
}
|
||||
|
||||
row.appendChild(cell);
|
||||
|
||||
totalOther = totalOther.plus(other);
|
||||
}
|
||||
|
||||
Cell totalOtherCell = getCenteredCell(getDisabledTextbox(
|
||||
getTotalOtherTextboxId(), totalOther));
|
||||
Cell totalOtherCell = getCenteredCell(getDisabledTextbox(getTotalOtherTextboxId(), totalOther));
|
||||
totalOtherCell.setColspan(2);
|
||||
row.appendChild(totalOtherCell);
|
||||
}
|
||||
|
|
@ -453,26 +450,26 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
private void appendCapcityForDaysAndTotal(Row row) {
|
||||
EffortDuration totalCapacity = EffortDuration.zero();
|
||||
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
EffortDuration capacity = personalTimesheetModel
|
||||
.getResourceCapacity(day);
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||
EffortDuration capacity = personalTimesheetModel.getResourceCapacity(day);
|
||||
|
||||
Cell cell = getCenteredCell(getDisabledTextbox(
|
||||
getCapcityColumnTextboxId(day), capacity));
|
||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
Cell cell = getCenteredCell(getDisabledTextbox(getCapcityColumnTextboxId(day), capacity));
|
||||
|
||||
if ( personalTimesheetModel.getResourceCapacity(day).isZero() ) {
|
||||
setBackgroundNonCapacityCell(cell);
|
||||
}
|
||||
|
||||
row.appendChild(cell);
|
||||
|
||||
totalCapacity = totalCapacity.plus(capacity);
|
||||
}
|
||||
|
||||
Cell totalCapacityCell = getCenteredCell(getDisabledTextbox(
|
||||
getTotalCapacityTextboxId(), totalCapacity));
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
Cell totalCapacityCell = getCenteredCell(getDisabledTextbox(getTotalCapacityTextboxId(), totalCapacity));
|
||||
|
||||
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||
totalCapacityCell.setColspan(2);
|
||||
}
|
||||
|
||||
row.appendChild(totalCapacityCell);
|
||||
}
|
||||
|
||||
|
|
@ -483,12 +480,13 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private void appendExtraForDays(Row row) {
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||
Cell cell = getCenteredCell(getDisabledTextbox(getExtraColumnTextboxId(day)));
|
||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
|
||||
if ( personalTimesheetModel.getResourceCapacity(day).isZero() ) {
|
||||
setBackgroundNonCapacityCell(cell);
|
||||
}
|
||||
|
||||
row.appendChild(cell);
|
||||
|
||||
updateExtraRow(day);
|
||||
|
|
@ -501,40 +499,39 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
EffortDuration capacity = getEffortDuration(getCapcityColumnTextboxId(date));
|
||||
|
||||
EffortDuration extra = EffortDuration.zero();
|
||||
if (total.compareTo(capacity) > 0) {
|
||||
if ( total.compareTo(capacity) > 0 ) {
|
||||
extra = total.minus(capacity);
|
||||
}
|
||||
|
||||
Textbox textbox = (Textbox) timesheet
|
||||
.getFellow(getExtraColumnTextboxId(date));
|
||||
Textbox textbox = (Textbox) timesheet.getFellow(getExtraColumnTextboxId(date));
|
||||
textbox.setValue(effortDurationToString(extra));
|
||||
}
|
||||
|
||||
private EffortDuration getEffortDuration(String textboxId) {
|
||||
String value = ((Textbox) timesheet.getFellow(textboxId))
|
||||
.getValue();
|
||||
String value = ((Textbox) timesheet.getFellow(textboxId)).getValue();
|
||||
|
||||
return effortDurationFromString(value);
|
||||
}
|
||||
|
||||
private void appendTotalExtra(Row row) {
|
||||
Cell totalExtraCell = getCenteredCell(getDisabledTextbox(getTotalExtraTextboxId()));
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
|
||||
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||
totalExtraCell.setColspan(2);
|
||||
}
|
||||
|
||||
row.appendChild(totalExtraCell);
|
||||
updateTotalExtraColumn();
|
||||
}
|
||||
|
||||
private void updateTotalExtraColumn() {
|
||||
EffortDuration totalExtra = EffortDuration.zero();
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||
EffortDuration extra = getEffortDuration(getExtraColumnTextboxId(day));
|
||||
totalExtra = totalExtra.plus(extra);
|
||||
}
|
||||
|
||||
Textbox textbox = (Textbox) timesheet
|
||||
.getFellow(getTotalExtraTextboxId());
|
||||
Textbox textbox = (Textbox) timesheet.getFellow(getTotalExtraTextboxId());
|
||||
textbox.setValue(effortDurationToString(totalExtra));
|
||||
}
|
||||
|
||||
|
|
@ -543,12 +540,14 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
textbox.setHflex("true");
|
||||
textbox.setId(id);
|
||||
textbox.setDisabled(true);
|
||||
|
||||
return textbox;
|
||||
}
|
||||
|
||||
private Textbox getDisabledTextbox(String id, EffortDuration effort) {
|
||||
Textbox textbox = getDisabledTextbox(id);
|
||||
textbox.setValue(effortDurationToString(effort));
|
||||
|
||||
return textbox;
|
||||
}
|
||||
|
||||
|
|
@ -556,6 +555,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
Cell cell = new Cell();
|
||||
cell.setAlign("center");
|
||||
cell.appendChild(component);
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
|
@ -563,6 +563,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
Cell cell = new Cell();
|
||||
cell.setAlign("left");
|
||||
cell.appendChild(component);
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
|
@ -582,31 +583,31 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
|
||||
checkUserComesFromEntryPointsOrSendForbiddenCode();
|
||||
|
||||
URLHandlerRegistry.getRedirectorFor(IPersonalTimesheetController.class)
|
||||
.register(this, page);
|
||||
URLHandlerRegistry.getRedirectorFor(IPersonalTimesheetController.class).register(this, page);
|
||||
}
|
||||
|
||||
private void adjustFrozenWidth() {
|
||||
// Hack to reduce frozen scrollarea
|
||||
// Hack to reduce frozen scroll area
|
||||
Clients.evalJavaScript("jq('.z-frozen-inner div').width(jq('.totals-column').offset().left);");
|
||||
}
|
||||
|
||||
private void checkUserComesFromEntryPointsOrSendForbiddenCode() {
|
||||
HttpServletRequest request = (HttpServletRequest) Executions
|
||||
.getCurrent().getNativeRequest();
|
||||
HttpServletRequest request = (HttpServletRequest) Executions.getCurrent().getNativeRequest();
|
||||
Map<String, String> matrixParams = MatrixParameters.extract(request);
|
||||
|
||||
// If it doesn't come from a entry point
|
||||
if (matrixParams.isEmpty()) {
|
||||
if ( matrixParams.isEmpty() ) {
|
||||
Util.sendForbiddenStatusCodeInHttpServletResponse();
|
||||
}
|
||||
}
|
||||
|
||||
private void setBreadcrumbs(Component comp) {
|
||||
Component breadcrumbs = comp.getPage().getFellow("breadcrumbs");
|
||||
if (breadcrumbs.getChildren() != null) {
|
||||
|
||||
if ( breadcrumbs.getChildren() != null ) {
|
||||
breadcrumbs.getChildren().clear();
|
||||
}
|
||||
|
||||
breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR));
|
||||
breadcrumbs.appendChild(new Label(_("My account")));
|
||||
breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR));
|
||||
|
|
@ -617,7 +618,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
|
||||
@Override
|
||||
public void goToCreateOrEditForm(LocalDate date) {
|
||||
if (!SecurityUtils.isUserInRole(UserRole.ROLE_BOUND_USER)) {
|
||||
if ( !SecurityUtils.isUserInRole(UserRole.ROLE_BOUND_USER) ) {
|
||||
Util.sendForbiddenStatusCodeInHttpServletResponse();
|
||||
}
|
||||
|
||||
|
|
@ -627,8 +628,9 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
|
||||
@Override
|
||||
public void goToCreateOrEditFormForResource(LocalDate date,
|
||||
org.libreplan.business.resources.entities.Resource resource) {
|
||||
if (!SecurityUtils.isSuperuserOrUserInRoles(UserRole.ROLE_TIMESHEETS)) {
|
||||
org.libreplan.business.resources.entities.Resource resource) {
|
||||
|
||||
if ( !SecurityUtils.isSuperuserOrUserInRoles(UserRole.ROLE_TIMESHEETS) ) {
|
||||
Util.sendForbiddenStatusCodeInHttpServletResponse();
|
||||
}
|
||||
|
||||
|
|
@ -653,9 +655,11 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
private void createColumns(LocalDate date) {
|
||||
createProjectAndTaskColumns();
|
||||
createColumnsForDays(date);
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
|
||||
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||
createOtherColumn();
|
||||
}
|
||||
|
||||
createTotalColumn();
|
||||
}
|
||||
|
||||
|
|
@ -672,13 +676,10 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private void createColumnsForDays(LocalDate date) {
|
||||
LocalDate start = personalTimesheetModel
|
||||
.getPersonalTimesheetsPeriodicity().getStart(date);
|
||||
LocalDate end = personalTimesheetModel
|
||||
.getPersonalTimesheetsPeriodicity().getEnd(date);
|
||||
LocalDate start = personalTimesheetModel.getPersonalTimesheetsPeriodicity().getStart(date);
|
||||
LocalDate end = personalTimesheetModel.getPersonalTimesheetsPeriodicity().getEnd(date);
|
||||
|
||||
for (LocalDate day = start; day.compareTo(end) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
for (LocalDate day = start; day.compareTo(end) <= 0; day = day.plusDays(1)) {
|
||||
Column column = new Column(day.getDayOfMonth() + "");
|
||||
column.setAlign("center");
|
||||
column.setWidth(EFFORT_DURATION_TEXTBOX_WIDTH);
|
||||
|
|
@ -711,15 +712,15 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
public List<PersonalTimesheetRow> getRows() {
|
||||
List<PersonalTimesheetRow> result = PersonalTimesheetRow
|
||||
.wrap(personalTimesheetModel
|
||||
.getOrderElements());
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
List<PersonalTimesheetRow> result = PersonalTimesheetRow.wrap(personalTimesheetModel.getOrderElements());
|
||||
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||
result.add(PersonalTimesheetRow.createOtherRow());
|
||||
}
|
||||
|
||||
result.add(PersonalTimesheetRow.createTotalRow());
|
||||
result.add(PersonalTimesheetRow.createCapacityRow());
|
||||
result.add(PersonalTimesheetRow.createExtraRow());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -729,22 +730,24 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
|
||||
public void save() {
|
||||
personalTimesheetModel.save();
|
||||
String url = IndexController.USER_DASHBOARD_URL
|
||||
+ "?timesheet_saved=" + personalTimesheetModel.getDate();
|
||||
if (!personalTimesheetModel.isCurrentUser()) {
|
||||
String url = IndexController.USER_DASHBOARD_URL + "?timesheet_saved=" + personalTimesheetModel.getDate();
|
||||
|
||||
if ( !personalTimesheetModel.isCurrentUser() ) {
|
||||
url = WORK_REPORTS_URL + "?timesheet_saved=true";
|
||||
}
|
||||
|
||||
Executions.getCurrent().sendRedirect(url);
|
||||
}
|
||||
|
||||
public void saveAndContinue() {
|
||||
personalTimesheetModel.save();
|
||||
if (personalTimesheetModel.isCurrentUser()) {
|
||||
|
||||
if ( personalTimesheetModel.isCurrentUser() ) {
|
||||
goToCreateOrEditForm(personalTimesheetModel.getDate());
|
||||
} else {
|
||||
goToCreateOrEditFormForResource(personalTimesheetModel.getDate(),
|
||||
personalTimesheetModel.getWorker());
|
||||
goToCreateOrEditFormForResource(personalTimesheetModel.getDate(), personalTimesheetModel.getWorker());
|
||||
}
|
||||
|
||||
messagesForUser.showMessage(Level.INFO, _("Personal timesheet saved"));
|
||||
Util.reloadBindings(timesheet);
|
||||
}
|
||||
|
|
@ -752,16 +755,17 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
public void cancel() {
|
||||
personalTimesheetModel.cancel();
|
||||
String url = IndexController.USER_DASHBOARD_URL;
|
||||
if (!personalTimesheetModel.isCurrentUser()) {
|
||||
|
||||
if ( !personalTimesheetModel.isCurrentUser() ) {
|
||||
url = WORK_REPORTS_URL;
|
||||
}
|
||||
|
||||
Executions.getCurrent().sendRedirect(url);
|
||||
}
|
||||
|
||||
public void addOrderElement() {
|
||||
OrderElement orderElement = (OrderElement) orderElementBandboxSearch
|
||||
.getSelectedElement();
|
||||
if (orderElement != null) {
|
||||
OrderElement orderElement = (OrderElement) orderElementBandboxSearch.getSelectedElement();
|
||||
if ( orderElement != null ) {
|
||||
personalTimesheetModel.addOrderElement(orderElement);
|
||||
orderElementBandboxSearch.setSelectedElement(null);
|
||||
Util.reloadBindings(timesheet);
|
||||
|
|
@ -778,18 +782,17 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
public void previousPeriod() {
|
||||
if (personalTimesheetModel.isModified()) {
|
||||
throw new WrongValueException(
|
||||
previousPeriod,
|
||||
if ( personalTimesheetModel.isModified() ) {
|
||||
throw new WrongValueException(previousPeriod,
|
||||
_("There are unsaved changes in the current personal timesheet, please save before moving"));
|
||||
}
|
||||
|
||||
sendToPersonalTimesheet(personalTimesheetModel.getPrevious());
|
||||
}
|
||||
|
||||
public void nextPeriod() {
|
||||
if (personalTimesheetModel.isModified()) {
|
||||
throw new WrongValueException(
|
||||
nextPeriod,
|
||||
if ( personalTimesheetModel.isModified() ) {
|
||||
throw new WrongValueException(nextPeriod,
|
||||
_("There are unsaved changes in the current personal timesheet, please save before moving"));
|
||||
}
|
||||
|
||||
|
|
@ -803,6 +806,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
personalTimesheetController.goToCreateOrEditForm(date);
|
||||
}
|
||||
});
|
||||
|
||||
Executions.getCurrent().sendRedirect(capturePath);
|
||||
}
|
||||
|
||||
|
|
@ -855,7 +859,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private static String effortDurationToString(EffortDuration effort) {
|
||||
if (effort == null || effort.isZero()) {
|
||||
if ( effort == null || effort.isZero() ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
@ -863,19 +867,19 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private static EffortDuration effortDurationFromString(String effort) {
|
||||
if (StringUtils.isBlank(effort)) {
|
||||
if ( StringUtils.isBlank(effort) ) {
|
||||
return EffortDuration.zero();
|
||||
}
|
||||
|
||||
String decimalSeparator = ((DecimalFormat) DecimalFormat
|
||||
.getInstance(Locales.getCurrent()))
|
||||
.getDecimalFormatSymbols().getDecimalSeparator() + "";
|
||||
if (effort.contains(decimalSeparator) || effort.contains(".")) {
|
||||
|
||||
if ( effort.contains(decimalSeparator) || effort.contains(".") ) {
|
||||
try {
|
||||
effort = effort.replace(decimalSeparator, ".");
|
||||
double hours = Double.parseDouble(effort);
|
||||
return EffortDuration.fromHoursAsBigDecimal(new BigDecimal(
|
||||
hours));
|
||||
return EffortDuration.fromHoursAsBigDecimal(new BigDecimal(hours));
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -887,21 +891,23 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
public void updateSummary() {
|
||||
EffortDuration total = getEffortDurationFromTextbox(getTotalTextboxId());
|
||||
EffortDuration other = EffortDuration.zero();
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
|
||||
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||
other = getEffortDurationFromTextbox(getTotalOtherTextboxId());
|
||||
}
|
||||
|
||||
EffortDuration capacity = getEffortDurationFromTextbox(getTotalCapacityTextboxId());
|
||||
EffortDuration extraPerDay = getEffortDurationFromTextbox(getTotalExtraTextboxId());
|
||||
|
||||
EffortDuration timesheet = total.minus(other);
|
||||
EffortDuration extra = EffortDuration.zero();
|
||||
if (total.compareTo(capacity) > 0) {
|
||||
|
||||
if ( total.compareTo(capacity) > 0 ) {
|
||||
extra = total.minus(capacity);
|
||||
}
|
||||
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
summaryTotalPersonalTimesheet
|
||||
.setValue(timesheet.toFormattedString());
|
||||
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||
summaryTotalPersonalTimesheet.setValue(timesheet.toFormattedString());
|
||||
summaryTotalOther.setValue(other.toFormattedString());
|
||||
}
|
||||
|
||||
|
|
@ -912,8 +918,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private EffortDuration getEffortDurationFromTextbox(String id) {
|
||||
return effortDurationFromString(((Textbox) timesheet.getFellow(id))
|
||||
.getValue());
|
||||
return effortDurationFromString(((Textbox) timesheet.getFellow(id)).getValue());
|
||||
}
|
||||
|
||||
public boolean hasOtherReports() {
|
||||
|
|
@ -932,19 +937,19 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
|||
* This is used to mark the special rows like capacity and total.
|
||||
*/
|
||||
class PersonalTimesheetRow {
|
||||
|
||||
enum PersonalTimesheetRowType {
|
||||
ORDER_ELEMENT, OTHER, CAPACITY, TOTAL, EXTRA
|
||||
};
|
||||
}
|
||||
|
||||
private PersonalTimesheetRowType type;
|
||||
private OrderElement orderElemement;
|
||||
|
||||
public static PersonalTimesheetRow createOrderElementRow(
|
||||
OrderElement orderElemement) {
|
||||
PersonalTimesheetRow row = new PersonalTimesheetRow(
|
||||
PersonalTimesheetRowType.ORDER_ELEMENT);
|
||||
public static PersonalTimesheetRow createOrderElementRow(OrderElement orderElemement) {
|
||||
PersonalTimesheetRow row = new PersonalTimesheetRow(PersonalTimesheetRowType.ORDER_ELEMENT);
|
||||
Assert.notNull(orderElemement);
|
||||
row.orderElemement = orderElemement;
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
|
|
@ -964,12 +969,12 @@ class PersonalTimesheetRow {
|
|||
return new PersonalTimesheetRow(PersonalTimesheetRowType.EXTRA);
|
||||
}
|
||||
|
||||
public static List<PersonalTimesheetRow> wrap(
|
||||
List<OrderElement> orderElements) {
|
||||
List<PersonalTimesheetRow> result = new ArrayList<PersonalTimesheetRow>();
|
||||
public static List<PersonalTimesheetRow> wrap(List<OrderElement> orderElements) {
|
||||
List<PersonalTimesheetRow> result = new ArrayList<>();
|
||||
for (OrderElement each : orderElements) {
|
||||
result.add(createOrderElementRow(each));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
6
pom.xml
6
pom.xml
|
|
@ -390,9 +390,9 @@
|
|||
|
||||
<!-- Commons lang -->
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.4</version>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Commons Math-->
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue