Unify editable validation and javax validation.

This commit is contained in:
robin shine 2013-10-17 21:15:03 +08:00
parent 428d0fc510
commit 7712a31f3f
35 changed files with 216 additions and 365 deletions

View File

@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -43,6 +44,7 @@ public class Bootstrap {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void main(String[] args) { public static void main(String[] args) {
Locale.setDefault(Locale.US);
File sandboxDir = new File("target/sandbox"); File sandboxDir = new File("target/sandbox");
if (sandboxDir.exists()) { if (sandboxDir.exists()) {

View File

@ -2,16 +2,20 @@ package com.pmease.commons.editable;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.pmease.commons.util.GeneralException; import javax.validation.ConstraintViolation;
import javax.validation.Path;
import javax.validation.Validator;
import com.pmease.commons.loader.AppLoader;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public abstract class AbstractEditContext implements EditContext { public abstract class AbstractEditContext implements EditContext {
protected List<String> validationErrorMessages = new ArrayList<String>(); protected List<String> validationErrors = new ArrayList<String>();
private final Serializable bean; private final Serializable bean;
@ -25,62 +29,77 @@ public abstract class AbstractEditContext implements EditContext {
} }
@Override @Override
public List<ValidationError> getValidationErrors(boolean recursive) { public List<String> getValidationErrors() {
List<ValidationError> validationErrors = new ArrayList<ValidationError>(); return validationErrors;
for (String each: validationErrorMessages) { }
validationErrors.add(new ValidationError(each));
public boolean hasValidationError() {
if (!validationErrors.isEmpty())
return true;
for (EditContext each: getChildContexts().values()) {
if (each.hasValidationError())
return true;
} }
if (recursive && getChildContexts() != null) { return false;
for (Map.Entry<Serializable, EditContext> eachEntry: getChildContexts().entrySet()) {
for (ValidationError eachError: eachEntry.getValue().getValidationErrors(true)) {
PropertyPath newPath = eachError.getPropertyPath().prepend(eachEntry.getKey());
validationErrors.add(new ValidationError(newPath, eachError.getErrorMessage()));
}
}
}
return Collections.unmodifiableList(validationErrors);
} }
@Override @Override
public void validate() { public void validate() {
validationErrorMessages.clear(); clearValidationErrors();
if (getChildContexts() != null) { updateBean();
for (EditContext each: getChildContexts().values())
each.validate(); for (ConstraintViolation<Serializable> violation: AppLoader.getInstance(Validator.class).validate(bean)) {
List<Serializable> contextPath = new ArrayList<Serializable>();
for (Path.Node node: violation.getPropertyPath()) {
if (node.getIndex() != null)
contextPath.add(node.getIndex());
if (node.getName() != null)
contextPath.add(node.getName());
}
findChildContext(contextPath, false).addValidationError(violation.getMessage());
} }
doValidation();
} }
protected abstract void doValidation();
@Override @Override
public void error(String errorMessage) { public void clearValidationErrors() {
validationErrorMessages.add(errorMessage); validationErrors.clear();
for (EditContext each: getChildContexts().values())
each.clearValidationErrors();
}
@Override
public void updateBean() {
for (EditContext each: getChildContexts().values())
each.updateBean();
}
@Override
public void addValidationError(String errorMessage) {
validationErrors.add(errorMessage);
} }
@Override @Override
public EditContext getChildContext(Serializable propertyName) { public EditContext findChildContext(List<Serializable> contextPath, boolean exactMatch) {
if (getChildContexts() != null) { if (contextPath.size() == 0)
EditContext childContext = getChildContexts().get(propertyName); return this;
if (childContext != null)
return childContext; contextPath = new ArrayList<>(contextPath);
} Serializable pathElement = contextPath.remove(0);
EditContext childContext = getChildContexts().get(pathElement);
throw new GeneralException("Unable to find child context of property '%s'", propertyName); if (childContext != null)
return childContext.findChildContext(contextPath, exactMatch);
else if (!exactMatch)
return this;
else
return null;
} }
@Override @Override
public boolean hasValidationError(Serializable propertyName, boolean recursive) { public Map<Serializable, EditContext> getChildContexts() {
EditContext childContext = getChildContext(propertyName); return new HashMap<>();
return !childContext.getValidationErrors(recursive).isEmpty();
} }
@Override
public boolean hasValidationError(boolean recursive) {
return !getValidationErrors(recursive).isEmpty();
}
} }

View File

@ -2,6 +2,7 @@ package com.pmease.commons.editable;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -61,18 +62,7 @@ public abstract class AbstractPolymorphicPropertyEditContext extends PropertyEdi
if (valueContext != null) if (valueContext != null)
return valueContext.getChildContexts(); return valueContext.getChildContexts();
else else
return null; return new HashMap<>();
}
@Override
protected void doValidation() {
super.doValidation();
// redirect error message of bean level of the property value to be directly
// under this property
if (valueContext != null && valueContext.getBean() instanceof Validatable) {
((Validatable)valueContext.getBean()).validate(this);
}
} }
} }

View File

@ -36,7 +36,7 @@ public abstract class AbstractReflectionBeanEditContext extends BeanEditContext
@Override @Override
public Map<Serializable, EditContext> getChildContexts() { public Map<Serializable, EditContext> getChildContexts() {
Map<Serializable, EditContext> childContexts = new LinkedHashMap<Serializable, EditContext>(); Map<Serializable, EditContext> childContexts = new LinkedHashMap<>();
for (PropertyEditContext each: propertyContexts) { for (PropertyEditContext each: propertyContexts) {
childContexts.put(each.getPropertyName(), each); childContexts.put(each.getPropertyName(), each);
} }

View File

@ -1,6 +1,7 @@
package com.pmease.commons.editable; package com.pmease.commons.editable;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.pmease.commons.loader.AppLoader; import com.pmease.commons.loader.AppLoader;
@ -41,18 +42,7 @@ public abstract class AbstractReflectionPropertyEditContext extends PropertyEdit
if (valueContext != null) if (valueContext != null)
return valueContext.getChildContexts(); return valueContext.getChildContexts();
else else
return null; return new HashMap<>();
} }
@Override
protected void doValidation() {
super.doValidation();
// redirect error message of bean level of the property value to be directly
// under this property
if (valueContext != null && valueContext.getBean() instanceof Validatable) {
((Validatable)valueContext.getBean()).validate(this);
}
}
} }

View File

@ -3,8 +3,6 @@ package com.pmease.commons.editable;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -104,17 +102,18 @@ public abstract class AbstractTableListPropertyEditContext extends PropertyEditC
@Override @Override
public Map<Serializable, EditContext> getChildContexts() { public Map<Serializable, EditContext> getChildContexts() {
Map<Serializable, EditContext> childContexts = new LinkedHashMap<Serializable, EditContext>(); Map<Serializable, EditContext> childContexts = new LinkedHashMap<>();
if (elementContexts != null) { if (elementContexts != null) {
for (int i=0; i<elementContexts.size(); i++) { for (int i=0; i<elementContexts.size(); i++) {
final String errorMessagePrefix = "row " + (i+1) + ": "; final String errorMessagePrefix = "Row " + (i+1) + ": ";
final List<PropertyEditContext> elementPropertyContexts = elementContexts.get(i); final List<PropertyEditContext> elementPropertyContexts = elementContexts.get(i);
EditContext elementContext = new AbstractEditContext(getPropertyValue().get(i)) { EditContext elementContext = new AbstractEditContext(getPropertyValue().get(i)) {
@Override @Override
public Map<Serializable, EditContext> getChildContexts() { public Map<Serializable, EditContext> getChildContexts() {
Map<Serializable, EditContext> childContexts = new LinkedHashMap<Serializable, EditContext>(); Map<Serializable, EditContext> childContexts = new LinkedHashMap<>();
for (PropertyEditContext each: elementPropertyContexts) for (PropertyEditContext each: elementPropertyContexts)
childContexts.put(each.getPropertyName(), each); childContexts.put(each.getPropertyName(), each);
return childContexts; return childContexts;
@ -131,39 +130,8 @@ public abstract class AbstractTableListPropertyEditContext extends PropertyEditC
} }
@Override @Override
public List<ValidationError> getValidationErrors(boolean recursive) { public void addValidationError(String errorMessage) {
List<ValidationError> validationErrors = new ArrayList<ValidationError>(); AbstractTableListPropertyEditContext.this.addValidationError(errorMessagePrefix + errorMessage);
for (String each: AbstractTableListPropertyEditContext.this.validationErrorMessages) {
if (each.startsWith(errorMessagePrefix))
validationErrors.add(new ValidationError(each.substring(errorMessagePrefix.length())));
}
if (recursive) {
for (Map.Entry<Serializable, EditContext> eachEntry: getChildContexts().entrySet()) {
for (ValidationError eachError: eachEntry.getValue().getValidationErrors(true)) {
PropertyPath newPath = eachError.getPropertyPath().prepend(eachEntry.getKey());
validationErrors.add(new ValidationError(newPath, eachError.getErrorMessage()));
}
}
}
return Collections.unmodifiableList(validationErrors);
}
@Override
public void error(String errorMessage) {
AbstractTableListPropertyEditContext.this.error(errorMessagePrefix + errorMessage);
}
@Override
public void doValidation() {
for (Iterator<String> it = AbstractTableListPropertyEditContext.this.validationErrorMessages.iterator(); it.hasNext();) {
if (it.next().startsWith(errorMessagePrefix))
it.remove();
}
if (getBean() instanceof Validatable) {
((Validatable)getBean()).validate(this);
}
} }
}; };

View File

@ -9,11 +9,4 @@ public abstract class BeanEditContext extends AbstractEditContext {
super(bean); super(bean);
} }
@Override
protected void doValidation() {
if (getBean() instanceof Validatable) {
((Validatable)getBean()).validate(this);
}
}
} }

View File

@ -8,19 +8,21 @@ public interface EditContext extends Serializable {
Serializable getBean(); Serializable getBean();
void updateBean();
void validate(); void validate();
List<ValidationError> getValidationErrors(boolean recursive); List<String> getValidationErrors();
void clearValidationErrors();
boolean hasValidationError();
Map<Serializable, EditContext> getChildContexts(); Map<Serializable, EditContext> getChildContexts();
EditContext getChildContext(Serializable propertyName); EditContext findChildContext(List<Serializable> contextPath, boolean exactMatch);
boolean hasValidationError(Serializable propertyName, boolean recursive); void addValidationError(String errorMessage);
boolean hasValidationError(boolean recursive);
void error(String errorMessage);
Object renderForEdit(Object renderParam); Object renderForEdit(Object renderParam);

View File

@ -114,21 +114,6 @@ public class EditableUtils {
return null; return null;
} }
public static void validate(Serializable bean) {
EditContext context = AppLoader.getInstance(EditSupportRegistry.class).getBeanEditContext(bean);
context.validate();
List<ValidationError> errors = context.getValidationErrors(true);
if (!errors.isEmpty()) {
StringBuffer buffer = new StringBuffer();
for (ValidationError error: errors) {
buffer.append(error.toString()).append("\n");
}
throw new ValidationException(buffer.toString());
}
}
public static boolean isPropertyRequired(Method propertyGetter) { public static boolean isPropertyRequired(Method propertyGetter) {
if (propertyGetter.getReturnType().isPrimitive() && propertyGetter.getReturnType() != boolean.class if (propertyGetter.getReturnType().isPrimitive() && propertyGetter.getReturnType() != boolean.class
|| propertyGetter.getAnnotation(NotNull.class) != null || propertyGetter.getAnnotation(NotNull.class) != null

View File

@ -4,10 +4,6 @@ import java.io.Serializable;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import com.pmease.commons.loader.AppLoader;
import com.pmease.commons.util.BeanUtils; import com.pmease.commons.util.BeanUtils;
import com.pmease.commons.util.ExceptionUtils; import com.pmease.commons.util.ExceptionUtils;
import com.pmease.commons.util.ReflectionUtils; import com.pmease.commons.util.ReflectionUtils;
@ -58,13 +54,6 @@ public abstract class PropertyEditContext extends AbstractEditContext {
} }
} }
protected void doValidation() {
Validator validator = AppLoader.getInstance(Validator.class);
for (ConstraintViolation<Serializable> violation: validator.validateProperty(getBean(), getPropertyName())) {
error(violation.getMessage());
}
}
public Serializable instantiate(Class<?> clazz) { public Serializable instantiate(Class<?> clazz) {
try { try {
Constructor<?> constructor = ReflectionUtils.findConstructor(clazz, getBean().getClass()); Constructor<?> constructor = ReflectionUtils.findConstructor(clazz, getBean().getClass());

View File

@ -1,51 +0,0 @@
package com.pmease.commons.editable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@SuppressWarnings("serial")
public class PropertyPath implements Serializable {
private final List<Serializable> elements;
public PropertyPath() {
this.elements = new ArrayList<Serializable>();
}
public PropertyPath(List<Serializable> elements) {
this.elements = new ArrayList<Serializable>(elements);
}
public List<Serializable> getElements() {
return Collections.unmodifiableList(elements);
}
public PropertyPath prepend(Serializable element) {
PropertyPath newPath = new PropertyPath(elements);
newPath.elements.add(0, element);
return newPath;
}
public PropertyPath append(Serializable element) {
PropertyPath newPath = new PropertyPath(elements);
newPath.elements.add(element);
return newPath;
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
for (Serializable element: elements) {
if (element instanceof String) {
if (buffer.length() != 0)
buffer.append(".");
buffer.append(element);
} else {
buffer.append("[").append(element.toString()).append("]");
}
}
return buffer.toString();
}
}

View File

@ -1,7 +0,0 @@
package com.pmease.commons.editable;
public interface Validatable {
void validate(EditContext editContext);
}

View File

@ -1,37 +0,0 @@
package com.pmease.commons.editable;
import java.io.Serializable;
@SuppressWarnings("serial")
public class ValidationError implements Serializable {
private final PropertyPath propertyPath;
private final String errorMessage;
public ValidationError(PropertyPath propertyPath, String errorMessage) {
this.propertyPath = propertyPath;
this.errorMessage = errorMessage;
}
public ValidationError(String errorMessage) {
this(new PropertyPath(), errorMessage);
}
public PropertyPath getPropertyPath() {
return propertyPath;
}
public String getErrorMessage() {
return errorMessage;
}
@Override
public String toString() {
if (!propertyPath.getElements().isEmpty())
return propertyPath + ": " + errorMessage;
else
return errorMessage;
}
}

View File

@ -1,12 +0,0 @@
package com.pmease.commons.editable;
import com.pmease.commons.util.GeneralException;
@SuppressWarnings("serial")
public class ValidationException extends GeneralException {
public ValidationException(String format, Object... args) {
super(format, args);
}
}

View File

@ -0,0 +1,24 @@
package com.pmease.commons.validation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ClassValidatingValidator.class)
@Documented
public @interface ClassValidating {
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

View File

@ -0,0 +1,20 @@
package com.pmease.commons.validation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;
public class ClassValidatingValidator implements ConstraintValidator<ClassValidating, Validatable> {
public void initialize(ClassValidating constraintAnnotation) {
}
public boolean isValid(Validatable value, ConstraintValidatorContext constraintValidatorContext) {
ConstraintValidatorContextImpl impl = (ConstraintValidatorContextImpl)constraintValidatorContext;
impl.disableDefaultConstraintViolation();
value.validate(constraintValidatorContext);
return impl.getMessageAndPathList().isEmpty();
}
}

View File

@ -0,0 +1,7 @@
package com.pmease.commons.validation;
import javax.validation.ConstraintValidatorContext;
public interface Validatable {
void validate(ConstraintValidatorContext constraintValidatorContext);
}

View File

@ -42,7 +42,7 @@ public class ManualConfigStep implements WizardStep {
@Override @Override
public boolean complete() { public boolean complete() {
editContext.validate(); editContext.validate();
if (editContext.hasValidationError(true)) { if (editContext.hasValidationError()) {
return false; return false;
} else { } else {
config.complete(); config.complete();

View File

@ -1,7 +1,6 @@
package com.pmease.commons.wicket.editable.bool; package com.pmease.commons.wicket.editable.bool;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map;
import org.apache.wicket.Component; import org.apache.wicket.Component;
import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.ComponentTag;
@ -9,7 +8,6 @@ import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.model.IModel; import org.apache.wicket.model.IModel;
import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.PropertyEditContext; import com.pmease.commons.editable.PropertyEditContext;
import com.pmease.commons.wicket.editable.EditableResourceBehavior; import com.pmease.commons.wicket.editable.EditableResourceBehavior;
@ -55,9 +53,4 @@ public class BooleanPropertyEditContext extends PropertyEditContext {
return new Label((String) renderParam, getPropertyValue().toString()); return new Label((String) renderParam, getPropertyValue().toString());
} }
@Override
public Map<Serializable, EditContext> getChildContexts() {
return null;
}
} }

View File

@ -1,7 +1,6 @@
package com.pmease.commons.wicket.editable.bool; package com.pmease.commons.wicket.editable.bool;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map;
import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.basic.Label;
@ -9,7 +8,6 @@ import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.model.IModel; import org.apache.wicket.model.IModel;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.PropertyEditContext; import com.pmease.commons.editable.PropertyEditContext;
import com.pmease.commons.wicket.editable.EditableResourceBehavior; import com.pmease.commons.wicket.editable.EditableResourceBehavior;
@ -77,9 +75,4 @@ public class NullableBooleanPropertyEditContext extends PropertyEditContext {
} }
} }
@Override
public Map<Serializable, EditContext> getChildContexts() {
return null;
}
} }

View File

@ -43,11 +43,14 @@ table.reflection input[type="text"], table.reflection select {
width: 100%; width: 100%;
height: 32px; height: 32px;
font-size: 13px; font-size: 13px;
} }
div.reflection div.name { div.reflection div.name {
font-weight: bold; font-weight: bold;
} }
div.reflection select.type, div.reflectio input.enable { div.reflection select.type, div.reflectio input.enable {
margin-bottom: 15px; margin-bottom: 15px;
}
table.reflection .right-spacing {
margin-right: 8px;
} }

View File

@ -20,7 +20,6 @@ import org.apache.wicket.model.IModel;
import com.pmease.commons.editable.BeanEditContext; import com.pmease.commons.editable.BeanEditContext;
import com.pmease.commons.editable.EditableUtils; import com.pmease.commons.editable.EditableUtils;
import com.pmease.commons.editable.ValidationError;
import com.pmease.commons.wicket.WicketUtils; import com.pmease.commons.wicket.WicketUtils;
import com.pmease.commons.wicket.editable.EditableResourceBehavior; import com.pmease.commons.wicket.editable.EditableResourceBehavior;
@ -157,19 +156,18 @@ public class PolymorphicListPropertyEditor extends Panel {
}.setDefaultFormProcessing(false)); }.setDefaultFormProcessing(false));
item.add(new ListView<ValidationError>("elementValidationErrors", item.getModelObject().getValidationErrors(false)) { item.add(new ListView<String>("elementValidationErrors", item.getModelObject().getValidationErrors()) {
@Override @Override
protected void populateItem(ListItem<ValidationError> item) { protected void populateItem(ListItem<String> item) {
ValidationError error = item.getModelObject(); item.add(new Label("propertyValidationError", item.getModelObject()));
item.add(new Label("propertyValidationError", error.toString()));
} }
@Override @Override
protected void onConfigure() { protected void onConfigure() {
super.onConfigure(); super.onConfigure();
setVisible(!item.getModelObject().getValidationErrors(false).isEmpty()); setVisible(!item.getModelObject().getValidationErrors().isEmpty());
} }
}); });

View File

@ -24,7 +24,6 @@ import org.apache.wicket.model.LoadableDetachableModel;
import com.pmease.commons.editable.EditContext; import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.EditableUtils; import com.pmease.commons.editable.EditableUtils;
import com.pmease.commons.editable.PropertyEditContext; import com.pmease.commons.editable.PropertyEditContext;
import com.pmease.commons.editable.ValidationError;
import com.pmease.commons.wicket.WicketUtils; import com.pmease.commons.wicket.WicketUtils;
import com.pmease.commons.wicket.editable.EditableResourceBehavior; import com.pmease.commons.wicket.editable.EditableResourceBehavior;
@ -135,25 +134,24 @@ public class TableListPropertyEditor extends Panel {
final PropertyEditContext elementPropertyContext = columnItem.getModelObject(); final PropertyEditContext elementPropertyContext = columnItem.getModelObject();
columnItem.add((Component)elementPropertyContext.renderForEdit("elementPropertyEditor")); columnItem.add((Component)elementPropertyContext.renderForEdit("elementPropertyEditor"));
columnItem.add(new ListView<ValidationError>("propertyValidationErrors", elementPropertyContext.getValidationErrors(false)) { columnItem.add(new ListView<String>("propertyValidationErrors", elementPropertyContext.getValidationErrors()) {
@Override @Override
protected void populateItem(ListItem<ValidationError> item) { protected void populateItem(ListItem<String> item) {
ValidationError error = item.getModelObject(); item.add(new Label("propertyValidationError", item.getModelObject()));
item.add(new Label("propertyValidationError", error.toString()));
} }
@Override @Override
protected void onConfigure() { protected void onConfigure() {
super.onConfigure(); super.onConfigure();
setVisible(!elementPropertyContext.getValidationErrors(false).isEmpty()); setVisible(!elementPropertyContext.getValidationErrors().isEmpty());
} }
}); });
Map<Serializable, EditContext> childContexts = elementPropertyContext.getChildContexts(); Map<Serializable, EditContext> childContexts = elementPropertyContext.getChildContexts();
if ((childContexts == null || childContexts.isEmpty()) && !elementPropertyContext.getValidationErrors(false).isEmpty()) if (childContexts.isEmpty() && !elementPropertyContext.getValidationErrors().isEmpty())
columnItem.add(AttributeModifier.append("class", "has-error")); columnItem.add(AttributeModifier.append("class", "has-error"));
} }

View File

@ -1,7 +1,6 @@
package com.pmease.commons.wicket.editable.nuemric; package com.pmease.commons.wicket.editable.nuemric;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map;
import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.basic.Label;
@ -9,7 +8,6 @@ import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel; import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model; import org.apache.wicket.model.Model;
import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.PropertyEditContext; import com.pmease.commons.editable.PropertyEditContext;
import com.pmease.commons.wicket.editable.EditableResourceBehavior; import com.pmease.commons.wicket.editable.EditableResourceBehavior;
@ -58,14 +56,16 @@ public class NumericPropertyEditContext extends PropertyEditContext {
} }
@Override @Override
protected void doValidation() { public void updateBean() {
String input = inputModel.getObject(); String input = inputModel.getObject();
Serializable convertedInput; Serializable convertedInput;
boolean isInt = getPropertyGetter().getReturnType() == int.class || getPropertyGetter().getReturnType() == Integer.class;
try { try {
if (input != null) { if (input != null) {
if (getPropertyGetter().getReturnType() == int.class || getPropertyGetter().getReturnType() == Integer.class) if (isInt)
convertedInput = Integer.valueOf(input); convertedInput = Integer.valueOf(input);
else else
convertedInput = Long.valueOf(input); convertedInput = Long.valueOf(input);
@ -73,19 +73,16 @@ public class NumericPropertyEditContext extends PropertyEditContext {
convertedInput = null; convertedInput = null;
} }
setPropertyValue(convertedInput); setPropertyValue(convertedInput);
} catch (NumberFormatException e) {
error("Expects a number here.");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
error("Please specify a number here."); addValidationError("Expects a number here.");
if (isInt)
setPropertyValue(Integer.MIN_VALUE);
else
setPropertyValue(Long.MIN_VALUE);
} }
if (!hasValidationError(true)) super.updateBean();
super.doValidation();
}
@Override
public Map<Serializable, EditContext> getChildContexts() {
return null;
} }
} }

View File

@ -1,12 +1,10 @@
package com.pmease.commons.wicket.editable.password; package com.pmease.commons.wicket.editable.password;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map;
import org.apache.shiro.authc.credential.PasswordService; import org.apache.shiro.authc.credential.PasswordService;
import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.basic.Label;
import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.PropertyEditContext; import com.pmease.commons.editable.PropertyEditContext;
import com.pmease.commons.loader.AppLoader; import com.pmease.commons.loader.AppLoader;
@ -36,23 +34,17 @@ public class ConfirmativePasswordPropertyEditContext extends PropertyEditContext
} }
@Override @Override
protected void doValidation() { public void updateBean() {
if (password == null) if (password == null)
error("Please specify the password."); addValidationError("Please specify the password.");
else if (confirmedPassword == null) else if (confirmedPassword == null)
error("Please confirm the password."); addValidationError("Please confirm the password.");
else if (!password.equals(confirmedPassword)) else if (!password.equals(confirmedPassword))
error("Password and its confirmation should be identical."); addValidationError("Password and its confirmation should be identical.");
else else
setPropertyValue(AppLoader.getInstance(PasswordService.class).encryptPassword(password)); setPropertyValue(AppLoader.getInstance(PasswordService.class).encryptPassword(password));
if (!hasValidationError(true)) super.updateBean();
super.doValidation();
}
@Override
public Map<Serializable, EditContext> getChildContexts() {
return null;
} }
public String getPassword() { public String getPassword() {

View File

@ -1,14 +1,12 @@
package com.pmease.commons.wicket.editable.password; package com.pmease.commons.wicket.editable.password;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map;
import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.PasswordTextField; import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.model.IModel; import org.apache.wicket.model.IModel;
import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.PropertyEditContext; import com.pmease.commons.editable.PropertyEditContext;
import com.pmease.commons.wicket.editable.EditableResourceBehavior; import com.pmease.commons.wicket.editable.EditableResourceBehavior;
@ -65,9 +63,4 @@ public class PasswordPropertyEditContext extends PropertyEditContext {
} }
} }
@Override
public Map<Serializable, EditContext> getChildContexts() {
return null;
}
} }

View File

@ -13,20 +13,22 @@
<wicket:fragment wicket:id="default"> <wicket:fragment wicket:id="default">
<div class="reflection editor"> <div class="reflection editor">
<div wicket:id="properties" class="form-group"> <div wicket:id="properties" class="form-group">
<div class="name control-label"> <label class="name control-label">
<span wicket:id="name"></span> <span wicket:id="name"></span>
<span wicket:id="required" class="required"></span> <span wicket:id="required" class="required"></span>
</div> </label>
<div class="value"> <div class="value">
<div wicket:id="value"></div> <div wicket:id="value"></div>
<span wicket:id="description" class="help-block"></span> <div wicket:id="hint">
<wicket:enclosure child="propertyValidationErrors"> <span wicket:id="description" class="help-block"></span>
<ul class="help-block"> <wicket:enclosure child="propertyValidationErrors">
<li wicket:id="propertyValidationErrors"> <ul class="help-block">
<span wicket:id="propertyValidationError"></span> <li wicket:id="propertyValidationErrors">
</li> <span wicket:id="propertyValidationError"></span>
</ul> </li>
</wicket:enclosure> </ul>
</wicket:enclosure>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -41,14 +43,16 @@
</td> </td>
<td class="value"> <td class="value">
<div wicket:id="value"></div> <div wicket:id="value"></div>
<span wicket:id="description" class="help-block"></span> <div wicket:id="hint">
<wicket:enclosure child="propertyValidationErrors"> <span wicket:id="description" class="help-block"></span>
<ul class="help-block"> <wicket:enclosure child="propertyValidationErrors">
<li wicket:id="propertyValidationErrors"> <ul class="help-block">
<span wicket:id="propertyValidationError"></span> <li wicket:id="propertyValidationErrors">
</li> <span wicket:id="propertyValidationError"></span>
</ul> </li>
</wicket:enclosure> </ul>
</wicket:enclosure>
</div>
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -6,6 +6,7 @@ import java.util.Map;
import org.apache.wicket.AttributeModifier; import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component; import org.apache.wicket.Component;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.list.ListView;
@ -16,7 +17,6 @@ import org.apache.wicket.model.LoadableDetachableModel;
import com.pmease.commons.editable.EditContext; import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.EditableUtils; import com.pmease.commons.editable.EditableUtils;
import com.pmease.commons.editable.PropertyEditContext; import com.pmease.commons.editable.PropertyEditContext;
import com.pmease.commons.editable.ValidationError;
import com.pmease.commons.editable.annotation.TableLayout; import com.pmease.commons.editable.annotation.TableLayout;
import com.pmease.commons.wicket.editable.EditableResourceBehavior; import com.pmease.commons.wicket.editable.EditableResourceBehavior;
@ -37,19 +37,18 @@ public class ReflectionBeanEditor extends Panel {
add(new EditableResourceBehavior()); add(new EditableResourceBehavior());
add(new ListView<ValidationError>("beanValidationErrors", new LoadableDetachableModel<List<ValidationError>>() { add(new ListView<String>("beanValidationErrors", new LoadableDetachableModel<List<String>>() {
@Override @Override
protected List<ValidationError> load() { protected List<String> load() {
return editContext.getValidationErrors(false); return editContext.getValidationErrors();
} }
}) { }) {
@Override @Override
protected void populateItem(ListItem<ValidationError> item) { protected void populateItem(ListItem<String> item) {
ValidationError error = item.getModelObject(); item.add(new Label("beanValidationError", item.getModelObject()));
item.add(new Label("beanValidationError", error.toString()));
} }
@Override @Override
@ -87,32 +86,36 @@ public class ReflectionBeanEditor extends Panel {
item.add((Component)propertyContext.renderForEdit("value")); item.add((Component)propertyContext.renderForEdit("value"));
WebMarkupContainer hint = new WebMarkupContainer("hint");
String description = EditableUtils.getDescription(propertyContext.getPropertyGetter()); String description = EditableUtils.getDescription(propertyContext.getPropertyGetter());
if (description != null) if (description != null)
item.add(new Label("description", description).setEscapeModelStrings(false)); hint.add(new Label("description", description).setEscapeModelStrings(false));
else else
item.add(new Label("description").setVisible(false)); hint.add(new Label("description").setVisible(false));
item.add(new ListView<ValidationError>("propertyValidationErrors", propertyContext.getValidationErrors(false)) { hint.add(new ListView<String>("propertyValidationErrors", propertyContext.getValidationErrors()) {
@Override @Override
protected void populateItem(ListItem<ValidationError> item) { protected void populateItem(ListItem<String> item) {
ValidationError error = item.getModelObject(); item.add(new Label("propertyValidationError", item.getModelObject()));
item.add(new Label("propertyValidationError", error.toString()));
} }
@Override @Override
protected void onConfigure() { protected void onConfigure() {
super.onConfigure(); super.onConfigure();
setVisible(!propertyContext.getValidationErrors(false).isEmpty()); setVisible(!propertyContext.getValidationErrors().isEmpty());
} }
}); });
item.add(hint);
Map<Serializable, EditContext> childContexts = propertyContext.getChildContexts(); Map<Serializable, EditContext> childContexts = propertyContext.getChildContexts();
if ((childContexts == null || childContexts.isEmpty()) && !propertyContext.getValidationErrors(false).isEmpty()) if (childContexts.isEmpty() && !propertyContext.getValidationErrors().isEmpty())
item.add(AttributeModifier.append("class", "has-error")); item.add(AttributeModifier.append("class", "has-error"));
else
hint.add(AttributeModifier.append("class", "has-error"));
} }
}); });

View File

@ -1,14 +1,12 @@
package com.pmease.commons.wicket.editable.string; package com.pmease.commons.wicket.editable.string;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map;
import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel; import org.apache.wicket.model.IModel;
import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.PropertyEditContext; import com.pmease.commons.editable.PropertyEditContext;
import com.pmease.commons.wicket.editable.EditableResourceBehavior; import com.pmease.commons.wicket.editable.EditableResourceBehavior;
@ -59,9 +57,4 @@ public class StringPropertyEditContext extends PropertyEditContext {
return new Label((String) renderParam, "<i>Not Defined</i>").setEscapeModelStrings(false); return new Label((String) renderParam, "<i>Not Defined</i>").setEscapeModelStrings(false);
} }
@Override
public Map<Serializable, EditContext> getChildContexts() {
return null;
}
} }

View File

@ -3,6 +3,7 @@ package com.pmease.gitop.core.gatekeeper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
@ -24,6 +25,7 @@ public class AndGateKeeper extends AbstractGateKeeper {
} }
@Editable(name="Sub Gate Keepers") @Editable(name="Sub Gate Keepers")
@Valid
@NotNull @NotNull
@Size(min=1, message="At least one element has to be added.") @Size(min=1, message="At least one element has to be added.")
public List<GateKeeper> getGateKeepers() { public List<GateKeeper> getGateKeepers() {

View File

@ -1,5 +1,6 @@
package com.pmease.gitop.core.gatekeeper; package com.pmease.gitop.core.gatekeeper;
import javax.validation.Valid;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import com.pmease.commons.editable.annotation.Editable; import com.pmease.commons.editable.annotation.Editable;
@ -15,6 +16,7 @@ public class IfThenGateKeeper extends AbstractGateKeeper {
@Editable @Editable
@NotNull @NotNull
@Valid
public GateKeeper getIfGate() { public GateKeeper getIfGate() {
return ifGate; return ifGate;
} }
@ -25,6 +27,7 @@ public class IfThenGateKeeper extends AbstractGateKeeper {
@Editable @Editable
@NotNull @NotNull
@Valid
public GateKeeper getThenGate() { public GateKeeper getThenGate() {
return thenGate; return thenGate;
} }

View File

@ -1,5 +1,6 @@
package com.pmease.gitop.core.gatekeeper; package com.pmease.gitop.core.gatekeeper;
import javax.validation.Valid;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import com.pmease.commons.editable.annotation.Editable; import com.pmease.commons.editable.annotation.Editable;
@ -13,6 +14,7 @@ public class NotGateKeeper extends AbstractGateKeeper {
@Editable @Editable
@NotNull @NotNull
@Valid
public GateKeeper getGateKeeper() { public GateKeeper getGateKeeper() {
return gateKeeper; return gateKeeper;
} }

View File

@ -3,6 +3,7 @@ package com.pmease.gitop.core.gatekeeper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
@ -21,6 +22,7 @@ public class OrGateKeeper extends AbstractGateKeeper {
private List<GateKeeper> gateKeepers = new ArrayList<GateKeeper>(); private List<GateKeeper> gateKeepers = new ArrayList<GateKeeper>();
@Editable(name="Sub Gate Keepers") @Editable(name="Sub Gate Keepers")
@Valid
@NotNull @NotNull
@Size(min=1, message="At least one element has to be added.") @Size(min=1, message="At least one element has to be added.")
public List<GateKeeper> getGateKeepers() { public List<GateKeeper> getGateKeepers() {

View File

@ -14,8 +14,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.UniqueConstraint; import javax.persistence.UniqueConstraint;
import javax.validation.Valid;
import org.hibernate.validator.constraints.NotEmpty;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.pmease.commons.editable.annotation.Editable; import com.pmease.commons.editable.annotation.Editable;
@ -76,7 +75,6 @@ public class Project extends AbstractEntity implements UserBelonging {
@Editable(description= @Editable(description=
"Specify name of the project. It will be used to identify the project when accessing via Git.") "Specify name of the project. It will be used to identify the project when accessing via Git.")
@NotEmpty
@ProjectName @ProjectName
public String getName() { public String getName() {
return name; return name;
@ -117,6 +115,7 @@ public class Project extends AbstractEntity implements UserBelonging {
@Editable( @Editable(
name="Accept Merge Requests If", name="Accept Merge Requests If",
description="Optionally define gate keeper to accept merge requests under certain condition.") description="Optionally define gate keeper to accept merge requests under certain condition.")
@Valid
public GateKeeper getGateKeeper() { public GateKeeper getGateKeeper() {
return gateKeeper; return gateKeeper;
} }

View File

@ -7,9 +7,6 @@ import org.apache.wicket.markup.html.form.Form;
import com.pmease.commons.editable.EditContext; import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.EditableUtils; import com.pmease.commons.editable.EditableUtils;
import com.pmease.gitop.core.Gitop;
import com.pmease.gitop.core.manager.ProjectManager;
import com.pmease.gitop.core.manager.UserManager;
import com.pmease.gitop.core.model.Project; import com.pmease.gitop.core.model.Project;
import com.pmease.gitop.web.page.BasePage; import com.pmease.gitop.web.page.BasePage;
@ -35,10 +32,7 @@ public class TestPage extends BasePage {
protected void onSubmit() { protected void onSubmit() {
super.onSubmit(); super.onSubmit();
editContext.validate(); editContext.validate();
if (!editContext.hasValidationError(true)) { if (!editContext.hasValidationError()) {
Project project = (Project) editContext.getBean();
project.setOwner(Gitop.getInstance(UserManager.class).getRootUser());
Gitop.getInstance(ProjectManager.class).save(project);
} }
} }