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>
|
<artifactId>commons-logging</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-lang</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-collections</groupId>
|
<groupId>commons-collections</groupId>
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
package org.zkoss.ganttz;
|
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.ICommand;
|
||||||
import org.zkoss.ganttz.extensions.IContext;
|
import org.zkoss.ganttz.extensions.IContext;
|
||||||
import org.zkoss.zk.ui.event.Event;
|
import org.zkoss.zk.ui.event.Event;
|
||||||
|
|
@ -31,8 +31,7 @@ import org.zkoss.zul.Button;
|
||||||
|
|
||||||
class CommandContextualized<T> {
|
class CommandContextualized<T> {
|
||||||
|
|
||||||
public static <T> CommandContextualized<T> create(ICommand<T> command,
|
public static <T> CommandContextualized<T> create(ICommand<T> command, IContext<T> context) {
|
||||||
IContext<T> context) {
|
|
||||||
return new CommandContextualized<T>(command, context);
|
return new CommandContextualized<T>(command, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,28 +51,31 @@ class CommandContextualized<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Button toButton() {
|
Button toButton() {
|
||||||
if (button != null) {
|
if ( button != null ) {
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
Button result = new Button();
|
Button result = new Button();
|
||||||
if (StringUtils.isEmpty(command.getImage())) {
|
if ( StringUtils.isEmpty(command.getImage()) ) {
|
||||||
result.setLabel(command.getName());
|
result.setLabel(command.getName());
|
||||||
} else {
|
} else {
|
||||||
result.setImage(command.getImage());
|
result.setImage(command.getImage());
|
||||||
result.setTooltiptext(command.getName());
|
result.setTooltiptext(command.getName());
|
||||||
}
|
}
|
||||||
if (command.isDisabled()) {
|
|
||||||
|
if ( command.isDisabled() ) {
|
||||||
result.setDisabled(true);
|
result.setDisabled(true);
|
||||||
} else {
|
} else {
|
||||||
result.addEventListener(Events.ON_CLICK, new EventListener() {
|
result.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(Event event) {
|
public void onEvent(Event event) {
|
||||||
doAction();
|
doAction();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
button = result;
|
button = result;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,13 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.zkoss.ganttz;
|
package org.zkoss.ganttz;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
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.DateTime;
|
||||||
import org.joda.time.Duration;
|
import org.joda.time.Duration;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
|
@ -43,16 +41,13 @@ public class DatesMapperOnInterval implements IDatesMapper {
|
||||||
public DatesMapperOnInterval(int horizontalSize, Interval interval) {
|
public DatesMapperOnInterval(int horizontalSize, Interval interval) {
|
||||||
this.horizontalSize = horizontalSize;
|
this.horizontalSize = horizontalSize;
|
||||||
this.interval = interval;
|
this.interval = interval;
|
||||||
this.millisecondsPerPixel = interval.getLengthBetween().getMillis()
|
this.millisecondsPerPixel = interval.getLengthBetween().getMillis() / horizontalSize;
|
||||||
/ horizontalSize;
|
this.pixelsPerDay = Fraction.getFraction(horizontalSize, interval.getDaysBetween().getDays());
|
||||||
this.pixelsPerDay = Fraction.getFraction(horizontalSize, interval
|
|
||||||
.getDaysBetween().getDays());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDate toDate(int pixels) {
|
public LocalDate toDate(int pixels) {
|
||||||
int daysInto = Fraction.getFraction(pixels, 1).divideBy(pixelsPerDay)
|
int daysInto = Fraction.getFraction(pixels, 1).divideBy(pixelsPerDay).intValue();
|
||||||
.intValue();
|
|
||||||
return getInterval().getStart().plusDays(daysInto);
|
return getInterval().getStart().plusDays(daysInto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,29 +66,29 @@ public class DatesMapperOnInterval implements IDatesMapper {
|
||||||
|
|
||||||
private int toPixels(Fraction proportion) {
|
private int toPixels(Fraction proportion) {
|
||||||
try {
|
try {
|
||||||
return proportion.multiplyBy(Fraction.getFraction(horizontalSize, 1))
|
return proportion.multiplyBy(Fraction.getFraction(horizontalSize, 1)).intValue();
|
||||||
.intValue();
|
|
||||||
} catch (ArithmeticException e) {
|
} catch (ArithmeticException e) {
|
||||||
double d = Math.log10(horizontalSize);
|
double d = Math.log10(horizontalSize);
|
||||||
int scale = (int) d + 1;
|
int scale = (int) d + 1;
|
||||||
|
|
||||||
BigDecimal quotient = new BigDecimal(proportion.getNumerator())
|
BigDecimal quotient = new BigDecimal(proportion.getNumerator())
|
||||||
.divide(new BigDecimal(proportion.getDenominator()), scale,
|
.divide(new BigDecimal(proportion.getDenominator()), scale, RoundingMode.HALF_UP);
|
||||||
RoundingMode.HALF_UP);
|
|
||||||
return quotient.multiply(new BigDecimal(horizontalSize))
|
return quotient.multiply(new BigDecimal(horizontalSize)).intValue();
|
||||||
.intValue();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int toPixels(ReadableDuration duration) {
|
public int toPixels(ReadableDuration duration) {
|
||||||
DateTime end = getInterval().getStart().toDateTimeAtStartOfDay()
|
DateTime end = getInterval().getStart().toDateTimeAtStartOfDay().plus(duration);
|
||||||
.plus(duration);
|
|
||||||
return toPixels(getProportion(end));
|
return toPixels(getProportion(end));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int toPixelsAbsolute(long milliseconds) {
|
public int toPixelsAbsolute(long milliseconds) {
|
||||||
DateTime date = new DateTime(milliseconds);
|
DateTime date = new DateTime(milliseconds);
|
||||||
|
|
||||||
return this.toPixels(getProportion(date));
|
return this.toPixels(getProportion(date));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.IOException;
|
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.Dependency;
|
||||||
import org.zkoss.ganttz.data.DependencyType;
|
import org.zkoss.ganttz.data.DependencyType;
|
||||||
import org.zkoss.ganttz.data.GanttDate;
|
import org.zkoss.ganttz.data.GanttDate;
|
||||||
|
|
@ -62,13 +62,13 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
||||||
|
|
||||||
private boolean violated = false;
|
private boolean violated = false;
|
||||||
|
|
||||||
public DependencyComponent(TaskComponent source, TaskComponent destination,
|
public DependencyComponent(TaskComponent source, TaskComponent destination, Dependency dependency) {
|
||||||
Dependency dependency) {
|
|
||||||
Validate.notNull(dependency);
|
Validate.notNull(dependency);
|
||||||
Validate.notNull(source);
|
Validate.notNull(source);
|
||||||
Validate.notNull(destination);
|
Validate.notNull(destination);
|
||||||
Validate.isTrue(source.getTask() == dependency.getSource());
|
Validate.isTrue(source.getTask() == dependency.getSource());
|
||||||
Validate.isTrue(destination.getTask() == dependency.getDestination());
|
Validate.isTrue(destination.getTask() == dependency.getDestination());
|
||||||
|
|
||||||
this.type = dependency.getType();
|
this.type = dependency.getType();
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
|
|
@ -76,8 +76,7 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendCSSUpdate() {
|
private void sendCSSUpdate() {
|
||||||
response("constraintViolated", new AuInvoke(DependencyComponent.this,
|
response("constraintViolated", new AuInvoke(DependencyComponent.this, "setCSSClass", getCSSClass()));
|
||||||
"setCSSClass", getCSSClass()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCSSClass() {
|
public String getCSSClass() {
|
||||||
|
|
@ -88,9 +87,10 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterCompose() {
|
public void afterCompose() {
|
||||||
if (listenerAdded) {
|
if ( listenerAdded ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
listener = new PropertyChangeListener() {
|
listener = new PropertyChangeListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -98,11 +98,11 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
||||||
redrawDependency();
|
redrawDependency();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.source.getTask().addFundamentalPropertiesChangeListener(listener);
|
this.source.getTask().addFundamentalPropertiesChangeListener(listener);
|
||||||
this.destination.getTask().addFundamentalPropertiesChangeListener(listener);
|
this.destination.getTask().addFundamentalPropertiesChangeListener(listener);
|
||||||
|
|
||||||
violationListener = Constraint
|
violationListener = Constraint.onlyOnZKExecution(new IConstraintViolationListener<GanttDate>() {
|
||||||
.onlyOnZKExecution(new IConstraintViolationListener<GanttDate>() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void constraintViolated(Constraint<GanttDate> constraint, GanttDate value) {
|
public void constraintViolated(Constraint<GanttDate> constraint, GanttDate value) {
|
||||||
|
|
@ -116,16 +116,17 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
||||||
sendCSSUpdate();
|
sendCSSUpdate();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.dependency.addConstraintViolationListener(violationListener,
|
|
||||||
Mode.RECEIVE_PENDING);
|
this.dependency.addConstraintViolationListener(violationListener, Mode.RECEIVE_PENDING);
|
||||||
|
|
||||||
listenerAdded = true;
|
listenerAdded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeChangeListeners() {
|
public void removeChangeListeners() {
|
||||||
if (!listenerAdded) {
|
if ( !listenerAdded ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.source.getTask().removePropertyChangeListener(listener);
|
this.source.getTask().removePropertyChangeListener(listener);
|
||||||
this.destination.getTask().removePropertyChangeListener(listener);
|
this.destination.getTask().removePropertyChangeListener(listener);
|
||||||
listenerAdded = false;
|
listenerAdded = false;
|
||||||
|
|
@ -169,6 +170,7 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
||||||
public boolean contains(Task task) {
|
public boolean contains(Task task) {
|
||||||
Task sourceTask = getSource().getTask();
|
Task sourceTask = getSource().getTask();
|
||||||
Task destinationTask = getDestination().getTask();
|
Task destinationTask = getDestination().getTask();
|
||||||
|
|
||||||
return task.equals(sourceTask) || task.equals(destinationTask);
|
return task.equals(sourceTask) || task.equals(destinationTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,8 +193,8 @@ public class DependencyComponent extends XulElement implements AfterCompose {
|
||||||
public boolean hasSameSourceAndDestination(Dependency dependency) {
|
public boolean hasSameSourceAndDestination(Dependency dependency) {
|
||||||
Task sourceTask = source.getTask();
|
Task sourceTask = source.getTask();
|
||||||
Task destinationTask = destination.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{
|
protected void renderProperties(ContentRenderer renderer) throws IOException{
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
package org.zkoss.ganttz;
|
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.LocalDate;
|
||||||
import org.joda.time.ReadableDuration;
|
import org.joda.time.ReadableDuration;
|
||||||
import org.zkoss.ganttz.util.Interval;
|
import org.zkoss.ganttz.util.Interval;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
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.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
|
@ -71,8 +71,6 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
LeftTasksTreeRow getAboveRow();
|
LeftTasksTreeRow getAboveRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Log LOG = LogFactory.getLog(LeftTasksTreeRow.class);
|
|
||||||
|
|
||||||
private final Task task;
|
private final Task task;
|
||||||
|
|
||||||
private Label nameLabel;
|
private Label nameLabel;
|
||||||
|
|
@ -101,20 +99,22 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
|
|
||||||
private final IDisabilityConfiguration disabilityConfiguration;
|
private final IDisabilityConfiguration disabilityConfiguration;
|
||||||
|
|
||||||
public static LeftTasksTreeRow create(
|
public static LeftTasksTreeRow create(IDisabilityConfiguration disabilityConfiguration,
|
||||||
IDisabilityConfiguration disabilityConfiguration, Task bean,
|
Task bean,
|
||||||
ILeftTasksTreeNavigator taskDetailnavigator, Planner planner) {
|
ILeftTasksTreeNavigator taskDetailnavigator,
|
||||||
return new LeftTasksTreeRow(disabilityConfiguration, bean,
|
Planner planner) {
|
||||||
taskDetailnavigator, planner);
|
|
||||||
|
return new LeftTasksTreeRow(disabilityConfiguration, bean, taskDetailnavigator, planner);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LeftTasksTreeRow(IDisabilityConfiguration disabilityConfiguration,
|
private LeftTasksTreeRow(IDisabilityConfiguration disabilityConfiguration,
|
||||||
Task task, ILeftTasksTreeNavigator leftTasksTreeNavigator,
|
Task task,
|
||||||
|
ILeftTasksTreeNavigator leftTasksTreeNavigator,
|
||||||
Planner planner) {
|
Planner planner) {
|
||||||
|
|
||||||
this.disabilityConfiguration = disabilityConfiguration;
|
this.disabilityConfiguration = disabilityConfiguration;
|
||||||
this.task = task;
|
this.task = task;
|
||||||
this.dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locales
|
this.dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locales.getCurrent());
|
||||||
.getCurrent());
|
|
||||||
this.leftTasksTreeNavigator = leftTasksTreeNavigator;
|
this.leftTasksTreeNavigator = leftTasksTreeNavigator;
|
||||||
this.planner = planner;
|
this.planner = planner;
|
||||||
}
|
}
|
||||||
|
|
@ -143,13 +143,14 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
* the component that has received focus
|
* the component that has received focus
|
||||||
*/
|
*/
|
||||||
public void userWantsDateBox(Component component) {
|
public void userWantsDateBox(Component component) {
|
||||||
if (component == startDateTextBox) {
|
if ( component == startDateTextBox ) {
|
||||||
if (canChangeStartDate()) {
|
if ( canChangeStartDate() ) {
|
||||||
createDateBox(startDateTextBox);
|
createDateBox(startDateTextBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (component == endDateTextBox) {
|
|
||||||
if (canChangeEndDate()) {
|
if ( component == endDateTextBox ) {
|
||||||
|
if ( canChangeEndDate() ) {
|
||||||
createDateBox(endDateTextBox);
|
createDateBox(endDateTextBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -185,7 +186,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
|
|
||||||
public void focusGoUp(int position) {
|
public void focusGoUp(int position) {
|
||||||
LeftTasksTreeRow aboveDetail = leftTasksTreeNavigator.getAboveRow();
|
LeftTasksTreeRow aboveDetail = leftTasksTreeNavigator.getAboveRow();
|
||||||
if (aboveDetail != null) {
|
if ( aboveDetail != null ) {
|
||||||
aboveDetail.receiveFocus(position);
|
aboveDetail.receiveFocus(position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -200,7 +201,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
|
|
||||||
public void focusGoDown(int position) {
|
public void focusGoDown(int position) {
|
||||||
LeftTasksTreeRow belowDetail = leftTasksTreeNavigator.getBelowRow();
|
LeftTasksTreeRow belowDetail = leftTasksTreeNavigator.getBelowRow();
|
||||||
if (belowDetail != null) {
|
if ( belowDetail != null ) {
|
||||||
belowDetail.receiveFocus(position);
|
belowDetail.receiveFocus(position);
|
||||||
} else {
|
} else {
|
||||||
getListDetails().getGoingDownInLastArrowCommand().doAction();
|
getListDetails().getGoingDownInLastArrowCommand().doAction();
|
||||||
|
|
@ -212,6 +213,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
while (!(current instanceof LeftTasksTree)) {
|
while (!(current instanceof LeftTasksTree)) {
|
||||||
current = current.getParent();
|
current = current.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (LeftTasksTree) current;
|
return (LeftTasksTree) current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,9 +225,11 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
case UP:
|
case UP:
|
||||||
focusGoUp(position);
|
focusGoUp(position);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DOWN:
|
case DOWN:
|
||||||
focusGoDown(position);
|
focusGoDown(position);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("case not covered: " + navigation);
|
throw new RuntimeException("case not covered: " + navigation);
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +265,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerTextboxesListeners() {
|
private void registerTextboxesListeners() {
|
||||||
if (disabilityConfiguration.isTreeEditable()) {
|
if ( disabilityConfiguration.isTreeEditable() ) {
|
||||||
registerKeyboardListener(nameBox);
|
registerKeyboardListener(nameBox);
|
||||||
registerOnChange(nameBox);
|
registerOnChange(nameBox);
|
||||||
registerKeyboardListener(startDateTextBox);
|
registerKeyboardListener(startDateTextBox);
|
||||||
|
|
@ -275,9 +279,9 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
|
|
||||||
private void findComponents(Treerow row) {
|
private void findComponents(Treerow row) {
|
||||||
List<Object> rowChildren = row.getChildren();
|
List<Object> rowChildren = row.getChildren();
|
||||||
List<Treecell> treeCells = ComponentsFinder.findComponentsOfType(Treecell.class,
|
List<Treecell> treeCells = ComponentsFinder.findComponentsOfType(Treecell.class, rowChildren);
|
||||||
rowChildren);
|
|
||||||
assert treeCells.size() == 4;
|
assert treeCells.size() == 4;
|
||||||
|
|
||||||
findComponentsForNameCell(treeCells.get(0));
|
findComponentsForNameCell(treeCells.get(0));
|
||||||
findComponentsForStartDateCell(treeCells.get(1));
|
findComponentsForStartDateCell(treeCells.get(1));
|
||||||
findComponentsForEndDateCell(treeCells.get(2));
|
findComponentsForEndDateCell(treeCells.get(2));
|
||||||
|
|
@ -286,12 +290,11 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
|
|
||||||
private static Textbox findTextBoxOfCell(Treecell treecell) {
|
private static Textbox findTextBoxOfCell(Treecell treecell) {
|
||||||
List<Object> children = treecell.getChildren();
|
List<Object> children = treecell.getChildren();
|
||||||
return ComponentsFinder.findComponentsOfType(Textbox.class, children)
|
return ComponentsFinder.findComponentsOfType(Textbox.class, children).get(0);
|
||||||
.get(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findComponentsForNameCell(Treecell treecell) {
|
private void findComponentsForNameCell(Treecell treecell) {
|
||||||
if (disabilityConfiguration.isTreeEditable()) {
|
if ( disabilityConfiguration.isTreeEditable() ) {
|
||||||
nameBox = (Textbox) treecell.getChildren().get(0);
|
nameBox = (Textbox) treecell.getChildren().get(0);
|
||||||
} else {
|
} else {
|
||||||
nameLabel = (Label) treecell.getChildren().get(0);
|
nameLabel = (Label) treecell.getChildren().get(0);
|
||||||
|
|
@ -318,8 +321,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerOnChangeDatebox(final Datebox datebox,
|
private void registerOnChangeDatebox(final Datebox datebox, final Textbox textbox) {
|
||||||
final Textbox textbox) {
|
|
||||||
datebox.addEventListener("onChange", new EventListener() {
|
datebox.addEventListener("onChange", new EventListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -351,7 +353,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findComponentsForStartDateCell(Treecell treecell) {
|
private void findComponentsForStartDateCell(Treecell treecell) {
|
||||||
if (disabilityConfiguration.isTreeEditable()) {
|
if ( disabilityConfiguration.isTreeEditable() ) {
|
||||||
startDateTextBox = findTextBoxOfCell(treecell);
|
startDateTextBox = findTextBoxOfCell(treecell);
|
||||||
} else {
|
} else {
|
||||||
startDateLabel = (Label) treecell.getChildren().get(0);
|
startDateLabel = (Label) treecell.getChildren().get(0);
|
||||||
|
|
@ -359,7 +361,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findComponentsForEndDateCell(Treecell treecell) {
|
private void findComponentsForEndDateCell(Treecell treecell) {
|
||||||
if (disabilityConfiguration.isTreeEditable()) {
|
if ( disabilityConfiguration.isTreeEditable() ) {
|
||||||
endDateTextBox = findTextBoxOfCell(treecell);
|
endDateTextBox = findTextBoxOfCell(treecell);
|
||||||
} else {
|
} else {
|
||||||
endDateLabel = (Label) treecell.getChildren().get(0);
|
endDateLabel = (Label) treecell.getChildren().get(0);
|
||||||
|
|
@ -369,8 +371,7 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
private void findComponentsForStatusCell(Treecell treecell) {
|
private void findComponentsForStatusCell(Treecell treecell) {
|
||||||
List<Object> children = treecell.getChildren();
|
List<Object> children = treecell.getChildren();
|
||||||
|
|
||||||
Hlayout hlayout = ComponentsFinder.findComponentsOfType(Hlayout.class,
|
Hlayout hlayout = ComponentsFinder.findComponentsOfType(Hlayout.class, children).get(0);
|
||||||
children).get(0);
|
|
||||||
|
|
||||||
hoursStatusDiv = (Div) hlayout.getChildren().get(0);
|
hoursStatusDiv = (Div) hlayout.getChildren().get(0);
|
||||||
// there is a <label> "/" between the divs
|
// there is a <label> "/" between the divs
|
||||||
|
|
@ -389,15 +390,18 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateBean(Component updatedComponent) {
|
public void updateBean(Component updatedComponent) {
|
||||||
if (updatedComponent == getNameBox()) {
|
if ( updatedComponent == getNameBox() ) {
|
||||||
|
|
||||||
task.setName(getNameBox().getValue());
|
task.setName(getNameBox().getValue());
|
||||||
if (StringUtils.isEmpty(getNameBox().getValue())) {
|
|
||||||
|
if ( StringUtils.isEmpty(getNameBox().getValue()) ) {
|
||||||
getNameBox().setValue(task.getName());
|
getNameBox().setValue(task.getName());
|
||||||
}
|
}
|
||||||
} else if (updatedComponent == getStartDateTextBox()) {
|
|
||||||
|
} else if ( updatedComponent == getStartDateTextBox() ) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Date begin = dateFormat.parse(getStartDateTextBox()
|
final Date begin = dateFormat.parse(getStartDateTextBox().getValue());
|
||||||
.getValue());
|
|
||||||
task.doPositionModifications(new IModifications() {
|
task.doPositionModifications(new IModifications() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -408,23 +412,26 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
// Do nothing as textbox is rested in the next sentence
|
// Do nothing as textbox is rested in the next sentence
|
||||||
}
|
}
|
||||||
getStartDateTextBox().setValue(
|
|
||||||
dateFormat.format(task.getBeginDate().toDayRoundedDate()));
|
getStartDateTextBox().setValue(dateFormat.format(task.getBeginDate().toDayRoundedDate()));
|
||||||
} else if (updatedComponent == getEndDateTextBox()) {
|
|
||||||
|
} else if ( updatedComponent == getEndDateTextBox() ) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Date newEnd = dateFormat.parse(getEndDateTextBox().getValue());
|
Date newEnd = dateFormat.parse(getEndDateTextBox().getValue());
|
||||||
task.resizeTo(LocalDate.fromDateFields(newEnd));
|
task.resizeTo(LocalDate.fromDateFields(newEnd));
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
// Do nothing as textbox is rested in the next sentence
|
// Do nothing as textbox is rested in the next sentence
|
||||||
}
|
}
|
||||||
getEndDateTextBox().setValue(
|
|
||||||
asString(task.getEndDate().toDayRoundedDate()));
|
getEndDateTextBox().setValue(asString(task.getEndDate().toDayRoundedDate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
planner.updateTooltips();
|
planner.updateTooltips();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateComponents() {
|
private void updateComponents() {
|
||||||
if (disabilityConfiguration.isTreeEditable()) {
|
if ( disabilityConfiguration.isTreeEditable() ) {
|
||||||
getNameBox().setValue(task.getName());
|
getNameBox().setValue(task.getName());
|
||||||
getNameBox().setDisabled(!canRenameTask());
|
getNameBox().setDisabled(!canRenameTask());
|
||||||
getNameBox().setTooltiptext(task.getName());
|
getNameBox().setTooltiptext(task.getName());
|
||||||
|
|
@ -432,42 +439,35 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
getStartDateTextBox().setDisabled(!canChangeStartDate());
|
getStartDateTextBox().setDisabled(!canChangeStartDate());
|
||||||
getEndDateTextBox().setDisabled(!canChangeEndDate());
|
getEndDateTextBox().setDisabled(!canChangeEndDate());
|
||||||
|
|
||||||
getStartDateTextBox().setValue(
|
getStartDateTextBox().setValue(asString(task.getBeginDate().toDayRoundedDate()));
|
||||||
asString(task.getBeginDate().toDayRoundedDate()));
|
getEndDateTextBox().setValue(asString(task.getEndDate().toDayRoundedDate()));
|
||||||
getEndDateTextBox().setValue(
|
|
||||||
asString(task.getEndDate().toDayRoundedDate()));
|
|
||||||
} else {
|
} else {
|
||||||
nameLabel.setValue(task.getName());
|
nameLabel.setValue(task.getName());
|
||||||
nameLabel.setTooltiptext(task.getName());
|
nameLabel.setTooltiptext(task.getName());
|
||||||
nameLabel.setSclass("clickable-rows");
|
nameLabel.setSclass("clickable-rows");
|
||||||
|
|
||||||
nameLabel.addEventListener(Events.ON_CLICK, new EventListener() {
|
nameLabel.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(Event arg0) throws Exception {
|
public void onEvent(Event arg0) throws Exception {
|
||||||
Executions.getCurrent().sendRedirect(
|
Executions.getCurrent().sendRedirect("/planner/index.zul;order=" + task.getProjectCode());
|
||||||
"/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(),
|
startDateLabel.setValue(asString(task.getBeginDate().toDayRoundedDate()));
|
||||||
task.getTooltipTextForProjectBudgetStatus());
|
endDateLabel.setValue(asString(task.getEndDate().toDayRoundedDate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
setHoursStatus(task.getProjectHoursStatus(), task.getTooltipTextForProjectHoursStatus());
|
||||||
|
|
||||||
|
setBudgetStatus(task.getProjectBudgetStatus(), task.getTooltipTextForProjectBudgetStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean canChangeStartDate() {
|
private boolean canChangeStartDate() {
|
||||||
return disabilityConfiguration.isMovingTasksEnabled()
|
return disabilityConfiguration.isMovingTasksEnabled() && task.canBeExplicitlyMoved();
|
||||||
&& task.canBeExplicitlyMoved();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean canChangeEndDate() {
|
private boolean canChangeEndDate() {
|
||||||
return disabilityConfiguration.isResizingTasksEnabled()
|
return disabilityConfiguration.isResizingTasksEnabled() && task.canBeExplicitlyResized();
|
||||||
&& task.canBeExplicitlyResized();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean canRenameTask() {
|
private boolean canRenameTask() {
|
||||||
|
|
@ -508,29 +508,31 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
||||||
|
|
||||||
private String getProjectStatusSclass(ProjectStatusEnum status) {
|
private String getProjectStatusSclass(ProjectStatusEnum status) {
|
||||||
String cssClass;
|
String cssClass;
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case MARGIN_EXCEEDED:
|
case MARGIN_EXCEEDED:
|
||||||
cssClass = "status-red";
|
cssClass = "status-red";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WITHIN_MARGIN:
|
case WITHIN_MARGIN:
|
||||||
cssClass = "status-orange";
|
cssClass = "status-orange";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AS_PLANNED:
|
case AS_PLANNED:
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cssClass = "status-green";
|
cssClass = "status-green";
|
||||||
}
|
}
|
||||||
|
|
||||||
return cssClass;
|
return cssClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onProjectStatusClick(Component statucComp) {
|
private void onProjectStatusClick(Component statucComp) {
|
||||||
if (!disabilityConfiguration.isTreeEditable()) {
|
if ( !disabilityConfiguration.isTreeEditable() ) {
|
||||||
statucComp.addEventListener(Events.ON_CLICK, new EventListener() {
|
statucComp.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(Event arg0) throws Exception {
|
public void onEvent(Event arg0) throws Exception {
|
||||||
Executions.getCurrent()
|
Executions.getCurrent().sendRedirect("/planner/index.zul;order=" + task.getProjectCode());
|
||||||
.sendRedirect(
|
|
||||||
"/planner/index.zul;order="
|
|
||||||
+ task.getProjectCode());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
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.DateTime;
|
||||||
import org.joda.time.Days;
|
import org.joda.time.Days;
|
||||||
import org.joda.time.Duration;
|
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.Milestone;
|
||||||
import org.zkoss.ganttz.data.Task;
|
import org.zkoss.ganttz.data.Task;
|
||||||
import org.zkoss.ganttz.data.Task.IReloadResourcesTextRequested;
|
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;
|
||||||
import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener;
|
import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener;
|
||||||
import org.zkoss.ganttz.util.WeakReferencedListeners.Mode;
|
import org.zkoss.ganttz.util.WeakReferencedListeners.Mode;
|
||||||
|
|
@ -84,85 +83,88 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
IDisabilityConfiguration disabilityConfiguration,
|
IDisabilityConfiguration disabilityConfiguration,
|
||||||
boolean isTopLevel) {
|
boolean isTopLevel) {
|
||||||
final TaskComponent result;
|
final TaskComponent result;
|
||||||
if (task.isContainer()) {
|
|
||||||
result = TaskContainerComponent.asTask((TaskContainer) task,
|
if ( task.isContainer() ) {
|
||||||
disabilityConfiguration);
|
result = TaskContainerComponent.asTask(task, disabilityConfiguration);
|
||||||
} else if (task instanceof Milestone) {
|
|
||||||
|
} else if ( task instanceof Milestone ) {
|
||||||
result = new MilestoneComponent(task, disabilityConfiguration);
|
result = new MilestoneComponent(task, disabilityConfiguration);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new TaskComponent(task, disabilityConfiguration);
|
result = new TaskComponent(task, disabilityConfiguration);
|
||||||
}
|
}
|
||||||
result.isTopLevel = isTopLevel;
|
result.isTopLevel = isTopLevel;
|
||||||
|
|
||||||
return TaskRow.wrapInRow(result);
|
return TaskRow.wrapInRow(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TaskComponent asTaskComponent(Task task,
|
public static TaskComponent asTaskComponent(Task task, IDisabilityConfiguration disabilityConfiguration) {
|
||||||
IDisabilityConfiguration disabilityConfiguration) {
|
|
||||||
return asTaskComponent(task, disabilityConfiguration, true);
|
return asTaskComponent(task, disabilityConfiguration, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IReloadResourcesTextRequested reloadResourcesTextRequested;
|
private IReloadResourcesTextRequested reloadResourcesTextRequested;
|
||||||
|
|
||||||
public TaskComponent(Task task,
|
public TaskComponent(Task task, IDisabilityConfiguration disabilityConfiguration) {
|
||||||
IDisabilityConfiguration disabilityConfiguration) {
|
|
||||||
setHeight(HEIGHT_PER_TASK + "px");
|
setHeight(HEIGHT_PER_TASK + "px");
|
||||||
setContext("idContextMenuTaskAssignment");
|
setContext("idContextMenuTaskAssignment");
|
||||||
this.task = task;
|
this.task = task;
|
||||||
setClass(calculateCSSClass());
|
setClass(calculateCSSClass());
|
||||||
setId(UUID.randomUUID().toString());
|
setId(UUID.randomUUID().toString());
|
||||||
this.disabilityConfiguration = disabilityConfiguration;
|
this.disabilityConfiguration = disabilityConfiguration;
|
||||||
taskViolationListener = Constraint
|
taskViolationListener = Constraint.onlyOnZKExecution(new IConstraintViolationListener<GanttDate>() {
|
||||||
.onlyOnZKExecution(new IConstraintViolationListener<GanttDate>() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void constraintViolated(Constraint<GanttDate> constraint,
|
public void constraintViolated(Constraint<GanttDate> constraint, GanttDate value) {
|
||||||
GanttDate value) {
|
|
||||||
// TODO mark graphically task as violated
|
// TODO mark graphically task as violated
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void constraintSatisfied(Constraint<GanttDate> constraint,
|
public void constraintSatisfied(Constraint<GanttDate> constraint, GanttDate value) {
|
||||||
GanttDate value) {
|
|
||||||
// TODO mark graphically dependency as not violated
|
// TODO mark graphically dependency as not violated
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.task.addConstraintViolationListener(taskViolationListener,
|
|
||||||
Mode.RECEIVE_PENDING);
|
this.task.addConstraintViolationListener(taskViolationListener, Mode.RECEIVE_PENDING);
|
||||||
reloadResourcesTextRequested = new IReloadResourcesTextRequested() {
|
reloadResourcesTextRequested = new IReloadResourcesTextRequested() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reloadResourcesTextRequested() {
|
public void reloadResourcesTextRequested() {
|
||||||
if (canShowResourcesText()) {
|
if ( canShowResourcesText() ) {
|
||||||
smartUpdate("resourcesText", getResourcesText());
|
smartUpdate("resourcesText", getResourcesText());
|
||||||
}
|
}
|
||||||
|
|
||||||
String cssClass = calculateCSSClass();
|
String cssClass = calculateCSSClass();
|
||||||
|
|
||||||
response("setClass", new AuInvoke(TaskComponent.this,
|
response("setClass", new AuInvoke(TaskComponent.this, "setClass", cssClass));
|
||||||
"setClass", cssClass));
|
|
||||||
|
|
||||||
// FIXME: Refactorize to another listener
|
// FIXME: Refactor to another listener
|
||||||
updateDeadline();
|
updateDeadline();
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.task.addReloadListener(reloadResourcesTextRequested);
|
this.task.addReloadListener(reloadResourcesTextRequested);
|
||||||
|
|
||||||
setAuService(new AuService(){
|
setAuService(new AuService(){
|
||||||
|
|
||||||
public boolean service(AuRequest request, boolean everError){
|
public boolean service(AuRequest request, boolean everError){
|
||||||
String command = request.getCommand();
|
String command = request.getCommand();
|
||||||
final TaskComponent ta;
|
final TaskComponent ta;
|
||||||
|
|
||||||
if (command.equals("onUpdatePosition")){
|
if ( command.equals("onUpdatePosition") ){
|
||||||
ta = retrieveTaskComponent(request);
|
ta = retrieveTaskComponent(request);
|
||||||
|
|
||||||
ta.doUpdatePosition(
|
ta.doUpdatePosition(
|
||||||
toInteger(retrieveData(request, "left")),
|
toInteger(retrieveData(request, "left"))
|
||||||
toInteger(retrieveData(request, "top")));
|
);
|
||||||
|
|
||||||
Events.postEvent(new Event(getId(), ta, request.getData()));
|
Events.postEvent(new Event(getId(), ta, request.getData()));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (command.equals("onUpdateWidth")){
|
|
||||||
|
if ( command.equals("onUpdateWidth") ){
|
||||||
ta = retrieveTaskComponent(request);
|
ta = retrieveTaskComponent(request);
|
||||||
|
|
||||||
ta.doUpdateSize(toInteger(retrieveData(request, "width")));
|
ta.doUpdateSize(toInteger(retrieveData(request, "width")));
|
||||||
|
|
@ -170,7 +172,8 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (command.equals("onAddDependency")){
|
|
||||||
|
if ( command.equals("onAddDependency") ){
|
||||||
ta = retrieveTaskComponent(request);
|
ta = retrieveTaskComponent(request);
|
||||||
|
|
||||||
ta.doAddDependency((String) retrieveData(request, "dependencyId"));
|
ta.doAddDependency((String) retrieveData(request, "dependencyId"));
|
||||||
|
|
@ -178,6 +181,7 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -188,9 +192,8 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
private TaskComponent retrieveTaskComponent(AuRequest request){
|
private TaskComponent retrieveTaskComponent(AuRequest request){
|
||||||
final TaskComponent ta = (TaskComponent) request.getComponent();
|
final TaskComponent ta = (TaskComponent) request.getComponent();
|
||||||
|
|
||||||
if (ta == null) {
|
if ( ta == null ) {
|
||||||
throw new UiException(MZk.ILLEGAL_REQUEST_COMPONENT_REQUIRED,
|
throw new UiException(MZk.ILLEGAL_REQUEST_COMPONENT_REQUIRED, this);
|
||||||
this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ta;
|
return ta;
|
||||||
|
|
@ -198,9 +201,8 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
|
|
||||||
private Object retrieveData(AuRequest request, String key){
|
private Object retrieveData(AuRequest request, String key){
|
||||||
Object value = request.getData().get(key);
|
Object value = request.getData().get(key);
|
||||||
if ( value == null)
|
if ( value == null )
|
||||||
throw new UiException(MZk.ILLEGAL_REQUEST_WRONG_DATA,
|
throw new UiException(MZk.ILLEGAL_REQUEST_WRONG_DATA, new Object[] { key, this });
|
||||||
new Object[] { key, this });
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
@ -209,27 +211,29 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
|
|
||||||
/* Generate CSS class attribute depending on task properties */
|
/* Generate CSS class attribute depending on task properties */
|
||||||
protected String calculateCSSClass() {
|
protected String calculateCSSClass() {
|
||||||
String cssClass = isSubcontracted() ? "box subcontracted-task"
|
String cssClass = isSubcontracted() ? "box subcontracted-task" : "box standard-task";
|
||||||
: "box standard-task";
|
|
||||||
cssClass += isResizingTasksEnabled() ? " yui-resize" : "";
|
cssClass += isResizingTasksEnabled() ? " yui-resize" : "";
|
||||||
if (isContainer()) {
|
|
||||||
|
if ( isContainer() ) {
|
||||||
cssClass += task.isExpanded() ? " expanded" : " closed ";
|
cssClass += task.isExpanded() ? " expanded" : " closed ";
|
||||||
cssClass += task.isInCriticalPath() && !task.isExpanded() ? " critical"
|
cssClass += task.isInCriticalPath() && !task.isExpanded() ? " critical" : "";
|
||||||
: "";
|
|
||||||
} else {
|
} else {
|
||||||
cssClass += task.isInCriticalPath() ? " critical" : "";
|
cssClass += task.isInCriticalPath() ? " critical" : "";
|
||||||
if (!task.canBeExplicitlyMoved()) {
|
if ( !task.canBeExplicitlyMoved() ) {
|
||||||
cssClass += " fixed";
|
cssClass += " fixed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cssClass += " " + task.getAssignedStatus();
|
cssClass += " " + task.getAssignedStatus();
|
||||||
if (task.isLimiting()) {
|
if ( task.isLimiting() ) {
|
||||||
cssClass += task.isLimitingAndHasDayAssignments() ? " limiting-assigned "
|
cssClass += task.isLimitingAndHasDayAssignments() ? " limiting-assigned " : " limiting-unassigned ";
|
||||||
: " limiting-unassigned ";
|
|
||||||
}
|
}
|
||||||
if (task.isRoot() && task.belongsClosedProject()) {
|
|
||||||
|
if ( task.isRoot() && task.belongsClosedProject() ) {
|
||||||
cssClass += " project-closed ";
|
cssClass += " project-closed ";
|
||||||
}
|
}
|
||||||
|
|
||||||
return cssClass;
|
return cssClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,7 +247,7 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
|
|
||||||
public final void afterCompose() {
|
public final void afterCompose() {
|
||||||
updateProperties();
|
updateProperties();
|
||||||
if (propertiesListener == null) {
|
if ( propertiesListener == null ) {
|
||||||
propertiesListener = new PropertyChangeListener() {
|
propertiesListener = new PropertyChangeListener() {
|
||||||
|
|
||||||
@Override
|
@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() {
|
showingAdvancePropertyListener = new PropertyChangeListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
if (isInPage() && !(task instanceof Milestone)) {
|
if ( isInPage() && !(task instanceof Milestone) ) {
|
||||||
updateCompletionAdvance();
|
updateCompletionAdvance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.task
|
|
||||||
.addAdvancesPropertyChangeListener(showingAdvancePropertyListener);
|
|
||||||
|
|
||||||
if (showingReportedHoursPropertyListener == null) {
|
this.task.addAdvancesPropertyChangeListener(showingAdvancePropertyListener);
|
||||||
|
|
||||||
|
if ( showingReportedHoursPropertyListener == null ) {
|
||||||
showingReportedHoursPropertyListener = new PropertyChangeListener() {
|
showingReportedHoursPropertyListener = new PropertyChangeListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
if (isInPage() && !(task instanceof Milestone)) {
|
if ( isInPage() && !(task instanceof Milestone) ) {
|
||||||
updateCompletionReportedHours();
|
updateCompletionReportedHours();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.task
|
|
||||||
.addReportedHoursPropertyChangeListener(showingReportedHoursPropertyListener);
|
|
||||||
|
|
||||||
if (showingMoneyCostBarPropertyListener == null) {
|
this.task.addReportedHoursPropertyChangeListener(showingReportedHoursPropertyListener);
|
||||||
|
|
||||||
|
if ( showingMoneyCostBarPropertyListener == null ) {
|
||||||
showingMoneyCostBarPropertyListener = new PropertyChangeListener() {
|
showingMoneyCostBarPropertyListener = new PropertyChangeListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
if (isInPage() && !(task instanceof Milestone)) {
|
if ( isInPage() && !(task instanceof Milestone) ) {
|
||||||
updateCompletionMoneyCostBar();
|
updateCompletionMoneyCostBar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.task
|
|
||||||
.addMoneyCostBarPropertyChangeListener(showingMoneyCostBarPropertyListener);
|
|
||||||
|
|
||||||
if (criticalPathPropertyListener == null) {
|
this.task.addMoneyCostBarPropertyChangeListener(showingMoneyCostBarPropertyListener);
|
||||||
|
|
||||||
|
if ( criticalPathPropertyListener == null ) {
|
||||||
criticalPathPropertyListener = new PropertyChangeListener() {
|
criticalPathPropertyListener = new PropertyChangeListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -307,8 +311,8 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.task
|
|
||||||
.addCriticalPathPropertyChangeListener(criticalPathPropertyListener);
|
this.task.addCriticalPathPropertyChangeListener(criticalPathPropertyListener);
|
||||||
|
|
||||||
updateClass();
|
updateClass();
|
||||||
}
|
}
|
||||||
|
|
@ -328,15 +332,14 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
private transient PropertyChangeListener propertiesListener;
|
private transient PropertyChangeListener propertiesListener;
|
||||||
private IConstraintViolationListener<GanttDate> taskViolationListener;
|
private IConstraintViolationListener<GanttDate> taskViolationListener;
|
||||||
|
|
||||||
// FIXME Bug #1270
|
|
||||||
private String progressType;
|
private String progressType;
|
||||||
|
|
||||||
public TaskRow getRow() {
|
public TaskRow getRow() {
|
||||||
if (getParent() == null) {
|
if ( getParent() == null ) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"the TaskComponent should have been wraped by a "
|
"the TaskComponent should have been wraped by a " + TaskRow.class.getName());
|
||||||
+ TaskRow.class.getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (TaskRow) getParent();
|
return (TaskRow) getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -353,19 +356,19 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isResizingTasksEnabled() {
|
public boolean isResizingTasksEnabled() {
|
||||||
return (disabilityConfiguration != null)
|
return (disabilityConfiguration != null) &&
|
||||||
&& disabilityConfiguration.isResizingTasksEnabled()
|
disabilityConfiguration.isResizingTasksEnabled() &&
|
||||||
&& !task.isSubcontracted() && task.canBeExplicitlyResized();
|
!task.isSubcontracted() && task.canBeExplicitlyResized();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMovingTasksEnabled() {
|
public boolean isMovingTasksEnabled() {
|
||||||
return (disabilityConfiguration != null)
|
return (disabilityConfiguration != null) &&
|
||||||
&& disabilityConfiguration.isMovingTasksEnabled()
|
disabilityConfiguration.isMovingTasksEnabled() &&
|
||||||
&& task.canBeExplicitlyMoved();
|
task.canBeExplicitlyMoved();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void doUpdatePosition(int leftX, int topY) {
|
void doUpdatePosition(int leftX) {
|
||||||
GanttDate startBeforeMoving = this.task.getBeginDate();
|
GanttDate startBeforeMoving = this.task.getBeginDate();
|
||||||
final LocalDate newPosition = getMapper().toDate(leftX);
|
final LocalDate newPosition = getMapper().toDate(leftX);
|
||||||
this.task.doPositionModifications(new IModifications() {
|
this.task.doPositionModifications(new IModifications() {
|
||||||
|
|
@ -375,24 +378,23 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
position.moveTo(GanttDate.createFrom(newPosition));
|
position.moveTo(GanttDate.createFrom(newPosition));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
boolean remainsInOriginalPosition = this.task.getBeginDate().equals(
|
|
||||||
startBeforeMoving);
|
boolean remainsInOriginalPosition = this.task.getBeginDate().equals(startBeforeMoving);
|
||||||
if (remainsInOriginalPosition) {
|
if ( remainsInOriginalPosition ) {
|
||||||
updateProperties();
|
updateProperties();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doUpdateSize(int size) {
|
void doUpdateSize(int size) {
|
||||||
DateTime end = new DateTime(this.task.getBeginDate()
|
DateTime end =
|
||||||
.toDayRoundedDate().getTime()).plus(getMapper().toDuration(
|
new DateTime(this.task.getBeginDate().toDayRoundedDate().getTime()).plus(getMapper().toDuration(size));
|
||||||
size));
|
|
||||||
this.task.resizeTo(end.toLocalDate());
|
this.task.resizeTo(end.toLocalDate());
|
||||||
updateProperties();
|
updateProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
void doAddDependency(String destinyTaskId) {
|
void doAddDependency(String destinyTaskId) {
|
||||||
getTaskList().addDependency(this,
|
getTaskList().addDependency(this, ((TaskComponent) getFellow(destinyTaskId)));
|
||||||
((TaskComponent) getFellow(destinyTaskId)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getColor() {
|
public String getColor() {
|
||||||
|
|
@ -401,11 +403,11 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
|
|
||||||
public void setColor(String color) {
|
public void setColor(String color) {
|
||||||
|
|
||||||
if ((color != null) && (color.length() == 0)) {
|
if ( (color != null) && (color.length() == 0) ) {
|
||||||
color = null;
|
color = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Objects.equals(_color, color)) {
|
if ( !Objects.equals(_color, color) ) {
|
||||||
_color = color;
|
_color = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -415,13 +417,12 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
* of the style
|
* of the style
|
||||||
*/
|
*/
|
||||||
protected void renderProperties(ContentRenderer renderer) throws IOException{
|
protected void renderProperties(ContentRenderer renderer) throws IOException{
|
||||||
if(getColor() != null)
|
if( getColor() != null ) setStyle("background-color : " + getColor());
|
||||||
setStyle("background-color : " + getColor());
|
|
||||||
|
|
||||||
setWidgetAttribute("movingTasksEnabled",((Boolean)isMovingTasksEnabled()).toString());
|
setWidgetAttribute("movingTasksEnabled", ((Boolean)isMovingTasksEnabled()).toString());
|
||||||
setWidgetAttribute("resizingTasksEnabled", ((Boolean)isResizingTasksEnabled()).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
|
* involved with UiVisualizer#getResponses and the
|
||||||
* smartUpdate method (when the request is asynchronous) */
|
* smartUpdate method (when the request is asynchronous) */
|
||||||
render(renderer, "style", "position : absolute");
|
render(renderer, "style", "position : absolute");
|
||||||
|
|
@ -461,9 +462,10 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateProperties() {
|
public void updateProperties() {
|
||||||
if (!isInPage()) {
|
if ( !isInPage() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLeft("0");
|
setLeft("0");
|
||||||
setLeft(this.task.getBeginDate().toPixels(getMapper()) + "px");
|
setLeft(this.task.getBeginDate().toPixels(getMapper()) + "px");
|
||||||
updateWidth();
|
updateWidth();
|
||||||
|
|
@ -483,23 +485,27 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
|
|
||||||
private void updateDeadline() {
|
private void updateDeadline() {
|
||||||
// Task mark is placed after midnight date of the deadline day
|
// Task mark is placed after midnight date of the deadline day
|
||||||
if (task.getDeadline() != null) {
|
if ( task.getDeadline() != null ) {
|
||||||
|
|
||||||
String position = (getMapper().toPixels(
|
String position = (getMapper().toPixels(
|
||||||
LocalDate.fromDateFields(task.getDeadline()).plusDays(1)) - HALF_DEADLINE_MARK)
|
LocalDate.fromDateFields(task.getDeadline()).plusDays(1)) - HALF_DEADLINE_MARK) + "px";
|
||||||
+ "px";
|
|
||||||
response(null, new AuInvoke(this, "moveDeadline", position));
|
response(null, new AuInvoke(this, "moveDeadline", position));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Move deadline out of visible area
|
// Move deadline out of visible area
|
||||||
response(null, new AuInvoke(this, "moveDeadline","-100px"));
|
response(null, new AuInvoke(this, "moveDeadline","-100px"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task.getConsolidatedline() != null) {
|
if ( task.getConsolidatedline() != null ) {
|
||||||
int pixels = getMapper().toPixels(
|
|
||||||
LocalDate.fromDateFields(task.getConsolidatedline()
|
int pixels = getMapper()
|
||||||
.toDayRoundedDate()))
|
.toPixels(LocalDate.fromDateFields(task.getConsolidatedline().toDayRoundedDate()))
|
||||||
- CONSOLIDATED_MARK_HALF_WIDTH;
|
- CONSOLIDATED_MARK_HALF_WIDTH;
|
||||||
|
|
||||||
String position = pixels + "px";
|
String position = pixels + "px";
|
||||||
response(null, new AuInvoke(this, "moveConsolidatedline", position));
|
response(null, new AuInvoke(this, "moveConsolidatedline", position));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Move consolidated line out of visible area
|
// Move consolidated line out of visible area
|
||||||
response(null, new AuInvoke(this, "moveConsolidatedline", "-100px"));
|
response(null, new AuInvoke(this, "moveConsolidatedline", "-100px"));
|
||||||
|
|
@ -507,43 +513,45 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCompletionIfPossible() {
|
public void updateCompletionIfPossible() {
|
||||||
if (task instanceof Milestone) {
|
if ( task instanceof Milestone ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCompletionReportedHours();
|
updateCompletionReportedHours();
|
||||||
updateCompletionMoneyCostBar();
|
updateCompletionMoneyCostBar();
|
||||||
updateCompletionAdvance();
|
updateCompletionAdvance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCompletionReportedHours() {
|
public void updateCompletionReportedHours() {
|
||||||
if (task.isShowingReportedHours()) {
|
if ( task.isShowingReportedHours() ) {
|
||||||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||||
String widthHoursAdvancePercentage = pixelsFromStartUntil(
|
|
||||||
startPixels,
|
String widthHoursAdvancePercentage =
|
||||||
this.task.getHoursAdvanceBarEndDate()) + "px";
|
pixelsFromStartUntil(startPixels, this.task.getHoursAdvanceBarEndDate()) + "px";
|
||||||
response(null, new AuInvoke(this, "resizeCompletionAdvance",
|
|
||||||
widthHoursAdvancePercentage));
|
response(null, new AuInvoke(this, "resizeCompletionAdvance", widthHoursAdvancePercentage));
|
||||||
|
|
||||||
Date firstTimesheetDate = task.getFirstTimesheetDate();
|
Date firstTimesheetDate = task.getFirstTimesheetDate();
|
||||||
Date lastTimesheetDate = task.getLastTimesheetDate();
|
Date lastTimesheetDate = task.getLastTimesheetDate();
|
||||||
if (firstTimesheetDate != null && lastTimesheetDate != null) {
|
|
||||||
|
if ( firstTimesheetDate != null && lastTimesheetDate != null ) {
|
||||||
|
|
||||||
Duration firstDuration = Days.daysBetween(
|
Duration firstDuration = Days.daysBetween(
|
||||||
task.getBeginDateAsLocalDate(),
|
task.getBeginDateAsLocalDate(),
|
||||||
LocalDate.fromDateFields(firstTimesheetDate))
|
LocalDate.fromDateFields(firstTimesheetDate)).toStandardDuration();
|
||||||
.toStandardDuration();
|
|
||||||
int pixelsFirst = getMapper().toPixels(firstDuration);
|
int pixelsFirst = getMapper().toPixels(firstDuration);
|
||||||
String positionFirst = pixelsFirst + "px";
|
String positionFirst = pixelsFirst + "px";
|
||||||
|
|
||||||
Duration lastDuration = Days
|
Duration lastDuration = Days.daysBetween(
|
||||||
.daysBetween(
|
|
||||||
task.getBeginDateAsLocalDate(),
|
task.getBeginDateAsLocalDate(),
|
||||||
LocalDate.fromDateFields(lastTimesheetDate)
|
LocalDate.fromDateFields(lastTimesheetDate).plusDays(1)).toStandardDuration();
|
||||||
.plusDays(1)).toStandardDuration();
|
|
||||||
int pixelsLast = getMapper().toPixels(lastDuration);
|
int pixelsLast = getMapper().toPixels(lastDuration);
|
||||||
String positionLast = pixelsLast + "px";
|
String positionLast = pixelsLast + "px";
|
||||||
|
|
||||||
response(null, new AuInvoke(this, "showTimsheetDateMarks",
|
response(null, new AuInvoke(this, "showTimsheetDateMarks", positionFirst, positionLast));
|
||||||
positionFirst, positionLast));
|
|
||||||
} else {
|
} else {
|
||||||
response(null, new AuInvoke(this, "hideTimsheetDateMarks"));
|
response(null, new AuInvoke(this, "hideTimsheetDateMarks"));
|
||||||
}
|
}
|
||||||
|
|
@ -555,44 +563,38 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCompletionMoneyCostBar() {
|
public void updateCompletionMoneyCostBar() {
|
||||||
if (task.isShowingMoneyCostBar()) {
|
if ( task.isShowingMoneyCostBar() ) {
|
||||||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||||
int endPixels = this.task.getEndDate().toPixels(getMapper());
|
int endPixels = this.task.getEndDate().toPixels(getMapper());
|
||||||
int widthPixels = (int) ((endPixels - startPixels) * this.task
|
int widthPixels = (int) ((endPixels - startPixels) * this.task.getMoneyCostBarPercentage().doubleValue());
|
||||||
.getMoneyCostBarPercentage().doubleValue());
|
|
||||||
String widthMoneyCostBar = widthPixels + "px";
|
String widthMoneyCostBar = widthPixels + "px";
|
||||||
response(null, new AuInvoke(this, "resizeCompletionMoneyCostBar",
|
response(null, new AuInvoke(this, "resizeCompletionMoneyCostBar", widthMoneyCostBar));
|
||||||
widthMoneyCostBar));
|
|
||||||
} else {
|
} else {
|
||||||
response(null, new AuInvoke(this, "resizeCompletionMoneyCostBar",
|
response(null, new AuInvoke(this, "resizeCompletionMoneyCostBar", "0px"));
|
||||||
"0px"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCompletionAdvance() {
|
private void updateCompletionAdvance() {
|
||||||
if (task.isShowingAdvances()) {
|
if ( task.isShowingAdvances() ) {
|
||||||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||||
String widthAdvancePercentage = pixelsFromStartUntil(startPixels,
|
String widthAdvancePercentage = pixelsFromStartUntil(startPixels, this.task.getAdvanceBarEndDate()) + "px";
|
||||||
this.task.getAdvanceBarEndDate()) + "px";
|
response(null, new AuInvoke(this, "resizeCompletion2Advance", widthAdvancePercentage));
|
||||||
response(null, new AuInvoke(this, "resizeCompletion2Advance",
|
|
||||||
widthAdvancePercentage));
|
|
||||||
} else {
|
} else {
|
||||||
response(null,
|
response(null, new AuInvoke(this, "resizeCompletion2Advance", "0px"));
|
||||||
new AuInvoke(this, "resizeCompletion2Advance", "0px"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCompletion(String progressType) {
|
public void updateCompletion(String progressType) {
|
||||||
if (task.isShowingAdvances()) {
|
if ( task.isShowingAdvances() ) {
|
||||||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||||
|
|
||||||
String widthAdvancePercentage = pixelsFromStartUntil(startPixels,
|
String widthAdvancePercentage =
|
||||||
this.task.getAdvanceBarEndDate(progressType)) + "px";
|
pixelsFromStartUntil(startPixels, this.task.getAdvanceBarEndDate(progressType)) + "px";
|
||||||
response(null, new AuInvoke(this, "resizeCompletion2Advance",
|
|
||||||
widthAdvancePercentage));
|
response(null, new AuInvoke(this, "resizeCompletion2Advance", widthAdvancePercentage));
|
||||||
} else {
|
} else {
|
||||||
response(null,
|
response(null, new AuInvoke(this, "resizeCompletion2Advance", "0px"));
|
||||||
new AuInvoke(this, "resizeCompletion2Advance", "0px"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -603,12 +605,10 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateTooltipText() {
|
public void updateTooltipText() {
|
||||||
// FIXME Bug #1270
|
|
||||||
this.progressType = null;
|
this.progressType = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateTooltipText(String progressType) {
|
public void updateTooltipText(String progressType) {
|
||||||
// FIXME Bug #1270
|
|
||||||
this.progressType = progressType;
|
this.progressType = progressType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -635,8 +635,7 @@ public class TaskComponent extends Div implements AfterCompose {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTooltipText() {
|
public String getTooltipText() {
|
||||||
// FIXME Bug #1270
|
if ( progressType == null ) {
|
||||||
if (progressType == null) {
|
|
||||||
return task.getTooltipText();
|
return task.getTooltipText();
|
||||||
} else {
|
} else {
|
||||||
return task.updateTooltipText(progressType);
|
return task.updateTooltipText(progressType);
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.WeakHashMap;
|
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.joda.time.LocalDate;
|
||||||
import org.zkoss.ganttz.adapters.IDisabilityConfiguration;
|
import org.zkoss.ganttz.adapters.IDisabilityConfiguration;
|
||||||
import org.zkoss.ganttz.data.Dependency;
|
import org.zkoss.ganttz.data.Dependency;
|
||||||
|
|
@ -75,7 +75,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
|
|
||||||
private FilterAndParentExpandedPredicates predicate;
|
private FilterAndParentExpandedPredicates predicate;
|
||||||
|
|
||||||
private Set<Task> visibleTasks = new HashSet<Task>();
|
private Set<Task> visibleTasks = new HashSet<>();
|
||||||
|
|
||||||
private Map<Task, TaskComponent> taskComponentByTask;
|
private Map<Task, TaskComponent> taskComponentByTask;
|
||||||
|
|
||||||
|
|
@ -86,9 +86,10 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
List<? extends CommandOnTaskContextualized<?>> commandsOnTasksContextualized,
|
List<? extends CommandOnTaskContextualized<?>> commandsOnTasksContextualized,
|
||||||
IDisabilityConfiguration disabilityConfiguration,
|
IDisabilityConfiguration disabilityConfiguration,
|
||||||
FilterAndParentExpandedPredicates predicate) {
|
FilterAndParentExpandedPredicates predicate) {
|
||||||
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.doubleClickCommand = doubleClickCommand;
|
this.doubleClickCommand = doubleClickCommand;
|
||||||
this.currentTotalTasks = new ArrayList<Task>(tasks);
|
this.currentTotalTasks = new ArrayList<>(tasks);
|
||||||
this.commandsOnTasksContextualized = commandsOnTasksContextualized;
|
this.commandsOnTasksContextualized = commandsOnTasksContextualized;
|
||||||
this.disabilityConfiguration = disabilityConfiguration;
|
this.disabilityConfiguration = disabilityConfiguration;
|
||||||
this.predicate = predicate;
|
this.predicate = predicate;
|
||||||
|
|
@ -103,7 +104,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Task> getAllTasks() {
|
public List<Task> getAllTasks() {
|
||||||
return new ArrayList<Task>(currentTotalTasks);
|
return new ArrayList<>(currentTotalTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TaskList createFor(
|
public static TaskList createFor(
|
||||||
|
|
@ -112,20 +113,26 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
List<? extends CommandOnTaskContextualized<?>> commandsOnTasksContextualized,
|
List<? extends CommandOnTaskContextualized<?>> commandsOnTasksContextualized,
|
||||||
IDisabilityConfiguration disabilityConfiguration,
|
IDisabilityConfiguration disabilityConfiguration,
|
||||||
FilterAndParentExpandedPredicates predicate) {
|
FilterAndParentExpandedPredicates predicate) {
|
||||||
TaskList result = new TaskList(context, doubleClickCommand, context
|
|
||||||
.getDiagramGraph().getTopLevelTasks(),
|
TaskList result = new TaskList(
|
||||||
commandsOnTasksContextualized, disabilityConfiguration,
|
context,
|
||||||
|
doubleClickCommand,
|
||||||
|
context.getDiagramGraph().getTopLevelTasks(),
|
||||||
|
commandsOnTasksContextualized,
|
||||||
|
disabilityConfiguration,
|
||||||
predicate);
|
predicate);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DependencyComponent> asDependencyComponents(Collection<? extends Dependency> dependencies) {
|
public List<DependencyComponent> asDependencyComponents(Collection<? extends Dependency> dependencies) {
|
||||||
List<DependencyComponent> result = new ArrayList<DependencyComponent>();
|
List<DependencyComponent> result = new ArrayList<>();
|
||||||
for (Dependency dependency : dependencies) {
|
for (Dependency dependency : dependencies) {
|
||||||
result.add(new DependencyComponent(taskComponentByTask
|
result.add(new DependencyComponent(
|
||||||
.get(dependency.getSource()), taskComponentByTask
|
taskComponentByTask.get(dependency.getSource()),
|
||||||
.get(dependency.getDestination()), dependency));
|
taskComponentByTask.get(dependency.getDestination()), dependency));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,11 +140,14 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
return asDependencyComponents(Arrays.asList(dependency)).get(0);
|
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);
|
insertBefore(taskComponent.getRow(), beforeThis);
|
||||||
addContextMenu(taskComponent);
|
addContextMenu(taskComponent);
|
||||||
addListenerForTaskComponentEditForm(taskComponent);
|
addListenerForTaskComponentEditForm(taskComponent);
|
||||||
taskComponent.afterCompose();
|
taskComponent.afterCompose();
|
||||||
|
|
||||||
if ( relocate ) {
|
if ( relocate ) {
|
||||||
getGanttPanel().adjustZoomColumnsHeight();
|
getGanttPanel().adjustZoomColumnsHeight();
|
||||||
}
|
}
|
||||||
|
|
@ -145,12 +155,14 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
|
|
||||||
public void addTasks(Position position, Collection<? extends Task> newTasks) {
|
public void addTasks(Position position, Collection<? extends Task> newTasks) {
|
||||||
createAndPublishComponentsIfNeeded(newTasks);
|
createAndPublishComponentsIfNeeded(newTasks);
|
||||||
if (position.isAppendToTop()) {
|
|
||||||
|
if ( position.isAppendToTop() ) {
|
||||||
currentTotalTasks.addAll(newTasks);
|
currentTotalTasks.addAll(newTasks);
|
||||||
} else if (position.isAtTop()) {
|
} else if ( position.isAtTop() ) {
|
||||||
final int insertionPosition = position.getInsertionPosition();
|
final int insertionPosition = position.getInsertionPosition();
|
||||||
currentTotalTasks.addAll(insertionPosition, newTasks);
|
currentTotalTasks.addAll(insertionPosition, newTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the position is children of some already existent task when
|
// if the position is children of some already existent task when
|
||||||
// reloading it will be added if the predicate tells so
|
// reloading it will be added if the predicate tells so
|
||||||
reload(true);
|
reload(true);
|
||||||
|
|
@ -159,7 +171,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
public TaskComponent find(Task task) {
|
public TaskComponent find(Task task) {
|
||||||
List<TaskComponent> taskComponents = getTaskComponents();
|
List<TaskComponent> taskComponents = getTaskComponents();
|
||||||
for (TaskComponent taskComponent : taskComponents) {
|
for (TaskComponent taskComponent : taskComponents) {
|
||||||
if (taskComponent.getTask().equals(task)) {
|
if ( taskComponent.getTask().equals(task) ) {
|
||||||
return taskComponent;
|
return taskComponent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -196,13 +208,14 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<TaskComponent> getTaskComponents() {
|
protected List<TaskComponent> getTaskComponents() {
|
||||||
ArrayList<TaskComponent> result = new ArrayList<TaskComponent>();
|
ArrayList<TaskComponent> result = new ArrayList<>();
|
||||||
for (Object child : getChildren()) {
|
for (Object child : getChildren()) {
|
||||||
if (child instanceof TaskRow) {
|
if ( child instanceof TaskRow ) {
|
||||||
TaskRow row = (TaskRow) child;
|
TaskRow row = (TaskRow) child;
|
||||||
result.add(row.getChild());
|
result.add(row.getChild());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,42 +231,44 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void publishOriginalTasksAsComponents() {
|
private void publishOriginalTasksAsComponents() {
|
||||||
taskComponentByTask = new HashMap<Task, TaskComponent>();
|
taskComponentByTask = new HashMap<>();
|
||||||
createAndPublishComponentsIfNeeded(currentTotalTasks);
|
createAndPublishComponentsIfNeeded(currentTotalTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<TaskComponent> createAndPublishComponentsIfNeeded(
|
private List<TaskComponent> createAndPublishComponentsIfNeeded(Collection<? extends Task> newTasks) {
|
||||||
Collection<? extends Task> newTasks) {
|
if ( predicate.isFilterContainers() ) {
|
||||||
if (predicate.isFilterContainers()) {
|
List<Task> taskLeafs = new ArrayList<>();
|
||||||
List<Task> taskLeafs = new ArrayList<Task>();
|
|
||||||
for (Task task : newTasks) {
|
for (Task task : newTasks) {
|
||||||
taskLeafs.addAll(task.getAllTaskLeafs());
|
taskLeafs.addAll(task.getAllTaskLeafs());
|
||||||
}
|
}
|
||||||
newTasks = taskLeafs;
|
newTasks = taskLeafs;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<TaskComponent> result = new ArrayList<TaskComponent>();
|
List<TaskComponent> result = new ArrayList<>();
|
||||||
for (Task task : newTasks) {
|
for (Task task : newTasks) {
|
||||||
TaskComponent taskComponent = taskComponentByTask.get(task);
|
TaskComponent taskComponent = taskComponentByTask.get(task);
|
||||||
if (taskComponent == null) {
|
|
||||||
taskComponent = TaskComponent.asTaskComponent(task,
|
if ( taskComponent == null ) {
|
||||||
disabilityConfiguration);
|
taskComponent = TaskComponent.asTaskComponent(task, disabilityConfiguration);
|
||||||
taskComponent.publishTaskComponents(taskComponentByTask);
|
taskComponent.publishTaskComponents(taskComponentByTask);
|
||||||
}
|
}
|
||||||
if (task.isContainer()) {
|
|
||||||
|
if ( task.isContainer() ) {
|
||||||
addExpandListenerTo((TaskContainer) task);
|
addExpandListenerTo((TaskContainer) task);
|
||||||
}
|
}
|
||||||
result.add(taskComponent);
|
result.add(taskComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<TaskContainer, IExpandListener> autoRemovedListers = new WeakHashMap<TaskContainer, IExpandListener>();
|
private Map<TaskContainer, IExpandListener> autoRemovedListers = new WeakHashMap<>();
|
||||||
|
|
||||||
private void addExpandListenerTo(TaskContainer container) {
|
private void addExpandListenerTo(TaskContainer container) {
|
||||||
if (autoRemovedListers.containsKey(container)) {
|
if ( autoRemovedListers.containsKey(container) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IExpandListener expandListener = new IExpandListener() {
|
IExpandListener expandListener = new IExpandListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -261,12 +276,13 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
reload(true);
|
reload(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
container.addExpandListener(expandListener);
|
container.addExpandListener(expandListener);
|
||||||
autoRemovedListers.put(container, expandListener);
|
autoRemovedListers.put(container, expandListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerZoomLevelChangedListener() {
|
private void registerZoomLevelChangedListener() {
|
||||||
if (zoomLevelChangedListener == null) {
|
if ( zoomLevelChangedListener == null ) {
|
||||||
zoomLevelChangedListener = new IZoomLevelChangedListener() {
|
zoomLevelChangedListener = new IZoomLevelChangedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void zoomLevelChanged(ZoomLevel detailLevel) {
|
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) {
|
public LocalDate toDate(int pixels, Fraction pixelsPerDay, Interval interval) {
|
||||||
int daysInto = Fraction.getFraction(pixels, 1).divideBy(pixelsPerDay)
|
int daysInto = Fraction.getFraction(pixels, 1).divideBy(pixelsPerDay).intValue();
|
||||||
.intValue();
|
|
||||||
return interval.getStart().plusDays(daysInto);
|
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) {
|
private Menupopup getContextMenuFor(TaskComponent taskComponent) {
|
||||||
if ( contextMenus.get(taskComponent) == null ) {
|
if ( contextMenus.get(taskComponent) == null ) {
|
||||||
|
|
@ -295,7 +310,6 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
if ( disabilityConfiguration.isAddingDependenciesEnabled() ) {
|
if ( disabilityConfiguration.isAddingDependenciesEnabled() ) {
|
||||||
menuBuilder.item(_("Add Dependency"), "/common/img/ico_dependency.png",
|
menuBuilder.item(_("Add Dependency"), "/common/img/ico_dependency.png",
|
||||||
new ItemAction<TaskComponent>() {
|
new ItemAction<TaskComponent>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(TaskComponent choosen, Event event) {
|
public void onEvent(TaskComponent choosen, Event event) {
|
||||||
choosen.addDependency();
|
choosen.addDependency();
|
||||||
|
|
@ -308,10 +322,13 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
menuBuilder.item(command.getName(), command.getIcon(), command.toItemAction());
|
menuBuilder.item(command.getName(), command.getIcon(), command.toItemAction());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Menupopup result = menuBuilder.createWithoutSettingContext();
|
Menupopup result = menuBuilder.createWithoutSettingContext();
|
||||||
contextMenus.put(taskComponent, result);
|
contextMenus.put(taskComponent, result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return contextMenus.get(taskComponent);
|
return contextMenus.get(taskComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -330,16 +347,16 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
public void remove(Task task) {
|
public void remove(Task task) {
|
||||||
currentTotalTasks.remove(task);
|
currentTotalTasks.remove(task);
|
||||||
for (TaskComponent taskComponent : getTaskComponents()) {
|
for (TaskComponent taskComponent : getTaskComponents()) {
|
||||||
if (taskComponent.getTask().equals(task)) {
|
if ( taskComponent.getTask().equals(task) ) {
|
||||||
taskComponent.remove();
|
taskComponent.remove();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDependency(TaskComponent source, TaskComponent destination) {
|
public void addDependency(TaskComponent source, TaskComponent destination) {
|
||||||
context.addDependency(new Dependency(source.getTask(), destination
|
context.addDependency(new Dependency(source.getTask(), destination.getTask(), DependencyType.END_START));
|
||||||
.getTask(), DependencyType.END_START));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDisabilityConfiguration getDisabilityConfiguration() {
|
public IDisabilityConfiguration getDisabilityConfiguration() {
|
||||||
|
|
@ -347,7 +364,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reload(boolean relocate) {
|
private void reload(boolean relocate) {
|
||||||
ArrayList<Task> tasksPendingToAdd = new ArrayList<Task>();
|
ArrayList<Task> tasksPendingToAdd = new ArrayList<>();
|
||||||
reload(currentTotalTasks, tasksPendingToAdd, relocate);
|
reload(currentTotalTasks, tasksPendingToAdd, relocate);
|
||||||
addPendingTasks(tasksPendingToAdd, null, relocate);
|
addPendingTasks(tasksPendingToAdd, null, relocate);
|
||||||
getGanttPanel().getDependencyList().redrawDependencies();
|
getGanttPanel().getDependencyList().redrawDependencies();
|
||||||
|
|
@ -358,6 +375,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
if ( visibleTasks.contains(task) ) {
|
if ( visibleTasks.contains(task) ) {
|
||||||
addPendingTasks(tasksPendingToAdd, rowFor(task), relocate);
|
addPendingTasks(tasksPendingToAdd, rowFor(task), relocate);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean isShown = visibleTasks.contains(task);
|
final boolean isShown = visibleTasks.contains(task);
|
||||||
|
|
||||||
if ( predicate.accepts(task) != isShown ) {
|
if ( predicate.accepts(task) != isShown ) {
|
||||||
|
|
@ -367,6 +385,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
tasksPendingToAdd.add(task);
|
tasksPendingToAdd.add(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( task instanceof TaskContainer ) {
|
if ( task instanceof TaskContainer ) {
|
||||||
reload(task.getTasks(), tasksPendingToAdd, relocate);
|
reload(task.getTasks(), tasksPendingToAdd, relocate);
|
||||||
}
|
}
|
||||||
|
|
@ -389,6 +408,7 @@ public class TaskList extends XulElement implements AfterCompose {
|
||||||
if ( tasksPendingToAdd.isEmpty() ) {
|
if ( tasksPendingToAdd.isEmpty() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TaskComponent each : createAndPublishComponentsIfNeeded(tasksPendingToAdd)) {
|
for (TaskComponent each : createAndPublishComponentsIfNeeded(tasksPendingToAdd)) {
|
||||||
addTaskComponent(insertBefore, each, relocate);
|
addTaskComponent(insertBefore, each, relocate);
|
||||||
visibleTasks.add(each.getTask());
|
visibleTasks.add(each.getTask());
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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.Planner;
|
||||||
import org.zkoss.ganttz.data.GanttDate;
|
import org.zkoss.ganttz.data.GanttDate;
|
||||||
import org.zkoss.ganttz.data.GanttDiagramGraph.IGraphChangeListener;
|
import org.zkoss.ganttz.data.GanttDiagramGraph.IGraphChangeListener;
|
||||||
|
|
@ -53,15 +53,15 @@ import org.zkoss.zk.ui.Component;
|
||||||
public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
||||||
|
|
||||||
public interface IPrintAction {
|
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 interface IReloadChartListener {
|
||||||
public void reloadChart();
|
void reloadChart();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class NullCommand<T> implements ICommand<T> {
|
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<? 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;
|
private Component chartComponent;
|
||||||
|
|
||||||
|
|
@ -167,26 +167,25 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
||||||
|
|
||||||
// private String identifier = null;
|
// private String identifier = null;
|
||||||
|
|
||||||
private IDetailItemModificator firstLevelModificators = SeveralModificators
|
private IDetailItemModificator firstLevelModificators = SeveralModificators.empty();
|
||||||
.empty();
|
|
||||||
|
|
||||||
private IDetailItemModificator secondLevelModificators = SeveralModificators
|
private IDetailItemModificator secondLevelModificators = SeveralModificators.empty();
|
||||||
.empty();
|
|
||||||
|
|
||||||
private List<IReloadChartListener> reloadChartListeners = new ArrayList<IReloadChartListener>();
|
private List<IReloadChartListener> reloadChartListeners = new ArrayList<>();
|
||||||
|
|
||||||
private IPrintAction printAction;
|
private IPrintAction printAction;
|
||||||
|
|
||||||
private boolean expandPlanningViewCharts;
|
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;
|
private boolean scheduleBackwards = false;
|
||||||
|
|
||||||
public PlannerConfiguration(IAdapterToTaskFundamentalProperties<T> adapter,
|
public PlannerConfiguration(IAdapterToTaskFundamentalProperties<T> adapter,
|
||||||
IStructureNavigator<T> navigator, List<? extends T> data) {
|
IStructureNavigator<T> navigator,
|
||||||
|
List<? extends T> data) {
|
||||||
this.adapter = adapter;
|
this.adapter = adapter;
|
||||||
this.navigator = navigator;
|
this.navigator = navigator;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
|
@ -234,8 +233,7 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
||||||
this.notAfterThan = GanttDate.createFrom(notAfterThan);
|
this.notAfterThan = GanttDate.createFrom(notAfterThan);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGoingDownInLastArrowCommand(
|
public void setGoingDownInLastArrowCommand(ICommand<T> goingDownInLastArrowCommand) {
|
||||||
ICommand<T> goingDownInLastArrowCommand) {
|
|
||||||
Validate.notNull(goingDownInLastArrowCommand);
|
Validate.notNull(goingDownInLastArrowCommand);
|
||||||
this.goingDownInLastArrowCommand = goingDownInLastArrowCommand;
|
this.goingDownInLastArrowCommand = goingDownInLastArrowCommand;
|
||||||
}
|
}
|
||||||
|
|
@ -293,11 +291,11 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
||||||
this.editingDatesEnabled = editingDatesEnabled;
|
this.editingDatesEnabled = editingDatesEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Constraint<GanttDate>> getStartConstraintsGiven(
|
public static List<Constraint<GanttDate>> getStartConstraintsGiven(GanttDate notBeforeThan) {
|
||||||
GanttDate notBeforeThan) {
|
if ( notBeforeThan != null ) {
|
||||||
if (notBeforeThan != null) {
|
|
||||||
return Collections.singletonList(biggerOrEqualThan(notBeforeThan));
|
return Collections.singletonList(biggerOrEqualThan(notBeforeThan));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -305,11 +303,11 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
||||||
return getStartConstraintsGiven(notBeforeThan);
|
return getStartConstraintsGiven(notBeforeThan);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Constraint<GanttDate>> getEndConstraintsGiven(
|
public static List<Constraint<GanttDate>> getEndConstraintsGiven(GanttDate notAfterThan) {
|
||||||
GanttDate notAfterThan) {
|
if ( notAfterThan != null ) {
|
||||||
if (notAfterThan != null) {
|
|
||||||
return Collections.singletonList(lessOrEqualThan(notAfterThan));
|
return Collections.singletonList(lessOrEqualThan(notAfterThan));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -401,20 +399,16 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
||||||
return secondLevelModificators;
|
return secondLevelModificators;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSecondLevelModificators(
|
public void setSecondLevelModificators(IDetailItemModificator... secondLevelModificators) {
|
||||||
IDetailItemModificator... secondLevelModificators) {
|
this.secondLevelModificators = SeveralModificators.create(secondLevelModificators);
|
||||||
this.secondLevelModificators = SeveralModificators
|
|
||||||
.create(secondLevelModificators);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDetailItemModificator getFirstLevelModificators() {
|
public IDetailItemModificator getFirstLevelModificators() {
|
||||||
return firstLevelModificators;
|
return firstLevelModificators;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFirstLevelModificators(
|
public void setFirstLevelModificators(IDetailItemModificator... firstLevelModificators) {
|
||||||
IDetailItemModificator... firstLevelModificators) {
|
this.firstLevelModificators = SeveralModificators.create(firstLevelModificators);
|
||||||
this.firstLevelModificators = SeveralModificators
|
|
||||||
.create(firstLevelModificators);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addReloadChartListener(IReloadChartListener reloadChartListener) {
|
public void addReloadChartListener(IReloadChartListener reloadChartListener) {
|
||||||
|
|
@ -437,21 +431,21 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void print() {
|
public void print() {
|
||||||
if (!isPrintEnabled()) {
|
if ( !isPrintEnabled() ) {
|
||||||
throw new UnsupportedOperationException("print not supported");
|
throw new UnsupportedOperationException("print not supported");
|
||||||
}
|
}
|
||||||
printAction.doPrint();
|
printAction.doPrint();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void print(Map<String, String> parameters) {
|
public void print(Map<String, String> parameters) {
|
||||||
if (!isPrintEnabled()) {
|
if ( !isPrintEnabled() ) {
|
||||||
throw new UnsupportedOperationException("print not supported");
|
throw new UnsupportedOperationException("print not supported");
|
||||||
}
|
}
|
||||||
printAction.doPrint(parameters);
|
printAction.doPrint(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void print(HashMap<String, String> parameters, Planner planner) {
|
public void print(HashMap<String, String> parameters, Planner planner) {
|
||||||
if (!isPrintEnabled()) {
|
if ( !isPrintEnabled() ) {
|
||||||
throw new UnsupportedOperationException("print not supported");
|
throw new UnsupportedOperationException("print not supported");
|
||||||
}
|
}
|
||||||
printAction.doPrint(parameters, planner);
|
printAction.doPrint(parameters, planner);
|
||||||
|
|
@ -466,18 +460,16 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
||||||
return expandPlanningViewCharts;
|
return expandPlanningViewCharts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPreGraphChangeListener(
|
public void addPreGraphChangeListener(IGraphChangeListener preGraphChangeListener) {
|
||||||
IGraphChangeListener preGraphChangeListener) {
|
|
||||||
Validate.notNull(preGraphChangeListener);
|
Validate.notNull(preGraphChangeListener);
|
||||||
if (!preGraphChangeListeners.contains(preGraphChangeListener)) {
|
if ( !preGraphChangeListeners.contains(preGraphChangeListener) ) {
|
||||||
preGraphChangeListeners.add(preGraphChangeListener);
|
preGraphChangeListeners.add(preGraphChangeListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPostGraphChangeListener(
|
public void addPostGraphChangeListener(IGraphChangeListener postGraphChangeListener) {
|
||||||
IGraphChangeListener postGraphChangeListener) {
|
|
||||||
Validate.notNull(postGraphChangeListener);
|
Validate.notNull(postGraphChangeListener);
|
||||||
if (!postGraphChangeListeners.contains(postGraphChangeListener)) {
|
if ( !postGraphChangeListeners.contains(postGraphChangeListener) ) {
|
||||||
postGraphChangeListeners.add(postGraphChangeListener);
|
postGraphChangeListeners.add(postGraphChangeListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
import org.zkoss.ganttz.data.DependencyType.Point;
|
import org.zkoss.ganttz.data.DependencyType.Point;
|
||||||
import org.zkoss.ganttz.data.constraint.Constraint;
|
import org.zkoss.ganttz.data.constraint.Constraint;
|
||||||
import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener;
|
import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener;
|
||||||
|
|
@ -42,12 +42,14 @@ public class Dependency implements IDependency<Task> {
|
||||||
|
|
||||||
public static List<Constraint<GanttDate>> getConstraintsFor(
|
public static List<Constraint<GanttDate>> getConstraintsFor(
|
||||||
ConstraintCalculator<Task> calculator,
|
ConstraintCalculator<Task> calculator,
|
||||||
Collection<Dependency> dependencies, Point pointBeingModified) {
|
Collection<Dependency> dependencies,
|
||||||
List<Constraint<GanttDate>> result = new ArrayList<Constraint<GanttDate>>();
|
Point pointBeingModified) {
|
||||||
|
|
||||||
|
List<Constraint<GanttDate>> result = new ArrayList<>();
|
||||||
for (Dependency each : dependencies) {
|
for (Dependency each : dependencies) {
|
||||||
result.addAll(each.withViolationNotification(calculator
|
result.addAll(each.withViolationNotification(calculator.getConstraints(each, pointBeingModified)));
|
||||||
.getConstraints(each, pointBeingModified)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,60 +61,62 @@ public class Dependency implements IDependency<Task> {
|
||||||
|
|
||||||
private final boolean visible;
|
private final boolean visible;
|
||||||
|
|
||||||
private ConstraintViolationNotificator<GanttDate> violationsNotificator = ConstraintViolationNotificator
|
private ConstraintViolationNotificator<GanttDate> violationsNotificator = ConstraintViolationNotificator.create();
|
||||||
.create();
|
|
||||||
|
|
||||||
public Dependency(Task source, Task destination,
|
public Dependency(Task source, Task destination, DependencyType type, boolean visible) {
|
||||||
DependencyType type, boolean visible) {
|
if ( source == null ) {
|
||||||
if (source == null) {
|
|
||||||
throw new IllegalArgumentException("source cannot be null");
|
throw new IllegalArgumentException("source cannot be null");
|
||||||
}
|
}
|
||||||
if (destination == null) {
|
|
||||||
|
if ( destination == null ) {
|
||||||
throw new IllegalArgumentException("destination cannot be null");
|
throw new IllegalArgumentException("destination cannot be null");
|
||||||
}
|
}
|
||||||
if (type == null) {
|
|
||||||
|
if ( type == null ) {
|
||||||
throw new IllegalArgumentException("type cannot be null");
|
throw new IllegalArgumentException("type cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.visible = visible;
|
this.visible = visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dependency(Task source, Task destination,
|
public Dependency(Task source, Task destination, DependencyType type) {
|
||||||
DependencyType type) {
|
|
||||||
this(source, destination, type, true);
|
this(source, destination, type, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Constraint<GanttDate>> withViolationNotification(
|
private List<Constraint<GanttDate>> withViolationNotification(List<Constraint<GanttDate>> original) {
|
||||||
List<Constraint<GanttDate>> original) {
|
|
||||||
return violationsNotificator.withListener(original);
|
return violationsNotificator.withListener(original);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addConstraintViolationListener(
|
public void addConstraintViolationListener(IConstraintViolationListener<GanttDate> listener, Mode mode) {
|
||||||
IConstraintViolationListener<GanttDate> listener, Mode mode) {
|
|
||||||
violationsNotificator.addConstraintViolationListener(listener, mode);
|
violationsNotificator.addConstraintViolationListener(listener, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return new HashCodeBuilder().append(source).append(destination).append(
|
return new HashCodeBuilder().append(source).append(destination).append(type).toHashCode();
|
||||||
type).toHashCode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) {
|
if ( this == obj ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (obj == null) {
|
|
||||||
|
if ( obj == null ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (getClass() != obj.getClass()) {
|
|
||||||
|
if ( getClass() != obj.getClass() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dependency other = (Dependency) obj;
|
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.source, other.source)
|
||||||
.append(this.type, other.type).isEquals();
|
.append(this.type, other.type).isEquals();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.zkoss.ganttz.IDatesMapper;
|
import org.zkoss.ganttz.IDatesMapper;
|
||||||
|
|
||||||
|
|
@ -60,16 +60,18 @@ import org.zkoss.ganttz.IDatesMapper;
|
||||||
public abstract class GanttDate implements Comparable<GanttDate> {
|
public abstract class GanttDate implements Comparable<GanttDate> {
|
||||||
|
|
||||||
public static LocalDateBased createFrom(Date date) {
|
public static LocalDateBased createFrom(Date date) {
|
||||||
if (date == null) {
|
if ( date == null ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return createFrom(LocalDate.fromDateFields(date));
|
return createFrom(LocalDate.fromDateFields(date));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LocalDateBased createFrom(LocalDate localDate) {
|
public static LocalDateBased createFrom(LocalDate localDate) {
|
||||||
if (localDate == null) {
|
if ( localDate == null ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LocalDateBased(localDate);
|
return new LocalDateBased(localDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,13 +85,15 @@ public abstract class GanttDate implements Comparable<GanttDate> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean equals(Object obj) {
|
public final boolean equals(Object obj) {
|
||||||
if (obj == this) {
|
if ( obj == this ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (obj instanceof GanttDate) {
|
|
||||||
|
if ( obj instanceof GanttDate ) {
|
||||||
GanttDate other = (GanttDate) obj;
|
GanttDate other = (GanttDate) obj;
|
||||||
return isEqualsTo(other);
|
return isEqualsTo(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,13 +103,12 @@ public abstract class GanttDate implements Comparable<GanttDate> {
|
||||||
public abstract int hashCode();
|
public abstract int hashCode();
|
||||||
|
|
||||||
public interface ICases<R> {
|
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
|
public static abstract class Cases<T extends CustomDate, R> implements ICases<R> {
|
||||||
ICases<R> {
|
|
||||||
|
|
||||||
private final Class<T> klass;
|
private final Class<T> klass;
|
||||||
|
|
||||||
|
|
@ -243,6 +246,7 @@ public abstract class GanttDate implements Comparable<GanttDate> {
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(GanttDate o) {
|
public int compareTo(GanttDate o) {
|
||||||
return o.byCases(new ICases<Integer>() {
|
return o.byCases(new ICases<Integer>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer on(LocalDateBased localDateBased) {
|
public Integer on(LocalDateBased localDateBased) {
|
||||||
return compareToLocalDate(localDateBased.localDate);
|
return compareToLocalDate(localDateBased.localDate);
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@ import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.jgrapht.DirectedGraph;
|
import org.jgrapht.DirectedGraph;
|
||||||
|
|
@ -197,7 +197,6 @@ public class GanttDiagramGraph<V, D extends IDependency<V>> implements ICritical
|
||||||
@Override
|
@Override
|
||||||
public void setEndDateFor(Task task, final GanttDate newEnd) {
|
public void setEndDateFor(Task task, final GanttDate newEnd) {
|
||||||
task.doPositionModifications(new IModifications() {
|
task.doPositionModifications(new IModifications() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doIt(IUpdatablePosition position) {
|
public void doIt(IUpdatablePosition position) {
|
||||||
position.setEndDate(newEnd);
|
position.setEndDate(newEnd);
|
||||||
|
|
@ -213,7 +212,6 @@ public class GanttDiagramGraph<V, D extends IDependency<V>> implements ICritical
|
||||||
@Override
|
@Override
|
||||||
public void setStartDateFor(Task task, final GanttDate newStart) {
|
public void setStartDateFor(Task task, final GanttDate newStart) {
|
||||||
task.doPositionModifications(new IModifications() {
|
task.doPositionModifications(new IModifications() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doIt(IUpdatablePosition position) {
|
public void doIt(IUpdatablePosition position) {
|
||||||
position.setBeginDate(newStart);
|
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> {
|
public static class GanttZKDiagramGraph extends GanttDiagramGraph<Task, Dependency> {
|
||||||
|
|
||||||
private GanttZKDiagramGraph(boolean scheduleBackwards, List<Constraint<GanttDate>> globalStartConstraints,
|
private GanttZKDiagramGraph(
|
||||||
List<Constraint<GanttDate>> globalEndConstraints, boolean dependenciesConstraintsHavePriority) {
|
boolean scheduleBackwards,
|
||||||
|
List<Constraint<GanttDate>> globalStartConstraints,
|
||||||
|
List<Constraint<GanttDate>> globalEndConstraints,
|
||||||
|
boolean dependenciesConstraintsHavePriority) {
|
||||||
|
|
||||||
super(scheduleBackwards, GANTTZK_ADAPTER, globalStartConstraints, globalEndConstraints,
|
super(scheduleBackwards, GANTTZK_ADAPTER, globalStartConstraints, globalEndConstraints,
|
||||||
dependenciesConstraintsHavePriority);
|
dependenciesConstraintsHavePriority);
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a position for a task <br />
|
* Represents a position for a task <br />
|
||||||
|
|
@ -40,13 +40,13 @@ public abstract class Position {
|
||||||
* @param positionInParent
|
* @param positionInParent
|
||||||
* @return a {@link Position} specified by the params
|
* @return a {@link Position} specified by the params
|
||||||
*/
|
*/
|
||||||
public static Position createPosition(
|
public static Position createPosition(List<? extends TaskContainer> parents, int positionInParent) {
|
||||||
List<? extends TaskContainer> parents, int positionInParent) {
|
|
||||||
Validate.notEmpty(parents);
|
Validate.notEmpty(parents);
|
||||||
Validate.noNullElements(parents);
|
Validate.noNullElements(parents);
|
||||||
Validate.isTrue(positionInParent >= 0);
|
Validate.isTrue(positionInParent >= 0);
|
||||||
Task firstParent = parents.get(0);
|
Task firstParent = parents.get(0);
|
||||||
Validate.isTrue(positionInParent < firstParent.getTasks().size());
|
Validate.isTrue(positionInParent < firstParent.getTasks().size());
|
||||||
|
|
||||||
return new ChildPosition(parents, positionInParent);
|
return new ChildPosition(parents, positionInParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,9 +115,10 @@ public abstract class Position {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Position down(TaskContainer current, int positionInParent) {
|
public Position down(TaskContainer current, int positionInParent) {
|
||||||
List<TaskContainer> ancestors = new ArrayList<TaskContainer>();
|
List<TaskContainer> ancestors = new ArrayList<>();
|
||||||
ancestors.add(current);
|
ancestors.add(current);
|
||||||
ancestors.addAll(getAncestors());
|
ancestors.addAll(getAncestors());
|
||||||
|
|
||||||
return new ChildPosition(ancestors, positionInParent);
|
return new ChildPosition(ancestors, positionInParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,11 +128,12 @@ public abstract class Position {
|
||||||
private static class ChildPosition extends Position {
|
private static class ChildPosition extends Position {
|
||||||
|
|
||||||
private final List<? extends TaskContainer> parents;
|
private final List<? extends TaskContainer> parents;
|
||||||
|
|
||||||
private TaskContainer parent;
|
private TaskContainer parent;
|
||||||
|
|
||||||
ChildPosition(List<? extends TaskContainer> parents,
|
ChildPosition(List<? extends TaskContainer> parents, int positionInParent) {
|
||||||
int positionInParent) {
|
|
||||||
super(positionInParent);
|
super(positionInParent);
|
||||||
|
|
||||||
this.parents = parents;
|
this.parents = parents;
|
||||||
this.parent = parents.get(0);
|
this.parent = parents.get(0);
|
||||||
}
|
}
|
||||||
|
|
@ -153,8 +155,7 @@ public abstract class Position {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Position pop() {
|
public Position pop() {
|
||||||
return new ChildPosition(parents.subList(0, parents.size() - 1),
|
return new ChildPosition(parents.subList(0, parents.size() - 1), getInsertionPosition());
|
||||||
getInsertionPosition());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
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.Duration;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.joda.time.ReadableDuration;
|
import org.joda.time.ReadableDuration;
|
||||||
|
|
@ -56,28 +56,22 @@ import org.zkoss.ganttz.util.WeakReferencedListeners.Mode;
|
||||||
public abstract class Task implements ITaskFundamentalProperties {
|
public abstract class Task implements ITaskFundamentalProperties {
|
||||||
|
|
||||||
public interface IReloadResourcesTextRequested {
|
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(
|
private PropertyChangeSupport fundamentalPropertiesListeners = new PropertyChangeSupport(this);
|
||||||
this);
|
|
||||||
|
|
||||||
private PropertyChangeSupport visibilityProperties = new PropertyChangeSupport(
|
private PropertyChangeSupport visibilityProperties = new PropertyChangeSupport(this);
|
||||||
this);
|
|
||||||
|
|
||||||
private PropertyChangeSupport criticalPathProperty = new PropertyChangeSupport(
|
private PropertyChangeSupport criticalPathProperty = new PropertyChangeSupport(this);
|
||||||
this);
|
|
||||||
|
|
||||||
private PropertyChangeSupport advancesProperty = new PropertyChangeSupport(
|
private PropertyChangeSupport advancesProperty = new PropertyChangeSupport(this);
|
||||||
this);
|
|
||||||
|
|
||||||
private PropertyChangeSupport reportedHoursProperty = new PropertyChangeSupport(
|
private PropertyChangeSupport reportedHoursProperty = new PropertyChangeSupport(this);
|
||||||
this);
|
|
||||||
|
|
||||||
private PropertyChangeSupport moneyCostBarProperty = new PropertyChangeSupport(
|
private PropertyChangeSupport moneyCostBarProperty = new PropertyChangeSupport(this);
|
||||||
this);
|
|
||||||
|
|
||||||
private final ITaskFundamentalProperties fundamentalProperties;
|
private final ITaskFundamentalProperties fundamentalProperties;
|
||||||
|
|
||||||
|
|
@ -91,19 +85,18 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
|
|
||||||
private boolean showingMoneyCostBar = false;
|
private boolean showingMoneyCostBar = false;
|
||||||
|
|
||||||
private ConstraintViolationNotificator<GanttDate> violationNotificator = ConstraintViolationNotificator
|
private ConstraintViolationNotificator<GanttDate> violationNotificator = ConstraintViolationNotificator.create();
|
||||||
.create();
|
|
||||||
|
|
||||||
private IDependenciesEnforcerHook dependenciesEnforcerHook = GanttDiagramGraph
|
private IDependenciesEnforcerHook dependenciesEnforcerHook = GanttDiagramGraph.doNothingHook();
|
||||||
.doNothingHook();
|
|
||||||
|
|
||||||
private final INotificationAfterDependenciesEnforcement notifyDates = new INotificationAfterDependenciesEnforcement() {
|
|
||||||
|
|
||||||
|
private final INotificationAfterDependenciesEnforcement notifyDates =
|
||||||
|
new INotificationAfterDependenciesEnforcement() {
|
||||||
@Override
|
@Override
|
||||||
public void onStartDateChange(GanttDate previousStart,
|
public void onStartDateChange(GanttDate previousStart, GanttDate previousEnd, GanttDate newStart) {
|
||||||
GanttDate previousEnd, GanttDate newStart) {
|
|
||||||
fundamentalPropertiesListeners.firePropertyChange("beginDate",
|
fundamentalPropertiesListeners.firePropertyChange(
|
||||||
previousStart, fundamentalProperties.getBeginDate());
|
"beginDate", previousStart, fundamentalProperties.getBeginDate());
|
||||||
|
|
||||||
fireEndDate(previousEnd);
|
fireEndDate(previousEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,8 +106,8 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fireEndDate(GanttDate previousEnd) {
|
private void fireEndDate(GanttDate previousEnd) {
|
||||||
fundamentalPropertiesListeners.firePropertyChange("endDate",
|
fundamentalPropertiesListeners.firePropertyChange(
|
||||||
previousEnd, fundamentalProperties.getEndDate());
|
"endDate", previousEnd, fundamentalProperties.getEndDate());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -124,13 +117,11 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Constraint<GanttDate>> getStartConstraints() {
|
public List<Constraint<GanttDate>> getStartConstraints() {
|
||||||
return violationNotificator.withListener(fundamentalProperties
|
return violationNotificator.withListener(fundamentalProperties.getStartConstraints());
|
||||||
.getStartConstraints());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Constraint<GanttDate>> getEndConstraints() {
|
public List<Constraint<GanttDate>> getEndConstraints() {
|
||||||
return violationNotificator.withListener(fundamentalProperties
|
return violationNotificator.withListener(fundamentalProperties.getEndConstraints());
|
||||||
.getEndConstraints());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -149,13 +140,13 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEndDate(GanttDate value) {
|
public void setEndDate(GanttDate value) {
|
||||||
if (value == null) {
|
if ( value == null ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GanttDate previousEnd = fundamentalProperties.getEndDate();
|
GanttDate previousEnd = fundamentalProperties.getEndDate();
|
||||||
getFundamentalPropertiesPosition().setEndDate(value);
|
getFundamentalPropertiesPosition().setEndDate(value);
|
||||||
dependenciesEnforcerHook.setNewEnd(previousEnd,
|
dependenciesEnforcerHook.setNewEnd(previousEnd, fundamentalProperties.getEndDate());
|
||||||
fundamentalProperties.getEndDate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -163,8 +154,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
GanttDate previousValue = fundamentalProperties.getBeginDate();
|
GanttDate previousValue = fundamentalProperties.getBeginDate();
|
||||||
GanttDate previousEnd = fundamentalProperties.getEndDate();
|
GanttDate previousEnd = fundamentalProperties.getEndDate();
|
||||||
getFundamentalPropertiesPosition().setBeginDate(newStart);
|
getFundamentalPropertiesPosition().setBeginDate(newStart);
|
||||||
dependenciesEnforcerHook.setStartDate(previousValue, previousEnd,
|
dependenciesEnforcerHook.setStartDate(previousValue, previousEnd, newStart);
|
||||||
newStart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -179,20 +169,18 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
GanttDate previousStart = getBeginDate();
|
GanttDate previousStart = getBeginDate();
|
||||||
GanttDate previousEnd = getEndDate();
|
GanttDate previousEnd = getEndDate();
|
||||||
getFundamentalPropertiesPosition().moveTo(date);
|
getFundamentalPropertiesPosition().moveTo(date);
|
||||||
dependenciesEnforcerHook.setStartDate(previousStart, previousEnd,
|
dependenciesEnforcerHook.setStartDate(previousStart, previousEnd, date);
|
||||||
date);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IUpdatablePosition getFundamentalPropertiesPosition() {
|
private IUpdatablePosition getFundamentalPropertiesPosition() {
|
||||||
final IUpdatablePosition[] result = new IUpdatablePosition[1];
|
final IUpdatablePosition[] result = new IUpdatablePosition[1];
|
||||||
fundamentalProperties.doPositionModifications(new IModifications() {
|
fundamentalProperties.doPositionModifications(new IModifications() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doIt(IUpdatablePosition position) {
|
public void doIt(IUpdatablePosition position) {
|
||||||
result[0] = position;
|
result[0] = position;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
assert result[0] != null;
|
|
||||||
return result[0];
|
return result[0];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -203,8 +191,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
|
|
||||||
public abstract boolean isExpanded() throws UnsupportedOperationException;
|
public abstract boolean isExpanded() throws UnsupportedOperationException;
|
||||||
|
|
||||||
public abstract List<Task> getTasks()
|
public abstract List<Task> getTasks() throws UnsupportedOperationException;
|
||||||
throws UnsupportedOperationException;
|
|
||||||
|
|
||||||
public boolean isVisible() {
|
public boolean isVisible() {
|
||||||
return visible;
|
return visible;
|
||||||
|
|
@ -213,8 +200,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
public void setVisible(boolean visible) {
|
public void setVisible(boolean visible) {
|
||||||
boolean previousValue = this.visible;
|
boolean previousValue = this.visible;
|
||||||
this.visible = visible;
|
this.visible = visible;
|
||||||
visibilityProperties.firePropertyChange("visible", previousValue,
|
visibilityProperties.firePropertyChange("visible", previousValue, this.visible);
|
||||||
this.visible);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInCriticalPath() {
|
public boolean isInCriticalPath() {
|
||||||
|
|
@ -224,15 +210,13 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
public void setInCriticalPath(boolean inCriticalPath) {
|
public void setInCriticalPath(boolean inCriticalPath) {
|
||||||
boolean previousValue = this.inCriticalPath;
|
boolean previousValue = this.inCriticalPath;
|
||||||
this.inCriticalPath = inCriticalPath;
|
this.inCriticalPath = inCriticalPath;
|
||||||
criticalPathProperty.firePropertyChange("inCriticalPath",
|
criticalPathProperty.firePropertyChange("inCriticalPath", previousValue, this.inCriticalPath);
|
||||||
previousValue, this.inCriticalPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowingAdvances(boolean showingAdvances) {
|
public void setShowingAdvances(boolean showingAdvances) {
|
||||||
boolean previousValue = this.showingAdvances;
|
boolean previousValue = this.showingAdvances;
|
||||||
this.showingAdvances = showingAdvances;
|
this.showingAdvances = showingAdvances;
|
||||||
advancesProperty.firePropertyChange("showingAdvances", previousValue,
|
advancesProperty.firePropertyChange("showingAdvances", previousValue, this.showingAdvances);
|
||||||
this.showingAdvances);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowingAdvances() {
|
public boolean isShowingAdvances() {
|
||||||
|
|
@ -242,8 +226,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
public void setShowingReportedHours(boolean showingReportedHours) {
|
public void setShowingReportedHours(boolean showingReportedHours) {
|
||||||
boolean previousValue = this.showingReportedHours;
|
boolean previousValue = this.showingReportedHours;
|
||||||
this.showingReportedHours = showingReportedHours;
|
this.showingReportedHours = showingReportedHours;
|
||||||
reportedHoursProperty.firePropertyChange("showingReportedHours",
|
reportedHoursProperty.firePropertyChange("showingReportedHours", previousValue, this.showingReportedHours);
|
||||||
previousValue, this.showingReportedHours);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowingReportedHours() {
|
public boolean isShowingReportedHours() {
|
||||||
|
|
@ -253,8 +236,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
public void setShowingMoneyCostBar(boolean showingMoneyCostBar) {
|
public void setShowingMoneyCostBar(boolean showingMoneyCostBar) {
|
||||||
boolean previousValue = this.showingMoneyCostBar;
|
boolean previousValue = this.showingMoneyCostBar;
|
||||||
this.showingMoneyCostBar = showingMoneyCostBar;
|
this.showingMoneyCostBar = showingMoneyCostBar;
|
||||||
moneyCostBarProperty.firePropertyChange("showingMoneyCostBar",
|
moneyCostBarProperty.firePropertyChange("showingMoneyCostBar", previousValue, this.showingMoneyCostBar);
|
||||||
previousValue, this.showingMoneyCostBar);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowingMoneyCostBar() {
|
public boolean isShowingMoneyCostBar() {
|
||||||
|
|
@ -268,12 +250,10 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
String previousValue = fundamentalProperties.getName();
|
String previousValue = fundamentalProperties.getName();
|
||||||
fundamentalProperties.setName(name);
|
fundamentalProperties.setName(name);
|
||||||
fundamentalPropertiesListeners.firePropertyChange("name",
|
fundamentalPropertiesListeners.firePropertyChange("name", previousValue, name);
|
||||||
previousValue, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerDependenciesEnforcerHook(
|
public void registerDependenciesEnforcerHook(IDependenciesEnforcerHookFactory<Task> factory) {
|
||||||
IDependenciesEnforcerHookFactory<Task> factory) {
|
|
||||||
Validate.notNull(factory);
|
Validate.notNull(factory);
|
||||||
dependenciesEnforcerHook = factory.create(this, notifyDates);
|
dependenciesEnforcerHook = factory.create(this, notifyDates);
|
||||||
Validate.notNull(dependenciesEnforcerHook);
|
Validate.notNull(dependenciesEnforcerHook);
|
||||||
|
|
@ -288,52 +268,42 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLengthMilliseconds() {
|
public long getLengthMilliseconds() {
|
||||||
return getEndDate().toDayRoundedDate().getTime()
|
return getEndDate().toDayRoundedDate().getTime() - getBeginDate().toDayRoundedDate().getTime();
|
||||||
- getBeginDate().toDayRoundedDate().getTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadableDuration getLength() {
|
public ReadableDuration getLength() {
|
||||||
return new Duration(getBeginDate().toDayRoundedDate().getTime(),
|
return new Duration(getBeginDate().toDayRoundedDate().getTime(), getEndDate().toDayRoundedDate().getTime());
|
||||||
getEndDate().toDayRoundedDate().getTime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addVisibilityPropertiesChangeListener(
|
public void addVisibilityPropertiesChangeListener(PropertyChangeListener listener) {
|
||||||
PropertyChangeListener listener) {
|
|
||||||
this.visibilityProperties.addPropertyChangeListener(listener);
|
this.visibilityProperties.addPropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCriticalPathPropertyChangeListener(
|
public void addCriticalPathPropertyChangeListener(PropertyChangeListener listener) {
|
||||||
PropertyChangeListener listener) {
|
|
||||||
this.criticalPathProperty.addPropertyChangeListener(listener);
|
this.criticalPathProperty.addPropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAdvancesPropertyChangeListener(
|
public void addAdvancesPropertyChangeListener(PropertyChangeListener listener) {
|
||||||
PropertyChangeListener listener) {
|
|
||||||
this.advancesProperty.addPropertyChangeListener(listener);
|
this.advancesProperty.addPropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addReportedHoursPropertyChangeListener(
|
public void addReportedHoursPropertyChangeListener(PropertyChangeListener listener) {
|
||||||
PropertyChangeListener listener) {
|
|
||||||
this.reportedHoursProperty.addPropertyChangeListener(listener);
|
this.reportedHoursProperty.addPropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addMoneyCostBarPropertyChangeListener(
|
public void addMoneyCostBarPropertyChangeListener(PropertyChangeListener listener) {
|
||||||
PropertyChangeListener listener) {
|
|
||||||
this.moneyCostBarProperty.addPropertyChangeListener(listener);
|
this.moneyCostBarProperty.addPropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addFundamentalPropertiesChangeListener(
|
public void addFundamentalPropertiesChangeListener(PropertyChangeListener listener) {
|
||||||
PropertyChangeListener listener) {
|
|
||||||
this.fundamentalPropertiesListeners.addPropertyChangeListener(listener);
|
this.fundamentalPropertiesListeners.addPropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||||
this.fundamentalPropertiesListeners
|
this.fundamentalPropertiesListeners.removePropertyChangeListener(listener);
|
||||||
.removePropertyChangeListener(listener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeVisibilityPropertiesChangeListener(
|
public void removeVisibilityPropertiesChangeListener(PropertyChangeListener listener) {
|
||||||
PropertyChangeListener listener) {
|
|
||||||
this.visibilityProperties.removePropertyChangeListener(listener);
|
this.visibilityProperties.removePropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -344,16 +314,15 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Constraint<GanttDate>> getCurrentLengthConstraint() {
|
public List<Constraint<GanttDate>> getCurrentLengthConstraint() {
|
||||||
if (isContainer()) {
|
if ( isContainer() ) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return violationNotificator.withListener(fundamentalProperties
|
|
||||||
.getCurrentLengthConstraint());
|
return violationNotificator.withListener(fundamentalProperties.getCurrentLengthConstraint());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Constraint<GanttDate> getEndDateBiggerThanStartDate() {
|
public Constraint<GanttDate> getEndDateBiggerThanStartDate() {
|
||||||
return violationNotificator
|
return violationNotificator.withListener(biggerOrEqualThan(getBeginDate()));
|
||||||
.withListener(biggerOrEqualThan(getBeginDate()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNotes() {
|
public String getNotes() {
|
||||||
|
|
@ -363,16 +332,17 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
public void setNotes(String notes) {
|
public void setNotes(String notes) {
|
||||||
String previousValue = fundamentalProperties.getNotes();
|
String previousValue = fundamentalProperties.getNotes();
|
||||||
this.fundamentalProperties.setNotes(notes);
|
this.fundamentalProperties.setNotes(notes);
|
||||||
fundamentalPropertiesListeners.firePropertyChange("notes",
|
|
||||||
previousValue, this.fundamentalProperties.getNotes());
|
fundamentalPropertiesListeners.firePropertyChange(
|
||||||
|
"notes", previousValue, this.fundamentalProperties.getNotes());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resizeTo(final LocalDate date) {
|
public void resizeTo(final LocalDate date) {
|
||||||
if (date.compareTo(getBeginDateAsLocalDate()) < 0) {
|
if ( date.compareTo(getBeginDateAsLocalDate()) < 0 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
doPositionModifications(new IModifications() {
|
|
||||||
|
|
||||||
|
doPositionModifications(new IModifications() {
|
||||||
@Override
|
@Override
|
||||||
public void doIt(IUpdatablePosition position) {
|
public void doIt(IUpdatablePosition position) {
|
||||||
position.resizeTo(GanttDate.createFrom(date));
|
position.resizeTo(GanttDate.createFrom(date));
|
||||||
|
|
@ -447,8 +417,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
public void setDeadline(Date date) {
|
public void setDeadline(Date date) {
|
||||||
Date previousValue = fundamentalProperties.getDeadline();
|
Date previousValue = fundamentalProperties.getDeadline();
|
||||||
fundamentalProperties.setDeadline(date);
|
fundamentalProperties.setDeadline(date);
|
||||||
fundamentalPropertiesListeners.firePropertyChange("deadline",
|
fundamentalPropertiesListeners.firePropertyChange("deadline", previousValue, date);
|
||||||
previousValue, date);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -456,19 +425,16 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
return fundamentalProperties.getConsolidatedline();
|
return fundamentalProperties.getConsolidatedline();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addConstraintViolationListener(
|
public void addConstraintViolationListener(IConstraintViolationListener<GanttDate> listener, Mode mode) {
|
||||||
IConstraintViolationListener<GanttDate> listener, Mode mode) {
|
|
||||||
violationNotificator.addConstraintViolationListener(listener, mode);
|
violationNotificator.addConstraintViolationListener(listener, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addReloadListener(
|
public void addReloadListener(IReloadResourcesTextRequested reloadResourcesTextRequested) {
|
||||||
IReloadResourcesTextRequested reloadResourcesTextRequested) {
|
|
||||||
Validate.notNull(reloadResourcesTextRequested);
|
Validate.notNull(reloadResourcesTextRequested);
|
||||||
this.reloadRequestedListeners.add(reloadResourcesTextRequested);
|
this.reloadRequestedListeners.add(reloadResourcesTextRequested);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeReloadListener(
|
public void removeReloadListener(IReloadResourcesTextRequested reloadResourcesTextRequested) {
|
||||||
IReloadResourcesTextRequested reloadResourcesTextRequested) {
|
|
||||||
this.reloadRequestedListeners.remove(reloadResourcesTextRequested);
|
this.reloadRequestedListeners.remove(reloadResourcesTextRequested);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -481,8 +447,8 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
public static void reloadResourcesText(IContextWithPlannerTask<?> context) {
|
public static void reloadResourcesText(IContextWithPlannerTask<?> context) {
|
||||||
Task task = context.getTask();
|
Task task = context.getTask();
|
||||||
task.reloadResourcesText();
|
task.reloadResourcesText();
|
||||||
List<? extends TaskContainer> parents = context.getMapper().getParents(
|
List<? extends TaskContainer> parents = context.getMapper().getParents(task);
|
||||||
task);
|
|
||||||
for (TaskContainer each : parents) {
|
for (TaskContainer each : parents) {
|
||||||
each.reloadResourcesText();
|
each.reloadResourcesText();
|
||||||
}
|
}
|
||||||
|
|
@ -545,8 +511,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSizeDueToDateChanges(GanttDate previousStart, GanttDate previousEnd) {
|
public void updateSizeDueToDateChanges(GanttDate previousStart, GanttDate previousEnd) {
|
||||||
dependenciesEnforcerHook.setStartDate(previousStart, previousEnd,
|
dependenciesEnforcerHook.setStartDate(previousStart, previousEnd, getBeginDate());
|
||||||
getBeginDate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -565,10 +530,8 @@ public abstract class Task implements ITaskFundamentalProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void firePropertyChangeForTaskDates() {
|
public void firePropertyChangeForTaskDates() {
|
||||||
fundamentalPropertiesListeners.firePropertyChange("beginDate", null,
|
fundamentalPropertiesListeners.firePropertyChange("beginDate", null, getBeginDate());
|
||||||
getBeginDate());
|
fundamentalPropertiesListeners.firePropertyChange("endDate", null, getEndDate());
|
||||||
fundamentalPropertiesListeners.firePropertyChange("endDate", null,
|
|
||||||
getEndDate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCode() {
|
public String getCode() {
|
||||||
|
|
|
||||||
|
|
@ -23,22 +23,19 @@ package org.zkoss.ganttz.data.constraint;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Óscar González Fernández
|
* @author Óscar González Fernández
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ConstraintOnComparableValues<T extends Comparable<T>> extends
|
public class ConstraintOnComparableValues<T extends Comparable<T>> extends Constraint<T> {
|
||||||
Constraint<T> {
|
|
||||||
|
|
||||||
public static <T extends Comparable<T>> Constraint<T> biggerOrEqualThan(
|
public static <T extends Comparable<T>> Constraint<T> biggerOrEqualThan(T value) {
|
||||||
T value) {
|
|
||||||
return instantiate(ComparisonType.BIGGER_OR_EQUAL_THAN, value);
|
return instantiate(ComparisonType.BIGGER_OR_EQUAL_THAN, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Comparable<T>> Constraint<T> lessOrEqualThan(
|
public static <T extends Comparable<T>> Constraint<T> lessOrEqualThan(T value) {
|
||||||
T value) {
|
|
||||||
return instantiate(ComparisonType.LESS_OR_EQUAL_THAN, 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);
|
return instantiate(ComparisonType.EQUAL_TO, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Comparable<T>> Constraint<T> instantiate(
|
public static <T extends Comparable<T>> Constraint<T> instantiate(ComparisonType type, T value) {
|
||||||
ComparisonType type, T value) {
|
if ( value == null ) {
|
||||||
if (value == null) {
|
|
||||||
return Constraint.voidConstraint();
|
return Constraint.voidConstraint();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ConstraintOnComparableValues<T>(type, value);
|
return new ConstraintOnComparableValues<T>(type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,19 +67,26 @@ public class ConstraintOnComparableValues<T extends Comparable<T>> extends
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected T applyConstraintTo(T value) {
|
protected T applyConstraintTo(T value) {
|
||||||
if (value == null) {
|
if ( value == null ) {
|
||||||
return comparisonValue;
|
return comparisonValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (comparisonType) {
|
switch (comparisonType) {
|
||||||
|
|
||||||
case LESS_OR_EQUAL_THAN:
|
case LESS_OR_EQUAL_THAN:
|
||||||
return min(comparisonValue, value);
|
return min(comparisonValue, value);
|
||||||
|
|
||||||
case LESS_OR_EQUAL_THAN_RIGHT_FLOATING:
|
case LESS_OR_EQUAL_THAN_RIGHT_FLOATING:
|
||||||
|
|
||||||
case BIGGER_OR_EQUAL_THAN_LEFT_FLOATING:
|
case BIGGER_OR_EQUAL_THAN_LEFT_FLOATING:
|
||||||
return comparisonValue;
|
return comparisonValue;
|
||||||
|
|
||||||
case BIGGER_OR_EQUAL_THAN:
|
case BIGGER_OR_EQUAL_THAN:
|
||||||
return max(comparisonValue, value);
|
return max(comparisonValue, value);
|
||||||
|
|
||||||
case EQUAL_TO:
|
case EQUAL_TO:
|
||||||
return comparisonValue;
|
return comparisonValue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("can't handle "+comparisonType);
|
throw new RuntimeException("can't handle "+comparisonType);
|
||||||
}
|
}
|
||||||
|
|
@ -99,14 +103,20 @@ public class ConstraintOnComparableValues<T extends Comparable<T>> extends
|
||||||
@Override
|
@Override
|
||||||
public boolean isSatisfiedBy(T value) {
|
public boolean isSatisfiedBy(T value) {
|
||||||
switch (comparisonType) {
|
switch (comparisonType) {
|
||||||
|
|
||||||
case LESS_OR_EQUAL_THAN:
|
case LESS_OR_EQUAL_THAN:
|
||||||
|
|
||||||
case LESS_OR_EQUAL_THAN_RIGHT_FLOATING:
|
case LESS_OR_EQUAL_THAN_RIGHT_FLOATING:
|
||||||
return value.compareTo(comparisonValue) <= 0;
|
return value.compareTo(comparisonValue) <= 0;
|
||||||
|
|
||||||
case BIGGER_OR_EQUAL_THAN:
|
case BIGGER_OR_EQUAL_THAN:
|
||||||
|
|
||||||
case BIGGER_OR_EQUAL_THAN_LEFT_FLOATING:
|
case BIGGER_OR_EQUAL_THAN_LEFT_FLOATING:
|
||||||
return value.compareTo(comparisonValue) >= 0;
|
return value.compareTo(comparisonValue) >= 0;
|
||||||
|
|
||||||
case EQUAL_TO:
|
case EQUAL_TO:
|
||||||
return value.compareTo(comparisonValue) == 0;
|
return value.compareTo(comparisonValue) == 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("can't handle " + comparisonType);
|
throw new RuntimeException("can't handle " + comparisonType);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
package org.zkoss.ganttz.data.resourceload;
|
package org.zkoss.ganttz.data.resourceload;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
public class LoadLevel {
|
public class LoadLevel {
|
||||||
|
|
||||||
|
|
@ -33,18 +33,21 @@ public class LoadLevel {
|
||||||
return percentage == 0;
|
return percentage == 0;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
SOME_LOAD {
|
SOME_LOAD {
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(int percentage) {
|
public boolean contains(int percentage) {
|
||||||
return percentage > 0 && percentage < 100;
|
return percentage > 0 && percentage < 100;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
FULL_LOAD {
|
FULL_LOAD {
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(int percentage) {
|
public boolean contains(int percentage) {
|
||||||
return percentage == 100;
|
return percentage == 100;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
OVERLOAD {
|
OVERLOAD {
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(int percentage) {
|
public boolean contains(int percentage) {
|
||||||
|
|
@ -55,10 +58,11 @@ public class LoadLevel {
|
||||||
protected abstract boolean contains(int percentage);
|
protected abstract boolean contains(int percentage);
|
||||||
public static Category categoryFor(int percentage) {
|
public static Category categoryFor(int percentage) {
|
||||||
for (Category category : values()) {
|
for (Category category : values()) {
|
||||||
if (category.contains(percentage)) {
|
if ( category.contains(percentage) ) {
|
||||||
return category;
|
return category;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException("couldn't handle " + percentage);
|
throw new IllegalArgumentException("couldn't handle " + percentage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.zkoss.ganttz.data.GanttDate;
|
import org.zkoss.ganttz.data.GanttDate;
|
||||||
|
|
@ -47,14 +47,20 @@ public class LoadPeriod {
|
||||||
|
|
||||||
private final String assignedEffort;
|
private final String assignedEffort;
|
||||||
|
|
||||||
public LoadPeriod(GanttDate start, GanttDate end, String availableEffort,
|
public LoadPeriod(
|
||||||
String assignedEffort, LoadLevel loadLevel) {
|
GanttDate start,
|
||||||
|
GanttDate end,
|
||||||
|
String availableEffort,
|
||||||
|
String assignedEffort,
|
||||||
|
LoadLevel loadLevel) {
|
||||||
|
|
||||||
Validate.notNull(start);
|
Validate.notNull(start);
|
||||||
Validate.notNull(end);
|
Validate.notNull(end);
|
||||||
Validate.notNull(loadLevel);
|
Validate.notNull(loadLevel);
|
||||||
Validate.notNull(availableEffort);
|
Validate.notNull(availableEffort);
|
||||||
Validate.notNull(assignedEffort);
|
Validate.notNull(assignedEffort);
|
||||||
Validate.isTrue(start.compareTo(end) <= 0);
|
Validate.isTrue(start.compareTo(end) <= 0);
|
||||||
|
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.loadLevel = loadLevel;
|
this.loadLevel = loadLevel;
|
||||||
|
|
@ -80,27 +86,28 @@ public class LoadPeriod {
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if some of the LoadPeriod overlaps
|
* if some of the LoadPeriod overlaps
|
||||||
*/
|
*/
|
||||||
public static List<LoadPeriod> sort(
|
public static List<LoadPeriod> sort(Collection<? extends LoadPeriod> notOverlappingPeriods)
|
||||||
Collection<? extends LoadPeriod> notOverlappingPeriods)
|
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
ArrayList<LoadPeriod> result = new ArrayList<LoadPeriod>(
|
|
||||||
notOverlappingPeriods);
|
ArrayList<LoadPeriod> result = new ArrayList<>(notOverlappingPeriods);
|
||||||
Collections.sort(result, new Comparator<LoadPeriod>() {
|
Collections.sort(result, new Comparator<LoadPeriod>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(LoadPeriod o1, LoadPeriod o2) {
|
public int compare(LoadPeriod o1, LoadPeriod o2) {
|
||||||
if (o1.overlaps(o2)) {
|
if ( o1.overlaps(o2) ) {
|
||||||
LOG.warn(o1 + " overlaps with " + o2);
|
LOG.warn(o1 + " overlaps with " + o2);
|
||||||
throw new IllegalArgumentException(o1 + " overlaps with "
|
throw new IllegalArgumentException(o1 + " overlaps with " + o2);
|
||||||
+ o2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int comparison = o1.start.compareTo(o2.start);
|
int comparison = o1.start.compareTo(o2.start);
|
||||||
if (comparison != 0) {
|
if ( comparison != 0 ) {
|
||||||
return comparison;
|
return comparison;
|
||||||
}
|
}
|
||||||
|
|
||||||
return o1.end.compareTo(o2.end);
|
return o1.end.compareTo(o2.end);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.collections.ComparatorUtils;
|
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.joda.time.LocalDate;
|
||||||
import org.zkoss.ganttz.data.GanttDate;
|
import org.zkoss.ganttz.data.GanttDate;
|
||||||
import org.zkoss.ganttz.util.Interval;
|
import org.zkoss.ganttz.util.Interval;
|
||||||
|
|
@ -35,20 +35,19 @@ import org.zkoss.ganttz.util.Interval;
|
||||||
public class LoadTimeLine {
|
public class LoadTimeLine {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static final Comparator<GanttDate> nullSafeComparator = ComparatorUtils
|
private static final Comparator<GanttDate> nullSafeComparator =
|
||||||
.nullLowComparator(ComparatorUtils.naturalComparator());
|
ComparatorUtils.nullLowComparator(ComparatorUtils.naturalComparator());
|
||||||
|
|
||||||
public static Comparator<LoadTimeLine> byStartAndEndDate() {
|
public static Comparator<LoadTimeLine> byStartAndEndDate() {
|
||||||
return new Comparator<LoadTimeLine>() {
|
return new Comparator<LoadTimeLine>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(LoadTimeLine o1, LoadTimeLine o2) {
|
public int compare(LoadTimeLine o1, LoadTimeLine o2) {
|
||||||
int result = nullSafeComparator.compare(o1.getStartPeriod(),
|
int result = nullSafeComparator.compare(o1.getStartPeriod(), o2.getStartPeriod());
|
||||||
o2.getStartPeriod());
|
if ( result == 0 ) {
|
||||||
if (result == 0) {
|
return nullSafeComparator.compare(o1.getEndPeriod(), o2.getEndPeriod());
|
||||||
return nullSafeComparator.compare(o1.getEndPeriod(),
|
|
||||||
o2.getEndPeriod());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -63,40 +62,43 @@ public class LoadTimeLine {
|
||||||
|
|
||||||
private final List<LoadTimeLine> children;
|
private final List<LoadTimeLine> children;
|
||||||
|
|
||||||
public LoadTimeLine(String conceptName, List<LoadPeriod> loadPeriods,
|
public LoadTimeLine(String conceptName,
|
||||||
|
List<LoadPeriod> loadPeriods,
|
||||||
TimeLineRole<?> role) {
|
TimeLineRole<?> role) {
|
||||||
|
|
||||||
Validate.notEmpty(conceptName);
|
Validate.notEmpty(conceptName);
|
||||||
Validate.notNull(loadPeriods);
|
Validate.notNull(loadPeriods);
|
||||||
|
|
||||||
this.loadPeriods = LoadPeriod.sort(loadPeriods);
|
this.loadPeriods = LoadPeriod.sort(loadPeriods);
|
||||||
this.conceptName = conceptName;
|
this.conceptName = conceptName;
|
||||||
this.type = "";
|
this.type = "";
|
||||||
this.timeLineRole = role;
|
this.timeLineRole = role;
|
||||||
this.children = Collections
|
this.children = Collections.unmodifiableList(new ArrayList<LoadTimeLine>());
|
||||||
.unmodifiableList(new ArrayList<LoadTimeLine>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoadTimeLine(String conceptName, List<LoadPeriod> loadPeriods,
|
public LoadTimeLine(String conceptName, List<LoadPeriod> loadPeriods, String type, TimeLineRole<?> role) {
|
||||||
String type, TimeLineRole<?> role) {
|
|
||||||
Validate.notEmpty(conceptName);
|
Validate.notEmpty(conceptName);
|
||||||
Validate.notNull(loadPeriods);
|
Validate.notNull(loadPeriods);
|
||||||
|
|
||||||
this.loadPeriods = LoadPeriod.sort(loadPeriods);
|
this.loadPeriods = LoadPeriod.sort(loadPeriods);
|
||||||
this.conceptName = conceptName;
|
this.conceptName = conceptName;
|
||||||
this.timeLineRole = role;
|
this.timeLineRole = role;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.children = Collections
|
this.children = Collections.unmodifiableList(new ArrayList<LoadTimeLine>());
|
||||||
.unmodifiableList(new ArrayList<LoadTimeLine>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoadTimeLine(LoadTimeLine main, List<LoadTimeLine> children) {
|
public LoadTimeLine(LoadTimeLine main, List<LoadTimeLine> children) {
|
||||||
Validate.notEmpty(main.getConceptName());
|
Validate.notEmpty(main.getConceptName());
|
||||||
Validate.notNull(main.getLoadPeriods());
|
Validate.notNull(main.getLoadPeriods());
|
||||||
|
|
||||||
this.loadPeriods = LoadPeriod.sort(main.getLoadPeriods());
|
this.loadPeriods = LoadPeriod.sort(main.getLoadPeriods());
|
||||||
this.conceptName = main.getConceptName();
|
this.conceptName = main.getConceptName();
|
||||||
this.timeLineRole = main.getRole();
|
this.timeLineRole = main.getRole();
|
||||||
this.type = main.getType();
|
this.type = main.getType();
|
||||||
|
|
||||||
Validate.notNull(children);
|
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() {
|
public GanttDate getStartPeriod() {
|
||||||
if (isEmpty()) {
|
if ( isEmpty() ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getFirst().getStart();
|
return getFirst().getStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,9 +135,10 @@ public class LoadTimeLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
public GanttDate getEndPeriod() {
|
public GanttDate getEndPeriod() {
|
||||||
if (isEmpty()) {
|
if ( isEmpty() ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getLast().getEnd();
|
return getLast().getEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,38 +149,46 @@ public class LoadTimeLine {
|
||||||
public static Interval getIntervalFrom(List<LoadTimeLine> timeLines) {
|
public static Interval getIntervalFrom(List<LoadTimeLine> timeLines) {
|
||||||
GanttDate start = null;
|
GanttDate start = null;
|
||||||
GanttDate end = null;
|
GanttDate end = null;
|
||||||
|
|
||||||
for (LoadTimeLine loadTimeLine : timeLines) {
|
for (LoadTimeLine loadTimeLine : timeLines) {
|
||||||
if(!loadTimeLine.isEmpty()) {
|
if( !loadTimeLine.isEmpty() ) {
|
||||||
Validate.notNull(loadTimeLine.getStart());
|
Validate.notNull(loadTimeLine.getStart());
|
||||||
start = min(start, loadTimeLine.getStart());
|
start = min(start, loadTimeLine.getStart());
|
||||||
Validate.notNull(loadTimeLine.getEnd());
|
Validate.notNull(loadTimeLine.getEnd());
|
||||||
end = max(end, 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();
|
LocalDate localDateNow = new LocalDate();
|
||||||
|
|
||||||
return new Interval(localDateNow, localDateNow.plusYears(5));
|
return new Interval(localDateNow, localDateNow.plusYears(5));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Interval(start.toLocalDate(), end.asExclusiveEnd());
|
return new Interval(start.toLocalDate(), end.asExclusiveEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GanttDate max(GanttDate one, GanttDate other) {
|
private static GanttDate max(GanttDate one, GanttDate other) {
|
||||||
if (one == null) {
|
if ( one == null ) {
|
||||||
return other;
|
return other;
|
||||||
}
|
}
|
||||||
if (other == null) {
|
|
||||||
|
if ( other == null ) {
|
||||||
return one;
|
return one;
|
||||||
}
|
}
|
||||||
|
|
||||||
return one.compareTo(other) > 0 ? one : other;
|
return one.compareTo(other) > 0 ? one : other;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GanttDate min(GanttDate one, GanttDate other) {
|
private static GanttDate min(GanttDate one, GanttDate other) {
|
||||||
if (one == null) {
|
if ( one == null ) {
|
||||||
return other;
|
return other;
|
||||||
}
|
}
|
||||||
if (other == null) {
|
|
||||||
|
if ( other == null ) {
|
||||||
return one;
|
return one;
|
||||||
}
|
}
|
||||||
|
|
||||||
return one.compareTo(other) < 0 ? one : other;
|
return one.compareTo(other) < 0 ? one : other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -189,35 +201,39 @@ public class LoadTimeLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LoadTimeLine> getAllChildren() {
|
public List<LoadTimeLine> getAllChildren() {
|
||||||
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
|
List<LoadTimeLine> result = new ArrayList<>();
|
||||||
for (LoadTimeLine child : children) {
|
for (LoadTimeLine child : children) {
|
||||||
result.add(child);
|
result.add(child);
|
||||||
result.addAll(child.getAllChildren());
|
result.addAll(child.getAllChildren());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GanttDate getStart() {
|
public GanttDate getStart() {
|
||||||
GanttDate result = getStartPeriod();
|
GanttDate result = getStartPeriod();
|
||||||
|
|
||||||
for (LoadTimeLine loadTimeLine : getChildren()) {
|
for (LoadTimeLine loadTimeLine : getChildren()) {
|
||||||
GanttDate start = loadTimeLine.getStart();
|
GanttDate start = loadTimeLine.getStart();
|
||||||
if (start != null) {
|
|
||||||
result = result == null || result.compareTo(start) > 0 ? start
|
if ( start != null ) {
|
||||||
: result;
|
result = result == null || result.compareTo(start) > 0 ? start : result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GanttDate getEnd() {
|
public GanttDate getEnd() {
|
||||||
GanttDate result = getEndPeriod();
|
GanttDate result = getEndPeriod();
|
||||||
|
|
||||||
for (LoadTimeLine loadTimeLine : getChildren()) {
|
for (LoadTimeLine loadTimeLine : getChildren()) {
|
||||||
GanttDate end = loadTimeLine.getEnd();
|
GanttDate end = loadTimeLine.getEnd();
|
||||||
if (end != null) {
|
if ( end != null ) {
|
||||||
result = result == null || result.compareTo(end) < 0 ? end
|
result = result == null || result.compareTo(end) < 0 ? end : result;
|
||||||
: result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
package org.zkoss.ganttz.extensions;
|
package org.zkoss.ganttz.extensions;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.zkoss.zk.ui.Component;
|
import org.zkoss.zk.ui.Component;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import static org.zkoss.ganttz.i18n.I18nHelper._;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.zkoss.ganttz.IChartVisibilityChangedListener;
|
import org.zkoss.ganttz.IChartVisibilityChangedListener;
|
||||||
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
|
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.Combobox;
|
||||||
import org.zkoss.zul.api.Listbox;
|
import org.zkoss.zul.api.Listbox;
|
||||||
import org.zkoss.zul.api.South;
|
import org.zkoss.zul.api.South;
|
||||||
|
|
||||||
public class ResourcesLoadPanel extends HtmlMacroComponent {
|
public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
|
|
||||||
public interface IToolbarCommand {
|
public interface IToolbarCommand {
|
||||||
public void doAction();
|
void doAction();
|
||||||
|
|
||||||
public String getLabel();
|
String getLabel();
|
||||||
|
|
||||||
public String getImage();
|
String getImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimeTrackerComponent timeTrackerComponent;
|
private TimeTrackerComponent timeTrackerComponent;
|
||||||
|
|
@ -81,8 +82,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
|
|
||||||
private final Component componentOnWhichGiveFeedback;
|
private final Component componentOnWhichGiveFeedback;
|
||||||
|
|
||||||
private WeakReferencedListeners<IFilterChangedListener> zoomListeners = WeakReferencedListeners
|
private WeakReferencedListeners<IFilterChangedListener> zoomListeners = WeakReferencedListeners.create();
|
||||||
.create();
|
|
||||||
|
|
||||||
private Listbox listZoomLevels;
|
private Listbox listZoomLevels;
|
||||||
|
|
||||||
|
|
@ -104,8 +104,8 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
|
|
||||||
private boolean visibleChart = true;
|
private boolean visibleChart = true;
|
||||||
|
|
||||||
private WeakReferencedListeners<IChartVisibilityChangedListener> chartVisibilityListeners = WeakReferencedListeners
|
private WeakReferencedListeners<IChartVisibilityChangedListener> chartVisibilityListeners =
|
||||||
.create();
|
WeakReferencedListeners.create();
|
||||||
|
|
||||||
private final boolean expandResourceLoadViewCharts;
|
private final boolean expandResourceLoadViewCharts;
|
||||||
|
|
||||||
|
|
@ -113,12 +113,17 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
|
|
||||||
private Component secondOptionalFilter;
|
private Component secondOptionalFilter;
|
||||||
|
|
||||||
public ResourcesLoadPanel(List<LoadTimeLine> groups,
|
public ResourcesLoadPanel(
|
||||||
TimeTracker timeTracker, Component componentOnWhichGiveFeedback,
|
List<LoadTimeLine> groups,
|
||||||
boolean expandResourceLoadViewCharts, PaginationType paginationType) {
|
TimeTracker timeTracker,
|
||||||
|
Component componentOnWhichGiveFeedback,
|
||||||
|
boolean expandResourceLoadViewCharts,
|
||||||
|
PaginationType paginationType) {
|
||||||
|
|
||||||
this.componentOnWhichGiveFeedback = componentOnWhichGiveFeedback;
|
this.componentOnWhichGiveFeedback = componentOnWhichGiveFeedback;
|
||||||
this.expandResourceLoadViewCharts = expandResourceLoadViewCharts;
|
this.expandResourceLoadViewCharts = expandResourceLoadViewCharts;
|
||||||
this.paginationType = paginationType;
|
this.paginationType = paginationType;
|
||||||
|
|
||||||
init(groups, timeTracker);
|
init(groups, timeTracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,17 +143,19 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
|
|
||||||
public ListModel getFilters() {
|
public ListModel getFilters() {
|
||||||
String[] filters = new String[] { FILTER_RESOURCES, FILTER_CRITERIA };
|
String[] filters = new String[] { FILTER_RESOURCES, FILTER_CRITERIA };
|
||||||
|
|
||||||
return new SimpleListModel(filters);
|
return new SimpleListModel(filters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFilter(String filterby) {
|
public void setFilter(String filterby) {
|
||||||
if (filterby.equals(FILTER_RESOURCES)) {
|
if ( filterby.equals(FILTER_RESOURCES) ) {
|
||||||
this.filterbyResources = true;
|
this.filterbyResources = true;
|
||||||
this.feedBackMessage = _("showing resources");
|
this.feedBackMessage = _("showing resources");
|
||||||
} else {
|
} else {
|
||||||
this.filterbyResources = false;
|
this.filterbyResources = false;
|
||||||
this.feedBackMessage = _("showing criteria");
|
this.feedBackMessage = _("showing criteria");
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshNameFilter = true;
|
refreshNameFilter = true;
|
||||||
filterByNamePosition = 0;
|
filterByNamePosition = 0;
|
||||||
invalidatingChangeHappenedWithFeedback();
|
invalidatingChangeHappenedWithFeedback();
|
||||||
|
|
@ -159,9 +166,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invalidatingChangeHappenedWithFeedback() {
|
private void invalidatingChangeHappenedWithFeedback() {
|
||||||
LongOperationFeedback.execute(componentOnWhichGiveFeedback,
|
LongOperationFeedback.execute(componentOnWhichGiveFeedback, new ILongOperation() {
|
||||||
new ILongOperation() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAction() {
|
public void doAction() {
|
||||||
applyFilter();
|
applyFilter();
|
||||||
|
|
@ -179,8 +184,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyFilter() {
|
private void applyFilter() {
|
||||||
zoomListeners
|
zoomListeners.fireEvent(new IListenerNotification<IFilterChangedListener>() {
|
||||||
.fireEvent(new IListenerNotification<IFilterChangedListener>() {
|
|
||||||
@Override
|
@Override
|
||||||
public void doNotify(IFilterChangedListener listener) {
|
public void doNotify(IFilterChangedListener listener) {
|
||||||
listener.filterChanged(getFilter());
|
listener.filterChanged(getFilter());
|
||||||
|
|
@ -193,9 +197,13 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListModel getZoomLevels() {
|
public ListModel getZoomLevels() {
|
||||||
ZoomLevel[] selectableZoomlevels = { ZoomLevel.DETAIL_ONE,
|
ZoomLevel[] selectableZoomlevels = {
|
||||||
ZoomLevel.DETAIL_TWO, ZoomLevel.DETAIL_THREE,
|
ZoomLevel.DETAIL_ONE,
|
||||||
ZoomLevel.DETAIL_FOUR, ZoomLevel.DETAIL_FIVE };
|
ZoomLevel.DETAIL_TWO,
|
||||||
|
ZoomLevel.DETAIL_THREE,
|
||||||
|
ZoomLevel.DETAIL_FOUR,
|
||||||
|
ZoomLevel.DETAIL_FIVE };
|
||||||
|
|
||||||
return new SimpleListModel(selectableZoomlevels);
|
return new SimpleListModel(selectableZoomlevels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -239,6 +247,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
Component toolbar = getToolbar();
|
Component toolbar = getToolbar();
|
||||||
resetToolbar(toolbar);
|
resetToolbar(toolbar);
|
||||||
Separator separator = getSeparator();
|
Separator separator = getSeparator();
|
||||||
|
|
||||||
for (IToolbarCommand c : commands) {
|
for (IToolbarCommand c : commands) {
|
||||||
toolbar.insertBefore(asButton(c), separator);
|
toolbar.insertBefore(asButton(c), separator);
|
||||||
}
|
}
|
||||||
|
|
@ -246,8 +255,8 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
|
|
||||||
private void resetToolbar(Component toolbar) {
|
private void resetToolbar(Component toolbar) {
|
||||||
List<Component> children = toolbar.getChildren();
|
List<Component> children = toolbar.getChildren();
|
||||||
List<Button> buttons = ComponentsFinder.findComponentsOfType(
|
List<Button> buttons = ComponentsFinder.findComponentsOfType(Button.class, children);
|
||||||
Button.class, children);
|
|
||||||
for (Button b : buttons) {
|
for (Button b : buttons) {
|
||||||
toolbar.removeChild(b);
|
toolbar.removeChild(b);
|
||||||
}
|
}
|
||||||
|
|
@ -255,63 +264,66 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
|
|
||||||
private Button asButton(final IToolbarCommand c) {
|
private Button asButton(final IToolbarCommand c) {
|
||||||
Button result = new Button();
|
Button result = new Button();
|
||||||
|
|
||||||
result.addEventListener(Events.ON_CLICK, new EventListener() {
|
result.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(Event event) {
|
public void onEvent(Event event) {
|
||||||
c.doAction();
|
c.doAction();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!StringUtils.isEmpty(c.getImage())) {
|
|
||||||
|
if ( !StringUtils.isEmpty(c.getImage()) ) {
|
||||||
result.setImage(c.getImage());
|
result.setImage(c.getImage());
|
||||||
result.setTooltiptext(c.getLabel());
|
result.setTooltiptext(c.getLabel());
|
||||||
} else {
|
} else {
|
||||||
result.setLabel(c.getLabel());
|
result.setLabel(c.getLabel());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Separator getSeparator() {
|
private Separator getSeparator() {
|
||||||
List<Component> children = getToolbar().getChildren();
|
List<Component> children = getToolbar().getChildren();
|
||||||
Separator separator = ComponentsFinder.findComponentsOfType(
|
Separator separator = ComponentsFinder.findComponentsOfType(Separator.class, children).get(0);
|
||||||
Separator.class, children).get(0);
|
|
||||||
return separator;
|
return separator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Component getToolbar() {
|
private Component getToolbar() {
|
||||||
Component toolbar = getFellow("toolbar");
|
Component toolbar = getFellow("toolbar");
|
||||||
|
|
||||||
return toolbar;
|
return toolbar;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MutableTreeModel<LoadTimeLine> createModelForTree() {
|
private MutableTreeModel<LoadTimeLine> createModelForTree() {
|
||||||
MutableTreeModel<LoadTimeLine> result = MutableTreeModel
|
MutableTreeModel<LoadTimeLine> result = MutableTreeModel.create(LoadTimeLine.class);
|
||||||
.create(LoadTimeLine.class);
|
|
||||||
for (LoadTimeLine loadTimeLine : this.getGroupsToShow()) {
|
for (LoadTimeLine loadTimeLine : this.getGroupsToShow()) {
|
||||||
result.addToRoot(loadTimeLine);
|
result.addToRoot(loadTimeLine);
|
||||||
result = addNodes(result, loadTimeLine);
|
result = addNodes(result, loadTimeLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private MutableTreeModel<LoadTimeLine> addNodes(
|
private MutableTreeModel<LoadTimeLine> addNodes(MutableTreeModel<LoadTimeLine> tree, LoadTimeLine parent) {
|
||||||
MutableTreeModel<LoadTimeLine> tree, LoadTimeLine parent) {
|
if ( !parent.getChildren().isEmpty() ) {
|
||||||
if (!parent.getChildren().isEmpty()) {
|
|
||||||
tree.add(parent, parent.getChildren());
|
tree.add(parent, parent.getChildren());
|
||||||
|
|
||||||
for (LoadTimeLine loadTimeLine : parent.getChildren()) {
|
for (LoadTimeLine loadTimeLine : parent.getChildren()) {
|
||||||
tree = addNodes(tree, loadTimeLine);
|
tree = addNodes(tree, loadTimeLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimeTrackerComponent timeTrackerForResourcesLoadPanel(
|
private TimeTrackerComponent timeTrackerForResourcesLoadPanel(TimeTracker timeTracker) {
|
||||||
TimeTracker timeTracker) {
|
|
||||||
return new TimeTrackerComponent(timeTracker) {
|
return new TimeTrackerComponent(timeTracker) {
|
||||||
@Override
|
@Override
|
||||||
protected void scrollHorizontalPercentage(int daysDisplacement) {
|
protected void scrollHorizontalPercentage(int daysDisplacement) {
|
||||||
response("", new AuInvoke(resourceLoadList,
|
response("", new AuInvoke(resourceLoadList, "scroll_horizontal", daysDisplacement + ""));
|
||||||
"scroll_horizontal", daysDisplacement + ""));
|
|
||||||
moveCurrentPositionScroll();
|
moveCurrentPositionScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -321,20 +333,18 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
LocalDate previousStart = getPreviousStart();
|
LocalDate previousStart = getPreviousStart();
|
||||||
|
|
||||||
// get the current data
|
// get the current data
|
||||||
int diffDays = getTimeTrackerComponent().getDiffDays(
|
int diffDays = getTimeTrackerComponent().getDiffDays(previousStart);
|
||||||
previousStart);
|
|
||||||
double pixelPerDay = getTimeTrackerComponent().getPixelPerDay();
|
double pixelPerDay = getTimeTrackerComponent().getPixelPerDay();
|
||||||
|
|
||||||
response("move_scroll", new AuInvoke(resourceLoadList,
|
response("move_scroll", new AuInvoke(resourceLoadList, "move_scroll", "" + diffDays, "" + pixelPerDay));
|
||||||
"move_scroll", "" + diffDays, "" + pixelPerDay));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateCurrentDayScroll() {
|
protected void updateCurrentDayScroll() {
|
||||||
double previousPixelPerDay = getTimeTracker().getMapper()
|
double previousPixelPerDay = getTimeTracker().getMapper().getPixelsPerDay().doubleValue();
|
||||||
.getPixelsPerDay().doubleValue();
|
|
||||||
|
|
||||||
response("update_day_scroll", new AuInvoke(resourceLoadList,
|
response(
|
||||||
"update_day_scroll", "" + previousPixelPerDay));
|
"update_day_scroll",
|
||||||
|
new AuInvoke(resourceLoadList, "update_day_scroll", "" + previousPixelPerDay));
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -354,11 +364,12 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
|
|
||||||
// Insert additional filters if any
|
// Insert additional filters if any
|
||||||
Component additionalFilter = getFirstOptionalFilter();
|
Component additionalFilter = getFirstOptionalFilter();
|
||||||
if(additionalFilter != null) {
|
if( additionalFilter != null ) {
|
||||||
getFellow("additionalFilterInsertionPoint1").appendChild(additionalFilter);
|
getFellow("additionalFilterInsertionPoint1").appendChild(additionalFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
additionalFilter = getSecondOptionalFilter();
|
additionalFilter = getSecondOptionalFilter();
|
||||||
if(additionalFilter != null) {
|
if( additionalFilter != null ) {
|
||||||
getFellow("additionalFilterInsertionPoint2").appendChild(additionalFilter);
|
getFellow("additionalFilterInsertionPoint2").appendChild(additionalFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -367,10 +378,10 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
listZoomLevels = (Listbox) getFellow("listZoomLevels");
|
listZoomLevels = (Listbox) getFellow("listZoomLevels");
|
||||||
listZoomLevels.setSelectedIndex(timeTracker.getDetailLevel().ordinal());
|
listZoomLevels.setSelectedIndex(timeTracker.getDetailLevel().ordinal());
|
||||||
|
|
||||||
if(paginationType == PaginationType.INTERNAL_PAGINATION && refreshNameFilter) {
|
if( paginationType == PaginationType.INTERNAL_PAGINATION && refreshNameFilter ) {
|
||||||
setupNameFilter();
|
setupNameFilter();
|
||||||
}
|
}
|
||||||
else if(paginationType == PaginationType.NONE) {
|
else if( paginationType == PaginationType.NONE ) {
|
||||||
getFellow("filterByNameCombo").setVisible(false);
|
getFellow("filterByNameCombo").setVisible(false);
|
||||||
getFellow("filterByNameLabel").setVisible(false);
|
getFellow("filterByNameLabel").setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
@ -406,8 +417,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimeTrackerComponent createTimeTrackerHeader() {
|
private TimeTrackerComponent createTimeTrackerHeader() {
|
||||||
return new TimeTrackerComponent(
|
return new TimeTrackerComponent(timeTracker) {
|
||||||
timeTracker) {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void scrollHorizontalPercentage(int pixelsDisplacement) {
|
protected void scrollHorizontalPercentage(int pixelsDisplacement) {
|
||||||
|
|
@ -415,20 +425,15 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void moveCurrentPositionScroll() {
|
protected void moveCurrentPositionScroll() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateCurrentDayScroll() {
|
protected void updateCurrentDayScroll() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSeeScheduledOfListener(
|
public void addSeeScheduledOfListener(ISeeScheduledOfListener seeScheduledOfListener) {
|
||||||
ISeeScheduledOfListener seeScheduledOfListener) {
|
|
||||||
leftPane.addSeeScheduledOfListener(seeScheduledOfListener);
|
leftPane.addSeeScheduledOfListener(seeScheduledOfListener);
|
||||||
resourceLoadList.addSeeScheduledOfListener(seeScheduledOfListener);
|
resourceLoadList.addSeeScheduledOfListener(seeScheduledOfListener);
|
||||||
}
|
}
|
||||||
|
|
@ -438,19 +443,19 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
filterByNameCombo.getChildren().clear();
|
filterByNameCombo.getChildren().clear();
|
||||||
int size = groups.size();
|
int size = groups.size();
|
||||||
|
|
||||||
if(size > numberOfGroupsByName) {
|
if( size > numberOfGroupsByName ) {
|
||||||
int position = 0;
|
int position = 0;
|
||||||
|
|
||||||
while(position < size) {
|
while(position < size) {
|
||||||
String firstName = groups.get(position).getConceptName();
|
String firstName = groups.get(position).getConceptName();
|
||||||
String lastName;
|
String lastName;
|
||||||
int newPosition = position + numberOfGroupsByName;
|
int newPosition = position + numberOfGroupsByName;
|
||||||
if(newPosition - 1 < size) {
|
|
||||||
lastName = groups.get(newPosition - 1)
|
if( newPosition - 1 < size ) {
|
||||||
.getConceptName();
|
lastName = groups.get(newPosition - 1).getConceptName();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lastName = groups.get(size - 1)
|
lastName = groups.get(size - 1).getConceptName();
|
||||||
.getConceptName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Comboitem item = new Comboitem();
|
Comboitem item = new Comboitem();
|
||||||
|
|
@ -478,34 +483,34 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private List<LoadTimeLine> getGroupsToShow() {
|
private List<LoadTimeLine> getGroupsToShow() {
|
||||||
if(paginationType != PaginationType.INTERNAL_PAGINATION ||
|
if( paginationType != PaginationType.INTERNAL_PAGINATION || filterByNamePosition == -1 ) {
|
||||||
filterByNamePosition == -1) {
|
|
||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
int endPosition =
|
|
||||||
(filterByNamePosition + numberOfGroupsByName < groups.size())?
|
boolean condition = (filterByNamePosition + numberOfGroupsByName < groups.size());
|
||||||
filterByNamePosition + numberOfGroupsByName :
|
int endPosition = condition ? filterByNamePosition + numberOfGroupsByName : groups.size();
|
||||||
groups.size();
|
|
||||||
return groups.subList(filterByNamePosition, endPosition);
|
return groups.subList(filterByNamePosition, endPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSelectFilterByName(Combobox comboByName) {
|
public void onSelectFilterByName(Combobox comboByName) {
|
||||||
if (comboByName.getSelectedItemApi() == null) {
|
if ( comboByName.getSelectedItemApi() == null ) {
|
||||||
resetComboByName(comboByName);
|
resetComboByName(comboByName);
|
||||||
} else {
|
} else {
|
||||||
Integer filterByNamePosition = (Integer) comboByName
|
Integer filterByNamePosition = (Integer) comboByName.getSelectedItemApi().getValue();
|
||||||
.getSelectedItemApi().getValue();
|
|
||||||
if (paginationType != PaginationType.NONE) {
|
if ( paginationType != PaginationType.NONE ) {
|
||||||
this.filterByNamePosition = filterByNamePosition.intValue();
|
this.filterByNamePosition = filterByNamePosition;
|
||||||
this.lastSelectedName = comboByName.getSelectedIndex();
|
this.lastSelectedName = comboByName.getSelectedIndex();
|
||||||
this.feedBackMessage = _("filtering by name");
|
this.feedBackMessage = _("filtering by name");
|
||||||
|
|
||||||
changeNameFilterWithFeedback();
|
changeNameFilterWithFeedback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetComboByName(Combobox comboByName) {
|
private void resetComboByName(Combobox comboByName) {
|
||||||
if (this.lastSelectedName == -1) {
|
if ( this.lastSelectedName == -1 ) {
|
||||||
comboByName.setSelectedIndex(0);
|
comboByName.setSelectedIndex(0);
|
||||||
} else {
|
} else {
|
||||||
comboByName.setSelectedIndex(this.lastSelectedName);
|
comboByName.setSelectedIndex(this.lastSelectedName);
|
||||||
|
|
@ -514,24 +519,26 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeNameFilterWithFeedback() {
|
private void changeNameFilterWithFeedback() {
|
||||||
LongOperationFeedback.execute(componentOnWhichGiveFeedback,
|
LongOperationFeedback.execute(componentOnWhichGiveFeedback, new ILongOperation() {
|
||||||
new ILongOperation() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAction() {
|
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
|
//if the pagination is internal, we are in charge of repainting the graph
|
||||||
treeModel = createModelForTree();
|
treeModel = createModelForTree();
|
||||||
|
|
||||||
timeTrackerComponent = timeTrackerForResourcesLoadPanel(timeTracker);
|
timeTrackerComponent = timeTrackerForResourcesLoadPanel(timeTracker);
|
||||||
resourceLoadList = new ResourceLoadList(timeTracker, treeModel);
|
resourceLoadList = new ResourceLoadList(timeTracker, treeModel);
|
||||||
leftPane = new ResourceLoadLeftPane(treeModel, resourceLoadList);
|
leftPane = new ResourceLoadLeftPane(treeModel, resourceLoadList);
|
||||||
}
|
}
|
||||||
|
|
||||||
nameFilterListener.fireEvent(new IListenerNotification<IPaginationFilterChangedListener>() {
|
nameFilterListener.fireEvent(new IListenerNotification<IPaginationFilterChangedListener>() {
|
||||||
@Override
|
@Override
|
||||||
public void doNotify(IPaginationFilterChangedListener listener) {
|
public void doNotify(IPaginationFilterChangedListener listener) {
|
||||||
listener.filterChanged(filterByNamePosition);
|
listener.filterChanged(filterByNamePosition);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
afterCompose();
|
afterCompose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -544,25 +551,21 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
|
|
||||||
public void setInternalPaginationDisabled(boolean disabled) {
|
public void setInternalPaginationDisabled(boolean disabled) {
|
||||||
Combobox combo = ((Combobox) getFellow("filterByNameCombo"));
|
Combobox combo = ((Combobox) getFellow("filterByNameCombo"));
|
||||||
if (combo != null && combo.isDisabled() != disabled) {
|
if ( combo != null && combo.isDisabled() != disabled ) {
|
||||||
filterByNamePosition = disabled? -1 :
|
filterByNamePosition = disabled? -1 : (Integer) combo.getSelectedItemApi().getValue();
|
||||||
((Integer)combo.getSelectedItemApi().getValue()).intValue();
|
|
||||||
combo.setDisabled(disabled);
|
combo.setDisabled(disabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPaginationFilterListener(
|
public void addPaginationFilterListener(IPaginationFilterChangedListener iFilterChangedListener) {
|
||||||
IPaginationFilterChangedListener iFilterChangedListener) {
|
|
||||||
nameFilterListener.addListener(iFilterChangedListener);
|
nameFilterListener.addListener(iFilterChangedListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changeChartVisibility(boolean visible) {
|
public void changeChartVisibility(boolean visible) {
|
||||||
visibleChart = visible;
|
visibleChart = visible;
|
||||||
chartVisibilityListeners
|
chartVisibilityListeners.fireEvent(new IListenerNotification<IChartVisibilityChangedListener>() {
|
||||||
.fireEvent(new IListenerNotification<IChartVisibilityChangedListener>() {
|
|
||||||
@Override
|
@Override
|
||||||
public void doNotify(
|
public void doNotify(IChartVisibilityChangedListener listener) {
|
||||||
IChartVisibilityChangedListener listener) {
|
|
||||||
listener.chartVisibilityChanged(visibleChart);
|
listener.chartVisibilityChanged(visibleChart);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -572,8 +575,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
return visibleChart;
|
return visibleChart;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addChartVisibilityListener(
|
public void addChartVisibilityListener(IChartVisibilityChangedListener chartVisibilityChangedListener) {
|
||||||
IChartVisibilityChangedListener chartVisibilityChangedListener) {
|
|
||||||
chartVisibilityListeners.addListener(chartVisibilityChangedListener);
|
chartVisibilityListeners.addListener(chartVisibilityChangedListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -586,9 +588,10 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Combobox getPaginationFilterCombobox() {
|
public Combobox getPaginationFilterCombobox() {
|
||||||
if(paginationType == PaginationType.EXTERNAL_PAGINATION) {
|
if( paginationType == PaginationType.EXTERNAL_PAGINATION ) {
|
||||||
return (Combobox) getFellow("filterByNameCombo");
|
return (Combobox) getFellow("filterByNameCombo");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -606,7 +609,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
||||||
/**
|
/**
|
||||||
* Disables pagination. Shows all the LoadTimeLine objects received.
|
* 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.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.zkoss.web.servlet.http.HttpServlet;
|
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 String MAPPING = "/callback/";
|
||||||
|
|
||||||
private static final long CLEANING_PERIOD_MILLIS = 1000 * 60 * 1; // one
|
private static final long CLEANING_PERIOD_MILLIS = 1000 * 60; // one minute
|
||||||
// minute
|
|
||||||
// minutes
|
|
||||||
|
|
||||||
private static Random random = new Random();
|
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);
|
private static Timer cleaningTimer = new Timer(true);
|
||||||
|
|
||||||
public interface IServletRequestHandler {
|
public interface IServletRequestHandler {
|
||||||
public void handle(HttpServletRequest request,
|
void handle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
|
||||||
HttpServletResponse response) throws ServletException,
|
|
||||||
IOException;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DisposalMode {
|
public enum DisposalMode {
|
||||||
|
|
@ -72,26 +68,24 @@ public class CallbackServlet extends HttpServlet {
|
||||||
return new WeakReferencedHandler(handler);
|
return new WeakReferencedHandler(handler);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
AFTER_TEN_MINUTES {
|
AFTER_TEN_MINUTES {
|
||||||
@Override
|
@Override
|
||||||
public IHandler create(IServletRequestHandler handler) {
|
public IHandler create(IServletRequestHandler handler) {
|
||||||
return new BasedOnExpirationTimeHandler(handler,
|
return new BasedOnExpirationTimeHandler(handler, tenMinutesInMillis);
|
||||||
tenMinutesInMillis);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final long tenMinutesInMillis = TimeUnit.MILLISECONDS
|
private static final long tenMinutesInMillis = TimeUnit.MILLISECONDS.convert(10, TimeUnit.MINUTES);
|
||||||
.convert(10, TimeUnit.MINUTES);
|
|
||||||
|
|
||||||
public abstract IHandler create(
|
public abstract IHandler create(IServletRequestHandler handler);
|
||||||
IServletRequestHandler handler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface IHandler {
|
private interface IHandler {
|
||||||
|
|
||||||
abstract boolean hasExpired();
|
boolean hasExpired();
|
||||||
|
|
||||||
abstract IServletRequestHandler getHandler();
|
IServletRequestHandler getHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BasedOnExpirationTimeHandler implements IHandler {
|
private static class BasedOnExpirationTimeHandler implements IHandler {
|
||||||
|
|
@ -101,9 +95,9 @@ public class CallbackServlet extends HttpServlet {
|
||||||
private final long creationTime;
|
private final long creationTime;
|
||||||
private final long expirationTimeMilliseconds;
|
private final long expirationTimeMilliseconds;
|
||||||
|
|
||||||
public BasedOnExpirationTimeHandler(IServletRequestHandler handler,
|
public BasedOnExpirationTimeHandler(IServletRequestHandler handler, long expirationTimeMilliseconds) {
|
||||||
long expirationTimeMilliseconds) {
|
|
||||||
Validate.notNull(handler);
|
Validate.notNull(handler);
|
||||||
|
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
this.creationTime = System.currentTimeMillis();
|
this.creationTime = System.currentTimeMillis();
|
||||||
this.expirationTimeMilliseconds = expirationTimeMilliseconds;
|
this.expirationTimeMilliseconds = expirationTimeMilliseconds;
|
||||||
|
|
@ -125,7 +119,7 @@ public class CallbackServlet extends HttpServlet {
|
||||||
private final WeakReference<IServletRequestHandler> handler;
|
private final WeakReference<IServletRequestHandler> handler;
|
||||||
|
|
||||||
WeakReferencedHandler(IServletRequestHandler handler) {
|
WeakReferencedHandler(IServletRequestHandler handler) {
|
||||||
this.handler = new WeakReference<IServletRequestHandler>(handler);
|
this.handler = new WeakReference<>(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -140,40 +134,44 @@ public class CallbackServlet extends HttpServlet {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String registerAndCreateURLFor(HttpServletRequest request,
|
public static String registerAndCreateURLFor(HttpServletRequest request, IServletRequestHandler handler) {
|
||||||
IServletRequestHandler handler) {
|
return registerAndCreateURLFor(request, handler, DisposalMode.AFTER_TEN_MINUTES);
|
||||||
return registerAndCreateURLFor(request, handler,
|
|
||||||
DisposalMode.AFTER_TEN_MINUTES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String registerAndCreateURLFor(HttpServletRequest request,
|
public static String registerAndCreateURLFor(HttpServletRequest request, IServletRequestHandler handler,
|
||||||
IServletRequestHandler handler, DisposalMode disposalMode) {
|
DisposalMode disposalMode) {
|
||||||
|
|
||||||
return registerAndCreateURLFor(request, handler, true, disposalMode);
|
return registerAndCreateURLFor(request, handler, true, disposalMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String registerAndCreateURLFor(HttpServletRequest request,
|
public static String registerAndCreateURLFor(HttpServletRequest request, IServletRequestHandler handler,
|
||||||
IServletRequestHandler handler, boolean withContextPath) {
|
boolean withContextPath) {
|
||||||
return registerAndCreateURLFor(request, handler, withContextPath,
|
|
||||||
DisposalMode.AFTER_TEN_MINUTES);
|
return registerAndCreateURLFor(request, handler, withContextPath, DisposalMode.AFTER_TEN_MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String registerAndCreateURLFor(HttpServletRequest request,
|
public static String registerAndCreateURLFor(HttpServletRequest request,
|
||||||
IServletRequestHandler handler, boolean withContextPath,
|
IServletRequestHandler handler,
|
||||||
|
boolean withContextPath,
|
||||||
DisposalMode disposalMode) {
|
DisposalMode disposalMode) {
|
||||||
Validate.notNull(disposalMode);
|
Validate.notNull(disposalMode);
|
||||||
|
|
||||||
// theoretically could be an infinite loop, could be improved.
|
// theoretically could be an infinite loop, could be improved.
|
||||||
String generatedKey = "";
|
String generatedKey;
|
||||||
|
|
||||||
IHandler toBeRegistered = disposalMode.create(handler);
|
IHandler toBeRegistered = disposalMode.create(handler);
|
||||||
do {
|
do {
|
||||||
generatedKey = generateKey();
|
generatedKey = generateKey();
|
||||||
} while (handlersCallbacks.putIfAbsent(generatedKey, toBeRegistered) != null);
|
} while (handlersCallbacks.putIfAbsent(generatedKey, toBeRegistered) != null);
|
||||||
|
|
||||||
return buildURLFromKey(request, generatedKey, withContextPath);
|
return buildURLFromKey(request, generatedKey, withContextPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static synchronized String buildURLFromKey(
|
private static synchronized String buildURLFromKey(HttpServletRequest request, String generatedKey,
|
||||||
HttpServletRequest request, String generatedKey,
|
|
||||||
boolean withContextPath) {
|
boolean withContextPath) {
|
||||||
|
|
||||||
String contextPath = withContextPath ? request.getContextPath() : "";
|
String contextPath = withContextPath ? request.getContextPath() : "";
|
||||||
|
|
||||||
return contextPath + MAPPING + generatedKey;
|
return contextPath + MAPPING + generatedKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,9 +180,10 @@ public class CallbackServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getId(String pathInfo) {
|
private static String getId(String pathInfo) {
|
||||||
if (pathInfo.startsWith("/")) {
|
if ( pathInfo.startsWith("/") ) {
|
||||||
return pathInfo.substring(1);
|
return pathInfo.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pathInfo;
|
return pathInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,14 +198,15 @@ public class CallbackServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> findExpired() {
|
private static List<String> findExpired() {
|
||||||
ArrayList<Entry<String, IHandler>> handlersList = new ArrayList<Entry<String, IHandler>>(
|
ArrayList<Entry<String, IHandler>> handlersList = new ArrayList<>(handlersCallbacks.entrySet());
|
||||||
handlersCallbacks.entrySet());
|
List<String> expired = new ArrayList<>();
|
||||||
List<String> expired = new ArrayList<String>();
|
|
||||||
for (Entry<String, IHandler> entry : handlersList) {
|
for (Entry<String, IHandler> entry : handlersList) {
|
||||||
if (entry.getValue().hasExpired()) {
|
if ( entry.getValue().hasExpired() ) {
|
||||||
expired.add(entry.getKey());
|
expired.add(entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return expired;
|
return expired;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,8 +217,7 @@ public class CallbackServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleTimer() {
|
private void scheduleTimer() {
|
||||||
cleaningTimer.schedule(cleaningTask(), CLEANING_PERIOD_MILLIS,
|
cleaningTimer.schedule(cleaningTask(), CLEANING_PERIOD_MILLIS, CLEANING_PERIOD_MILLIS);
|
||||||
CLEANING_PERIOD_MILLIS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimerTask cleaningTask() {
|
private TimerTask cleaningTask() {
|
||||||
|
|
@ -231,11 +230,11 @@ public class CallbackServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
throws ServletException, IOException {
|
|
||||||
String callbackId = getId(req.getPathInfo());
|
String callbackId = getId(req.getPathInfo());
|
||||||
IServletRequestHandler handler = handlerFor(callbackId);
|
IServletRequestHandler handler = handlerFor(callbackId);
|
||||||
if (handler == null) {
|
|
||||||
|
if ( handler == null ) {
|
||||||
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||||
} else {
|
} else {
|
||||||
handler.handle(req, resp);
|
handler.handle(req, resp);
|
||||||
|
|
@ -244,6 +243,7 @@ public class CallbackServlet extends HttpServlet {
|
||||||
|
|
||||||
private IServletRequestHandler handlerFor(String callbackId) {
|
private IServletRequestHandler handlerFor(String callbackId) {
|
||||||
IHandler h = handlersCallbacks.get(callbackId);
|
IHandler h = handlersCallbacks.get(callbackId);
|
||||||
|
|
||||||
return h != null ? h.getHandler() : null;
|
return h != null ? h.getHandler() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,32 +27,36 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
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.zk.ui.Component;
|
||||||
import org.zkoss.zul.Row;
|
import org.zkoss.zul.Row;
|
||||||
import org.zkoss.zul.RowRenderer;
|
import org.zkoss.zul.RowRenderer;
|
||||||
|
|
||||||
public class OnColumnsRowRenderer<C, T> implements RowRenderer {
|
public class OnColumnsRowRenderer<C, T> implements RowRenderer {
|
||||||
|
|
||||||
public static <C, T> OnColumnsRowRenderer<C, T> create(
|
public static <C, T> OnColumnsRowRenderer<C, T> create(ICellForDetailItemRenderer<C, T> cellRenderer,
|
||||||
ICellForDetailItemRenderer<C, T> cellRenderer, Collection<C> columns) {
|
Collection<C> columns) {
|
||||||
|
|
||||||
return create(inferGenericType(cellRenderer), cellRenderer, columns);
|
return create(inferGenericType(cellRenderer), cellRenderer, columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <C, T> OnColumnsRowRenderer<C, T> create(Class<T> type,
|
public static <C, T> OnColumnsRowRenderer<C, T> create(Class<T> type,
|
||||||
ICellForDetailItemRenderer<C, T> cellRenderer, Collection<C> columns) {
|
ICellForDetailItemRenderer<C, T> cellRenderer,
|
||||||
return new OnColumnsRowRenderer<C, T>(type, cellRenderer, columns);
|
Collection<C> columns) {
|
||||||
|
|
||||||
|
return new OnColumnsRowRenderer<>(type, cellRenderer, columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> Class<T> inferGenericType(
|
private static <T> Class<T> inferGenericType(ICellForDetailItemRenderer<?, T> renderer) {
|
||||||
ICellForDetailItemRenderer<?, T> renderer) {
|
|
||||||
ParameterizedType parametrizedType = findRenderererInterfaceType(renderer);
|
ParameterizedType parametrizedType = findRenderererInterfaceType(renderer);
|
||||||
Type[] actualTypeArguments = parametrizedType.getActualTypeArguments();
|
Type[] actualTypeArguments = parametrizedType.getActualTypeArguments();
|
||||||
final int genericTypePosition = 1;
|
final int genericTypePosition = 1;
|
||||||
Type type = actualTypeArguments[genericTypePosition];
|
Type type = actualTypeArguments[genericTypePosition];
|
||||||
if (!isActualType(type)) {
|
|
||||||
|
if ( !isActualType(type) ) {
|
||||||
informCannotBeInferred(renderer);
|
informCannotBeInferred(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (Class<T>) actualTypeArguments[genericTypePosition];
|
return (Class<T>) actualTypeArguments[genericTypePosition];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,39 +64,41 @@ public class OnColumnsRowRenderer<C, T> implements RowRenderer {
|
||||||
return t instanceof Class;
|
return t instanceof Class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ParameterizedType findRenderererInterfaceType(
|
private static ParameterizedType findRenderererInterfaceType(ICellForDetailItemRenderer<?, ?> renderer) {
|
||||||
ICellForDetailItemRenderer<?, ?> renderer) {
|
|
||||||
Type[] genericInterfaces = renderer.getClass().getGenericInterfaces();
|
Type[] genericInterfaces = renderer.getClass().getGenericInterfaces();
|
||||||
|
|
||||||
for (Type type : genericInterfaces) {
|
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;
|
return (ParameterizedType) type;
|
||||||
} else {
|
} else {
|
||||||
informCannotBeInferred(renderer);
|
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,
|
private static boolean isTypeForInterface(Type type, Class<?> interfaceBeingSearched) {
|
||||||
Class<?> interfaceBeingSearched) {
|
if ( type instanceof ParameterizedType ) {
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
ParameterizedType p = (ParameterizedType) type;
|
ParameterizedType p = (ParameterizedType) type;
|
||||||
Type rawType = p.getRawType();
|
Type rawType = p.getRawType();
|
||||||
|
|
||||||
return rawType.equals(interfaceBeingSearched);
|
return rawType.equals(interfaceBeingSearched);
|
||||||
}
|
}
|
||||||
|
|
||||||
return type.equals(interfaceBeingSearched);
|
return type.equals(interfaceBeingSearched);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void informCannotBeInferred(
|
private static void informCannotBeInferred(ICellForDetailItemRenderer<?, ?> renderer) {
|
||||||
ICellForDetailItemRenderer<?, ?> renderer) {
|
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"the generic type cannot be inferred "
|
"the generic type cannot be inferred " +
|
||||||
+ "if actual type parameters are not declared "
|
"if actual type parameters are not declared " +
|
||||||
+ "or implements the raw interface: "
|
"or implements the raw interface: " +
|
||||||
+ renderer.getClass().getName());
|
renderer.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<C> columns;
|
private final List<C> columns;
|
||||||
|
|
@ -100,22 +106,24 @@ public class OnColumnsRowRenderer<C, T> implements RowRenderer {
|
||||||
private Class<T> type;
|
private Class<T> type;
|
||||||
|
|
||||||
private OnColumnsRowRenderer(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(type);
|
||||||
Validate.notNull(columns);
|
Validate.notNull(columns);
|
||||||
Validate.notNull(cellRenderer);
|
Validate.notNull(cellRenderer);
|
||||||
Validate.noNullElements(columns);
|
Validate.noNullElements(columns);
|
||||||
|
|
||||||
this.cellRenderer = cellRenderer;
|
this.cellRenderer = cellRenderer;
|
||||||
this.columns = new ArrayList<C>(columns);
|
this.columns = new ArrayList<>(columns);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(Row row, Object data) {
|
public void render(Row row, Object data) {
|
||||||
if (!type.isInstance(data)) {
|
if ( !type.isInstance(data) ) {
|
||||||
throw new IllegalArgumentException(data + " is not instance of "
|
throw new IllegalArgumentException(data + " is not instance of " + type);
|
||||||
+ type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (C item : columns) {
|
for (C item : columns) {
|
||||||
Component child = cellRenderer.cellFor(item, type.cast(data));
|
Component child = cellRenderer.cellFor(item, type.cast(data));
|
||||||
child.setParent(row);
|
child.setParent(row);
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import java.beans.PropertyChangeListener;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.zkoss.ganttz.DatesMapperOnInterval;
|
import org.zkoss.ganttz.DatesMapperOnInterval;
|
||||||
import org.zkoss.ganttz.IDatesMapper;
|
import org.zkoss.ganttz.IDatesMapper;
|
||||||
|
|
@ -50,22 +50,19 @@ public class TimeTracker {
|
||||||
|
|
||||||
public interface IDetailItemFilter {
|
public interface IDetailItemFilter {
|
||||||
|
|
||||||
public Collection<DetailItem> selectsFirstLevel(
|
Collection<DetailItem> selectsFirstLevel(Collection<DetailItem> firstLevelDetails);
|
||||||
Collection<DetailItem> firstLevelDetails);
|
|
||||||
|
|
||||||
public Collection<DetailItem> selectsSecondLevel(
|
Collection<DetailItem> selectsSecondLevel(Collection<DetailItem> secondLevelDetails);
|
||||||
Collection<DetailItem> secondLevelDetails);
|
|
||||||
|
|
||||||
public Interval getCurrentPaginationInterval();
|
Interval getCurrentPaginationInterval();
|
||||||
|
|
||||||
public void resetInterval();
|
void resetInterval();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ZoomLevel detailLevel = ZoomLevel.DETAIL_ONE;
|
private ZoomLevel detailLevel = ZoomLevel.DETAIL_ONE;
|
||||||
|
|
||||||
private WeakReferencedListeners<IZoomLevelChangedListener> zoomListeners = WeakReferencedListeners
|
private WeakReferencedListeners<IZoomLevelChangedListener> zoomListeners = WeakReferencedListeners.create();
|
||||||
.create();
|
|
||||||
|
|
||||||
private IDatesMapper datesMapper = null;
|
private IDatesMapper datesMapper = null;
|
||||||
|
|
||||||
|
|
@ -90,35 +87,38 @@ public class TimeTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeTracker(Interval interval, ZoomLevel zoomLevel, Component parent) {
|
public TimeTracker(Interval interval, ZoomLevel zoomLevel, Component parent) {
|
||||||
this(interval, zoomLevel, SeveralModificators.empty(),
|
this(interval, zoomLevel, SeveralModificators.empty(), SeveralModificators.empty(), parent);
|
||||||
SeveralModificators.empty(), parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeTracker(Interval interval, Component componentOnWhichGiveFeedback) {
|
public TimeTracker(Interval interval, Component componentOnWhichGiveFeedback) {
|
||||||
this(interval, SeveralModificators.empty(),
|
this(interval, SeveralModificators.empty(), SeveralModificators.empty(), componentOnWhichGiveFeedback);
|
||||||
SeveralModificators.empty(), componentOnWhichGiveFeedback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeTracker(Interval interval,
|
public TimeTracker(
|
||||||
|
Interval interval,
|
||||||
IDetailItemModificator firstLevelModificator,
|
IDetailItemModificator firstLevelModificator,
|
||||||
IDetailItemModificator secondLevelModificator,
|
IDetailItemModificator secondLevelModificator,
|
||||||
Component componentOnWhichGiveFeedback) {
|
Component componentOnWhichGiveFeedback) {
|
||||||
|
|
||||||
Validate.notNull(interval);
|
Validate.notNull(interval);
|
||||||
Validate.notNull(firstLevelModificator);
|
Validate.notNull(firstLevelModificator);
|
||||||
Validate.notNull(secondLevelModificator);
|
Validate.notNull(secondLevelModificator);
|
||||||
Validate.notNull(componentOnWhichGiveFeedback);
|
Validate.notNull(componentOnWhichGiveFeedback);
|
||||||
|
|
||||||
this.interval = interval;
|
this.interval = interval;
|
||||||
this.firstLevelModificator = firstLevelModificator;
|
this.firstLevelModificator = firstLevelModificator;
|
||||||
this.secondLevelModificator = secondLevelModificator;
|
this.secondLevelModificator = secondLevelModificator;
|
||||||
this.componentOnWhichGiveFeedback = componentOnWhichGiveFeedback;
|
this.componentOnWhichGiveFeedback = componentOnWhichGiveFeedback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeTracker(Interval interval, ZoomLevel zoomLevel,
|
public TimeTracker(
|
||||||
|
Interval interval,
|
||||||
|
ZoomLevel zoomLevel,
|
||||||
IDetailItemModificator firstLevelModificator,
|
IDetailItemModificator firstLevelModificator,
|
||||||
IDetailItemModificator secondLevelModificator,
|
IDetailItemModificator secondLevelModificator,
|
||||||
Component componentOnWhichGiveFeedback) {
|
Component componentOnWhichGiveFeedback) {
|
||||||
this(interval, firstLevelModificator, secondLevelModificator,
|
|
||||||
componentOnWhichGiveFeedback);
|
this(interval, firstLevelModificator, secondLevelModificator, componentOnWhichGiveFeedback);
|
||||||
detailLevel = zoomLevel;
|
detailLevel = zoomLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,55 +136,53 @@ public class TimeTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<DetailItem> getDetailsFirstLevel() {
|
public Collection<DetailItem> getDetailsFirstLevel() {
|
||||||
if (detailsFirstLevelCached == null) {
|
if ( detailsFirstLevelCached == null ) {
|
||||||
detailsFirstLevelCached = getTimeTrackerState()
|
detailsFirstLevelCached = getTimeTrackerState().getFirstLevelDetails(interval);
|
||||||
.getFirstLevelDetails(interval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return filterFirstLevel(detailsFirstLevelCached);
|
return filterFirstLevel(detailsFirstLevelCached);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<DetailItem> filterFirstLevel(
|
private Collection<DetailItem> filterFirstLevel(Collection<DetailItem> firstLevelDetails) {
|
||||||
Collection<DetailItem> firstLevelDetails) {
|
if ( filter == null ) {
|
||||||
if (filter == null) {
|
|
||||||
return firstLevelDetails;
|
return firstLevelDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
return filter.selectsFirstLevel(firstLevelDetails);
|
return filter.selectsFirstLevel(firstLevelDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<DetailItem> getDetailsSecondLevel() {
|
public Collection<DetailItem> getDetailsSecondLevel() {
|
||||||
if (detailsSecondLevelCached == null) {
|
if ( detailsSecondLevelCached == null ) {
|
||||||
detailsSecondLevelCached = getTimeTrackerState()
|
detailsSecondLevelCached = getTimeTrackerState().getSecondLevelDetails(interval);
|
||||||
.getSecondLevelDetails(interval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return filterSecondLevel(detailsSecondLevelCached);
|
return filterSecondLevel(detailsSecondLevelCached);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<DetailItem> filterSecondLevel(
|
private Collection<DetailItem> filterSecondLevel(Collection<DetailItem> secondLevelDetails) {
|
||||||
Collection<DetailItem> secondLevelDetails) {
|
if ( filter == null ) {
|
||||||
if (filter == null) {
|
|
||||||
return secondLevelDetails;
|
return secondLevelDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
return filter.selectsSecondLevel(secondLevelDetails);
|
return filter.selectsSecondLevel(secondLevelDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Interval realIntervalCached;
|
private Interval realIntervalCached;
|
||||||
|
|
||||||
public Interval getRealInterval() {
|
public Interval getRealInterval() {
|
||||||
if (realIntervalCached == null) {
|
if ( realIntervalCached == null ) {
|
||||||
realIntervalCached = getTimeTrackerState().getRealIntervalFor(
|
realIntervalCached = getTimeTrackerState().getRealIntervalFor(interval);
|
||||||
interval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return realIntervalCached;
|
return realIntervalCached;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeTrackerState getTimeTrackerState() {
|
public TimeTrackerState getTimeTrackerState() {
|
||||||
return detailLevel.getTimeTrackerState(firstLevelModificator,
|
return detailLevel.getTimeTrackerState(firstLevelModificator, secondLevelModificator);
|
||||||
secondLevelModificator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fireZoomChanged() {
|
private void fireZoomChanged() {
|
||||||
zoomListeners
|
zoomListeners.fireEvent(new IListenerNotification<IZoomLevelChangedListener>() {
|
||||||
.fireEvent(new IListenerNotification<IZoomLevelChangedListener>() {
|
|
||||||
@Override
|
@Override
|
||||||
public void doNotify(IZoomLevelChangedListener listener) {
|
public void doNotify(IZoomLevelChangedListener listener) {
|
||||||
listener.zoomLevelChanged(detailLevel);
|
listener.zoomLevelChanged(detailLevel);
|
||||||
|
|
@ -197,6 +195,7 @@ public class TimeTracker {
|
||||||
for (DetailItem detailItem : getDetailsSecondLevel()) {
|
for (DetailItem detailItem : getDetailsSecondLevel()) {
|
||||||
horizontalSize += detailItem.getSize();
|
horizontalSize += detailItem.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
return horizontalSize;
|
return horizontalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,15 +211,14 @@ public class TimeTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDatesMapper getMapper() {
|
public IDatesMapper getMapper() {
|
||||||
if (datesMapper == null) {
|
if ( datesMapper == null ) {
|
||||||
if (filter == null) {
|
if ( filter == null ) {
|
||||||
datesMapper = new DatesMapperOnInterval(getHorizontalSize(),
|
datesMapper = new DatesMapperOnInterval(getHorizontalSize(), getRealInterval());
|
||||||
getRealInterval());
|
|
||||||
} else {
|
} else {
|
||||||
datesMapper = new DatesMapperOnInterval(getHorizontalSize(),
|
datesMapper = new DatesMapperOnInterval(getHorizontalSize(), filter.getCurrentPaginationInterval());
|
||||||
filter.getCurrentPaginationInterval());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return datesMapper;
|
return datesMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,9 +228,7 @@ public class TimeTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invalidatingChangeHappenedWithFeedback() {
|
private void invalidatingChangeHappenedWithFeedback() {
|
||||||
LongOperationFeedback.execute(componentOnWhichGiveFeedback,
|
LongOperationFeedback.execute(componentOnWhichGiveFeedback, new ILongOperation() {
|
||||||
new ILongOperation() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAction() {
|
public void doAction() {
|
||||||
invalidatingChangeHappened();
|
invalidatingChangeHappened();
|
||||||
|
|
@ -261,40 +257,38 @@ public class TimeTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void trackPosition(final Task task) {
|
public void trackPosition(final Task task) {
|
||||||
task
|
task.addFundamentalPropertiesChangeListener(new PropertyChangeListener() {
|
||||||
.addFundamentalPropertiesChangeListener(new PropertyChangeListener() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
updateIntervalIfNeeded(task);
|
updateIntervalIfNeeded(task);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
updateIntervalIfNeeded(task);
|
updateIntervalIfNeeded(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateIntervalIfNeeded(Task task) {
|
private void updateIntervalIfNeeded(Task task) {
|
||||||
if (registeredFirstTask == false) {
|
if ( !registeredFirstTask ) {
|
||||||
registeredFirstTask = true;
|
registeredFirstTask = true;
|
||||||
interval = new Interval(startMinusTwoWeeks(task),
|
interval = new Interval(startMinusTwoWeeks(task), endPlusOneMonth(task));
|
||||||
endPlusOneMonth(task));
|
|
||||||
invalidatingChangeHappened();
|
invalidatingChangeHappened();
|
||||||
} else {
|
} else {
|
||||||
LocalDate newStart = interval.getStart();
|
LocalDate newStart = interval.getStart();
|
||||||
LocalDate newFinish = interval.getFinish();
|
LocalDate newFinish = interval.getFinish();
|
||||||
|
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
if (interval.getStart().compareTo(startMinusTwoWeeks(task)) > 0) {
|
|
||||||
|
if ( interval.getStart().compareTo(startMinusTwoWeeks(task) ) > 0) {
|
||||||
newStart = startMinusTwoWeeks(task);
|
newStart = startMinusTwoWeeks(task);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interval.getFinish()
|
if ( interval.getFinish().compareTo(endPlusOneMonth(task)) < 0 ) {
|
||||||
.compareTo(endPlusOneMonth(task)) < 0) {
|
|
||||||
newFinish = endPlusOneMonth(task);
|
newFinish = endPlusOneMonth(task);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
if ( changed ) {
|
||||||
interval = new Interval(newStart, newFinish);
|
interval = new Interval(newStart, newFinish);
|
||||||
invalidatingChangeHappened();
|
invalidatingChangeHappened();
|
||||||
}
|
}
|
||||||
|
|
@ -302,39 +296,43 @@ public class TimeTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Date max(Date date1, Date date2) {
|
private Date max(Date date1, Date date2) {
|
||||||
if (date1 == null) {
|
if ( date1 == null ) {
|
||||||
return date2;
|
return date2;
|
||||||
}
|
}
|
||||||
if (date2 == null) {
|
if ( date2 == null ) {
|
||||||
return date1;
|
return date1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return date1.compareTo(date2) > 0 ? date1 : date2;
|
return date1.compareTo(date2) > 0 ? date1 : date2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Date min(Date date1, Date date2) {
|
private Date min(Date date1, Date date2) {
|
||||||
if (date1 == null) {
|
if ( date1 == null ) {
|
||||||
return date2;
|
return date2;
|
||||||
}
|
}
|
||||||
if (date2 == null) {
|
|
||||||
|
if ( date2 == null ) {
|
||||||
return date1;
|
return date1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return date1.compareTo(date2) <= 0 ? date1 : date2;
|
return date1.compareTo(date2) <= 0 ? date1 : date2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalDate endPlusOneMonth(Task task) {
|
private LocalDate endPlusOneMonth(Task task) {
|
||||||
Date taskEnd = max(task.getEndDate().toDayRoundedDate(),
|
Date taskEnd = max(task.getEndDate().toDayRoundedDate(), task.getDeadline());
|
||||||
task.getDeadline());
|
|
||||||
return new LocalDate(taskEnd).plusMonths(1);
|
return new LocalDate(taskEnd).plusMonths(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalDate startMinusTwoWeeks(Task task) {
|
private LocalDate startMinusTwoWeeks(Task task) {
|
||||||
// the deadline could be before the start
|
// the deadline could be before the start
|
||||||
Date start = min(task.getBeginDate().toDayRoundedDate(),
|
Date start = min(task.getBeginDate().toDayRoundedDate(), task.getDeadline());
|
||||||
task.getDeadline());
|
|
||||||
// the last consolidated value could be before the start
|
// the last consolidated value could be before the start
|
||||||
if (task.getConsolidatedline() != null) {
|
if ( task.getConsolidatedline() != null ) {
|
||||||
start = min(start, task.getConsolidatedline().toDayRoundedDate());
|
start = min(start, task.getConsolidatedline().toDayRoundedDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LocalDate(start).minusWeeks(2);
|
return new LocalDate(start).minusWeeks(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
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>
|
* @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 class SeveralModificators implements IDetailItemModificator {
|
||||||
|
|
||||||
public static IDetailItemModificator empty() {
|
public static IDetailItemModificator empty() {
|
||||||
return new SeveralModificators(Collections
|
return new SeveralModificators(Collections.<IDetailItemModificator> emptyList());
|
||||||
.<IDetailItemModificator> emptyList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IDetailItemModificator create(
|
public static IDetailItemModificator create(IDetailItemModificator... modificators) {
|
||||||
IDetailItemModificator... modificators) {
|
|
||||||
return new SeveralModificators(Arrays.asList(modificators));
|
return new SeveralModificators(Arrays.asList(modificators));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IDetailItemModificator create(
|
public static IDetailItemModificator create(Collection<? extends IDetailItemModificator> modificators) {
|
||||||
Collection<? extends IDetailItemModificator> modificators) {
|
|
||||||
return new SeveralModificators(modificators);
|
return new SeveralModificators(modificators);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<IDetailItemModificator> modificators;
|
private final List<IDetailItemModificator> modificators;
|
||||||
|
|
||||||
private SeveralModificators(
|
private SeveralModificators(Collection<? extends IDetailItemModificator> modificators) {
|
||||||
Collection<? extends IDetailItemModificator> modificators) {
|
|
||||||
Validate.noNullElements(modificators);
|
Validate.noNullElements(modificators);
|
||||||
this.modificators = new ArrayList<IDetailItemModificator>(modificators);
|
this.modificators = new ArrayList<>(modificators);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -63,6 +59,7 @@ public class SeveralModificators implements IDetailItemModificator {
|
||||||
for (IDetailItemModificator each : modificators) {
|
for (IDetailItemModificator each : modificators) {
|
||||||
result = each.applyModificationsTo(result, z);
|
result = each.applyModificationsTo(result, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ package org.zkoss.ganttz.timetracker.zoom;
|
||||||
|
|
||||||
import java.util.Iterator;
|
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.LocalDate;
|
||||||
import org.joda.time.ReadablePeriod;
|
import org.joda.time.ReadablePeriod;
|
||||||
|
|
||||||
|
|
@ -30,16 +30,17 @@ import org.joda.time.ReadablePeriod;
|
||||||
* @author Óscar González Fernández
|
* @author Óscar González Fernández
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class TimeTrackerStateWithSubintervalsFitting extends
|
public abstract class TimeTrackerStateWithSubintervalsFitting extends TimeTrackerState {
|
||||||
TimeTrackerState {
|
|
||||||
|
|
||||||
protected TimeTrackerStateWithSubintervalsFitting(
|
protected TimeTrackerStateWithSubintervalsFitting(
|
||||||
IDetailItemModificator firstLevelModificator,
|
IDetailItemModificator firstLevelModificator,
|
||||||
IDetailItemModificator secondLevelModificator) {
|
IDetailItemModificator secondLevelModificator) {
|
||||||
|
|
||||||
super(firstLevelModificator, secondLevelModificator);
|
super(firstLevelModificator, secondLevelModificator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class PeriodicalGenerator extends LazyGenerator<LocalDate> {
|
private final class PeriodicalGenerator extends LazyGenerator<LocalDate> {
|
||||||
|
|
||||||
private final ReadablePeriod period;
|
private final ReadablePeriod period;
|
||||||
|
|
||||||
private PeriodicalGenerator(LocalDate first, ReadablePeriod period) {
|
private PeriodicalGenerator(LocalDate first, ReadablePeriod period) {
|
||||||
|
|
@ -55,8 +56,7 @@ public abstract class TimeTrackerStateWithSubintervalsFitting extends
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Iterator<LocalDate> getPeriodsFirstLevelGenerator(
|
protected Iterator<LocalDate> getPeriodsFirstLevelGenerator(final LocalDate start) {
|
||||||
final LocalDate start) {
|
|
||||||
return new PeriodicalGenerator(start, getPeriodFirstLevel());
|
return new PeriodicalGenerator(start, getPeriodFirstLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,6 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.zkoss.ganttz.util;
|
package org.zkoss.ganttz.util;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
|
@ -29,8 +26,8 @@ import static java.util.Arrays.asList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.commons.lang.math.Fraction;
|
import org.apache.commons.lang3.math.Fraction;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.Days;
|
import org.joda.time.Days;
|
||||||
import org.joda.time.Duration;
|
import org.joda.time.Duration;
|
||||||
|
|
@ -54,13 +51,15 @@ public class Interval {
|
||||||
Validate.notNull(startInclusive);
|
Validate.notNull(startInclusive);
|
||||||
Validate.notNull(endExclusive);
|
Validate.notNull(endExclusive);
|
||||||
Validate.isTrue(endExclusive.isAfter(startInclusive));
|
Validate.isTrue(endExclusive.isAfter(startInclusive));
|
||||||
|
|
||||||
this.startInclusive = startInclusive;
|
this.startInclusive = startInclusive;
|
||||||
this.endExclusive = endExclusive;
|
this.endExclusive = endExclusive;
|
||||||
|
|
||||||
this.lengthBetween = new Duration(
|
this.lengthBetween = new Duration(
|
||||||
this.startInclusive.toDateTimeAtStartOfDay(),
|
this.startInclusive.toDateTimeAtStartOfDay(),
|
||||||
this.endExclusive.toDateTimeAtStartOfDay());
|
this.endExclusive.toDateTimeAtStartOfDay());
|
||||||
this.daysBetween = Days.daysBetween(this.startInclusive,
|
|
||||||
this.endExclusive);
|
this.daysBetween = Days.daysBetween(this.startInclusive, this.endExclusive);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Days getDaysBetween() {
|
public Days getDaysBetween() {
|
||||||
|
|
@ -80,10 +79,9 @@ public class Interval {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Fraction getProportion(DateTime date) {
|
public Fraction getProportion(DateTime date) {
|
||||||
Days fromStartToDate = Days.daysBetween(startInclusive,
|
Days fromStartToDate = Days.daysBetween(startInclusive, date.toLocalDate());
|
||||||
date.toLocalDate());
|
Fraction result = Fraction.getFraction(fromStartToDate.getDays(), this.daysBetween.getDays());
|
||||||
Fraction result = Fraction.getFraction(fromStartToDate.getDays(),
|
|
||||||
this.daysBetween.getDays());
|
|
||||||
try {
|
try {
|
||||||
return result.add(inTheDayIncrement(date));
|
return result.add(inTheDayIncrement(date));
|
||||||
} catch (ArithmeticException e) {
|
} catch (ArithmeticException e) {
|
||||||
|
|
@ -94,18 +92,17 @@ public class Interval {
|
||||||
private Fraction inTheDayIncrement(DateTime date) {
|
private Fraction inTheDayIncrement(DateTime date) {
|
||||||
DateTime atStartOfDay = date.toLocalDate().toDateTimeAtStartOfDay();
|
DateTime atStartOfDay = date.toLocalDate().toDateTimeAtStartOfDay();
|
||||||
Duration duration = new Duration(atStartOfDay, date);
|
Duration duration = new Duration(atStartOfDay, date);
|
||||||
double result = ((double) duration.getMillis())
|
double result = ((double) duration.getMillis()) / lengthBetween.getMillis();
|
||||||
/ lengthBetween.getMillis();
|
|
||||||
return Fraction.getFraction(result);
|
return Fraction.getFraction(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Interval coalesce(Interval otherInterval) {
|
public Interval coalesce(Interval otherInterval) {
|
||||||
Validate.notNull(otherInterval);
|
Validate.notNull(otherInterval);
|
||||||
LocalDate minStart = Collections.min(asList(startInclusive,
|
LocalDate minStart = Collections.min(asList(startInclusive, otherInterval.startInclusive));
|
||||||
otherInterval.startInclusive));
|
LocalDate maxEnd = Collections.max(asList(endExclusive, otherInterval.endExclusive));
|
||||||
LocalDate maxEnd = Collections.max(asList(endExclusive,
|
|
||||||
otherInterval.endExclusive));
|
|
||||||
return new Interval(minStart, maxEnd);
|
return new Interval(minStart, maxEnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -28,7 +28,7 @@ import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
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.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.zkoss.zk.ui.Component;
|
import org.zkoss.zk.ui.Component;
|
||||||
|
|
@ -46,8 +46,7 @@ import org.zkoss.zk.ui.util.Clients;
|
||||||
*/
|
*/
|
||||||
public class LongOperationFeedback {
|
public class LongOperationFeedback {
|
||||||
|
|
||||||
private static final Log LOG = LogFactory
|
private static final Log LOG = LogFactory.getLog(LongOperationFeedback.class);
|
||||||
.getLog(LongOperationFeedback.class);
|
|
||||||
|
|
||||||
public interface ILongOperation {
|
public interface ILongOperation {
|
||||||
void doAction() throws Exception;
|
void doAction() throws Exception;
|
||||||
|
|
@ -62,12 +61,11 @@ public class LongOperationFeedback {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void execute(final Component component,
|
public static void execute(final Component component, final ILongOperation longOperation) {
|
||||||
final ILongOperation longOperation) {
|
|
||||||
Validate.notNull(component);
|
Validate.notNull(component);
|
||||||
Validate.notNull(longOperation);
|
Validate.notNull(longOperation);
|
||||||
|
|
||||||
if (alreadyInside.get()) {
|
if ( alreadyInside.get() ) {
|
||||||
dispatchActionDirectly(longOperation);
|
dispatchActionDirectly(longOperation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -88,10 +86,10 @@ public class LongOperationFeedback {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void executeLater(final Component component,
|
public static void executeLater(final Component component, final Runnable runnable) {
|
||||||
final Runnable runnable) {
|
|
||||||
Validate.notNull(runnable);
|
Validate.notNull(runnable);
|
||||||
Validate.notNull(component);
|
Validate.notNull(component);
|
||||||
|
|
||||||
final String eventName = generateEventName();
|
final String eventName = generateEventName();
|
||||||
component.addEventListener(eventName, new EventListener() {
|
component.addEventListener(eventName, new EventListener() {
|
||||||
|
|
||||||
|
|
@ -105,11 +103,11 @@ public class LongOperationFeedback {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.echoEvent(eventName, component, null);
|
Events.echoEvent(eventName, component, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void dispatchActionDirectly(
|
private static void dispatchActionDirectly(final ILongOperation longOperation) {
|
||||||
final ILongOperation longOperation) {
|
|
||||||
try {
|
try {
|
||||||
longOperation.doAction();
|
longOperation.doAction();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
@ -125,11 +123,11 @@ public class LongOperationFeedback {
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IDesktopUpdatesEmitter<T> {
|
public interface IDesktopUpdatesEmitter<T> {
|
||||||
public void doUpdate(T value);
|
void doUpdate(T value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IDesktopUpdate {
|
public interface IDesktopUpdate {
|
||||||
public void doUpdate();
|
void doUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IDesktopUpdate and(final IDesktopUpdate... desktopUpdates) {
|
public static IDesktopUpdate and(final IDesktopUpdate... desktopUpdates) {
|
||||||
|
|
@ -145,11 +143,10 @@ public class LongOperationFeedback {
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IBackGroundOperation<T> {
|
public interface IBackGroundOperation<T> {
|
||||||
public void doOperation(IDesktopUpdatesEmitter<T> desktopUpdateEmitter);
|
void doOperation(IDesktopUpdatesEmitter<T> desktopUpdateEmitter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final ExecutorService executor = Executors
|
private static final ExecutorService executor = Executors.newCachedThreadPool();
|
||||||
.newCachedThreadPool();
|
|
||||||
|
|
||||||
public static <T> IDesktopUpdatesEmitter<T> doNothingEmitter() {
|
public static <T> IDesktopUpdatesEmitter<T> doNothingEmitter() {
|
||||||
return new IDesktopUpdatesEmitter<T>() {
|
return new IDesktopUpdatesEmitter<T>() {
|
||||||
|
|
@ -164,11 +161,8 @@ public class LongOperationFeedback {
|
||||||
* {@link IDesktopUpdate} objects that can update desktop state. Trying to
|
* {@link IDesktopUpdate} objects that can update desktop state. Trying to
|
||||||
* update the components in any other way would fail
|
* update the components in any other way would fail
|
||||||
*/
|
*/
|
||||||
public static void progressive(final Desktop desktop,
|
public static void progressive(final Desktop desktop, final IBackGroundOperation<IDesktopUpdate> operation) {
|
||||||
final IBackGroundOperation<IDesktopUpdate> operation) {
|
progressive(desktop, operation, new IDesktopUpdatesEmitter<IDesktopUpdate>() {
|
||||||
progressive(desktop, operation,
|
|
||||||
new IDesktopUpdatesEmitter<IDesktopUpdate>() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doUpdate(IDesktopUpdate update) {
|
public void doUpdate(IDesktopUpdate update) {
|
||||||
update.doUpdate();
|
update.doUpdate();
|
||||||
|
|
@ -182,15 +176,17 @@ public class LongOperationFeedback {
|
||||||
* {@link IDesktopUpdatesEmitter} that handle these objects is necessary.
|
* {@link IDesktopUpdatesEmitter} that handle these objects is necessary.
|
||||||
* Trying to update the components in any other way would fail.
|
* 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 IBackGroundOperation<T> operation,
|
||||||
final IDesktopUpdatesEmitter<T> emitter) {
|
final IDesktopUpdatesEmitter<T> emitter) {
|
||||||
|
|
||||||
desktop.enableServerPush(true);
|
desktop.enableServerPush(true);
|
||||||
executor.execute(new Runnable() {
|
executor.execute(new Runnable() {
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
IBackGroundOperation<T> operationWithAsyncUpates = withAsyncUpates(
|
IBackGroundOperation<T> operationWithAsyncUpates = withAsyncUpates(operation, desktop);
|
||||||
operation, desktop);
|
|
||||||
operationWithAsyncUpates.doOperation(emitter);
|
operationWithAsyncUpates.doOperation(emitter);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("error executing background operation", e);
|
LOG.error("error executing background operation", e);
|
||||||
|
|
@ -204,14 +200,16 @@ public class LongOperationFeedback {
|
||||||
private static <T> IBackGroundOperation<T> withAsyncUpates(
|
private static <T> IBackGroundOperation<T> withAsyncUpates(
|
||||||
final IBackGroundOperation<T> backgroundOperation,
|
final IBackGroundOperation<T> backgroundOperation,
|
||||||
final Desktop desktop) {
|
final Desktop desktop) {
|
||||||
return new IBackGroundOperation<T>() {
|
|
||||||
|
|
||||||
|
return new IBackGroundOperation<T>() {
|
||||||
@Override
|
@Override
|
||||||
public void doOperation(
|
public void doOperation(IDesktopUpdatesEmitter<T> originalEmitter) {
|
||||||
IDesktopUpdatesEmitter<T> originalEmitter) {
|
|
||||||
NotBlockingDesktopUpdates<T> notBlockingDesktopUpdates = new NotBlockingDesktopUpdates<T>(
|
NotBlockingDesktopUpdates<T> notBlockingDesktopUpdates =
|
||||||
desktop, originalEmitter);
|
new NotBlockingDesktopUpdates<T>(desktop, originalEmitter);
|
||||||
|
|
||||||
Future<?> future = executor.submit(notBlockingDesktopUpdates);
|
Future<?> future = executor.submit(notBlockingDesktopUpdates);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
backgroundOperation.doOperation(notBlockingDesktopUpdates);
|
backgroundOperation.doOperation(notBlockingDesktopUpdates);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -230,15 +228,13 @@ public class LongOperationFeedback {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class NotBlockingDesktopUpdates<T> implements
|
private static class NotBlockingDesktopUpdates<T> implements IDesktopUpdatesEmitter<T>, Runnable {
|
||||||
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 IDesktopUpdatesEmitter<T> original;
|
||||||
private final Desktop desktop;
|
private final Desktop desktop;
|
||||||
|
|
||||||
NotBlockingDesktopUpdates(Desktop desktop,
|
NotBlockingDesktopUpdates(Desktop desktop, IDesktopUpdatesEmitter<T> original) {
|
||||||
IDesktopUpdatesEmitter<T> original) {
|
|
||||||
this.original = original;
|
this.original = original;
|
||||||
this.desktop = desktop;
|
this.desktop = desktop;
|
||||||
}
|
}
|
||||||
|
|
@ -254,40 +250,48 @@ public class LongOperationFeedback {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
List<T> batch = new ArrayList<T>();
|
List<T> batch = new ArrayList<>();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
batch.clear();
|
batch.clear();
|
||||||
EndOrValue<T> current = null;
|
EndOrValue<T> current;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
current = queue.take();
|
current = queue.take();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
if (current.isEnd()) {
|
|
||||||
|
if ( current.isEnd() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!desktop.isAlive() || !desktop.isServerPushEnabled()) {
|
|
||||||
|
if ( !desktop.isAlive() || !desktop.isServerPushEnabled() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Executions.activate(desktop);
|
Executions.activate(desktop);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("unable to access desktop", e);
|
LOG.error("unable to access desktop", e);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
original.doUpdate(current.getValue());
|
original.doUpdate(current.getValue());
|
||||||
while ((current = queue.poll()) != null) {
|
while ((current = queue.poll()) != null) {
|
||||||
if (current.isEnd()) {
|
|
||||||
|
if ( current.isEnd() ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.add(current.getValue());
|
batch.add(current.getValue());
|
||||||
original.doUpdate(current.getValue());
|
original.doUpdate(current.getValue());
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Executions.deactivate(desktop);
|
Executions.deactivate(desktop);
|
||||||
}
|
}
|
||||||
if (current != null && current.isEnd()) {
|
if ( current != null && current.isEnd() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -297,11 +301,11 @@ public class LongOperationFeedback {
|
||||||
|
|
||||||
private static abstract class EndOrValue<T> {
|
private static abstract class EndOrValue<T> {
|
||||||
public static <T> EndOrValue<T> end() {
|
public static <T> EndOrValue<T> end() {
|
||||||
return new End<T>();
|
return new End<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> EndOrValue<T> value(T value) {
|
public static <T> EndOrValue<T> value(T value) {
|
||||||
return new Value<T>(value);
|
return new Value<>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean isEnd();
|
public abstract boolean isEnd();
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
package org.zkoss.ganttz.util;
|
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.Desktop;
|
||||||
import org.zkoss.zk.ui.Executions;
|
import org.zkoss.zk.ui.Executions;
|
||||||
|
|
||||||
|
|
@ -37,6 +37,7 @@ public class OnZKDesktopRegistry<T> {
|
||||||
|
|
||||||
public OnZKDesktopRegistry(Class<T> klass) {
|
public OnZKDesktopRegistry(Class<T> klass) {
|
||||||
Validate.notNull(klass);
|
Validate.notNull(klass);
|
||||||
|
|
||||||
this.klass = klass;
|
this.klass = klass;
|
||||||
this.attributeName = klass.getName() + "_locator";
|
this.attributeName = klass.getName() + "_locator";
|
||||||
}
|
}
|
||||||
|
|
@ -51,6 +52,7 @@ public class OnZKDesktopRegistry<T> {
|
||||||
|
|
||||||
public boolean isRegistered() {
|
public boolean isRegistered() {
|
||||||
Object result = get();
|
Object result = get();
|
||||||
|
|
||||||
return result != null;
|
return result != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,10 +61,10 @@ public class OnZKDesktopRegistry<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public T retrieve() throws IllegalStateException {
|
public T retrieve() throws IllegalStateException {
|
||||||
if (!isRegistered()) {
|
if ( !isRegistered() ) {
|
||||||
throw new IllegalStateException("no " + klass.getSimpleName()
|
throw new IllegalStateException("no " + klass.getSimpleName() + " registered");
|
||||||
+ " registered");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return klass.cast(get());
|
return klass.cast(get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
package org.zkoss.ganttz.util;
|
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>
|
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||||
|
|
@ -38,7 +38,7 @@ public abstract class PreAndPostNotReentrantActionsWrapper {
|
||||||
|
|
||||||
public void doAction(IAction action) {
|
public void doAction(IAction action) {
|
||||||
Validate.notNull(action);
|
Validate.notNull(action);
|
||||||
if (inside.get()) {
|
if ( inside.get() ) {
|
||||||
action.doAction();
|
action.doAction();
|
||||||
} else {
|
} else {
|
||||||
executeWithPreAndPostActions(action);
|
executeWithPreAndPostActions(action);
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
public class WeakReferencedListeners<T> {
|
public class WeakReferencedListeners<T> {
|
||||||
|
|
||||||
|
|
@ -38,10 +38,10 @@ public class WeakReferencedListeners<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> WeakReferencedListeners<T> create() {
|
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() {
|
private WeakReferencedListeners() {
|
||||||
|
|
||||||
|
|
@ -58,13 +58,13 @@ public class WeakReferencedListeners<T> {
|
||||||
public synchronized void addListener(T listener, Mode mode) {
|
public synchronized void addListener(T listener, Mode mode) {
|
||||||
Validate.notNull(listener);
|
Validate.notNull(listener);
|
||||||
|
|
||||||
if (getActiveListeners().isEmpty() && mode == Mode.RECEIVE_PENDING) {
|
if ( getActiveListeners().isEmpty() && mode == Mode.RECEIVE_PENDING ) {
|
||||||
notifyPendingOfNotificationTo(listener);
|
notifyPendingOfNotificationTo(listener);
|
||||||
}
|
}
|
||||||
listeners.add(new WeakReference<T>(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) {
|
private void notifyPendingOfNotificationTo(T listener) {
|
||||||
for (IListenerNotification<? super T> each : pendingOfNotification) {
|
for (IListenerNotification<? super T> each : pendingOfNotification) {
|
||||||
|
|
@ -73,30 +73,31 @@ public class WeakReferencedListeners<T> {
|
||||||
pendingOfNotification.clear();
|
pendingOfNotification.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void fireEvent(
|
public synchronized void fireEvent(IListenerNotification<? super T> notification) {
|
||||||
IListenerNotification<? super T> notification) {
|
|
||||||
List<T> active = getActiveListeners();
|
List<T> active = getActiveListeners();
|
||||||
|
|
||||||
for (T listener : active) {
|
for (T listener : active) {
|
||||||
notification.doNotify(listener);
|
notification.doNotify(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active.isEmpty()) {
|
if ( active.isEmpty() ) {
|
||||||
pendingOfNotification.add(notification);
|
pendingOfNotification.add(notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<T> getActiveListeners() {
|
private List<T> getActiveListeners() {
|
||||||
ListIterator<WeakReference<T>> listIterator = listeners.listIterator();
|
ListIterator<WeakReference<T>> listIterator = listeners.listIterator();
|
||||||
List<T> result = new ArrayList<T>();
|
List<T> result = new ArrayList<>();
|
||||||
|
|
||||||
while (listIterator.hasNext()) {
|
while (listIterator.hasNext()) {
|
||||||
T listener = listIterator.next().get();
|
T listener = listIterator.next().get();
|
||||||
if (listener == null) {
|
if ( listener == null ) {
|
||||||
listIterator.remove();
|
listIterator.remove();
|
||||||
} else {
|
} else {
|
||||||
result.add(listener);
|
result.add(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,7 @@ public class LoadPeriodTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void givenExampleLoadPeriod(LocalDate start, LocalDate end) {
|
private void givenExampleLoadPeriod(LocalDate start, LocalDate end) {
|
||||||
givenExampleLoadPeriod(GanttDate.createFrom(start),
|
givenExampleLoadPeriod(GanttDate.createFrom(start), GanttDate.createFrom(end));
|
||||||
GanttDate.createFrom(end));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void givenExampleLoadPeriod(GanttDate start, GanttDate end) {
|
private void givenExampleLoadPeriod(GanttDate start, GanttDate end) {
|
||||||
|
|
@ -59,16 +58,13 @@ public class LoadPeriodTest {
|
||||||
givenExampleLoadPeriod(start, end, loadLevel);
|
givenExampleLoadPeriod(start, end, loadLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void givenExampleLoadPeriod(GanttDate start, GanttDate end,
|
private void givenExampleLoadPeriod(GanttDate start, GanttDate end, LoadLevel loadLevel) {
|
||||||
LoadLevel loadLevel) {
|
loadPeriod = new LoadPeriod(start, end, totalHours, assignedHours, loadLevel);
|
||||||
loadPeriod = new LoadPeriod(start, end, totalHours, assignedHours,
|
|
||||||
loadLevel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
public void aLoadPeriodMustHaveAStartDate() {
|
public void aLoadPeriodMustHaveAStartDate() {
|
||||||
new LoadPeriod(null, GanttDate.createFrom(new LocalDate()), totalHours,
|
new LoadPeriod(null, GanttDate.createFrom(new LocalDate()), totalHours, assignedHours, correctLoadLevel());
|
||||||
assignedHours, correctLoadLevel());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String totalHours = "100";
|
private static final String totalHours = "100";
|
||||||
|
|
@ -79,26 +75,33 @@ public class LoadPeriodTest {
|
||||||
return new LoadLevel(40);
|
return new LoadLevel(40);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
public void aLoadPeriodMustHaveAnEndDate() {
|
public void aLoadPeriodMustHaveAnEndDate() {
|
||||||
new LoadPeriod(GanttDate.createFrom(new LocalDate()), null, totalHours,
|
new LoadPeriod(GanttDate.createFrom(new LocalDate()), null, totalHours, assignedHours, correctLoadLevel());
|
||||||
assignedHours, correctLoadLevel());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void theEndDateCantBeBeforeTheStartDate() {
|
public void theEndDateCantBeBeforeTheStartDate() {
|
||||||
LocalDate start = new LocalDate(2009, 10, 4);
|
LocalDate start = new LocalDate(2009, 10, 4);
|
||||||
LocalDate end = new LocalDate(2009, 10, 3);
|
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
|
@Test
|
||||||
public void theEndDateCanBeTheSameThanTheStartDate() {
|
public void theEndDateCanBeTheSameThanTheStartDate() {
|
||||||
LocalDate start = new LocalDate(2009, 10, 4);
|
LocalDate start = new LocalDate(2009, 10, 4);
|
||||||
LocalDate end = 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
|
@Test
|
||||||
|
|
@ -115,8 +118,8 @@ public class LoadPeriodTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void twoLoadPeriodOverlapCanOverlap() {
|
public void twoLoadPeriodOverlapCanOverlap() {
|
||||||
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009,
|
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009, 12, 1));
|
||||||
12, 1));
|
|
||||||
assertTrue(loadPeriod.overlaps(create(2009, 11, 2, 2009, 11, 3)));
|
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, 30, 2009, 11, 2)));
|
||||||
assertTrue(loadPeriod.overlaps(create(2009, 10, 20, 2009, 12, 2)));
|
assertTrue(loadPeriod.overlaps(create(2009, 10, 20, 2009, 12, 2)));
|
||||||
|
|
@ -128,31 +131,31 @@ public class LoadPeriodTest {
|
||||||
@Test
|
@Test
|
||||||
// [start, end)
|
// [start, end)
|
||||||
public void startInclusiveButEndExclusive() {
|
public void startInclusiveButEndExclusive() {
|
||||||
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009,
|
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009, 12, 1));
|
||||||
12, 1));
|
|
||||||
assertFalse(loadPeriod.overlaps(create(2009, 12, 1, 2009, 12, 3)));
|
assertFalse(loadPeriod.overlaps(create(2009, 12, 1, 2009, 12, 3)));
|
||||||
assertFalse(loadPeriod.overlaps(create(2009, 10, 1, 2009, 11, 1)));
|
assertFalse(loadPeriod.overlaps(create(2009, 10, 1, 2009, 11, 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void pointDontOverlap() {
|
public void pointDontOverlap() {
|
||||||
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009,
|
givenExampleLoadPeriod(new LocalDate(2009, 11, 1), new LocalDate(2009, 12, 1));
|
||||||
12, 1));
|
|
||||||
assertFalse(loadPeriod.overlaps(create(2009, 11, 1, 2009, 11, 1)));
|
assertFalse(loadPeriod.overlaps(create(2009, 11, 1, 2009, 11, 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LoadPeriod create(int startYear, int startMonth,
|
private static LoadPeriod create(
|
||||||
int startDay, int endYear, int endMonth, int endDay) {
|
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(
|
return new LoadPeriod(
|
||||||
endYear, endMonth, endDay)), totalHours,
|
GanttDate.createFrom(new LocalDate(startYear, startMonth, startDay)),
|
||||||
assignedHours, correctLoadLevel());
|
GanttDate.createFrom(new LocalDate(endYear, endMonth, endDay)),
|
||||||
|
totalHours, assignedHours,
|
||||||
|
correctLoadLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void loadPeriodsThatOverlapCannotBeSorted() {
|
public void loadPeriodsThatOverlapCannotBeSorted() {
|
||||||
LoadPeriod.sort(Arrays.asList(create(2009, 4, 10, 2010, 1, 12), create(
|
LoadPeriod.sort(Arrays.asList(create(2009, 4, 10, 2010, 1, 12), create(2009, 4, 11, 2011, 1, 20)));
|
||||||
2009, 4, 11, 2011, 1, 20)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -164,15 +167,16 @@ public class LoadPeriodTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void aZeroDaysLoadPeriodStartingTheSameDateThanANoZeroDaysLoadPeriodGoesAfter() {
|
public void aZeroDaysLoadPeriodStartingTheSameDateThanANoZeroDaysLoadPeriodGoesAfter() {
|
||||||
givenUnsortedListOfPeriods(create(2009, 4, 10, 2010, 1, 12), create(
|
givenUnsortedListOfPeriods(create(2009, 4, 10, 2010, 1, 12), create(2009, 4, 10, 2009, 4, 10));
|
||||||
2009, 4, 10, 2009, 4, 10));
|
|
||||||
List<LoadPeriod> sorted = LoadPeriod.sort(unsortedList);
|
List<LoadPeriod> sorted = LoadPeriod.sort(unsortedList);
|
||||||
thenIsSorted(sorted);
|
thenIsSorted(sorted);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void givenUnsortedListOfPeriods() {
|
private void givenUnsortedListOfPeriods() {
|
||||||
givenUnsortedListOfPeriods(create(2009, 4, 10, 2010, 1, 12), create(
|
givenUnsortedListOfPeriods(
|
||||||
2010, 1, 12, 2010, 1, 12), create(2010, 2, 13, 2010, 5, 7),
|
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));
|
create(2009, 3, 5, 2009, 3, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,18 +186,19 @@ public class LoadPeriodTest {
|
||||||
|
|
||||||
private void thenIsSorted(List<LoadPeriod> sorted) {
|
private void thenIsSorted(List<LoadPeriod> sorted) {
|
||||||
ListIterator<LoadPeriod> listIterator = sorted.listIterator();
|
ListIterator<LoadPeriod> listIterator = sorted.listIterator();
|
||||||
LoadPeriod previous = null;
|
LoadPeriod previous;
|
||||||
LoadPeriod current = null;
|
LoadPeriod current = null;
|
||||||
|
|
||||||
while (listIterator.hasNext()) {
|
while (listIterator.hasNext()) {
|
||||||
previous = current;
|
previous = current;
|
||||||
current = listIterator.next();
|
current = listIterator.next();
|
||||||
if (previous != null) {
|
if ( previous != null ) {
|
||||||
assertFalse(current.getStart().compareTo(previous.getEnd()) < 0);
|
assertFalse(current.getStart().compareTo(previous.getEnd()) < 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
public void aLoadPeriodMustHaveANotNullLoadLevel() {
|
public void aLoadPeriodMustHaveANotNullLoadLevel() {
|
||||||
givenExampleLoadPeriod();
|
givenExampleLoadPeriod();
|
||||||
new LoadPeriod(start, end, totalHours, assignedHours, null);
|
new LoadPeriod(start, end, totalHours, assignedHours, null);
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ public class LoadTimelineTest {
|
||||||
private LoadTimeLine loadTimeLine;
|
private LoadTimeLine loadTimeLine;
|
||||||
private String conceptName;
|
private String conceptName;
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
public void aLoadTimelineMustHaveANotNullName() {
|
public void aLoadTimelineMustHaveANotNullName() {
|
||||||
new LoadTimeLine(null, Collections.<LoadPeriod> emptyList(), null);
|
new LoadTimeLine(null, Collections.<LoadPeriod> emptyList(), null);
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +49,7 @@ public class LoadTimelineTest {
|
||||||
new LoadTimeLine("", Collections.<LoadPeriod> emptyList(), null);
|
new LoadTimeLine("", Collections.<LoadPeriod> emptyList(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
public void aLoadTimelineCannotHaveNullLoadPeriods() {
|
public void aLoadTimelineCannotHaveNullLoadPeriods() {
|
||||||
new LoadTimeLine("bla", null, null);
|
new LoadTimeLine("bla", null, null);
|
||||||
}
|
}
|
||||||
|
|
@ -62,30 +62,34 @@ public class LoadTimelineTest {
|
||||||
|
|
||||||
private void givenValidLoadTimeLine() {
|
private void givenValidLoadTimeLine() {
|
||||||
conceptName = "bla";
|
conceptName = "bla";
|
||||||
loadTimeLine = new LoadTimeLine(conceptName,
|
loadTimeLine = new LoadTimeLine(
|
||||||
|
conceptName,
|
||||||
Arrays.asList(new LoadPeriod(GanttDate
|
Arrays.asList(new LoadPeriod(GanttDate
|
||||||
.createFrom(new LocalDate(2009, 10, 5)), GanttDate
|
.createFrom(new LocalDate(2009, 10, 5)), GanttDate
|
||||||
.createFrom(new LocalDate(2009, 10, 11)), "100", "20",
|
.createFrom(new LocalDate(2009, 10, 11)), "100", "20",
|
||||||
new LoadLevel(20))), null);
|
new LoadLevel(20))),
|
||||||
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void aLoadTimelineWithZeroLoadPeriodsIsEmpty() {
|
public void aLoadTimelineWithZeroLoadPeriodsIsEmpty() {
|
||||||
LoadTimeLine timeline = new LoadTimeLine("bla", Collections
|
LoadTimeLine timeline = new LoadTimeLine("bla", Collections.<LoadPeriod> emptyList(), null);
|
||||||
.<LoadPeriod> emptyList(), null);
|
|
||||||
assertTrue(timeline.isEmpty());
|
assertTrue(timeline.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void aLoadTimelineSortsItsReceivedPeriods() {
|
public void aLoadTimelineSortsItsReceivedPeriods() {
|
||||||
LoadPeriod l1 = new LoadPeriod(GanttDate.createFrom(new LocalDate(2009,
|
LoadPeriod l1 = new LoadPeriod(
|
||||||
10, 5)), GanttDate.createFrom(new LocalDate(2009, 10, 11)),
|
GanttDate.createFrom(new LocalDate(2009, 10, 5)),
|
||||||
|
GanttDate.createFrom(new LocalDate(2009, 10, 11)),
|
||||||
"100", "20", new LoadLevel(20));
|
"100", "20", new LoadLevel(20));
|
||||||
LoadPeriod l2 = new LoadPeriod(GanttDate.createFrom(new LocalDate(2009,
|
|
||||||
5, 3)), GanttDate.createFrom(new LocalDate(2009, 6, 3)), "100",
|
LoadPeriod l2 = new LoadPeriod(
|
||||||
"20", new LoadLevel(20));
|
GanttDate.createFrom(new LocalDate(2009, 5, 3)),
|
||||||
LoadTimeLine loadTimeLine = new LoadTimeLine("bla", Arrays.asList(l1,
|
GanttDate.createFrom(new LocalDate(2009, 6, 3)),
|
||||||
l2), null);
|
"100", "20", new LoadLevel(20));
|
||||||
|
|
||||||
|
LoadTimeLine loadTimeLine = new LoadTimeLine("bla", Arrays.asList(l1, l2), null);
|
||||||
|
|
||||||
List<LoadPeriod> loadPeriods = loadTimeLine.getLoadPeriods();
|
List<LoadPeriod> loadPeriods = loadTimeLine.getLoadPeriods();
|
||||||
assertThat(loadPeriods.get(0), sameInstance(l2));
|
assertThat(loadPeriods.get(0), sameInstance(l2));
|
||||||
|
|
@ -94,12 +98,16 @@ public class LoadTimelineTest {
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void theLoadPeriodsMustNotOverlap() {
|
public void theLoadPeriodsMustNotOverlap() {
|
||||||
LoadPeriod l1 = new LoadPeriod(GanttDate.createFrom(new LocalDate(2009,
|
LoadPeriod l1 = new LoadPeriod(
|
||||||
10, 5)), GanttDate.createFrom(new LocalDate(2009, 10, 11)),
|
GanttDate.createFrom(new LocalDate(2009, 10, 5)),
|
||||||
|
GanttDate.createFrom(new LocalDate(2009, 10, 11)),
|
||||||
"100", "20", new LoadLevel(20));
|
"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));
|
"100", "20", new LoadLevel(20));
|
||||||
|
|
||||||
new LoadTimeLine("bla", Arrays.asList(l1, l2), null);
|
new LoadTimeLine("bla", Arrays.asList(l1, l2), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,7 @@ public class OnColumnsRowRendererTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CellRenderer implements
|
private static class CellRenderer implements ICellForDetailItemRenderer<DetailItem, Data> {
|
||||||
ICellForDetailItemRenderer<DetailItem, Data> {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Component cellFor(DetailItem item, Data data) {
|
public Component cellFor(DetailItem item, Data data) {
|
||||||
|
|
@ -57,8 +56,7 @@ public class OnColumnsRowRendererTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CellRendererNotInferable<T> implements
|
private static class CellRendererNotInferable<T> implements ICellForDetailItemRenderer<DetailItem, T> {
|
||||||
ICellForDetailItemRenderer<DetailItem, T> {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Component cellFor(DetailItem item, T data) {
|
public Component cellFor(DetailItem item, T data) {
|
||||||
|
|
@ -75,20 +73,19 @@ public class OnColumnsRowRendererTest {
|
||||||
|
|
||||||
private List<Data> data;
|
private List<Data> data;
|
||||||
|
|
||||||
private void givenOnDetailItemsRowRenderer(
|
private void givenOnDetailItemsRowRenderer(ICellForDetailItemRenderer<DetailItem, Data> cellRenderer) {
|
||||||
ICellForDetailItemRenderer<DetailItem, Data> cellRenderer) {
|
if ( detailItems == null ) {
|
||||||
if (detailItems == null) {
|
|
||||||
givenDetailItems();
|
givenDetailItems();
|
||||||
}
|
}
|
||||||
rowRenderer = OnColumnsRowRenderer.create(Data.class, cellRenderer,
|
rowRenderer = OnColumnsRowRenderer.create(Data.class, cellRenderer, detailItems);
|
||||||
detailItems);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void givenDetailItems() {
|
private void givenDetailItems() {
|
||||||
detailItems = new ArrayList<DetailItem>();
|
detailItems = new ArrayList<>();
|
||||||
start = new LocalDate(2010, 1, 1).toDateMidnight().toDateTime();
|
start = new LocalDate(2010, 1, 1).toDateMidnight().toDateTime();
|
||||||
DateTime current = start;
|
DateTime current = start;
|
||||||
Period period = Period.months(2);
|
Period period = Period.months(2);
|
||||||
|
|
||||||
for (int i = 1; i <= 10; i++) {
|
for (int i = 1; i <= 10; i++) {
|
||||||
DateTime end = current.plus(period);
|
DateTime end = current.plus(period);
|
||||||
DetailItem detail = new DetailItem(200, i + "", current, end);
|
DetailItem detail = new DetailItem(200, i + "", current, end);
|
||||||
|
|
@ -98,57 +95,50 @@ public class OnColumnsRowRendererTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void givenData() {
|
private void givenData() {
|
||||||
data = new ArrayList<Data>();
|
data = new ArrayList<>();
|
||||||
data.add(new Data());
|
data.add(new Data());
|
||||||
data.add(new Data());
|
data.add(new Data());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
public void itNeedsNotNullDetailItems() {
|
public void itNeedsNotNullDetailItems() {
|
||||||
OnColumnsRowRenderer.create(Data.class, createStub(), null);
|
OnColumnsRowRenderer.create(Data.class, createStub(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
public void itNeedsNotNullCellRenderer() {
|
public void itNeedsNotNullCellRenderer() {
|
||||||
OnColumnsRowRenderer.create(Data.class, null,
|
OnColumnsRowRenderer.create(Data.class, null, new ArrayList<DetailItem>());
|
||||||
new ArrayList<DetailItem>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
public void itNeedsTheTypeAsClass() {
|
public void itNeedsTheTypeAsClass() {
|
||||||
OnColumnsRowRenderer.create(null, createStub(),
|
OnColumnsRowRenderer.create(null, createStub(), new ArrayList<DetailItem>());
|
||||||
new ArrayList<DetailItem>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void itCanHaveEmptyDetailItems() {
|
public void itCanHaveEmptyDetailItems() {
|
||||||
OnColumnsRowRenderer.create(Data.class, createStub(),
|
OnColumnsRowRenderer.create(Data.class, createStub(), new ArrayList<DetailItem>());
|
||||||
new ArrayList<DetailItem>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void itCanInferTheGenericType() {
|
public void itCanInferTheGenericType() {
|
||||||
OnColumnsRowRenderer.create(new CellRenderer(),
|
OnColumnsRowRenderer.create(new CellRenderer(), new ArrayList<DetailItem>());
|
||||||
new ArrayList<DetailItem>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void ifComesFromRawTypeIsNotInferrable() {
|
public void ifComesFromRawTypeIsNotInferrable() {
|
||||||
OnColumnsRowRenderer.create(createStub(),
|
OnColumnsRowRenderer.create(createStub(), new ArrayList<DetailItem>());
|
||||||
new ArrayList<DetailItem>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void ifItNotShowsTheActualTypeIsNotInferrable() {
|
public void ifItNotShowsTheActualTypeIsNotInferrable() {
|
||||||
OnColumnsRowRenderer.create(new CellRendererNotInferable<Data>(),
|
OnColumnsRowRenderer.create(new CellRendererNotInferable<Data>(), new ArrayList<DetailItem>());
|
||||||
new ArrayList<DetailItem>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void noDetailItemCanBeNull() {
|
public void noDetailItemCanBeNull() {
|
||||||
OnColumnsRowRenderer.create(Data.class, createStub(),
|
OnColumnsRowRenderer.create(Data.class, createStub(), new ArrayList<DetailItem>() {
|
||||||
new ArrayList<DetailItem>() {
|
|
||||||
{
|
{
|
||||||
add(new DetailItem(300, "bla"));
|
add(new DetailItem(300, "bla"));
|
||||||
add(null);
|
add(null);
|
||||||
|
|
@ -193,6 +183,7 @@ public class OnColumnsRowRendererTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
replay(mock);
|
replay(mock);
|
||||||
|
|
||||||
return mock;
|
return mock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,17 +200,16 @@ public class OnColumnsRowRendererTest {
|
||||||
verify(labelMock);
|
verify(labelMock);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Label expectTheCreatedLabelIsAddedToTheRow(
|
private Label expectTheCreatedLabelIsAddedToTheRow(ICellForDetailItemRenderer<DetailItem, Data> mock) {
|
||||||
ICellForDetailItemRenderer<DetailItem, Data> mock) {
|
|
||||||
Label labelMock = createStrictMock(Label.class);
|
Label labelMock = createStrictMock(Label.class);
|
||||||
for (Data d : data) {
|
for (Data ignored1 : data) {
|
||||||
for (DetailItem item : detailItems) {
|
for (DetailItem ignored2 : detailItems) {
|
||||||
expect(mock.cellFor(isA(DetailItem.class), isA(Data.class)))
|
expect(mock.cellFor(isA(DetailItem.class), isA(Data.class))).andReturn(labelMock);
|
||||||
.andReturn(labelMock);
|
|
||||||
labelMock.setParent(isA(Row.class));
|
labelMock.setParent(isA(Row.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
replay(mock, labelMock);
|
replay(mock, labelMock);
|
||||||
|
|
||||||
return labelMock;
|
return labelMock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,15 @@ public class AvailabilityTimeLine {
|
||||||
@Override
|
@Override
|
||||||
public final int compareTo(DatePoint obj) {
|
public final int compareTo(DatePoint obj) {
|
||||||
Validate.notNull(obj);
|
Validate.notNull(obj);
|
||||||
if (obj instanceof FixedPoint) {
|
if ( obj instanceof FixedPoint ) {
|
||||||
return compareTo((FixedPoint) obj);
|
return compareTo((FixedPoint) obj);
|
||||||
} else if (obj instanceof EndOfTime) {
|
|
||||||
|
} else if ( obj instanceof EndOfTime ) {
|
||||||
return compareTo((EndOfTime) obj);
|
return compareTo((EndOfTime) obj);
|
||||||
} else if (obj instanceof StartOfTime) {
|
|
||||||
|
} else if ( obj instanceof StartOfTime ) {
|
||||||
return compareTo((StartOfTime) obj);
|
return compareTo((StartOfTime) obj);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("unknown subclass for " + obj);
|
throw new RuntimeException("unknown subclass for " + obj);
|
||||||
}
|
}
|
||||||
|
|
@ -69,15 +72,19 @@ public class AvailabilityTimeLine {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean equals(Object obj) {
|
public final boolean equals(Object obj) {
|
||||||
if (!(obj instanceof DatePoint)) {
|
if ( !(obj instanceof DatePoint) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (obj instanceof FixedPoint) {
|
|
||||||
|
if ( obj instanceof FixedPoint ) {
|
||||||
return equalTo((FixedPoint) obj);
|
return equalTo((FixedPoint) obj);
|
||||||
} else if (obj instanceof EndOfTime) {
|
|
||||||
|
} else if ( obj instanceof EndOfTime ) {
|
||||||
return equalTo((EndOfTime) obj);
|
return equalTo((EndOfTime) obj);
|
||||||
} else if (obj instanceof StartOfTime) {
|
|
||||||
|
} else if ( obj instanceof StartOfTime ) {
|
||||||
return equalTo((StartOfTime) obj);
|
return equalTo((StartOfTime) obj);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("unknown subclass for " + obj);
|
throw new RuntimeException("unknown subclass for " + obj);
|
||||||
}
|
}
|
||||||
|
|
@ -142,6 +149,7 @@ public class AvailabilityTimeLine {
|
||||||
|
|
||||||
public static LocalDate tryExtract(DatePoint start) {
|
public static LocalDate tryExtract(DatePoint start) {
|
||||||
FixedPoint point = (FixedPoint) start;
|
FixedPoint point = (FixedPoint) start;
|
||||||
|
|
||||||
return point.getDate();
|
return point.getDate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -243,8 +251,7 @@ public class AvailabilityTimeLine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Interval implements
|
public static class Interval implements Comparable<Interval> {
|
||||||
Comparable<Interval> {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an interval. Null values can be provided.
|
* Creates an interval. Null values can be provided.
|
||||||
|
|
@ -256,10 +263,9 @@ public class AvailabilityTimeLine {
|
||||||
* @return an interval from start to end
|
* @return an interval from start to end
|
||||||
*/
|
*/
|
||||||
public static Interval create(LocalDate start, LocalDate end) {
|
public static Interval create(LocalDate start, LocalDate end) {
|
||||||
DatePoint startPoint = start == null ? new StartOfTime()
|
DatePoint startPoint = start == null ? new StartOfTime() : new FixedPoint(start);
|
||||||
: new FixedPoint(start);
|
DatePoint endPoint = end == null ? new EndOfTime() : new FixedPoint(end);
|
||||||
DatePoint endPoint = end == null ? new EndOfTime()
|
|
||||||
: new FixedPoint(end);
|
|
||||||
return new Interval(startPoint, endPoint);
|
return new Interval(startPoint, endPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -272,13 +278,11 @@ public class AvailabilityTimeLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Interval to(LocalDate date) {
|
public static Interval to(LocalDate date) {
|
||||||
return new Interval(StartOfTime.create(), new FixedPoint(
|
return new Interval(StartOfTime.create(), new FixedPoint(date));
|
||||||
date));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Interval point(LocalDate start) {
|
static Interval point(LocalDate start) {
|
||||||
return new Interval(new FixedPoint(start), new FixedPoint(start
|
return new Interval(new FixedPoint(start), new FixedPoint(start.plusDays(1)));
|
||||||
.plusDays(1)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final DatePoint start;
|
private final DatePoint start;
|
||||||
|
|
@ -300,17 +304,17 @@ public class AvailabilityTimeLine {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Interval other) {
|
public int compareTo(Interval other) {
|
||||||
return this.start.compareTo(other.start) * 2
|
return this.start.compareTo(other.start) * 2 - this.end.compareTo(other.end);
|
||||||
- this.end.compareTo(other.end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj instanceof Interval) {
|
if ( obj instanceof Interval ) {
|
||||||
Interval other = (Interval) obj;
|
Interval other = (Interval) obj;
|
||||||
return start.equals(other.getStart())
|
|
||||||
&& end.equals(other.getEnd());
|
return start.equals(other.getStart()) && end.equals(other.getEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -324,35 +328,32 @@ public class AvailabilityTimeLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean includes(FixedPoint point) {
|
private boolean includes(FixedPoint point) {
|
||||||
return start.equals(point) || start.compareTo(point) <= 0
|
return start.equals(point) || start.compareTo(point) <= 0 && point.compareTo(end) < 0;
|
||||||
&& point.compareTo(end) < 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean overlaps(Interval other) {
|
public boolean overlaps(Interval other) {
|
||||||
return start.compareTo(other.end) <= 0
|
return start.compareTo(other.end) <= 0 && end.compareTo(other.start) >= 0;
|
||||||
&& end.compareTo(other.start) >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Interval intersect(Interval other) {
|
public Interval intersect(Interval other) {
|
||||||
Validate.isTrue(overlaps(other));
|
Validate.isTrue(overlaps(other));
|
||||||
|
|
||||||
return new Interval(max(start, other.start), min(end, other.end));
|
return new Interval(max(start, other.start), min(end, other.end));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Interval coalesce(Interval other) {
|
public Interval coalesce(Interval other) {
|
||||||
if (!overlaps(other)) {
|
if ( !overlaps(other) ) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException("in order to coalesce two intervals must overlap");
|
||||||
"in order to coalesce two intervals must overlap");
|
|
||||||
}
|
}
|
||||||
return new Interval(min(start, other.start), max(end,
|
return new Interval(min(start, other.start), max(end, other.end));
|
||||||
other.end));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DatePoint min(DatePoint... values) {
|
private DatePoint min(DatePoint... values) {
|
||||||
return (DatePoint) Collections.min(Arrays.asList(values));
|
return Collections.min(Arrays.asList(values));
|
||||||
}
|
}
|
||||||
|
|
||||||
private DatePoint max(DatePoint... values) {
|
private DatePoint max(DatePoint... values) {
|
||||||
return (DatePoint) Collections.max(Arrays.asList(values));
|
return Collections.max(Arrays.asList(values));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -362,7 +363,7 @@ public class AvailabilityTimeLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IVetoer {
|
public interface IVetoer {
|
||||||
public boolean isValid(LocalDate date);
|
boolean isValid(LocalDate date);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AvailabilityTimeLine allValid() {
|
public static AvailabilityTimeLine allValid() {
|
||||||
|
|
@ -372,6 +373,7 @@ public class AvailabilityTimeLine {
|
||||||
public static AvailabilityTimeLine createAllInvalid() {
|
public static AvailabilityTimeLine createAllInvalid() {
|
||||||
AvailabilityTimeLine result = new AvailabilityTimeLine();
|
AvailabilityTimeLine result = new AvailabilityTimeLine();
|
||||||
result.allInvalid();
|
result.allInvalid();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -385,7 +387,7 @@ public class AvailabilityTimeLine {
|
||||||
|
|
||||||
private IVetoer vetoer = NO_VETOER;
|
private IVetoer vetoer = NO_VETOER;
|
||||||
|
|
||||||
private List<Interval> invalids = new ArrayList<Interval>();
|
private List<Interval> invalids = new ArrayList<>();
|
||||||
|
|
||||||
private AvailabilityTimeLine() {
|
private AvailabilityTimeLine() {
|
||||||
}
|
}
|
||||||
|
|
@ -395,23 +397,27 @@ public class AvailabilityTimeLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidBasedOnInvaidIntervals(LocalDate date) {
|
private boolean isValidBasedOnInvaidIntervals(LocalDate date) {
|
||||||
if (invalids.isEmpty()) {
|
if ( invalids.isEmpty() ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Interval possibleInterval = findPossibleIntervalFor(date);
|
Interval possibleInterval = findPossibleIntervalFor(date);
|
||||||
|
|
||||||
return possibleInterval == null || !possibleInterval.includes(date);
|
return possibleInterval == null || !possibleInterval.includes(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Interval findPossibleIntervalFor(LocalDate date) {
|
private Interval findPossibleIntervalFor(LocalDate date) {
|
||||||
Interval point = Interval.point(date);
|
Interval point = Interval.point(date);
|
||||||
int binarySearch = Collections.binarySearch(invalids, point);
|
int binarySearch = Collections.binarySearch(invalids, point);
|
||||||
if (binarySearch >= 0) {
|
|
||||||
|
if ( binarySearch >= 0) {
|
||||||
return invalids.get(binarySearch);
|
return invalids.get(binarySearch);
|
||||||
} else {
|
} else {
|
||||||
int insertionPoint = insertionPoint(binarySearch);
|
int insertionPoint = insertionPoint(binarySearch);
|
||||||
if (insertionPoint == 0) {
|
if ( insertionPoint == 0 ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return invalids.get(insertionPoint - 1);
|
return invalids.get(insertionPoint - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -439,10 +445,11 @@ public class AvailabilityTimeLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insert(Interval toBeInserted) {
|
private void insert(Interval toBeInserted) {
|
||||||
if (invalids.isEmpty()) {
|
if ( invalids.isEmpty() ) {
|
||||||
invalids.add(toBeInserted);
|
invalids.add(toBeInserted);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
toBeInserted = coalesceWithAdjacent(toBeInserted);
|
toBeInserted = coalesceWithAdjacent(toBeInserted);
|
||||||
int insertionPoint = insertBeforeAllAdjacent(toBeInserted);
|
int insertionPoint = insertBeforeAllAdjacent(toBeInserted);
|
||||||
removeAdjacent(insertionPoint, toBeInserted);
|
removeAdjacent(insertionPoint, toBeInserted);
|
||||||
|
|
@ -456,12 +463,14 @@ public class AvailabilityTimeLine {
|
||||||
*/
|
*/
|
||||||
private int findInsertionPosition(Interval interval) {
|
private int findInsertionPosition(Interval interval) {
|
||||||
int binarySearch = Collections.binarySearch(invalids, interval);
|
int binarySearch = Collections.binarySearch(invalids, interval);
|
||||||
|
|
||||||
return insertionPoint(binarySearch);
|
return insertionPoint(binarySearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int insertBeforeAllAdjacent(Interval toBeInserted) {
|
private int insertBeforeAllAdjacent(Interval toBeInserted) {
|
||||||
int insertionPoint = findInsertionPosition(toBeInserted);
|
int insertionPoint = findInsertionPosition(toBeInserted);
|
||||||
invalids.add(insertionPoint, toBeInserted);
|
invalids.add(insertionPoint, toBeInserted);
|
||||||
|
|
||||||
return insertionPoint;
|
return insertionPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,39 +480,43 @@ public class AvailabilityTimeLine {
|
||||||
for (Interval each : adjacent) {
|
for (Interval each : adjacent) {
|
||||||
result = result.coalesce(each);
|
result = result.coalesce(each);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Interval> getAdjacent(Interval toBeInserted) {
|
private List<Interval> getAdjacent(Interval toBeInserted) {
|
||||||
final int insertionPoint = findInsertionPosition(toBeInserted);
|
final int insertionPoint = findInsertionPosition(toBeInserted);
|
||||||
List<Interval> result = new ArrayList<Interval>();
|
List<Interval> result = new ArrayList<>();
|
||||||
assert insertionPoint <= invalids.size();
|
assert insertionPoint <= invalids.size();
|
||||||
|
|
||||||
for (int i = insertionPoint - 1; i >= 0 && at(i).overlaps(toBeInserted); i--) {
|
for (int i = insertionPoint - 1; i >= 0 && at(i).overlaps(toBeInserted); i--) {
|
||||||
result.add(at(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));
|
result.add(at(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Interval> intersectWithAdjacent(Interval interval) {
|
private List<Interval> intersectWithAdjacent(Interval interval) {
|
||||||
List<Interval> result = new ArrayList<Interval>();
|
List<Interval> result = new ArrayList<>();
|
||||||
List<Interval> adjacent = getAdjacent(interval);
|
List<Interval> adjacent = getAdjacent(interval);
|
||||||
|
|
||||||
for (Interval each : adjacent) {
|
for (Interval each : adjacent) {
|
||||||
assert interval.overlaps(each);
|
assert interval.overlaps(each);
|
||||||
result.add(interval.intersect(each));
|
result.add(interval.intersect(each));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeAdjacent(int insertionPoint, Interval inserted) {
|
private void removeAdjacent(int insertionPoint, Interval inserted) {
|
||||||
ListIterator<Interval> listIterator = invalids
|
ListIterator<Interval> listIterator = invalids.listIterator(insertionPoint + 1);
|
||||||
.listIterator(insertionPoint + 1);
|
|
||||||
while (listIterator.hasNext()) {
|
while (listIterator.hasNext()) {
|
||||||
Interval next = listIterator.next();
|
Interval next = listIterator.next();
|
||||||
if (!next.overlaps(inserted)) {
|
if ( !next.overlaps(inserted) ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
listIterator.remove();
|
listIterator.remove();
|
||||||
|
|
@ -515,14 +528,12 @@ public class AvailabilityTimeLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int insertionPoint(int binarySearchResult) {
|
private int insertionPoint(int binarySearchResult) {
|
||||||
return binarySearchResult < 0 ? (-binarySearchResult) - 1
|
return binarySearchResult < 0 ? (-binarySearchResult) - 1 : binarySearchResult;
|
||||||
: binarySearchResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invalidAt(LocalDate intervalStart, LocalDate intervalEnd) {
|
public void invalidAt(LocalDate intervalStart, LocalDate intervalEnd) {
|
||||||
if (intervalStart.isAfter(intervalEnd)) {
|
if ( intervalStart.isAfter(intervalEnd) ) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException("end must be equal or after start");
|
||||||
"end must be equal or after start");
|
|
||||||
}
|
}
|
||||||
insert(Interval.create(intervalStart, intervalEnd));
|
insert(Interval.create(intervalStart, intervalEnd));
|
||||||
}
|
}
|
||||||
|
|
@ -540,11 +551,11 @@ public class AvailabilityTimeLine {
|
||||||
inserting(result, invalids);
|
inserting(result, invalids);
|
||||||
inserting(result, another.invalids);
|
inserting(result, another.invalids);
|
||||||
result.setVetoer(and(this.vetoer, another.vetoer));
|
result.setVetoer(and(this.vetoer, another.vetoer));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IVetoer and(final IVetoer a,
|
private static IVetoer and(final IVetoer a, final IVetoer b) {
|
||||||
final IVetoer b) {
|
|
||||||
return new IVetoer() {
|
return new IVetoer() {
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(LocalDate date) {
|
public boolean isValid(LocalDate date) {
|
||||||
|
|
@ -556,27 +567,30 @@ public class AvailabilityTimeLine {
|
||||||
public AvailabilityTimeLine or(AvailabilityTimeLine another) {
|
public AvailabilityTimeLine or(AvailabilityTimeLine another) {
|
||||||
List<Interval> intersections = doIntersections(this, another);
|
List<Interval> intersections = doIntersections(this, another);
|
||||||
AvailabilityTimeLine result = AvailabilityTimeLine.allValid();
|
AvailabilityTimeLine result = AvailabilityTimeLine.allValid();
|
||||||
|
|
||||||
for (Interval each : intersections) {
|
for (Interval each : intersections) {
|
||||||
boolean fromStartOfTime = each.getStart().equals(
|
boolean fromStartOfTime = each.getStart().equals(StartOfTime.create());
|
||||||
StartOfTime.create());
|
|
||||||
boolean untilEndOfTime = each.getEnd().equals(EndOfTime.create());
|
boolean untilEndOfTime = each.getEnd().equals(EndOfTime.create());
|
||||||
if (fromStartOfTime && untilEndOfTime) {
|
|
||||||
|
if ( fromStartOfTime && untilEndOfTime ) {
|
||||||
result.allInvalid();
|
result.allInvalid();
|
||||||
} else if (fromStartOfTime) {
|
|
||||||
|
} else if ( fromStartOfTime ) {
|
||||||
result.invalidUntil(FixedPoint.tryExtract(each.getEnd()));
|
result.invalidUntil(FixedPoint.tryExtract(each.getEnd()));
|
||||||
} else if (untilEndOfTime) {
|
|
||||||
|
} else if ( untilEndOfTime ) {
|
||||||
result.invalidFrom(FixedPoint.tryExtract(each.getStart()));
|
result.invalidFrom(FixedPoint.tryExtract(each.getStart()));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result.invalidAt(FixedPoint.tryExtract(each.getStart()),
|
result.invalidAt(FixedPoint.tryExtract(each.getStart()), FixedPoint.tryExtract(each.getEnd()));
|
||||||
FixedPoint.tryExtract(each.getEnd()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.setVetoer(or(this.vetoer, another.vetoer));
|
result.setVetoer(or(this.vetoer, another.vetoer));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IVetoer or(final IVetoer a,
|
private static IVetoer or(final IVetoer a, final IVetoer b) {
|
||||||
final IVetoer b) {
|
|
||||||
return new IVetoer() {
|
return new IVetoer() {
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(LocalDate date) {
|
public boolean isValid(LocalDate date) {
|
||||||
|
|
@ -585,12 +599,12 @@ public class AvailabilityTimeLine {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Interval> doIntersections(AvailabilityTimeLine one,
|
private static List<Interval> doIntersections(AvailabilityTimeLine one, AvailabilityTimeLine another) {
|
||||||
AvailabilityTimeLine another) {
|
List<Interval> result = new ArrayList<>();
|
||||||
List<Interval> result = new ArrayList<Interval>();
|
|
||||||
for (Interval each : one.invalids) {
|
for (Interval each : one.invalids) {
|
||||||
result.addAll(another.intersectWithAdjacent(each));
|
result.addAll(another.intersectWithAdjacent(each));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -601,19 +615,22 @@ public class AvailabilityTimeLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Interval> getValidPeriods() {
|
public List<Interval> getValidPeriods() {
|
||||||
List<Interval> result = new ArrayList<Interval>();
|
List<Interval> result = new ArrayList<>();
|
||||||
DatePoint previous = StartOfTime.create();
|
DatePoint previous = StartOfTime.create();
|
||||||
|
|
||||||
for (Interval each : invalids) {
|
for (Interval each : invalids) {
|
||||||
DatePoint invalidStart = each.start;
|
DatePoint invalidStart = each.start;
|
||||||
if (!invalidStart.equals(StartOfTime.create())
|
if ( !invalidStart.equals(StartOfTime.create()) && !invalidStart.equals(EndOfTime.create()) ) {
|
||||||
&& !invalidStart.equals(EndOfTime.create())) {
|
|
||||||
result.add(new Interval(previous, invalidStart));
|
result.add(new Interval(previous, invalidStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
previous = each.getEnd();
|
previous = each.getEnd();
|
||||||
}
|
}
|
||||||
if (!previous.equals(EndOfTime.create())) {
|
|
||||||
|
if ( !previous.equals(EndOfTime.create()) ) {
|
||||||
result.add(new Interval(previous, EndOfTime.create()));
|
result.add(new Interval(previous, EndOfTime.create()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ public class Dependency extends BaseEntity {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
START_START {
|
START_START {
|
||||||
@Override
|
@Override
|
||||||
public boolean modifiesDestinationStart() {
|
public boolean modifiesDestinationStart() {
|
||||||
|
|
@ -61,6 +62,7 @@ public class Dependency extends BaseEntity {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
END_END {
|
END_END {
|
||||||
@Override
|
@Override
|
||||||
public boolean modifiesDestinationStart() {
|
public boolean modifiesDestinationStart() {
|
||||||
|
|
@ -72,6 +74,7 @@ public class Dependency extends BaseEntity {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
START_END {
|
START_END {
|
||||||
@Override
|
@Override
|
||||||
public boolean modifiesDestinationStart() {
|
public boolean modifiesDestinationStart() {
|
||||||
|
|
@ -89,12 +92,12 @@ public class Dependency extends BaseEntity {
|
||||||
public abstract boolean modifiesDestinationEnd();
|
public abstract boolean modifiesDestinationEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dependency create(TaskElement origin,
|
public static Dependency create(TaskElement origin, TaskElement destination, Type type) {
|
||||||
TaskElement destination, Type type) {
|
|
||||||
Dependency dependency = new Dependency(origin, destination, type);
|
Dependency dependency = new Dependency(origin, destination, type);
|
||||||
dependency.setNewObject(true);
|
dependency.setNewObject(true);
|
||||||
origin.add(dependency);
|
origin.add(dependency);
|
||||||
destination.add(dependency);
|
destination.add(dependency);
|
||||||
|
|
||||||
return dependency;
|
return dependency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,8 +120,8 @@ public class Dependency extends BaseEntity {
|
||||||
Validate.notNull(origin);
|
Validate.notNull(origin);
|
||||||
Validate.notNull(destination);
|
Validate.notNull(destination);
|
||||||
Validate.notNull(type);
|
Validate.notNull(type);
|
||||||
Validate.isTrue(!origin.equals(destination),
|
Validate.isTrue(!origin.equals(destination), "a dependency must have a different origin than destination");
|
||||||
"a dependency must have a different origin than destination");
|
|
||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
@ -145,8 +148,7 @@ public class Dependency extends BaseEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDependencyBetweenLimitedAllocatedTasks() {
|
public boolean isDependencyBetweenLimitedAllocatedTasks() {
|
||||||
return getOrigin().hasLimitedResourceAllocation() &&
|
return getOrigin().hasLimitedResourceAllocation() && getDestination().hasLimitedResourceAllocation();
|
||||||
getDestination().hasLimitedResourceAllocation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasLimitedQueueDependencyAssociated() {
|
public boolean hasLimitedQueueDependencyAssociated() {
|
||||||
|
|
@ -156,11 +158,15 @@ public class Dependency extends BaseEntity {
|
||||||
public Date getDateFromOrigin() {
|
public Date getDateFromOrigin() {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case END_START:
|
case END_START:
|
||||||
|
|
||||||
case END_END:
|
case END_END:
|
||||||
return origin.getEndDate();
|
return origin.getEndDate();
|
||||||
|
|
||||||
case START_END:
|
case START_END:
|
||||||
|
|
||||||
case START_START:
|
case START_START:
|
||||||
return origin.getStartDate();
|
return origin.getStartDate();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("unexpected type");
|
throw new RuntimeException("unexpected type");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,48 +58,48 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
|
|
||||||
private boolean consolidated = false;
|
private boolean consolidated = false;
|
||||||
|
|
||||||
public static Interval create(BigDecimal loadProportion, LocalDate start,
|
public static Interval create(BigDecimal loadProportion, LocalDate start, LocalDate end, boolean consolidated) {
|
||||||
LocalDate end, boolean consolidated) {
|
|
||||||
Interval result = create(loadProportion, start, end);
|
Interval result = create(loadProportion, start, end);
|
||||||
result.consolidated(consolidated);
|
result.consolidated(consolidated);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Interval create(BigDecimal loadProportion, LocalDate start,
|
public static Interval create(BigDecimal loadProportion, LocalDate start, LocalDate end) {
|
||||||
LocalDate end) {
|
|
||||||
return new Interval(loadProportion, start, end);
|
return new Interval(loadProportion, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Interval(BigDecimal loadProportion, LocalDate start,
|
public Interval(BigDecimal loadProportion, LocalDate start, LocalDate end) {
|
||||||
LocalDate end) {
|
|
||||||
Validate.notNull(loadProportion);
|
Validate.notNull(loadProportion);
|
||||||
Validate.isTrue(loadProportion.signum() >= 0);
|
Validate.isTrue(loadProportion.signum() >= 0);
|
||||||
Validate.notNull(end);
|
Validate.notNull(end);
|
||||||
this.loadProportion = loadProportion.setScale(2,
|
|
||||||
RoundingMode.HALF_UP);
|
this.loadProportion = loadProportion.setScale(2, RoundingMode.HALF_UP);
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double[] getHoursPointsFor(int totalHours,
|
public static double[] getHoursPointsFor(int totalHours, List<Interval> intervalsDefinedByStreches) {
|
||||||
List<Interval> intervalsDefinedByStreches) {
|
|
||||||
double[] result = new double[intervalsDefinedByStreches.size()];
|
double[] result = new double[intervalsDefinedByStreches.size()];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int accumulated = 0;
|
int accumulated = 0;
|
||||||
|
|
||||||
for (Interval each : intervalsDefinedByStreches) {
|
for (Interval each : intervalsDefinedByStreches) {
|
||||||
accumulated += each.getHoursFor(totalHours);
|
accumulated += each.getHoursFor(totalHours);
|
||||||
result[i++] = accumulated;
|
result[i++] = accumulated;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double[] getDayPointsFor(LocalDate start,
|
public static double[] getDayPointsFor(LocalDate start, List<Interval> intervalsDefinedByStreches) {
|
||||||
List<Interval> intervalsDefinedByStreches) {
|
|
||||||
double[] result = new double[intervalsDefinedByStreches.size()];
|
double[] result = new double[intervalsDefinedByStreches.size()];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (Interval each : intervalsDefinedByStreches) {
|
for (Interval each : intervalsDefinedByStreches) {
|
||||||
result[i++] = Days.daysBetween(start, each.getEnd()).getDays();
|
result[i++] = Days.daysBetween(start, each.getEnd()).getDays();
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,8 +120,7 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHoursFor(int totalHours) {
|
public int getHoursFor(int totalHours) {
|
||||||
return loadProportion.multiply(new BigDecimal(totalHours))
|
return loadProportion.multiply(new BigDecimal(totalHours)).intValue();
|
||||||
.intValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate getStartFor(LocalDate allocationStart) {
|
public LocalDate getStartFor(LocalDate allocationStart) {
|
||||||
|
|
@ -129,41 +128,43 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void apply(ResourceAllocation<?> resourceAllocation,
|
private void apply(ResourceAllocation<?> resourceAllocation,
|
||||||
LocalDate startInclusive, LocalDate taskEnd,
|
LocalDate startInclusive,
|
||||||
int intervalHours) {
|
int intervalHours) {
|
||||||
|
|
||||||
Validate.isTrue(!isConsolidated());
|
Validate.isTrue(!isConsolidated());
|
||||||
resourceAllocation.withPreviousAssociatedResources()
|
resourceAllocation.withPreviousAssociatedResources()
|
||||||
.onInterval(getStartFor(startInclusive), getEnd())
|
.onInterval(getStartFor(startInclusive), getEnd()).allocateHours(intervalHours);
|
||||||
.allocateHours(intervalHours);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void apply(ResourceAllocation<?> allocation,
|
public static void apply(ResourceAllocation<?> allocation,
|
||||||
List<Interval> intervalsDefinedByStreches,
|
List<Interval> intervalsDefinedByStreches,
|
||||||
LocalDate allocationStart, LocalDate allocationEnd,
|
LocalDate allocationStart,
|
||||||
int totalHours) {
|
int totalHours) {
|
||||||
if (intervalsDefinedByStreches.isEmpty()) {
|
|
||||||
|
if ( intervalsDefinedByStreches.isEmpty() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Validate.isTrue(totalHours == allocation.getNonConsolidatedHours());
|
Validate.isTrue(totalHours == allocation.getNonConsolidatedHours());
|
||||||
|
|
||||||
int[] hoursPerInterval = getHoursPerInterval(
|
int[] hoursPerInterval = getHoursPerInterval(intervalsDefinedByStreches, totalHours);
|
||||||
intervalsDefinedByStreches, totalHours);
|
|
||||||
int remainder = totalHours - sum(hoursPerInterval);
|
int remainder = totalHours - sum(hoursPerInterval);
|
||||||
hoursPerInterval[0] += remainder;
|
hoursPerInterval[0] += remainder;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (Interval interval : intervalsDefinedByStreches) {
|
for (Interval interval : intervalsDefinedByStreches) {
|
||||||
interval.apply(allocation, allocationStart, allocationEnd,
|
interval.apply(allocation, allocationStart, hoursPerInterval[i++]);
|
||||||
hoursPerInterval[i++]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] getHoursPerInterval(
|
private static int[] getHoursPerInterval(List<Interval> intervalsDefinedByStreches, int totalHours) {
|
||||||
List<Interval> intervalsDefinedByStreches, int totalHours) {
|
|
||||||
int[] hoursPerInterval = new int[intervalsDefinedByStreches.size()];
|
int[] hoursPerInterval = new int[intervalsDefinedByStreches.size()];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (Interval each : intervalsDefinedByStreches) {
|
for (Interval each : intervalsDefinedByStreches) {
|
||||||
hoursPerInterval[i++] = each.getHoursFor(totalHours);
|
hoursPerInterval[i++] = each.getHoursFor(totalHours);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hoursPerInterval;
|
return hoursPerInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,6 +173,7 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
for (int each : hoursPerInterval) {
|
for (int each : hoursPerInterval) {
|
||||||
result += each;
|
result += each;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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;
|
private StretchesFunctionTypeEnum type;
|
||||||
|
|
||||||
|
|
@ -203,7 +205,7 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
private ResourceAllocation<?> resourceAllocation;
|
private ResourceAllocation<?> resourceAllocation;
|
||||||
|
|
||||||
public static StretchesFunction create() {
|
public static StretchesFunction create() {
|
||||||
return (StretchesFunction) create(new StretchesFunction());
|
return create(new StretchesFunction());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -215,22 +217,27 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
|
|
||||||
public static List<Interval> intervalsFor(ResourceAllocation<?> allocation,
|
public static List<Interval> intervalsFor(ResourceAllocation<?> allocation,
|
||||||
Collection<? extends Stretch> streches) {
|
Collection<? extends Stretch> streches) {
|
||||||
ArrayList<Interval> result = new ArrayList<Interval>();
|
|
||||||
LocalDate previous = null, stretchDate = null;
|
ArrayList<Interval> result = new ArrayList<>();
|
||||||
BigDecimal sumOfProportions = BigDecimal.ZERO, loadedProportion = BigDecimal.ZERO;
|
LocalDate previous = null;
|
||||||
|
LocalDate stretchDate;
|
||||||
|
|
||||||
|
BigDecimal sumOfProportions = BigDecimal.ZERO;
|
||||||
|
BigDecimal loadedProportion;
|
||||||
|
|
||||||
for (Stretch each : streches) {
|
for (Stretch each : streches) {
|
||||||
stretchDate = each.getDateIn(allocation);
|
stretchDate = each.getDateIn(allocation);
|
||||||
loadedProportion = each.getAmountWorkPercentage().subtract(
|
loadedProportion = each.getAmountWorkPercentage().subtract(sumOfProportions);
|
||||||
sumOfProportions);
|
|
||||||
if (loadedProportion.signum() < 0) {
|
if ( loadedProportion.signum() < 0 ) {
|
||||||
loadedProportion = BigDecimal.ZERO;
|
loadedProportion = BigDecimal.ZERO;
|
||||||
}
|
}
|
||||||
result.add(Interval.create(loadedProportion, previous,
|
|
||||||
stretchDate, each.isConsolidated()));
|
result.add(Interval.create(loadedProportion, previous, stretchDate, each.isConsolidated()));
|
||||||
sumOfProportions = each.getAmountWorkPercentage();
|
sumOfProportions = each.getAmountWorkPercentage();
|
||||||
previous = stretchDate;
|
previous = stretchDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -245,6 +252,7 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
result.desiredType = desiredType;
|
result.desiredType = desiredType;
|
||||||
result.consolidatedStretch = consolidatedStretch;
|
result.consolidatedStretch = consolidatedStretch;
|
||||||
result.resourceAllocation = resourceAllocation;
|
result.resourceAllocation = resourceAllocation;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -257,29 +265,30 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Stretch> getStretchesDefinedByUser() {
|
public List<Stretch> getStretchesDefinedByUser() {
|
||||||
return Collections.unmodifiableList(Stretch
|
return Collections.unmodifiableList(Stretch.sortByLengthPercentage(stretches));
|
||||||
.sortByLengthPercentage(stretches));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Valid
|
@Valid
|
||||||
public List<Stretch> getStretches() {
|
public List<Stretch> getStretches() {
|
||||||
List<Stretch> result = new ArrayList<Stretch>();
|
List<Stretch> result = new ArrayList<>();
|
||||||
result.add(getFirstStretch());
|
result.add(getFirstStretch());
|
||||||
result.addAll(stretches);
|
result.addAll(stretches);
|
||||||
result.add(getLastStretch());
|
result.add(getLastStretch());
|
||||||
return Collections.unmodifiableList(Stretch
|
|
||||||
.sortByLengthPercentage(result));
|
return Collections.unmodifiableList(Stretch.sortByLengthPercentage(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stretch getLastStretch() {
|
private Stretch getLastStretch() {
|
||||||
Stretch result = Stretch.create(BigDecimal.ONE, BigDecimal.ONE);
|
Stretch result = Stretch.create(BigDecimal.ONE, BigDecimal.ONE);
|
||||||
result.readOnly(true);
|
result.readOnly(true);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stretch getFirstStretch() {
|
private Stretch getFirstStretch() {
|
||||||
Stretch result = Stretch.create(BigDecimal.ZERO, BigDecimal.ZERO);
|
Stretch result = Stretch.create(BigDecimal.ZERO, BigDecimal.ZERO);
|
||||||
result.readOnly(true);
|
result.readOnly(true);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,67 +322,74 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
return getStretchesPlusConsolidated().size() > 2;
|
return getStretchesPlusConsolidated().size() > 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@AssertTrue(message = "A stretch has lower or equal values than the "
|
@AssertTrue(message = "A stretch has lower or equal values than the previous stretch")
|
||||||
+ "previous stretch")
|
|
||||||
public boolean isStretchesOrderConstraint() {
|
public boolean isStretchesOrderConstraint() {
|
||||||
List<Stretch> stretchesPlusConsolidated = getStretchesPlusConsolidated();
|
List<Stretch> stretchesPlusConsolidated = getStretchesPlusConsolidated();
|
||||||
if (stretchesPlusConsolidated.isEmpty()) {
|
if ( stretchesPlusConsolidated.isEmpty() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<Stretch> iterator = stretchesPlusConsolidated.iterator();
|
Iterator<Stretch> iterator = stretchesPlusConsolidated.iterator();
|
||||||
Stretch previous = iterator.next();
|
Stretch previous = iterator.next();
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
Stretch current = iterator.next();
|
Stretch current = iterator.next();
|
||||||
if (current.getLengthPercentage().compareTo(
|
if ( current.getLengthPercentage().compareTo(previous.getLengthPercentage()) <= 0 ) {
|
||||||
previous.getLengthPercentage()) <= 0) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (current.getAmountWorkPercentage().compareTo(
|
|
||||||
previous.getAmountWorkPercentage()) <= 0) {
|
if ( current.getAmountWorkPercentage().compareTo(previous.getAmountWorkPercentage()) <= 0 ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
previous = current;
|
previous = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Stretch> getStretchesPlusConsolidated() {
|
public List<Stretch> getStretchesPlusConsolidated() {
|
||||||
List<Stretch> result = new ArrayList<Stretch>();
|
List<Stretch> result = new ArrayList<>();
|
||||||
result.addAll(getStretches());
|
result.addAll(getStretches());
|
||||||
if (consolidatedStretch != null) {
|
|
||||||
|
if ( consolidatedStretch != null ) {
|
||||||
result.add(consolidatedStretch);
|
result.add(consolidatedStretch);
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableList(Stretch
|
|
||||||
.sortByLengthPercentage(result));
|
return Collections.unmodifiableList(Stretch.sortByLengthPercentage(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
@AssertTrue(message = "Last stretch should have one hundred percent "
|
@AssertTrue(message = "Last stretch should have one hundred percent " +
|
||||||
+ "length and one hundred percent of work percentage")
|
"length and one hundred percent of work percentage")
|
||||||
public boolean isOneHundredPercentConstraint() {
|
public boolean isOneHundredPercentConstraint() {
|
||||||
List<Stretch> stretches = getStretchesPlusConsolidated();
|
List<Stretch> stretches = getStretchesPlusConsolidated();
|
||||||
if (stretches.isEmpty()) {
|
if ( stretches.isEmpty() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stretch lastStretch = stretches.get(stretches.size() - 1);
|
Stretch lastStretch = stretches.get(stretches.size() - 1);
|
||||||
if (lastStretch.getLengthPercentage().compareTo(BigDecimal.ONE) != 0) {
|
if ( lastStretch.getLengthPercentage().compareTo(BigDecimal.ONE) != 0 ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (lastStretch.getAmountWorkPercentage().compareTo(BigDecimal.ONE) != 0) {
|
|
||||||
|
if ( lastStretch.getAmountWorkPercentage().compareTo(BigDecimal.ONE) != 0 ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyTo(ResourceAllocation<?> resourceAllocation) {
|
public void applyTo(ResourceAllocation<?> resourceAllocation) {
|
||||||
if (!resourceAllocation.hasAssignments()) {
|
if ( !resourceAllocation.hasAssignments() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is 100% consolidated
|
// Is 100% consolidated
|
||||||
if (resourceAllocation.getFirstNonConsolidatedDate() == null) {
|
if ( resourceAllocation.getFirstNonConsolidatedDate() == null ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.resourceAllocation = resourceAllocation;
|
this.resourceAllocation = resourceAllocation;
|
||||||
getDesiredType().applyTo(resourceAllocation, this);
|
getDesiredType().applyTo(resourceAllocation, this);
|
||||||
type = getDesiredType();
|
type = getDesiredType();
|
||||||
|
|
@ -381,7 +397,7 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
if (StretchesFunctionTypeEnum.INTERPOLATED.equals(type)) {
|
if ( StretchesFunctionTypeEnum.INTERPOLATED.equals(type) ) {
|
||||||
return AssignmentFunctionName.INTERPOLATION.toString();
|
return AssignmentFunctionName.INTERPOLATION.toString();
|
||||||
} else {
|
} else {
|
||||||
return AssignmentFunctionName.STRETCHES.toString();
|
return AssignmentFunctionName.STRETCHES.toString();
|
||||||
|
|
@ -389,25 +405,27 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Interval> getIntervalsDefinedByStreches() {
|
public List<Interval> getIntervalsDefinedByStreches() {
|
||||||
List<Stretch> stretches = stretchesFor(type);
|
List<Stretch> stretches = stretchesFor();
|
||||||
if (stretches.isEmpty()) {
|
if ( stretches.isEmpty() ) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
checkStretchesSumOneHundredPercent();
|
checkStretchesSumOneHundredPercent();
|
||||||
|
|
||||||
return intervalsFor(resourceAllocation, stretches);
|
return intervalsFor(resourceAllocation, stretches);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Stretch> stretchesFor(StretchesFunctionTypeEnum type) {
|
private List<Stretch> stretchesFor() {
|
||||||
return (getDesiredType().equals(StretchesFunctionTypeEnum.INTERPOLATED)) ? getStretchesPlusConsolidated()
|
boolean condition = (getDesiredType().equals(StretchesFunctionTypeEnum.INTERPOLATED));
|
||||||
: getStretches();
|
|
||||||
|
return condition ? getStretchesPlusConsolidated() : getStretches();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkStretchesSumOneHundredPercent() {
|
private void checkStretchesSumOneHundredPercent() {
|
||||||
List<Stretch> stretches = getStretchesPlusConsolidated();
|
List<Stretch> stretches = getStretchesPlusConsolidated();
|
||||||
BigDecimal sumOfProportions = stretches.isEmpty() ? BigDecimal.ZERO
|
BigDecimal sumOfProportions = stretches.isEmpty() ? BigDecimal.ZERO : last(stretches).getAmountWorkPercentage();
|
||||||
: last(stretches).getAmountWorkPercentage();
|
|
||||||
BigDecimal left = calculateLeftFor(sumOfProportions);
|
BigDecimal left = calculateLeftFor(sumOfProportions);
|
||||||
if (!left.equals(BigDecimal.ZERO)) {
|
|
||||||
|
if ( !left.equals(BigDecimal.ZERO) ) {
|
||||||
throw new IllegalStateException(_("Stretches must sum 100%"));
|
throw new IllegalStateException(_("Stretches must sum 100%"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -415,6 +433,7 @@ public class StretchesFunction extends AssignmentFunction {
|
||||||
private BigDecimal calculateLeftFor(BigDecimal sumOfProportions) {
|
private BigDecimal calculateLeftFor(BigDecimal sumOfProportions) {
|
||||||
BigDecimal left = BigDecimal.ONE.subtract(sumOfProportions);
|
BigDecimal left = BigDecimal.ONE.subtract(sumOfProportions);
|
||||||
left = left.signum() <= 0 ? BigDecimal.ZERO : left;
|
left = left.signum() <= 0 ? BigDecimal.ZERO : left;
|
||||||
|
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public enum StretchesFunctionTypeEnum {
|
||||||
LocalDate startInclusive, LocalDate endExclusive,
|
LocalDate startInclusive, LocalDate endExclusive,
|
||||||
int totalHours) {
|
int totalHours) {
|
||||||
|
|
||||||
Interval.apply(allocation, intervalsDefinedByStreches, startInclusive, endExclusive, totalHours);
|
Interval.apply(allocation, intervalsDefinedByStreches, startInclusive, totalHours);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
INTERPOLATED {
|
INTERPOLATED {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -55,11 +55,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
@Repository
|
@Repository
|
||||||
@Scope(BeanDefinition.SCOPE_SINGLETON)
|
@Scope(BeanDefinition.SCOPE_SINGLETON)
|
||||||
@Transactional
|
@Transactional
|
||||||
public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
public class ResourceDAO extends IntegrationEntityDAO<Resource> implements IResourceDAO {
|
||||||
IResourceDAO {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IScenarioManager scenarioManager;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Worker> getWorkers() {
|
public List<Worker> getWorkers() {
|
||||||
|
|
@ -71,10 +67,11 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
||||||
List<Worker> list = getWorkers();
|
List<Worker> list = getWorkers();
|
||||||
for (Iterator<Worker> iterator = list.iterator(); iterator.hasNext();) {
|
for (Iterator<Worker> iterator = list.iterator(); iterator.hasNext();) {
|
||||||
Worker worker = iterator.next();
|
Worker worker = iterator.next();
|
||||||
if (worker.isReal()) {
|
if ( worker.isReal() ) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,10 +80,11 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
||||||
List<Worker> list = getWorkers();
|
List<Worker> list = getWorkers();
|
||||||
for (Iterator<Worker> iterator = list.iterator(); iterator.hasNext();) {
|
for (Iterator<Worker> iterator = list.iterator(); iterator.hasNext();) {
|
||||||
Worker worker = iterator.next();
|
Worker worker = iterator.next();
|
||||||
if (worker.isVirtual()) {
|
if ( worker.isVirtual() ) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,15 +95,13 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public List<Resource> getAllLimitingResources() {
|
public List<Resource> getAllLimitingResources() {
|
||||||
return getSession().createCriteria(Resource.class).add(
|
return getSession().createCriteria(Resource.class).add(Restrictions.eq("limitingResource", true)).list();
|
||||||
Restrictions.eq("limitingResource", true)).list();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public List<Resource> getAllNonLimitingResources() {
|
public List<Resource> getAllNonLimitingResources() {
|
||||||
return getSession().createCriteria(Resource.class).add(
|
return getSession().createCriteria(Resource.class).add(Restrictions.eq("limitingResource", false)).list();
|
||||||
Restrictions.eq("limitingResource", false)).list();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -115,82 +111,95 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Resource> getRealResources() {
|
public List<Resource> getRealResources() {
|
||||||
List<Resource> list = new ArrayList<Resource>();
|
List<Resource> list = new ArrayList<>();
|
||||||
list.addAll(getRealWorkers());
|
list.addAll(getRealWorkers());
|
||||||
list.addAll(getMachines());
|
list.addAll(getMachines());
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(Resource resource) {
|
public void save(Resource resource) {
|
||||||
if (resource instanceof Worker || resource instanceof Machine) {
|
if ( resource instanceof Worker || resource instanceof Machine ) {
|
||||||
if (resource.isLimitingResource() && resource.getLimitingResourceQueue() == null) {
|
if ( resource.isLimitingResource() && resource.getLimitingResourceQueue() == null ) {
|
||||||
resource.setLimitingResourceQueue(LimitingResourceQueue.create());
|
resource.setLimitingResourceQueue(LimitingResourceQueue.create());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.save(resource);
|
super.save(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public List<HoursWorkedPerResourceDTO> getWorkingHoursPerWorker(
|
public List<HoursWorkedPerResourceDTO> getWorkingHoursPerWorker(
|
||||||
List<Resource> resources, List<Label> labels,
|
List<Resource> resources,
|
||||||
LabelFilterType labelFilterType, List<Criterion> criterions,
|
List<Label> labels,
|
||||||
|
LabelFilterType labelFilterType,
|
||||||
|
List<Criterion> criterions,
|
||||||
Date startingDate,
|
Date startingDate,
|
||||||
Date endingDate) {
|
Date endingDate) {
|
||||||
|
|
||||||
String strQuery = "SELECT new org.libreplan.business.reports.dtos.HoursWorkedPerResourceDTO(resource, wrl) "
|
String strQuery =
|
||||||
+ "FROM Resource resource, WorkReportLine wrl "
|
"SELECT new org.libreplan.business.reports.dtos.HoursWorkedPerResourceDTO(resource, wrl) " +
|
||||||
+ "LEFT OUTER JOIN wrl.resource wrlresource "
|
"FROM Resource resource, WorkReportLine wrl " +
|
||||||
+ "WHERE wrlresource.id = resource.id ";
|
"LEFT OUTER JOIN wrl.resource wrlresource " +
|
||||||
|
"WHERE wrlresource.id = resource.id ";
|
||||||
|
|
||||||
// Set date range
|
// Set date range
|
||||||
if (startingDate != null && endingDate != null) {
|
if ( startingDate != null && endingDate != null ) {
|
||||||
strQuery += "AND wrl.date BETWEEN :startingDate AND :endingDate ";
|
strQuery += "AND wrl.date BETWEEN :startingDate AND :endingDate ";
|
||||||
}
|
}
|
||||||
if (startingDate != null && endingDate == null) {
|
|
||||||
|
if ( startingDate != null && endingDate == null ) {
|
||||||
strQuery += "AND wrl.date >= :startingDate ";
|
strQuery += "AND wrl.date >= :startingDate ";
|
||||||
}
|
}
|
||||||
if (startingDate == null && endingDate != null) {
|
|
||||||
|
if ( startingDate == null && endingDate != null ) {
|
||||||
strQuery += "AND wrl.date <= :endingDate ";
|
strQuery += "AND wrl.date <= :endingDate ";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set workers
|
// Set workers
|
||||||
if (resources != null && !resources.isEmpty()) {
|
if ( resources != null && !resources.isEmpty() ) {
|
||||||
strQuery += "AND resource IN (:resources) ";
|
strQuery += "AND resource IN (:resources) ";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set labels
|
// Set labels
|
||||||
if (labels != null && !labels.isEmpty()) {
|
if ( labels != null && !labels.isEmpty() ) {
|
||||||
switch (labelFilterType) {
|
switch (labelFilterType) {
|
||||||
case ORDER_ELEMENT:
|
case ORDER_ELEMENT:
|
||||||
strQuery += " AND ( EXISTS (FROM wrl.orderElement.labels as etq WHERE etq IN (:labels)) "
|
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)) ) ";
|
"OR EXISTS (FROM wrl.workReport.orderElement.labels as etqwr WHERE etqwr IN (:labels)) ) ";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WORK_REPORT:
|
case WORK_REPORT:
|
||||||
strQuery += " AND ( EXISTS (FROM wrl.labels as etq WHERE etq IN (:labels)) "
|
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.workReport.labels as etqwr WHERE etqwr IN (:labels)) ) ";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BOTH:
|
case BOTH:
|
||||||
strQuery += " AND ( EXISTS (FROM wrl.labels as etq WHERE etq IN (:labels)) "
|
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.workReport.labels as etqwr WHERE etqwr IN (:labels)) ) " +
|
||||||
+ "AND ( EXISTS (FROM wrl.orderElement.labels as etq WHERE etq 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)) ) ";
|
"OR EXISTS (FROM wrl.workReport.orderElement.labels as etqwr WHERE etqwr IN (:labels)) ) ";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ANY:
|
case ANY:
|
||||||
|
|
||||||
default:
|
default:
|
||||||
strQuery += " AND ( ( EXISTS (FROM wrl.labels as etq WHERE etq IN (:labels)) "
|
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.workReport.labels as etqwr WHERE etqwr IN (:labels)) ) " +
|
||||||
+ "OR ( EXISTS (FROM wrl.orderElement.labels as etq WHERE etq 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)) ) ) ";
|
"OR EXISTS (FROM wrl.workReport.orderElement.labels as etqwr WHERE etqwr " +
|
||||||
|
"IN (:labels)) ) ) ";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Criterions
|
// Set Criterions
|
||||||
if (criterions != null && !criterions.isEmpty()) {
|
if ( criterions != null && !criterions.isEmpty() ) {
|
||||||
strQuery += " AND EXISTS (FROM resource.criterionSatisfactions as satisfaction "
|
strQuery +=
|
||||||
+ " WHERE satisfaction.criterion IN (:criterions)) ";
|
" AND EXISTS (FROM resource.criterionSatisfactions as satisfaction " +
|
||||||
|
" WHERE satisfaction.criterion IN (:criterions)) ";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Order by
|
// Order by
|
||||||
|
|
@ -198,22 +207,24 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
||||||
|
|
||||||
// Set parameters
|
// Set parameters
|
||||||
Query query = getSession().createQuery(strQuery);
|
Query query = getSession().createQuery(strQuery);
|
||||||
if (startingDate != null) {
|
if ( startingDate != null ) {
|
||||||
query.setParameter("startingDate", startingDate);
|
query.setParameter("startingDate", startingDate);
|
||||||
}
|
}
|
||||||
if (endingDate != null) {
|
|
||||||
|
if ( endingDate != null ) {
|
||||||
query.setParameter("endingDate", endingDate);
|
query.setParameter("endingDate", endingDate);
|
||||||
}
|
}
|
||||||
if (resources != null && !resources.isEmpty()) {
|
|
||||||
|
if ( resources != null && !resources.isEmpty() ) {
|
||||||
query.setParameterList("resources", resources);
|
query.setParameterList("resources", resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (labels != null && !labels.isEmpty()) {
|
if ( labels != null && !labels.isEmpty() ) {
|
||||||
query.setParameterList("labels", labels);
|
query.setParameterList("labels", labels);
|
||||||
}
|
}
|
||||||
if (criterions != null && !criterions.isEmpty()) {
|
|
||||||
query.setParameterList("criterions",
|
if ( criterions != null && !criterions.isEmpty() ) {
|
||||||
Criterion.withAllDescendants(criterions));
|
query.setParameterList("criterions", Criterion.withAllDescendants(criterions));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get result
|
// Get result
|
||||||
|
|
@ -221,52 +232,55 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<HoursWorkedPerWorkerInAMonthDTO> getWorkingHoursPerWorker(
|
public List<HoursWorkedPerWorkerInAMonthDTO> getWorkingHoursPerWorker(Integer year, Integer month) {
|
||||||
Integer year, Integer month) {
|
|
||||||
|
|
||||||
String strQuery = "SELECT wrlresource.id, SUM(wrl.effort) "
|
String strQuery =
|
||||||
+ "FROM WorkReportLine wrl "
|
"SELECT wrlresource.id, SUM(wrl.effort) " +
|
||||||
+ "LEFT OUTER JOIN wrl.resource wrlresource ";
|
"FROM WorkReportLine wrl " +
|
||||||
|
"LEFT OUTER JOIN wrl.resource wrlresource ";
|
||||||
|
|
||||||
if (year != null) {
|
if ( year != null ) {
|
||||||
strQuery += "WHERE YEAR(wrl.date) = :year ";
|
strQuery += "WHERE YEAR(wrl.date) = :year ";
|
||||||
}
|
}
|
||||||
if (month != null) {
|
|
||||||
|
if ( month != null ) {
|
||||||
strQuery += "AND MONTH(wrl.date) = :month ";
|
strQuery += "AND MONTH(wrl.date) = :month ";
|
||||||
}
|
}
|
||||||
|
|
||||||
strQuery += "GROUP BY wrlresource.id, MONTH(wrl.date) ";
|
strQuery += "GROUP BY wrlresource.id, MONTH(wrl.date) ";
|
||||||
|
|
||||||
Query query = getSession().createQuery(strQuery);
|
Query query = getSession().createQuery(strQuery);
|
||||||
if (year != null) {
|
if ( year != null ) {
|
||||||
query.setParameter("year", year);
|
query.setParameter("year", year);
|
||||||
}
|
}
|
||||||
if (month != null) {
|
|
||||||
|
if ( month != null ) {
|
||||||
query.setParameter("month", month);
|
query.setParameter("month", month);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<HoursWorkedPerWorkerInAMonthDTO> result = toDTO(query.list());
|
List<HoursWorkedPerWorkerInAMonthDTO> result = toDTO(query.list());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Number getRowCount() {
|
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) {
|
private List<HoursWorkedPerWorkerInAMonthDTO> toDTO(List<Object> rows) {
|
||||||
List<HoursWorkedPerWorkerInAMonthDTO> result = new ArrayList<HoursWorkedPerWorkerInAMonthDTO>();
|
List<HoursWorkedPerWorkerInAMonthDTO> result = new ArrayList<>();
|
||||||
|
|
||||||
for (Object row: rows) {
|
for (Object row: rows) {
|
||||||
Object[] columns = (Object[]) row;
|
Object[] columns = (Object[]) row;
|
||||||
Resource resource = (Resource) findExistingEntity((Long) columns[0]);
|
Resource resource = findExistingEntity((Long) columns[0]);
|
||||||
EffortDuration effort = EffortDuration.seconds(((Long) columns[1])
|
EffortDuration effort = EffortDuration.seconds(((Long) columns[1]).intValue());
|
||||||
.intValue());
|
|
||||||
|
|
||||||
HoursWorkedPerWorkerInAMonthDTO dto = new HoursWorkedPerWorkerInAMonthDTO(
|
HoursWorkedPerWorkerInAMonthDTO dto = new HoursWorkedPerWorkerInAMonthDTO(resource, effort);
|
||||||
resource, effort);
|
|
||||||
result.add(dto);
|
result.add(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import org.joda.time.LocalDate;
|
||||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||||
*/
|
*/
|
||||||
public abstract class Interval {
|
public abstract class Interval {
|
||||||
|
|
||||||
protected final LocalDate start;
|
protected final LocalDate start;
|
||||||
|
|
||||||
protected final LocalDate end;
|
protected final LocalDate end;
|
||||||
|
|
@ -45,21 +46,24 @@ public abstract class Interval {
|
||||||
|
|
||||||
public static Interval range(LocalDate start, LocalDate end) {
|
public static Interval range(LocalDate start, LocalDate end) {
|
||||||
Validate.notNull(start, "start date must be not null");
|
Validate.notNull(start, "start date must be not null");
|
||||||
if (end == null) {
|
if ( end == null ) {
|
||||||
return from(start);
|
return from(start);
|
||||||
}
|
}
|
||||||
if (start.equals(end)) {
|
|
||||||
|
if ( start.equals(end) ) {
|
||||||
return point(start);
|
return point(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Range(start, end);
|
return new Range(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Interval(LocalDate start, LocalDate end) {
|
protected Interval(LocalDate start, LocalDate end) {
|
||||||
Validate.notNull(start, "start date must be not null");
|
Validate.notNull(start, "start date must be not null");
|
||||||
if (end != null) {
|
|
||||||
Validate.isTrue(start.compareTo(end) <= 0,
|
if ( end != null ) {
|
||||||
"start date must be equal or before than end date");
|
Validate.isTrue(start.compareTo(end) <= 0, "start date must be equal or before than end date");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
}
|
}
|
||||||
|
|
@ -68,11 +72,12 @@ public abstract class Interval {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj instanceof Interval) {
|
if ( obj instanceof Interval ) {
|
||||||
Interval interval = (Interval) obj;
|
Interval interval = (Interval) obj;
|
||||||
return dateEquals(start, interval.start)
|
|
||||||
&& dateEquals(end, interval.end);
|
return dateEquals(start, interval.start) && dateEquals(end, interval.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,8 +87,7 @@ public abstract class Interval {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean dateEquals(LocalDate date1, LocalDate date2) {
|
private boolean dateEquals(LocalDate date1, LocalDate date2) {
|
||||||
return date1 == date2
|
return date1 == date2 || (date1 != null && date2 != null && date1.equals(date2));
|
||||||
|| (date1 != null && date2 != null && date1.equals(date2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean includes(Interval included);
|
public abstract boolean includes(Interval included);
|
||||||
|
|
@ -108,6 +112,7 @@ class Range extends Interval {
|
||||||
|
|
||||||
Range(LocalDate start, LocalDate end) {
|
Range(LocalDate start, LocalDate end) {
|
||||||
super(start, end);
|
super(start, end);
|
||||||
|
|
||||||
Validate.notNull(start);
|
Validate.notNull(start);
|
||||||
Validate.notNull(end);
|
Validate.notNull(end);
|
||||||
}
|
}
|
||||||
|
|
@ -119,36 +124,39 @@ class Range extends Interval {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean includes(Interval included) {
|
public boolean includes(Interval included) {
|
||||||
if (included instanceof Point) {
|
if ( included instanceof Point ) {
|
||||||
Point point = (Point) included;
|
Point point = (Point) included;
|
||||||
|
|
||||||
return point.overlapsWith(this);
|
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
|
@Override
|
||||||
public boolean overlapsWith(Interval interval) {
|
public boolean overlapsWith(Interval interval) {
|
||||||
if (interval instanceof Point) {
|
if ( interval instanceof Point ) {
|
||||||
Point point = (Point) interval;
|
Point point = (Point) interval;
|
||||||
|
|
||||||
return point.overlapsWith(this);
|
return point.overlapsWith(this);
|
||||||
}
|
}
|
||||||
if (interval instanceof OpenEndedInterval) {
|
|
||||||
|
if ( interval instanceof OpenEndedInterval ) {
|
||||||
return interval.overlapsWith(this);
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new StringBuilder("[").append(start).append(", ").append(end)
|
return new StringBuilder("[").append(start).append(", ").append(end).append(")").toString();
|
||||||
.append(")").toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenEndedInterval extends Interval {
|
class OpenEndedInterval extends Interval {
|
||||||
|
|
||||||
OpenEndedInterval(LocalDate start) {
|
OpenEndedInterval(LocalDate start) {
|
||||||
super(start, null);
|
super(start, null);
|
||||||
}
|
}
|
||||||
|
|
@ -165,8 +173,7 @@ class OpenEndedInterval extends Interval {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean overlapsWith(Interval interval) {
|
public boolean overlapsWith(Interval interval) {
|
||||||
return start.isBefore(interval.start) || interval.end == null
|
return start.isBefore(interval.start) || interval.end == null || start.isBefore(interval.end);
|
||||||
|| start.isBefore(interval.end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -198,8 +205,7 @@ class Point extends Interval {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new StringBuilder().append("[").append(start).append(")")
|
return new StringBuilder().append("[").append(start).append(")").toString();
|
||||||
.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -38,19 +38,22 @@ public class Task extends BaseEntity {
|
||||||
|
|
||||||
public static final String RESOURCE = "resource";
|
public static final String RESOURCE = "resource";
|
||||||
|
|
||||||
public static final String ORDER_ELEMENT = "orderElement";
|
|
||||||
|
|
||||||
public static Task create() {
|
public static Task create() {
|
||||||
Task workReportLine = new Task();
|
Task workReportLine = new Task();
|
||||||
workReportLine.setNewObject(true);
|
workReportLine.setNewObject(true);
|
||||||
|
|
||||||
return workReportLine;
|
return workReportLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task create(Integer numHours, Resource resource,
|
public static Task create(
|
||||||
OrderElement orderElement, Set<Criterion> criterions) {
|
Integer numHours,
|
||||||
Task workReportLine = new Task(numHours, resource,
|
Resource resource,
|
||||||
orderElement, criterions);
|
OrderElement orderElement,
|
||||||
|
Set<Criterion> criterions) {
|
||||||
|
|
||||||
|
Task workReportLine = new Task(numHours, resource, orderElement, criterions);
|
||||||
workReportLine.setNewObject(true);
|
workReportLine.setNewObject(true);
|
||||||
|
|
||||||
return workReportLine;
|
return workReportLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,7 +67,7 @@ public class Task extends BaseEntity {
|
||||||
|
|
||||||
private WorkReport workReport;
|
private WorkReport workReport;
|
||||||
|
|
||||||
private Set<Criterion> criterions = new HashSet<Criterion>();
|
private Set<Criterion> criterions = new HashSet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for hibernate. Do not use!
|
* Constructor for hibernate. Do not use!
|
||||||
|
|
@ -73,8 +76,7 @@ public class Task extends BaseEntity {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task(Integer numHours, Resource resource,
|
private Task(Integer numHours, Resource resource, OrderElement orderElement, Set<Criterion> criterions) {
|
||||||
OrderElement orderElement, Set<Criterion> criterions) {
|
|
||||||
this.numHours = numHours;
|
this.numHours = numHours;
|
||||||
this.resource = resource;
|
this.resource = resource;
|
||||||
this.orderElement = orderElement;
|
this.orderElement = orderElement;
|
||||||
|
|
@ -106,7 +108,7 @@ public class Task extends BaseEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Criterion> getCriterions() {
|
public Set<Criterion> getCriterions() {
|
||||||
return new HashSet<Criterion>(criterions);
|
return new HashSet<>(criterions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCriterions(Set<Criterion> criterions) {
|
public void setCriterions(Set<Criterion> criterions) {
|
||||||
|
|
|
||||||
|
|
@ -70,43 +70,35 @@ public class DashboardModel implements IDashboardModel {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IOrderResourceLoadCalculator resourceLoadCalculator;
|
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 Order currentOrder;
|
||||||
|
|
||||||
private List<TaskElement> criticalPath;
|
private List<TaskElement> criticalPath;
|
||||||
|
|
||||||
private Integer taskCount = null;
|
private Integer taskCount = null;
|
||||||
|
|
||||||
private final Map<TaskStatusEnum, BigDecimal> taskStatusStats;
|
private final Map<TaskStatusEnum, BigDecimal> taskStatusStats;
|
||||||
|
|
||||||
private final Map<TaskDeadlineViolationStatusEnum, BigDecimal> taskDeadlineViolationStatusStats;
|
private final Map<TaskDeadlineViolationStatusEnum, BigDecimal> taskDeadlineViolationStatusStats;
|
||||||
|
|
||||||
private BigDecimal marginWithDeadLine;
|
private BigDecimal marginWithDeadLine;
|
||||||
|
|
||||||
private Integer absoluteMarginWithDeadLine;
|
private Integer absoluteMarginWithDeadLine;
|
||||||
|
|
||||||
public DashboardModel() {
|
public DashboardModel() {
|
||||||
taskStatusStats = new EnumMap<TaskStatusEnum, BigDecimal>(
|
taskStatusStats = new EnumMap<>(TaskStatusEnum.class);
|
||||||
TaskStatusEnum.class);
|
taskDeadlineViolationStatusStats = new EnumMap<>(TaskDeadlineViolationStatusEnum.class);
|
||||||
taskDeadlineViolationStatusStats = new EnumMap<TaskDeadlineViolationStatusEnum, BigDecimal>(
|
|
||||||
TaskDeadlineViolationStatusEnum.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCurrentOrder(PlanningState planningState, List<TaskElement> criticalPath) {
|
public void setCurrentOrder(PlanningState planningState, List<TaskElement> criticalPath) {
|
||||||
final Order order = planningState.getOrder();
|
final Order order = planningState.getOrder();
|
||||||
|
|
||||||
resourceLoadCalculator.setOrder(order,
|
resourceLoadCalculator.setOrder(order, planningState.getAssignmentsCalculator());
|
||||||
planningState.getAssignmentsCalculator());
|
|
||||||
this.currentOrder = order;
|
this.currentOrder = order;
|
||||||
this.criticalPath = criticalPath;
|
this.criticalPath = criticalPath;
|
||||||
this.taskCount = null;
|
this.taskCount = null;
|
||||||
if (tasksAvailable()) {
|
|
||||||
|
if ( tasksAvailable() ) {
|
||||||
this.calculateGlobalProgress();
|
this.calculateGlobalProgress();
|
||||||
this.calculateTaskStatusStatistics();
|
this.calculateTaskStatusStatistics();
|
||||||
this.calculateTaskViolationStatusStatistics();
|
this.calculateTaskViolationStatusStatistics();
|
||||||
|
|
@ -139,26 +131,23 @@ public class DashboardModel implements IDashboardModel {
|
||||||
/* Progress KPI: "Deadline violation" */
|
/* Progress KPI: "Deadline violation" */
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getPercentageOfOnScheduleTasks() {
|
public BigDecimal getPercentageOfOnScheduleTasks() {
|
||||||
return taskDeadlineViolationStatusStats
|
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.ON_SCHEDULE);
|
||||||
.get(TaskDeadlineViolationStatusEnum.ON_SCHEDULE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getPercentageOfTasksWithViolatedDeadline() {
|
public BigDecimal getPercentageOfTasksWithViolatedDeadline() {
|
||||||
return taskDeadlineViolationStatusStats
|
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.DEADLINE_VIOLATED);
|
||||||
.get(TaskDeadlineViolationStatusEnum.DEADLINE_VIOLATED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getPercentageOfTasksWithNoDeadline() {
|
public BigDecimal getPercentageOfTasksWithNoDeadline() {
|
||||||
return taskDeadlineViolationStatusStats
|
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.NO_DEADLINE);
|
||||||
.get(TaskDeadlineViolationStatusEnum.NO_DEADLINE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Progress KPI: "Global Progress of the Project" */
|
/* Progress KPI: "Global Progress of the Project" */
|
||||||
private void calculateGlobalProgress() {
|
private void calculateGlobalProgress() {
|
||||||
TaskGroup rootTask = getRootTask();
|
TaskGroup rootTask = getRootTask();
|
||||||
if (rootTask == null) {
|
if ( rootTask == null ) {
|
||||||
throw new RuntimeException("Root task is null");
|
throw new RuntimeException("Root task is null");
|
||||||
}
|
}
|
||||||
rootTask.updateCriticalPathProgress(criticalPath);
|
rootTask.updateCriticalPathProgress(criticalPath);
|
||||||
|
|
@ -170,8 +159,7 @@ public class DashboardModel implements IDashboardModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal asPercentage(BigDecimal value) {
|
private BigDecimal asPercentage(BigDecimal value) {
|
||||||
return value != null ? value.multiply(BigDecimal.valueOf(100))
|
return value != null ? value.multiply(BigDecimal.valueOf(100)) : BigDecimal.ZERO;
|
||||||
: BigDecimal.ZERO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -181,8 +169,7 @@ public class DashboardModel implements IDashboardModel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getExpectedAdvancePercentageByHours() {
|
public BigDecimal getExpectedAdvancePercentageByHours() {
|
||||||
return asPercentage(getRootTask()
|
return asPercentage(getRootTask().getTheoreticalProgressByNumHoursForAllTasksUntilNow());
|
||||||
.getTheoreticalProgressByNumHoursForAllTasksUntilNow());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -192,8 +179,7 @@ public class DashboardModel implements IDashboardModel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getExpectedCriticalPathProgressByNumHours() {
|
public BigDecimal getExpectedCriticalPathProgressByNumHours() {
|
||||||
return asPercentage(getRootTask()
|
return asPercentage(getRootTask().getTheoreticalProgressByNumHoursForCriticalPathUntilNow());
|
||||||
.getTheoreticalProgressByNumHoursForCriticalPathUntilNow());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -203,8 +189,7 @@ public class DashboardModel implements IDashboardModel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getExpectedCriticalPathProgressByDuration() {
|
public BigDecimal getExpectedCriticalPathProgressByDuration() {
|
||||||
return asPercentage(getRootTask()
|
return asPercentage(getRootTask().getTheoreticalProgressByDurationForCriticalPathUntilNow());
|
||||||
.getTheoreticalProgressByDurationForCriticalPathUntilNow());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Time KPI: Margin with deadline */
|
/* Time KPI: Margin with deadline */
|
||||||
|
|
@ -214,29 +199,26 @@ public class DashboardModel implements IDashboardModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculateMarginWithDeadLine() {
|
private void calculateMarginWithDeadLine() {
|
||||||
if (this.getRootTask() == null) {
|
if ( this.getRootTask() == null ) {
|
||||||
throw new RuntimeException("Root task is null");
|
throw new RuntimeException("Root task is null");
|
||||||
}
|
}
|
||||||
if (this.currentOrder.getDeadline() == null) {
|
|
||||||
|
if ( this.currentOrder.getDeadline() == null ) {
|
||||||
this.marginWithDeadLine = null;
|
this.marginWithDeadLine = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskGroup rootTask = getRootTask();
|
TaskGroup rootTask = getRootTask();
|
||||||
LocalDate endDate = TaskElement.maxDate(rootTask.getChildren())
|
LocalDate endDate = TaskElement.maxDate(rootTask.getChildren()).asExclusiveEnd();
|
||||||
.asExclusiveEnd();
|
Days orderDuration = Days.daysBetween(TaskElement.minDate(rootTask.getChildren()).getDate(), endDate);
|
||||||
Days orderDuration = Days.daysBetween(
|
|
||||||
TaskElement.minDate(rootTask.getChildren()).getDate(), endDate);
|
|
||||||
|
|
||||||
LocalDate deadLineAsLocalDate = LocalDate.fromDateFields(currentOrder
|
LocalDate deadLineAsLocalDate = LocalDate.fromDateFields(currentOrder.getDeadline());
|
||||||
.getDeadline());
|
Days deadlineOffset = Days.daysBetween(endDate, deadLineAsLocalDate.plusDays(1));
|
||||||
Days deadlineOffset = Days.daysBetween(endDate,
|
|
||||||
deadLineAsLocalDate.plusDays(1));
|
|
||||||
|
|
||||||
BigDecimal outcome = new BigDecimal(deadlineOffset.getDays(),
|
BigDecimal outcome = new BigDecimal(deadlineOffset.getDays(), MathContext.DECIMAL32);
|
||||||
MathContext.DECIMAL32);
|
|
||||||
this.marginWithDeadLine = outcome.divide(
|
this.marginWithDeadLine =
|
||||||
new BigDecimal(orderDuration.getDays()), 8,
|
outcome.divide(new BigDecimal(orderDuration.getDays()), 8, BigDecimal.ROUND_HALF_EVEN);
|
||||||
BigDecimal.ROUND_HALF_EVEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -248,13 +230,15 @@ public class DashboardModel implements IDashboardModel {
|
||||||
TaskElement rootTask = getRootTask();
|
TaskElement rootTask = getRootTask();
|
||||||
Date deadline = currentOrder.getDeadline();
|
Date deadline = currentOrder.getDeadline();
|
||||||
|
|
||||||
if (rootTask == null) {
|
if ( rootTask == null ) {
|
||||||
throw new RuntimeException("Root task is null");
|
throw new RuntimeException("Root task is null");
|
||||||
}
|
}
|
||||||
if (deadline == null) {
|
|
||||||
|
if ( deadline == null ) {
|
||||||
this.absoluteMarginWithDeadLine = null;
|
this.absoluteMarginWithDeadLine = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
absoluteMarginWithDeadLine = daysBetween(
|
absoluteMarginWithDeadLine = daysBetween(
|
||||||
TaskElement.maxDate(rootTask.getChildren()).asExclusiveEnd(),
|
TaskElement.maxDate(rootTask.getChildren()).asExclusiveEnd(),
|
||||||
LocalDate.fromDateFields(deadline).plusDays(1));
|
LocalDate.fromDateFields(deadline).plusDays(1));
|
||||||
|
|
@ -277,16 +261,19 @@ public class DashboardModel implements IDashboardModel {
|
||||||
@Override
|
@Override
|
||||||
public Map<Interval, Integer> calculateTaskCompletion() {
|
public Map<Interval, Integer> calculateTaskCompletion() {
|
||||||
List<Double> deviations = getTaskLagDeviations();
|
List<Double> deviations = getTaskLagDeviations();
|
||||||
|
|
||||||
return calculateHistogramIntervals(deviations, 6, 1);
|
return calculateHistogramIntervals(deviations, 6, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Double> getTaskLagDeviations() {
|
private List<Double> getTaskLagDeviations() {
|
||||||
if (this.getRootTask() == null) {
|
if ( this.getRootTask() == null ) {
|
||||||
throw new RuntimeException("Root task is null");
|
throw new RuntimeException("Root task is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
CalculateFinishedTasksLagInCompletionVisitor visitor = new CalculateFinishedTasksLagInCompletionVisitor();
|
CalculateFinishedTasksLagInCompletionVisitor visitor = new CalculateFinishedTasksLagInCompletionVisitor();
|
||||||
TaskElement rootTask = getRootTask();
|
TaskElement rootTask = getRootTask();
|
||||||
rootTask.acceptVisitor(visitor);
|
rootTask.acceptVisitor(visitor);
|
||||||
|
|
||||||
return visitor.getDeviations();
|
return visitor.getDeviations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -318,18 +305,19 @@ public class DashboardModel implements IDashboardModel {
|
||||||
@Override
|
@Override
|
||||||
public Map<Interval, Integer> calculateEstimationAccuracy() {
|
public Map<Interval, Integer> calculateEstimationAccuracy() {
|
||||||
List<Double> deviations = getEstimationAccuracyDeviations();
|
List<Double> deviations = getEstimationAccuracyDeviations();
|
||||||
|
|
||||||
return calculateHistogramIntervals(deviations, 6, 10);
|
return calculateHistogramIntervals(deviations, 6, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Interval, Integer> calculateHistogramIntervals(
|
private Map<Interval, Integer> calculateHistogramIntervals(List<Double> values, int intervalsNumber,
|
||||||
List<Double> values, int intervalsNumber, int intervalMinimumSize) {
|
int intervalMinimumSize) {
|
||||||
Map<Interval, Integer> result = new LinkedHashMap<Interval, Integer>();
|
Map<Interval, Integer> result = new LinkedHashMap<>();
|
||||||
|
|
||||||
int totalMinimumSize = intervalsNumber * intervalMinimumSize;
|
int totalMinimumSize = intervalsNumber * intervalMinimumSize;
|
||||||
int halfSize = totalMinimumSize / 2;
|
int halfSize = totalMinimumSize / 2;
|
||||||
|
|
||||||
double maxDouble, minDouble;
|
double maxDouble, minDouble;
|
||||||
if (values.isEmpty()) {
|
if ( values.isEmpty() ) {
|
||||||
minDouble = -halfSize;
|
minDouble = -halfSize;
|
||||||
maxDouble = halfSize;
|
maxDouble = halfSize;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -339,39 +327,34 @@ public class DashboardModel implements IDashboardModel {
|
||||||
|
|
||||||
// If min and max are between -halfSize and +halfSize, set -halfSize as
|
// If min and max are between -halfSize and +halfSize, set -halfSize as
|
||||||
// min and +halfSize as max
|
// min and +halfSize as max
|
||||||
if (minDouble >= -halfSize && maxDouble <= halfSize) {
|
if ( minDouble >= -halfSize && maxDouble <= halfSize ) {
|
||||||
minDouble = -halfSize;
|
minDouble = -halfSize;
|
||||||
maxDouble = halfSize;
|
maxDouble = halfSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the difference between min and max is less than totalMinimumSize,
|
// If the difference between min and max is less than totalMinimumSize,
|
||||||
// decrease min
|
// decrease min
|
||||||
// and increase max till get that difference
|
|
||||||
boolean changeMin = true;
|
|
||||||
while (maxDouble - minDouble < totalMinimumSize) {
|
while (maxDouble - minDouble < totalMinimumSize) {
|
||||||
if (changeMin) {
|
|
||||||
minDouble -= intervalMinimumSize;
|
minDouble -= intervalMinimumSize;
|
||||||
} else {
|
|
||||||
maxDouble += intervalMinimumSize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round min and max properly depending on decimal part or not
|
// Round min and max properly depending on decimal part or not
|
||||||
int min;
|
int min;
|
||||||
double minDecimalPart = minDouble - (int) minDouble;
|
double minDecimalPart = minDouble - (int) minDouble;
|
||||||
if (minDouble >= 0) {
|
if ( minDouble >= 0 ) {
|
||||||
min = (int) (minDouble - minDecimalPart);
|
min = (int) (minDouble - minDecimalPart);
|
||||||
} else {
|
} else {
|
||||||
min = (int) (minDouble - minDecimalPart);
|
min = (int) (minDouble - minDecimalPart);
|
||||||
if (minDecimalPart != 0) {
|
if ( minDecimalPart != 0 ) {
|
||||||
min--;
|
min--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int max;
|
int max;
|
||||||
double maxDecimalPart = maxDouble - (int) maxDouble;
|
double maxDecimalPart = maxDouble - (int) maxDouble;
|
||||||
if (maxDouble >= 0) {
|
if ( maxDouble >= 0 ) {
|
||||||
max = (int) (maxDouble - maxDecimalPart);
|
max = (int) (maxDouble - maxDecimalPart);
|
||||||
if (maxDecimalPart != 0) {
|
if ( maxDecimalPart != 0 ) {
|
||||||
max++;
|
max++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -387,10 +370,11 @@ public class DashboardModel implements IDashboardModel {
|
||||||
for (int i = 0; i < intervalsNumber; i++) {
|
for (int i = 0; i < intervalsNumber; i++) {
|
||||||
int to = from + (int) delta;
|
int to = from + (int) delta;
|
||||||
// Fix to depending on decimal part if it's not the last interval
|
// 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--;
|
to--;
|
||||||
}
|
}
|
||||||
result.put(new Interval(from, to), Integer.valueOf(0));
|
|
||||||
|
result.put(new Interval(from, to), 0);
|
||||||
|
|
||||||
from = to + 1;
|
from = to + 1;
|
||||||
}
|
}
|
||||||
|
|
@ -398,23 +382,25 @@ public class DashboardModel implements IDashboardModel {
|
||||||
// Construct map with number of tasks for each interval
|
// Construct map with number of tasks for each interval
|
||||||
final Set<Interval> intervals = result.keySet();
|
final Set<Interval> intervals = result.keySet();
|
||||||
for (Double each : values) {
|
for (Double each : values) {
|
||||||
Interval interval = Interval.containingValue(
|
Interval interval = Interval.containingValue(intervals, each);
|
||||||
intervals, each);
|
if ( interval != null ) {
|
||||||
if (interval != null) {
|
|
||||||
Integer value = result.get(interval);
|
Integer value = result.get(interval);
|
||||||
result.put(interval, value + 1);
|
result.put(interval, value + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Double> getEstimationAccuracyDeviations() {
|
private List<Double> getEstimationAccuracyDeviations() {
|
||||||
if (this.getRootTask() == null) {
|
if ( this.getRootTask() == null ) {
|
||||||
throw new RuntimeException("Root task is null");
|
throw new RuntimeException("Root task is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
CalculateFinishedTasksEstimationDeviationVisitor visitor = new CalculateFinishedTasksEstimationDeviationVisitor();
|
CalculateFinishedTasksEstimationDeviationVisitor visitor = new CalculateFinishedTasksEstimationDeviationVisitor();
|
||||||
TaskElement rootTask = getRootTask();
|
TaskElement rootTask = getRootTask();
|
||||||
rootTask.acceptVisitor(visitor);
|
rootTask.acceptVisitor(visitor);
|
||||||
|
|
||||||
return visitor.getDeviations();
|
return visitor.getDeviations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -427,13 +413,13 @@ public class DashboardModel implements IDashboardModel {
|
||||||
this.max = max;
|
this.max = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Interval containingValue(
|
public static Interval containingValue(Collection<Interval> intervals, double value) {
|
||||||
Collection<Interval> intervals, double value) {
|
|
||||||
for (Interval each : intervals) {
|
for (Interval each : intervals) {
|
||||||
if (each.includes(value)) {
|
if ( each.includes(value) ) {
|
||||||
return each;
|
return each;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -452,20 +438,25 @@ public class DashboardModel implements IDashboardModel {
|
||||||
public Map<TaskStatusEnum, Integer> calculateTaskStatus() {
|
public Map<TaskStatusEnum, Integer> calculateTaskStatus() {
|
||||||
AccumulateTasksStatusVisitor visitor = new AccumulateTasksStatusVisitor();
|
AccumulateTasksStatusVisitor visitor = new AccumulateTasksStatusVisitor();
|
||||||
TaskElement rootTask = getRootTask();
|
TaskElement rootTask = getRootTask();
|
||||||
if (this.getRootTask() == null) {
|
|
||||||
|
if ( this.getRootTask() == null ) {
|
||||||
throw new RuntimeException("Root task is null");
|
throw new RuntimeException("Root task is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
resetTasksStatusInGraph();
|
resetTasksStatusInGraph();
|
||||||
rootTask.acceptVisitor(visitor);
|
rootTask.acceptVisitor(visitor);
|
||||||
|
|
||||||
return visitor.getTaskStatusData();
|
return visitor.getTaskStatusData();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculateTaskStatusStatistics() {
|
private void calculateTaskStatusStatistics() {
|
||||||
AccumulateTasksStatusVisitor visitor = new AccumulateTasksStatusVisitor();
|
AccumulateTasksStatusVisitor visitor = new AccumulateTasksStatusVisitor();
|
||||||
TaskElement rootTask = getRootTask();
|
TaskElement rootTask = getRootTask();
|
||||||
if (this.getRootTask() == null) {
|
|
||||||
|
if ( this.getRootTask() == null ) {
|
||||||
throw new RuntimeException("Root task is null");
|
throw new RuntimeException("Root task is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
resetTasksStatusInGraph();
|
resetTasksStatusInGraph();
|
||||||
rootTask.acceptVisitor(visitor);
|
rootTask.acceptVisitor(visitor);
|
||||||
Map<TaskStatusEnum, Integer> count = visitor.getTaskStatusData();
|
Map<TaskStatusEnum, Integer> count = visitor.getTaskStatusData();
|
||||||
|
|
@ -475,21 +466,21 @@ public class DashboardModel implements IDashboardModel {
|
||||||
private void calculateTaskViolationStatusStatistics() {
|
private void calculateTaskViolationStatusStatistics() {
|
||||||
AccumulateTasksDeadlineStatusVisitor visitor = new AccumulateTasksDeadlineStatusVisitor();
|
AccumulateTasksDeadlineStatusVisitor visitor = new AccumulateTasksDeadlineStatusVisitor();
|
||||||
TaskElement rootTask = getRootTask();
|
TaskElement rootTask = getRootTask();
|
||||||
if (this.getRootTask() == null) {
|
|
||||||
|
if ( this.getRootTask() == null ) {
|
||||||
throw new RuntimeException("Root task is null");
|
throw new RuntimeException("Root task is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
rootTask.acceptVisitor(visitor);
|
rootTask.acceptVisitor(visitor);
|
||||||
Map<TaskDeadlineViolationStatusEnum, Integer> count = visitor
|
Map<TaskDeadlineViolationStatusEnum, Integer> count = visitor.getTaskDeadlineViolationStatusData();
|
||||||
.getTaskDeadlineViolationStatusData();
|
|
||||||
mapAbsoluteValuesToPercentages(count, taskDeadlineViolationStatusStats);
|
mapAbsoluteValuesToPercentages(count, taskDeadlineViolationStatusStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void mapAbsoluteValuesToPercentages(Map<T, Integer> source,
|
private <T> void mapAbsoluteValuesToPercentages(Map<T, Integer> source, Map<T, BigDecimal> dest) {
|
||||||
Map<T, BigDecimal> dest) {
|
|
||||||
int totalTasks = countTasksInAResultMap(source);
|
int totalTasks = countTasksInAResultMap(source);
|
||||||
for (Map.Entry<T, Integer> entry : source.entrySet()) {
|
for (Map.Entry<T, Integer> entry : source.entrySet()) {
|
||||||
BigDecimal percentage;
|
BigDecimal percentage;
|
||||||
if (totalTasks == 0) {
|
if ( totalTasks == 0 ) {
|
||||||
percentage = BigDecimal.ZERO;
|
percentage = BigDecimal.ZERO;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -511,18 +502,18 @@ public class DashboardModel implements IDashboardModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int countTasksInAResultMap(Map<? extends Object, Integer> map) {
|
private int countTasksInAResultMap(Map<? extends Object, Integer> map) {
|
||||||
/*
|
|
||||||
* It's only needed to count the number of tasks once each time setOrder
|
// It's only needed to count the number of tasks once each time setOrder is called.
|
||||||
* is called.
|
if ( this.taskCount != null ) {
|
||||||
*/
|
|
||||||
if (this.taskCount != null) {
|
|
||||||
return this.taskCount.intValue();
|
return this.taskCount.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
for (Object count : map.values()) {
|
for (Object count : map.values()) {
|
||||||
sum += (Integer) count;
|
sum += (Integer) count;
|
||||||
}
|
}
|
||||||
this.taskCount = new Integer(sum);
|
this.taskCount = sum;
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -534,36 +525,32 @@ public class DashboardModel implements IDashboardModel {
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getOvertimeRatio() {
|
public BigDecimal getOvertimeRatio() {
|
||||||
EffortDuration totalLoad = sumAll(resourceLoadCalculator.getAllLoad());
|
EffortDuration totalLoad = sumAll(resourceLoadCalculator.getAllLoad());
|
||||||
EffortDuration overload = sumAll(resourceLoadCalculator
|
EffortDuration overload = sumAll(resourceLoadCalculator.getAllOverload());
|
||||||
.getAllOverload());
|
|
||||||
return overload.dividedByAndResultAsBigDecimal(totalLoad).setScale(2,
|
return overload.dividedByAndResultAsBigDecimal(totalLoad).setScale(2, RoundingMode.HALF_UP);
|
||||||
RoundingMode.HALF_UP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private EffortDuration sumAll(
|
private EffortDuration sumAll(ContiguousDaysLine<EffortDuration> contiguousDays) {
|
||||||
ContiguousDaysLine<EffortDuration> contiguousDays) {
|
|
||||||
EffortDuration result = EffortDuration.zero();
|
EffortDuration result = EffortDuration.zero();
|
||||||
Iterator<OnDay<EffortDuration>> iterator = contiguousDays
|
Iterator<OnDay<EffortDuration>> iterator = contiguousDays.iterator();
|
||||||
.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
OnDay<EffortDuration> value = iterator.next();
|
OnDay<EffortDuration> value = iterator.next();
|
||||||
EffortDuration effort = value.getValue();
|
EffortDuration effort = value.getValue();
|
||||||
result = EffortDuration.sum(result, effort);
|
result = EffortDuration.sum(result, effort);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getAvailabilityRatio() {
|
public BigDecimal getAvailabilityRatio() {
|
||||||
EffortDuration totalLoad = sumAll(resourceLoadCalculator.getAllLoad());
|
EffortDuration totalLoad = sumAll(resourceLoadCalculator.getAllLoad());
|
||||||
EffortDuration overload = sumAll(resourceLoadCalculator
|
EffortDuration overload = sumAll(resourceLoadCalculator.getAllOverload());
|
||||||
.getAllOverload());
|
|
||||||
EffortDuration load = totalLoad.minus(overload);
|
EffortDuration load = totalLoad.minus(overload);
|
||||||
|
EffortDuration capacity = sumAll(resourceLoadCalculator.getMaxCapacityOnResources());
|
||||||
|
|
||||||
EffortDuration capacity = sumAll(resourceLoadCalculator
|
return BigDecimal.ONE.setScale(2, RoundingMode.HALF_UP).subtract(load.dividedByAndResultAsBigDecimal(capacity));
|
||||||
.getMaxCapacityOnResources());
|
|
||||||
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>
|
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class PersonalTimesheetController extends GenericForwardComposer
|
public class PersonalTimesheetController extends GenericForwardComposer implements IPersonalTimesheetController {
|
||||||
implements IPersonalTimesheetController {
|
|
||||||
|
|
||||||
private final static String EFFORT_DURATION_TEXTBOX_WIDTH = "30px";
|
private final static String EFFORT_DURATION_TEXTBOX_WIDTH = "30px";
|
||||||
private final static String TOTAL_DURATION_TEXTBOX_WIDTH = "50px";
|
private final static String TOTAL_DURATION_TEXTBOX_WIDTH = "50px";
|
||||||
|
|
@ -143,28 +142,31 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
|
|
||||||
switch (personalTimesheetRow.getType()) {
|
switch (personalTimesheetRow.getType()) {
|
||||||
case ORDER_ELEMENT:
|
case ORDER_ELEMENT:
|
||||||
renderOrderElementRow(row,
|
renderOrderElementRow(row, personalTimesheetRow.getOrderElemement());
|
||||||
personalTimesheetRow.getOrderElemement());
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OTHER:
|
case OTHER:
|
||||||
renderOtherRow(row);
|
renderOtherRow(row);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAPACITY:
|
case CAPACITY:
|
||||||
renderCapacityRow(row);
|
renderCapacityRow(row);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOTAL:
|
case TOTAL:
|
||||||
renderTotalRow(row);
|
renderTotalRow(row);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXTRA:
|
case EXTRA:
|
||||||
renderExtraRow(row);
|
renderExtraRow(row);
|
||||||
|
|
||||||
// This is the last row so we can load the info in the summary
|
// This is the last row so we can load the info in the summary
|
||||||
updateSummary();
|
updateSummary();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Unknown PersonalTimesheetRow type: "
|
"Unknown PersonalTimesheetRow type: " + personalTimesheetRow.getType());
|
||||||
+ personalTimesheetRow.getType());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,51 +176,52 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderOrderElementRow(Row row, OrderElement orderElement) {
|
private void renderOrderElementRow(Row row, OrderElement orderElement) {
|
||||||
Util.appendLabel(row, personalTimesheetModel.getOrder(orderElement)
|
Util.appendLabel(row, personalTimesheetModel.getOrder(orderElement).getName());
|
||||||
.getName());
|
|
||||||
Util.appendLabel(row, orderElement.getName());
|
Util.appendLabel(row, orderElement.getName());
|
||||||
|
|
||||||
appendInputsForDays(row, orderElement);
|
appendInputsForDays(row, orderElement);
|
||||||
|
|
||||||
if (personalTimesheetModel.hasOtherReports()) {
|
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||||
appendOtherColumn(row, orderElement);
|
appendOtherColumn(row, orderElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
appendTotalColumn(row, orderElement);
|
appendTotalColumn(row, orderElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendInputsForDays(Row row,
|
private void appendInputsForDays(Row row, final OrderElement orderElement) {
|
||||||
final OrderElement orderElement) {
|
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
|
||||||
.plusDays(1)) {
|
|
||||||
final LocalDate textboxDate = day;
|
final LocalDate textboxDate = day;
|
||||||
|
|
||||||
final Textbox textbox = new Textbox();
|
final Textbox textbox = new Textbox();
|
||||||
textbox.setHflex("true");
|
textbox.setHflex("true");
|
||||||
|
|
||||||
Util.bind(textbox, new Util.Getter<String>() {
|
Util.bind(
|
||||||
|
textbox,
|
||||||
|
new Util.Getter<String>() {
|
||||||
@Override
|
@Override
|
||||||
public String get() {
|
public String get() {
|
||||||
EffortDuration effortDuration = personalTimesheetModel
|
|
||||||
.getEffortDuration(orderElement, textboxDate);
|
EffortDuration effortDuration =
|
||||||
|
personalTimesheetModel.getEffortDuration(orderElement, textboxDate);
|
||||||
|
|
||||||
return effortDurationToString(effortDuration);
|
return effortDurationToString(effortDuration);
|
||||||
}
|
}
|
||||||
}, new Util.Setter<String>() {
|
},
|
||||||
|
new Util.Setter<String>() {
|
||||||
@Override
|
@Override
|
||||||
public void set(String value) {
|
public void set(String value) {
|
||||||
EffortDuration effortDuration = effortDurationFromString(value);
|
EffortDuration effortDuration = effortDurationFromString(value);
|
||||||
if (effortDuration == null) {
|
|
||||||
throw new WrongValueException(textbox,
|
if ( effortDuration == null ) {
|
||||||
_("Invalid Effort Duration"));
|
throw new WrongValueException(textbox, _("Invalid Effort Duration"));
|
||||||
}
|
}
|
||||||
personalTimesheetModel.setEffortDuration(orderElement,
|
|
||||||
textboxDate, effortDuration);
|
personalTimesheetModel.setEffortDuration(orderElement, textboxDate, effortDuration);
|
||||||
markAsModified(textbox);
|
markAsModified(textbox);
|
||||||
updateTotals(orderElement, textboxDate);
|
updateTotals(orderElement, textboxDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTotals(OrderElement orderElement,
|
private void updateTotals(OrderElement orderElement, LocalDate date) {
|
||||||
LocalDate date) {
|
|
||||||
updateTotalColumn(orderElement);
|
updateTotalColumn(orderElement);
|
||||||
updateTotalRow(date);
|
updateTotalRow(date);
|
||||||
updateExtraRow(date);
|
updateExtraRow(date);
|
||||||
|
|
@ -226,29 +229,25 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
updateTotalExtraColumn();
|
updateTotalExtraColumn();
|
||||||
updateSummary();
|
updateSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
EventListener openPersonalTimesheetPopup = new EventListener() {
|
EventListener openPersonalTimesheetPopup = new EventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(Event event) throws Exception {
|
public void onEvent(Event event) throws Exception {
|
||||||
openPersonalTimesheetPopup(textbox,
|
openPersonalTimesheetPopup(textbox, orderElement, textboxDate);
|
||||||
orderElement, textboxDate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
textbox.addEventListener(Events.ON_DOUBLE_CLICK,
|
|
||||||
openPersonalTimesheetPopup);
|
|
||||||
textbox.addEventListener(Events.ON_OK,
|
|
||||||
openPersonalTimesheetPopup);
|
|
||||||
|
|
||||||
if (personalTimesheetModel
|
textbox.addEventListener(Events.ON_DOUBLE_CLICK, openPersonalTimesheetPopup);
|
||||||
.wasModified(orderElement, textboxDate)) {
|
textbox.addEventListener(Events.ON_OK, openPersonalTimesheetPopup);
|
||||||
|
|
||||||
|
if ( personalTimesheetModel.wasModified(orderElement, textboxDate) ) {
|
||||||
markAsModified(textbox);
|
markAsModified(textbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cell cell = getCenteredCell(textbox);
|
Cell cell = getCenteredCell(textbox);
|
||||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
if ( personalTimesheetModel.getResourceCapacity(day).isZero() ) {
|
||||||
setBackgroundNonCapacityCell(cell);
|
setBackgroundNonCapacityCell(cell);
|
||||||
}
|
}
|
||||||
row.appendChild(cell);
|
row.appendChild(cell);
|
||||||
|
|
@ -256,64 +255,71 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openPersonalTimesheetPopup(Textbox textbox,
|
private void openPersonalTimesheetPopup(Textbox textbox, OrderElement orderElement, LocalDate textboxDate) {
|
||||||
OrderElement orderElement, LocalDate textboxDate) {
|
Textbox toFocus = setupPersonalTimesheetPopup(textbox, orderElement, textboxDate);
|
||||||
Textbox toFocus = setupPersonalTimesheetPopup(textbox,
|
|
||||||
orderElement, textboxDate);
|
|
||||||
personalTimesheetPopup.open(textbox, "after_start");
|
personalTimesheetPopup.open(textbox, "after_start");
|
||||||
toFocus.setFocus(true);
|
toFocus.setFocus(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Textbox setupPersonalTimesheetPopup(final Textbox textbox,
|
private Textbox setupPersonalTimesheetPopup(final Textbox textbox, final OrderElement orderElement,
|
||||||
final OrderElement orderElement, final LocalDate textboxDate) {
|
final LocalDate textboxDate) {
|
||||||
|
|
||||||
personalTimesheetPopupTask.setValue(orderElement.getName());
|
personalTimesheetPopupTask.setValue(orderElement.getName());
|
||||||
personalTimesheetPopupDate.setValue(textboxDate.toString());
|
personalTimesheetPopupDate.setValue(textboxDate.toString());
|
||||||
|
|
||||||
personalTimesheetPopupEffort.getChildren().clear();
|
personalTimesheetPopupEffort.getChildren().clear();
|
||||||
Textbox effortTextbox = Util.bind(new Textbox(),
|
|
||||||
|
Textbox effortTextbox = Util.bind(
|
||||||
|
new Textbox(),
|
||||||
new Util.Getter<String>() {
|
new Util.Getter<String>() {
|
||||||
@Override
|
@Override
|
||||||
public String get() {
|
public String get() {
|
||||||
EffortDuration effortDuration = personalTimesheetModel
|
|
||||||
.getEffortDuration(orderElement, textboxDate);
|
EffortDuration effortDuration =
|
||||||
|
personalTimesheetModel.getEffortDuration(orderElement, textboxDate);
|
||||||
|
|
||||||
return effortDurationToString(effortDuration);
|
return effortDurationToString(effortDuration);
|
||||||
}
|
}
|
||||||
}, new Util.Setter<String>() {
|
},
|
||||||
|
new Util.Setter<String>() {
|
||||||
@Override
|
@Override
|
||||||
public void set(String value) {
|
public void set(String value) {
|
||||||
EffortDuration effortDuration = effortDurationFromString(value);
|
EffortDuration effortDuration = effortDurationFromString(value);
|
||||||
if (effortDuration == null) {
|
|
||||||
|
if ( effortDuration == null ) {
|
||||||
throw new WrongValueException(
|
throw new WrongValueException(
|
||||||
personalTimesheetPopupEffort,
|
personalTimesheetPopupEffort, _("Invalid Effort Duration"));
|
||||||
_("Invalid Effort Duration"));
|
|
||||||
}
|
}
|
||||||
Events.sendEvent(new InputEvent(Events.ON_CHANGE, textbox,
|
|
||||||
value));
|
Events.sendEvent(new InputEvent(Events.ON_CHANGE, textbox, value));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
addOnOkEventToClosePopup(effortTextbox);
|
addOnOkEventToClosePopup(effortTextbox);
|
||||||
personalTimesheetPopupEffort.appendChild(effortTextbox);
|
personalTimesheetPopupEffort.appendChild(effortTextbox);
|
||||||
|
|
||||||
personalTimesheetPopupFinished.getChildren().clear();
|
personalTimesheetPopupFinished.getChildren().clear();
|
||||||
Checkbox finishedCheckbox = Util.bind(new Checkbox(),
|
|
||||||
|
Checkbox finishedCheckbox = Util.bind(
|
||||||
|
new Checkbox(),
|
||||||
new Util.Getter<Boolean>() {
|
new Util.Getter<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean get() {
|
public Boolean get() {
|
||||||
return personalTimesheetModel.isFinished(
|
return personalTimesheetModel.isFinished(orderElement, textboxDate);
|
||||||
orderElement, textboxDate);
|
|
||||||
}
|
}
|
||||||
}, new Util.Setter<Boolean>() {
|
},
|
||||||
|
new Util.Setter<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public void set(Boolean value) {
|
public void set(Boolean value) {
|
||||||
personalTimesheetModel.setFinished(orderElement,
|
personalTimesheetModel.setFinished(orderElement, textboxDate, value);
|
||||||
textboxDate, value);
|
|
||||||
markAsModified(textbox);
|
markAsModified(textbox);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!finishedCheckbox.isChecked()) {
|
|
||||||
finishedCheckbox.setDisabled(personalTimesheetModel
|
if ( !finishedCheckbox.isChecked() ) {
|
||||||
.isFinished(orderElement));
|
finishedCheckbox.setDisabled(personalTimesheetModel.isFinished(orderElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
addOnOkEventToClosePopup(finishedCheckbox);
|
addOnOkEventToClosePopup(finishedCheckbox);
|
||||||
personalTimesheetPopupFinished.appendChild(finishedCheckbox);
|
personalTimesheetPopupFinished.appendChild(finishedCheckbox);
|
||||||
|
|
||||||
|
|
@ -321,8 +327,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean addOnOkEventToClosePopup(Component component) {
|
private boolean addOnOkEventToClosePopup(Component component) {
|
||||||
return component.addEventListener(Events.ON_OK,
|
return component.addEventListener(Events.ON_OK, new EventListener() {
|
||||||
new EventListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(Event event) throws Exception {
|
public void onEvent(Event event) throws Exception {
|
||||||
closePersonalTimesheetPopup();
|
closePersonalTimesheetPopup();
|
||||||
|
|
@ -346,13 +351,10 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTotalColumn(OrderElement orderElement) {
|
private void updateTotalColumn(OrderElement orderElement) {
|
||||||
EffortDuration effort = personalTimesheetModel
|
EffortDuration effort = personalTimesheetModel.getEffortDuration(orderElement);
|
||||||
.getEffortDuration(orderElement);
|
effort = effort.plus(personalTimesheetModel.getOtherEffortDuration(orderElement));
|
||||||
effort = effort.plus(personalTimesheetModel
|
|
||||||
.getOtherEffortDuration(orderElement));
|
|
||||||
|
|
||||||
Textbox textbox = (Textbox) timesheet
|
Textbox textbox = (Textbox) timesheet.getFellow(getTotalRowTextboxId(orderElement));
|
||||||
.getFellow(getTotalRowTextboxId(orderElement));
|
|
||||||
textbox.setValue(effortDurationToString(effort));
|
textbox.setValue(effortDurationToString(effort));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -373,12 +375,13 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendTotalForDays(Row row) {
|
private void appendTotalForDays(Row row) {
|
||||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||||
.plusDays(1)) {
|
|
||||||
Cell cell = getCenteredCell(getDisabledTextbox(getTotalColumnTextboxId(day)));
|
Cell cell = getCenteredCell(getDisabledTextbox(getTotalColumnTextboxId(day)));
|
||||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
|
||||||
|
if ( personalTimesheetModel.getResourceCapacity(day).isZero() ) {
|
||||||
setBackgroundNonCapacityCell(cell);
|
setBackgroundNonCapacityCell(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
row.appendChild(cell);
|
row.appendChild(cell);
|
||||||
|
|
||||||
updateTotalRow(day);
|
updateTotalRow(day);
|
||||||
|
|
@ -386,33 +389,29 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTotalRow(LocalDate date) {
|
private void updateTotalRow(LocalDate date) {
|
||||||
EffortDuration effort = personalTimesheetModel
|
EffortDuration effort = personalTimesheetModel.getEffortDuration(date);
|
||||||
.getEffortDuration(date);
|
effort = effort.plus(personalTimesheetModel.getOtherEffortDuration(date));
|
||||||
effort = effort.plus(personalTimesheetModel
|
|
||||||
.getOtherEffortDuration(date));
|
|
||||||
|
|
||||||
Textbox textbox = (Textbox) timesheet
|
Textbox textbox = (Textbox) timesheet.getFellow(getTotalColumnTextboxId(date));
|
||||||
.getFellow(getTotalColumnTextboxId(date));
|
|
||||||
textbox.setValue(effortDurationToString(effort));
|
textbox.setValue(effortDurationToString(effort));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendTotalColumn(Row row) {
|
private void appendTotalColumn(Row row) {
|
||||||
Cell totalCell = getCenteredCell(getDisabledTextbox(getTotalTextboxId()));
|
Cell totalCell = getCenteredCell(getDisabledTextbox(getTotalTextboxId()));
|
||||||
if (personalTimesheetModel.hasOtherReports()) {
|
|
||||||
|
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||||
totalCell.setColspan(2);
|
totalCell.setColspan(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
row.appendChild(totalCell);
|
row.appendChild(totalCell);
|
||||||
updateTotalColumn();
|
updateTotalColumn();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTotalColumn() {
|
private void updateTotalColumn() {
|
||||||
EffortDuration effort = personalTimesheetModel
|
EffortDuration effort = personalTimesheetModel.getTotalEffortDuration();
|
||||||
.getTotalEffortDuration();
|
effort = effort.plus(personalTimesheetModel.getTotalOtherEffortDuration());
|
||||||
effort = effort.plus(personalTimesheetModel
|
|
||||||
.getTotalOtherEffortDuration());
|
|
||||||
|
|
||||||
Textbox textbox = (Textbox) timesheet
|
Textbox textbox = (Textbox) timesheet.getFellow(getTotalTextboxId());
|
||||||
.getFellow(getTotalTextboxId());
|
|
||||||
textbox.setValue(effortDurationToString(effort));
|
textbox.setValue(effortDurationToString(effort));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -424,23 +423,21 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
private void appendOtherForDaysAndTotal(Row row) {
|
private void appendOtherForDaysAndTotal(Row row) {
|
||||||
EffortDuration totalOther = EffortDuration.zero();
|
EffortDuration totalOther = EffortDuration.zero();
|
||||||
|
|
||||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||||
.plusDays(1)) {
|
EffortDuration other = personalTimesheetModel.getOtherEffortDuration(day);
|
||||||
EffortDuration other = personalTimesheetModel
|
|
||||||
.getOtherEffortDuration(day);
|
|
||||||
|
|
||||||
Cell cell = getCenteredCell(getDisabledTextbox(
|
Cell cell = getCenteredCell(getDisabledTextbox(getOtherColumnTextboxId(day), other));
|
||||||
getOtherColumnTextboxId(day), other));
|
|
||||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
if ( personalTimesheetModel.getResourceCapacity(day).isZero() ) {
|
||||||
setBackgroundNonCapacityCell(cell);
|
setBackgroundNonCapacityCell(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
row.appendChild(cell);
|
row.appendChild(cell);
|
||||||
|
|
||||||
totalOther = totalOther.plus(other);
|
totalOther = totalOther.plus(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cell totalOtherCell = getCenteredCell(getDisabledTextbox(
|
Cell totalOtherCell = getCenteredCell(getDisabledTextbox(getTotalOtherTextboxId(), totalOther));
|
||||||
getTotalOtherTextboxId(), totalOther));
|
|
||||||
totalOtherCell.setColspan(2);
|
totalOtherCell.setColspan(2);
|
||||||
row.appendChild(totalOtherCell);
|
row.appendChild(totalOtherCell);
|
||||||
}
|
}
|
||||||
|
|
@ -453,26 +450,26 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
private void appendCapcityForDaysAndTotal(Row row) {
|
private void appendCapcityForDaysAndTotal(Row row) {
|
||||||
EffortDuration totalCapacity = EffortDuration.zero();
|
EffortDuration totalCapacity = EffortDuration.zero();
|
||||||
|
|
||||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||||
.plusDays(1)) {
|
EffortDuration capacity = personalTimesheetModel.getResourceCapacity(day);
|
||||||
EffortDuration capacity = personalTimesheetModel
|
|
||||||
.getResourceCapacity(day);
|
|
||||||
|
|
||||||
Cell cell = getCenteredCell(getDisabledTextbox(
|
Cell cell = getCenteredCell(getDisabledTextbox(getCapcityColumnTextboxId(day), capacity));
|
||||||
getCapcityColumnTextboxId(day), capacity));
|
|
||||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
if ( personalTimesheetModel.getResourceCapacity(day).isZero() ) {
|
||||||
setBackgroundNonCapacityCell(cell);
|
setBackgroundNonCapacityCell(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
row.appendChild(cell);
|
row.appendChild(cell);
|
||||||
|
|
||||||
totalCapacity = totalCapacity.plus(capacity);
|
totalCapacity = totalCapacity.plus(capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cell totalCapacityCell = getCenteredCell(getDisabledTextbox(
|
Cell totalCapacityCell = getCenteredCell(getDisabledTextbox(getTotalCapacityTextboxId(), totalCapacity));
|
||||||
getTotalCapacityTextboxId(), totalCapacity));
|
|
||||||
if (personalTimesheetModel.hasOtherReports()) {
|
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||||
totalCapacityCell.setColspan(2);
|
totalCapacityCell.setColspan(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
row.appendChild(totalCapacityCell);
|
row.appendChild(totalCapacityCell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -483,12 +480,13 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendExtraForDays(Row row) {
|
private void appendExtraForDays(Row row) {
|
||||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||||
.plusDays(1)) {
|
|
||||||
Cell cell = getCenteredCell(getDisabledTextbox(getExtraColumnTextboxId(day)));
|
Cell cell = getCenteredCell(getDisabledTextbox(getExtraColumnTextboxId(day)));
|
||||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
|
||||||
|
if ( personalTimesheetModel.getResourceCapacity(day).isZero() ) {
|
||||||
setBackgroundNonCapacityCell(cell);
|
setBackgroundNonCapacityCell(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
row.appendChild(cell);
|
row.appendChild(cell);
|
||||||
|
|
||||||
updateExtraRow(day);
|
updateExtraRow(day);
|
||||||
|
|
@ -501,40 +499,39 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
EffortDuration capacity = getEffortDuration(getCapcityColumnTextboxId(date));
|
EffortDuration capacity = getEffortDuration(getCapcityColumnTextboxId(date));
|
||||||
|
|
||||||
EffortDuration extra = EffortDuration.zero();
|
EffortDuration extra = EffortDuration.zero();
|
||||||
if (total.compareTo(capacity) > 0) {
|
if ( total.compareTo(capacity) > 0 ) {
|
||||||
extra = total.minus(capacity);
|
extra = total.minus(capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
Textbox textbox = (Textbox) timesheet
|
Textbox textbox = (Textbox) timesheet.getFellow(getExtraColumnTextboxId(date));
|
||||||
.getFellow(getExtraColumnTextboxId(date));
|
|
||||||
textbox.setValue(effortDurationToString(extra));
|
textbox.setValue(effortDurationToString(extra));
|
||||||
}
|
}
|
||||||
|
|
||||||
private EffortDuration getEffortDuration(String textboxId) {
|
private EffortDuration getEffortDuration(String textboxId) {
|
||||||
String value = ((Textbox) timesheet.getFellow(textboxId))
|
String value = ((Textbox) timesheet.getFellow(textboxId)).getValue();
|
||||||
.getValue();
|
|
||||||
return effortDurationFromString(value);
|
return effortDurationFromString(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendTotalExtra(Row row) {
|
private void appendTotalExtra(Row row) {
|
||||||
Cell totalExtraCell = getCenteredCell(getDisabledTextbox(getTotalExtraTextboxId()));
|
Cell totalExtraCell = getCenteredCell(getDisabledTextbox(getTotalExtraTextboxId()));
|
||||||
if (personalTimesheetModel.hasOtherReports()) {
|
|
||||||
|
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||||
totalExtraCell.setColspan(2);
|
totalExtraCell.setColspan(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
row.appendChild(totalExtraCell);
|
row.appendChild(totalExtraCell);
|
||||||
updateTotalExtraColumn();
|
updateTotalExtraColumn();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTotalExtraColumn() {
|
private void updateTotalExtraColumn() {
|
||||||
EffortDuration totalExtra = EffortDuration.zero();
|
EffortDuration totalExtra = EffortDuration.zero();
|
||||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
for (LocalDate day = first; day.compareTo(last) <= 0; day = day.plusDays(1)) {
|
||||||
.plusDays(1)) {
|
|
||||||
EffortDuration extra = getEffortDuration(getExtraColumnTextboxId(day));
|
EffortDuration extra = getEffortDuration(getExtraColumnTextboxId(day));
|
||||||
totalExtra = totalExtra.plus(extra);
|
totalExtra = totalExtra.plus(extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
Textbox textbox = (Textbox) timesheet
|
Textbox textbox = (Textbox) timesheet.getFellow(getTotalExtraTextboxId());
|
||||||
.getFellow(getTotalExtraTextboxId());
|
|
||||||
textbox.setValue(effortDurationToString(totalExtra));
|
textbox.setValue(effortDurationToString(totalExtra));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -543,12 +540,14 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
textbox.setHflex("true");
|
textbox.setHflex("true");
|
||||||
textbox.setId(id);
|
textbox.setId(id);
|
||||||
textbox.setDisabled(true);
|
textbox.setDisabled(true);
|
||||||
|
|
||||||
return textbox;
|
return textbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Textbox getDisabledTextbox(String id, EffortDuration effort) {
|
private Textbox getDisabledTextbox(String id, EffortDuration effort) {
|
||||||
Textbox textbox = getDisabledTextbox(id);
|
Textbox textbox = getDisabledTextbox(id);
|
||||||
textbox.setValue(effortDurationToString(effort));
|
textbox.setValue(effortDurationToString(effort));
|
||||||
|
|
||||||
return textbox;
|
return textbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -556,6 +555,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
Cell cell = new Cell();
|
Cell cell = new Cell();
|
||||||
cell.setAlign("center");
|
cell.setAlign("center");
|
||||||
cell.appendChild(component);
|
cell.appendChild(component);
|
||||||
|
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,6 +563,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
Cell cell = new Cell();
|
Cell cell = new Cell();
|
||||||
cell.setAlign("left");
|
cell.setAlign("left");
|
||||||
cell.appendChild(component);
|
cell.appendChild(component);
|
||||||
|
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -582,31 +583,31 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
|
|
||||||
checkUserComesFromEntryPointsOrSendForbiddenCode();
|
checkUserComesFromEntryPointsOrSendForbiddenCode();
|
||||||
|
|
||||||
URLHandlerRegistry.getRedirectorFor(IPersonalTimesheetController.class)
|
URLHandlerRegistry.getRedirectorFor(IPersonalTimesheetController.class).register(this, page);
|
||||||
.register(this, page);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void adjustFrozenWidth() {
|
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);");
|
Clients.evalJavaScript("jq('.z-frozen-inner div').width(jq('.totals-column').offset().left);");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkUserComesFromEntryPointsOrSendForbiddenCode() {
|
private void checkUserComesFromEntryPointsOrSendForbiddenCode() {
|
||||||
HttpServletRequest request = (HttpServletRequest) Executions
|
HttpServletRequest request = (HttpServletRequest) Executions.getCurrent().getNativeRequest();
|
||||||
.getCurrent().getNativeRequest();
|
|
||||||
Map<String, String> matrixParams = MatrixParameters.extract(request);
|
Map<String, String> matrixParams = MatrixParameters.extract(request);
|
||||||
|
|
||||||
// If it doesn't come from a entry point
|
// If it doesn't come from a entry point
|
||||||
if (matrixParams.isEmpty()) {
|
if ( matrixParams.isEmpty() ) {
|
||||||
Util.sendForbiddenStatusCodeInHttpServletResponse();
|
Util.sendForbiddenStatusCodeInHttpServletResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBreadcrumbs(Component comp) {
|
private void setBreadcrumbs(Component comp) {
|
||||||
Component breadcrumbs = comp.getPage().getFellow("breadcrumbs");
|
Component breadcrumbs = comp.getPage().getFellow("breadcrumbs");
|
||||||
if (breadcrumbs.getChildren() != null) {
|
|
||||||
|
if ( breadcrumbs.getChildren() != null ) {
|
||||||
breadcrumbs.getChildren().clear();
|
breadcrumbs.getChildren().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR));
|
breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR));
|
||||||
breadcrumbs.appendChild(new Label(_("My account")));
|
breadcrumbs.appendChild(new Label(_("My account")));
|
||||||
breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR));
|
breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR));
|
||||||
|
|
@ -617,7 +618,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void goToCreateOrEditForm(LocalDate date) {
|
public void goToCreateOrEditForm(LocalDate date) {
|
||||||
if (!SecurityUtils.isUserInRole(UserRole.ROLE_BOUND_USER)) {
|
if ( !SecurityUtils.isUserInRole(UserRole.ROLE_BOUND_USER) ) {
|
||||||
Util.sendForbiddenStatusCodeInHttpServletResponse();
|
Util.sendForbiddenStatusCodeInHttpServletResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -628,7 +629,8 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
@Override
|
@Override
|
||||||
public void goToCreateOrEditFormForResource(LocalDate date,
|
public void goToCreateOrEditFormForResource(LocalDate date,
|
||||||
org.libreplan.business.resources.entities.Resource resource) {
|
org.libreplan.business.resources.entities.Resource resource) {
|
||||||
if (!SecurityUtils.isSuperuserOrUserInRoles(UserRole.ROLE_TIMESHEETS)) {
|
|
||||||
|
if ( !SecurityUtils.isSuperuserOrUserInRoles(UserRole.ROLE_TIMESHEETS) ) {
|
||||||
Util.sendForbiddenStatusCodeInHttpServletResponse();
|
Util.sendForbiddenStatusCodeInHttpServletResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -653,9 +655,11 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
private void createColumns(LocalDate date) {
|
private void createColumns(LocalDate date) {
|
||||||
createProjectAndTaskColumns();
|
createProjectAndTaskColumns();
|
||||||
createColumnsForDays(date);
|
createColumnsForDays(date);
|
||||||
if (personalTimesheetModel.hasOtherReports()) {
|
|
||||||
|
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||||
createOtherColumn();
|
createOtherColumn();
|
||||||
}
|
}
|
||||||
|
|
||||||
createTotalColumn();
|
createTotalColumn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -672,13 +676,10 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createColumnsForDays(LocalDate date) {
|
private void createColumnsForDays(LocalDate date) {
|
||||||
LocalDate start = personalTimesheetModel
|
LocalDate start = personalTimesheetModel.getPersonalTimesheetsPeriodicity().getStart(date);
|
||||||
.getPersonalTimesheetsPeriodicity().getStart(date);
|
LocalDate end = personalTimesheetModel.getPersonalTimesheetsPeriodicity().getEnd(date);
|
||||||
LocalDate end = personalTimesheetModel
|
|
||||||
.getPersonalTimesheetsPeriodicity().getEnd(date);
|
|
||||||
|
|
||||||
for (LocalDate day = start; day.compareTo(end) <= 0; day = day
|
for (LocalDate day = start; day.compareTo(end) <= 0; day = day.plusDays(1)) {
|
||||||
.plusDays(1)) {
|
|
||||||
Column column = new Column(day.getDayOfMonth() + "");
|
Column column = new Column(day.getDayOfMonth() + "");
|
||||||
column.setAlign("center");
|
column.setAlign("center");
|
||||||
column.setWidth(EFFORT_DURATION_TEXTBOX_WIDTH);
|
column.setWidth(EFFORT_DURATION_TEXTBOX_WIDTH);
|
||||||
|
|
@ -711,15 +712,15 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PersonalTimesheetRow> getRows() {
|
public List<PersonalTimesheetRow> getRows() {
|
||||||
List<PersonalTimesheetRow> result = PersonalTimesheetRow
|
List<PersonalTimesheetRow> result = PersonalTimesheetRow.wrap(personalTimesheetModel.getOrderElements());
|
||||||
.wrap(personalTimesheetModel
|
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||||
.getOrderElements());
|
|
||||||
if (personalTimesheetModel.hasOtherReports()) {
|
|
||||||
result.add(PersonalTimesheetRow.createOtherRow());
|
result.add(PersonalTimesheetRow.createOtherRow());
|
||||||
}
|
}
|
||||||
|
|
||||||
result.add(PersonalTimesheetRow.createTotalRow());
|
result.add(PersonalTimesheetRow.createTotalRow());
|
||||||
result.add(PersonalTimesheetRow.createCapacityRow());
|
result.add(PersonalTimesheetRow.createCapacityRow());
|
||||||
result.add(PersonalTimesheetRow.createExtraRow());
|
result.add(PersonalTimesheetRow.createExtraRow());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -729,22 +730,24 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
|
|
||||||
public void save() {
|
public void save() {
|
||||||
personalTimesheetModel.save();
|
personalTimesheetModel.save();
|
||||||
String url = IndexController.USER_DASHBOARD_URL
|
String url = IndexController.USER_DASHBOARD_URL + "?timesheet_saved=" + personalTimesheetModel.getDate();
|
||||||
+ "?timesheet_saved=" + personalTimesheetModel.getDate();
|
|
||||||
if (!personalTimesheetModel.isCurrentUser()) {
|
if ( !personalTimesheetModel.isCurrentUser() ) {
|
||||||
url = WORK_REPORTS_URL + "?timesheet_saved=true";
|
url = WORK_REPORTS_URL + "?timesheet_saved=true";
|
||||||
}
|
}
|
||||||
|
|
||||||
Executions.getCurrent().sendRedirect(url);
|
Executions.getCurrent().sendRedirect(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveAndContinue() {
|
public void saveAndContinue() {
|
||||||
personalTimesheetModel.save();
|
personalTimesheetModel.save();
|
||||||
if (personalTimesheetModel.isCurrentUser()) {
|
|
||||||
|
if ( personalTimesheetModel.isCurrentUser() ) {
|
||||||
goToCreateOrEditForm(personalTimesheetModel.getDate());
|
goToCreateOrEditForm(personalTimesheetModel.getDate());
|
||||||
} else {
|
} else {
|
||||||
goToCreateOrEditFormForResource(personalTimesheetModel.getDate(),
|
goToCreateOrEditFormForResource(personalTimesheetModel.getDate(), personalTimesheetModel.getWorker());
|
||||||
personalTimesheetModel.getWorker());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
messagesForUser.showMessage(Level.INFO, _("Personal timesheet saved"));
|
messagesForUser.showMessage(Level.INFO, _("Personal timesheet saved"));
|
||||||
Util.reloadBindings(timesheet);
|
Util.reloadBindings(timesheet);
|
||||||
}
|
}
|
||||||
|
|
@ -752,16 +755,17 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
personalTimesheetModel.cancel();
|
personalTimesheetModel.cancel();
|
||||||
String url = IndexController.USER_DASHBOARD_URL;
|
String url = IndexController.USER_DASHBOARD_URL;
|
||||||
if (!personalTimesheetModel.isCurrentUser()) {
|
|
||||||
|
if ( !personalTimesheetModel.isCurrentUser() ) {
|
||||||
url = WORK_REPORTS_URL;
|
url = WORK_REPORTS_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Executions.getCurrent().sendRedirect(url);
|
Executions.getCurrent().sendRedirect(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOrderElement() {
|
public void addOrderElement() {
|
||||||
OrderElement orderElement = (OrderElement) orderElementBandboxSearch
|
OrderElement orderElement = (OrderElement) orderElementBandboxSearch.getSelectedElement();
|
||||||
.getSelectedElement();
|
if ( orderElement != null ) {
|
||||||
if (orderElement != null) {
|
|
||||||
personalTimesheetModel.addOrderElement(orderElement);
|
personalTimesheetModel.addOrderElement(orderElement);
|
||||||
orderElementBandboxSearch.setSelectedElement(null);
|
orderElementBandboxSearch.setSelectedElement(null);
|
||||||
Util.reloadBindings(timesheet);
|
Util.reloadBindings(timesheet);
|
||||||
|
|
@ -778,18 +782,17 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
public void previousPeriod() {
|
public void previousPeriod() {
|
||||||
if (personalTimesheetModel.isModified()) {
|
if ( personalTimesheetModel.isModified() ) {
|
||||||
throw new WrongValueException(
|
throw new WrongValueException(previousPeriod,
|
||||||
previousPeriod,
|
|
||||||
_("There are unsaved changes in the current personal timesheet, please save before moving"));
|
_("There are unsaved changes in the current personal timesheet, please save before moving"));
|
||||||
}
|
}
|
||||||
|
|
||||||
sendToPersonalTimesheet(personalTimesheetModel.getPrevious());
|
sendToPersonalTimesheet(personalTimesheetModel.getPrevious());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void nextPeriod() {
|
public void nextPeriod() {
|
||||||
if (personalTimesheetModel.isModified()) {
|
if ( personalTimesheetModel.isModified() ) {
|
||||||
throw new WrongValueException(
|
throw new WrongValueException(nextPeriod,
|
||||||
nextPeriod,
|
|
||||||
_("There are unsaved changes in the current personal timesheet, please save before moving"));
|
_("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);
|
personalTimesheetController.goToCreateOrEditForm(date);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Executions.getCurrent().sendRedirect(capturePath);
|
Executions.getCurrent().sendRedirect(capturePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -855,7 +859,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String effortDurationToString(EffortDuration effort) {
|
private static String effortDurationToString(EffortDuration effort) {
|
||||||
if (effort == null || effort.isZero()) {
|
if ( effort == null || effort.isZero() ) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -863,19 +867,19 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EffortDuration effortDurationFromString(String effort) {
|
private static EffortDuration effortDurationFromString(String effort) {
|
||||||
if (StringUtils.isBlank(effort)) {
|
if ( StringUtils.isBlank(effort) ) {
|
||||||
return EffortDuration.zero();
|
return EffortDuration.zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
String decimalSeparator = ((DecimalFormat) DecimalFormat
|
String decimalSeparator = ((DecimalFormat) DecimalFormat
|
||||||
.getInstance(Locales.getCurrent()))
|
.getInstance(Locales.getCurrent()))
|
||||||
.getDecimalFormatSymbols().getDecimalSeparator() + "";
|
.getDecimalFormatSymbols().getDecimalSeparator() + "";
|
||||||
if (effort.contains(decimalSeparator) || effort.contains(".")) {
|
|
||||||
|
if ( effort.contains(decimalSeparator) || effort.contains(".") ) {
|
||||||
try {
|
try {
|
||||||
effort = effort.replace(decimalSeparator, ".");
|
effort = effort.replace(decimalSeparator, ".");
|
||||||
double hours = Double.parseDouble(effort);
|
double hours = Double.parseDouble(effort);
|
||||||
return EffortDuration.fromHoursAsBigDecimal(new BigDecimal(
|
return EffortDuration.fromHoursAsBigDecimal(new BigDecimal(hours));
|
||||||
hours));
|
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -887,21 +891,23 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
public void updateSummary() {
|
public void updateSummary() {
|
||||||
EffortDuration total = getEffortDurationFromTextbox(getTotalTextboxId());
|
EffortDuration total = getEffortDurationFromTextbox(getTotalTextboxId());
|
||||||
EffortDuration other = EffortDuration.zero();
|
EffortDuration other = EffortDuration.zero();
|
||||||
if (personalTimesheetModel.hasOtherReports()) {
|
|
||||||
|
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||||
other = getEffortDurationFromTextbox(getTotalOtherTextboxId());
|
other = getEffortDurationFromTextbox(getTotalOtherTextboxId());
|
||||||
}
|
}
|
||||||
|
|
||||||
EffortDuration capacity = getEffortDurationFromTextbox(getTotalCapacityTextboxId());
|
EffortDuration capacity = getEffortDurationFromTextbox(getTotalCapacityTextboxId());
|
||||||
EffortDuration extraPerDay = getEffortDurationFromTextbox(getTotalExtraTextboxId());
|
EffortDuration extraPerDay = getEffortDurationFromTextbox(getTotalExtraTextboxId());
|
||||||
|
|
||||||
EffortDuration timesheet = total.minus(other);
|
EffortDuration timesheet = total.minus(other);
|
||||||
EffortDuration extra = EffortDuration.zero();
|
EffortDuration extra = EffortDuration.zero();
|
||||||
if (total.compareTo(capacity) > 0) {
|
|
||||||
|
if ( total.compareTo(capacity) > 0 ) {
|
||||||
extra = total.minus(capacity);
|
extra = total.minus(capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (personalTimesheetModel.hasOtherReports()) {
|
if ( personalTimesheetModel.hasOtherReports() ) {
|
||||||
summaryTotalPersonalTimesheet
|
summaryTotalPersonalTimesheet.setValue(timesheet.toFormattedString());
|
||||||
.setValue(timesheet.toFormattedString());
|
|
||||||
summaryTotalOther.setValue(other.toFormattedString());
|
summaryTotalOther.setValue(other.toFormattedString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -912,8 +918,7 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
private EffortDuration getEffortDurationFromTextbox(String id) {
|
private EffortDuration getEffortDurationFromTextbox(String id) {
|
||||||
return effortDurationFromString(((Textbox) timesheet.getFellow(id))
|
return effortDurationFromString(((Textbox) timesheet.getFellow(id)).getValue());
|
||||||
.getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasOtherReports() {
|
public boolean hasOtherReports() {
|
||||||
|
|
@ -932,19 +937,19 @@ public class PersonalTimesheetController extends GenericForwardComposer
|
||||||
* This is used to mark the special rows like capacity and total.
|
* This is used to mark the special rows like capacity and total.
|
||||||
*/
|
*/
|
||||||
class PersonalTimesheetRow {
|
class PersonalTimesheetRow {
|
||||||
|
|
||||||
enum PersonalTimesheetRowType {
|
enum PersonalTimesheetRowType {
|
||||||
ORDER_ELEMENT, OTHER, CAPACITY, TOTAL, EXTRA
|
ORDER_ELEMENT, OTHER, CAPACITY, TOTAL, EXTRA
|
||||||
};
|
}
|
||||||
|
|
||||||
private PersonalTimesheetRowType type;
|
private PersonalTimesheetRowType type;
|
||||||
private OrderElement orderElemement;
|
private OrderElement orderElemement;
|
||||||
|
|
||||||
public static PersonalTimesheetRow createOrderElementRow(
|
public static PersonalTimesheetRow createOrderElementRow(OrderElement orderElemement) {
|
||||||
OrderElement orderElemement) {
|
PersonalTimesheetRow row = new PersonalTimesheetRow(PersonalTimesheetRowType.ORDER_ELEMENT);
|
||||||
PersonalTimesheetRow row = new PersonalTimesheetRow(
|
|
||||||
PersonalTimesheetRowType.ORDER_ELEMENT);
|
|
||||||
Assert.notNull(orderElemement);
|
Assert.notNull(orderElemement);
|
||||||
row.orderElemement = orderElemement;
|
row.orderElemement = orderElemement;
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -964,12 +969,12 @@ class PersonalTimesheetRow {
|
||||||
return new PersonalTimesheetRow(PersonalTimesheetRowType.EXTRA);
|
return new PersonalTimesheetRow(PersonalTimesheetRowType.EXTRA);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<PersonalTimesheetRow> wrap(
|
public static List<PersonalTimesheetRow> wrap(List<OrderElement> orderElements) {
|
||||||
List<OrderElement> orderElements) {
|
List<PersonalTimesheetRow> result = new ArrayList<>();
|
||||||
List<PersonalTimesheetRow> result = new ArrayList<PersonalTimesheetRow>();
|
|
||||||
for (OrderElement each : orderElements) {
|
for (OrderElement each : orderElements) {
|
||||||
result.add(createOrderElementRow(each));
|
result.add(createOrderElementRow(each));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
6
pom.xml
6
pom.xml
|
|
@ -390,9 +390,9 @@
|
||||||
|
|
||||||
<!-- Commons lang -->
|
<!-- Commons lang -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-lang</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>2.4</version>
|
<version>3.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Commons Math-->
|
<!-- Commons Math-->
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue