diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/IntegrationEntity.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/IntegrationEntity.java new file mode 100644 index 000000000..984ccdd32 --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/IntegrationEntity.java @@ -0,0 +1,152 @@ +/* + * 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.business.common; + +import java.util.UUID; + +import org.apache.commons.lang.StringUtils; +import org.hibernate.validator.AssertTrue; +import org.hibernate.validator.NotEmpty; +import org.navalplanner.business.common.daos.IIntegrationEntityDAO; +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; + +/** + * Base class for all entities to be sent/received to/from other applications. + * These entities have a "code" attribute, which unlike "id" is unique among + * the applications to be integrated ("id" is only unique inside + * "navalplanner"). + * + * @author Fernando Bellas Permuy + */ +public abstract class IntegrationEntity extends BaseEntity { + + private String code; + + @NotEmpty(message="code not specified") + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + /** + * This creation method must be used when we want to create an instance + * specifying a specific code (e.g. provided by the end-user or an external + * application). + */ + protected static T create( + T integrationEntity, String code) { + + BaseEntity.create(integrationEntity); + integrationEntity.code = code; + + return integrationEntity; + + } + + /** + * This creation method must be used when we want the creation method to + * automatically generate a code. This is a Template method which delegates + * code generation by calling on generateCode(). + */ + protected static T create( + T integrationEntity) { + + BaseEntity.create(integrationEntity); + integrationEntity.code = generateCode(); + + return integrationEntity; + + } + + /** + * This method is called by create(IntegrationEntity). It + * returns an unique String UUID. The current implementation is good enough + * for entities created in test classes. However, concrete classes + * interested in automatically generating descriptive identifiers when + * calling create(IntegrationEntity), will probably redefine + * this method. + */ + protected static String generateCode() { + return UUID.randomUUID().toString(); + } + + /** + * It checks if there exists another integration entity of the same type + * with the same code. This method is a Template method that calls on + * the private method findIntegrationEntityDAO, which in turn + * calls on the abstract method getIntegrationEntityDAO(). + */ + @AssertTrue(message="code is already being used") + public boolean checkConstraintUniqueCode() { + + /* Check if it makes sense to check the constraint .*/ + if (!iCodeSpecified()) { + return true; + } + + /* Check the constraint. */ + IIntegrationEntityDAO + integrationEntityDAO = findIntegrationEntityDAO(); + + if (isNewObject()) { + return !integrationEntityDAO.existsByCodeAnotherTransaction(code); + } else { + try { + IntegrationEntity entity = + integrationEntityDAO.findByCodeAnotherTransaction(code); + return entity.getId().equals(getId()); + } catch (InstanceNotFoundException e) { + return true; + } + } + + } + + /** + * It returns the DAO of this entity. + */ + protected abstract IIntegrationEntityDAO + getIntegrationEntityDAO(); + + private IIntegrationEntityDAO + findIntegrationEntityDAO() { + + IIntegrationEntityDAO + integrationEntityDAO = getIntegrationEntityDAO(); + + if (!integrationEntityDAO.getEntityClass().equals(this.getClass())) { + throw new RuntimeException(this.getClass().getName() + "::" + + "getIntegrationEntityDAO returns an incompatible " + + "DAO: " + integrationEntityDAO.getClass().getName()); + } else { + return integrationEntityDAO; + } + + } + + private boolean iCodeSpecified() { + return !StringUtils.isBlank(code); + } + +} diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/GenericDAOHibernate.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/GenericDAOHibernate.java index d8c30de54..b65992100 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/GenericDAOHibernate.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/GenericDAOHibernate.java @@ -79,6 +79,10 @@ public class GenericDAOHibernate getEntityClass() { + return entityClass; + } + /** * It's necessary to save and validate later. * diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IGenericDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IGenericDAO.java index 27b8c1de5..06f52bebb 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IGenericDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IGenericDAO.java @@ -39,6 +39,8 @@ import org.springframework.dao.OptimisticLockingFailureException; */ public interface IGenericDAO { + public Class getEntityClass(); + /** * It inserts the object passed as a parameter in the ORM session, planning * it for updating (even though it is not modified before or after the call diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IIntegrationEntityDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IIntegrationEntityDAO.java new file mode 100644 index 000000000..f6f88ce69 --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IIntegrationEntityDAO.java @@ -0,0 +1,47 @@ +/* + * 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.business.common.daos; + +import org.navalplanner.business.common.IntegrationEntity; +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; + +/** + * Common DAO interface for all entities used in application integration. All + * DAO interfaces of entities used in application integration must extend from + * this interface. + * + * @author Fernando Bellas Permuy + */ +public interface IIntegrationEntityDAO + extends IGenericDAO { + + public boolean existsByCode(String code); + + public boolean existsByCodeAnotherTransaction(String code); + + public E findByCode(String code) throws InstanceNotFoundException; + + public E findByCodeAnotherTransaction(String code) + throws InstanceNotFoundException; + + public E findExistingEntityByCode(String code); + +} diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IntegrationEntityDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IntegrationEntityDAO.java new file mode 100644 index 000000000..592d772b8 --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IntegrationEntityDAO.java @@ -0,0 +1,92 @@ +/* + * 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.business.common.daos; + +import org.hibernate.criterion.Restrictions; +import org.navalplanner.business.common.IntegrationEntity; +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +/** + * Default implementation of IIntegrationEntityDAO. DAOs of + * entities used in application integration may extend from this interface. + * + * @author Fernando Bellas Permuy + */ +public class IntegrationEntityDAO + extends GenericDAOHibernate implements IIntegrationEntityDAO { + + @Override + public boolean existsByCode(String code) { + + try { + findByCode(code); + return true; + } catch (InstanceNotFoundException e) { + return false; + } + + } + + @Override + @Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW) + public boolean existsByCodeAnotherTransaction(String code) { + return existsByCode(code); + } + + @SuppressWarnings("unchecked") + @Override + public E findByCode(String code) throws InstanceNotFoundException { + + E entity = (E) getSession().createCriteria(getEntityClass()).add( + Restrictions.eq("code", code).ignoreCase()).uniqueResult(); + + if (entity == null) { + throw new InstanceNotFoundException( + code, getEntityClass().getName()); + } else { + return entity; + } + + } + + @Override + @Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW) + public E findByCodeAnotherTransaction(String code) + throws InstanceNotFoundException { + + return findByCode(code); + + } + + @Override + public E findExistingEntityByCode(String code) { + + try { + return findByCode(code); + } catch (InstanceNotFoundException e) { + throw new RuntimeException(e); + } + + } + +} diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionDAO.java index 1e7a73c6f..750bc8e28 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionDAO.java @@ -27,7 +27,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.Criteria; import org.hibernate.criterion.Restrictions; -import org.navalplanner.business.common.daos.GenericDAOHibernate; +import org.navalplanner.business.common.daos.IntegrationEntityDAO; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.resources.entities.Criterion; import org.navalplanner.business.resources.entities.ICriterionType; @@ -46,8 +46,8 @@ import org.springframework.transaction.annotation.Transactional; */ @Repository @Scope(BeanDefinition.SCOPE_SINGLETON) -public class CriterionDAO extends GenericDAOHibernate - implements ICriterionDAO { +public class CriterionDAO extends IntegrationEntityDAO + implements ICriterionDAO { private static final Log log = LogFactory.getLog(CriterionDAO.class); diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionTypeDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionTypeDAO.java index 1ad2b38ca..66fa16edb 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionTypeDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionTypeDAO.java @@ -26,7 +26,7 @@ import java.util.List; import org.apache.commons.lang.Validate; import org.hibernate.Criteria; import org.hibernate.criterion.Restrictions; -import org.navalplanner.business.common.daos.GenericDAOHibernate; +import org.navalplanner.business.common.daos.IntegrationEntityDAO; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.resources.entities.CriterionType; import org.navalplanner.business.resources.entities.ResourceEnum; @@ -41,8 +41,8 @@ import org.springframework.transaction.annotation.Transactional; */ @Component -public class CriterionTypeDAO extends GenericDAOHibernate - implements ICriterionTypeDAO { +public class CriterionTypeDAO extends IntegrationEntityDAO + implements ICriterionTypeDAO { @Override public List findByName(CriterionType criterionType) { diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionDAO.java index ce2447293..0c346fedd 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionDAO.java @@ -22,7 +22,7 @@ package org.navalplanner.business.resources.daos; import java.util.List; -import org.navalplanner.business.common.daos.IGenericDAO; +import org.navalplanner.business.common.daos.IIntegrationEntityDAO; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.resources.entities.Criterion; import org.navalplanner.business.resources.entities.ICriterionType; @@ -33,8 +33,9 @@ import org.springframework.transaction.annotation.Transactional; * * @author Óscar González Fernández * @author Diego Pino García + * @author Fernando Bellas Permuy */ -public interface ICriterionDAO extends IGenericDAO { +public interface ICriterionDAO extends IIntegrationEntityDAO { public void removeByNameAndType(Criterion criterion); diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionTypeDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionTypeDAO.java index a9a1689aa..7664c8cdf 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionTypeDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionTypeDAO.java @@ -23,7 +23,7 @@ package org.navalplanner.business.resources.daos; import java.util.Collection; import java.util.List; -import org.navalplanner.business.common.daos.IGenericDAO; +import org.navalplanner.business.common.daos.IIntegrationEntityDAO; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.resources.entities.CriterionType; import org.navalplanner.business.resources.entities.ResourceEnum; @@ -33,7 +33,8 @@ import org.navalplanner.business.resources.entities.ResourceEnum; * @author Diego Pino Garcia * @author Fernando Bellas Permuy */ -public interface ICriterionTypeDAO extends IGenericDAO { +public interface ICriterionTypeDAO + extends IIntegrationEntityDAO { CriterionType findUniqueByName(String name) throws InstanceNotFoundException; 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 d6fb55f83..1e56a7d7e 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 @@ -32,20 +32,22 @@ import org.hibernate.validator.AssertTrue; import org.hibernate.validator.NotEmpty; import org.hibernate.validator.NotNull; import org.hibernate.validator.Valid; -import org.navalplanner.business.common.BaseEntity; +import org.navalplanner.business.common.IntegrationEntity; +import org.navalplanner.business.common.Registry; import org.navalplanner.business.requirements.entities.CriterionRequirement; +import org.navalplanner.business.resources.daos.ICriterionDAO; /** * A criterion stored in the database
* @author Óscar González Fernández * @author Fernando Bellas Permuy */ -public class Criterion extends BaseEntity implements ICriterion { +public class Criterion extends IntegrationEntity implements ICriterion { - public static Criterion createUnvalidated(String name, CriterionType type, - Criterion parent, boolean active) { + public static Criterion createUnvalidated(String code, String name, + CriterionType type, Criterion parent, boolean active) { - Criterion criterion = create(new Criterion()); + Criterion criterion = create(new Criterion(), code); criterion.name = name; criterion.type = type; @@ -57,26 +59,19 @@ public class Criterion extends BaseEntity implements ICriterion { } public static Criterion create(CriterionType type) { - Criterion criterion = new Criterion(type); - criterion.setNewObject(true); - return criterion; + return create(new Criterion(type)); } public static Criterion create(String name, CriterionType type) { - Criterion criterion = new Criterion(name, type); - criterion.setNewObject(true); - return criterion; + return create(new Criterion(name, type)); } - @NotEmpty(message="criterion name not specified") private String name; - @NotNull(message="criterion type not specified") private CriterionType type; private Criterion parent = null; - @Valid private Set children = new HashSet(); private boolean active = true; @@ -127,6 +122,7 @@ public class Criterion extends BaseEntity implements ICriterion { Interval.range(start, end)).result().isEmpty(); } + @NotEmpty(message="criterion name not specified") public String getName() { return name; } @@ -135,6 +131,7 @@ public class Criterion extends BaseEntity implements ICriterion { this.name = name; } + @NotNull(message="criterion type not specified") public CriterionType getType() { return type; } @@ -163,6 +160,7 @@ public class Criterion extends BaseEntity implements ICriterion { this.parent = parent; } + @Valid public Set getChildren() { return children; } @@ -213,4 +211,9 @@ public class Criterion extends BaseEntity implements ICriterion { criterionRequirement.setCriterion(this); this.criterionRequirements.add(criterionRequirement); } + + @Override + protected ICriterionDAO getIntegrationEntityDAO() { + return Registry.getCriterionDAO(); + } } 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 95113ffea..461dd948e 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 @@ -28,7 +28,7 @@ import org.apache.commons.lang.builder.EqualsBuilder; import org.hibernate.validator.AssertTrue; import org.hibernate.validator.NotEmpty; import org.hibernate.validator.Valid; -import org.navalplanner.business.common.BaseEntity; +import org.navalplanner.business.common.IntegrationEntity; import org.navalplanner.business.common.Registry; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.resources.daos.ICriterionTypeDAO; @@ -41,22 +41,20 @@ import org.springframework.stereotype.Component; * @author Fernando Bellas Permuy */ @Component -public class CriterionType extends BaseEntity implements +public class CriterionType extends IntegrationEntity implements ICriterionType { public static CriterionType create() { - CriterionType criterionType = new CriterionType(); - criterionType.setNewObject(true); - return criterionType; + return create(new CriterionType()); } - public static CriterionType createUnvalidated(String name, + public static CriterionType createUnvalidated(String code, String name, String description, Boolean allowHierarchy, Boolean allowSimultaneousCriterionsPerResource, Boolean enabled, ResourceEnum resource) { - CriterionType criterionType = create(new CriterionType()); + CriterionType criterionType = create(new CriterionType(), code); criterionType.name = name; criterionType.description = description; @@ -71,21 +69,18 @@ public class CriterionType extends BaseEntity implements } public static CriterionType create(String name,String description) { - CriterionType criterionType = new CriterionType(name,description); - criterionType.setNewObject(true); - return criterionType; + return create(new CriterionType(name,description)); } public static CriterionType create(String name,String description, boolean allowHierarchy,boolean allowSimultaneousCriterionsPerResource, boolean enabled,ResourceEnum resource) { - CriterionType criterionType = new CriterionType(name,description, allowHierarchy, - allowSimultaneousCriterionsPerResource,enabled,resource); - criterionType.setNewObject(true); - return criterionType; + + return create(new CriterionType(name,description, allowHierarchy, + allowSimultaneousCriterionsPerResource,enabled,resource)); + } - @NotEmpty(message="criterion type name not specified") private String name; private String description; @@ -98,7 +93,6 @@ public class CriterionType extends BaseEntity implements private ResourceEnum resource = ResourceEnum.getDefault(); - @Valid private Set criterions = new HashSet(); private int numCriterions; @@ -146,6 +140,7 @@ public class CriterionType extends BaseEntity implements } @Override + @NotEmpty(message="criterion type name not specified") public String getName() { return name; } @@ -154,6 +149,7 @@ public class CriterionType extends BaseEntity implements this.name = name; } + @Valid public Set getCriterions() { return criterions; } @@ -378,4 +374,10 @@ public class CriterionType extends BaseEntity implements return !StringUtils.isBlank(name); } + + @Override + protected ICriterionTypeDAO getIntegrationEntityDAO() { + return Registry.getCriterionTypeDAO(); + } + } 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 4681319ab..cdabb89b8 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 @@ -66,6 +66,7 @@ + @@ -110,6 +111,7 @@ + diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTO.java index 728497806..c0d90dbbb 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTO.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTO.java @@ -35,16 +35,33 @@ import javax.xml.bind.annotation.XmlElement; */ public class InstanceConstraintViolationsDTO { + public final static String NUM_ITEM_ATTRIBUTE_NAME = "num-item"; + public final static String CODE_ATTRIBUTE_NAME = + IntegrationEntityDTO.CODE_ATTRIBUTE_NAME; + public final static String ENTITY_TYPE_ATTRIBUTE_NAME = "entity-type"; + + @Deprecated public final static String INSTANCE_ID_ATTRIBUTE_NAME = "instance-id"; + @Deprecated @XmlAttribute(name=INSTANCE_ID_ATTRIBUTE_NAME) public String instanceId; + @XmlAttribute(name=NUM_ITEM_ATTRIBUTE_NAME) + public Long numItem; + + @XmlAttribute(name=CODE_ATTRIBUTE_NAME) + public String code; + + @XmlAttribute(name=ENTITY_TYPE_ATTRIBUTE_NAME) + public String entityType; + @XmlElement(name="constraint-violation") public List constraintViolations; public InstanceConstraintViolationsDTO() {} + @Deprecated public InstanceConstraintViolationsDTO(String instanceId, List constraintViolations) { @@ -53,6 +70,18 @@ public class InstanceConstraintViolationsDTO { } + public InstanceConstraintViolationsDTO( + InstanceConstraintViolationsDTOId instanceId, + List constraintViolations) { + + this.numItem = instanceId.getNumItem(); + this.code = instanceId.getCode(); + this.entityType = instanceId.getEntityType(); + this.constraintViolations = constraintViolations; + + } + + @Deprecated public static InstanceConstraintViolationsDTO create(String instanceId, String message) { @@ -66,6 +95,19 @@ public class InstanceConstraintViolationsDTO { } + public static InstanceConstraintViolationsDTO create( + InstanceConstraintViolationsDTOId instanceId, String message) { + + List constraintViolations = + new ArrayList(); + + constraintViolations.add(new ConstraintViolationDTO(null, message)); + + return new InstanceConstraintViolationsDTO(instanceId, + constraintViolations); + + } + @Override public String toString() { @@ -75,6 +117,12 @@ public class InstanceConstraintViolationsDTO { printWriter.println("** " + INSTANCE_ID_ATTRIBUTE_NAME + " = " + instanceId + " **"); + printWriter.println("** " + + NUM_ITEM_ATTRIBUTE_NAME + " = " + numItem + " - " + + CODE_ATTRIBUTE_NAME + " = " + code + " - " + + ENTITY_TYPE_ATTRIBUTE_NAME + " = " + entityType + + " **"); + for (ConstraintViolationDTO i : constraintViolations) { printWriter.println(i); } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTOId.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTOId.java new file mode 100644 index 000000000..08ebed23a --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTOId.java @@ -0,0 +1,55 @@ +/* + * 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.ws.common.api; + +/** + * Identifier for an instance causing a list of constraint violations. + * + * @author Fernando Bellas Permuy + */ +public class InstanceConstraintViolationsDTOId { + + private Long numItem; + private String code; + private String entityType; + + public InstanceConstraintViolationsDTOId(Long numItem, String code, + String entityType) { + + this.numItem = numItem; + this.code = code; + this.entityType = entityType; + + } + + public Long getNumItem() { + return numItem; + } + + public String getCode() { + return code; + } + + public String getEntityType() { + return entityType; + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/IntegrationEntityDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/IntegrationEntityDTO.java new file mode 100644 index 000000000..b37432465 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/IntegrationEntityDTO.java @@ -0,0 +1,62 @@ +/* + * 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.ws.common.api; + +import java.util.UUID; + +import javax.xml.bind.annotation.XmlAttribute; + +/** + * DTO for IntegrationEntity. All DTOs corresponding to entities + * to be used in application integration must extend from this DTO. + * + * @author Fernando Bellas Permuy + */ +public abstract class IntegrationEntityDTO { + + public final static String CODE_ATTRIBUTE_NAME = "code"; + + @XmlAttribute(name=CODE_ATTRIBUTE_NAME) + public String code; + + public IntegrationEntityDTO() {} + + public IntegrationEntityDTO(String code) { + this.code = code; + } + + + /** + * It returns the String to use in + * InstanceConstraintViolationsDTOId.entityType. + */ + public abstract String getEntityType(); + + /** + * This method is useful to implement constructors (in subclasses) that + * automatically generate a unique code. Such constructors are useful for + * the implementation of test cases that add new instances (such instances + * will have a unique code). + */ + protected static String generateCode() { + return UUID.randomUUID().toString(); + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/ConstraintViolationConverter.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/ConstraintViolationConverter.java index 7640ea454..e432563c4 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/ConstraintViolationConverter.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/ConstraintViolationConverter.java @@ -26,6 +26,7 @@ import java.util.List; import org.hibernate.validator.InvalidValue; import org.navalplanner.ws.common.api.ConstraintViolationDTO; import org.navalplanner.ws.common.api.InstanceConstraintViolationsDTO; +import org.navalplanner.ws.common.api.InstanceConstraintViolationsDTOId; /** * Converter for constraint violations. @@ -58,6 +59,7 @@ public class ConstraintViolationConverter { } + @Deprecated public final static InstanceConstraintViolationsDTO toDTO(String instanceId, InvalidValue[] invalidValues) { @@ -73,4 +75,20 @@ public class ConstraintViolationConverter { } + public final static InstanceConstraintViolationsDTO toDTO( + InstanceConstraintViolationsDTOId instanceId, + InvalidValue[] invalidValues) { + + List constraintViolationDTOs = + new ArrayList(); + + for (InvalidValue i : invalidValues) { + constraintViolationDTOs.add(toDTO(i)); + } + + return new InstanceConstraintViolationsDTO(instanceId, + constraintViolationDTOs); + + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/Util.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/Util.java index 06fbd220e..6b8581e56 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/Util.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/Util.java @@ -25,14 +25,28 @@ import java.io.StringWriter; import org.apache.cxf.common.util.Base64Utility; import org.apache.cxf.jaxrs.client.WebClient; +import org.navalplanner.ws.common.api.InstanceConstraintViolationsDTOId; +import org.navalplanner.ws.common.api.IntegrationEntityDTO; /** * Utilities class related with web service. * * @author Manuel Rego Casasnovas + * @author Fernando Bellas Permuy */ public class Util { + public static InstanceConstraintViolationsDTOId + generateInstanceConstraintViolationsDTOId(Long numItem, + IntegrationEntityDTO integrationEntityDTO) { + + return new InstanceConstraintViolationsDTOId(numItem, + integrationEntityDTO.code, + integrationEntityDTO.getEntityType()); + + } + + @Deprecated public static String generateInstanceId(int instanceNumber, String instanceIdentifier) { String instanceId = instanceNumber + ""; diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/api/CriterionDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/api/CriterionDTO.java index 798c9866b..56c189fc5 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/api/CriterionDTO.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/api/CriterionDTO.java @@ -27,12 +27,16 @@ import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; +import org.navalplanner.ws.common.api.IntegrationEntityDTO; + /** * DTO for Criterion entity. * * @author Fernando Bellas Permuy */ -public class CriterionDTO { +public class CriterionDTO extends IntegrationEntityDTO { + + public final static String ENTITY_TYPE = "criterion"; @XmlAttribute public String name; @@ -46,13 +50,31 @@ public class CriterionDTO { public CriterionDTO() {} - public CriterionDTO(String name, boolean active, + public CriterionDTO(String code, String name, boolean active, List children) { + super(code); this.name = name; this.active = active; this.children = children; } + /** + * This constructor automatically generates a unique code. It is intended + * to facilitate the implementation of test cases that add new instances + * (such instances will have a unique code). + */ + public CriterionDTO(String name, boolean active, + List children) { + + this(generateCode(), name, active, children); + + } + + @Override + public String getEntityType() { + return ENTITY_TYPE; + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/api/CriterionTypeDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/api/CriterionTypeDTO.java index 2b8e7211f..eed20c505 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/api/CriterionTypeDTO.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/api/CriterionTypeDTO.java @@ -27,6 +27,7 @@ import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; +import org.navalplanner.ws.common.api.IntegrationEntityDTO; import org.navalplanner.ws.common.api.ResourceEnumDTO; /** @@ -34,7 +35,9 @@ import org.navalplanner.ws.common.api.ResourceEnumDTO; * * @author Fernando Bellas Permuy */ -public class CriterionTypeDTO { +public class CriterionTypeDTO extends IntegrationEntityDTO { + + public final static String ENTITY_TYPE = "criterion-type"; @XmlAttribute public String name; @@ -60,11 +63,12 @@ public class CriterionTypeDTO { public CriterionTypeDTO() {} - public CriterionTypeDTO(String name, String description, + public CriterionTypeDTO(String code, String name, String description, boolean allowHierarchy, boolean allowSimultaneousCriterionsPerResource, boolean enabled, ResourceEnumDTO resource, List criterions) { + super(code); this.name = name; this.description = description; this.allowHierarchy = allowHierarchy; @@ -76,4 +80,25 @@ public class CriterionTypeDTO { } + /** + * This constructor automatically generates a unique code. It is intended + * to facilitate the implementation of test cases that add new instances + * (such instances will have a unique code). + */ + public CriterionTypeDTO(String name, String description, + boolean allowHierarchy, boolean allowSimultaneousCriterionsPerResource, + boolean enabled, ResourceEnumDTO resource, + List criterions) { + + this(generateCode(), name, description, allowHierarchy, + allowSimultaneousCriterionsPerResource, enabled, resource, + criterions); + + } + + @Override + public String getEntityType() { + return ENTITY_TYPE; + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionConverter.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionConverter.java index 00ef6d99b..f8924edfc 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionConverter.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionConverter.java @@ -70,6 +70,7 @@ public final class CriterionConverter { } return new CriterionTypeDTO( + criterionType.getCode(), criterionType.getName(), criterionType.getDescription(), criterionType.allowHierarchy(), @@ -93,8 +94,8 @@ public final class CriterionConverter { childrenDTOs = null; } - return new CriterionDTO(criterion.getName(), criterion.isActive(), - childrenDTOs); + return new CriterionDTO(criterion.getCode(), criterion.getName(), + criterion.isActive(), childrenDTOs); } @@ -102,6 +103,7 @@ public final class CriterionConverter { CriterionTypeDTO criterionTypeDTO) { CriterionType criterionType = CriterionType.createUnvalidated( + StringUtils.trim(criterionTypeDTO.code), StringUtils.trim(criterionTypeDTO.name), StringUtils.trim(criterionTypeDTO.description), criterionTypeDTO.allowHierarchy, @@ -139,6 +141,7 @@ public final class CriterionConverter { Criterion criterionParent) { Criterion criterion = Criterion.createUnvalidated( + StringUtils.trim(childDTO.code), StringUtils.trim(childDTO.name), criterionType, criterionParent, childDTO.active); diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionServiceREST.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionServiceREST.java index 808163236..4f5f52a70 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionServiceREST.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionServiceREST.java @@ -76,7 +76,7 @@ public class CriterionServiceREST implements ICriterionService { List instanceConstraintViolationsList = new ArrayList(); - int instanceNumber = 1; + Long numItem = new Long(1); Set criterionTypeNames = new HashSet(); /* Process criterion types. */ @@ -98,8 +98,8 @@ public class CriterionServiceREST implements ICriterionService { instanceConstraintViolationsDTO = InstanceConstraintViolationsDTO.create( - Util.generateInstanceId(instanceNumber, - criterionTypeDTO.name), + Util.generateInstanceConstraintViolationsDTOId(numItem, + criterionTypeDTO), _("criterion type name is used by another criterion " + "type being imported")); @@ -138,8 +138,8 @@ public class CriterionServiceREST implements ICriterionService { } catch (ValidationException e) { instanceConstraintViolationsDTO = ConstraintViolationConverter.toDTO( - Util.generateInstanceId(instanceNumber, - criterionTypeDTO.name), + Util.generateInstanceConstraintViolationsDTOId( + numItem, criterionTypeDTO), e.getInvalidValues()); } @@ -151,7 +151,7 @@ public class CriterionServiceREST implements ICriterionService { instanceConstraintViolationsDTO); } - instanceNumber++; + numItem++; } diff --git a/scripts/rest-clients/criterion-types-sample.xml b/scripts/rest-clients/criterion-types-sample.xml index 4006f58f3..b270cf83d 100644 --- a/scripts/rest-clients/criterion-types-sample.xml +++ b/scripts/rest-clients/criterion-types-sample.xml @@ -3,87 +3,87 @@ - - - + + - + - - + + - + - - - + + - + - - + + - + - - + + - + - - - + - - + + - - + + - + @@ -92,19 +92,19 @@ - - + - - + +