From aefacfdace4f5120df6bdd9391a5d510cb9c8c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20Gonz=C3=A1lez=20Fern=C3=A1ndez?= Date: Tue, 17 Nov 2009 11:54:47 +0100 Subject: [PATCH] ItEr35S12CUCreacionUnidadesPlanificacionItEr34S12: Removing split task command --- .../business/planner/entities/Task.java | 28 ----- .../planner/entities/TaskElementTest.java | 76 ------------- .../planner/order/IOrderPlanningModel.java | 2 - .../order/OrderPlanningController.java | 10 +- .../web/planner/order/OrderPlanningModel.java | 14 --- .../planner/splitting/ISplitTaskCommand.java | 33 ------ .../web/planner/splitting/ShareBean.java | 90 --------------- .../planner/splitting/SplitTaskCommand.java | 93 ---------------- .../splitting/SplittingController.java | 103 ------------------ .../navalplanner-webapp-spring-config.xml | 1 - .../src/main/webapp/planner/order.zul | 25 ----- 11 files changed, 1 insertion(+), 474 deletions(-) delete mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/ISplitTaskCommand.java delete mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/ShareBean.java delete mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/SplitTaskCommand.java delete mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/SplittingController.java diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/Task.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/Task.java index fbeffb2bb..e4912a868 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/Task.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/Task.java @@ -184,34 +184,6 @@ public class Task extends TaskElement { return hoursGroup.getWorkingHours(); } - public TaskGroup split(int... shares) { - int totalSumOfHours = sum(shares); - if (totalSumOfHours != getWorkHours()) { - throw new IllegalArgumentException( - "the shares don't sum up the work hours"); - } - TaskGroup result = TaskGroup.create(); - result.copyPropertiesFrom(this); - result.shareOfHours = this.shareOfHours; - copyParenTo(result); - for (int i = 0; i < shares.length; i++) { - Task task = Task.createTask(hoursGroup); - task.copyPropertiesFrom(this); - result.addTaskElement(task); - task.shareOfHours = shares[i]; - } - copyDependenciesTo(result); - return result; - } - - private int sum(int[] shares) { - int result = 0; - for (int share : shares) { - result += share; - } - return result; - } - public Set getGenericResourceAllocations() { return new HashSet(ResourceAllocation .getOfType(GenericResourceAllocation.class, diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/TaskElementTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/TaskElementTest.java index ba2139470..bfa407d40 100644 --- a/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/TaskElementTest.java +++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/TaskElementTest.java @@ -135,56 +135,6 @@ public class TaskElementTest { equalTo(0)); } - @Test - public void splittingATaskIntoSeveral() { - HoursGroup hoursGroup = new HoursGroup(); - Task taskBeingSplitted = Task.createTask(hoursGroup); - taskBeingSplitted.setName("prueba"); - taskBeingSplitted.setNotes("blabla"); - taskBeingSplitted.setStartDate(new Date()); - OrderLine orderLine = OrderLine.create(); - hoursGroup.setWorkingHours(100); - orderLine.addHoursGroup(hoursGroup); - taskBeingSplitted.setOrderElement(orderLine); - int[] shares = { 20, 30, 50 }; - TaskGroup taskGroup = taskBeingSplitted.split(shares); - assertThat(taskGroup.getChildren().size(), equalTo(3)); - - checkPopertiesAreKept(taskBeingSplitted, taskGroup); - for (TaskElement taskElement : taskGroup.getChildren()) { - assertThat(taskElement.getOrderElement(), equalTo(taskBeingSplitted - .getOrderElement())); - } - TaskElement first = taskGroup.getChildren().get(0); - checkPopertiesAreKept(taskBeingSplitted, first); - TaskElement second = taskGroup.getChildren().get(1); - checkPopertiesAreKept(taskBeingSplitted, second); - TaskElement third = taskGroup.getChildren().get(2); - checkPopertiesAreKept(taskBeingSplitted, third); - assertThat(first.getWorkHours(), equalTo(20)); - assertThat(second.getWorkHours(), equalTo(30)); - assertThat(third.getWorkHours(), equalTo(50)); - } - - @Test - public void splittingATaskKeepsItsShareOfHoursIfPresent() { - HoursGroup hoursGroup = new HoursGroup(); - Task initial = Task.createTask(hoursGroup); - initial.setName("prueba"); - initial.setNotes("blabla"); - initial.setStartDate(new Date()); - OrderLine orderLine = OrderLine.create(); - hoursGroup.setWorkingHours(100); - orderLine.addHoursGroup(hoursGroup); - initial.setOrderElement(orderLine); - int[] shares = { 50, 50 }; - TaskGroup group = initial.split(shares); - Task t = (Task) group.getChildren().get(0); - TaskGroup childSplittedGroup = t.split(new int[] { 25, 25 }); - assertThat("the work hours must be the same that it had", - childSplittedGroup.getWorkHours(), equalTo(50)); - } - private void checkPopertiesAreKept(TaskElement original, TaskElement result) { assertThat(result.getName(), equalTo(original.getName())); assertThat(result.getNotes(), equalTo(original.getNotes())); @@ -193,32 +143,6 @@ public class TaskElementTest { equalTo(original.getOrderElement())); } - @Test - public void splittingATaskIntoSeveralKeepsDependencies() { - HoursGroup hoursGroup = new HoursGroup(); - TaskGroup root = TaskGroup.create(); - Task taskBeingSplitted = Task.createTask(hoursGroup); - root.addTaskElement(taskBeingSplitted); - taskBeingSplitted.setName("prueba"); - taskBeingSplitted.setNotes("blabla"); - taskBeingSplitted.setStartDate(new Date()); - Task sourceDependencyTask = Task.createTask(new HoursGroup()); - Task destinationDependencyTask = Task.createTask(new HoursGroup()); - addDependenciesForChecking(taskBeingSplitted, sourceDependencyTask, - destinationDependencyTask); - OrderLine orderLine = OrderLine.create(); - hoursGroup.setWorkingHours(100); - orderLine.addHoursGroup(hoursGroup); - taskBeingSplitted.setOrderElement(orderLine); - - int[] shares = { 50, 50 }; - TaskGroup taskResultOfSplit = taskBeingSplitted.split(shares); - assertThat(taskResultOfSplit.getParent(), equalTo(root)); - - checkDependenciesAreKept(taskResultOfSplit, sourceDependencyTask, - destinationDependencyTask); - } - private void checkDependenciesAreKept( TaskElement taskResultOfTransformation, Task sourceDependencyTask, Task destinationDependencyTask) { diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/IOrderPlanningModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/IOrderPlanningModel.java index 2095b96fc..bc1f40683 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/IOrderPlanningModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/IOrderPlanningModel.java @@ -27,7 +27,6 @@ import org.navalplanner.business.planner.entities.TaskElement; import org.navalplanner.web.common.ViewSwitcher; import org.navalplanner.web.planner.allocation.ResourceAllocationController; import org.navalplanner.web.planner.calendar.CalendarAllocationController; -import org.navalplanner.web.planner.splitting.SplittingController; import org.navalplanner.web.planner.taskedition.EditTaskController; import org.zkoss.ganttz.Planner; import org.zkoss.ganttz.extensions.ICommand; @@ -41,7 +40,6 @@ public interface IOrderPlanningModel { ViewSwitcher viewSwitcher, ResourceAllocationController resourceAllocationController, EditTaskController editTaskController, - SplittingController splittingController, CalendarAllocationController calendarAllocationController, List> additional); diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/OrderPlanningController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/OrderPlanningController.java index 2349c9265..99f26fa77 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/OrderPlanningController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/OrderPlanningController.java @@ -30,7 +30,6 @@ import org.navalplanner.business.planner.entities.TaskElement; import org.navalplanner.web.common.ViewSwitcher; import org.navalplanner.web.planner.allocation.ResourceAllocationController; import org.navalplanner.web.planner.calendar.CalendarAllocationController; -import org.navalplanner.web.planner.splitting.SplittingController; import org.navalplanner.web.planner.taskedition.EditTaskController; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; @@ -56,9 +55,6 @@ public class OrderPlanningController implements Composer { @Autowired private ResourceAllocationController resourceAllocationController; - @Autowired - private SplittingController splittingController; - public ResourceAllocationController getResourceAllocationController() { return resourceAllocationController; } @@ -104,10 +100,6 @@ public class OrderPlanningController implements Composer { } } - public SplittingController getSplittingController() { - return splittingController; - } - public CalendarAllocationController getCalendarAllocationController() { return calendarAllocationController; } @@ -128,7 +120,7 @@ public class OrderPlanningController implements Composer { private void updateConfiguration() { model.setConfigurationToPlanner(planner, order, viewSwitcher, resourceAllocationController, editTaskController, - splittingController, calendarAllocationController, additional); + calendarAllocationController, additional); } } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/OrderPlanningModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/OrderPlanningModel.java index 822461ce7..604deb444 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/OrderPlanningModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/OrderPlanningModel.java @@ -53,8 +53,6 @@ import org.navalplanner.web.planner.loadchart.LoadChart; import org.navalplanner.web.planner.loadchart.LoadChartFiller; import org.navalplanner.web.planner.milestone.IAddMilestoneCommand; import org.navalplanner.web.planner.order.ISaveCommand.IAfterSaveListener; -import org.navalplanner.web.planner.splitting.ISplitTaskCommand; -import org.navalplanner.web.planner.splitting.SplittingController; import org.navalplanner.web.planner.taskedition.EditTaskController; import org.navalplanner.web.planner.taskedition.IEditTaskCommand; import org.springframework.beans.factory.annotation.Autowired; @@ -124,7 +122,6 @@ public abstract class OrderPlanningModel implements IOrderPlanningModel { ViewSwitcher switcher, ResourceAllocationController resourceAllocationController, EditTaskController editTaskController, - SplittingController splittingController, CalendarAllocationController calendarAllocationController, List> additional) { Order orderReloaded = reload(order); @@ -138,7 +135,6 @@ public abstract class OrderPlanningModel implements IOrderPlanningModel { configuration.addGlobalCommand(saveCommand); configuration.addCommandOnTask(buildResourceAllocationCommand(resourceAllocationController)); - configuration.addCommandOnTask(buildSplitCommand(splittingController)); configuration.addCommandOnTask(buildMilestoneCommand()); configuration .addCommandOnTask(buildCalendarAllocationCommand(calendarAllocationController)); @@ -197,14 +193,6 @@ public abstract class OrderPlanningModel implements IOrderPlanningModel { return addMilestoneCommand; } - private ISplitTaskCommand buildSplitCommand( - SplittingController splittingController) { - ISplitTaskCommand splitCommand = getSplitCommand(); - splitCommand.setState(planningState); - splitCommand.setSplitWindowController(splittingController); - return splitCommand; - } - private IResourceAllocationCommand buildResourceAllocationCommand( ResourceAllocationController resourceAllocationController) { IResourceAllocationCommand resourceAllocationCommand = getResourceAllocationCommand(); @@ -319,8 +307,6 @@ public abstract class OrderPlanningModel implements IOrderPlanningModel { protected abstract IResourceAllocationCommand getResourceAllocationCommand(); - protected abstract ISplitTaskCommand getSplitCommand(); - protected abstract IAddMilestoneCommand getAddMilestoneCommand(); protected abstract IEditTaskCommand getEditTaskCommand(); diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/ISplitTaskCommand.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/ISplitTaskCommand.java deleted file mode 100644 index fb73be9ea..000000000 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/ISplitTaskCommand.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of ###PROJECT_NAME### - * - * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e - * Desenvolvemento Tecnolóxico de Galicia - * - * 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 . - */ - -package org.navalplanner.web.planner.splitting; - -import org.navalplanner.business.planner.entities.TaskElement; -import org.navalplanner.web.planner.order.PlanningState; -import org.zkoss.ganttz.extensions.ICommandOnTask; - -public interface ISplitTaskCommand extends ICommandOnTask { - - public void setState(PlanningState planningState); - - public void setSplitWindowController(SplittingController splittingController); - -} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/ShareBean.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/ShareBean.java deleted file mode 100644 index b19b16f54..000000000 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/ShareBean.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of ###PROJECT_NAME### - * - * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e - * Desenvolvemento Tecnolóxico de Galicia - * - * 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 . - */ - -package org.navalplanner.web.planner.splitting; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.Validate; - -public class ShareBean { - - public static int[] toHours(ShareBean... shares) { - Validate.noNullElements(shares); - int[] result = new int[shares.length]; - for (int i = 0; i < result.length; i++) { - result[i] = shares[i].getHours(); - } - return result; - } - - public static int sum(Collection shareBeans) { - Validate.noNullElements(shareBeans); - int result = 0; - for (ShareBean shareBean : shareBeans) { - result += shareBean.getHours(); - } - return result; - } - - public static List toShareBeans(String name, int[] hours) { - ArrayList result = new ArrayList(); - for (int i = 0; i < hours.length; i++) { - ShareBean s = new ShareBean(); - s.setName(name + "." + (i + 1)); - s.setHours(hours[i]); - result.add(s); - } - return result; - } - - private String name; - - private Integer hours; - - public ShareBean() { - } - - public String getName() { - return name; - } - - public void setName(String name) { - if (StringUtils.isEmpty(name)) { - return; - } - this.name = name; - } - - public Integer getHours() { - return hours; - } - - public void setHours(Integer share) { - if (share == null || share <= 0) { - return; - } - this.hours = share; - } - -} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/SplitTaskCommand.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/SplitTaskCommand.java deleted file mode 100644 index cbfd78542..000000000 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/SplitTaskCommand.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This file is part of ###PROJECT_NAME### - * - * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e - * Desenvolvemento Tecnolóxico de Galicia - * - * 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 . - */ - -package org.navalplanner.web.planner.splitting; - -import java.util.List; - -import org.navalplanner.business.planner.entities.Task; -import org.navalplanner.business.planner.entities.TaskElement; -import org.navalplanner.business.planner.entities.TaskGroup; -import org.navalplanner.web.planner.order.PlanningState; -import org.navalplanner.web.planner.splitting.SplittingController.IActionOnOk; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.zkoss.ganttz.extensions.IContextWithPlannerTask; - -import static org.navalplanner.web.I18nHelper._; - -@Component -@Scope(BeanDefinition.SCOPE_PROTOTYPE) -public class SplitTaskCommand implements ISplitTaskCommand { - - private PlanningState planningState; - private SplittingController splittingController; - - @Override - public void setState(PlanningState planningState) { - this.planningState = planningState; - } - - @Override - public void doAction(final IContextWithPlannerTask context, - final TaskElement taskElement) { - if (!taskElement.isLeaf()) { - // TODO show some message if this action is not aplyable - return; - } - final Task task = (Task) taskElement; - int[] shares = createTwoEqualShares(taskElement); - splittingController.show( - ShareBean.toShareBeans(task.getName(), shares), task - .getWorkHours(), new IActionOnOk() { - - @Override - public void doOkAction(ShareBean[] shares) { - TaskGroup newGroup = task.split(ShareBean - .toHours(shares)); - List children = newGroup.getChildren(); - for (int i = 0; i < shares.length; i++) { - children.get(i).setName(shares[i].getName()); - } - context.replace(task, newGroup); - planningState.removed(taskElement); - planningState.added(newGroup); - } - }); - } - - private int[] createTwoEqualShares(TaskElement taskElement) { - Integer workHours = taskElement.getWorkHours(); - int half = workHours / 2; - return new int[] { half, half + workHours % 2 }; - } - - @Override - public String getName() { - return _("Split task"); - } - - @Override - public void setSplitWindowController(SplittingController splittingController) { - this.splittingController = splittingController; - } - -} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/SplittingController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/SplittingController.java deleted file mode 100644 index 5cf248ce6..000000000 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/splitting/SplittingController.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * This file is part of ###PROJECT_NAME### - * - * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e - * Desenvolvemento Tecnolóxico de Galicia - * - * 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 . - */ - -package org.navalplanner.web.planner.splitting; - -import java.util.List; - -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.zkoss.zk.ui.WrongValueException; -import org.zkoss.zk.ui.util.Clients; -import org.zkoss.zk.ui.util.GenericForwardComposer; -import org.zkoss.zul.Label; -import org.zkoss.zul.SimpleListModel; -import org.zkoss.zul.Window; -import org.zkoss.zul.api.Grid; - -import static org.navalplanner.web.I18nHelper._; - -@Component -@Scope(BeanDefinition.SCOPE_PROTOTYPE) -public class SplittingController extends GenericForwardComposer { - - private IActionOnOk curentAction; - private Window window; - - private Grid sharesListing; - - private Label totalHoursLabel; - private List sharesList; - private Integer totalHours; - - public interface IActionOnOk { - public void doOkAction(ShareBean[] shares); - } - - public void show(List initialSharesList, Integer totalHours, - IActionOnOk ok) { - this.sharesList = initialSharesList; - this.totalHours = totalHours; - this.curentAction = ok; - this.totalHoursLabel.setValue(totalHours + ""); - this.sharesListing.setModel(new SimpleListModel(initialSharesList)); - showWindow(); - } - - public void onClick$splitOk() { - checkSumIsEqualToTotal(); - Clients.closeErrorBox(totalHoursLabel); - hideWindow(); - curentAction.doOkAction(this.sharesList.toArray(new ShareBean[0])); - } - - private void checkSumIsEqualToTotal() { - int sum = ShareBean.sum(sharesList); - if (sum != totalHours) { - throw new WrongValueException(totalHoursLabel, - _("The sum is not equal: {0}", sum)); - } - } - - public void onClick$splitCancel() { - hideWindow(); - } - - private void showWindow() { - try { - window.setMode("modal"); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - private void hideWindow() { - window.setVisible(false); - } - - @Override - public void doAfterCompose(org.zkoss.zk.ui.Component comp) throws Exception { - super.doAfterCompose(comp); - window = (Window) comp; - - } - -} diff --git a/navalplanner-webapp/src/main/resources/navalplanner-webapp-spring-config.xml b/navalplanner-webapp/src/main/resources/navalplanner-webapp-spring-config.xml index a5d1ab991..dfa2b997f 100644 --- a/navalplanner-webapp/src/main/resources/navalplanner-webapp-spring-config.xml +++ b/navalplanner-webapp/src/main/resources/navalplanner-webapp-spring-config.xml @@ -27,7 +27,6 @@ - diff --git a/navalplanner-webapp/src/main/webapp/planner/order.zul b/navalplanner-webapp/src/main/webapp/planner/order.zul index 0422d8264..13c17351f 100644 --- a/navalplanner-webapp/src/main/webapp/planner/order.zul +++ b/navalplanner-webapp/src/main/webapp/planner/order.zul @@ -29,7 +29,6 @@ - - - - - - - - - - - - - - - - - -