Package org.libreplan.web.planner.reassign

Source Code of org.libreplan.web.planner.reassign.ReassignCommand$IConfigurationResult

/*
* 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-2012 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.web.planner.reassign;

import static org.libreplan.web.I18nHelper._;
import static org.zkoss.ganttz.util.LongOperationFeedback.and;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;

import org.apache.commons.lang.Validate;
import org.libreplan.business.common.IAdHocTransactionService;
import org.libreplan.business.common.IOnTransaction;
import org.libreplan.business.planner.daos.ITaskElementDAO;
import org.libreplan.business.planner.entities.GenericResourceAllocation;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.resources.daos.ICriterionTypeDAO;
import org.libreplan.business.resources.daos.IResourcesSearcher;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.resources.entities.CriterionType;
import org.libreplan.web.planner.order.PlanningStateCreator.PlanningState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.zkoss.ganttz.adapters.IDomainAndBeansMapper;
import org.zkoss.ganttz.data.Dependency;
import org.zkoss.ganttz.data.GanttDate;
import org.zkoss.ganttz.data.GanttDiagramGraph;
import org.zkoss.ganttz.data.Task;
import org.zkoss.ganttz.extensions.IContext;
import org.zkoss.ganttz.util.IAction;
import org.zkoss.ganttz.util.LongOperationFeedback;
import org.zkoss.ganttz.util.LongOperationFeedback.IBackGroundOperation;
import org.zkoss.ganttz.util.LongOperationFeedback.IDesktopUpdate;
import org.zkoss.ganttz.util.LongOperationFeedback.IDesktopUpdatesEmitter;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.Messagebox;

/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class ReassignCommand implements IReassignCommand {

    private PlanningState planningState;

    @Autowired
    private IAdHocTransactionService transactionService;

    @Autowired
    private IResourcesSearcher resourcesSearcher;

    @Autowired
    private ITaskElementDAO taskElementDAO;

    @Autowired
    private ICriterionTypeDAO criterionTypeDAO;

    public interface IConfigurationResult {
        public void result(ReassignConfiguration configuration);
    }

    @Override
    public void setState(PlanningState planningState) {
        Validate.notNull(planningState);
        this.planningState = planningState;
    }

    @Override
    public void doAction(final IContext<TaskElement> context) {
        ReassignController.openOn(context.getRelativeTo(),
                new IConfigurationResult() {
                    @Override
                    public void result(final ReassignConfiguration configuration) {
                        final List<WithAssociatedEntity> reassignations = getReassignations(
                                context, configuration);
                        LongOperationFeedback.progressive(getDesktop(context),
                                reassignations(context, reassignations));
                    }
                });
    }

    private IBackGroundOperation<IDesktopUpdate> reassignations(
            final IContext<TaskElement> context,
            final List<WithAssociatedEntity> reassignations) {
        return new IBackGroundOperation<IDesktopUpdate>() {

            @Override
            public void doOperation(
                    final IDesktopUpdatesEmitter<IDesktopUpdate> updater) {
                updater.doUpdate(busyStart(reassignations.size()));
                GanttDiagramGraph<Task, Dependency>.DeferedNotifier notifications = null;
                try {
                    GanttDiagramGraph<Task, Dependency> ganttDiagramGraph = context
                            .getGanttDiagramGraph();
                    notifications = ganttDiagramGraph
                            .manualNotificationOn(doReassignations(
                                    ganttDiagramGraph, reassignations, updater));
                } finally {
                    if (notifications != null) {
                        // null if error
                        updater.doUpdate(and(doNotifications(notifications),
                                reloadCharts(context), busyEnd(),
                                tellUserOnEnd(context, Messagebox.INFORMATION,
                                        new Callable<String>() {

                                    @Override
                                    public String call() {
                                        return _("{0} reassignations finished",
                                                reassignations.size());
                                    }
                                })));
                    } else {
                        updater.doUpdate(and(busyEnd(),
                                tellUserOnEnd(context, Messagebox.EXCLAMATION,
                                        new Callable<String>() {

                                    @Override
                                    public String call() {
                                        return _("Assignments could not be completed");
                                    }
                                })));
                    }
                }
            }

        };
    }

    private IAction doReassignations(final GanttDiagramGraph<Task, Dependency> diagramGraph,
            final List<WithAssociatedEntity> reassignations,
            final IDesktopUpdatesEmitter<IDesktopUpdate> updater) {
        return new IAction() {

            @Override
            public void doAction() {
                int i = 1;
                final int total = reassignations.size();
                for (final WithAssociatedEntity each : reassignations) {
                    Task ganttTask = each.ganntTask;
                    GanttDate previousStart = ganttTask.getBeginDate();
                    GanttDate previousEnd = ganttTask.getEndDate();

                    transactionService
                            .runOnReadOnlyTransaction(reassignmentTransaction(each));
                    diagramGraph.enforceRestrictions(each.ganntTask);
                    ganttTask.enforceDependenciesDueToPositionPotentiallyModified();
                    ganttTask.updateSizeDueToDateChanges(previousStart, previousEnd);

                    updater.doUpdate(showCompleted(i, total));
                    i++;
                }
            }
        };
    }

    private IDesktopUpdate busyStart(final int total) {
        return new IDesktopUpdate() {
            @Override
            public void doUpdate() {
                Clients.showBusy(_("Doing {0} reassignations", total), true);
            }
        };
    }

    private IDesktopUpdate showCompleted(final int number, final int total) {
        return new IDesktopUpdate() {

            @Override
            public void doUpdate() {
                Clients.showBusy(_("Done {0} of {1}", number, total), true);
            }
        };
    }

    private IDesktopUpdate reloadCharts(final IContext<?> context) {
        return new IDesktopUpdate() {
            @Override
            public void doUpdate() {
                context.reloadCharts();
            }
        };
    }

    private IDesktopUpdate doNotifications(
            final GanttDiagramGraph<Task, Dependency>.DeferedNotifier notifier) {
        return new IDesktopUpdate() {
            @Override
            public void doUpdate() {
                notifier.doNotifications();
            }
        };
    }

    private IDesktopUpdate busyEnd() {
        return new IDesktopUpdate() {

            @Override
            public void doUpdate() {
                Clients.showBusy(null, false);
            }
        };
    }

    private IDesktopUpdate tellUserOnEnd(final IContext<TaskElement> context,
            String icon, final Callable<String> message) {
        // using callable so the message is built inside a zk execution and the
        // locale is correctly retrieved

        return new IDesktopUpdate() {

            @Override
            public void doUpdate() {
                final org.zkoss.zk.ui.Component relativeTo = context
                        .getRelativeTo();
                final String eventName = "onLater";

                Events.echoEvent(eventName, relativeTo, null);

                relativeTo.addEventListener(eventName, new EventListener() {

                    @Override
                    public void onEvent(Event event) {
                        relativeTo.removeEventListener(eventName, this);
                        try {
                            Messagebox.show(resolve(message),
                                    _("Reassignation"),
                                    Messagebox.OK, Messagebox.INFORMATION);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
            }
        };
    }

    private <T> T resolve(Callable<T> callable) {
        try {
            return callable.call();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static class WithAssociatedEntity {
        static WithAssociatedEntity create(
                IDomainAndBeansMapper<TaskElement> mapper, Task each) {
            return new WithAssociatedEntity(mapper
                    .findAssociatedDomainObject(each), each);
        }

        private TaskElement domainEntity;

        private Task ganntTask;

        WithAssociatedEntity(TaskElement domainEntity, Task ganntTask) {
            Validate.notNull(domainEntity);
            Validate.notNull(ganntTask);
            this.domainEntity = domainEntity;
            this.ganntTask = ganntTask;
        }

    }

    private List<WithAssociatedEntity> getReassignations(
            IContext<TaskElement> context, ReassignConfiguration configuration) {
        Validate.notNull(configuration);
        List<Task> taskToReassign = configuration.filterForReassignment(context
                .getTasksOrderedByStartDate());
        return withEntities(context.getMapper(), taskToReassign);
    }

    private List<WithAssociatedEntity> withEntities(
            IDomainAndBeansMapper<TaskElement> mapper,
            List<Task> forReassignment) {
        List<WithAssociatedEntity> result = new ArrayList<WithAssociatedEntity>();
        for (Task each : forReassignment) {
            result.add(WithAssociatedEntity.create(mapper, each));
        }
        return result;
    }

    private IOnTransaction<Void> reassignmentTransaction(
            final WithAssociatedEntity withAssociatedEntity) {
        return new IOnTransaction<Void>() {

            @Override
            public Void execute() {
                reattach(withAssociatedEntity);
                reassign(withAssociatedEntity.domainEntity);
                return null;
            }
        };
    }

    private void reattach(WithAssociatedEntity each) {
        planningState.reassociateResourcesWithSession();
        Set<Long> idsOfTypesAlreadyAttached = new HashSet<Long>();
        taskElementDAO.reattach(each.domainEntity);
        Set<ResourceAllocation<?>> resourceAllocations = each.domainEntity
                .getSatisfiedResourceAllocations();
        List<GenericResourceAllocation> generic = ResourceAllocation.getOfType(
                GenericResourceAllocation.class, resourceAllocations);
        reattachCriterionTypesToAvoidLazyInitializationExceptionOnType(
                idsOfTypesAlreadyAttached, generic);
    }

    private void reattachCriterionTypesToAvoidLazyInitializationExceptionOnType(
            Set<Long> idsOfTypesAlreadyAttached,
            List<GenericResourceAllocation> generic) {
        for (GenericResourceAllocation eachGenericAllocation : generic) {
            Set<Criterion> criterions = eachGenericAllocation.getCriterions();
            for (Criterion eachCriterion : criterions) {
                CriterionType type = eachCriterion.getType();
                if (!idsOfTypesAlreadyAttached.contains(type.getId())) {
                    idsOfTypesAlreadyAttached.add(type.getId());
                    criterionTypeDAO.reattachUnmodifiedEntity(type);
                }
            }
        }
    }

    private void reassign(TaskElement taskElement) {
        org.libreplan.business.planner.entities.Task t = (org.libreplan.business.planner.entities.Task) taskElement;
        t.reassignAllocationsWithNewResources(
                planningState.getCurrentScenario(), resourcesSearcher);
    }

    @Override
    public String getName() {
        return _("Reassign");
    }

    @Override
    public String getImage() {
        return "/common/img/ico_reassign.png";
    }

    private Desktop getDesktop(final IContext<TaskElement> context) {
        return context.getRelativeTo().getDesktop();
    }

    @Override
    public boolean isDisabled() {
        return false;
    }

    @Override
    public boolean isPlannerCommand() {
        return true;
    }

}
TOP

Related Classes of org.libreplan.web.planner.reassign.ReassignCommand$IConfigurationResult

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.