mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-11 01:32:08 +10:00
allow property edit validation
This commit is contained in:
+11
-7
@@ -3,6 +3,8 @@ package org.diylc.common;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
|
||||
/**
|
||||
* Entity class for editable properties extracted from component objects.
|
||||
* Represents a single editable property together with it's current value.
|
||||
@@ -17,19 +19,21 @@ public class PropertyWrapper implements Cloneable {
|
||||
private Method setter;
|
||||
private Method getter;
|
||||
private boolean defaultable;
|
||||
private IPropertyValidator validator;
|
||||
|
||||
public PropertyWrapper(String name, Class<?> type, Method getter, Method setter,
|
||||
boolean defaultable) {
|
||||
boolean defaultable, IPropertyValidator validator) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
this.defaultable = defaultable;
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
public void readFrom(Object object) throws IllegalArgumentException,
|
||||
IllegalAccessException, InvocationTargetException {
|
||||
public void readFrom(Object object) throws IllegalArgumentException, IllegalAccessException,
|
||||
InvocationTargetException {
|
||||
this.value = getter.invoke(object);
|
||||
}
|
||||
|
||||
@@ -42,8 +46,8 @@ public class PropertyWrapper implements Cloneable {
|
||||
// }
|
||||
// }
|
||||
|
||||
public void writeTo(Object object) throws IllegalArgumentException,
|
||||
IllegalAccessException, InvocationTargetException {
|
||||
public void writeTo(Object object) throws IllegalArgumentException, IllegalAccessException,
|
||||
InvocationTargetException {
|
||||
setter.invoke(object, value);
|
||||
}
|
||||
|
||||
@@ -67,8 +71,8 @@ public class PropertyWrapper implements Cloneable {
|
||||
return defaultable;
|
||||
}
|
||||
|
||||
public void setDefaultable(boolean defaultable) {
|
||||
this.defaultable = defaultable;
|
||||
public IPropertyValidator getValidator() {
|
||||
return validator;
|
||||
}
|
||||
|
||||
// @Override
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package org.diylc.core;
|
||||
|
||||
/**
|
||||
* Validator that allows all values.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class AllowAllValidator implements IPropertyValidator {
|
||||
|
||||
@Override
|
||||
public void validate(Object value) throws ValidationException {
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package org.diylc.core;
|
||||
|
||||
/**
|
||||
* Interface for validating property value changes.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IPropertyValidator {
|
||||
|
||||
/**
|
||||
* @param value
|
||||
* @throws ValidationException
|
||||
* if validation fails. Message will contain the reason.
|
||||
*/
|
||||
void validate(Object value) throws ValidationException;
|
||||
}
|
||||
+19
-3
@@ -7,6 +7,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
import org.diylc.core.annotations.PositiveMeasureValidator;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
|
||||
@@ -92,7 +93,7 @@ public class Project implements Serializable {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Grid spacing")
|
||||
@EditableProperty(name = "Grid spacing", validatorClass = SpacingValidator.class)
|
||||
public Size getGridSpacing() {
|
||||
return gridSpacing;
|
||||
}
|
||||
@@ -118,7 +119,7 @@ public class Project implements Serializable {
|
||||
public Set<Set<IDIYComponent<?>>> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
|
||||
public Set<Integer> getLockedLayers() {
|
||||
return lockedLayers;
|
||||
}
|
||||
@@ -177,12 +178,27 @@ public class Project implements Serializable {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public static class SpacingValidator extends PositiveMeasureValidator {
|
||||
|
||||
@Override
|
||||
public void validate(Object value) throws ValidationException {
|
||||
super.validate(value);
|
||||
Size size = (Size) value;
|
||||
if (size.compareTo(new Size(1d, SizeUnit.mm)) < 0) {
|
||||
throw new ValidationException("must be greater than 1mm");
|
||||
}
|
||||
if (size.compareTo(new Size(1d, SizeUnit.in)) > 0) {
|
||||
throw new ValidationException("must be less than 1in");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Project clone() throws CloneNotSupportedException {
|
||||
// List<IDIYComponent> clonedComponents = new
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
|
||||
package org.diylc.core;
|
||||
|
||||
public class ValidationException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ValidationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+9
@@ -3,6 +3,9 @@ package org.diylc.core.annotations;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.diylc.core.AllowAllValidator;
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
|
||||
/**
|
||||
* Used to annotate editable component property. Editable property XYZ must have
|
||||
* both getter and setter named <code>getXYZ</code> and <code>setXYZ</code>
|
||||
@@ -30,4 +33,10 @@ public @interface EditableProperty {
|
||||
* @return
|
||||
*/
|
||||
boolean defaultable() default true;
|
||||
|
||||
/**
|
||||
* Class of validator to use to
|
||||
* @return
|
||||
*/
|
||||
Class<? extends IPropertyValidator> validatorClass() default AllowAllValidator.class;
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package org.diylc.core.annotations;
|
||||
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
import org.diylc.core.ValidationException;
|
||||
import org.diylc.core.measures.AbstractMeasure;
|
||||
|
||||
public class PositiveMeasureValidator implements IPropertyValidator {
|
||||
|
||||
@Override
|
||||
public void validate(Object value) throws ValidationException {
|
||||
if (value instanceof AbstractMeasure) {
|
||||
AbstractMeasure measure = (AbstractMeasure) value;
|
||||
if (measure.getValue() <= 0) {
|
||||
throw new ValidationException("must be greater than zero.");
|
||||
}
|
||||
} else {
|
||||
throw new ValidationException("wrong data type, measure expected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -2,7 +2,7 @@ package org.diylc.core.measures;
|
||||
|
||||
import org.diylc.utils.Constants;
|
||||
|
||||
public class Size extends AbstractMeasure<SizeUnit> {
|
||||
public class Size extends AbstractMeasure<SizeUnit> implements Comparable<Size> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -39,4 +39,9 @@ public class Size extends AbstractMeasure<SizeUnit> {
|
||||
}
|
||||
throw new IllegalArgumentException("Could not parse size: " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Size o) {
|
||||
return new Double(value * unit.getFactor()).compareTo(o.getValue() * o.getUnit().getFactor());
|
||||
}
|
||||
}
|
||||
|
||||
+27
-6
@@ -19,6 +19,7 @@ import org.diylc.common.ComponentType;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.core.CreationMethod;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
import org.diylc.core.annotations.ComponentDescriptor;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
|
||||
@@ -35,7 +36,8 @@ public class ComponentProcessor {
|
||||
|
||||
private static ComponentProcessor instance;
|
||||
|
||||
private Map<Class<?>, List<PropertyWrapper>> propertyCache;
|
||||
private Map<String, List<PropertyWrapper>> propertyCache;
|
||||
private Map<String, IPropertyValidator> propertyValidatorCache;
|
||||
private Map<String, ComponentType> componentTypeMap;
|
||||
|
||||
private Cloner cloner;
|
||||
@@ -50,8 +52,9 @@ public class ComponentProcessor {
|
||||
private ComponentProcessor() {
|
||||
super();
|
||||
this.cloner = new Cloner();
|
||||
this.propertyCache = new HashMap<Class<?>, List<PropertyWrapper>>();
|
||||
this.propertyCache = new HashMap<String, List<PropertyWrapper>>();
|
||||
this.componentTypeMap = new HashMap<String, ComponentType>();
|
||||
this.propertyValidatorCache = new HashMap<String, IPropertyValidator>();
|
||||
}
|
||||
|
||||
public ComponentType extractComponentTypeFrom(Class<? extends IDIYComponent<?>> clazz) {
|
||||
@@ -117,8 +120,8 @@ public class ComponentProcessor {
|
||||
* @return
|
||||
*/
|
||||
public List<PropertyWrapper> extractProperties(Class<?> clazz) {
|
||||
if (propertyCache.containsKey(clazz)) {
|
||||
return cloner.deepClone(propertyCache.get(clazz));
|
||||
if (propertyCache.containsKey(clazz.getName())) {
|
||||
return cloner.deepClone(propertyCache.get(clazz.getName()));
|
||||
}
|
||||
List<PropertyWrapper> properties = new ArrayList<PropertyWrapper>();
|
||||
for (Method method : clazz.getMethods()) {
|
||||
@@ -133,10 +136,13 @@ public class ComponentProcessor {
|
||||
} else {
|
||||
name = annotation.name();
|
||||
}
|
||||
IPropertyValidator validator = getPropertyValidator(annotation
|
||||
.validatorClass());
|
||||
Method setter = clazz.getMethod("set" + method.getName().substring(3),
|
||||
method.getReturnType());
|
||||
PropertyWrapper property = new PropertyWrapper(name,
|
||||
method.getReturnType(), method, setter, annotation.defaultable());
|
||||
method.getReturnType(), method, setter, annotation.defaultable(),
|
||||
validator);
|
||||
properties.add(property);
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
@@ -146,7 +152,7 @@ public class ComponentProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
propertyCache.put(clazz, properties);
|
||||
propertyCache.put(clazz.getName(), properties);
|
||||
return cloner.deepClone(properties);
|
||||
}
|
||||
|
||||
@@ -187,4 +193,19 @@ public class ComponentProcessor {
|
||||
Collections.sort(properties, ComparatorFactory.getInstance().getPropertyNameComparator());
|
||||
return properties;
|
||||
}
|
||||
|
||||
private IPropertyValidator getPropertyValidator(Class<? extends IPropertyValidator> clazz) {
|
||||
if (propertyValidatorCache.containsKey(clazz.getName())) {
|
||||
return propertyValidatorCache.get(clazz.getName());
|
||||
}
|
||||
IPropertyValidator validator;
|
||||
try {
|
||||
validator = clazz.newInstance();
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not instantiate validator for " + clazz.getName(), e);
|
||||
return null;
|
||||
}
|
||||
propertyValidatorCache.put(clazz.getName(), validator);
|
||||
return validator;
|
||||
}
|
||||
}
|
||||
|
||||
+19
@@ -18,10 +18,12 @@ import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.core.ValidationException;
|
||||
|
||||
import com.diyfever.gui.ButtonDialog;
|
||||
|
||||
@@ -65,6 +67,23 @@ public class PropertyEditorDialog extends ButtonDialog {
|
||||
// setLocationRelativeTo(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean validateInput(String button) {
|
||||
if (button.equals(ButtonDialog.OK)) {
|
||||
for (PropertyWrapper property : properties) {
|
||||
try {
|
||||
property.getValidator().validate(property.getValue());
|
||||
} catch (ValidationException ve) {
|
||||
JOptionPane.showMessageDialog(PropertyEditorDialog.this, "Input error for \""
|
||||
+ property.getName() + "\": " + ve.getMessage(), "Error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private JPanel createEditorFields() {
|
||||
JPanel editorPanel = new JPanel(new GridBagLayout());
|
||||
editorPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
||||
|
||||
Reference in New Issue
Block a user