/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.business.planner.limiting.entities;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.Validate;
import javax.validation.Valid;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.LocalDate;
import org.libreplan.business.common.BaseEntity;
import org.libreplan.business.planner.entities.DayAssignment;
import org.libreplan.business.planner.entities.GenericResourceAllocation;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.SpecificResourceAllocation;
import org.libreplan.business.planner.entities.Task;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.resources.entities.LimitingResourceQueue;
import org.libreplan.business.resources.entities.LimitingResourceQueueElementComparator;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.workingday.IntraDayDate;
/**
* Entity which represents an element in the queue which represents the limiting
* resources.
* @author Diego Pino Garcia <dpino@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
*/
public class LimitingResourceQueueElement extends BaseEntity {
public static Comparator<LimitingResourceQueueElement> byStartTimeComparator() {
return new LimitingResourceQueueElementComparator();
}
private ResourceAllocation<?> resourceAllocation;
private LimitingResourceQueue limitingResourceQueue;
private Date earlierStartDateBecauseOfGantt;
private Date earliestEndDateBecauseOfGantt;
private QueuePosition startQueuePosition;
private QueuePosition endQueuePosition;
private long creationTimestamp;
private Set<LimitingResourceQueueDependency> dependenciesAsOrigin = new HashSet<LimitingResourceQueueDependency>();
private Set<LimitingResourceQueueDependency> dependenciesAsDestiny = new HashSet<LimitingResourceQueueDependency>();
public static boolean isAfter(LimitingResourceQueueElement element, DateAndHour time) {
return element.getStartTime().isAfter(time);
}
public static boolean isInTheMiddle(LimitingResourceQueueElement element, DateAndHour time) {
return (element.getStartTime().isBefore(time) || element.getStartTime().isEquals(time))
&& (element.getEndTime().isAfter(time) || element.getEndTime().isEquals(time));
}
public static LimitingResourceQueueElement create() {
return create(new LimitingResourceQueueElement());
}
protected LimitingResourceQueueElement() {
creationTimestamp = (new Date()).getTime();
startQueuePosition = new QueuePosition();
startQueuePosition.setHour(0);
endQueuePosition = new QueuePosition();
endQueuePosition.setHour(0);
}
@Valid
public ResourceAllocation<?> getResourceAllocation() {
return resourceAllocation;
}
public void setResourceAllocation(ResourceAllocation<?> resourceAllocation) {
this.resourceAllocation = resourceAllocation;
}
public void setEarlierStartDateBecauseOfGantt(Date date) {
earlierStartDateBecauseOfGantt = date;
}
public LimitingResourceQueue getLimitingResourceQueue() {
return limitingResourceQueue;
}
public void setLimitingResourceQueue(
LimitingResourceQueue limitingResourceQueue) {
this.limitingResourceQueue = limitingResourceQueue;
}
public LocalDate getStartDate() {
return startQueuePosition.getDate();
}
public void setStartDate(LocalDate date) {
startQueuePosition.setDate(date);
notifyQueueElementIsMoved();
}
private void notifyQueueElementIsMoved() {
if (getLimitingResourceQueue() != null) {
getLimitingResourceQueue().queueElementMoved(this);
}
}
public int getStartHour() {
return startQueuePosition.getHour();
}
public void setStartHour(int hour) {
startQueuePosition.setHour(hour);
notifyQueueElementIsMoved();
}
public LocalDate getEndDate() {
return endQueuePosition.getDate();
}
public void setEndDate(LocalDate date) {
notifyQueueElementIsMoved();
endQueuePosition.setDate(date);
}
public int getEndHour() {
return endQueuePosition.getHour();
}
public void setEndHour(int hour) {
endQueuePosition.setHour(hour);
notifyQueueElementIsMoved();
}
public Duration getLengthBetween() {
DateTime start = getStartDate().toDateTimeAtStartOfDay().plusHours(
getStartHour());
DateTime end = getEndDate().toDateTimeAtStartOfDay().plusHours(
getEndHour());
return new Duration(start, end);
}
public Date getEarliestStartDateBecauseOfGantt() {
return earlierStartDateBecauseOfGantt;
}
public Date getEarliestEndDateBecauseOfGantt() {
if (earliestEndDateBecauseOfGantt == null) {
// can be null because it's a new column
return earlierStartDateBecauseOfGantt;
}
return earliestEndDateBecauseOfGantt;
}
public long getCreationTimestamp() {
return creationTimestamp;
}
public void setCreationTimestamp(long creationTimestamp) {
this.creationTimestamp = creationTimestamp;
}
public Resource getResource() {
if (resourceAllocation instanceof SpecificResourceAllocation) {
final SpecificResourceAllocation specific = (SpecificResourceAllocation) resourceAllocation;
return specific.getResource();
}
return null;
}
public Integer getIntentedTotalHours() {
return (getResourceAllocation() != null) ? getResourceAllocation()
.getIntendedTotalHours() : null;
}
public DateAndHour getStartTime() {
return new DateAndHour(getStartDate(), getStartHour());
}
public DateAndHour getEndTime() {
return new DateAndHour(getEndDate(), getEndHour());
}
public void add(LimitingResourceQueueDependency d) {
Validate.notNull(d);
if (sameInDB(d.getHasAsOrigin())) {
dependenciesAsOrigin.add(d);
} else if (sameInDB(d.getHasAsDestiny())) {
dependenciesAsDestiny.add(d);
} else {
throw new IllegalArgumentException(
"It cannot be added a dependency"
+ " in which the current queue element is neither origin"
+ " not desinty");
}
}
private boolean sameInDB(LimitingResourceQueueElement other) {
return this == other || other.getId() != null && this.getId() != null
&& other.getId().equals(this.getId());
}
public void remove(LimitingResourceQueueDependency d) {
if (dependenciesAsOrigin.contains(d)) {
dependenciesAsOrigin.remove(d);
}
if (dependenciesAsDestiny.contains(d)) {
dependenciesAsDestiny.remove(d);
}
}
public Set<LimitingResourceQueueDependency> getDependenciesAsOrigin() {
return Collections.unmodifiableSet(dependenciesAsOrigin);
}
public Set<LimitingResourceQueueDependency> getDependenciesAsDestiny() {
return Collections.unmodifiableSet(dependenciesAsDestiny);
}
public void updateDates(IntraDayDate earliestStart, IntraDayDate earliestEnd) {
this.earlierStartDateBecauseOfGantt = toDate(earliestStart);
this.earliestEndDateBecauseOfGantt = toDate(earliestEnd);
}
private Date toDate(IntraDayDate intraDayDate) {
return intraDayDate.toDateTimeAtStartOfDay().toDate();
}
public void detach() {
setLimitingResourceQueue(null);
setStartDate(null);
setStartHour(0);
setEndDate(null);
setEndHour(0);
getResourceAllocation().removeLimitingDayAssignments();
}
public boolean isDetached() {
return getStartDate() == null;
}
public boolean isSpecific() {
return resourceAllocation instanceof SpecificResourceAllocation;
}
public boolean isGeneric() {
return resourceAllocation instanceof GenericResourceAllocation;
}
public Set<Criterion> getCriteria() {
if (!isGeneric()) {
throw new IllegalStateException("this is not a generic element");
}
final ResourceAllocation<?> resourceAllocation = getResourceAllocation();
return ((GenericResourceAllocation) resourceAllocation).getCriterions();
}
public boolean hasDayAssignments() {
return !getResourceAllocation().getAssignments().isEmpty();
}
public List<? extends DayAssignment> getDayAssignments() {
return resourceAllocation.getAssignments();
}
public BigDecimal getAdvancePercentage() {
return resourceAllocation.getTask().getAdvancePercentage();
}
public Task getTask() {
return resourceAllocation.getTask();
}
public String toString() {
return getTask().getName() + "; " + getLimitingResourceQueue();
}
}