/*******************************************************************************
* Copyright (c) 2007, 2014 compeople AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.ui.ridgets.validation;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Locale;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.osgi.util.NLS;
import org.eclipse.riena.core.util.ArraysUtil;
import org.eclipse.riena.core.util.PropertiesUtils;
import org.eclipse.riena.ui.ridgets.nls.Messages;
/**
* Tests, if input is an valid integer, which may be signed or not.
*/
public class ValidInteger extends ValidDecimal {
private boolean signed;
/**
* Constructs a rule t check whether the given object is a String which can
* be safely parsed to an Integer. The rule works for the default Locale and
* for signed values.
*/
public ValidInteger() {
this(Locale.getDefault());
}
/**
* Constructs a rule t check whether the given object is a String which can
* be safely parsed to an Integer. The rule works for the default Locale.
*
* @param signed
* if <tt>true</tt> the rule allows minus signs.
*/
public ValidInteger(final boolean signed) {
this(signed, Locale.getDefault());
}
/**
* Constructs a rule t check whether the given object is a String which can
* be safely parsed to an Integer. The rule works for signed values and the
* given locale.
*
* @param locale
* the Locale to use for number formatting; never null.
*/
public ValidInteger(final Locale locale) {
this(true, locale);
}
/**
* Constructs a rule t check whether the given object is a String which can
* be safely parsed to an Integer.
*
* @param signed
* if <tt>true</tt> the rule allows minus signs.
* @param locale
* the Locale to use for number formatting; never null.
*/
public ValidInteger(final boolean signed, final Locale locale) {
super(true, locale);
this.signed = signed;
}
/**
* Validates the given object. If the object is no String instance, a
* {@link ValidationFailure} will be thrown. The rule validates if the given
* object is a string, a well formed integer according to the rule's
* {@linkplain Locale}
*
* @param object
* the object to validate, must be of type String.
*/
@Override
public IStatus validate(final Object value) {
if (value != null) {
if (!(value instanceof String)) {
throw new ValidationFailure("ValidCharacters can only validate objects of type String."); //$NON-NLS-1$
}
final String string = Utils.removeWhitespace((String) value);
if (string.length() > 0) {
final ScanResult scanned = scan(string);
if (scanned.decimalSeparatorIndex >= 0) {
final Character decSep = Character.valueOf(getSymbols().getDecimalSeparator());
final String message = NLS.bind(Messages.ValidInteger_error_hasDecSep, decSep, string);
return ValidationRuleStatus.error(true, message);
}
// test if sign present
if (!signed && scanned.minusSignIndex > -1) {
final String message = NLS.bind(Messages.ValidInteger_error_hasMinus,
Integer.valueOf(scanned.minusSignIndex), string);
return ValidationRuleStatus.error(true, message);
}
// test if alien character present:
if (scanned.lastAlienCharIndex > -1) {
final String message = NLS.bind(Messages.ValidInteger_error_alienChar,
Character.valueOf(scanned.lastAlienCharacter), string);
return ValidationRuleStatus.error(true, message);
}
try {
final DecimalFormat format = getFormat();
synchronized (format) {// NumberFormat not threadsafe!
format.parse(string);
}
} catch (final ParseException e) {
final String message = NLS.bind(Messages.ValidInteger_error_cannotParse, string);
return ValidationRuleStatus.error(true, message);
}
}
}
return ValidationRuleStatus.ok();
}
/**
* This method is called on a newly constructed extension for validation.
* After creating a new instance of {@code ValidInteger} this method is
* called to initialize the instance. The argument for initialization are in
* the parameter {@code data}. Is the data a string the arguments are
* separated with ','. The order of the arguments in data is equivalent to
* the order of the parameters of one of the constructors.<br>
* If data has more than one argument. The last arguments are used to set
* the Local for this validator.
*
*
* @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement,
* java.lang.String, java.lang.Object)
* @see org.eclipse.riena.ui.ridgets.validation.ValidDecimal#setLocale(java.lang.String[])
*/
@Override
public void setInitializationData(final IConfigurationElement config, final String propertyName, final Object data)
throws CoreException {
if (data instanceof String) {
final String[] args = PropertiesUtils.asArray(data);
int localStart = 0;
if (args.length > 0) {
if (args[0].equals(Boolean.TRUE.toString())) {
this.signed = true;
localStart = 1;
} else if (args[0].equals(Boolean.FALSE.toString())) {
this.signed = false;
localStart = 1;
}
}
if (args.length > localStart) {
final String[] localArgs = ArraysUtil.copyRange(args, localStart, args.length);
setLocale(localArgs);
}
}
}
}