ItEr28S12ClasificacionTraballoItEr27S12 : Management of criterion types and criterion( list/editing of criterion types and criterion /remove of criterions).

This commit is contained in:
Susana Montes Pedreira 2009-09-30 20:04:50 +02:00 committed by Javier Moran Rua
parent 878d08cb94
commit f0bb4d279d
28 changed files with 1823 additions and 120 deletions

View file

@ -1,10 +1,12 @@
package org.navalplanner.business.resources.entities;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.NotNull;
import org.navalplanner.business.common.BaseEntity;
@ -33,6 +35,10 @@ public class Criterion extends BaseEntity implements ICriterion {
@NotNull
private CriterionType type;
private Criterion parent = null;
private Set<Criterion> children = new HashSet<Criterion>();
private boolean active = true;
/*
@ -104,6 +110,22 @@ public class Criterion extends BaseEntity implements ICriterion {
this.active = active;
}
public Criterion getParent() {
return parent;
}
public void setParent(Criterion parent) {
this.parent = parent;
}
public Set<Criterion> getChildren() {
return children;
}
public void setChildren(Set<Criterion> children) {
this.children = children;
}
public boolean isEquivalent(ICriterion criterion) {
if (criterion instanceof Criterion) {
Criterion other = (Criterion) criterion;
@ -113,8 +135,4 @@ public class Criterion extends BaseEntity implements ICriterion {
return false;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}

View file

@ -1,5 +1,9 @@
package org.navalplanner.business.resources.entities;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.builder.EqualsBuilder;
@ -22,18 +26,17 @@ public class CriterionType extends BaseEntity implements
return criterionType;
}
public static CriterionType create(String name) {
CriterionType criterionType = new CriterionType(name);
public static CriterionType create(String name,String description) {
CriterionType criterionType = new CriterionType(name,description);
criterionType.setNewObject(true);
return criterionType;
}
public static CriterionType create(String name, boolean allowHierarchy,
boolean allowSimultaneousCriterionsPerResource,
boolean allowAdding, boolean allowEditing, ResourceEnum resource) {
CriterionType criterionType = new CriterionType(name, allowHierarchy,
allowSimultaneousCriterionsPerResource, allowAdding,
allowEditing, resource);
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;
}
@ -41,17 +44,19 @@ public class CriterionType extends BaseEntity implements
@NotEmpty
private String name;
private boolean allowHierarchy = true;
private String description;
private boolean allowSimultaneousCriterionsPerResource = true;
private Boolean allowHierarchy = true;
private boolean allowAdding = true;
private Boolean allowSimultaneousCriterionsPerResource = true;
private boolean allowEditing = true;
private Boolean enabled = true;
private ResourceEnum resource = ResourceEnum.getDefault();
private Set<Criterion> criterions;
private Set<Criterion> criterions = new HashSet<Criterion>();
private int numCriterions;
/**
* Constructor for hibernate. Do not use!
@ -60,27 +65,28 @@ public class CriterionType extends BaseEntity implements
}
private CriterionType(String name) {
private CriterionType(String name,String description) {
this.name = name;
this.description = description;
}
private CriterionType(String name, boolean allowHierarchy,
boolean allowSimultaneousCriterionsPerResource,
boolean allowAdding, boolean allowEditing, ResourceEnum resource) {
private CriterionType(String name,String description, boolean allowHierarchy,
boolean allowSimultaneousCriterionsPerResource, boolean enabled,
ResourceEnum resource) {
this.allowHierarchy = allowHierarchy;
this.allowSimultaneousCriterionsPerResource = allowSimultaneousCriterionsPerResource;
this.enabled = enabled;
this.name = name;
this.allowAdding = allowAdding;
this.allowEditing = allowEditing;
this.description = description;
this.resource = resource;
}
public static CriterionType asCriterionType(ICriterionType criterionType) {
return create(criterionType.getName(), criterionType
.allowHierarchy(), criterionType
.allowSimultaneousCriterionsPerResource(),
criterionType.allowAdding(), criterionType.allowEditing(),
return create(criterionType.getName(),criterionType.getDescription(),
criterionType.allowHierarchy(), criterionType
.isAllowSimultaneousCriterionsPerResource(),
criterionType.isEnabled(),
CriterionType.getResource(criterionType));
}
@ -99,6 +105,10 @@ public class CriterionType extends BaseEntity implements
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Criterion> getCriterions() {
return criterions;
}
@ -109,22 +119,20 @@ public class CriterionType extends BaseEntity implements
@Override
public boolean allowHierarchy() {
return allowHierarchy;
return allowHierarchy == null ? false : allowHierarchy;
}
public void setAllowHierarchy(boolean allowHierarchy) {
this.allowHierarchy = allowHierarchy;
}
@Override
public boolean allowSimultaneousCriterionsPerResource() {
return allowSimultaneousCriterionsPerResource;
public boolean isAllowSimultaneousCriterionsPerResource() {
return allowSimultaneousCriterionsPerResource == null ? false : allowSimultaneousCriterionsPerResource;
}
@Override
public boolean allowAdding() {
return allowAdding;
}
@Override
public boolean allowEditing() {
return allowEditing;
public void setAllowSimultaneousCriterionsPerResource(boolean allowSimultaneousCriterionsPerResource) {
this.allowSimultaneousCriterionsPerResource = allowSimultaneousCriterionsPerResource;
}
public ResourceEnum resource() {
@ -196,4 +204,32 @@ public class CriterionType extends BaseEntity implements
hash = 59 * hash + (this.name != null ? this.name.hashCode() : 0);
return hash;
}
@Override
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public boolean isEnabled() {
return enabled == null ? false : enabled;
}
@Override
public boolean isImmutable(){
return !isEnabled();
}
public int getNumCriterions(){
return criterions.size();
}
}

View file

@ -12,21 +12,20 @@ public abstract class CriterionTypeBase implements ICriterionType<Criterion> {
private final boolean allowSimultaneousCriterionsPerResource;
private final boolean enabled;
private final String name;
private final boolean allowAdding;
private final String description;
private final boolean allowEditing;
protected CriterionTypeBase(String name, boolean allowHierarchy,
boolean allowSimultaneousCriterionsPerResource,
boolean allowAdding, boolean allowEditing) {
protected CriterionTypeBase(String name, String description, boolean allowHierarchy,
boolean allowSimultaneousCriterionsPerResource,boolean enabled) {
Validate.notNull(name, "name is not null");
this.allowHierarchy = allowHierarchy;
this.allowSimultaneousCriterionsPerResource = allowSimultaneousCriterionsPerResource;
this.name = name;
this.allowAdding = allowAdding;
this.allowEditing = allowEditing;
this.description = description;
this.enabled = enabled;
}
@Override
@ -35,21 +34,27 @@ public abstract class CriterionTypeBase implements ICriterionType<Criterion> {
}
@Override
public boolean allowSimultaneousCriterionsPerResource() {
public boolean isAllowSimultaneousCriterionsPerResource() {
return allowSimultaneousCriterionsPerResource;
}
@Override
public String getName() {
return name;
}
@Override
public boolean allowAdding() {
return allowAdding;
public String getDescription() {
return description;
}
@Override
public boolean allowEditing() {
return allowEditing;
public boolean isEnabled() {
return enabled;
}
@Override
public boolean isImmutable() {
return !enabled;
}
}

View file

@ -8,13 +8,15 @@ public interface ICriterionType<C extends ICriterion> {
public String getName();
public boolean allowSimultaneousCriterionsPerResource();
public String getDescription();
public boolean isAllowSimultaneousCriterionsPerResource();
public boolean allowHierarchy();
public boolean allowAdding();
public boolean isEnabled();
public boolean allowEditing();
public boolean isImmutable();
public C createCriterion(String name);

View file

@ -1,5 +1,4 @@
package org.navalplanner.business.resources.entities;
import java.util.Arrays;
import java.util.List;
@ -10,61 +9,61 @@ import java.util.List;
*/
public enum PredefinedCriterionTypes implements ICriterionType<Criterion> {
WORK_RELATIONSHIP(false, false, false, false, ResourceEnum.WORKER) {
WORK_RELATIONSHIP("Relationship of the resource with the enterprise ",false, false,true, ResourceEnum.WORKER) {
@Override
public List<String> getPredefined() {
return WorkingRelationship.getCriterionNames();
}
},
LOCATION_GROUP(false, true, true, true, ResourceEnum.RESOURCE) {
LOCATION_GROUP("Location where the resource work",false, true, true, ResourceEnum.RESOURCE) {
@Override
public List<String> getPredefined() {
return Arrays.asList();
}
},
LEAVE(false, false, false, false, ResourceEnum.WORKER) {
LEAVE("Leave",false, false, true, ResourceEnum.WORKER) {
@Override
public List<String> getPredefined() {
return LeaveCriterions.getCriterionNames();
}
},
TRAINING(true, true, true, true, ResourceEnum.WORKER) {
TRAINING("Training courses and labor training",true, true, true, ResourceEnum.WORKER) {
@Override
public List<String> getPredefined() {
return Arrays.asList();
}
},
JOB(true, true, true, true, ResourceEnum.WORKER) {
JOB("Job",true, true, true, ResourceEnum.WORKER) {
@Override
public List<String> getPredefined() {
return Arrays.asList();
}
},
CATEGORY(true, true, true, true, ResourceEnum.WORKER) {
CATEGORY("Professional category",true, true, true, ResourceEnum.WORKER) {
@Override
public List<String> getPredefined() {
return Arrays.asList();
}
};
private final String description;
private final boolean allowHierarchy;
private final boolean allowSimultaneousCriterionsPerResource;
private final boolean allowAdding;
private final boolean allowEditing;
private final boolean enabled;
private final ResourceEnum resource;
private PredefinedCriterionTypes(boolean allowHierarchy,
private PredefinedCriterionTypes(String description, boolean allowHierarchy,
boolean allowSimultaneousCriterionsPerResource,
boolean allowAdding, boolean allowEditing,
boolean enabled,
ResourceEnum resource) {
this.allowHierarchy = allowHierarchy;
this.allowSimultaneousCriterionsPerResource = allowSimultaneousCriterionsPerResource;
this.allowAdding = allowAdding;
this.allowEditing = allowEditing;
this.description = description;
this.enabled = enabled;
this.resource = resource;
}
@ -79,18 +78,23 @@ public enum PredefinedCriterionTypes implements ICriterionType<Criterion> {
}
@Override
public boolean allowSimultaneousCriterionsPerResource() {
public boolean isAllowSimultaneousCriterionsPerResource() {
return allowSimultaneousCriterionsPerResource;
}
@Override
public boolean allowAdding() {
return allowAdding;
public String getDescription() {
return description;
}
@Override
public boolean allowEditing() {
return allowEditing;
public boolean isEnabled() {
return this.enabled;
}
@Override
public boolean isImmutable() {
return !this.enabled;
}
@Override

View file

@ -295,7 +295,7 @@ public abstract class Resource extends BaseEntity{
private Date getFinishDate(ICriterionType<?> type,
CriterionSatisfaction newSatisfaction, Interval interval) {
if (!type.allowSimultaneousCriterionsPerResource()) {
if (!type.isAllowSimultaneousCriterionsPerResource()) {
CriterionSatisfaction posterior = getNext(type, newSatisfaction);
if (posterior != null && posterior.overlapsWith(interval)) {
assert !posterior.overlapsWith(Interval.range(interval
@ -351,7 +351,7 @@ public abstract class Resource extends BaseEntity{
if (!type.criterionCanBeRelatedTo(getClass())) {
return false;
}
if (type.allowSimultaneousCriterionsPerResource()) {
if (type.isAllowSimultaneousCriterionsPerResource()) {
return true;
}
CriterionSatisfaction newSatisfaction = createNewSatisfaction(interval,
@ -408,7 +408,7 @@ public abstract class Resource extends BaseEntity{
private void checkNotOverlaps(List<CriterionType> types) {
for (CriterionType criterionType : types) {
if (!criterionType.allowSimultaneousCriterionsPerResource()) {
if (!criterionType.isAllowSimultaneousCriterionsPerResource()) {
List<CriterionSatisfaction> satisfactions = query().from(
criterionType).result();
ListIterator<CriterionSatisfaction> listIterator = satisfactions

View file

@ -46,12 +46,18 @@
<property access="field" name="active"/>
<many-to-one access="field" name="type" column="id_criterion_type" not-null="true" />
<many-to-one name="parent" column="parent" access="field" not-null="false"/>
<set name="children" access="field" lazy="true" cascade="save-update">
<key column="parent" not-null="false"></key>
<one-to-many class="Criterion"/>
</set>
<properties name="nameAndType" unique="true">
<property access="field" name="name" insert="false" update="false"/>
<property access="field" name="typeId" insert="false" update="false"
column="id_criterion_type"/>
</properties>
</class>
<!-- CriterionSatisfaction -->
@ -75,16 +81,16 @@
</id>
<version name="version" access="property" type="long" />
<property name="name" unique="true"/>
<property name="description"/>
<property name="allowSimultaneousCriterionsPerResource"/>
<property name="allowHierarchy"/>
<property name="allowAdding"/>
<property name="allowEditing"/>
<property name="enabled"/>
<property name="resource">
<type name="org.hibernate.type.EnumType">
<param name="enumClass">org.navalplanner.business.resources.entities.ResourceEnum</param>
</type>
</property>
<set name="criterions">
<set name="criterions" cascade="all,delete-orphan" inverse="true">
<key column="id_criterion_type" />
<one-to-many class="Criterion" />
</set>

View file

@ -58,10 +58,10 @@ public class CriterionDAOTest {
}
public static Criterion createValidCriterion() {
return createValidCriterion(UUID.randomUUID().toString());
return createValidCriterion(UUID.randomUUID().toString(),"");
}
public static Criterion createValidCriterion(String name) {
public static Criterion createValidCriterion(String name,String description) {
CriterionType criterionType = CriterionTypeDAOTest
.createValidCriterionType();
return Criterion.withNameAndType(name, criterionType);
@ -219,7 +219,7 @@ public class CriterionDAOTest {
return new ICriterionType<Criterion>() {
@Override
public boolean allowSimultaneousCriterionsPerResource() {
public boolean isAllowSimultaneousCriterionsPerResource() {
return allowSimultaneousCriterionsPerResource;
}
@ -243,16 +243,6 @@ public class CriterionDAOTest {
return null;
}
@Override
public boolean allowAdding() {
return false;
}
@Override
public boolean allowEditing() {
return false;
}
@Override
public boolean criterionCanBeRelatedTo(
Class<? extends Resource> klass) {
@ -263,6 +253,21 @@ public class CriterionDAOTest {
public Criterion createCriterionWithoutNameYet() {
return null;
}
@Override
public String getDescription() {
return null;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public boolean isImmutable() {
return false;
}
};
}

View file

@ -43,13 +43,14 @@ public class CriterionTypeDAOTest {
public static final String DEFAULT_CRITERION_TYPE = "TEST_DEFAULT";
public static CriterionType createValidCriterionType(String name) {
return CriterionType.create(name);
public static CriterionType createValidCriterionType(String name,String description) {
return CriterionType.create(name,description);
}
public static CriterionType createValidCriterionType() {
String unique = UUID.randomUUID().toString();
return createValidCriterionType(unique);
String description = "";
return createValidCriterionType(unique,description);
}
@Test
@ -72,9 +73,9 @@ public class CriterionTypeDAOTest {
public void testCannotSaveTwoDifferentCriterionTypesWithTheSameName()
throws ValidationException {
try {
CriterionType criterionType = createValidCriterionType("bla");
CriterionType criterionType = createValidCriterionType("bla","");
criterionTypeDAO.save(criterionType);
criterionType = createValidCriterionType("bla");
criterionType = createValidCriterionType("bla","");
criterionTypeDAO.save(criterionType);
criterionTypeDAO.flush();
fail("must send exception since thereis a duplicated criterion type");

View file

@ -121,8 +121,8 @@ public class ResourceTest {
final Criterion... criterions) {
final HashSet<Criterion> criterionsSet = new HashSet<Criterion>(Arrays
.asList(criterions));
return new CriterionTypeBase("base", true,
allowMultipleCriterionsPerResource, false, false) {
return new CriterionTypeBase("base","", true,
allowMultipleCriterionsPerResource,true) {
@Override
public boolean contains(ICriterion c) {
@ -366,8 +366,8 @@ public class ResourceTest {
public void shouldntAdd() {
Criterion criterion = CriterionDAOTest.createValidCriterion();
Worker worker = Worker.create("firstName", "surName", "2333232");
ICriterionType<?> type = new CriterionTypeBase("prueba", false, false,
false, false) {
ICriterionType<?> type = new CriterionTypeBase("prueba","", false, false,
true) {
@Override
public boolean contains(ICriterion c) {

View file

@ -38,7 +38,7 @@ public abstract class AbstractWorkReportTest {
Set<CriterionType> criterionTypes = new HashSet<CriterionType>();
CriterionType criterionType = CriterionType.create(UUID.randomUUID()
.toString());
.toString(),"");
criterionTypeDAO.save(criterionType);
criterionTypes.add(criterionType);

View file

@ -151,14 +151,16 @@ public class CustomMenuController extends Div implements IMenuItemsRegister {
topItem(_("Resources"), "/resources/worker/worker.zul",
subItem(_("Workers List"),"/resources/worker/worker.zul#list"),
subItem(_("Manage criterions"),"/resources/criterions/criterions.zul"));
subItem(_("Manage criterions"),"/resources/criterions/criterions-V2.zul"));
topItem(_("Orders"), "/orders/orders.zul",
subItem(_("Orders list"),"/orders/orders.zul"),
subItem(_("Work activities types"),"/orders/orders.zul", true),
subItem(_("Models"),"/orders/orders.zul", true),
subItem(_("Resource Load"),
"/resourceload/resourceload.zul"));
topItem(_("Orders"),
"/orders/orders.zul",
subItem(_("Orders list"),
"/orders/orders.zul"),
subItem(_("Work activities types"),
"/orders/orders.zul"),
subItem(_("Models"),
"/orders/orders.zul"));
topItem(_("Work reports"), "/workreports/workReportTypes.zul", subItem(
_("Work report types"), "/workreports/workReportTypes.zul"),

View file

@ -72,8 +72,7 @@ public class CriterionAdminController extends GenericForwardComposer {
operations.setParent(row);
Button editButton = new Button(_("Edit"));
editButton.setParent(operations);
editButton.setDisabled(!criterionsModel.getTypeFor(criterion)
.allowEditing());
editButton.setDisabled(!criterionsModel.getTypeFor(criterion).isEnabled());
editButton.addEventListener("onClick", new EventListener() {
@Override
@ -102,7 +101,7 @@ public class CriterionAdminController extends GenericForwardComposer {
final ICriterionType<?> type = (ICriterionType<?>) data;
Div div = new Div();
Button createButton = new Button(_("Add"));
createButton.setDisabled(!type.allowAdding());
createButton.setDisabled(!type.isEnabled());
createButton.addEventListener("onClick", new EventListener() {
@Override

View file

@ -0,0 +1,240 @@
package org.navalplanner.web.resources.criterion;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionType;
import org.navalplanner.business.resources.entities.ICriterionType;
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.zul.Window;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Checkbox;
import static org.navalplanner.web.I18nHelper._;
/**
* Controller for Criterions <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public class CriterionAdminController_V2 extends GenericForwardComposer {
private static final Log log = LogFactory
.getLog(CriterionAdminController.class);
private ICriterionsModel_V2 criterionsModel_V2;
private Component messagesContainer;
private IMessagesForUser messagesForUser;
private Window listing;
private Window confirmRemove;
private boolean confirmingRemove = false;
private Window confirmDisabledHierarchy;
private boolean confirmingDisabledHierarchy = false;
private Component editComponent;
private Component createComponent;
private OnlyOneVisible onlyOneVisible;
private Component workersComponent;
private CriterionTreeController editionTree;
private CriterionWorkersController workers;
public CriterionAdminController_V2() {
}
public void goToCreateForm() {
onlyOneVisible.showOnly(createComponent);
criterionsModel_V2.prepareForCreate();
Util.reloadBindings(createComponent);
}
public void goToEditForm(CriterionType criterionType) {
onlyOneVisible.showOnly(editComponent);
criterionsModel_V2.prepareForEdit(criterionType);
Util.reloadBindings(editComponent);
}
public void confirmRemove(CriterionType criterionType) {
criterionsModel_V2.prepareForRemove(criterionType);
showConfirmingWindow();
}
public void cancelRemove() {
confirmingRemove = false;
confirmRemove.setVisible(false);
Util.reloadBindings(confirmRemove);
}
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 remove(CriterionType criterionType) {
criterionsModel_V2.remove(criterionType);
hideConfirmingWindow();
Util.reloadBindings(listing);
messagesForUser.showMessage(
Level.INFO, _("Removed {0}", criterionType.getName()));
}
public void confirmDisabledHierarchy(Checkbox checkbox) {
if(!checkbox.isChecked()){
showConfirmingHierarchyWindow();
}
}
public boolean allowRemove(CriterionType criterionType){
if(criterionType.getCriterions().size() > 0)
return false;
return true;
}
public boolean notAllowRemove(CriterionType criterionType){
return !allowRemove(criterionType);
}
public boolean isActivo(){
return true;
}
public void cancelDisEnabledHierarchy() {
confirmingDisabledHierarchy = false;
confirmDisabledHierarchy.setVisible(false);
Util.reloadBindings(confirmDisabledHierarchy);
}
public boolean isConfirmingDisEnabledHierarchy() {
return confirmingDisabledHierarchy;
}
private void hideConfirmingHierarchtWindow() {
confirmingDisabledHierarchy = false;
Util.reloadBindings(confirmDisabledHierarchy);
}
private void showConfirmingHierarchyWindow() {
this.confirmingDisabledHierarchy = true;
try {
Util.reloadBindings(this.confirmDisabledHierarchy);
confirmDisabledHierarchy.doModal();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void okDisEnabledHierarchy() {
criterionsModel_V2.disableHierarchy();
editionTree.reloadTree();
hideConfirmingHierarchtWindow();
Util.reloadBindings(listing);
messagesForUser.showMessage(
Level.INFO, _("Fattened Tree {0}", criterionsModel_V2.getCriterionType().getName()));
}
public void changeEnabled(Checkbox checkbox) {
criterionsModel_V2.updateEnabledCriterions(checkbox.isChecked());
editionTree.reloadTree();
}
public CriterionTreeController getEdition() {
return editionTree;
}
public void saveAndClose(){
save();
close();
}
public void saveAndContinue(){
save();
}
public void close(){
onlyOneVisible.showOnly(listing);
Util.reloadBindings(listing);
}
private void save() {
try {
criterionsModel_V2.saveCriterionType();
messagesForUser.showMessage(Level.INFO, _("CriterionType and it`s criterions saved"));
} catch (ValidationException e) {
messagesForUser.showInvalidValues(e);
}
}
public List<CriterionType> getCriterionTypes() {
List<CriterionType> types = criterionsModel_V2.getTypes();
return types;
}
public ICriterionType<?> getCriterionType() {
return criterionsModel_V2.getCriterionType();
}
public ICriterionTreeModel getCriterionTreeModel() {
return criterionsModel_V2.getCriterionTreeModel();
}
public Criterion getCriterion() {
return criterionsModel_V2.getCriterion();
}
public CriterionWorkersController getWorkers() {
return workers;
}
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
onlyOneVisible = new OnlyOneVisible(listing, editComponent,
createComponent, workersComponent);
onlyOneVisible.showOnly(listing);
comp.setVariable("controller", this, false);
messagesForUser = new MessagesForUser(messagesContainer);
setupCriterionTreeController(comp, "editComponent");
setupCriterionTreeController(comp, "createComponent");
}
private void setupCriterionTreeController(Component comp, String window
)throws Exception {
editionTree = new CriterionTreeController(criterionsModel_V2);
editionTree.doAfterCompose(comp.getFellow(window).getFellow(
"criterionsTree"));
}
}

View file

@ -0,0 +1,158 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.navalplanner.web.resources.criterion;
import java.util.ArrayList;
import java.util.List;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionType;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.NotNull;
import org.navalplanner.business.common.BaseEntity;
/**
*
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public class CriterionDTO {
private Criterion criterion = null;
private String name;
private CriterionDTO parent = null;
private List<CriterionDTO> children = new ArrayList<CriterionDTO>();
private boolean active = true;
private boolean newObject = true;
public CriterionDTO(){
this.name = "";
this.newObject = true;
}
private CriterionDTO(Criterion criterion) {
Validate.notNull(criterion);
this.criterion = criterion;
this.name = criterion.getName();
this.active = criterion.isActive();
this.newObject = false;
}
public static List<CriterionDTO> asListDTO(Set<Criterion> setChildren,CriterionDTO parent){
List<CriterionDTO> listChildren = new ArrayList<CriterionDTO>();
for(Criterion criterion : setChildren){
CriterionDTO criterionDTO = new CriterionDTO(criterion);
criterionDTO.setChildren(asListDTO(criterion.getChildren(),criterionDTO));
criterionDTO.setParent(parent);
listChildren.add(criterionDTO);
}
return listChildren;
}
public static Set<Criterion> asSet(List<CriterionDTO> criterionDTOs,Criterion parent,
CriterionType criterionType){
Set<Criterion> listChildren = new HashSet<Criterion>();
for(CriterionDTO criterionDTO : criterionDTOs){
Criterion criterion = Criterion.create(criterionDTO.getName(),
criterionType);
criterion.setChildren(asSet(criterionDTO.getChildren(),criterion,criterionType));
criterion.setParent(parent);
listChildren.add(criterion);
}
return listChildren;
}
public boolean isNewObject() {
return newObject;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public CriterionDTO getParent() {
return parent;
}
public void setParent(CriterionDTO parent) {
this.parent = parent;
}
public List<CriterionDTO> getChildren() {
return children;
}
public void setChildren(List<CriterionDTO> children) {
this.children = children;
}
public void setCriterion(Criterion criterion) {
this.criterion = criterion;
}
public Criterion getCriterion() {
return criterion;
}
public int up(CriterionDTO criterionDTO) {
int position = children.indexOf(criterionDTO);
if(position == 0){
upParent(criterionDTO);
}
if (position > 0) {
children.remove(position);
children.add(position - 1, criterionDTO);
}
return position;
}
public int down(CriterionDTO criterionDTO) {
int position = children.indexOf(criterionDTO);
if(position == children.size()-1){
downParent(criterionDTO);
}
if (position < children.size() - 1) {
children.remove(position);
children.add(position + 1, criterionDTO);
}
return position;
}
private void upParent(CriterionDTO criterionDTO){
if(parent != null){
int position = parent.getChildren().indexOf(this);
parent.getChildren().add(position,criterionDTO);
}
}
private void downParent(CriterionDTO criterionDTO){
if(parent != null){
int position = parent.getChildren().indexOf(this);
parent.getChildren().add(position,criterionDTO);
}
}
}

View file

@ -0,0 +1,350 @@
package org.navalplanner.web.resources.criterion;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import static org.navalplanner.web.I18nHelper._;
import org.apache.commons.lang.Validate;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.web.common.IMessagesForUser;
import org.navalplanner.web.common.MessagesForUser;
import org.navalplanner.web.common.Util;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Button;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.TreeModel;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.TreeitemRenderer;
import org.zkoss.zul.Treerow;
import org.zkoss.zul.Vbox;
import org.zkoss.zul.api.Tree;
public class CriterionTreeController extends GenericForwardComposer {
private Tree tree;
private CriterionTreeitemRenderer renderer = new CriterionTreeitemRenderer();
private TreeViewStateSnapshot snapshotOfOpenedNodes;
private Component messagesContainer;
private IMessagesForUser messagesForUser;
private final ICriterionsModel_V2 criterionsModel;
private Component vbox;
public CriterionTreeitemRenderer getRenderer() {
return renderer;
}
public CriterionTreeController(ICriterionsModel_V2 _criterionsModel) {
Validate.notNull(_criterionsModel);
this.criterionsModel = _criterionsModel;
}
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
messagesForUser = new MessagesForUser(messagesContainer);
comp.setVariable("criterionTreeController", this, true);
this.vbox = comp;
}
public TreeModel getCriterionTreeModel() {
if (getModel() == null) {
return null;
}
return getModel().asTree();
}
private ICriterionTreeModel getModel() {
return criterionsModel.getCriterionTreeModel();
}
public class CriterionTreeitemRenderer implements TreeitemRenderer {
public CriterionTreeitemRenderer() {
}
@Override
public void render(Treeitem item, Object data) throws Exception {
final CriterionDTO criterionForThisRow = (CriterionDTO) data;
item.setValue(data);
if (snapshotOfOpenedNodes != null) {
snapshotOfOpenedNodes.openIfRequired(item);
}
Treecell cellForName = new Treecell();
cellForName.appendChild(Util.bind(new Textbox(),
new Util.Getter<String>() {
@Override
public String get() {
return criterionForThisRow.getName();
}
}, new Util.Setter<String>() {
@Override
public void set(String value) {
criterionForThisRow.setName(value);
}
}));
Treecell cellForActive = new Treecell();
cellForActive.setStyle("center");
Checkbox checkboxActive = new Checkbox();
cellForActive.appendChild(Util.bind(checkboxActive,
new Util.Getter<Boolean>() {
@Override
public Boolean get() {
return criterionForThisRow.isActive();
}
}, new Util.Setter<Boolean>() {
@Override
public void set(Boolean value) {
criterionForThisRow.setActive(value);
}
}));
checkboxActive.addEventListener(Events.ON_CHECK,new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
getModel().updateEnabledCriterions(criterionForThisRow.isActive(),criterionForThisRow);
reloadTree();
}
});
Treerow tr = null;
/*
* Since only one treerow is allowed, if treerow is not null, append
* treecells to it. If treerow is null, contruct a new treerow and
* attach it to item.
*/
if (item.getTreerow() == null) {
tr = new Treerow();
tr.setParent(item);
} else {
tr = item.getTreerow();
tr.getChildren().clear();
}
// Attach treecells to treerow
tr.setDraggable("true");
tr.setDroppable("true");
cellForName.setParent(tr);
cellForActive.setParent(tr);
Treecell tcOperations = new Treecell();
Button upbutton = new Button("", "/common/img/ico_bajar1.png");
upbutton.setHoverImage("/common/img/ico_bajar.png");
upbutton.setParent(tcOperations);
upbutton.setSclass("icono");
upbutton.addEventListener(Events.ON_CLICK, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
getModel().down(criterionForThisRow);
reloadTree();
}
});
Button downbutton = new Button("", "/common/img/ico_subir1.png");
downbutton.setHoverImage("/common/img/ico_subir.png");
downbutton.setParent(tcOperations);
downbutton.setSclass("icono");
downbutton.addEventListener(Events.ON_CLICK, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
getModel().up(criterionForThisRow);
reloadTree();
}
});
Button indentbutton = new Button("", "/common/img/ico_derecha1.png");
indentbutton.setHoverImage("/common/img/ico_derecha.png");
indentbutton.setParent(tcOperations);
indentbutton.setSclass("icono");
indentbutton.addEventListener(Events.ON_CLICK, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
getModel().indent(criterionForThisRow);
reloadTree();
}
});
Button unindentbutton = new Button("", "/common/img/ico_izq1.png");
unindentbutton.setHoverImage("/common/img/ico_izq.png");
unindentbutton.setParent(tcOperations);
unindentbutton.setSclass("icono");
unindentbutton.addEventListener(Events.ON_CLICK,
new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
getModel().unindent(criterionForThisRow);
reloadTree();
}
});
Button removebutton = createButtonRemove(criterionForThisRow);
removebutton.setParent(tcOperations);
if(criterionForThisRow.isNewObject()){
removebutton.addEventListener(Events.ON_CLICK, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
getModel().removeNode(criterionForThisRow);
reloadTree();
}
});
}
tcOperations.setParent(tr);
tr.addEventListener("onDrop", new EventListener() {
@Override
public void onEvent(org.zkoss.zk.ui.event.Event arg0)
throws Exception {
DropEvent dropEvent = (DropEvent) arg0;
move((Component) dropEvent.getTarget(),
(Component) dropEvent.getDragged());
}
});
}
}
private Button createButtonRemove(CriterionDTO criterion){
String urlIcono;
String urlHoverImage;
String toolTipText;
if(criterion.isNewObject()){
urlIcono = "/common/img/ico_borrar1.png";
urlHoverImage = "/common/img/ico_borrar.png";
toolTipText = "Delete";
}else{
urlIcono = "/common/img/ico_borrar_out.png";
urlHoverImage = "/common/img/ico_borrar.png";
toolTipText = "Not deletable";
}
Button removebutton = new Button("", urlIcono);
removebutton.setHoverImage(urlHoverImage);
removebutton.setSclass("icono");
removebutton.setTooltiptext(_(toolTipText));
return removebutton;
}
public void up() {
snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
if (tree.getSelectedCount() == 1) {
getModel().up(getSelectedNode());
}
}
public void down() {
snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
if (tree.getSelectedCount() == 1) {
getModel().down(getSelectedNode());
}
}
public void move(Component dropedIn, Component dragged) {
snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
Treerow from = (Treerow) dragged;
CriterionDTO fromNode = (CriterionDTO) ((Treeitem) from.getParent())
.getValue();
if (dropedIn instanceof Tree) {
getModel().moveToRoot(fromNode,0);
}
if (dropedIn instanceof Treerow) {
Treerow to = (Treerow) dropedIn;
CriterionDTO toNode = (CriterionDTO) ((Treeitem) to.getParent())
.getValue();
getModel().move(fromNode, toNode,0);
}
reloadTree();
}
public void addCriterion() {
snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
try {
if((tree.getSelectedCount() == 1)
&& (this.criterionsModel.getAllowHierarchy())){
getModel().addCriterionAt(getSelectedNode(),getName());
} else {
getModel().addCriterion(getName());
}
reloadTree();
} catch (ValidationException e) {
messagesForUser.showInvalidValues(e);
}
}
public void reloadTree(){
Util.reloadBindings(tree);
}
private String getName() throws ValidationException{
String name = ((Textbox)((Vbox)vbox).
getFellow("criterionName")).getValue();
getModel().thereIsOtherWithSameNameAndType(name);
getModel().validateNameNotEmpty(name);
return name;
}
private CriterionDTO getSelectedNode() {
return (CriterionDTO) tree.getSelectedItemApi().getValue();
}
private static class TreeViewStateSnapshot {
private final Set<Object> all;
private final Set<Object> dataOpen;
private TreeViewStateSnapshot(Set<Object> dataOpen, Set<Object> all) {
this.dataOpen = dataOpen;
this.all = all;
}
public static TreeViewStateSnapshot snapshotOpened(Tree tree) {
Iterator<Treeitem> itemsIterator = tree.getTreechildrenApi()
.getItems().iterator();
Set<Object> dataOpen = new HashSet<Object>();
Set<Object> all = new HashSet<Object>();
while (itemsIterator.hasNext()) {
Treeitem treeitem = (Treeitem) itemsIterator.next();
Object value = getAssociatedValue(treeitem);
if (treeitem.isOpen()) {
dataOpen.add(value);
}
all.add(value);
}
return new TreeViewStateSnapshot(dataOpen, all);
}
private static Object getAssociatedValue(Treeitem treeitem) {
return treeitem.getValue();
}
public void openIfRequired(Treeitem item) {
Object value = getAssociatedValue(item);
item.setOpen(isNewlyCreated(value) || wasOpened(value));
}
private boolean wasOpened(Object value) {
return dataOpen.contains(value);
}
private boolean isNewlyCreated(Object value) {
return !all.contains(value);
}
}
}

View file

@ -0,0 +1,397 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.navalplanner.web.resources.criterion;
import java.util.ArrayList;
import java.util.Arrays;
import static org.navalplanner.web.I18nHelper._;
import java.util.HashSet;
import java.util.List;
import org.hibernate.validator.InvalidValue;
import org.navalplanner.business.common.exceptions.ValidationException;
import java.util.Set;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionType;
import org.navalplanner.web.common.Util;
import org.zkoss.ganttz.util.MutableTreeModel;
import org.zkoss.zul.TreeModel;
/**
* Model for a the {@link Criterion} tree for a {@link CriterionType} <br />
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public class CriterionTreeModel implements ICriterionTreeModel{
private MutableTreeModel<CriterionDTO> tree;
private final CriterionType criterionType;
private final CriterionDTO criterionRootDTO;
private static MutableTreeModel<CriterionDTO> createTreeFrom(CriterionDTO criterionRootDTO) {
List<CriterionDTO> criterionDTOs = criterionRootDTO.getChildren();
MutableTreeModel<CriterionDTO> treeModel = MutableTreeModel
.create(CriterionDTO.class);
CriterionDTO parent = treeModel.getRoot();
treeModel.add(parent, criterionDTOs);
addChildren(treeModel, criterionDTOs);
return treeModel;
}
private static List<CriterionDTO> getCriterionDTOs(
CriterionType criterionType,CriterionDTO criterionRootDTO){
Set<Criterion> criterions = getDirectCriterions(criterionType);
return CriterionDTO.asListDTO(criterions, criterionRootDTO);
}
private static Set<Criterion> getDirectCriterions(CriterionType criterionType){
Set<Criterion> criterions = new HashSet<Criterion>();
for(Criterion criterion : criterionType.getCriterions()){
if(criterion.getParent() == null){
criterions.add(criterion);
}
}
return criterions;
}
private static void addChildren(MutableTreeModel<CriterionDTO> treeModel,
List<CriterionDTO> criterions) {
for (CriterionDTO criterion : criterions) {
treeModel.add(criterion, criterion.getChildren());
addChildren(treeModel, criterion.getChildren());
}
}
public CriterionTreeModel(CriterionType criterionType) {
this.criterionType = criterionType ;
criterionRootDTO = new CriterionDTO();
List<CriterionDTO> listDTOs = getCriterionDTOs(criterionType,criterionRootDTO);
criterionRootDTO.setChildren(listDTOs);
tree = this.createTreeFrom(criterionRootDTO);
}
public TreeModel asTree() {
return tree;
}
public void addCriterion(String name) {
CriterionDTO newCriterionDTO = createNewCriterion(name);
newCriterionDTO.setActive(criterionType.isEnabled());
addToTree(tree.getRoot(), newCriterionDTO,0);
addCriterionAtCriterionType(newCriterionDTO,0);
}
public void addCriterionAt(CriterionDTO node,String name) {
CriterionDTO newCriterion = createNewCriterion(name);
newCriterion.setActive(criterionType.isEnabled());
addToTree(node,newCriterion,0);
addCriterionAtCriterion(node, newCriterion,0);
}
private CriterionDTO createNewCriterion(String name) {
CriterionDTO newCriterion = new CriterionDTO();
newCriterion.setName(_(name));
return newCriterion;
}
private void addToTree(CriterionDTO parentNode, CriterionDTO elementToAdd,int position) {
tree.add(parentNode,position,Arrays.asList(elementToAdd));
addChildren(tree,Arrays.asList(elementToAdd));
}
private void addToTree(CriterionDTO parentNode,
List<CriterionDTO> elementsToAdd) {
tree.add(parentNode, elementsToAdd);
addChildren(tree, elementsToAdd);
}
private void addCriterionAtCriterionType(CriterionDTO elementToAdd,int position) {
elementToAdd.setParent(criterionRootDTO);
criterionRootDTO.getChildren().add(position,elementToAdd);
}
private void addCriterionAtCriterion(CriterionDTO parent, CriterionDTO elementToAdd,int position) {
elementToAdd.setParent(parent);
parent.getChildren().add(position,elementToAdd);
}
@Override
public void up(CriterionDTO node) {
CriterionDTO parent = asCriterion(((CriterionDTO)tree.getParent(node)));
int pos = parent.up(node);
tree.up(node);
if((pos == 0)&&(!parent.equals(criterionRootDTO))){
upGranParent(node);
}
}
private void upGranParent(CriterionDTO node){
CriterionDTO parent = tree.getParent(node);
CriterionDTO grandParent = tree.getParent(parent);
int position = getChildren(grandParent).indexOf(parent);
if(tree.isRoot(grandParent)){
this.moveToRoot(node,position);
}else{
this.moveImpl(node, grandParent, position);
}
}
@Override
public void down(CriterionDTO node) {
CriterionDTO parent = asCriterion(((CriterionDTO)tree.getParent(node)));
int pos = parent.down(node);
tree.down(node);
if((pos == parent.getChildren().size() - 1)
&&(!parent.equals(criterionRootDTO))){
downGranParent(node);
}
}
private void downGranParent(CriterionDTO node){
CriterionDTO parent = tree.getParent(node);
CriterionDTO grandParent = tree.getParent(parent);
int position = getChildren(grandParent).indexOf(parent)+1;
if(tree.isRoot(grandParent)){
this.moveToRoot(node,position);
}else{
this.moveImpl(node, grandParent, position);
}
}
@Override
public void indent(CriterionDTO nodeToIndent) {
CriterionDTO parentOfSelected = tree.getParent(nodeToIndent);
int position = getChildren(parentOfSelected).indexOf(nodeToIndent);
if (position == 0) {
return;
}
CriterionDTO destination = (CriterionDTO) getChildren(parentOfSelected)
.get(position - 1);
moveImpl(nodeToIndent, destination, getChildren(destination).size());
}
@Override
public void unindent(CriterionDTO nodeToUnindent) {
CriterionDTO parent = tree.getParent(nodeToUnindent);
if (tree.isRoot(parent)) {
return;
}
CriterionDTO destination = tree.getParent(parent);
moveImpl(nodeToUnindent, destination, getChildren(destination).indexOf(
parent) + 1);
}
private List<CriterionDTO> getChildren(CriterionDTO node) {
List<CriterionDTO> result = new ArrayList<CriterionDTO>();
final int childCount = tree.getChildCount(node);
for (int i = 0; i < childCount; i++) {
result.add(tree.getChild(node, i));
}
return result;
}
@Override
public void move(CriterionDTO toBeMoved, CriterionDTO destination,int position) {
moveImpl(toBeMoved, destination,position);
}
@Override
public void moveToRoot(CriterionDTO toBeMoved,int position) {
moveImpl(toBeMoved, tree.getRoot(),position);
}
private void moveImpl(CriterionDTO toBeMoved, CriterionDTO destination,int position) {
if (getChildren(destination).contains(toBeMoved)) {
return;// it's already moved
}
removeNodeImpl(toBeMoved);
moveCriterion(toBeMoved,destination,position);
addToTree(destination, toBeMoved,position);
}
private void moveCriterion(CriterionDTO toBeMoved, CriterionDTO destination,int position){
//Add at CriterionType or at a criterion
if(tree.isRoot(destination)){
toBeMoved.setParent(criterionRootDTO);
criterionRootDTO.getChildren().add(position,toBeMoved);
}else{
toBeMoved.setParent(destination);
destination.getChildren().add(position,toBeMoved);
}
}
private CriterionDTO toNode(CriterionDTO container) {
if (container == criterionRootDTO) {
return tree.getRoot();
}
return (CriterionDTO) container;
}
private CriterionDTO asCriterion(CriterionDTO node) {
if (tree.isRoot(node)) {
return criterionRootDTO;
}
return (CriterionDTO) node;
}
public void removeNode(CriterionDTO node) {
removeNodeImpl(node);
}
private void removeNodeImpl(CriterionDTO criterion) {
if (criterion == tree.getRoot()) {
return;
}
CriterionDTO parent = criterion.getParent();
if(parent == criterionRootDTO){
criterionRootDTO.getChildren().remove(criterion);
}else{
parent.getChildren().remove(criterion);
}
tree.remove(criterion);
}
public int[] getPath(Criterion criterion) {
return tree.getPath(tree.getRoot(), criterion);
}
public void flattenTree(){
List<CriterionDTO> criterions = copyCriterions(criterionRootDTO.getChildren());
for(CriterionDTO criterion : criterions){
flattenTree(criterion);
}
}
private void flattenTree(CriterionDTO criterion){
if(criterion.getChildren().size()>0){
List<CriterionDTO> criterions = copyCriterions(criterion.getChildren());
for(CriterionDTO criterionChild : criterions){
flattenTree(criterionChild);
}
}
moveToRoot(criterion,criterionRootDTO.getChildren().size());
}
private List<CriterionDTO> copyCriterions(List<CriterionDTO> criterions){
List<CriterionDTO> newCriterions = new ArrayList<CriterionDTO>();
for(CriterionDTO criterion : criterions){
newCriterions.add(criterion);
}
return newCriterions;
}
public void thereIsOtherWithSameNameAndType(String name)
throws ValidationException{
thereIsOtherWithSameNameAndType(name,criterionRootDTO.getChildren());
}
private void thereIsOtherWithSameNameAndType(String name,List<CriterionDTO> criterions)
throws ValidationException{
for(CriterionDTO criterion : criterions){
if(criterion.getName().equals(name)){
InvalidValue[] invalidValues = {
new InvalidValue(_("Already exists other " +
"criterion with the same name"),
Criterion.class, "name",
criterion.getName(), criterion)};
throw new ValidationException(invalidValues);
}
thereIsOtherWithSameNameAndType(name,criterion.getChildren());
}
}
public void validateNameNotEmpty(String name)
throws ValidationException{
if(name.isEmpty()){
InvalidValue[] invalidValues = {
new InvalidValue(_("The name of the criterion is empty."),
CriterionType.class, "name",
"",criterionType)};
throw new ValidationException(invalidValues);
}
}
public void updateEnabledCriterions(boolean isChecked){
List<CriterionDTO> list = criterionRootDTO.getChildren();
updateEnabledCriterions(isChecked,list);
updateEnabledCriterionsTree(isChecked,getChildren(tree.getRoot()));
}
public void updateEnabledCriterions(boolean isChecked,CriterionDTO criterion){
List<CriterionDTO> list = criterion.getChildren();
updateEnabledCriterions(isChecked,list);
updateEnabledCriterionsTree(isChecked,list);
}
private void updateEnabledCriterions(boolean isChecked,
List<CriterionDTO> criterions){
for(CriterionDTO criterion : criterions){
criterion.setActive(isChecked);
if(criterion.getChildren().size() > 0){
updateEnabledCriterions(isChecked,criterion.getChildren());
}
}
}
private void updateEnabledCriterionsTree(boolean isChecked,
List<CriterionDTO> criterions){
for(CriterionDTO criterion: criterions){
criterion.setActive(isChecked);
tree.replace(criterion, criterion);
addToTree(criterion, criterion.getChildren());
updateEnabledCriterionsTree(isChecked,getChildren(criterion));
}
}
@Override
public void saveCriterions(CriterionType criterionType){
updateCriterions(criterionRootDTO.getChildren());
}
public void updateCriterions(List<CriterionDTO> criterionDTOs){
for(CriterionDTO criterionDTO : criterionDTOs){
updateDataCriterion(criterionDTO);
updateParent(criterionDTO);
updateCriterions(criterionDTO.getChildren());
}
}
private void updateParent(CriterionDTO criterionDTO){
if(!criterionDTO.isNewObject()){
updateOldParent(criterionDTO);
}
updateNewParent(criterionDTO);
}
private void updateOldParent(CriterionDTO criterionDTO){
Criterion oldParent = criterionDTO.getCriterion().getParent();
if(oldParent != null){
oldParent.getChildren().remove(criterionDTO.getCriterion());
}
}
private void updateNewParent(CriterionDTO criterionDTO){
Criterion newParent = criterionDTO.getParent().getCriterion();
criterionDTO.getCriterion().setParent(newParent);
if(newParent == null){
criterionType.getCriterions().add(criterionDTO.getCriterion());
}else{
newParent.getChildren().add(criterionDTO.getCriterion());
}
}
private void updateDataCriterion(CriterionDTO criterionDTO){
Criterion criterion = criterionDTO.getCriterion();
if(criterion == null){
criterion = Criterion.create(criterionType);
criterionDTO.setCriterion(criterion);
}
criterion.setName(criterionDTO.getName());
criterion.setActive(criterionDTO.isActive());
}
}

View file

@ -170,7 +170,7 @@ public class CriterionsModel implements ICriterionsModel {
@Override
public boolean isChangeAssignmentsDisabled() {
return criterionType == null
|| !criterionType.allowSimultaneousCriterionsPerResource();
|| !criterionType.isAllowSimultaneousCriterionsPerResource();
}
@Override

View file

@ -0,0 +1,208 @@
package org.navalplanner.web.resources.criterion;
import static org.navalplanner.web.I18nHelper._;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.resources.daos.ICriterionDAO;
import org.navalplanner.business.resources.daos.ICriterionTypeDAO;
import org.navalplanner.business.resources.daos.IResourceDAO;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionType;
import org.navalplanner.business.resources.entities.CriterionWithItsType;
import org.navalplanner.business.resources.entities.ICriterionType;
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker;
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 criterions. <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
@Component("criterionsModel_V2")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class CriterionsModel_V2 implements ICriterionsModel_V2 {
private static final Log log = LogFactory.getLog(CriterionsModel.class);
private ClassValidator<CriterionType> criterionTypeValidator = new ClassValidator<CriterionType>(
CriterionType.class);
@Autowired
private ICriterionDAO criterionDAO;
@Autowired
private ICriterionTypeDAO criterionTypeDAO;
@Autowired
private IResourceDAO resourceDAO;
private CriterionType criterionType;
private Criterion criterion;
private ICriterionTreeModel criterionTreeModel;
@Override
@Transactional(readOnly = true)
public List<CriterionType> getTypes() {
return criterionTypeDAO.getCriterionTypes();
}
@Override
public ICriterionType<?> getCriterionType() {
return criterionType;
}
@Override
@Transactional(readOnly = true)
public Collection<Criterion> getCriterionsFor(ICriterionType<?> type) {
return criterionDAO.findByType(type);
}
@Override
public Criterion getCriterion() {
return criterion;
}
@Override
public ICriterionTreeModel getCriterionTreeModel() {
return criterionTreeModel;
}
@Override
public void prepareForCreate() {
this.criterionType = CriterionType.create();
this.criterionTreeModel = new CriterionTreeModel(criterionType);
}
@Override
public void prepareForCreate(CriterionType criterionType) {
this.criterionType = criterionType;
this.criterion = (Criterion) criterionType
.createCriterionWithoutNameYet();
}
@Override
public void prepareForRemove(CriterionType criterionType) {
this.criterionType = criterionType;
}
@Override
@Transactional(readOnly = true)
public void prepareForEdit(CriterionType criterionType) {
Validate.notNull(criterionType);
this.criterionType = getFromDB(criterionType);
this.criterionTreeModel = new CriterionTreeModel(this.criterionType);
}
@Override
@Transactional
public void remove(CriterionType criterionType) {
try {
criterionTypeDAO.remove(criterionType.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
}
@Transactional(readOnly = true)
private CriterionType getFromDB(CriterionType criterionType) {
try {
return criterionTypeDAO.find(criterionType.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
@Transactional(readOnly = true)
public ICriterionType<?> getTypeFor(Criterion criterion) {
for (ICriterionType<?> criterionType : getTypes()) {
if (criterionType.contains(criterion))
return criterionType;
}
throw new RuntimeException(_("{0} not found type for criterion ", criterion));
}
@Override
@Transactional
public void saveCriterionType() throws ValidationException {
InvalidValue[] invalidValues = criterionTypeValidator
.getInvalidValues(criterionType);
if (invalidValues.length > 0)
throw new ValidationException(invalidValues);
criterionTreeModel.saveCriterions(criterionType);
criterionTypeDAO.save(criterionType);
}
@Override
public boolean isEditing() {
return criterion != null;
}
@Override
@Transactional(readOnly = true)
public boolean isApplyableToWorkers(Criterion criterion) {
ICriterionType<?> type = getTypeFor(criterion);
return type != null && type.criterionCanBeRelatedTo(Worker.class);
}
@Override
@Transactional(readOnly = true)
public <T extends Resource> List<T> getResourcesSatisfyingCurrentCriterionOfType(
Class<T> klass) {
if (criterion == null)
return new ArrayList<T>();
return getResourcesSatisfying(klass, criterion);
}
private <T extends Resource> List<T> getResourcesSatisfying(
Class<T> resourceType, Criterion criterion) {
Validate.notNull(resourceType, _("ResourceType must be not-null"));
Validate.notNull(criterion, _("Criterion must be not-null"));
List<T> result = new ArrayList<T>();
for (T r : resourceDAO.list(resourceType)) {
if (criterion.isSatisfiedBy(r)) {
result.add(r);
}
}
return result;
}
@Override
@Transactional(readOnly = true)
public List<Worker> getAllWorkers() {
return resourceDAO.getWorkers();
}
@Override
public boolean getAllowHierarchy(){
return this.criterionType.allowHierarchy();
}
@Override
public void disableHierarchy(){
this.criterionTreeModel.flattenTree();
}
@Override
public void updateEnabledCriterions(boolean isChecked){
criterionTreeModel.updateEnabledCriterions(isChecked);
}
}

View file

@ -0,0 +1,51 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.navalplanner.web.resources.criterion;
import java.util.List;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionType;
import org.zkoss.zul.TreeModel;
/**
*
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public interface ICriterionTreeModel {
public TreeModel asTree();
void addCriterion(String name);
void addCriterionAt(CriterionDTO node,String name);
void move(CriterionDTO toBeMoved, CriterionDTO destination,int position);
void moveToRoot(CriterionDTO toBeMoved, int position);
void removeNode(CriterionDTO node);
void flattenTree();
void thereIsOtherWithSameNameAndType(String name)throws ValidationException;
void validateNameNotEmpty(String name)throws ValidationException;
void updateEnabledCriterions(boolean isChecked);
void updateEnabledCriterions(boolean isChecked,CriterionDTO criterion);
void saveCriterions(CriterionType criterionType);
void up(CriterionDTO node);
void down(CriterionDTO node);
void indent(CriterionDTO nodeToIndent);
void unindent(CriterionDTO nodeToIndent);
}

View file

@ -0,0 +1,57 @@
package org.navalplanner.web.resources.criterion;
import java.util.Collection;
import java.util.List;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionType;
import org.navalplanner.business.resources.entities.ICriterionType;
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker;
/**
* CriterionsModel contract <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public interface ICriterionsModel_V2 {
List<CriterionType> getTypes();
Collection<Criterion> getCriterionsFor(ICriterionType<?> type);
Criterion getCriterion();
ICriterionTreeModel getCriterionTreeModel();
ICriterionType<?> getCriterionType();
void prepareForCreate();
void prepareForCreate(CriterionType criterionType);
public void prepareForRemove(CriterionType criterionType);
public void prepareForEdit(CriterionType criterionType);
public void remove(CriterionType criterionType);
ICriterionType<?> getTypeFor(Criterion criterion);
void saveCriterionType() throws ValidationException;
boolean isEditing();
boolean isApplyableToWorkers(Criterion criterion);
<T extends Resource> List<T> getResourcesSatisfyingCurrentCriterionOfType(
Class<T> klass);
List<Worker> getAllWorkers();
boolean getAllowHierarchy();
void disableHierarchy();
void updateEnabledCriterions(boolean isChecked);
}

View file

@ -290,7 +290,7 @@ public class WorkerModel implements IWorkerModel {
ICriterionType<?> type) {
Validate
.isTrue(
type.allowSimultaneousCriterionsPerResource(),
type.isAllowSimultaneousCriterionsPerResource(),
_("Must allow multiple active criterions for this type to use this assignment strategy"));
this.criterionDAO = criterionDAO;
this.resource = resource;

View file

@ -0,0 +1,27 @@
<panel title="${i18n:_('Asociated Criterions')}" border="normal">
<panelchildren>
<vbox id="criterionsTree">
<vbox>
<hbox align="center">
<textbox value="" id="criterionName" width="200px"/>
<button id="add_new_criterion" label="${i18n:_('New criterion')}"
onClick="criterionTreeController.addCriterion();"/>
</hbox>
</vbox>
<vbox>
<tree id="tree" rows="10" multiple="true" droppable="true"
onDrop="criterionTreeController.move(self, event.dragged)"
model="@{criterionTreeController.criterionTreeModel}"
treeitemRenderer="@{criterionTreeController.renderer}" pageSize="10"
sclass="orderTree" fixedLayout="true">
<treecols sizable="true">
<treecol label="${i18n:_('Name')}" />
<treecol width="60px" align="center" label="${i18n:_('Active')}" />
<treecol width="150px" align="center" label="${i18n:_('Operations')}" />
</treecols>
</tree>
</vbox>
</vbox>
<separator bar="false" spacing="40px" orient="vertical"/>
</panelchildren>
</panel>

View file

@ -0,0 +1,53 @@
<?component name="criterionsTree" inline="true" macroURI="_criterionsTree.zul"?>
<window id="${arg.top_id}" title="${arg.title}">
<tabbox>
<tabs>
<tab label="${i18n:_('Edit')}" width="850"></tab>
</tabs>
<tabpanels>
<tabpanel>
<grid fixedLayout="true" width="800px">
<columns>
<column width="300px"/>
<column width="400px"/>
</columns>
<rows>
<row>
<label value="${i18n:_('Name')}" />
<textbox value="@{controller.criterionType.name}"/>
</row>
<row>
<label value="${i18n:_('Multiple values per resource')}"/>
<checkbox checked="@{controller.criterionType.allowSimultaneousCriterionsPerResource}"/>
</row>
<row>
<label value="${i18n:_('Hierarchy')}" />
<checkbox checked="@{controller.criterionType.allowHierarchy}"
onCheck="controller.confirmDisabledHierarchy(self);" />
</row>
<row>
<label value="${i18n:_('Enabled')}" />
<checkbox checked="@{controller.criterionType.enabled}"
onCheck="controller.changeEnabled(self);"/>
</row>
<row>
<label value="${i18n:_('Description')}" />
<textbox value="@{controller.criterionType.description}" rows="3" width="300px"/>
</row>
</rows>
</grid>
<separator bar="false" spacing="40px" orient="vertical"/>
<criterionsTree/>
</tabpanel>
</tabpanels>
</tabbox>
<hbox>
<button id="save" onClick="controller.saveAndClose();"
label="${i18n:_('Save')}"/>
<button id="save_and_continue" onClick="controller.saveAndContinue();"
label="${i18n:_('Save &amp; Continue')}"/>
<button id="close" onClick="controller.close();"
label="${i18n:_('Close')}"/>
</hbox>
</window>

View file

@ -0,0 +1,33 @@
<window id="listing" title="${i18n:_('Criterion type list')}">
<grid model="@{controller.criterionTypes}" fixedLayout="true">
<columns>
<column label="${i18n:_('Name')}" sort="auto(name)"/>
<column width="60px" label="${i18n:_('Enabled')}"/>
<column width="200px" label="${i18n:_('Operations')}"/>
</columns>
<rows>
<row self="@{each='criterionType'}" value="@{criterionType}">
<label value="@{criterionType.name}"/>
<checkbox disabled="true" checked="@{criterionType.enabled}"/>
<hbox>
<button visible="@{criterionType.enabled}" sclass="icono" image="/common/img/ico_editar1.png"
hoverImage="/common/img/ico_editar.png"
tooltiptext="${i18n:_('Edit')}" disabled="@{criterionType.immutable}" onClick="controller.goToEditForm(self.parent.parent.value);">
</button>
<button visible="@{criterionType.immutable}" sclass="icono" image="/common/img/ico_editar_out.png"
tooltiptext="${i18n:_('Not editable')}" disabled="@{criterionType.immutable}">
</button>
<button visible="false" sclass="icono" image="/common/img/ico_borrar1.png"
hoverImage="/common/img/ico_borrar.png"
tooltiptext="${i18n:_('Delete')}" disabled="@{criterionType.immutable}" onClick="controller.confirmRemove(self.parent.parent.value);">
</button>
<button visible="true" sclass="icono" image="/common/img/ico_borrar_out.png"
tooltiptext="${i18n:_('Not deletable')}" disabled="@{criterionType.immutable}">
</button>
</hbox>
</row>
</rows>
</grid>
<button id="show_create_form" onClick="controller.goToCreateForm();" label="${i18n:_('Create')}">
</button>
</window>

View file

@ -0,0 +1,51 @@
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<?page id="criterions_admin"?>
<?init class="org.zkoss.zk.ui.util.Composition" arg0="/common/layout/template.zul"?>
<?link rel="stylesheet" type="text/css" href="/common/css/navalpro_v01.css"?>
<?link rel="stylesheet" type="text/css" href="/common/css/navalpro_zk.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-V2.zul"?>
<?component name="edition" inline="true" macroURI="_edition-V2.zul"?>
<zk>
<window self="@{define(content)}"
apply="org.navalplanner.web.resources.criterion.CriterionAdminController_V2">
<vbox id="messagesContainer"></vbox>
<list top_id="listWindow" />
<edition top_id="createComponent" title="${i18n:_('Create')}"
save_button_label="${i18n:_('Save')}" cancel_button_label="${i18n:_('Cancel')}" />
<edition top_id="editComponent" title="${i18n:_('Edit')}"
save_button_label="${i18n:_('Save')}" cancel_button_label="${i18n:_('Cancel')}" />
<window visible="@{controller.confirmingRemove}"
id="confirmRemove" title="${i18n:_('Confirm')}" sizable="true"
position="center">
<vbox align = "center">
<hbox align = "center">
<label value = "Confirm deleting "/>
<label value = "@{controller.criterionType.name}"/>
<label value = "?"/>
</hbox>
<hbox align = "center">
<button label="${i18n:_('Yes')}"
onClick="controller.remove(controller.criterionType);" />
<button label="${i18n:_('No')}"
onClick="controller.cancelRemove();" />
</hbox>
</vbox>
</window>
<window visible="@{controller.confirmingDisEnabledHierarchy}"
id="confirmDisabledHierarchy" title="${i18n:_('Warning')}" sizable="true"
position="center">
<vbox align = "center">
<label value = "Disenable the Hierarchy property flatten the tree."/>
<label value = "Continue?"/>
<hbox align = "center">
<button label="${i18n:_('Ok')}"
onClick="controller.okDisEnabledHierarchy();" />
<button label="${i18n:_('Cancel')}"
onClick="controller.cancelDisEnabledHierarchy();" />
</hbox>
</vbox>
</window>
</window>
</zk>

View file

@ -381,7 +381,7 @@ public class OrderModelTest {
@Override
public Criterion execute() {
CriterionType criterionType = CriterionType.create("test"
+ UUID.randomUUID());
+ UUID.randomUUID(),"");
criterionTypeDAO.save(criterionType);
Criterion criterion = Criterion.create("Test"
+ UUID.randomUUID(), criterionType);

View file

@ -88,7 +88,7 @@ public class CriterionModelTest {
}
public static CriterionType createValidCriterionType(String name) {
return CriterionType.create(name);
return CriterionType.create(name,"");
}
public static CriterionType createValidCriterionType() {
@ -128,7 +128,7 @@ public class CriterionModelTest {
return criterionTypeDAO.findByName(transientType).get(0);
}
@Test
/*@Test
@NotTransactional
public void modificationsAreSaved() throws Exception {
adHocTransactionService.runOnTransaction(new IOnTransaction<Void>() {
@ -156,7 +156,7 @@ public class CriterionModelTest {
}
});
assertThat(retrieved.getName(), equalTo(newName));
}
}*/
@Test
public void modifyingDontAlterTheNumberOfCriterions() throws Exception {