Skip to content
Snippets Groups Projects
Commit b785e675 authored by Simon Barner's avatar Simon Barner
Browse files

Update and use kernel.databinding's input validators

* No longer depend on org.conqat.ide.commons.ui.databinding.validate.*
* Improve NumberFormat validation
  * Do not accept if input contains a valid prefix
  * Provide more precise error message
  * Do not accept (1000er) grouping separator (in order to avoid
    confusion with decimal separator
* PropertySectionBase
  * Use updated validators
  * For BigDecimals, avoid introducing grouping separators during
    value -> String conversion

Issue-Ref: 3582
Issue-Url: https://af3-developer.fortiss.org/issues/3582



Signed-off-by: default avatarSimon Barner <barner@fortiss.org>
parent a1a41e44
No related branches found
No related tags found
1 merge request!38Double input format validation: check if the entire string was parsed
Showing
with 199 additions and 92 deletions
......@@ -2,7 +2,9 @@ AbstractDecoratedStyledTextCellDatabindingEditingSupport.java a0b06a9bd98ce28da3
AbstractDecoratedTextCellDatabindingEditingSupport.java d82943c0d4000b164beb45b00c64665cdcab2352 GREEN
AbstractStyledTextCellDatabindingEditingSupport.java 6ddea6d5cb18847f202043d9bb2bd8a55ae27a12 GREEN
AbstractTextCellDatabindingEditingSupport.java 8728e78f399a63c11f020fa447c002f42d735771 YELLOW
FloatValidator.java 7a32cb83604838ae17d3da751ce003731a055b05 GREEN
IntValidator.java de2d93012a863ab26118453413ca09e7764124a8 GREEN
NumberPositiveZeroValidator.java 4f555462dc532a2e88f2842701a48e3991f7ef9d GREEN
NumberValidator.java 28871dc5823ad14466273995599d3cd74fe69512 YELLOW
FloatValidator.java 3173a438f0dc773331be9c7d57478984e1fd52b6 YELLOW
IntValidator.java 934eee306191839be6d319432a1a238ff38c3f66 YELLOW
NumberPositiveValidator.java c45d4433c260e1e7bd4117954221dacb6d2df225 YELLOW
NumberPositiveZeroValidator.java 8ba0dfdcc8b8ad2154f2fb3e6217ff585e59d6e5 YELLOW
NumberValidator.java 04c8ca1abee5fb1f7d7b8d7c61076dde8df76930 YELLOW
NumberValueValidatorBase.java a8cda58d8bba6fdc05c6ac3249dbf1b53fcb0c2b YELLOW
......@@ -15,33 +15,26 @@
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.kernel.ui.databinding;
import static org.eclipse.core.databinding.validation.ValidationStatus.cancel;
import static org.eclipse.core.runtime.Status.OK_STATUS;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.runtime.IStatus;
import java.text.NumberFormat;
/**
* Validator for String to Float conversion.
* Validator to check if a number is an floating point number.
*
* @author hoelzl
* @author hoelzl, barner
*/
public class FloatValidator implements IValidator {
public class FloatValidator extends NumberValidator {
/** Singleton instance. */
/** {@link FloatValidator} singleton instance. */
public static final FloatValidator FLOAT_VALIDATOR = new FloatValidator();
/** Constructor. */
private FloatValidator() {
super(NumberFormat.getNumberInstance());
}
/** {@inheritDoc} */
@Override
public IStatus validate(Object value) {
if(value instanceof String) {
try {
Float.valueOf((String)value);
return OK_STATUS;
} catch(NumberFormatException nfex) {
// ignore
}
}
return cancel("Illegal float value!");
protected String getFormatName() {
return "Floating point";
}
}
......@@ -15,33 +15,26 @@
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.kernel.ui.databinding;
import static org.eclipse.core.databinding.validation.ValidationStatus.cancel;
import static org.eclipse.core.runtime.Status.OK_STATUS;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.runtime.IStatus;
import java.text.NumberFormat;
/**
* Validator for String to Int conversion.
* Validator to check if a number is an integer.
*
* @author hoelzl
* @author hoelzl, barner
*/
public class IntValidator implements IValidator {
public class IntValidator extends NumberValidator {
/** Singleton instance. */
/** {@link IntValidator} singleton instance. */
public static final IntValidator INT_VALIDATOR = new IntValidator();
/** Constructor. */
private IntValidator() {
super(NumberFormat.getIntegerInstance());
}
/** {@inheritDoc} */
@Override
public IStatus validate(Object value) {
if(value instanceof String) {
try {
Integer.valueOf((String)value);
return OK_STATUS;
} catch(NumberFormatException nfex) {
// ignore
}
}
return cancel("Illegal int value!");
protected String getFormatName() {
return "Integer";
}
}
/*-------------------------------------------------------------------------+
| Copyright 2018 fortiss GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.kernel.ui.databinding;
import static org.eclipse.core.databinding.validation.ValidationStatus.cancel;
import static org.eclipse.core.databinding.validation.ValidationStatus.ok;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.runtime.IStatus;
/**
* {@link IValidator} for checking that a numeric value is positive.
*
* @author barner
*/
public class NumberPositiveValidator extends NumberValueValidatorBase {
/** Singleton instance. */
public static final NumberPositiveValidator NUMBER_POSITIVE_VALIDATOR =
new NumberPositiveValidator();
/** {@inheritDoc} */
@Override
protected IStatus doValidate(Number number) {
if(number.doubleValue() <= 0) {
return cancel("Value must be > 0");
}
return ok();
}
}
/*-------------------------------------------------------------------------+
| Copyright 2011 fortiss GmbH |
| Copyright 2018 fortiss GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
......@@ -15,30 +15,30 @@
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.kernel.ui.databinding;
import static org.eclipse.core.databinding.validation.ValidationStatus.cancel;
import static org.eclipse.core.databinding.validation.ValidationStatus.ok;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IStatus;
/**
* {@link IValidator} for checking that a numeric value is positive or zero.
*
* @author hattendorf
* @author barner
*/
public class NumberPositiveZeroValidator implements IValidator {
public class NumberPositiveZeroValidator extends NumberValueValidatorBase {
/** Singleton instance. */
public static final NumberPositiveZeroValidator INSTANCE = new NumberPositiveZeroValidator();
public static final NumberPositiveZeroValidator NUMBER_POSITIVE_ZERO_VALIDATOR =
new NumberPositiveZeroValidator();
/** {@inheritDoc} */
@Override
public IStatus validate(Object value) {
if(!(value instanceof Number)) {
return ValidationStatus
.cancel("Internal: Expected a Number, but had a " + value.getClass());
}
if(((Number)value).doubleValue() < 0) {
return ValidationStatus.cancel("Value must be positive or zero!");
protected IStatus doValidate(Number number) {
if(number.doubleValue() < 0) {
return cancel("Value must be >= 0");
}
return ValidationStatus.ok();
return ok();
}
}
......@@ -18,6 +18,7 @@ package org.fortiss.tooling.kernel.ui.databinding;
import static org.eclipse.core.databinding.validation.ValidationStatus.cancel;
import static org.eclipse.core.databinding.validation.ValidationStatus.ok;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParsePosition;
......@@ -25,38 +26,53 @@ import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.runtime.IStatus;
/** Validates if a given input is a valid {@link Number}. */
public class NumberValidator implements IValidator {
/** Singleton instance. */
public static final NumberValidator NUMBER_VALIDATOR = new NumberValidator();
public abstract class NumberValidator implements IValidator {
/** The number format used in the current locale. */
private final NumberFormat format;
/** Character used to separate blocks of large numbers. */
private Character groupingSeparator;
/** Constructor. */
protected NumberValidator() {
format = NumberFormat.getNumberInstance();
format.setGroupingUsed(false);
protected NumberValidator(NumberFormat format) {
this.format = format;
if(format instanceof DecimalFormat) {
DecimalFormat df = (DecimalFormat)format;
groupingSeparator = df.getDecimalFormatSymbols().getGroupingSeparator();
}
}
/** Returns the format name. */
protected abstract String getFormatName();
/** {@inheritDoc} */
@Override
public IStatus validate(Object value) {
String input = value != null ? value.toString().trim() : "";
if(input.isEmpty()) {
String input = value != null ? value.toString() : "";
String trimmedInput = input.trim();
if(trimmedInput.isEmpty()) {
return ok();
}
if(groupingSeparator != null && trimmedInput.indexOf(groupingSeparator) != -1) {
return cancel("Grouping separator \'" + groupingSeparator + "\' not allowed");
}
ParsePosition p = new ParsePosition(0);
format.parse(input, p);
format.parse(trimmedInput, p);
int errorIndex = p.getErrorIndex();
// In case the input as a valid prefix, the error index will not indicate a problem.
// Therefore, check if the entire input was parsed.
if(errorIndex == -1 && p.getIndex() < input.length()) {
errorIndex = p.getIndex();
if(errorIndex == -1) {
// In case the input as a valid prefix, the error index will not indicate a problem.
// Therefore, check if the entire input was parsed.
if(p.getIndex() < trimmedInput.length()) {
errorIndex = p.getIndex();
} else {
return ok();
}
}
return errorIndex == -1 ? ok()
: cancel("Double number format validation failed at position " + errorIndex + ".");
int n = input.indexOf(trimmedInput) + errorIndex;
return cancel(getFormatName() + " format validation failed at position " + n);
}
}
/*-------------------------------------------------------------------------+
| Copyright 2018 fortiss GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.kernel.ui.databinding;
import static org.eclipse.core.databinding.validation.ValidationStatus.cancel;
import static org.eclipse.core.databinding.validation.ValidationStatus.ok;
import static org.fortiss.tooling.kernel.utils.LoggingUtils.error;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.runtime.IStatus;
import org.fortiss.tooling.kernel.ToolingKernelActivator;
/**
* Base class for {@link IValidator}s to check the value of {@link Number}s.
*
* @author barner
*/
public abstract class NumberValueValidatorBase implements IValidator {
/** {@inheritDoc} */
@Override
public final IStatus validate(Object value) {
if(value == null) {
return ok();
}
if(!(value instanceof Number)) {
String typeName = value.getClass().getSimpleName();
error(ToolingKernelActivator.getDefault(), "Value \"" + value.toString() +
"\" is not a number but of type " + typeName + ".");
return cancel("Value is not a number");
}
return doValidate((Number)value);
}
/** Checks the value of the provided {@link Number}. */
protected abstract IStatus doValidate(Number number);
}
......@@ -8,7 +8,7 @@ ModelEditorBindingBase.java 4c5ac569c0b6e7678fc8191096b26dfd09fdcb98 GREEN
ModelElementHandlerBase.java 384727748f125c9d43f19d9c0eba4ba1be5a7a26 GREEN
MultiEObjectActionBase.java 9e237d8ea640c4194e4877af4a9cfce88698e543 GREEN
NamedCommentedModelElementHandlerBase.java 681b98b50b362f01abb7a36f108f4f11b9e51829 GREEN
PropertySectionBase.java 2744f0668de50938d3015a0efbf2b1be229e30ae YELLOW
PropertySectionBase.java f9b9f559d678b355ca0854a26972967639a95564 YELLOW
TutorialStepUIAtomicBase.java cea2a158158b476de2108d2309afcf47f217b6d9 GREEN
TutorialStepUIAtomicWithWhitelistBase.java a9788ae514f62d27169c737ef59fb583234b5d43 GREEN
TutorialStepUICompositeBase.java 8225210eacb5b88de47d78280c5819f572f00ffa GREEN
......
......@@ -21,15 +21,15 @@ import static org.eclipse.core.databinding.conversion.NumberToStringConverter.fr
import static org.eclipse.core.databinding.conversion.StringToNumberConverter.toBigDecimal;
import static org.eclipse.core.databinding.conversion.StringToNumberConverter.toDouble;
import static org.eclipse.core.databinding.conversion.StringToNumberConverter.toInteger;
import static org.fortiss.tooling.kernel.ui.databinding.NumberValidator.NUMBER_VALIDATOR;
import static org.fortiss.tooling.kernel.ui.databinding.FloatValidator.FLOAT_VALIDATOR;
import static org.fortiss.tooling.kernel.ui.databinding.IntValidator.INT_VALIDATOR;
import static org.fortiss.tooling.kernel.ui.databinding.NumberPositiveValidator.NUMBER_POSITIVE_VALIDATOR;
import static org.fortiss.tooling.kernel.ui.util.DataBindingUtils.DECORATION_KEY;
import static org.fortiss.tooling.kernel.ui.util.DataBindingUtils.performComplexTextBinding;
import static org.fortiss.tooling.kernel.ui.util.WidgetsFactory.createTextWithUndo;
import java.math.BigDecimal;
import org.conqat.ide.commons.ui.databinding.validate.NumberPositiveValidator;
import org.conqat.ide.commons.ui.databinding.validate.TextToIntegerValidator;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.emf.databinding.EMFDataBindingContext;
......@@ -304,7 +304,7 @@ public abstract class PropertySectionBase extends AbstractPropertySection {
* fraction digits to be used in the String representation.
*/
protected void bindPositiveBigDecimalValue(Control text, IObservableValue<?> observedValue) {
bindBigDecimalValue(text, observedValue, NumberPositiveValidator.INSTANCE);
bindBigDecimalValue(text, observedValue, NUMBER_POSITIVE_VALIDATOR);
}
/**
......@@ -313,8 +313,19 @@ public abstract class PropertySectionBase extends AbstractPropertySection {
*/
protected void bindPositiveBigDecimalValue(Control text, IObservableValue<?> observedValue,
int maxFractionDigits) {
bindBigDecimalValue(text, observedValue, NumberPositiveValidator.INSTANCE,
maxFractionDigits);
bindBigDecimalValue(text, observedValue, NUMBER_POSITIVE_VALIDATOR, maxFractionDigits);
}
/**
* Binds a {@link BigDecimal} value with the default number of a maximum of three fraction
* digits to be used in the String representation.
*/
private void bindBigDecimalValue(Control text, IObservableValue<?> observedValue,
IValidator numberValidator, NumberFormat nf) {
nf.setGroupingUsed(false);
performComplexTextBinding(dbc, text, observedValue, fromBigDecimal(nf), toBigDecimal(nf),
FLOAT_VALIDATOR, numberValidator);
}
/**
......@@ -323,10 +334,9 @@ public abstract class PropertySectionBase extends AbstractPropertySection {
*/
protected void bindBigDecimalValue(Control text, IObservableValue<?> observedValue,
IValidator numberValidator) {
// DoubleValidator checks format of fractional numbers and is hence also suitable for
// BigDecimals
performComplexTextBinding(dbc, text, observedValue, fromBigDecimal(), toBigDecimal(),
NUMBER_VALIDATOR, numberValidator);
NumberFormat nf = NumberFormat.getNumberInstance();
bindBigDecimalValue(text, observedValue, numberValidator, nf);
}
/**
......@@ -338,10 +348,7 @@ public abstract class PropertySectionBase extends AbstractPropertySection {
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(maxFractionDigits);
// DoubleValidator checks format of fractional numbers and is hence also suitable for
// BigDecimals
performComplexTextBinding(dbc, text, observedValue, fromBigDecimal(nf), toBigDecimal(nf),
NUMBER_VALIDATOR, numberValidator);
bindBigDecimalValue(text, observedValue, numberValidator, nf);
}
/**
......@@ -349,7 +356,7 @@ public abstract class PropertySectionBase extends AbstractPropertySection {
* to be used in the String representation.
*/
protected void bindPositiveDoubleValue(Control text, IObservableValue<?> observedValue) {
bindDoubleValue(text, observedValue, NumberPositiveValidator.INSTANCE);
bindDoubleValue(text, observedValue, NUMBER_POSITIVE_VALIDATOR);
}
/**
......@@ -358,7 +365,7 @@ public abstract class PropertySectionBase extends AbstractPropertySection {
*/
protected void bindPositiveDoubleValue(Control text, IObservableValue<?> observedValue,
int maxFractionDigits) {
bindDoubleValue(text, observedValue, NumberPositiveValidator.INSTANCE, maxFractionDigits);
bindDoubleValue(text, observedValue, NUMBER_POSITIVE_VALIDATOR, maxFractionDigits);
}
/**
......@@ -368,7 +375,7 @@ public abstract class PropertySectionBase extends AbstractPropertySection {
protected void bindDoubleValue(Control text, IObservableValue<?> observedValue,
IValidator numberValidator) {
performComplexTextBinding(dbc, text, observedValue, fromDouble(false), toDouble(false),
NUMBER_VALIDATOR, numberValidator);
FLOAT_VALIDATOR, numberValidator);
}
/**
......@@ -381,18 +388,18 @@ public abstract class PropertySectionBase extends AbstractPropertySection {
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(maxFractionDigits);
performComplexTextBinding(dbc, text, observedValue, fromDouble(nf, false),
toDouble(nf, false), NUMBER_VALIDATOR, numberValidator);
toDouble(nf, false), FLOAT_VALIDATOR, numberValidator);
}
/** Binds a positive integer value. */
protected void bindPositiveIntegerValue(Control text, IObservableValue<?> observedValue) {
bindIntegerValue(text, observedValue, NumberPositiveValidator.INSTANCE);
bindIntegerValue(text, observedValue, NUMBER_POSITIVE_VALIDATOR);
}
/** Binds a integer value. */
protected void bindIntegerValue(Control text, IObservableValue<?> observedValue,
IValidator numberValidator) {
performComplexTextBinding(dbc, text, observedValue, fromInteger(false), toInteger(false),
TextToIntegerValidator.INSTANCE, numberValidator);
INT_VALIDATOR, numberValidator);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment