org.libreplan.business.calendars.entities.Capacity.java Source code

Java tutorial

Introduction

Here is the source code for org.libreplan.business.calendars.entities.Capacity.java

Source

/*
 * This file is part of LibrePlan
 *
 * Copyright (C) 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.calendars.entities;

import static org.libreplan.business.i18n.I18nHelper._;

import java.util.Arrays;
import java.util.Collection;
import java.util.EnumMap;

import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.EffortDuration.Granularity;

/**
 * This class is intended as a Hibernate component.
 * It's formed by two components, the standard effort and the allowed extra effort.
 * It represents the capacity for a resource.
 *
 * @author scar Gonzlez Fernndez <ogonzalez@igalia.com>
 */
public class Capacity {

    private EffortDuration standardEffort;

    private EffortDuration allowedExtraEffort;

    public static Capacity sum(Capacity... capacities) {
        return sum(Arrays.asList(capacities));
    }

    public static Capacity sum(Collection<? extends Capacity> capacities) {
        EffortDuration standard = EffortDuration.zero();
        EffortDuration extra = EffortDuration.zero();
        for (Capacity each : capacities) {
            standard = standard.plus(each.getStandardEffort());
            extra = extra == null || each.isOverAssignableWithoutLimit() ? null
                    : extra.plus(each.getAllowedExtraEffort());
        }
        return Capacity.create(standard).withAllowedExtraEffort(extra);
    }

    public static Capacity min(Capacity a, Capacity b) {
        return new Capacity(EffortDuration.min(a.getStandardEffort(), b.getStandardEffort()), minExtraEffort(a, b));
    }

    private static EffortDuration minExtraEffort(Capacity a, Capacity b) {
        if (a.isOverAssignableWithoutLimit()) {
            return b.getAllowedExtraEffort();
        }
        if (b.isOverAssignableWithoutLimit()) {
            return a.getAllowedExtraEffort();
        }
        return EffortDuration.min(a.getAllowedExtraEffort(), b.getAllowedExtraEffort());
    }

    public static Capacity max(Capacity a, Capacity b) {
        return new Capacity(EffortDuration.max(a.getStandardEffort(), b.getStandardEffort()), maxExtraEffort(a, b));
    }

    private static EffortDuration maxExtraEffort(Capacity a, Capacity b) {
        if (a.isOverAssignableWithoutLimit() || b.isOverAssignableWithoutLimit()) {
            return null;
        }
        return EffortDuration.max(a.getAllowedExtraEffort(), b.getAllowedExtraEffort());
    }

    public static Capacity create(EffortDuration standardEffort) {
        return new Capacity(standardEffort, null);
    }

    private static Capacity noCapacity() {
        return Capacity.create(EffortDuration.zero()).notOverAssignableWithoutLimit();
    }

    public static Capacity zero() {
        return new Capacity(EffortDuration.zero(), EffortDuration.zero());
    }

    /**
     * Default constructor for hibernate. DO NOT USE!
     *
     * @see Capacity#create(EffortDuration)
     */
    public Capacity() {
    }

    private Capacity(EffortDuration standardEffort, EffortDuration extraHours) {
        Validate.notNull(standardEffort);
        this.standardEffort = standardEffort;
        this.allowedExtraEffort = extraHours;
    }

    public EffortDuration getStandardEffort() {
        if (standardEffort == null) {
            return EffortDuration.zero();
        }
        return standardEffort;
    }

    public EffortDuration getAllowedExtraEffort() {
        return allowedExtraEffort;
    }

    public boolean isOverAssignableWithoutLimit() {
        return allowedExtraEffort == null;
    }

    public Capacity withAllowedExtraEffort(EffortDuration extraEffort) {
        return new Capacity(standardEffort, extraEffort);
    }

    public Capacity withStandardEffort(EffortDuration standardEffort) {
        return new Capacity(standardEffort, allowedExtraEffort);
    }

    public Capacity overAssignableWithoutLimit() {
        return overAssignableWithoutLimit(true);
    }

    public Capacity notOverAssignableWithoutLimit() {
        return overAssignableWithoutLimit(false);
    }

    public Capacity overAssignableWithoutLimit(boolean overAssignableWithoutLimit) {
        if (overAssignableWithoutLimit) {
            return new Capacity(standardEffort, null);
        } else {
            return new Capacity(standardEffort,
                    allowedExtraEffort == null ? EffortDuration.zero() : allowedExtraEffort);
        }
    }

    public boolean isZero() {
        return standardEffort.isZero();
    }

    public String getStandardEffortString() {
        return asString(getStandardEffort());
    }

    public String getExtraEffortString() {
        if (getAllowedExtraEffort() == null) {
            return _("unlimited");
        }
        return asString(getAllowedExtraEffort());
    }

    private static String asString(EffortDuration duration) {
        if (duration == null) {
            return "";
        }
        EnumMap<Granularity, Integer> values = duration.decompose();
        Integer hours = values.get(Granularity.HOURS);
        Integer minutes = values.get(Granularity.MINUTES);
        return hours + ":" + minutes;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Capacity) {
            Capacity other = (Capacity) obj;
            return new EqualsBuilder().append(standardEffort, other.standardEffort)
                    .append(allowedExtraEffort, other.allowedExtraEffort).isEquals();
        }
        return false;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(standardEffort).append(allowedExtraEffort).toHashCode();
    }

    public EffortDuration limitDuration(EffortDuration duration) {
        if (isOverAssignableWithoutLimit()) {
            return duration;
        }
        return EffortDuration.min(standardEffort.plus(allowedExtraEffort), duration);
    }

    /**
     * <p>
     * Is the provided duration below the allowed duration? In that case there
     * is still spare space for more allocations.
     * </p>
     * <p>
     * The allowed duration is infinite if this {@link Capacity} is
     * {@link #overAssignableWithoutLimit(boolean)} or the duration provided is
     * less than the sum of the standard plus allowed extra effort.
     * </p>
     *
     * @param assignedDuration
     * @return
     */
    public boolean hasSpareSpaceForMoreAllocations(EffortDuration assignedDuration) {
        Validate.notNull(assignedDuration);
        return isOverAssignableWithoutLimit()
                || assignedDuration.compareTo(standardEffort.plus(allowedExtraEffort)) < 0;
    }

    public Capacity minus(EffortDuration assignment) {
        if (!hasSpareSpaceForMoreAllocations(assignment)) {
            return noCapacity();
        }

        EffortDuration newStandard = standardEffort.minus(EffortDuration.min(assignment, standardEffort));
        EffortDuration pending = assignment.minus(EffortDuration.min(standardEffort, assignment));
        EffortDuration newExtra = allowedExtraEffort == null ? null
                : allowedExtraEffort.minus(EffortDuration.min(pending, allowedExtraEffort));
        return Capacity.create(newStandard).withAllowedExtraEffort(newExtra);

    }

    public boolean allowsWorking() {
        return !getStandardEffort().isZero() || isOverAssignableWithoutLimit() || !getAllowedExtraEffort().isZero();
    }

    public Capacity multiplyBy(int capacity) {
        Validate.isTrue(capacity >= 0);
        return new Capacity(standardEffort.multiplyBy(capacity),
                allowedExtraEffort == null ? null : allowedExtraEffort.multiplyBy(capacity));
    }

    @Override
    public String toString() {
        return "[" + getStandardEffortString() + " - " + getExtraEffortString() + "]";
    }

}