ItEr52S10AdaptacionServiciosRESTItEr51S10: Creation and Adapting of MaterialCategoryServiceRest.

This commit is contained in:
Susana Montes Pedreira 2010-03-23 17:05:21 +01:00 committed by Javier Moran Rua
parent ca69d86831
commit 331837adf5
18 changed files with 1260 additions and 50 deletions

View file

@ -23,6 +23,7 @@ package org.navalplanner.business.materials.daos;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.navalplanner.business.common.daos.IntegrationEntityDAO;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
@ -88,4 +89,10 @@ public class MaterialCategoryDAO extends IntegrationEntityDAO<MaterialCategory>
return findUniqueByName(name);
}
@Override
public List<MaterialCategory> findAll() {
return getSession().createCriteria(MaterialCategory.class).add(
Restrictions.isNull("parent")).addOrder(Order.asc("code"))
.list();
}
}

View file

@ -22,32 +22,26 @@ package org.navalplanner.business.materials.entities;
import java.math.BigDecimal;
import org.hibernate.validator.AssertTrue;
import org.hibernate.validator.NotEmpty;
import org.apache.commons.lang.StringUtils;
import org.hibernate.validator.NotNull;
import org.navalplanner.business.common.IntegrationEntity;
import org.navalplanner.business.common.Registry;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.materials.daos.IMaterialDAO;
/**
* Material entity
*
* @author Jacobo Aragunde Perez <jaragunde@igalia.com>
*
*/
public class Material extends IntegrationEntity implements Comparable {
@NotEmpty(message = "code not specified")
private String code;
private String description;
private BigDecimal defaultUnitPrice = new BigDecimal(0);
private UnitType unitType;
private boolean disabled;
private Boolean disabled;
@NotNull
private MaterialCategory category = null;
@ -58,11 +52,38 @@ public class Material extends IntegrationEntity implements Comparable {
}
public static Material create(String code) {
return (Material) create(new Material(code));
return (Material) create(new Material(), code);
}
public static Material createUnvalidated(String code, String description,
BigDecimal defaultPrice, Boolean disabled) {
Material material = create(new Material(), code);
material.description = description;
material.defaultUnitPrice = defaultPrice;
material.disabled = disabled;
return material;
}
public void updateUnvalidated(String description,
BigDecimal defaultUnitPrice,
Boolean disabled) {
if (!StringUtils.isBlank(description)) {
this.description = description;
}
if (defaultUnitPrice != null) {
this.defaultUnitPrice = defaultUnitPrice;
}
if (disabled != null) {
this.disabled = disabled;
}
}
protected Material(String code) {
this.code = code;
this.setCode(code);
}
public MaterialCategory getCategory() {
@ -73,14 +94,6 @@ public class Material extends IntegrationEntity implements Comparable {
this.category = category;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
@ -89,11 +102,11 @@ public class Material extends IntegrationEntity implements Comparable {
this.description = description;
}
public boolean getDisabled() {
return disabled;
public Boolean getDisabled() {
return disabled == null ? false : disabled;
}
public void setDisabled(boolean disabled) {
public void setDisabled(Boolean disabled) {
this.disabled = disabled;
}
@ -116,34 +129,7 @@ public class Material extends IntegrationEntity implements Comparable {
@Override
public int compareTo(Object arg0) {
final Material material = (Material) arg0;
return code.compareTo(material.getCode());
}
@AssertTrue(message="materialcode has to be unique. It is already used")
public boolean checkConstraintUniqueCode() {
boolean result;
if (isNewObject()) {
result = !existsMaterialWithTheCode();
} else {
result = isIfExistsTheExistentMaterialThisOne();
}
return result;
}
private boolean existsMaterialWithTheCode() {
IMaterialDAO materialDAO = Registry.getMaterialDAO();
return materialDAO.existsMaterialWithCodeInAnotherTransaction(code);
}
private boolean isIfExistsTheExistentMaterialThisOne() {
IMaterialDAO materialDAO = Registry.getMaterialDAO();
try {
Material material =
materialDAO.findUniqueByCodeInAnotherTransaction(code);
return material.getId().equals(getId());
} catch (InstanceNotFoundException e) {
return true;
}
return getCode().compareTo(material.getCode());
}
@Override

View file

@ -73,6 +73,20 @@ public class MaterialCategory extends IntegrationEntity {
return (MaterialCategory) create(new MaterialCategory(name));
}
public static MaterialCategory createUnvalidated(String code, String name) {
MaterialCategory materialCategory = create(new MaterialCategory(), code);
materialCategory.name = name;
return materialCategory;
}
public void updateUnvalidated(String name) {
if (!StringUtils.isBlank(name)) {
this.name = name;
}
}
protected MaterialCategory(String name) {
this.name = name;
}
@ -163,9 +177,75 @@ public class MaterialCategory extends IntegrationEntity {
}
public MaterialCategory getSubcategoryByCode(String code)
throws InstanceNotFoundException {
if (StringUtils.isBlank(code)) {
throw new InstanceNotFoundException(code, MaterialCategory.class
.getName());
}
for (MaterialCategory s : this.subcategories) {
if (s.getCode().equalsIgnoreCase(StringUtils.trim(code))) {
return s;
}
}
throw new InstanceNotFoundException(code, MaterialCategory.class
.getName());
}
@Override
protected IMaterialCategoryDAO getIntegrationEntityDAO() {
return Registry.getMaterialCategoryDAO();
}
@SuppressWarnings("unused")
@AssertTrue(message = "The subcategories names must be unique.")
public boolean checkConstraintUniqueSubcategoryName() {
Set<String> subcategoriesNames = new HashSet<String>();
for (MaterialCategory mc : this.getAllSubcategories()) {
if (!StringUtils.isBlank(mc.getName())) {
String name = StringUtils.deleteWhitespace(mc.getName()
.toLowerCase());
if (subcategoriesNames.contains(name)) {
return false;
} else {
subcategoriesNames.add(name);
}
}
}
return true;
}
@AssertTrue
public boolean checkConstraintNonRepeatedMaterialCategoryCodes() {
Set<MaterialCategory> allSubcategories = getAllSubcategories();
allSubcategories.add(this);
return getFirstRepeatedCode(allSubcategories) == null;
}
private Set<MaterialCategory> getAllSubcategories() {
Set<MaterialCategory> result = new HashSet<MaterialCategory>(
subcategories);
for (MaterialCategory subcategory : subcategories) {
result.addAll(subcategory.getAllSubcategories());
}
return result;
}
@AssertTrue
public boolean checkConstraintNonRepeatedMaterialCodes() {
Set<Material> allMaterials = getAllMaterials();
return getFirstRepeatedCode(allMaterials) == null;
}
private Set<Material> getAllMaterials() {
Set<Material> result = new HashSet<Material>(materials);
for (MaterialCategory subcategory : subcategories) {
result.addAll(subcategory.getAllMaterials());
}
return result;
}
}

View file

@ -33,6 +33,10 @@ import org.navalplanner.business.materials.daos.IUnitTypeDAO;
*/
public class UnitType extends IntegrationEntity{
public static UnitType create(String code, String measure) {
return (UnitType) create(new UnitType(measure), code);
}
public static UnitType create(String measure) {
return (UnitType) create(new UnitType(measure));
}

View file

@ -0,0 +1,36 @@
/*
* This file is part of NavalPlan
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.ws.materials.api;
import org.navalplanner.ws.common.api.InstanceConstraintViolationsListDTO;
/**
* Service for managing material-related entities.
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public interface IMaterialService {
public MaterialCategoryListDTO getMaterials();
public InstanceConstraintViolationsListDTO addMaterials(
MaterialCategoryListDTO materialCategoryListDTO);
}

View file

@ -0,0 +1,84 @@
/*
* This file is part of NavalPlan
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.ws.materials.api;
import java.util.ArrayList;
import java.util.List;
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 <code>MaterialCategory</code> entity.
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public class MaterialCategoryDTO extends IntegrationEntityDTO {
public final static String ENTITY_TYPE = "material-category";
@XmlAttribute
public String name;
@XmlAttribute
public String parent;
@XmlElement
public MaterialCategoryListDTO subcategories;
@XmlElementWrapper(name = "material-list")
@XmlElement(name = "material")
public List<MaterialDTO> materials = new ArrayList<MaterialDTO>();
public MaterialCategoryDTO() {
}
public MaterialCategoryDTO(String code, String name, String parent,
MaterialCategoryListDTO subcategories, List<MaterialDTO> materials) {
super(code);
this.name = name;
this.parent = parent;
this.subcategories = subcategories;
this.materials = materials;
}
/**
* 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 MaterialCategoryDTO(String name, String parent,
MaterialCategoryListDTO subcategories, List<MaterialDTO> materials) {
this(generateCode(), name, parent, subcategories, materials);
}
@Override
public String getEntityType() {
return ENTITY_TYPE;
}
}

View file

@ -0,0 +1,49 @@
/*
* This file is part of NavalPlan
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.ws.materials.api;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* DTO for a list of <code>MaterialCategory</code> entities.
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
@XmlRootElement(name = "material-category-list")
public class MaterialCategoryListDTO {
@XmlElement(name = "material-category")
public List<MaterialCategoryDTO> materialCategoryDTOs = new ArrayList<MaterialCategoryDTO>();
public MaterialCategoryListDTO() {
}
public MaterialCategoryListDTO(
List<MaterialCategoryDTO> materialCategoryDTOs) {
if (materialCategoryDTOs != null) {
this.materialCategoryDTOs = materialCategoryDTOs;
}
}
}

View file

@ -0,0 +1,83 @@
/*
* This file is part of NavalPlan
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.ws.materials.api;
import java.math.BigDecimal;
import javax.xml.bind.annotation.XmlAttribute;
import org.navalplanner.ws.common.api.IntegrationEntityDTO;
/**
* DTO for <code>Material</code> entity.
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public class MaterialDTO extends IntegrationEntityDTO {
public final static String ENTITY_TYPE = "material";
@XmlAttribute
public String name;
@XmlAttribute
public String description;
@XmlAttribute
public BigDecimal defaultPrice;
@XmlAttribute
public String unitType;
@XmlAttribute
public Boolean disabled;
public MaterialDTO() {
}
public MaterialDTO(String code, String description,
BigDecimal defaultPrice, String unitType, Boolean disabled) {
super(code);
this.description = description;
this.defaultPrice = defaultPrice;
this.unitType = unitType;
this.disabled = disabled;
}
/**
* 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 MaterialDTO(String description, BigDecimal defaultPrice,
String unitType, Boolean disabled) {
this(generateCode(), description, defaultPrice, unitType, disabled);
}
@Override
public String getEntityType() {
return ENTITY_TYPE;
}
}

View file

@ -0,0 +1,30 @@
/*
* This file is part of NavalPlan
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* Specification of namespace for REST-based services.
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
@javax.xml.bind.annotation.XmlSchema(
elementFormDefault=javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
namespace=WSCommonGlobalNames.REST_NAMESPACE
)
package org.navalplanner.ws.materials.api;
import org.navalplanner.ws.common.api.WSCommonGlobalNames;

View file

@ -0,0 +1,272 @@
/*
* This file is part of NavalPlan
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.ws.materials.impl;
import static org.navalplanner.web.I18nHelper._;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.navalplanner.business.common.Registry;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.materials.entities.Material;
import org.navalplanner.business.materials.entities.MaterialCategory;
import org.navalplanner.business.materials.entities.UnitType;
import org.navalplanner.ws.materials.api.MaterialCategoryDTO;
import org.navalplanner.ws.materials.api.MaterialCategoryListDTO;
import org.navalplanner.ws.materials.api.MaterialDTO;
/**
* Converter from/to material-related entities to/from DTOs.
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public final class MaterialConverter {
private MaterialConverter() {
}
public final static MaterialCategoryDTO toDTO(
MaterialCategory materialCategory) {
// converter the materials
List<MaterialDTO> materialDTOs = new ArrayList<MaterialDTO>();
for (Material m : materialCategory.getMaterials()) {
materialDTOs.add(toDTO(m));
}
if (materialDTOs.isEmpty()) {
materialDTOs = null;
}
// converter the subcategories
MaterialCategoryListDTO subcategories = createSubcategoriesList(materialCategory
.getSubcategories());
// get the parent code
String parentCode = null;
if (materialCategory.getParent() != null) {
parentCode = materialCategory.getParent().getCode();
}
return new MaterialCategoryDTO(materialCategory.getCode(),
materialCategory.getName(), parentCode, subcategories,
materialDTOs);
}
private static MaterialCategoryListDTO createSubcategoriesList(
Set<MaterialCategory> subcategories) {
List<MaterialCategoryDTO> DTOs = new ArrayList<MaterialCategoryDTO>();
for (MaterialCategory m : subcategories) {
DTOs.add(toDTO(m));
}
if (DTOs.isEmpty()) {
return null;
}
return new MaterialCategoryListDTO(DTOs);
}
public final static MaterialDTO toDTO(Material material) {
String unitTypeCode = null;
if (material.getUnitType() != null) {
unitTypeCode = material.getUnitType().getCode();
}
return new MaterialDTO(material.getCode(), material.getDescription(),
material.getDefaultUnitPrice(), unitTypeCode, material
.getDisabled());
}
public final static MaterialCategory toEntity(
MaterialCategoryDTO materialCategoryDTO) {
MaterialCategory materialCategory = toEntityCategory(materialCategoryDTO);
// find the parent
if (materialCategoryDTO.parent != null) {
try {
MaterialCategory parentCategory = Registry
.getMaterialCategoryDAO().findByCode(
materialCategoryDTO.parent);
materialCategory.setParent(parentCategory);
} catch (InstanceNotFoundException e) {
throw new ValidationException(
_("There is no material category with this code"));
}
}
return materialCategory;
}
public final static MaterialCategory toEntityCategory(
MaterialCategoryDTO materialCategoryDTO) {
MaterialCategory materialCategory = MaterialCategory.createUnvalidated(
StringUtils.trim(materialCategoryDTO.code), StringUtils
.trim(materialCategoryDTO.name));
// Create and add the materials
if (materialCategoryDTO.materials != null) {
for (MaterialDTO materialDTO : materialCategoryDTO.materials) {
materialCategory.addMaterial(toEntity(materialDTO));
}
}
// Create and add the subcategories
if (materialCategoryDTO.subcategories != null) {
for (MaterialCategoryDTO subCategoryDTO : materialCategoryDTO.subcategories.materialCategoryDTOs) {
materialCategory.addSubcategory(toEntitySubCategories(
subCategoryDTO, materialCategory));
}
}
return materialCategory;
}
public final static MaterialCategory toEntitySubCategories(
MaterialCategoryDTO materialCategoryDTO, MaterialCategory parent) {
MaterialCategory materialCategory = toEntityCategory(materialCategoryDTO);
// find the parent
if (materialCategoryDTO.parent != null) {
if (!materialCategoryDTO.parent.equalsIgnoreCase(parent.getCode())) {
throw new ValidationException(_("inconsistent parent code."));
}
}
return materialCategory;
}
private static Material toEntity(MaterialDTO materialDTO) {
Material material = Material.createUnvalidated(StringUtils
.trim(materialDTO.code), StringUtils
.trim(materialDTO.description), materialDTO.defaultPrice,
materialDTO.disabled);
if (materialDTO.unitType != null) {
try {
UnitType unitType = Registry.getUnitTypeDAO().findByCode(
materialDTO.unitType);
material.setUnitType(unitType);
} catch (InstanceNotFoundException e) {
material.setUnitType(null);
}
}
return material;
}
public final static void updateMaterialCategory(
MaterialCategory materialCategory,
MaterialCategoryDTO materialCategoryDTO) throws ValidationException {
/* check the parent code */
if (((materialCategoryDTO.parent != null)
&& (materialCategory.getParent() != null)
&& (!materialCategory.getParent().getCode().equalsIgnoreCase(
materialCategoryDTO.parent)))
|| ((!(materialCategoryDTO.parent == null) && (materialCategory
.getParent() == null)))) {
throw new ValidationException(_("inconsistent parent code."));
}
/*
* 1: Update basic properties in existing material category and add new
* materials.
*/
if (materialCategoryDTO.materials != null) {
for (MaterialDTO materialDTO : materialCategoryDTO.materials) {
/* Step 1.1 requires each material DTO to have a code. */
if (StringUtils.isBlank(materialDTO.code)) {
throw new ValidationException(
_("missing code in a material"));
}
try {
Material material = materialCategory
.getMaterialByCode(materialDTO.code);
updateMaterial(material, materialDTO);
} catch (InstanceNotFoundException e) {
materialCategory.addMaterial(toEntity(materialDTO));
}
}
}
/*
* 2: Update basic properties in existing subcategories and add new
* subcategories.
*/
if (materialCategoryDTO.subcategories != null) {
for (MaterialCategoryDTO subcategoryDTO : materialCategoryDTO.subcategories.materialCategoryDTOs) {
/* Step 2.1 requires each subcategory DTO to have a code. */
if (StringUtils.isBlank(subcategoryDTO.code)) {
throw new ValidationException(
_("missing code in a subcategory"));
}
try {
MaterialCategory subcategory = materialCategory
.getSubcategoryByCode(subcategoryDTO.code);
updateMaterialCategory(subcategory, subcategoryDTO);
} catch (InstanceNotFoundException e) {
materialCategory
.addSubcategory(toEntity(subcategoryDTO));
}
}
}
/* 3: Update material category basic properties. */
materialCategory.updateUnvalidated(StringUtils
.trim(materialCategoryDTO.name));
}
public final static void updateMaterial(Material material,
MaterialDTO materialDTO) throws ValidationException {
if (materialDTO.unitType != null) {
try {
UnitType type = Registry.getUnitTypeDAO().findByCode(
materialDTO.unitType);
material.setUnitType(type);
} catch (InstanceNotFoundException e) {
throw new ValidationException(_("unit type code not found"));
}
}
material.updateUnvalidated(StringUtils.trim(materialDTO.description),
materialDTO.defaultPrice, materialDTO.disabled);
}
}

View file

@ -0,0 +1,95 @@
/*
* This file is part of NavalPlan
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.ws.materials.impl;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.navalplanner.business.common.daos.IIntegrationEntityDAO;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.materials.daos.IMaterialCategoryDAO;
import org.navalplanner.business.materials.entities.MaterialCategory;
import org.navalplanner.ws.common.api.InstanceConstraintViolationsListDTO;
import org.navalplanner.ws.common.impl.GenericRESTService;
import org.navalplanner.ws.materials.api.IMaterialService;
import org.navalplanner.ws.materials.api.MaterialCategoryDTO;
import org.navalplanner.ws.materials.api.MaterialCategoryListDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* REST-based implementation of <code>IMaterialService</code>.
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
@Path("/materialcategories/")
@Produces("application/xml")
@Service("materialServiceREST")
public class MaterialServiceREST extends
GenericRESTService<MaterialCategory, MaterialCategoryDTO> implements
IMaterialService {
@Autowired
private IMaterialCategoryDAO materialCategoryDAO;
@Override
@GET
@Transactional(readOnly = true)
public MaterialCategoryListDTO getMaterials() {
return new MaterialCategoryListDTO(findAll());
}
@Override
@POST
@Consumes("application/xml")
public InstanceConstraintViolationsListDTO addMaterials(
MaterialCategoryListDTO materialCategoryListDTO) {
return save(materialCategoryListDTO.materialCategoryDTOs);
}
@Override
protected MaterialCategory toEntity(MaterialCategoryDTO entityDTO) {
return MaterialConverter.toEntity(entityDTO);
}
@Override
protected MaterialCategoryDTO toDTO(MaterialCategory entity) {
return MaterialConverter.toDTO(entity);
}
@Override
protected IIntegrationEntityDAO<MaterialCategory> getIntegrationEntityDAO() {
return materialCategoryDAO;
}
@Override
protected void updateEntity(MaterialCategory entity,
MaterialCategoryDTO entityDTO)
throws ValidationException {
MaterialConverter.updateMaterialCategory(entity, entityDTO);
}
}

View file

@ -73,6 +73,7 @@
<ref bean="typeOfWorkHoursServiceREST"/>
<ref bean="calendarExceptionTypeServiceREST"/>
<ref bean="calendarServiceREST"/>
<ref bean="materialServiceREST"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="runtimeExceptionMapper" />

View file

@ -0,0 +1,384 @@
/*
* This file is part of NavalPlan
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.web.test.ws.materials;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
import static org.navalplanner.web.WebappGlobalNames.WEBAPP_SPRING_CONFIG_FILE;
import static org.navalplanner.web.test.WebappGlobalNames.WEBAPP_SPRING_CONFIG_TEST_FILE;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.hibernate.SessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.navalplanner.business.IDataBootstrap;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.materials.daos.IMaterialCategoryDAO;
import org.navalplanner.business.materials.daos.IMaterialDAO;
import org.navalplanner.business.materials.daos.IUnitTypeDAO;
import org.navalplanner.business.materials.entities.Material;
import org.navalplanner.business.materials.entities.MaterialCategory;
import org.navalplanner.business.materials.entities.UnitType;
import org.navalplanner.ws.common.api.InstanceConstraintViolationsDTO;
import org.navalplanner.ws.materials.api.IMaterialService;
import org.navalplanner.ws.materials.api.MaterialCategoryDTO;
import org.navalplanner.ws.materials.api.MaterialCategoryListDTO;
import org.navalplanner.ws.materials.api.MaterialDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
/**
* Tests for <code>IMaterialService</code>.
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE,
WEBAPP_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_TEST_FILE })
@Transactional
public class MaterialServiceTest {
@Autowired
private SessionFactory sessionFactory;
@Autowired
private IMaterialService materialService;
@Autowired
private IMaterialCategoryDAO materialCategoryDAO;
@Autowired
private IMaterialDAO materialDAO;
@Autowired
private IUnitTypeDAO unitTypeDAO;
@Resource
private IDataBootstrap materialCategoryBootstrap;
@Resource
private IDataBootstrap unitTypeBootstrap;
private String unitTypeCodeA = "unitTypeA";
private String unitTypeCodeB = "unitTypeB";
@Test
@Rollback(false)
public void CreateUnitType() {
UnitType entityA = UnitType.create(unitTypeCodeA, "uninewUnitTypeA");
UnitType entityB = UnitType.create(unitTypeCodeB, "uninewUnitTypeB");
unitTypeDAO.save(entityA);
unitTypeDAO.save(entityB);
unitTypeDAO.flush();
sessionFactory.getCurrentSession().evict(entityA);
sessionFactory.getCurrentSession().evict(entityB);
}
@Test
@Rollback(false)
public void loadRequiredaData() {
materialCategoryBootstrap.loadRequiredData();
unitTypeBootstrap.loadRequiredData();
}
@Test
public void testAddAndGetMaterialCategories() {
/* Build materialCategory (0 constraint violations). */
// Missing material name and the unit type.
MaterialDTO m1 = new MaterialDTO(null, new BigDecimal(13),
unitTypeCodeA, true);
// Missing default unit price
MaterialDTO m2 = new MaterialDTO("material 2", null, unitTypeCodeA,
true);
// Missing unit type
MaterialDTO m3 = new MaterialDTO("material 3", new BigDecimal(13),
null, true);
// Missing unit type, same name
MaterialDTO m4 = new MaterialDTO("material 3", new BigDecimal(13),
unitTypeCodeA, null);
List<MaterialDTO> materialDTOs = new ArrayList<MaterialDTO>();
materialDTOs.add(m1);
materialDTOs.add(m2);
materialDTOs.add(m3);
materialDTOs.add(m4);
MaterialCategoryDTO materialCategoryDTO = new MaterialCategoryDTO(
"categoryA", null, null, materialDTOs);
MaterialCategoryListDTO materialCategoryListDTO = createMaterialCategoryListDTO(materialCategoryDTO);
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = materialService
.addMaterials(materialCategoryListDTO).instanceConstraintViolationsList;
assertTrue(instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 0);
}
@Test
public void testAddMaterialRepeatedCodes() {
/* Build material with same code (1 constraint violations). */
MaterialDTO m1 = new MaterialDTO("CodeA", "material1", new BigDecimal(
13), unitTypeCodeA, true);
MaterialDTO m2 = new MaterialDTO("CodeA", "material2", new BigDecimal(
13), unitTypeCodeA, true);
List<MaterialDTO> materialDTOs = new ArrayList<MaterialDTO>();
materialDTOs.add(m1);
materialDTOs.add(m2);
MaterialCategoryDTO materialCategoryDTO = new MaterialCategoryDTO(
"category1", null, null, materialDTOs);
MaterialCategoryListDTO materialCategoryListDTO = createMaterialCategoryListDTO(materialCategoryDTO);
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = materialService
.addMaterials(materialCategoryListDTO).instanceConstraintViolationsList;
assertTrue(instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 1);
}
@Test
public void testAddValidMaterialCategory() {
/* Build material (0 constraint violations). */
MaterialDTO m1 = new MaterialDTO("CodeM1", "material1", new BigDecimal(
13), unitTypeCodeA, true);
MaterialDTO m2 = new MaterialDTO("CodeM2", "material2", new BigDecimal(
13), unitTypeCodeA, true);
List<MaterialDTO> materialDTOs1 = new ArrayList<MaterialDTO>();
List<MaterialDTO> materialDTOs2 = new ArrayList<MaterialDTO>();
materialDTOs1.add(m1);
materialDTOs2.add(m2);
/* Build material (0 constraint violations). */
MaterialCategoryDTO mc1 = new MaterialCategoryDTO("CodeMC1",
"subCategory1", "mainMaterialCode", null, materialDTOs1);
MaterialCategoryDTO mc2 = new MaterialCategoryDTO("CodeMC2",
"subCategory2", null, null, materialDTOs2);
MaterialCategoryListDTO subCategoryListDTO = createMaterialCategoryListDTO(
mc1, mc2);
/* Build main material category */
MaterialCategoryDTO materialCategoryDTO = new MaterialCategoryDTO(
"mainMaterialCode", "mainCategory1", null, subCategoryListDTO,
null);
MaterialCategoryListDTO materialCategoryListDTO = createMaterialCategoryListDTO(materialCategoryDTO);
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = materialService
.addMaterials(materialCategoryListDTO).instanceConstraintViolationsList;
assertTrue(instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 0);
}
@Test
public void testAddMaterialCategoryWithSameName() {
/* Build material (0 constraint violations). */
MaterialCategoryDTO mc1 = new MaterialCategoryDTO("subMC1",
"subCategory", "subMC2", null, null);
MaterialCategoryListDTO subCategoryListDTOC = createMaterialCategoryListDTO(mc1);
MaterialCategoryDTO mc2 = new MaterialCategoryDTO("subMC2",
"subCategory", null, subCategoryListDTOC, null);
MaterialCategoryListDTO subCategoryListDTOB = createMaterialCategoryListDTO(mc2);
/* Build main material category */
MaterialCategoryDTO materialCategoryDTO = new MaterialCategoryDTO(
"mainMaterialCode", "mainCategory1", null, subCategoryListDTOB,
null);
MaterialCategoryListDTO materialCategoryListDTOA = createMaterialCategoryListDTO(materialCategoryDTO);
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = materialService
.addMaterials(materialCategoryListDTOA).instanceConstraintViolationsList;
assertTrue(instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 1);
}
@Test
public void testAddMaterialCategoryWithInconsistentParent() {
/* Build material (0 constraint violations). */
MaterialCategoryDTO mc1 = new MaterialCategoryDTO("subMCX1",
"subCategoryC", "mainMaterialCode", null, null);
MaterialCategoryListDTO subCategoryListDTOC = createMaterialCategoryListDTO(mc1);
MaterialCategoryDTO mc2 = new MaterialCategoryDTO("subMCX2",
"subCategoryB", null, subCategoryListDTOC, null);
MaterialCategoryListDTO subCategoryListDTOB = createMaterialCategoryListDTO(mc2);
/* Build main material category */
MaterialCategoryDTO materialCategoryDTO = new MaterialCategoryDTO(
"mainMaterialCodeX", "mainCategory1", null,
subCategoryListDTOB,
null);
MaterialCategoryListDTO materialCategoryListDTOA = createMaterialCategoryListDTO(materialCategoryDTO);
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = materialService
.addMaterials(materialCategoryListDTOA).instanceConstraintViolationsList;
assertTrue(instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 1);
}
@Test
public void testAddAndUpdateMaterialCategory() {
/* Build material (0 constraint violations). */
MaterialDTO m1 = new MaterialDTO("M-1", "tornillos",
new BigDecimal(13), unitTypeCodeA, true);
List<MaterialDTO> materialDTOs1 = new ArrayList<MaterialDTO>();
materialDTOs1.add(m1);
MaterialCategoryDTO mc1 = new MaterialCategoryDTO("MC-C", "MC-C",
"MC-B",
null, null);
MaterialCategoryListDTO subCategoryListDTOC = createMaterialCategoryListDTO(mc1);
MaterialCategoryDTO mc2 = new MaterialCategoryDTO("MC-B", "MC-B", null,
subCategoryListDTOC, materialDTOs1);
MaterialCategoryListDTO subCategoryListDTOB = createMaterialCategoryListDTO(mc2);
/* Build main material category */
MaterialCategoryDTO materialCategoryDTO = new MaterialCategoryDTO(
"C-A", "C-A", null, subCategoryListDTOB, null);
MaterialCategoryListDTO materialCategoryListDTOA = createMaterialCategoryListDTO(materialCategoryDTO);
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = materialService
.addMaterials(materialCategoryListDTOA).instanceConstraintViolationsList;
assertTrue(instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 0);
try {
MaterialCategory mc = materialCategoryDAO.findByCode("MC-B");
assertTrue(mc.getMaterials().size() == 1);
assertTrue(mc.getSubcategories().size() == 1);
assertTrue(mc.getName().equalsIgnoreCase("MC-B"));
materialCategoryDAO.flush();
sessionFactory.getCurrentSession().evict(mc);
} catch (InstanceNotFoundException e) {
fail();
}
// Update data
m1 = new MaterialDTO("M-1", "update-tornillos", new BigDecimal(20),
unitTypeCodeB, false);
materialDTOs1 = new ArrayList<MaterialDTO>();
materialDTOs1.add(m1);
mc1 = new MaterialCategoryDTO("MC-C", "update-MC-C", "MC-B", null, null);
subCategoryListDTOC = createMaterialCategoryListDTO(mc1);
mc2 = new MaterialCategoryDTO("MC-B", "update-MC-B", null,
subCategoryListDTOC, materialDTOs1);
subCategoryListDTOB = createMaterialCategoryListDTO(mc2);
/* Build main material category */
materialCategoryDTO = new MaterialCategoryDTO("C-A", "update-C-A",
null, subCategoryListDTOB, null);
materialCategoryListDTOA = createMaterialCategoryListDTO(materialCategoryDTO);
instanceConstraintViolationsList = materialService
.addMaterials(materialCategoryListDTOA).instanceConstraintViolationsList;
assertTrue(instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 0);
try {
MaterialCategory mc = materialCategoryDAO.findByCode("C-A");
MaterialCategory mcb = materialCategoryDAO.findByCode("MC-B");
MaterialCategory mcc = materialCategoryDAO.findByCode("MC-C");
assertTrue(mcb.getMaterials().size() == 1);
assertTrue(mcb.getSubcategories().size() == 1);
assertTrue(mc.getName().equalsIgnoreCase("update-C-A"));
assertTrue(mcb.getName().equalsIgnoreCase("update-MC-B"));
assertTrue(mcc.getName().equalsIgnoreCase("update-MC-C"));
Material m = materialDAO.findByCode("M-1");
assertTrue(m.getDescription().equalsIgnoreCase("update-tornillos"));
assertTrue(m.getDefaultUnitPrice().compareTo(new BigDecimal(20)) == 0);
assertTrue(m.getUnitType().getCode().equals(unitTypeCodeB));
assertTrue(!m.getDisabled());
} catch (InstanceNotFoundException e) {
fail();
}
// invalid parent code. The parent not is updatable
mc1 = new MaterialCategoryDTO("MC-C", "update-MC-C", "C-A", null, null);
subCategoryListDTOC = createMaterialCategoryListDTO(mc1);
/* Build main material category */
materialCategoryDTO = new MaterialCategoryDTO("C-A", "update-C-A",
null, subCategoryListDTOC, null);
materialCategoryListDTOA = createMaterialCategoryListDTO(materialCategoryDTO);
instanceConstraintViolationsList = materialService
.addMaterials(materialCategoryListDTOA).instanceConstraintViolationsList;
assertTrue(instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 1);
/* Build main material category */
materialCategoryDTO = new MaterialCategoryDTO("C-A", "update-C-A",
"XXX", subCategoryListDTOC, null);
materialCategoryListDTOA = createMaterialCategoryListDTO(materialCategoryDTO);
instanceConstraintViolationsList = materialService
.addMaterials(materialCategoryListDTOA).instanceConstraintViolationsList;
assertTrue(instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 1);
}
private MaterialCategoryListDTO createMaterialCategoryListDTO(
MaterialCategoryDTO... materialCategoryDTOs) {
List<MaterialCategoryDTO> materialCategoryList = new ArrayList<MaterialCategoryDTO>();
for (MaterialCategoryDTO c : materialCategoryDTOs) {
materialCategoryList.add(c);
}
return new MaterialCategoryListDTO(materialCategoryList);
}
}

View file

@ -475,7 +475,7 @@ public class OrderElementServiceTest {
List<ConstraintViolationDTO> constraintViolations = instanceConstraintViolationsList
.get(0).constraintViolations;
// Mandatory fields: material code
assertThat(constraintViolations.size(), equalTo(2));
assertThat(constraintViolations.size(), equalTo(1));
assertThat(constraintViolations.get(0).fieldName, mustEnd("code"));
assertThat(orderDAO.getOrders().size(), equalTo(previous));

View file

@ -68,6 +68,32 @@ public class CriterionServiceTest {
@Autowired
private ICriterionTypeDAO criterionTypeDAO;
@Test
public void testAddCriterionWithSameCodeDistinctTypes() {
/* Build criterion type "ct1" (5 constraint violations). */
CriterionDTO c1 = new CriterionDTO("new_c1_code", "new_c1", true,
new ArrayList<CriterionDTO>());
List<CriterionDTO> ct1Criterions = new ArrayList<CriterionDTO>();
ct1Criterions.add(c1);
CriterionTypeDTO ct1 = new CriterionTypeDTO("new_type_A", "desc",
false, true, true, ResourceEnumDTO.RESOURCE, ct1Criterions);
CriterionTypeDTO ct2 = new CriterionTypeDTO("new_type_B", "desc", true,
true, false, ResourceEnumDTO.RESOURCE, null);
/* Criterion type list. */
CriterionTypeListDTO criterionTypes = createCriterionTypeListDTO(ct1,
ct2);
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = criterionService
.addCriterionTypes(criterionTypes).instanceConstraintViolationsList;
assertTrue(instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 1);
}
@Test
public void testAddAndGetCriterionTypes() {

View file

@ -0,0 +1,21 @@
#!/bin/sh
. ./rest-common-env.sh
printf "Login name: "
read loginName
printf "Password: "
read password
if [ "$1" = "--prod" ]; then
baseServiceURL=$PRODUCTION_BASE_SERVICE_URL
certificate=$PRODUCTION_CERTIFICATE
else
baseServiceURL=$DEVELOPMENT_BASE_SERVICE_URL
certificate=$DEVELOPMENT_CERTIFICATE
fi
authorization=`./base64.sh $loginName:$password`
curl -sv -X GET $certificate --header "Authorization: Basic $authorization" \
$baseServiceURL/materialcategories | tidy -xml -i -q -utf8

View file

@ -0,0 +1,33 @@
#!/bin/sh
. ./rest-common-env.sh
printf "Login name: "
read loginName
printf "Password: "
read password
baseServiceURL=$DEVELOPMENT_BASE_SERVICE_URL
certificate=$DEVELOPMENT_CERTIFICATE
for i in "$@"
do
if [ "$i" = "--prod" ]; then
baseServiceURL=$PRODUCTION_BASE_SERVICE_URL
certificate=$PRODUCTION_CERTIFICATE
else
file=$i
fi
done
if [ "$file" = "" ]; then
printf "Missing file\n" 1>&2
exit 1
fi
authorization=`./base64.sh $loginName:$password`
curl -sv -X POST $certificate -d @$file \
--header "Content-type: application/xml" \
--header "Authorization: Basic $authorization" \
$baseServiceURL/materialcategories | tidy -xml -i -q -utf8

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<material-category-list xmlns="http://rest.ws.navalplanner.org">
<material-category name="tornillos" code="60600">
<subcategories>
<material-category parent="60600" name="tornillos 10m"
code="60602" />
<material-category parent="60600" name="tornillos 12m"
code="60603" unitType="ff5fd2a7-b11e-490a-a340-b2a1e2f00726"/>
</subcategories>
<material-list>
<material disabled="false"
unitType="ff5fd2a7-b11e-490a-a340-b2a1e2f00726"
defaultPrice="30.00" description="asdfsdf" code="dafasd" />
</material-list>
</material-category>
<material-category name="tuercas" code="60601" />
<material-category name="Imported materials without category"
code="808" />
</material-category-list>