From 4302177cdebca97ff3cb5e1500b5588a2a6ca33e Mon Sep 17 00:00:00 2001 From: Susana Montes Pedreira Date: Wed, 13 Oct 2010 19:09:21 +0200 Subject: [PATCH] It Changes configuration interface to include the creation of the code sequences for each entity. FEA :ItEr61S04NavalPlanEntities --- .../web/common/ConfigurationController.java | 246 +++++++++++++++++- .../web/common/ConfigurationModel.java | 115 +++++++- .../web/common/IConfigurationModel.java | 11 +- .../common/components/panelEntitySequence.zul | 37 +++ .../src/main/webapp/common/configuration.zul | 33 ++- 5 files changed, 425 insertions(+), 17 deletions(-) create mode 100644 navalplanner-webapp/src/main/webapp/common/components/panelEntitySequence.zul diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/ConfigurationController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/ConfigurationController.java index 518569896..c1699c7c4 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/ConfigurationController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/ConfigurationController.java @@ -23,14 +23,18 @@ package org.navalplanner.web.common; import static org.navalplanner.web.I18nHelper._; import java.util.ConcurrentModificationException; +import java.util.HashMap; import java.util.List; import org.navalplanner.business.calendars.entities.BaseCalendar; import org.navalplanner.business.common.entities.Configuration; +import org.navalplanner.business.common.entities.EntityNameEnum; +import org.navalplanner.business.common.entities.EntitySequence; import org.navalplanner.business.common.entities.OrderSequence; import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.web.common.components.bandboxsearch.BandboxSearch; import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; @@ -39,16 +43,20 @@ import org.zkoss.zk.ui.event.SelectEvent; import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zul.Button; import org.zkoss.zul.Checkbox; +import org.zkoss.zul.Grid; import org.zkoss.zul.Intbox; +import org.zkoss.zul.Radio; import org.zkoss.zul.Row; import org.zkoss.zul.RowRenderer; +import org.zkoss.zul.SimpleListModel; +import org.zkoss.zul.Tabpanel; import org.zkoss.zul.Textbox; import org.zkoss.zul.api.Listitem; +import org.zkoss.zul.api.Panel; import org.zkoss.zul.api.Window; /** * Controller for {@link Configuration} entity. - * * @author Manuel Rego Casasnovas */ public class ConfigurationController extends GenericForwardComposer { @@ -62,6 +70,8 @@ public class ConfigurationController extends GenericForwardComposer { private Component messagesContainer; + private Tabpanel panelConfiguration; + private OrderSequenceRowRenderer orderSequenceRowRenderer = new OrderSequenceRowRenderer(); @Override @@ -75,14 +85,61 @@ public class ConfigurationController extends GenericForwardComposer { @Override public void onEvent(Event event) throws Exception { Listitem selectedItem = (Listitem) ((SelectEvent) event) - .getSelectedItems() - .iterator().next(); + .getSelectedItems().iterator().next(); setDefaultCalendar((BaseCalendar) selectedItem .getValue()); } }); messages = new MessagesForUser(messagesContainer); + + createPanelEntityComponents(); + } + + private void createPanelEntityComponents() { + for (final EntityNameEnum entityName : EntityNameEnum.values()) { + Component entitySequenceComponent = Executions.createComponents( + "components/panelEntitySequence.zul", panelConfiguration, + new HashMap()); + initPanelTitle((Panel) entitySequenceComponent, entityName); + initButtonInPanelSequence(entitySequenceComponent, entityName); + initGridInPanelSequence(entitySequenceComponent, entityName); + reloadEntitySequenceList(entityName); + } + } + + private void initPanelTitle(Panel panel, final EntityNameEnum entityName) { + panel.setTitle(_("{0} sequences", entityName.getDescription())); + } + + private void initButtonInPanelSequence(Component component, + final EntityNameEnum entityName) { + String name = entityName.getDescription(); + try { + Button button = (Button) component.getFirstChild().getFirstChild() + .getFirstChild(); + button.setLabel(_("New {0} sequence", name)); + button.addEventListener(Events.ON_CLICK, new EventListener() { + + @Override + public void onEvent(Event event) throws Exception { + addEntitySequence(entityName); + } + }); + } catch (ClassCastException e) { + } + } + + private void initGridInPanelSequence(Component component, + EntityNameEnum entityName) { + String name = entityName.getDescription(); + String id = name + "SequenceList"; + try { + Grid grid = (Grid) component.getFirstChild().getLastChild() + .getFirstChild(); + grid.setId(id); + } catch (ClassCastException e) { + } } public List getCalendars() { @@ -101,6 +158,7 @@ public class ConfigurationController extends GenericForwardComposer { if (ConstraintChecker.isValid(configurationWindow)) { try { configurationModel.confirm(); + configurationModel.init(); messages.showMessage(Level.INFO, _("Changes saved")); reloadWindow(); } catch (ValidationException e) { @@ -121,6 +179,9 @@ public class ConfigurationController extends GenericForwardComposer { private void reloadWindow() { Util.reloadBindings(configurationWindow); + for (EntityNameEnum sequence : EntityNameEnum.values()) { + reloadEntitySequenceList(sequence); + } } public String getCompanyCode() { @@ -183,6 +244,10 @@ public class ConfigurationController extends GenericForwardComposer { generateCodeForMaterialCategories); } + public void reloadGeneralConfiguration() { + reloadWindow(); + } + public Boolean getGenerateCodeForUnitTypes() { return configurationModel.getGenerateCodeForUnitTypes(); } @@ -211,6 +276,15 @@ public class ConfigurationController extends GenericForwardComposer { reloadOrderSequencesList(); } + public void removeEntitySequence(EntitySequence entitySequence) { + try { + configurationModel.removeEntitySequence(entitySequence); + } catch (IllegalArgumentException e) { + messages.showMessage(Level.ERROR, e.getMessage()); + } + reloadEntitySequenceList(entitySequence.getEntityName()); + } + private void reloadOrderSequencesList() { Util .reloadBindings(configurationWindow @@ -386,4 +460,170 @@ public class ConfigurationController extends GenericForwardComposer { return configurationModel.isMonteCarloMethodTabVisible(); } + private void reloadEntitySequenceList(EntityNameEnum entityNameEnum) { + String nameList = entityNameEnum.getDescription(); + Grid grid = (Grid) configurationWindow.getFellow(nameList + + "SequenceList"); + grid.setModel(new SimpleListModel(getEntitySequences(entityNameEnum))); + grid.invalidate(); + } + + public EntitySequenceRowRenderer getEntitySequenceRowRenderer() { + return new EntitySequenceRowRenderer(); + } + + private class EntitySequenceRowRenderer implements RowRenderer { + + @Override + public void render(Row row, Object data) throws Exception { + EntitySequence entitySequence = (EntitySequence) data; + row.setValue(entitySequence); + + appendActiveRadiobox(row, entitySequence); + appendPrefixTextbox(row, entitySequence); + appendNumberOfDigitsInbox(row, entitySequence); + appendLastValueInbox(row, entitySequence); + appendOperations(row, entitySequence); + } + + private void appendActiveRadiobox(final Row row, + final EntitySequence entitySequence) { + final Radio radiobox = Util.bind(new Radio(), + new Util.Getter() { + + @Override + public Boolean get() { + return entitySequence.isActive(); + } + }, new Util.Setter() { + + @Override + public void set(Boolean value) { + entitySequence.setActive(value); + updateOtherSequences(entitySequence); + } + }); + + row.appendChild(radiobox); + + if (entitySequence.isActive()) { + radiobox.getRadiogroup().setSelectedItem(radiobox); + radiobox.getRadiogroup().invalidate(); + } + } + + private void updateOtherSequences(final EntitySequence activeSequence) { + for (EntitySequence sequence : getEntitySequences(activeSequence + .getEntityName())) { + if (sequence.getId() != activeSequence.getId()) { + sequence.setActive(false); + } + } + } + + private void appendPrefixTextbox(Row row, + final EntitySequence entitySequence) { + final Textbox tempTextbox = new Textbox(); + Textbox textbox = Util.bind(tempTextbox, new Util.Getter() { + + @Override + public String get() { + return entitySequence.getPrefix(); + } + }, new Util.Setter() { + + @Override + public void set(String value) { + try { + entitySequence.setPrefix(value); + } catch (IllegalArgumentException e) { + throw new WrongValueException(tempTextbox, e + .getMessage()); + } + } + }); + textbox.setConstraint("no empty:" + _("cannot be null or empty")); + + if (entitySequence.isAlreadyInUse()) { + textbox.setDisabled(true); + } + + row.appendChild(textbox); + } + + private void appendNumberOfDigitsInbox(Row row, + final EntitySequence entitySequence) { + final Intbox tempIntbox = new Intbox(); + Intbox intbox = Util.bind(tempIntbox, new Util.Getter() { + + @Override + public Integer get() { + return entitySequence.getNumberOfDigits(); + } + }, new Util.Setter() { + + @Override + public void set(Integer value) { + try { + entitySequence.setNumberOfDigits(value); + } catch (IllegalArgumentException e) { + throw new WrongValueException(tempIntbox, e + .getMessage()); + } + } + }); + intbox.setConstraint("no empty:" + _("cannot be null or empty")); + + if (entitySequence.isAlreadyInUse()) { + intbox.setDisabled(true); + } + + row.appendChild(intbox); + } + + private void appendLastValueInbox(Row row, + final EntitySequence entitySequence) { + Textbox textbox = Util.bind(new Textbox(), + new Util.Getter() { + + @Override + public String get() { + return EntitySequence.formatValue(entitySequence + .getNumberOfDigits(), entitySequence + .getLastValue()); + } + }); + + row.appendChild(textbox); + } + + private void appendOperations(Row row, + final EntitySequence entitySequence) { + final Button removeButton = Util + .createRemoveButton(new EventListener() { + + @Override + public void onEvent(Event event) throws Exception { + removeEntitySequence(entitySequence); + } + }); + + if (entitySequence.isAlreadyInUse()) { + removeButton.setDisabled(true); + } + + row.appendChild(removeButton); + } + + } + + public void addEntitySequence(EntityNameEnum entityName) { + configurationModel.addEntitySequence(entityName); + reloadEntitySequenceList(entityName); + } + + public List getEntitySequences(EntityNameEnum entityName) { + return configurationModel.getEntitySequences(entityName); + } + } \ No newline at end of file diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/ConfigurationModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/ConfigurationModel.java index 62dcb3661..914a3874d 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/ConfigurationModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/ConfigurationModel.java @@ -22,17 +22,24 @@ package org.navalplanner.web.common; import static org.navalplanner.web.I18nHelper._; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.ConcurrentModificationException; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import org.navalplanner.business.calendars.daos.IBaseCalendarDAO; import org.navalplanner.business.calendars.entities.BaseCalendar; import org.navalplanner.business.common.daos.IConfigurationDAO; +import org.navalplanner.business.common.daos.IEntitySequenceDAO; import org.navalplanner.business.common.daos.IOrderSequenceDAO; import org.navalplanner.business.common.entities.Configuration; +import org.navalplanner.business.common.entities.EntityNameEnum; +import org.navalplanner.business.common.entities.EntitySequence; import org.navalplanner.business.common.entities.OrderSequence; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.common.exceptions.ValidationException; @@ -60,6 +67,8 @@ public class ConfigurationModel implements IConfigurationModel { private List orderSequences; + private Map> entitySequences = new HashMap>(); + @Autowired private IConfigurationDAO configurationDAO; @@ -69,6 +78,9 @@ public class ConfigurationModel implements IConfigurationModel { @Autowired private IOrderSequenceDAO orderSequenceDAO; + @Autowired + private IEntitySequenceDAO entitySequenceDAO; + @Override @Transactional(readOnly = true) public List getCalendars() { @@ -88,6 +100,18 @@ public class ConfigurationModel implements IConfigurationModel { public void init() { this.configuration = getCurrentConfiguration(); this.orderSequences = orderSequenceDAO.getAll(); + initEntitySequences(); + } + + private void initEntitySequences() { + this.entitySequences.clear(); + for (EntityNameEnum entityName : EntityNameEnum.values()) { + entitySequences.put(entityName, new ArrayList()); + } + for (EntitySequence entitySequence : entitySequenceDAO.getAll()) { + entitySequences.get(entitySequence.getEntityName()).add( + entitySequence); + } } private Configuration getCurrentConfiguration() { @@ -119,6 +143,9 @@ public class ConfigurationModel implements IConfigurationModel { @Override @Transactional public void confirm() { + + checkEntitySequences(); + if (orderSequences.isEmpty()) { throw new ValidationException( _("At least one order sequence is needed")); @@ -137,11 +164,37 @@ public class ConfigurationModel implements IConfigurationModel { try { configurationDAO.save(configuration); storeAndRemoveOrderSequences(); + storeAndRemoveEntitySequences(); } catch (HibernateOptimisticLockingFailureException e) { throw new ConcurrentModificationException( _("Some order was created during the configuration process, it is impossible to update order sequence table. Please, try again later")); } + } + private void checkEntitySequences() { + // check if exist at least one sequence for each entity + for (EntityNameEnum entityName : EntityNameEnum.values()) { + String entity = entityName.getDescription(); + List sequences = entitySequences.get(entityName); + if (sequences.isEmpty()) { + throw new ValidationException(_( + "At least one {0} sequence is needed", entity)); + } + + if (!isAnyActive(sequences)) { + throw new ValidationException(_( + "At least one {0} sequence must be active", entity)); + } + } + } + + private boolean isAnyActive(List sequences) { + for (EntitySequence entitySequence : sequences) { + if (entitySequence.isActive()) { + return true; + } + } + return false; } private boolean checkConstraintPrefixNotRepeated() { @@ -174,6 +227,48 @@ public class ConfigurationModel implements IConfigurationModel { } } + private void storeAndRemoveEntitySequences() { + Collection> col_sequences = entitySequences + .values(); + List sequences = new ArrayList(); + for (List list : col_sequences) { + sequences.addAll(list); + } + removeEntitySequences(sequences); + storeEntitySequences(sequences); + } + + public void removeEntitySequences(final List sequences) { + // first one is necessary to remove the deleted sequences. + List toRemove = entitySequenceDAO + .findEntitySquencesNotIn(sequences); + for (final EntitySequence entitySequence : toRemove) { + try { + entitySequenceDAO.remove(entitySequence); + } catch (InstanceNotFoundException e) { + throw new ValidationException( + _("Some sequences to remove not existed")); + } catch (IllegalArgumentException e) { + throw new ValidationException(e.getMessage()); + } + } + } + + public void storeEntitySequences(List sequences) { + // it updates the sequences that are not active first + List toSaveAfter = new ArrayList(); + for (EntitySequence entitySequence : sequences) { + if (entitySequence.isActive()) { + toSaveAfter.add(entitySequence); + } else { + entitySequenceDAO.save(entitySequence); + } + } + for (EntitySequence entitySequence : toSaveAfter) { + entitySequenceDAO.save(entitySequence); + } + } + private boolean checkConstraintJustOneOrderSequenceActive() { boolean someoneActive = false; for (OrderSequence orderSequence : orderSequences) { @@ -390,7 +485,6 @@ public class ConfigurationModel implements IConfigurationModel { return configuration.isExpandOrderPlanningViewCharts(); } - @Override public void setExpandResourceLoadViewCharts( Boolean expandResourceLoadViewCharts) { @@ -408,4 +502,23 @@ public class ConfigurationModel implements IConfigurationModel { return configuration.isExpandResourceLoadViewCharts(); } + public List getEntitySequences(EntityNameEnum entityName) { + return entitySequences.get(entityName); + } + + public void addEntitySequence(EntityNameEnum entityName) { + List sequences = entitySequences.get(entityName); + EntitySequence entitySequence = EntitySequence.create("", entityName); + if (sequences.isEmpty()) { + entitySequence.setActive(true); + } + sequences.add(entitySequence); + } + + public void removeEntitySequence(EntitySequence entitySequence) + throws IllegalArgumentException { + entitySequences.get(entitySequence.getEntityName()).remove( + entitySequence); + } + } \ No newline at end of file diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/IConfigurationModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/IConfigurationModel.java index 326348d3d..91c6bb66a 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/IConfigurationModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/IConfigurationModel.java @@ -20,10 +20,15 @@ package org.navalplanner.web.common; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import org.navalplanner.business.calendars.entities.BaseCalendar; +import org.navalplanner.business.common.entities.EntityNameEnum; +import org.navalplanner.business.common.entities.EntitySequence; import org.navalplanner.business.common.entities.OrderSequence; +import org.springframework.transaction.annotation.Transactional; /** * Contract for {@link ConfigurationModel}. @@ -76,6 +81,11 @@ public interface IConfigurationModel { void removeOrderSequence(OrderSequence orderSequence) throws IllegalArgumentException; + List getEntitySequences(EntityNameEnum entityName); + void addEntitySequence(EntityNameEnum entityName); + void removeEntitySequence(EntitySequence entitySequence) + throws IllegalArgumentException; + void setExpandCompanyPlanningViewCharts( Boolean expandCompanyPlanningViewCharts); @@ -102,5 +112,4 @@ public interface IConfigurationModel { Boolean getGenerateCodeForUnitTypes(); void setGenerateCodeForUnitTypes(Boolean generateCodeForUnitTypes); - } diff --git a/navalplanner-webapp/src/main/webapp/common/components/panelEntitySequence.zul b/navalplanner-webapp/src/main/webapp/common/components/panelEntitySequence.zul new file mode 100644 index 000000000..438111b26 --- /dev/null +++ b/navalplanner-webapp/src/main/webapp/common/components/panelEntitySequence.zul @@ -0,0 +1,37 @@ + + + + +