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

View File

@ -2,16 +2,20 @@ package com.pmease.commons.editable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
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")
public abstract class AbstractEditContext implements EditContext {
protected List<String> validationErrorMessages = new ArrayList<String>();
protected List<String> validationErrors = new ArrayList<String>();
private final Serializable bean;
@ -25,62 +29,77 @@ public abstract class AbstractEditContext implements EditContext {
}
@Override
public List<ValidationError> getValidationErrors(boolean recursive) {
List<ValidationError> validationErrors = new ArrayList<ValidationError>();
for (String each: validationErrorMessages) {
validationErrors.add(new ValidationError(each));
public List<String> getValidationErrors() {
return validationErrors;
}
public boolean hasValidationError() {
if (!validationErrors.isEmpty())
return true;
for (EditContext each: getChildContexts().values()) {
if (each.hasValidationError())
return true;
}
if (recursive && getChildContexts() != null) {
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);
return false;
}
@Override
public void validate() {
validationErrorMessages.clear();
clearValidationErrors();
if (getChildContexts() != null) {
for (EditContext each: getChildContexts().values())
each.validate();
updateBean();
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
public void error(String errorMessage) {
validationErrorMessages.add(errorMessage);
public void clearValidationErrors() {
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
public EditContext getChildContext(Serializable propertyName) {
if (getChildContexts() != null) {
EditContext childContext = getChildContexts().get(propertyName);
if (childContext != null)
return childContext;
}
throw new GeneralException("Unable to find child context of property '%s'", propertyName);
public EditContext findChildContext(List<Serializable> contextPath, boolean exactMatch) {
if (contextPath.size() == 0)
return this;
contextPath = new ArrayList<>(contextPath);
Serializable pathElement = contextPath.remove(0);
EditContext childContext = getChildContexts().get(pathElement);
if (childContext != null)
return childContext.findChildContext(contextPath, exactMatch);
else if (!exactMatch)
return this;
else
return null;
}
@Override
public boolean hasValidationError(Serializable propertyName, boolean recursive) {
EditContext childContext = getChildContext(propertyName);
return !childContext.getValidationErrors(recursive).isEmpty();
public Map<Serializable, EditContext> getChildContexts() {
return new HashMap<>();
}
@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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -61,18 +62,7 @@ public abstract class AbstractPolymorphicPropertyEditContext extends PropertyEdi
if (valueContext != null)
return valueContext.getChildContexts();
else
return null;
}
@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);
}
return new HashMap<>();
}
}

View File

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

View File

@ -1,6 +1,7 @@
package com.pmease.commons.editable;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import com.pmease.commons.loader.AppLoader;
@ -41,18 +42,7 @@ public abstract class AbstractReflectionPropertyEditContext extends PropertyEdit
if (valueContext != null)
return valueContext.getChildContexts();
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.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -104,17 +102,18 @@ public abstract class AbstractTableListPropertyEditContext extends PropertyEditC
@Override
public Map<Serializable, EditContext> getChildContexts() {
Map<Serializable, EditContext> childContexts = new LinkedHashMap<Serializable, EditContext>();
Map<Serializable, EditContext> childContexts = new LinkedHashMap<>();
if (elementContexts != null) {
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);
EditContext elementContext = new AbstractEditContext(getPropertyValue().get(i)) {
@Override
public Map<Serializable, EditContext> getChildContexts() {
Map<Serializable, EditContext> childContexts = new LinkedHashMap<Serializable, EditContext>();
Map<Serializable, EditContext> childContexts = new LinkedHashMap<>();
for (PropertyEditContext each: elementPropertyContexts)
childContexts.put(each.getPropertyName(), each);
return childContexts;
@ -131,39 +130,8 @@ public abstract class AbstractTableListPropertyEditContext extends PropertyEditC
}
@Override
public List<ValidationError> getValidationErrors(boolean recursive) {
List<ValidationError> validationErrors = new ArrayList<ValidationError>();
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);
}
public void addValidationError(String errorMessage) {
AbstractTableListPropertyEditContext.this.addValidationError(errorMessagePrefix + errorMessage);
}
};

View File

@ -9,11 +9,4 @@ public abstract class BeanEditContext extends AbstractEditContext {
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();
void updateBean();
void validate();
List<ValidationError> getValidationErrors(boolean recursive);
List<String> getValidationErrors();
void clearValidationErrors();
boolean hasValidationError();
Map<Serializable, EditContext> getChildContexts();
EditContext getChildContext(Serializable propertyName);
EditContext findChildContext(List<Serializable> contextPath, boolean exactMatch);
boolean hasValidationError(Serializable propertyName, boolean recursive);
boolean hasValidationError(boolean recursive);
void error(String errorMessage);
void addValidationError(String errorMessage);
Object renderForEdit(Object renderParam);

View File

@ -114,21 +114,6 @@ public class EditableUtils {
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) {
if (propertyGetter.getReturnType().isPrimitive() && propertyGetter.getReturnType() != boolean.class
|| propertyGetter.getAnnotation(NotNull.class) != null

View File

@ -4,10 +4,6 @@ import java.io.Serializable;
import java.lang.reflect.Constructor;
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.ExceptionUtils;
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) {
try {
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
public boolean complete() {
editContext.validate();
if (editContext.hasValidationError(true)) {
if (editContext.hasValidationError()) {
return false;
} else {
config.complete();

View File

@ -1,7 +1,6 @@
package com.pmease.commons.wicket.editable.bool;
import java.io.Serializable;
import java.util.Map;
import org.apache.wicket.Component;
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.model.IModel;
import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.PropertyEditContext;
import com.pmease.commons.wicket.editable.EditableResourceBehavior;
@ -55,9 +53,4 @@ public class BooleanPropertyEditContext extends PropertyEditContext {
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;
import java.io.Serializable;
import java.util.Map;
import org.apache.wicket.markup.ComponentTag;
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 com.google.common.collect.Lists;
import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.PropertyEditContext;
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%;
height: 32px;
font-size: 13px;
}
}
div.reflection div.name {
font-weight: bold;
}
div.reflection select.type, div.reflectio input.enable {
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.EditableUtils;
import com.pmease.commons.editable.ValidationError;
import com.pmease.commons.wicket.WicketUtils;
import com.pmease.commons.wicket.editable.EditableResourceBehavior;
@ -157,19 +156,18 @@ public class PolymorphicListPropertyEditor extends Panel {
}.setDefaultFormProcessing(false));
item.add(new ListView<ValidationError>("elementValidationErrors", item.getModelObject().getValidationErrors(false)) {
item.add(new ListView<String>("elementValidationErrors", item.getModelObject().getValidationErrors()) {
@Override
protected void populateItem(ListItem<ValidationError> item) {
ValidationError error = item.getModelObject();
item.add(new Label("propertyValidationError", error.toString()));
protected void populateItem(ListItem<String> item) {
item.add(new Label("propertyValidationError", item.getModelObject()));
}
@Override
protected void 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.EditableUtils;
import com.pmease.commons.editable.PropertyEditContext;
import com.pmease.commons.editable.ValidationError;
import com.pmease.commons.wicket.WicketUtils;
import com.pmease.commons.wicket.editable.EditableResourceBehavior;
@ -135,25 +134,24 @@ public class TableListPropertyEditor extends Panel {
final PropertyEditContext elementPropertyContext = columnItem.getModelObject();
columnItem.add((Component)elementPropertyContext.renderForEdit("elementPropertyEditor"));
columnItem.add(new ListView<ValidationError>("propertyValidationErrors", elementPropertyContext.getValidationErrors(false)) {
columnItem.add(new ListView<String>("propertyValidationErrors", elementPropertyContext.getValidationErrors()) {
@Override
protected void populateItem(ListItem<ValidationError> item) {
ValidationError error = item.getModelObject();
item.add(new Label("propertyValidationError", error.toString()));
protected void populateItem(ListItem<String> item) {
item.add(new Label("propertyValidationError", item.getModelObject()));
}
@Override
protected void onConfigure() {
super.onConfigure();
setVisible(!elementPropertyContext.getValidationErrors(false).isEmpty());
setVisible(!elementPropertyContext.getValidationErrors().isEmpty());
}
});
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"));
}

View File

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

View File

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

View File

@ -1,14 +1,12 @@
package com.pmease.commons.wicket.editable.password;
import java.io.Serializable;
import java.util.Map;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.model.IModel;
import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.PropertyEditContext;
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">
<div class="reflection editor">
<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="required" class="required"></span>
</div>
</label>
<div class="value">
<div wicket:id="value"></div>
<span wicket:id="description" class="help-block"></span>
<wicket:enclosure child="propertyValidationErrors">
<ul class="help-block">
<li wicket:id="propertyValidationErrors">
<span wicket:id="propertyValidationError"></span>
</li>
</ul>
</wicket:enclosure>
<div wicket:id="hint">
<span wicket:id="description" class="help-block"></span>
<wicket:enclosure child="propertyValidationErrors">
<ul class="help-block">
<li wicket:id="propertyValidationErrors">
<span wicket:id="propertyValidationError"></span>
</li>
</ul>
</wicket:enclosure>
</div>
</div>
</div>
</div>
@ -41,14 +43,16 @@
</td>
<td class="value">
<div wicket:id="value"></div>
<span wicket:id="description" class="help-block"></span>
<wicket:enclosure child="propertyValidationErrors">
<ul class="help-block">
<li wicket:id="propertyValidationErrors">
<span wicket:id="propertyValidationError"></span>
</li>
</ul>
</wicket:enclosure>
<div wicket:id="hint">
<span wicket:id="description" class="help-block"></span>
<wicket:enclosure child="propertyValidationErrors">
<ul class="help-block">
<li wicket:id="propertyValidationErrors">
<span wicket:id="propertyValidationError"></span>
</li>
</ul>
</wicket:enclosure>
</div>
</td>
</tr>
</table>

View File

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

View File

@ -1,14 +1,12 @@
package com.pmease.commons.wicket.editable.string;
import java.io.Serializable;
import java.util.Map;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import com.pmease.commons.editable.EditContext;
import com.pmease.commons.editable.PropertyEditContext;
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);
}
@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.List;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@ -24,6 +25,7 @@ public class AndGateKeeper extends AbstractGateKeeper {
}
@Editable(name="Sub Gate Keepers")
@Valid
@NotNull
@Size(min=1, message="At least one element has to be added.")
public List<GateKeeper> getGateKeepers() {

View File

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

View File

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

View File

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

View File

@ -14,8 +14,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.Valid;
import com.google.common.base.Objects;
import com.pmease.commons.editable.annotation.Editable;
@ -76,7 +75,6 @@ public class Project extends AbstractEntity implements UserBelonging {
@Editable(description=
"Specify name of the project. It will be used to identify the project when accessing via Git.")
@NotEmpty
@ProjectName
public String getName() {
return name;
@ -117,6 +115,7 @@ public class Project extends AbstractEntity implements UserBelonging {
@Editable(
name="Accept Merge Requests If",
description="Optionally define gate keeper to accept merge requests under certain condition.")
@Valid
public GateKeeper getGateKeeper() {
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.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.web.page.BasePage;
@ -35,10 +32,7 @@ public class TestPage extends BasePage {
protected void onSubmit() {
super.onSubmit();
editContext.validate();
if (!editContext.hasValidationError(true)) {
Project project = (Project) editContext.getBean();
project.setOwner(Gitop.getInstance(UserManager.class).getRootUser());
Gitop.getInstance(ProjectManager.class).save(project);
if (!editContext.hasValidationError()) {
}
}