From 1091ede3cae2f17299ff46ea6497e2b57b6e9f93 Mon Sep 17 00:00:00 2001 From: Fernando Bellas Permuy Date: Sat, 23 Jan 2010 16:28:31 +0100 Subject: [PATCH] ItEr44S17CUImportacionRecursosProductivosItEr43S08: First version of migration of criterion REST service to the new semantics of POST. IMPORTANT: CriterionType and Criterion tables must be removed because they now need "code" column with non-null values. Any row in any other table refering to CriterionType and Criterion instances must also probably be removed. In consequence, it is probably better to remove all databases (navaldev, navaldevtest, navalprod and navalprodtest). This first version does not implement updates yet (only insertions) and does not detect repeated codes in the entities being imported (repeated codes in database are detected). "code" attribute has now been added to entities, and "num-instance" + "code" + "entity-type" attribute has been added to InstanceConstraintViolationsDTO. This effort has been implemented creating reusable classes (to facilitate migration of the rest of services) and with a non-invasive approach (to make possible migrate each service individually and minimize the number of changes to the current code [specially testing code]). Some existing methods/attributes in existing reusable classes (e.g. Util, InstanceConstraintViolationsDTO) have been deprecated (to support migration of services incrementally) and new ones have been implemented. New reusables clases have been implemented: IntegrationEntity (all entities used in application integration must extend from this one), IIntegrationEntityDAO, IntegrationEntityDAO, InstanceConstraintViolationsDTOId (identifier for an instance causing a list of constraint violations), and IntegrationEntityDTO (all entity DTOs must extend from this one). Please, have a look to the JavaDoc of such classes. --- .../business/common/IntegrationEntity.java | 152 ++++++++++++++++++ .../common/daos/GenericDAOHibernate.java | 4 + .../business/common/daos/IGenericDAO.java | 2 + .../common/daos/IIntegrationEntityDAO.java | 47 ++++++ .../common/daos/IntegrationEntityDAO.java | 92 +++++++++++ .../business/resources/daos/CriterionDAO.java | 6 +- .../resources/daos/CriterionTypeDAO.java | 6 +- .../resources/daos/ICriterionDAO.java | 5 +- .../resources/daos/ICriterionTypeDAO.java | 5 +- .../resources/entities/Criterion.java | 31 ++-- .../resources/entities/CriterionType.java | 34 ++-- .../resources/entities/Resources.hbm.xml | 2 + .../api/InstanceConstraintViolationsDTO.java | 48 ++++++ .../InstanceConstraintViolationsDTOId.java | 55 +++++++ .../ws/common/api/IntegrationEntityDTO.java | 62 +++++++ .../impl/ConstraintViolationConverter.java | 18 +++ .../org/navalplanner/ws/common/impl/Util.java | 14 ++ .../resources/criterion/api/CriterionDTO.java | 26 ++- .../criterion/api/CriterionTypeDTO.java | 29 +++- .../criterion/impl/CriterionConverter.java | 7 +- .../criterion/impl/CriterionServiceREST.java | 12 +- .../rest-clients/criterion-types-sample.xml | 70 ++++---- 22 files changed, 640 insertions(+), 87 deletions(-) create mode 100644 navalplanner-business/src/main/java/org/navalplanner/business/common/IntegrationEntity.java create mode 100644 navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IIntegrationEntityDAO.java create mode 100644 navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IntegrationEntityDAO.java create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTOId.java create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/IntegrationEntityDTO.java 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 @@ - - + - - + +