diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java index fb7bc2370..939dfa5ac 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java @@ -174,7 +174,7 @@ public class Criterion extends IntegrationEntity implements ICriterion { } public static Criterion create(CriterionType type) { - return create(new Criterion(type)); + return create(new Criterion(type),""); } public static Criterion create(String name, CriterionType type) { diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java index 31624a352..3fde4afa3 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java @@ -27,11 +27,16 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.hibernate.validator.AssertTrue; import org.hibernate.validator.NotEmpty; +import org.hibernate.validator.NotNull; import org.hibernate.validator.Valid; import org.navalplanner.business.advance.entities.AdvanceAssignment; import org.navalplanner.business.common.IntegrationEntity; import org.navalplanner.business.common.Registry; +import org.navalplanner.business.common.entities.EntitySequence; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.orders.entities.HoursGroup; +import org.navalplanner.business.orders.entities.OrderElement; +import org.navalplanner.business.orders.entities.OrderLine; import org.navalplanner.business.resources.daos.ICriterionTypeDAO; import org.springframework.stereotype.Component; /** @@ -151,6 +156,7 @@ public class CriterionType extends IntegrationEntity implements private Boolean generateCode = false; + private Integer lastCriterionSequenceCode = 0; /** * Constructor for hibernate. Do not use! */ @@ -498,6 +504,10 @@ public class CriterionType extends IntegrationEntity implements this.generateCode = generateCode; } + public boolean isCodeAutogenerated() { + return getGenerateCode() != null && getGenerateCode(); + } + /** * It checks there are no {@link AdvanceAssignment} any criteria of this * {@link CriterionType} has been assigned to any {@link Resource} @@ -520,4 +530,16 @@ public class CriterionType extends IntegrationEntity implements .checkChildrenAssignedToAnyResource(this))); } + @NotNull(message = "last criterion sequence code not specified") + public Integer getLastCriterionSequenceCode() { + return lastCriterionSequenceCode; + } + + public void incrementLastCriterionSequenceCode() { + if (this.lastCriterionSequenceCode == null) { + this.lastCriterionSequenceCode = 0; + } + this.lastCriterionSequenceCode++; + } + } diff --git a/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml b/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml index 9e0b28e47..9d73618cd 100644 --- a/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml +++ b/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml @@ -168,6 +168,7 @@ + diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionAdminController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionAdminController.java index d7e0065b2..e7e2fff08 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionAdminController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionAdminController.java @@ -22,6 +22,7 @@ package org.navalplanner.web.resources.criterion; import static org.navalplanner.web.I18nHelper._; +import java.util.ConcurrentModificationException; import java.util.List; import org.apache.commons.logging.Log; @@ -342,13 +343,14 @@ public class CriterionAdminController extends GenericForwardComposer { public void onCheckGenerateCode(Event e) { CheckEvent ce = (CheckEvent) e; - if(ce.isChecked()) { - //we have to auto-generate the code for new objects - if(((CriterionType)criterionsModel_V2.getCriterionType()).isNewObject()) { - ((CriterionType)criterionsModel_V2.getCriterionType()).setCodeAutogenerated(); - Util.reloadBindings(createComponent); + if (ce.isChecked()) { + try { + // we have to auto-generate the code for new objects + criterionsModel_V2.setCodeAutogenerated(ce.isChecked()); + } catch (ConcurrentModificationException err) { + messagesForUser.showMessage(Level.ERROR, err.getMessage()); } - editionTree.regenerateCodeForUnsavedCriteria(); + Util.reloadBindings(createComponent); } //disable code field in criterion tree controller editionTree.setCriterionCodeEditionDisabled(ce.isChecked()); diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionTreeController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionTreeController.java index fa8271c88..565efd268 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionTreeController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionTreeController.java @@ -396,8 +396,8 @@ public class CriterionTreeController extends GenericForwardComposer { codeEditionDisabled = disabled; } - public void regenerateCodeForUnsavedCriteria() { - getModel().regenerateCodeForUnsavedCriteria(); + public void regenerateCodeForUnsavedCriteria(int numberOfDigits) { + getModel().regenerateCodeForUnsavedCriteria(numberOfDigits); } public void reloadTree(){ diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionTreeModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionTreeModel.java index cb1e0f421..43ff0d010 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionTreeModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionTreeModel.java @@ -34,6 +34,7 @@ import java.util.List; import java.util.Set; import org.hibernate.validator.InvalidValue; +import org.navalplanner.business.common.entities.EntitySequence; import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.resources.entities.Criterion; import org.navalplanner.business.resources.entities.CriterionType; @@ -436,17 +437,33 @@ public class CriterionTreeModel implements ICriterionTreeModel { return false; } - public void regenerateCodeForUnsavedCriteria() { - regenerateCodeForUnsavedCriteria(criterionRootDTO.getChildren()); + public void regenerateCodeForUnsavedCriteria(int numberOfDigits) { + regenerateCodeForUnsavedCriteria(criterionRootDTO.getChildren(), + numberOfDigits); } private void regenerateCodeForUnsavedCriteria( - List criterionDTOs) { - for(CriterionDTO criterionDTO : criterionDTOs){ - if(criterionDTO.getCriterion().isNewObject()) { - criterionDTO.getCriterion().setCodeAutogenerated(); + List criterionDTOs, int numberOfDigits) { + for (CriterionDTO criterionDTO : criterionDTOs) { + Criterion criterion = criterionDTO.getCriterion(); + if ((criterion.getCode() == null) + || (criterion.getCode().isEmpty()) + || (!criterion.getCode() + .startsWith(criterionType.getCode()))) { + setGenerateCode(criterion, numberOfDigits); } - regenerateCodeForUnsavedCriteria(criterionDTO.getChildren()); + regenerateCodeForUnsavedCriteria(criterionDTO.getChildren(), + numberOfDigits); + } + } + + private void setGenerateCode(Criterion criterion, int numberOfDigits) { + if ((criterion.getCode() == null) || (criterion.getCode().isEmpty()) + || (!criterion.getCode().startsWith(criterionType.getCode()))) { + criterionType.incrementLastCriterionSequenceCode(); + String criterionCode = EntitySequence.formatValue(numberOfDigits, + criterionType.getLastCriterionSequenceCode()); + criterion.setCode(criterionType.getCode() + criterionCode); } } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionsModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionsModel.java index 8fd96df97..b803e6977 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionsModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionsModel.java @@ -24,12 +24,19 @@ import static org.navalplanner.web.I18nHelper._; import java.util.ArrayList; import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.commons.lang.Validate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.hibernate.NonUniqueResultException; import org.navalplanner.business.common.daos.IConfigurationDAO; +import org.navalplanner.business.common.daos.IEntitySequenceDAO; +import org.navalplanner.business.common.entities.EntityNameEnum; +import org.navalplanner.business.common.entities.EntitySequence; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.resources.daos.ICriterionDAO; @@ -70,12 +77,21 @@ public class CriterionsModel implements ICriterionsModel { @Autowired private IConfigurationDAO configurationDAO; + @Autowired + private IEntitySequenceDAO entitySequenceDAO; + private CriterionType criterionType; private Criterion criterion; private ICriterionTreeModel criterionTreeModel; + private String oldCodeCriterionType; + + private Map oldCriterionTypeCodeChildren = new HashMap(); + + private Boolean generateCodeOldCriterionType; + @Override @Transactional(readOnly = true) public List getTypes() { @@ -106,15 +122,63 @@ public class CriterionsModel implements ICriterionsModel { @Override @Transactional(readOnly=true) public void prepareForCreate() { - boolean generateCode = configurationDAO.getConfiguration().getGenerateCodeForCriterion(); - if(generateCode) { - this.criterionType = CriterionType.create(); - } - else { - this.criterionType = CriterionType.create(""); + this.criterionType = CriterionType.create(""); + initializeCriterionTypeCode(); + this.criterionTreeModel = new CriterionTreeModel(criterionType); + } + + @Override + @Transactional(readOnly = true) + public void initializeCriterionTypeCode() { + boolean generateCode = configurationDAO.getConfiguration() + .getGenerateCodeForCriterion(); + if (generateCode) { + setDefaultCriterionTypeCode(); } this.criterionType.setGenerateCode(generateCode); - this.criterionTreeModel = new CriterionTreeModel(criterionType); + } + + @Override + public void setCodeAutogenerated(boolean codeAutogenerated) + throws ConcurrentModificationException { + if (criterionType != null) { + if (criterionType.isNewObject()) { + setDefaultCriterionTypeCode(); + } else { + if (isGenerateCodeOldCriterionType()) { + restoreOldCodes(); + } else { + setDefaultCriterionTypeCode(); + } + } + criterionType.setGenerateCode(codeAutogenerated); + } + } + + private void setDefaultCriterionTypeCode() + throws ConcurrentModificationException { + String code = entitySequenceDAO + .getNextEntityCode(EntityNameEnum.CRITERION); + if (code == null) { + throw new ConcurrentModificationException( + _("Could not get criterion type code, please try again later")); + } + this.criterionType.setCode(code); + } + + private void generateCriterionCodes() { + int numberOfDigits = 5; + try { + EntitySequence entitySequence = entitySequenceDAO + .getActiveEntitySequence(EntityNameEnum.CRITERION); + numberOfDigits = entitySequence.getNumberOfDigits(); + } catch (InstanceNotFoundException e) { + throw new RuntimeException(e); + } catch (NonUniqueResultException e) { + throw new RuntimeException(e); + } + + criterionTreeModel.regenerateCodeForUnsavedCriteria(numberOfDigits); } @Override @@ -138,6 +202,25 @@ public class CriterionsModel implements ICriterionsModel { Validate.notNull(criterionType); this.criterionType = getFromDB(criterionType); this.criterionTreeModel = new CriterionTreeModel(this.criterionType); + initOldCodes(); + } + + private void initOldCodes() { + if (criterionType != null) { + setOldCodeCriterionType(criterionType.getCode()); + for (Criterion criterion : criterionType.getCriterions()) { + oldCriterionTypeCodeChildren + .put(criterion, criterion.getCode()); + } + setGenerateCodeOldCriterionType(criterionType.isCodeAutogenerated()); + } + } + + private void restoreOldCodes() { + criterionType.setCode(getOldCodeCriterionType()); + for (Criterion criterion : oldCriterionTypeCodeChildren.keySet()) { + criterion.setCode(oldCriterionTypeCodeChildren.get(criterion)); + } } @Override @@ -147,7 +230,7 @@ public class CriterionsModel implements ICriterionsModel { criterionTypeDAO.remove(criterionType.getId()); } catch (InstanceNotFoundException e) { throw new RuntimeException(e); - } + } } @Transactional(readOnly = true) @@ -173,6 +256,9 @@ public class CriterionsModel implements ICriterionsModel { @Override @Transactional public void saveCriterionType() throws ValidationException { + if (criterionType.isCodeAutogenerated()) { + generateCriterionCodes(); + } criterionTreeModel.saveCriterions(criterionType); criterionTypeDAO.save(criterionType); } @@ -228,6 +314,7 @@ public class CriterionsModel implements ICriterionsModel { public void reloadCriterionType() { this.criterionType = getFromDB(criterionType); this.criterionTreeModel = new CriterionTreeModel(this.criterionType); + this.initOldCodes(); } @Override @@ -247,7 +334,6 @@ public class CriterionsModel implements ICriterionsModel { || (criterion.getChildren().isEmpty() && (numberOfRelatedEntities(criterion) == 0)); } - @Override public void addForRemoval(Criterion criterion) { criterionType.getCriterions().remove(criterion); @@ -264,4 +350,21 @@ public class CriterionsModel implements ICriterionsModel { return true; } + private void setOldCodeCriterionType(String oldCodeCriterionType) { + this.oldCodeCriterionType = oldCodeCriterionType; + } + + private String getOldCodeCriterionType() { + return oldCodeCriterionType; + } + + private void setGenerateCodeOldCriterionType(Boolean generatedCode) { + this.generateCodeOldCriterionType = generatedCode; + } + + private Boolean isGenerateCodeOldCriterionType() { + return (generateCodeOldCriterionType != null) ? generateCodeOldCriterionType + : false; + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/ICriterionTreeModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/ICriterionTreeModel.java index 9d38dc99e..910e017ba 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/ICriterionTreeModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/ICriterionTreeModel.java @@ -30,7 +30,6 @@ import org.navalplanner.business.resources.entities.CriterionType; import org.zkoss.zul.TreeModel; /** - * * @author Susana Montes Pedreira */ public interface ICriterionTreeModel { @@ -69,5 +68,5 @@ public interface ICriterionTreeModel { void unindent(CriterionDTO nodeToIndent); - void regenerateCodeForUnsavedCriteria(); + void regenerateCodeForUnsavedCriteria(int numberOfDigits); } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/ICriterionsModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/ICriterionsModel.java index 5e1d48104..7c93abcec 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/ICriterionsModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/ICriterionsModel.java @@ -21,6 +21,7 @@ package org.navalplanner.web.resources.criterion; import java.util.Collection; +import java.util.ConcurrentModificationException; import java.util.List; import org.navalplanner.business.common.exceptions.ValidationException; @@ -69,10 +70,8 @@ public interface ICriterionsModel { /** * Reloads {@link CriterionType} from DB and all its criterions - * * This method should be call after saveAndContinue() from controller to * synchronize what has been committed to DB after saving and the model - * */ void reloadCriterionType(); @@ -87,4 +86,9 @@ public interface ICriterionsModel { boolean isDeletable(CriterionType criterionType); void addForRemoval(Criterion criterion); + + void initializeCriterionTypeCode(); + + void setCodeAutogenerated(boolean codeAutogenerated) + throws ConcurrentModificationException; }