ItEr10S11CUCreacionProxectoCategorizacionTraballo: Created server entities and performs CRUD operations on ProjectWorker.

Javier Moran Rua <jmoran@igalia.com>: Refactorization applied to use package
navalplanner-webapp/src/main/java/org/navalplanner/web/workorders instead of
navalplanner-webapp/src/main/java/org/navalplanner/web/workorder
This commit is contained in:
Óscar González Fernández 2009-05-28 20:19:12 +02:00 committed by Javier Moran Rua
parent 500f658e29
commit cb6527aa99
19 changed files with 701 additions and 6 deletions

View file

@ -4,6 +4,7 @@ import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import org.apache.commons.lang.Validate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
@ -19,19 +20,19 @@ import org.springframework.orm.hibernate3.SessionFactoryUtils;
* An implementation of <code>IGenericDao</code> based on Hibernate's native
* API. Concrete DAOs must extend directly from this class. This constraint is
* imposed by the constructor of this class that must infer the type of the
* entity from the declaration of the concrete DAO. <p/>
*
* entity from the declaration of the concrete DAO.
* <p/>
* This class autowires a <code>SessionFactory</code> bean and allows to
* implement DAOs with Hibernate's native API. Subclasses access Hibernate's
* <code>Session</code> by calling on <code>getSession()</code> method.
* Operations must be implemented by catching <code>HibernateException</code>
* and rethrowing it by using <code>convertHibernateAccessException()</code>
* method. See source code of this class for an example.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
*
* @param <E> Entity class
* @param <PK> Primary key class
* @param <E>
* Entity class
* @param <PK>
* Primary key class
*/
public class GenericDaoHibernate<E, PK extends Serializable> implements
IGenericDao<E, PK> {
@ -47,6 +48,11 @@ public class GenericDaoHibernate<E, PK extends Serializable> implements
.getGenericSuperclass()).getActualTypeArguments()[0];
}
public GenericDaoHibernate(Class<E> entityClass) {
Validate.notNull(entityClass);
this.entityClass = entityClass;
}
protected Session getSession() {
return sessionFactory.getCurrentSession();
}

View file

@ -40,4 +40,8 @@ public class ValidationException extends Exception {
this.invalidValues = invalidValues;
}
public ValidationException(String message) {
this(new InvalidValue[] {}, message);
}
}

View file

@ -0,0 +1,97 @@
package org.navalplanner.business.workorders.entities;
import java.util.Date;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.NotNull;
/**
* It represents a project with its related information. <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public class ProjectWork {
private static Date copy(Date date) {
return date != null ? new Date(date.getTime()) : date;
}
private Long id;
private Long version;
@NotEmpty
private String name;
@NotNull
private Date initDate;
private Date endDate;
private String description;
private String responsible;
// TODO turn into a many to one relationship when Customer entity is defined
private String customer;
public Long getId() {
return id;
}
public Long getVersion() {
return version;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getInitDate() {
return copy(initDate);
}
public void setInitDate(Date initDate) {
this.initDate = initDate;
}
public Date getEndDate() {
return copy(endDate);
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getResponsible() {
return responsible;
}
public void setResponsible(String responsible) {
this.responsible = responsible;
}
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
public boolean isEndDateBeforeStart() {
return endDate != null && endDate.before(initDate);
}
}

View file

@ -0,0 +1,25 @@
package org.navalplanner.business.workorders.services;
import java.util.List;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.workorders.entities.ProjectWork;
/**
* Management of {@link ProjectWork} <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public interface IProjectWorkService {
void save(ProjectWork projectWork) throws ValidationException;
boolean exists(ProjectWork projectWork);
List<ProjectWork> getProjectWorks();
void remove(ProjectWork projectWork) throws InstanceNotFoundException;
ProjectWork find(Long workerId) throws InstanceNotFoundException;
}

View file

@ -0,0 +1,73 @@
package org.navalplanner.business.workorders.services;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.navalplanner.business.common.daos.impl.GenericDaoHibernate;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.workorders.entities.ProjectWork;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* Default implementation of {@link IProjectWorkService} <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
@Transactional
public class ProjectWorkService implements IProjectWorkService {
@Autowired
private SessionFactory sessionFactory;
/*
* Because the dao for project work doesn't have special needs, it's not
* created an interface for defining its contract
*/
private GenericDaoHibernate<ProjectWork, Long> dao = new GenericDaoHibernate<ProjectWork, Long>() {
@Override
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
};
@Override
@Transactional(readOnly = true)
public boolean exists(ProjectWork projectWork) {
return dao.exists(projectWork.getId());
}
@Override
public void save(ProjectWork projectWork) throws ValidationException {
if (projectWork.isEndDateBeforeStart()) {
throw new ValidationException("endDate must be after startDate");
}
dao.save(projectWork);
}
@Override
public List<ProjectWork> getProjectWorks() {
return dao.list(ProjectWork.class);
}
@Override
public ProjectWork find(Long projectWorkId)
throws InstanceNotFoundException {
return dao.find(projectWorkId);
}
@Override
public void remove(ProjectWork projectWork)
throws InstanceNotFoundException {
dao.remove(projectWork.getId());
}
}

View file

@ -23,6 +23,9 @@
<value>
org/navalplanner/business/resources/entities/Resources.hbm.xml
</value>
<value>
org/navalplanner/business/resources/entities/WorkOrders.hbm.xml
</value>
</list>
</property>
</bean>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.navalplanner.business.workorders.entities">
<class name="ProjectWork">
<id access="field" name="id">
<generator class="native" />
</id>
<version name="version" access="field" type="long"/>
<property name="initDate" access="field"></property>
<property name="endDate" access="field"></property>
<property name="name" access="field"></property>
<property name="description" access="field"></property>
<property name="responsible" access="field"></property>
<property name="customer" access="field"></property>
</class>
</hibernate-mapping>

View file

@ -0,0 +1,86 @@
package org.navalplanner.business.test.workorders.services;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.test.resources.daos.CriterionSatisfactionDAOTest;
import org.navalplanner.business.workorders.entities.ProjectWork;
import org.navalplanner.business.workorders.services.IProjectWorkService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
import static org.navalplanner.business.test.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_TEST_FILE;
/**
* Tests for {@link ProjectWork}. <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE,
BUSINESS_SPRING_CONFIG_TEST_FILE })
@Transactional
public class ProjectWorkServiceTest {
private static ProjectWork createValidProjectWork() {
ProjectWork projectWork = new ProjectWork();
projectWork.setDescription("description");
projectWork.setCustomer("blabla");
projectWork.setInitDate(CriterionSatisfactionDAOTest.year(2000));
projectWork.setName("name");
projectWork.setResponsible("responsible");
return projectWork;
}
@Autowired
private IProjectWorkService projectWorkService;
@Test
public void testCreation() throws ValidationException {
ProjectWork projectWork = createValidProjectWork();
projectWorkService.save(projectWork);
assertTrue(projectWorkService.exists(projectWork));
}
@Test
public void testListing() throws Exception {
List<ProjectWork> list = projectWorkService.getProjectWorks();
projectWorkService.save(createValidProjectWork());
assertThat(projectWorkService.getProjectWorks().size(), equalTo(list
.size() + 1));
}
@Test
public void testRemove() throws Exception {
ProjectWork projectWork = createValidProjectWork();
projectWorkService.save(projectWork);
assertTrue(projectWorkService.exists(projectWork));
projectWorkService.remove(projectWork);
assertFalse(projectWorkService.exists(projectWork));
}
@Test(expected = ValidationException.class)
public void shouldSendValidationExceptionIfEndDateIsBeforeThanStartingDate()
throws ValidationException {
ProjectWork projectWork = createValidProjectWork();
projectWork.setEndDate(CriterionSatisfactionDAOTest.year(0));
projectWorkService.save(projectWork);
}
@Test
public void testFind() throws Exception {
ProjectWork projectWork = createValidProjectWork();
projectWorkService.save(projectWork);
assertThat(projectWorkService.find(projectWork.getId()), notNullValue());
}
}

View file

@ -29,6 +29,9 @@
<value>
org/navalplanner/business/resources/entities/Resources.hbm.xml
</value>
<value>
org/navalplanner/business/resources/entities/WorkOrders.hbm.xml
</value>
</list>
</property>

View file

@ -5,6 +5,7 @@ import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.commons.lang.StringUtils;
import org.hibernate.validator.InvalidValue;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.zkoss.zk.ui.Component;
@ -135,6 +136,9 @@ public class MessagesForUser extends GenericForwardComposer implements
for (InvalidValue invalidValue : e.getInvalidValues()) {
invalidValue(invalidValue);
}
if (!StringUtils.isEmpty(e.getMessage())) {
showMessage(Level.INFO, e.getMessage());
}
}
}

View file

@ -0,0 +1,28 @@
package org.navalplanner.web.workorders;
import java.util.List;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.workorders.entities.ProjectWork;
/**
* Contract for {@link ProjectWorkModel}<br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public interface IProjectWorkModel {
List<ProjectWork> getProjects();
void prepareEditFor(ProjectWork project);
void prepareForCreate();
void save() throws ValidationException;
ProjectWork getProject();
void remove(ProjectWork projectWork);
void prepareForRemove(ProjectWork project);
}

View file

@ -0,0 +1,133 @@
package org.navalplanner.web.workorders;
import java.util.List;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.workorders.entities.ProjectWork;
import org.navalplanner.web.common.IMessagesForUser;
import org.navalplanner.web.common.Level;
import org.navalplanner.web.common.MessagesForUser;
import org.navalplanner.web.common.OnlyOneVisible;
import org.navalplanner.web.common.Util;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.api.Window;
/**
* Controller for CRUD actions <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public class ProjectWorkCRUDController extends GenericForwardComposer {
private IProjectWorkModel projectWorkModel;
private IMessagesForUser messagesForUser;
private Component messagesContainer;
private Component editWindow;
private Component createWindow;
private Component listWindow;
private OnlyOneVisible cachedOnlyOneVisible;
private Window confirmRemove;
public List<ProjectWork> getProjects() {
return projectWorkModel.getProjects();
}
private OnlyOneVisible getVisibility() {
if (cachedOnlyOneVisible == null) {
cachedOnlyOneVisible = new OnlyOneVisible(listWindow, editWindow,
createWindow);
}
return cachedOnlyOneVisible;
}
public ProjectWork getProject() {
return projectWorkModel.getProject();
}
public void save() {
try {
projectWorkModel.save();
messagesForUser.showMessage(Level.INFO, "proxecto gardado");
goToList();
} catch (ValidationException e) {
messagesForUser.showInvalidValues(e);
}
}
private void goToList() {
Util.reloadBindings(listWindow);
getVisibility().showOnly(listWindow);
}
public void cancel() {
goToList();
}
public void confirmRemove(ProjectWork project) {
projectWorkModel.prepareForRemove(project);
showConfirmingWindow();
}
public void cancelRemove() {
confirmingRemove = false;
confirmRemove.setVisible(false);
Util.reloadBindings(confirmRemove);
}
private boolean confirmingRemove = false;
public boolean isConfirmingRemove() {
return confirmingRemove;
}
private void hideConfirmingWindow() {
confirmingRemove = false;
Util.reloadBindings(confirmRemove);
}
private void showConfirmingWindow() {
confirmingRemove = true;
try {
Util.reloadBindings(confirmRemove);
confirmRemove.doModal();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void goToEditForm(ProjectWork project) {
projectWorkModel.prepareEditFor(project);
getVisibility().showOnly(editWindow);
Util.reloadBindings(editWindow);
}
public void remove(ProjectWork projectWork) {
projectWorkModel.remove(projectWork);
hideConfirmingWindow();
Util.reloadBindings(listWindow);
messagesForUser.showMessage(Level.INFO, "removed "
+ projectWork.getName());
}
public void goToCreateForm() {
projectWorkModel.prepareForCreate();
getVisibility().showOnly(createWindow);
Util.reloadBindings(createWindow);
}
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
messagesForUser = new MessagesForUser(messagesContainer);
comp.setVariable("controller", this, true);
getVisibility().showOnly(listWindow);
}
}

View file

@ -0,0 +1,92 @@
package org.navalplanner.web.workorders;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang.Validate;
import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.workorders.entities.ProjectWork;
import org.navalplanner.business.workorders.services.IProjectWorkService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* Model for UI operations related to {@link ProjectWork}. <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class ProjectWorkModel implements IProjectWorkModel {
private final IProjectWorkService projectService;
private ProjectWork project;
private ClassValidator<ProjectWork> projectValidator = new ClassValidator<ProjectWork>(
ProjectWork.class);
@Autowired
public ProjectWorkModel(IProjectWorkService projectService) {
Validate.notNull(projectService);
this.projectService = projectService;
}
@Override
@Transactional(readOnly = true)
public List<ProjectWork> getProjects() {
return projectService.getProjectWorks();
}
@Override
@Transactional(readOnly = true)
public void prepareEditFor(ProjectWork project) {
Validate.notNull(project);
try {
this.project = projectService.find(project.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
public void prepareForCreate() {
this.project = new ProjectWork();
this.project.setInitDate(new Date());
}
@Override
@Transactional
public void save() throws ValidationException {
InvalidValue[] invalidValues = projectValidator
.getInvalidValues(project);
if (invalidValues.length > 0)
throw new ValidationException(invalidValues);
this.projectService.save(project);
}
@Override
public ProjectWork getProject() {
return project;
}
@Override
public void remove(ProjectWork projectWork) {
try {
this.projectService.remove(projectWork);
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
public void prepareForRemove(ProjectWork project) {
this.project = project;
}
}

View file

@ -29,3 +29,5 @@ mainmenu.help=Axuda
mainmenu.about=Acerca de
mainmenu.aclunaga=Aclunaga
mainmenu.manage_criterions=Administrar criterios
mainmenu.workorders=Traballos
mainmenu.list_projects=Proxectos

View file

@ -29,3 +29,5 @@ mainmenu.help=Help
mainmenu.about=About
mainmenu.aclunaga=Aclunaga
mainmenu.manage_criterions=Manage criterions
mainmenu.workorders=Work
mainmenu.list_projects=Projects

View file

@ -36,6 +36,13 @@
</menupopup>
</menu>
<menu label="${c:l('mainmenu.workorders')}">
<menupopup>
<menuitem label="${c:l('mainmenu.list_projects')}"
href='/workorders/projects.zul' />
</menupopup>
</menu>
<menu label="${c:l('mainmenu.plannification')}">
<menupopup>
<menuitem label="${c:l('mainmenu.plannification')}"

View file

@ -0,0 +1,42 @@
<window id="${arg.top_id}" title="${arg.title}">
<grid fixedLayout="false">
<columns>
<column label="Nome" />
<column label="Comezo" />
<column label="Final" />
<column label="Responsable" />
<column label="Cliente" />
<column label="Descripción" />
</columns>
<rows>
<row>
<label value="Nome" />
<textbox value="@{controller.project.name}" />
</row>
<row>
<label value="Comezo" />
<datebox value="@{controller.project.initDate}" />
</row>
<row>
<label value="Final" />
<datebox value="@{controller.project.endDate}" />
</row>
<row>
<label value="Responsable" />
<textbox value="@{controller.project.responsible}" />
</row>
<row>
<label value="Cliente" />
<textbox value="@{controller.project.customer}" />
</row>
<row>
<label value="Descripción" />
<textbox value="@{controller.project.description}" rows="4"/>
</row>
</rows>
</grid>
<button onClick="controller.save();"
label="${arg.save_button_label}" />
<button onClick="controller.cancel();"
label="${arg.cancel_button_label}" />
</window>

View file

@ -0,0 +1,36 @@
<window id="${arg.top_id}" title="Listado Proxectos">
<grid id="listing" model="@{controller.projects}" mold="paging"
pageSize="5">
<columns>
<column label="Operacións" />
<column label="Nome" sort="auto(name)" />
<column label="Comezo" sort="auto(initDate)" />
<column label="Final" sort="auto(endDate)" />
<column label="Responsable" sort="auto(responsible)" />
<column label="Cliente" sort="auto(customer)" />
<column label="Descripción" sort="auto(description)" />
</columns>
<rows>
<row self="@{each='project'}" value="@{project}">
<hbox>
<button label="Edit"
onClick="controller.goToEditForm(self.parent.parent.value);">
</button>
<button label="Remove"
onClick="controller.confirmRemove(self.parent.parent.value);">
</button>
</hbox>
<label value="@{project.name}" />
<label value="@{project.initDate}" />
<label value="@{project.endDate}" />
<label value="@{project.responsible}" />
<label value="@{project.customer}" />
<label value="@{project.description}" />
</row>
</rows>
</grid>
<button id="show_create_form" onClick="controller.goToCreateForm();"
label="Create">
</button>
</window>

View file

@ -0,0 +1,36 @@
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c"?>
<?page id="List"?>
<?init class="org.zkoss.zk.ui.util.Composition" arg0="/common/layout/template.zul"?>
<?link rel="stylesheet" type="text/css" href="/common/css/navalpro.css"?>
<?link rel="stylesheet" type="text/css" href="/resources/css/resources.css"?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<?component name="list" inline="true" macroURI="_list.zul"?>
<?component name="edition" inline="true" macroURI="_edition.zul"?>
<zk >
<window self="@{define(content)}"
apply="org.navalplanner.web.workorders.ProjectWorkCRUDController">
<vbox id="messagesContainer"></vbox>
<list top_id="listWindow" />
<edition top_id="createWindow" title="Create"
save_button_label="Save" cancel_button_label="Cancel" />
<edition top_id="editWindow" title="Edit Personal Data"
save_button_label="Save" cancel_button_label="Cancel" />
<window visible="@{controller.confirmingRemove}"
id="confirmRemove" title="Confirmación" width="500px"
position="center">
<vbox>
<hbox>
¿Desexa borrar <label value="@{controller.project.name}"/> ?
</hbox>
<hbox>
<button label="Si"
onClick="controller.remove(controller.project);" />
<button label="Non"
onClick="controller.cancelRemove();" />
</hbox>
</vbox>
</window>
</window>
</zk>