Index: src/org/eclipse/core/tests/internal/databinding/BindingMessagesTest.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/BindingMessagesTest.java,v
--- src/org/eclipse/core/tests/internal/databinding/BindingMessagesTest.java 1 Apr 2007 20:58:10 -0000 1.1
+++ src/org/eclipse/core/tests/internal/databinding/BindingMessagesTest.java 11 Oct 2009 20:35:15 -0000
@@ -12,6 +12,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Ovidio Mallo - bug 183055
******************************************************************************/
/**
@@ -21,13 +22,13 @@
public class BindingMessagesTest extends TestCase {
public void testFormatString() throws Exception {
String key = "Validate_NumberOutOfRangeError";
- String result = BindingMessages.formatString(key, new Object[] {"1", "2"});
+ String result = BindingMessages.getFormattedString(key, new Object[] {"1", "2"});
assertFalse("key should not be returned", key.equals(result));
}
public void testFormatStringForKeyNotFound() throws Exception {
String key = "key_that_does_not_exist";
- String result = BindingMessages.formatString(key, null);
+ String result = BindingMessages.getFormattedString(key, null);
assertTrue(key.equals(result));
}
}
Index: .settings/org.eclipse.jdt.ui.prefs
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.examples.databinding/.settings/org.eclipse.jdt.ui.prefs,v
--- .settings/org.eclipse.jdt.ui.prefs 16 Feb 2009 23:03:20 -0000 1.6
+++ .settings/org.eclipse.jdt.ui.prefs 11 Oct 2009 20:35:20 -0000
@@ -1,4 +1,4 @@
-#Tue Feb 10 16:06:02 MST 2009
+#Mon Sep 21 22:46:54 CEST 2009
cleanup.add_default_serial_version_id=true
cleanup.add_generated_serial_version_id=false
cleanup.add_missing_annotations=true
@@ -78,7 +78,7 @@
sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=false
-sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code=false
sp_cleanup.format_source_code_changes_only=false
sp_cleanup.make_local_variable_final=false
sp_cleanup.make_parameters_final=false
Index: META-INF/MANIFEST.MF
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.examples.databinding/META-INF/MANIFEST.MF,v
--- META-INF/MANIFEST.MF 24 Aug 2009 21:33:42 -0000 1.21
+++ META-INF/MANIFEST.MF 11 Oct 2009 20:35:20 -0000
@@ -17,5 +17,6 @@
org.eclipse.jface.examples.databinding.mask.internal;x-internal:=true,
org.eclipse.jface.examples.databinding.model;x-internal:=false,
org.eclipse.jface.examples.databinding.radioGroup;x-internal:=false
-Import-Package: com.ibm.icu.text
+Import-Package: com.ibm.icu.math,
+ com.ibm.icu.text
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Index: src/org/eclipse/jface/examples/databinding/util/ObservableMapEditingSupport.java
===================================================================
RCS file: src/org/eclipse/jface/examples/databinding/util/ObservableMapEditingSupport.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/examples/databinding/util/ObservableMapEditingSupport.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.jface.examples.databinding.util;
+
+import org.eclipse.core.databinding.editing.Editing;
+import org.eclipse.core.databinding.observable.map.IObservableMap;
+import org.eclipse.core.databinding.util.Policy;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ColumnViewer;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * @since 3.2
+ */
+public class ObservableMapEditingSupport extends EditingSupport {
+
+ private final IObservableMap attributeMap;
+
+ private final Editing editing;
+
+ private final CellEditor cellEditor;
+
+ public ObservableMapEditingSupport(ColumnViewer viewer, IObservableMap attributeMap, Editing editing) {
+ super(viewer);
+ this.attributeMap = attributeMap;
+ this.editing = editing;
+ this.cellEditor = new TextCellEditor((Composite) getViewer().getControl());
+ }
+
+ protected boolean canEdit(Object element) {
+ return true;
+ }
+
+ protected CellEditor getCellEditor(Object element) {
+ return cellEditor;
+ }
+
+ protected Object getValue(Object element) {
+ return editing.convertToTarget(attributeMap.get(element));
+ }
+
+ protected void setValue(Object element, Object value) {
+ MultiStatus validationStatus = new MultiStatus(Policy.JFACE_DATABINDING, 0, null, null);
+ Object modelValue = editing.convertToModel(value, validationStatus);
+ if (handleValidation(validationStatus)) {
+ attributeMap.put(element, modelValue);
+ }
+ }
+
+ private boolean handleValidation(IStatus validationStatus) {
+ if (validationStatus.matches(IStatus.ERROR | IStatus.CANCEL)) {
+ MessageDialog.openError(getViewer().getControl().getShell(), "Validation Error", getValidationMessage(validationStatus));
+ return false;
+ }
+ return true;
+ }
+
+ private static String getValidationMessage(IStatus validationStatus) {
+ if (!validationStatus.isMultiStatus()) {
+ return validationStatus.getMessage();
+ }
+
+ MultiStatus multiStatus = (MultiStatus) validationStatus;
+ StringBuffer sb = new StringBuffer();
+ IStatus[] childStatus = multiStatus.getChildren();
+ for (int i = 0; i < childStatus.length; i++) {
+ if (i > 0) {
+ sb.append('\n');
+ }
+ sb.append(getValidationMessage(childStatus[i]));
+ }
+ return sb.toString();
+ }
+}
Index: src/org/eclipse/jface/examples/databinding/snippets/Snippet035Editing.java
===================================================================
RCS file: src/org/eclipse/jface/examples/databinding/snippets/Snippet035Editing.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/examples/databinding/snippets/Snippet035Editing.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.jface.examples.databinding.snippets;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import org.eclipse.core.databinding.Binding;
+import org.eclipse.core.databinding.DataBindingContext;
+import org.eclipse.core.databinding.editing.BooleanEditing;
+import org.eclipse.core.databinding.editing.DateEditing;
+import org.eclipse.core.databinding.editing.DecimalEditing;
+import org.eclipse.core.databinding.editing.Editing;
+import org.eclipse.core.databinding.editing.IntegerEditing;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.list.WritableList;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.core.databinding.observable.value.WritableValue;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.databinding.swt.ISWTObservableValue;
+import org.eclipse.jface.databinding.swt.SWTObservables;
+import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
+import org.eclipse.jface.examples.databinding.util.EditingFactory;
+import org.eclipse.jface.internal.databinding.provisional.fieldassist.ControlDecorationSupport;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.ListViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public class Snippet035Editing {
+
+ private DataBindingContext dbc;
+
+ public static void main(String[] args) {
+ Display display = new Display();
+
+ Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
+ public void run() {
+ Shell shell = new Snippet035Editing().createShell();
+ Display display = Display.getCurrent();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ }
+ });
+ }
+
+ private Shell createShell() {
+ Display display = Display.getCurrent();
+ Shell shell = new Shell(display);
+ shell.setText("Editing");
+ shell.setLayout(new GridLayout(1, false));
+
+ dbc = new DataBindingContext();
+
+ createValueSection(shell);
+ createListSection(shell);
+
+ shell.pack();
+ shell.open();
+
+ return shell;
+ }
+
+ private void createValueSection(Composite parent) {
+ Group section = createSectionGroup(parent, "Value bindings", false);
+
+ // Edit an e-mail address.
+ Text emailText = createTextField(section, "E-Mail*");
+ Editing emailEditing = EditingFactory.forEmailString().required();
+ bindTextField(emailText, new WritableValue(), emailEditing);
+
+ // Edit a required, positive short using the default validation message.
+ Text positiveText = createTextField(section, "Positive short*");
+ IntegerEditing positiveEditing = EditingFactory.forShort().required().positive();
+ bindTextField(positiveText, new WritableValue(), positiveEditing);
+
+ // Edit a required double with a maximum of two fractional digits.
+ Text doubleText = createTextField(section, "Double value*");
+ DecimalEditing doubleEditing = EditingFactory.forDouble().required().maxScale(2);
+ bindTextField(doubleText, new WritableValue(), doubleEditing);
+
+ // Edit an integer within the range [1, 100] using the default
+ // validation message.
+ Text rangeText = createTextField(section, "Value in [1, 100]");
+ IntegerEditing rangeEditing = EditingFactory.forInteger().range(1, 100);
+ bindTextField(rangeText, new WritableValue(new Integer(0), null), rangeEditing);
+
+ // Edit a percentage value which must lie within [0, 100] using a custom
+ // validation message which indicates that the value actually represents
+ // a percentage value. Note that you must specify the constraint message
+ // before the actual constraint.
+ Text percentText = createTextField(section, "Value [%]");
+ IntegerEditing percentEditing = EditingFactory.forInteger();
+ percentEditing.modelIntegerConstraints()
+ .rangeMessage("Please specify a percentage value within [{0}, {1}].")
+ .range(0, 100);
+ bindTextField(percentText, new WritableValue(new Integer(-1), null), percentEditing);
+
+ // Edit a hex integer within the range [0x00, 0xff]. The range validation
+ // message will display the range boundaries in hex format as well.
+ Text hexText = createTextField(section, "Hex value in [0x00, 0xff]");
+ IntegerEditing hexEditing = EditingFactory.forHexInteger(2).range(0x00, 0xff);
+ bindTextField(hexText, new WritableValue(new Integer(0), null), hexEditing);
+
+ // Edit a boolean value.
+ Text boolText = createTextField(section, "Boolean value");
+ BooleanEditing boolEditing = EditingFactory.forBoolean();
+ bindTextField(boolText, new WritableValue(Boolean.TRUE, null), boolEditing);
+ }
+
+ private void createListSection(Composite parent) {
+ Group section = createSectionGroup(parent, "List bindings", true);
+
+ // Our date should be >= 01.01.1990.
+ Calendar year1990Calendar = Calendar.getInstance();
+ year1990Calendar.clear();
+ year1990Calendar.set(1990, 0, 1);
+ Date year1990 = year1990Calendar.getTime();
+
+ // Edit a date supporting the default input/display patterns.
+ Text dateText = createTextField(section, "Date");
+ DateEditing dateEditing = EditingFactory.forDate().afterEqual(year1990);
+ final WritableValue dateObservable = new WritableValue();
+ final Binding dateBinding = bindTextField(dateText, dateObservable, dateEditing);
+
+ // Create a list to which the dates are added when the user hits ENTER.
+ new Label(section, SWT.LEFT);
+ ListViewer dateListViewer = new ListViewer(section);
+ GridDataFactory.fillDefaults().grab(true, true).hint(150, 200).applyTo(dateListViewer.getList());
+
+ dateListViewer.setContentProvider(new ObservableListContentProvider());
+ dateListViewer.setLabelProvider(new LabelProvider());
+
+ // We use the same DateEditing object as for the text field above to
+ // create a list binding which maps the entered dates to their string
+ // representation which is then set as input on the ListViewer.
+ final WritableList targetDateList = new WritableList();
+ final WritableList modelDateList = new WritableList();
+ dateEditing.bindList(dbc, targetDateList, modelDateList);
+
+ // Set the list containing the string representation of the dates as input.
+ dateListViewer.setInput(targetDateList);
+
+ // Add the current date in the text field when the user hits ENTER.
+ dateText.addSelectionListener(new SelectionAdapter() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ IStatus dateValidationStatus = (IStatus) dateBinding.getValidationStatus().getValue();
+ Date date = (Date) dateObservable.getValue();
+ if (dateValidationStatus.isOK() && date != null) {
+ modelDateList.add(date);
+ }
+ }
+ });
+ }
+
+ private Binding bindTextField(Text text, IObservableValue modelValue, Editing editing) {
+ // Create the binding using the editing object.
+ ISWTObservableValue textObservable = SWTObservables.observeText(text, SWT.Modify);
+ Binding binding = editing.bindValue(dbc, textObservable, modelValue);
+
+ // Decorate the control with the validation status.
+ ControlDecorationSupport.create(binding, SWT.TOP);
+
+ // Re-format when the text field looses the focus in order to always
+ // display the model in the default format in case multiple input formats
+ // are supported.
+ formatOnFocusOut(text, binding);
+
+ return binding;
+ }
+
+ private static void formatOnFocusOut(final Control control, final Binding binding) {
+ control.addFocusListener(new FocusAdapter() {
+ public void focusLost(FocusEvent e) {
+ IStatus dateValidationStatus = (IStatus) binding.getValidationStatus().getValue();
+ if (dateValidationStatus.isOK()) {
+ binding.updateModelToTarget();
+ }
+ }
+ });
+ }
+
+ private static Group createSectionGroup(Composite parent, String groupText, boolean grabVertical) {
+ Group section = new Group(parent, SWT.SHADOW_ETCHED_IN);
+ section.setText(groupText);
+ GridLayoutFactory.fillDefaults()
+ .numColumns(2)
+ .equalWidth(false)
+ .margins(5, 5)
+ .spacing(15, 5)
+ .applyTo(section);
+ GridDataFactory.fillDefaults().grab(true, grabVertical).applyTo(section);
+ return section;
+ }
+
+ private static Text createTextField(Composite parent, String labelText) {
+ Label label = new Label(parent, SWT.LEFT);
+ label.setText(labelText);
+ GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
+
+ final Text text = new Text(parent, SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, false).hint(150, SWT.DEFAULT).applyTo(text);
+
+ // Select the text when gaining focus.
+ text.addFocusListener(new FocusAdapter() {
+ public void focusGained(FocusEvent e) {
+ text.selectAll();
+ }
+ });
+
+ return text;
+ }
+}
Index: src/org/eclipse/jface/examples/databinding/util/EditingFactory.java
===================================================================
RCS file: src/org/eclipse/jface/examples/databinding/util/EditingFactory.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/examples/databinding/util/EditingFactory.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.jface.examples.databinding.util;
+
+import java.util.Locale;
+
+import org.eclipse.core.databinding.editing.BooleanEditing;
+import org.eclipse.core.databinding.editing.DateEditing;
+import org.eclipse.core.databinding.editing.DecimalEditing;
+import org.eclipse.core.databinding.editing.IntegerEditing;
+import org.eclipse.core.databinding.editing.StringEditing;
+
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.text.NumberFormat;
+
+/**
+ * @since 3.2
+ */
+public final class EditingFactory {
+
+ private static final String REQUIRED_MESSAGE = "Please specify a value.";
+
+ private static final String INTEGER_PARSE_ERROR_MESSAGE = "The input is invalid.";
+
+ private static final String INTEGER_OUT_OF_RANGE_MESSAGE = "The value lies outside the supported range.";
+
+ private static final String INTEGER_RANGE_MESSAGE = "The value must lie between {0} and {1}.";
+
+ private static final String[] BOOLEAN_TRUE_VALUES = new String[] {
+ "yes", "y", "true", "1"
+ };
+
+ private static final String[] BOOLEAN_FALSE_VALUES = new String[] {
+ "no", "n", "false", "0"
+ };
+
+ private static final String[] DATE_INPUT_PATTERNS = new String[] {
+ "yyMMdd",
+ "yyyyMMdd"
+ };
+
+ private static final String DATE_DISPLAY_PATTERN = "yyyyMMdd";
+
+ private static final String DATE_PARSE_ERROR_MESSAGE = createDateParseErrorMessage(DATE_INPUT_PATTERNS);
+
+ private static final String EMAIL_REGEX = "\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}\\b";
+
+ private static final String EMAIL_ERROR_MESSAGE = "Please specify a valid e-mail address.";
+
+ private EditingFactory() {
+ // prevent instantiation
+ }
+
+ public static StringEditing forString() {
+ return StringEditing.stripped(true);
+ }
+
+ public static StringEditing forEmailString() {
+ StringEditing editing = StringEditing.stripped(true);
+ editing.modelStringConstraints()
+ .matchesMessage(EMAIL_ERROR_MESSAGE)
+ .matches(EMAIL_REGEX);
+ return editing;
+ }
+
+ public static IntegerEditing forLong() {
+ return forLong(Locale.getDefault());
+ }
+
+ public static IntegerEditing forLong(Locale locale) {
+ IntegerEditing editing = IntegerEditing.forLongFormat(
+ NumberFormat.getIntegerInstance(locale),
+ INTEGER_PARSE_ERROR_MESSAGE,
+ INTEGER_OUT_OF_RANGE_MESSAGE);
+ configure(editing);
+ return editing;
+ }
+
+ public static IntegerEditing forInteger() {
+ return forInteger(Locale.getDefault());
+ }
+
+ public static IntegerEditing forInteger(Locale locale) {
+ IntegerEditing editing = IntegerEditing.forIntegerFormat(
+ NumberFormat.getIntegerInstance(locale),
+ INTEGER_PARSE_ERROR_MESSAGE,
+ INTEGER_OUT_OF_RANGE_MESSAGE);
+ configure(editing);
+ return editing;
+ }
+
+ public static IntegerEditing forShort() {
+ return forShort(Locale.getDefault());
+ }
+
+ public static IntegerEditing forShort(Locale locale) {
+ IntegerEditing editing = IntegerEditing.forShortFormat(
+ NumberFormat.getIntegerInstance(locale),
+ INTEGER_PARSE_ERROR_MESSAGE,
+ INTEGER_OUT_OF_RANGE_MESSAGE);
+ configure(editing);
+ return editing;
+ }
+
+ public static IntegerEditing forByte() {
+ return forByte(Locale.getDefault());
+ }
+
+ public static IntegerEditing forByte(Locale locale) {
+ IntegerEditing editing = IntegerEditing.forByteFormat(
+ NumberFormat.getIntegerInstance(locale),
+ INTEGER_PARSE_ERROR_MESSAGE,
+ INTEGER_OUT_OF_RANGE_MESSAGE);
+ configure(editing);
+ return editing;
+ }
+
+ public static IntegerEditing forHexInteger(int digits) {
+ IntegerEditing editing = IntegerEditing.forIntegerFormat(
+ RadixNumberFormat.getHexInstance("0x", digits),
+ INTEGER_PARSE_ERROR_MESSAGE,
+ INTEGER_OUT_OF_RANGE_MESSAGE);
+ configure(editing);
+ return editing;
+ }
+
+ private static void configure(IntegerEditing editing) {
+ editing.modelIntegerConstraints()
+ .requiredMessage(REQUIRED_MESSAGE)
+ .rangeMessage(INTEGER_RANGE_MESSAGE);
+ }
+
+ public static DecimalEditing forDouble() {
+ return forDouble(Locale.getDefault());
+ }
+
+ public static DecimalEditing forDouble(Locale locale) {
+ DecimalEditing editing = DecimalEditing.forDoubleFormat(
+ NumberFormat.getNumberInstance(locale),
+ INTEGER_PARSE_ERROR_MESSAGE,
+ INTEGER_OUT_OF_RANGE_MESSAGE);
+ configure(editing);
+ return editing;
+ }
+
+ private static void configure(DecimalEditing editing) {
+ editing.modelDecimalConstraints()
+ .requiredMessage(REQUIRED_MESSAGE)
+ .rangeMessage(INTEGER_RANGE_MESSAGE);
+ }
+
+ public static BooleanEditing forBoolean() {
+ BooleanEditing editing =
+ BooleanEditing.forStringValues(
+ BOOLEAN_TRUE_VALUES,
+ BOOLEAN_FALSE_VALUES);
+ configure(editing);
+ return editing;
+ }
+
+ private static void configure(BooleanEditing editing) {
+ editing.modelBooleanConstraints()
+ .requiredMessage(REQUIRED_MESSAGE);
+ }
+
+ public static DateEditing forDate() {
+ return forDate(Locale.getDefault());
+ }
+
+ public static DateEditing forDate(Locale locale) {
+ DateEditing editing = DateEditing
+ .forFormats(
+ createDateFormats(DATE_INPUT_PATTERNS, locale),
+ DATE_PARSE_ERROR_MESSAGE,
+ DateFormat.getPatternInstance(DATE_DISPLAY_PATTERN, locale));
+ editing.modelDateConstraints().requiredMessage(REQUIRED_MESSAGE);
+ return editing;
+ }
+
+ private static DateFormat[] createDateFormats(String[] datePatterns, Locale locale) {
+ DateFormat[] dateFormats = new DateFormat[datePatterns.length];
+ for (int i = 0; i < dateFormats.length; i++) {
+ dateFormats[i] = DateFormat.getPatternInstance(datePatterns[i], locale);
+ }
+ return dateFormats;
+ }
+
+ private static String createDateParseErrorMessage(String[] datePatterns) {
+ StringBuffer messageSb = new StringBuffer();
+ messageSb.append("Supported formats: ");
+ for (int i = 0; i < datePatterns.length; i++) {
+ if (i > 0) {
+ messageSb.append(", ");
+ }
+ messageSb.append(datePatterns[i]);
+ }
+ return messageSb.toString();
+ }
+}
Index: src/org/eclipse/jface/examples/databinding/util/RadixNumberFormat.java
===================================================================
RCS file: src/org/eclipse/jface/examples/databinding/util/RadixNumberFormat.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/examples/databinding/util/RadixNumberFormat.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.jface.examples.databinding.util;
+
+import java.math.BigInteger;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+
+import com.ibm.icu.math.BigDecimal;
+import com.ibm.icu.text.NumberFormat;
+
+/**
+ * @since 3.2
+ *
+ */
+public class RadixNumberFormat extends NumberFormat {
+
+ private static final long serialVersionUID = 411884077848863891L;
+
+ private final int radix;
+
+ private final String prefix;
+
+ private final int digits;
+
+ private RadixNumberFormat(int radix, String prefix, int digits) {
+ this.radix = radix;
+ this.prefix = prefix != null ? prefix : "";
+ this.digits = digits;
+ }
+
+ public static RadixNumberFormat getHexInstance() {
+ return getHexInstance(null, 0);
+ }
+
+ public static RadixNumberFormat getHexInstance(String prefix, int digits) {
+ return new RadixNumberFormat(16, prefix, digits);
+ }
+
+ public StringBuffer format(double number, StringBuffer toAppendTo,
+ FieldPosition pos) {
+ return format((long) number, toAppendTo, pos);
+ }
+
+ public StringBuffer format(long number, StringBuffer toAppendTo,
+ FieldPosition pos) {
+ return toAppendTo.append(prefix).append(addPadding(Long.toString(number, radix)));
+ }
+
+ public StringBuffer format(BigInteger number, StringBuffer toAppendTo,
+ FieldPosition pos) {
+ return toAppendTo.append(prefix).append(addPadding(number.toString(radix)));
+ }
+
+ public StringBuffer format(BigDecimal number, StringBuffer toAppendTo,
+ FieldPosition pos) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Number parse(String text, ParsePosition parsePosition) {
+ if (text.length() == 0) {
+ return null;
+ }
+
+ parsePosition.setIndex(parsePosition.getIndex() + text.length());
+
+ try {
+ if (text.startsWith(prefix)) {
+ return Integer.parseInt(text.substring(prefix.length()), radix);
+ }
+ return Integer.parseInt(text, radix);
+ } catch (NumberFormatException e) {
+ parsePosition.setErrorIndex(0);
+ return null;
+ }
+ }
+
+ private String addPadding(String numberText) {
+ if (numberText.length() >= digits) {
+ return numberText;
+ }
+
+ StringBuffer sb = new StringBuffer();
+ for (int i = numberText.length(); i < digits; i++) {
+ sb.append('0');
+ }
+ sb.append(numberText);
+ return sb.toString();
+ }
+}
Index: src/org/eclipse/jface/examples/databinding/util/ObservableMapEditingCellLabelProvider.java
===================================================================
RCS file: src/org/eclipse/jface/examples/databinding/util/ObservableMapEditingCellLabelProvider.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/examples/databinding/util/ObservableMapEditingCellLabelProvider.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.jface.examples.databinding.util;
+
+import org.eclipse.core.databinding.editing.Editing;
+import org.eclipse.core.databinding.observable.map.IObservableMap;
+import org.eclipse.jface.databinding.viewers.ObservableMapCellLabelProvider;
+import org.eclipse.jface.viewers.ViewerCell;
+
+/**
+ * @since 3.2
+ */
+public class ObservableMapEditingCellLabelProvider extends
+ ObservableMapCellLabelProvider {
+
+ private final IObservableMap attributeMap;
+
+ private final Editing editing;
+
+ public ObservableMapEditingCellLabelProvider(IObservableMap attributeMap, Editing editing) {
+ super(attributeMap);
+ this.attributeMap = attributeMap;
+ this.editing = editing;
+ }
+
+ public void update(ViewerCell cell) {
+ Object element = cell.getElement();
+ Object attribute = attributeMap.get(element);
+ cell.setText((String) editing.convertToTarget(attribute));
+ }
+}
Index: src/org/eclipse/jface/examples/databinding/snippets/Snippet036EditingTable.java
===================================================================
RCS file: src/org/eclipse/jface/examples/databinding/snippets/Snippet036EditingTable.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/examples/databinding/snippets/Snippet036EditingTable.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,252 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.jface.examples.databinding.snippets;
+
+import java.util.Date;
+
+import org.eclipse.core.databinding.Binding;
+import org.eclipse.core.databinding.DataBindingContext;
+import org.eclipse.core.databinding.beans.BeansObservables;
+import org.eclipse.core.databinding.editing.DateEditing;
+import org.eclipse.core.databinding.editing.Editing;
+import org.eclipse.core.databinding.editing.IntegerEditing;
+import org.eclipse.core.databinding.editing.StringEditing;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.list.WritableList;
+import org.eclipse.core.databinding.observable.map.IObservableMap;
+import org.eclipse.core.databinding.observable.set.IObservableSet;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.databinding.swt.ISWTObservableValue;
+import org.eclipse.jface.databinding.swt.SWTObservables;
+import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
+import org.eclipse.jface.databinding.viewers.ViewersObservables;
+import org.eclipse.jface.examples.databinding.ModelObject;
+import org.eclipse.jface.examples.databinding.util.EditingFactory;
+import org.eclipse.jface.examples.databinding.util.ObservableMapEditingCellLabelProvider;
+import org.eclipse.jface.examples.databinding.util.ObservableMapEditingSupport;
+import org.eclipse.jface.internal.databinding.provisional.fieldassist.ControlDecorationSupport;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public class Snippet036EditingTable {
+
+ private final StringEditing nameEditing = EditingFactory.forString().required();
+
+ private final IntegerEditing ageEditing = EditingFactory.forInteger().required().nonNegative();
+
+ private final DateEditing bdayEditing = EditingFactory.forDate().before(new Date());
+
+ private DataBindingContext dbc;
+
+ private TableViewer tableViewer;
+
+ public static void main(String[] args) {
+ Display display = new Display();
+
+ Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
+ public void run() {
+ Shell shell = new Snippet036EditingTable().createShell();
+ Display display = Display.getCurrent();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ }
+ });
+ }
+
+ private Shell createShell() {
+ Display display = Display.getCurrent();
+ Shell shell = new Shell(display);
+ shell.setText("Editing");
+ shell.setLayout(new GridLayout(2, false));
+
+ dbc = new DataBindingContext();
+
+ createTableSection(shell);
+ createFieldSection(shell);
+
+ shell.pack();
+ shell.open();
+
+ return shell;
+ }
+
+ private void createTableSection(Composite parent) {
+ Group section = createSectionGroup(parent, 1);
+
+ tableViewer = new TableViewer(section, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION);
+ GridDataFactory.fillDefaults().grab(true, true).hint(350, 250).applyTo(tableViewer.getTable());
+ tableViewer.getTable().setHeaderVisible(true);
+ tableViewer.getTable().setLinesVisible(true);
+
+ ObservableListContentProvider contentProvider = new ObservableListContentProvider();
+ tableViewer.setContentProvider(contentProvider);
+ IObservableSet contentElements = contentProvider.getKnownElements();
+
+ IObservableMap nameMap = BeansObservables.observeMap(contentElements, "name");
+ createColumn("Name*", 150, nameMap, nameEditing);
+
+ IObservableMap ageMap = BeansObservables.observeMap(contentElements, "age");
+ createColumn("Age*", 50, ageMap, ageEditing);
+
+ IObservableMap bdayMap = BeansObservables.observeMap(contentElements, "birthday");
+ createColumn("Birthday", 80, bdayMap, bdayEditing);
+
+ WritableList people = new WritableList();
+ people.add(new Person("John Doe", 27));
+ people.add(new Person("Steve Northover", 33));
+ people.add(new Person("Grant Gayed", 54));
+ people.add(new Person("Veronika Irvine", 25));
+ people.add(new Person("Mike Wilson", 44));
+ people.add(new Person("Christophe Cornu", 37));
+ people.add(new Person("Lynne Kues", 65));
+ people.add(new Person("Silenio Quarti", 15));
+
+ tableViewer.setInput(people);
+
+ tableViewer.setSelection(new StructuredSelection(people.get(0)));
+ }
+
+ private TableViewerColumn createColumn(String text, int width, IObservableMap attributeMap, Editing modelEditing) {
+ TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.NONE);
+ column.getColumn().setText(text);
+ column.getColumn().setWidth(width);
+ column.setLabelProvider(new ObservableMapEditingCellLabelProvider(attributeMap, modelEditing));
+ column.setEditingSupport(new ObservableMapEditingSupport(tableViewer, attributeMap, modelEditing));
+ return column;
+ }
+
+ private void createFieldSection(Composite parent) {
+ final Group section = createSectionGroup(parent, 2);
+
+ final IObservableValue personObservable = ViewersObservables.observeSingleSelection(tableViewer);
+
+ Text nameText = createTextField(section, "Name*");
+ IObservableValue nameObservable = BeansObservables.observeDetailValue(personObservable, "name", null);
+ bindTextField(nameText, nameObservable, nameEditing);
+
+ Text ageText = createTextField(section, "Age*");
+ IObservableValue ageObservable = BeansObservables.observeDetailValue(personObservable, "age", null);
+ bindTextField(ageText, ageObservable, ageEditing);
+
+ Text bdayText = createTextField(section, "Birthday");
+ IObservableValue bdayObservable = BeansObservables.observeDetailValue(personObservable, "birthday", null);
+ bindTextField(bdayText, bdayObservable, bdayEditing);
+ }
+
+ private Binding bindTextField(
+ Text text,
+ IObservableValue modelValue,
+ Editing editing) {
+ // Create the binding using the editing object.
+ ISWTObservableValue textObservable = SWTObservables.observeText(text, SWT.Modify);
+ Binding binding = editing.bindValue(dbc, textObservable, modelValue);
+
+ // Decorate the control with the validation status.
+ ControlDecorationSupport.create(binding, SWT.TOP);
+
+ formatOnFocusOut(text, binding);
+
+ return binding;
+ }
+
+ private static void formatOnFocusOut(final Control control, final Binding binding) {
+ control.addFocusListener(new FocusAdapter() {
+ public void focusLost(FocusEvent e) {
+ IStatus dateValidationStatus = (IStatus) binding.getValidationStatus().getValue();
+ if (dateValidationStatus.isOK()) {
+ binding.updateModelToTarget();
+ }
+ }
+ });
+ }
+
+ private Group createSectionGroup(Composite parent, int numColumns) {
+ Group section = new Group(parent, SWT.SHADOW_ETCHED_IN);
+ GridLayoutFactory.fillDefaults().numColumns(numColumns).equalWidth(false).margins(5, 5).spacing(15, 5).applyTo(section);
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(section);
+ return section;
+ }
+
+ private static Text createTextField(Composite parent, String labelText) {
+ Label label = new Label(parent, SWT.LEFT);
+ label.setText(labelText);
+ GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
+
+ final Text text = new Text(parent, SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, false).hint(200, SWT.DEFAULT).applyTo(text);
+
+ // Select the text when gaining focus.
+ text.addFocusListener(new FocusAdapter() {
+ public void focusGained(FocusEvent e) {
+ text.selectAll();
+ }
+ });
+
+ return text;
+ }
+
+ public static final class Person extends ModelObject {
+
+ private String name;
+
+ private int age;
+
+ private Date birthday;
+
+ public Person(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ firePropertyChange("name", this.name, this.name = name);
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ firePropertyChange("age", this.age, this.age = age);
+ }
+
+ public Date getBirthday() {
+ return birthday;
+ }
+
+ public void setBirthday(Date birthday) {
+ firePropertyChange("birthday", this.birthday, this.birthday = birthday);
+ }
+ }
+}
Index: src/org/eclipse/core/internal/databinding/conversion/StringToNumberParser.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/StringToNumberParser.java,v
--- src/org/eclipse/core/internal/databinding/conversion/StringToNumberParser.java 28 Oct 2008 19:54:39 -0000 1.6
+++ src/org/eclipse/core/internal/databinding/conversion/StringToNumberParser.java 11 Oct 2009 20:35:22 -0000
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Ovidio Mallo - bug 183055
*******************************************************************************/
package org.eclipse.core.internal.databinding.conversion;
@@ -115,11 +116,11 @@
.getErrorIndex() : position.getIndex();
if (errorIndex < value.length()) {
- return BindingMessages.formatString(BindingMessages.VALIDATE_NUMBER_PARSE_ERROR,
+ return BindingMessages.getFormattedString(BindingMessages.VALIDATE_NUMBER_PARSE_ERROR,
new Object[] { value, new Integer(errorIndex + 1),
new Character(value.charAt(errorIndex)) });
}
- return BindingMessages.formatString(BindingMessages.VALIDATE_NUMBER_PARSE_ERROR_NO_CHARACTER,
+ return BindingMessages.getFormattedString(BindingMessages.VALIDATE_NUMBER_PARSE_ERROR_NO_CHARACTER,
new Object[] { value, new Integer(errorIndex + 1) });
}
@@ -133,6 +134,22 @@
*/
public static String createOutOfRangeMessage(Number minValue,
Number maxValue, NumberFormat numberFormat) {
+ return createOutOfRangeMessage(
+ BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_OUT_OF_RANGE_ERROR), minValue, maxValue, numberFormat);
+ }
+
+ /**
+ * Formats an appropriate message for an out of range error.
+ *
+ * @param message
+ * @param minValue
+ * @param maxValue
+ * @param numberFormat
+ * when accessed method synchronizes on instance
+ * @return message
+ */
+ public static String createOutOfRangeMessage(String message,
+ Number minValue, Number maxValue, NumberFormat numberFormat) {
String min = null;
String max = null;
@@ -141,8 +158,8 @@
max = numberFormat.format(maxValue);
}
- return BindingMessages.formatString(
- "Validate_NumberOutOfRangeError", new Object[] { min, max }); //$NON-NLS-1$
+ return BindingMessages.formatMessage(message, new Object[] { min,
+ max });
}
/**
Index: src/org/eclipse/core/internal/databinding/conversion/StringToBooleanPrimitiveConverter.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/StringToBooleanPrimitiveConverter.java,v
--- src/org/eclipse/core/internal/databinding/conversion/StringToBooleanPrimitiveConverter.java 25 May 2009 20:52:20 -0000 1.4
+++ src/org/eclipse/core/internal/databinding/conversion/StringToBooleanPrimitiveConverter.java 11 Oct 2009 20:35:22 -0000
@@ -9,6 +9,7 @@
* Contributors:
* db4objects - Initial API and implementation
* Tom Schindl
+ * Note that the capitalization of the provided strings is ignored.
+ *
+ * This method provides a typesafe access to the {@link StringConstraints
+ * string target constraints} of this editing object and is equivalent to
+ * {@code (StringConstraints) targetConstraints()}.
+ *
+ * This method provides a typesafe access to the {@link StringConstraints
+ * string model constraints} of this editing object and is equivalent to
+ * {@code (StringConstraints) modelConstraints()}.
+ *
+ * This method provides a typesafe access to the {@link StringConstraints
+ * string before-set model constraints} of this editing object and is
+ * equivalent to {@code (StringConstraints) beforeSetModelConstraints()}.
+ *
+ * This decimal format will be used for any subsequent constraints which are
+ * applied.
+ *
+ * This integer format will be used for any subsequent constraints which are
+ * applied.
+ *
+ * This date format will be used for any subsequent constraints which are
+ * applied.
+ *
+ * For parsing, the given string values will be considered valid
+ * representations of {@code true} and {@code false}, respectively. For
+ * displaying, the first element of the respective array will be used for
+ * representing the corresponding boolean value.
+ *
+ * For parsing, the given string values will be considered valid
+ * representations of {@code true} and {@code false}, respectively. For
+ * displaying, the first element of the respective array will be used for
+ * representing the corresponding boolean value.
+ *
+ * This method provides a typesafe access to the {@link StringConstraints
+ * string target constraints} of this editing object and is equivalent to
+ * {@code (StringConstraints) targetConstraints()}.
+ *
+ * This method provides a typesafe access to the {@link BooleanConstraints
+ * bool model constraints} of this editing object and is equivalent to
+ * {@code (BooleanConstraints) modelConstraints()}.
+ *
+ * This method provides a typesafe access to the {@link BooleanConstraints
+ * bool before-set model constraints} of this editing object and is
+ * equivalent to {@code (BooleanConstraints) beforeSetModelConstraints()}.
+ *
+ * Note that this method will return
+ * Note that the capitalization of the provided strings is ignored.
+ *
+ * This integer format will be used for any subsequent constraints which are
+ * applied.
+ *
+ * The constraints object created by this method will be exposed as the
+ * {@link #targetConstraints()} of this editing object. By default, this
+ * method returns a plain {@link Constraints} object.
+ *
+ * This method will be called lazily the first time the target constraints
+ * are accessed. Subclasses may overwrite this method in order to create a
+ * custom constraints object which will then be typically exposed in the
+ * subclass as API in order to allow for a typesafe access.
+ *
+ * The constraints object created by this method will be exposed as the
+ * {@link #modelConstraints()} of this editing object. By default, this
+ * method returns a plain {@link Constraints} object.
+ *
+ * This method will be called lazily the first time the model constraints
+ * are accessed. Subclasses may overwrite this method in order to create a
+ * custom constraints object which will then be typically exposed in the
+ * subclass as API in order to allow for a typesafe access.
+ *
+ * The constraints object created by this method will be exposed as the
+ * {@link #beforeSetModelConstraints()} of this editing object. By default,
+ * this method returns a plain {@link Constraints} object.
+ *
+ * This method will be called lazily the first time the before-set model
+ * constraints are accessed. Subclasses may overwrite this method in order
+ * to create a custom constraints object which will then be typically
+ * exposed in the subclass as API in order to allow for a typesafe access.
+ *
+ * The configuration is done as follows:
+ * true
and false
value, respectively.
+ *
+ * true
value.
+ * @param falseValues
+ * The set of strings representing a false
value.
+ */
+ public final void setSourceStrings(String[] trueValues, String[] falseValues) {
+ this.trueValues = new String[trueValues.length];
+ for (int i = 0; i < trueValues.length; i++) {
+ this.trueValues[i] = trueValues[i].toUpperCase();
+ }
+ Arrays.sort(this.trueValues); // for binary search
+
+ this.falseValues = new String[falseValues.length];
+ for (int i = 0; i < falseValues.length; i++) {
+ this.falseValues[i] = falseValues[i].toUpperCase();
+ }
+ Arrays.sort(this.falseValues); // for binary search
+ }
+
/*
* (non-Javadoc)
*
Index: src/org/eclipse/core/internal/databinding/conversion/DateConversionSupport.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/DateConversionSupport.java,v
--- src/org/eclipse/core/internal/databinding/conversion/DateConversionSupport.java 25 May 2009 20:52:20 -0000 1.5
+++ src/org/eclipse/core/internal/databinding/conversion/DateConversionSupport.java 11 Oct 2009 20:35:22 -0000
@@ -10,6 +10,7 @@
* db4objects - Initial API and implementation
* Tom SchindlInteger.MIN_VALUE
and
+ * Integer.MAX_VALUE
values.
+ */
+ public final void setOutOfRangeMessage(String message) {
+ this.outOfRangeMessage = message;
+ this.formattedOutOfRangeMessage = null;
+ }
+
+ /**
* Validates the provided value
. An error status is returned if:
*
*
true
if in range
*/
protected abstract boolean isInRange(Number number);
+
+ private String createParseErrorMessage(String input,
+ ParsePosition parsePosition) {
+ if (parseErrorMessage == null) {
+ return StringToNumberParser.createParseErrorMessage(input,
+ parsePosition);
+ }
+ return parseErrorMessage;
+ }
+
+ private String getFormattedOutOfRangeMessage() {
+ if (formattedOutOfRangeMessage == null) {
+ formattedOutOfRangeMessage = StringToNumberParser
+ .createOutOfRangeMessage(outOfRangeMessage, min, max,
+ converter.getNumberFormat());
+ }
+ return formattedOutOfRangeMessage;
+ }
}
Index: META-INF/MANIFEST.MF
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/META-INF/MANIFEST.MF,v
--- META-INF/MANIFEST.MF 25 Aug 2009 04:57:27 -0000 1.21
+++ META-INF/MANIFEST.MF 11 Oct 2009 20:35:21 -0000
@@ -8,7 +8,9 @@
Bundle-Localization: plugin
Export-Package: org.eclipse.core.databinding,
org.eclipse.core.databinding.conversion;x-internal:=false,
+ org.eclipse.core.databinding.editing,
org.eclipse.core.databinding.validation;x-internal:=false,
+ org.eclipse.core.databinding.validation.constraint,
org.eclipse.core.internal.databinding;x-friends:="org.eclipse.core.databinding.beans",
org.eclipse.core.internal.databinding.conversion;x-friends:="org.eclipse.jface.tests.databinding",
org.eclipse.core.internal.databinding.validation;x-friends:="org.eclipse.jface.tests.databinding"
Index: src/org/eclipse/core/internal/databinding/BindingMessages.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/BindingMessages.java,v
--- src/org/eclipse/core/internal/databinding/BindingMessages.java 9 May 2008 14:13:00 -0000 1.6
+++ src/org/eclipse/core/internal/databinding/BindingMessages.java 11 Oct 2009 20:35:22 -0000
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Tom Schindlnull
in
+ * case stripping the input string results in an empty string.
+ * @return The new editing object which strips whitespace from both ends of
+ * the input string.
+ *
+ * @see Character#isWhitespace(char)
+ */
+ public static StringEditing stripped(boolean stripToNull) {
+ return new StringEditing(new StringStripConverter(stripToNull));
+ }
+
+ /**
+ * Creates a new editing object which {@link String#trim()}s the input
+ * string.
+ *
+ * @param trimToNull
+ * Whether to convert the input string to null
in
+ * case trimming the input string results in an empty string.
+ * @return The new editing object which trims whitespace from both ends of
+ * the input string.
+ *
+ * @see String#trim()
+ */
+ public static StringEditing trimmed(boolean trimToNull) {
+ return new StringEditing(new StringTrimConverter(trimToNull));
+ }
+
+ /**
+ * Returns the target constraints to apply.
+ *
+ * null
in case no
+ * lower bound is defined.
+ * @param max
+ * The max date of the range or null
in case no
+ * upper bound is defined.
+ * @param minConstraint
+ * The type of constraint imposed by the lower bound of the
+ * range.
+ * @param maxConstraint
+ * The type of constraint imposed by the upper bound of the
+ * range.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized by
+ * the lower and upper bound of the range, if defined.
+ * @param format
+ * The date format to use for formatting dates in the validation
+ * message.
+ */
+ private DateRangeValidator(Date min, Date max, int minConstraint,
+ int maxConstraint, String validationMessage, DateFormat format) {
+ this.min = min;
+ this.max = max;
+ this.minConstraint = minConstraint;
+ this.maxConstraint = maxConstraint;
+ this.validationMessage = validationMessage;
+ this.format = format;
+ }
+
+ /**
+ * Creates a validator which checks that an input date is after the given
+ * date.
+ *
+ * @param date
+ * The reference date of the after constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference date.
+ * @param format
+ * The display format to use for formatting dates in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DateRangeValidator after(Date date, String validationMessage,
+ DateFormat format) {
+ return new DateRangeValidator(date, null, AFTER, UNDEFINED,
+ defaultIfNull(validationMessage, AFTER_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input date is after or on the
+ * given date.
+ *
+ * @param date
+ * The reference date of the after-equal constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference date.
+ * @param format
+ * The display format to use for formatting dates in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DateRangeValidator afterEqual(Date date,
+ String validationMessage, DateFormat format) {
+ return new DateRangeValidator(date, null, AFTER_EQUAL, UNDEFINED,
+ defaultIfNull(validationMessage, AFTER_EQUAL_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input date is before the given
+ * date.
+ *
+ * @param date
+ * The reference date of the before constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference date.
+ * @param format
+ * The display format to use for formatting dates in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DateRangeValidator before(Date date, String validationMessage,
+ DateFormat format) {
+ return new DateRangeValidator(null, date, UNDEFINED, BEFORE,
+ defaultIfNull(validationMessage, BEFORE_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input date is before or on the
+ * given date.
+ *
+ * @param date
+ * The reference date of the before-equal constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference date.
+ * @param format
+ * The display format to use for formatting dates in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DateRangeValidator beforeEqual(Date date,
+ String validationMessage, DateFormat format) {
+ return new DateRangeValidator(null, date, UNDEFINED, BEFORE_EQUAL,
+ defaultIfNull(validationMessage, BEFORE_EQUAL_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input date is within the given
+ * range.
+ *
+ * @param min
+ * The lower bound of the range (inclusive).
+ * @param max
+ * The upper bound of the range (inclusive).
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the range's lower and upper bound.
+ * @param format
+ * The display format to use for formatting dates in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DateRangeValidator range(Date min, Date max,
+ String validationMessage, DateFormat format) {
+ return new DateRangeValidator(min, max, AFTER_EQUAL, BEFORE_EQUAL,
+ defaultIfNull(validationMessage, WITHIN_RANGE_MESSAGE), format);
+ }
+
+ public IStatus validate(Object value) {
+ if (value != null) {
+ Date date = (Date) value;
+ if ((min != null && !fulfillsConstraint(date, min, minConstraint))
+ || (max != null && !fulfillsConstraint(date, max,
+ maxConstraint))) {
+ return ValidationStatus.error(getFormattedValidationMessage());
+ }
+ }
+ return ValidationStatus.ok();
+ }
+
+ private boolean fulfillsConstraint(Date date1, Date date2, int constraint) {
+ switch (constraint) {
+ case AFTER:
+ return date1.after(date2);
+ case AFTER_EQUAL:
+ return date1.after(date2) || date1.equals(date2);
+ case BEFORE:
+ return date1.before(date2);
+ case BEFORE_EQUAL:
+ return date1.before(date2) || date1.equals(date2);
+ case UNDEFINED:
+ default:
+ throw new IllegalArgumentException(
+ "Unsupported constraint: " + constraint); //$NON-NLS-1$
+ }
+ }
+
+ private synchronized String getFormattedValidationMessage() {
+ if (formattedValidationMessage == null) {
+ formattedValidationMessage = MessageFormat.format(
+ validationMessage, getValidationMessageArguments());
+ }
+ return formattedValidationMessage;
+ }
+
+ private String[] getValidationMessageArguments() {
+ synchronized (format) {
+ if (min == null) {
+ return new String[] { format.format(max) };
+ } else if (max == null) {
+ return new String[] { format.format(min) };
+ }
+ return new String[] { format.format(min), format.format(max) };
+ }
+ }
+
+ private static String defaultIfNull(String string, String defaultString) {
+ return (string != null) ? string : defaultString;
+ }
+}
Index: src/org/eclipse/core/internal/databinding/validation/NumberRangeValidator.java
===================================================================
RCS file: src/org/eclipse/core/internal/databinding/validation/NumberRangeValidator.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/internal/databinding/validation/NumberRangeValidator.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding.validation;
+
+import java.text.MessageFormat;
+
+import org.eclipse.core.databinding.validation.IValidator;
+import org.eclipse.core.databinding.validation.ValidationStatus;
+import org.eclipse.core.internal.databinding.BindingMessages;
+import org.eclipse.core.runtime.IStatus;
+
+import com.ibm.icu.text.NumberFormat;
+
+/**
+ * Provides validations for numbers which must lie within an open/closed range.
+ *
+ * @since 1.4
+ */
+public abstract class NumberRangeValidator implements IValidator {
+
+ // The set of constraint types for the lower/upper bound of the date range.
+ protected static final int UNDEFINED = -1;
+ protected static final int GREATER = 0;
+ protected static final int GREATER_EQUAL = 1;
+ protected static final int LESS = 2;
+ protected static final int LESS_EQUAL = 3;
+
+ // The default validation messages.
+ protected static final String GREATER_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_GREATER);
+ protected static final String GREATER_EQUAL_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_GREATER_EQUAL);
+ protected static final String LESS_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_LESS);
+ protected static final String LESS_EQUAL_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_LESS_EQUAL);
+ protected static final String WITHIN_RANGE_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_WITHIN_RANGE);
+ protected static final String POSITIVE_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_POSITIVE);
+ protected static final String NON_NEGATIVE_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_NON_NEGATIVE);
+
+ private final Number min;
+ private final Number max;
+ private final int minConstraint;
+ private final int maxConstraint;
+ private final String validationMessage;
+ private String formattedValidationMessage;
+ private final NumberFormat format;
+
+ /**
+ * Single constructor which supports the individual number range types.
+ *
+ * @param min
+ * The min number of the range or null
in case no
+ * lower bound is defined.
+ * @param max
+ * The max number of the range or null
in case no
+ * upper bound is defined.
+ * @param minConstraint
+ * The type of constraint imposed by the lower bound of the
+ * range.
+ * @param maxConstraint
+ * The type of constraint imposed by the upper bound of the
+ * range.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized by
+ * the lower and upper bound of the range, if defined.
+ * @param format
+ * The integer format to use for formatting numbers in the
+ * validation message.
+ */
+ protected NumberRangeValidator(Number min, Number max, int minConstraint,
+ int maxConstraint, String validationMessage, NumberFormat format) {
+ this.min = min;
+ this.max = max;
+ this.minConstraint = minConstraint;
+ this.maxConstraint = maxConstraint;
+ this.validationMessage = validationMessage;
+ this.format = format;
+ }
+
+ public IStatus validate(Object value) {
+ if (value != null) {
+ Number number = (Number) value;
+ if ((min != null && !fulfillsConstraint(number, min, minConstraint))
+ || (max != null && !fulfillsConstraint(number, max,
+ maxConstraint))) {
+ return ValidationStatus.error(getFormattedValidationMessage());
+ }
+ }
+ return ValidationStatus.ok();
+ }
+
+ private boolean fulfillsConstraint(Number number1, Number number2,
+ int constraint) {
+ int compareResult = compare(number1, number2);
+ switch (constraint) {
+ case GREATER:
+ return compareResult > 0;
+ case GREATER_EQUAL:
+ return compareResult >= 0;
+ case LESS:
+ return compareResult < 0;
+ case LESS_EQUAL:
+ return compareResult <= 0;
+ case UNDEFINED:
+ default:
+ throw new IllegalArgumentException(
+ "Unsupported constraint: " + constraint); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Comparator method to be implemented by subclasses in order to compare two
+ * instances of the concrete number type.
+ *
+ * @param number1
+ * The first number to compare.
+ * @param number2
+ * The second number to compare.
+ * @return A negative number, zero, or a positive number in case the first
+ * number is smaller than, equal to, or greater than the second
+ * number, respectively.
+ */
+ protected abstract int compare(Number number1, Number number2);
+
+ private synchronized String getFormattedValidationMessage() {
+ if (formattedValidationMessage == null) {
+ formattedValidationMessage = MessageFormat.format(
+ validationMessage, getValidationMessageArguments());
+ }
+ return formattedValidationMessage;
+ }
+
+ private String[] getValidationMessageArguments() {
+ synchronized (format) {
+ if (min == null) {
+ return new String[] { format.format(max) };
+ } else if (max == null) {
+ return new String[] { format.format(min) };
+ }
+ return new String[] { format.format(min), format.format(max) };
+ }
+ }
+}
Index: src/org/eclipse/core/internal/databinding/validation/StringLengthValidator.java
===================================================================
RCS file: src/org/eclipse/core/internal/databinding/validation/StringLengthValidator.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/internal/databinding/validation/StringLengthValidator.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding.validation;
+
+import java.text.MessageFormat;
+
+import org.eclipse.core.databinding.validation.IValidator;
+import org.eclipse.core.databinding.validation.ValidationStatus;
+import org.eclipse.core.internal.databinding.BindingMessages;
+import org.eclipse.core.runtime.IStatus;
+
+import com.ibm.icu.text.NumberFormat;
+
+/**
+ * Provides validations for strings which must have a specified length.
+ *
+ * @since 1.4
+ */
+public class StringLengthValidator implements IValidator {
+
+ // The default validation messages.
+ private static final String MIN_LENGTH_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_STRING_LENGTH_MIN);
+ private static final String MAX_LENGTH_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_STRING_LENGTH_MAX);
+ private static final String LENGTH_RANGE_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_STRING_LENGTH_RANGE);
+
+ private final Integer minLength;
+ private final Integer maxLength;
+ private final String validationMessage;
+ private String formattedValidationMessage;
+ private final NumberFormat format;
+
+ /**
+ * Creates a string length validator defining a minimum and/or maximum
+ * length for a string.
+ *
+ * @param minLength
+ * The minimum length of the string or null
in case
+ * no minimum length is defined.
+ * @param maxLength
+ * The maximum length of the string or null
in case
+ * no maximum length is defined.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized by
+ * the lower and upper bound of the range, if defined.
+ * @param format
+ * The number format to use for formatting integers (the length
+ * bounds) in the validation message.
+ */
+ private StringLengthValidator(Integer minLength, Integer maxLength,
+ String validationMessage, NumberFormat format) {
+ this.minLength = minLength;
+ this.maxLength = maxLength;
+ this.validationMessage = validationMessage;
+ this.format = format;
+ }
+
+ /**
+ * Creates a validator which checks that an input string has the given
+ * minimum length.
+ *
+ * @param minLength
+ * The minimum length which the input string must have.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given minimum length.
+ * @param format
+ * The display format to use for formatting integers (the minimum
+ * length) in the validation message.
+ * @return The validator instance.
+ */
+ public static StringLengthValidator minLength(int minLength,
+ String validationMessage, NumberFormat format) {
+ return new StringLengthValidator(new Integer(minLength), null,
+ defaultIfNull(validationMessage, MIN_LENGTH_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input string has the given
+ * maximum length.
+ *
+ * @param maxLength
+ * The maximum length which the input string must have.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given maximum length.
+ * @param format
+ * The display format to use for formatting integers (the maximum
+ * length) in the validation message.
+ * @return The validator instance.
+ */
+ public static StringLengthValidator maxLength(int maxLength,
+ String validationMessage, NumberFormat format) {
+ return new StringLengthValidator(null, new Integer(maxLength),
+ defaultIfNull(validationMessage, MAX_LENGTH_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that the length of an input string lies
+ * in the given range.
+ *
+ * @param minLength
+ * The minimum length which the input string must have.
+ * @param maxLength
+ * The maximum length which the input string must have.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given minimum and maximum lengths.
+ * @param format
+ * The display format to use for formatting integers (the
+ * minimum/maximum length) in the validation message.
+ * @return The validator instance.
+ */
+ public static StringLengthValidator lengthRange(int minLength,
+ int maxLength, String validationMessage, NumberFormat format) {
+ return new StringLengthValidator(new Integer(minLength), new Integer(
+ maxLength), defaultIfNull(validationMessage,
+ LENGTH_RANGE_MESSAGE), format);
+ }
+
+ public IStatus validate(Object value) {
+ String input = (String) value;
+ if (input != null) {
+ int inputLength = input.length();
+ if ((minLength != null && inputLength < minLength.intValue())
+ || maxLength != null && inputLength > maxLength.intValue()) {
+ return ValidationStatus.error(getFormattedValidationMessage());
+ }
+ }
+ return ValidationStatus.ok();
+ }
+
+ private synchronized String getFormattedValidationMessage() {
+ if (formattedValidationMessage == null) {
+ formattedValidationMessage = MessageFormat.format(
+ validationMessage, getValidationMessageArguments());
+ }
+ return formattedValidationMessage;
+ }
+
+ private String[] getValidationMessageArguments() {
+ synchronized (format) {
+ if (minLength == null) {
+ return new String[] { format.format(maxLength) };
+ } else if (maxLength == null) {
+ return new String[] { format.format(minLength) };
+ }
+ return new String[] { format.format(minLength),
+ format.format(maxLength) };
+ }
+ }
+
+ private static String defaultIfNull(String string, String defaultString) {
+ return (string != null) ? string : defaultString;
+ }
+}
Index: src/org/eclipse/core/databinding/validation/constraint/DecimalConstraints.java
===================================================================
RCS file: src/org/eclipse/core/databinding/validation/constraint/DecimalConstraints.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/databinding/validation/constraint/DecimalConstraints.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.databinding.validation.constraint;
+
+import org.eclipse.core.internal.databinding.validation.DecimalRangeValidator;
+import org.eclipse.core.internal.databinding.validation.DecimalScaleValidator;
+import org.eclipse.core.internal.databinding.validation.NonNullValidator;
+
+import com.ibm.icu.text.NumberFormat;
+
+/**
+ * @since 1.4
+ */
+public final class DecimalConstraints extends Constraints {
+
+ private NumberFormat decimalDisplayFormat = NumberFormat
+ .getNumberInstance();
+
+ private NumberFormat integerDisplayFormat = NumberFormat
+ .getIntegerInstance();
+
+ private String requiredMessage = null;
+
+ private String greaterMessage = null;
+
+ private String greaterEqualMessage = null;
+
+ private String lessMessage = null;
+
+ private String lessEqualMessage = null;
+
+ private String rangeMessage = null;
+
+ private String positiveMessage = null;
+
+ private String nonNegativeMessage = null;
+
+ private String maxScaleMessage = null;
+
+ /**
+ * Sets the format to use when formatting a decimal to be included in any of
+ * the validation messages.
+ *
+ * null
. Uses the current {@link #requiredMessage(String)
+ * validation message}.
+ *
+ * @return This constraints instance for method chaining.
+ */
+ public DecimalConstraints required() {
+ addValidator(new NonNullValidator(requiredMessage));
+ return this;
+ }
+
+ /**
+ * Sets the validation message for the {@link #required()} constraint.
+ *
+ * @param message
+ * The validation message for the {@link #required()} constraint.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #required()
+ */
+ public DecimalConstraints requiredMessage(String message) {
+ this.requiredMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed decimal is greater than the
+ * given number. Uses the current {@link #greaterMessage(String) validation
+ * message}.
+ *
+ * @param number
+ * The number which the parsed decimal must be greater than.
+ * @return This constraints instance for method chaining.
+ */
+ public DecimalConstraints greater(double number) {
+ addValidator(DecimalRangeValidator.greater(number, greaterMessage,
+ decimalDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #greater(double)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #greater(double)} constraint. Can be parameterized with
+ * the number which the parsed decimal must be greater than.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #greater(double)
+ */
+ public DecimalConstraints greaterMessage(String message) {
+ this.greaterMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed decimal is greater than or
+ * equal to the given number. Uses the current
+ * {@link #greaterEqualMessage(String) validation message}.
+ *
+ * @param number
+ * The number which the parsed decimal must be greater than or
+ * equal to.
+ * @return This constraints instance for method chaining.
+ */
+ public DecimalConstraints greaterEqual(double number) {
+ addValidator(DecimalRangeValidator.greaterEqual(number,
+ greaterEqualMessage, decimalDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #greaterEqual(double)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #greaterEqual(double)} constraint. Can be parameterized
+ * with the number which the parsed decimal must be greater than
+ * or equal to.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #greaterEqual(double)
+ */
+ public DecimalConstraints greaterEqualMessage(String message) {
+ this.greaterEqualMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed decimal is less than the given
+ * number. Uses the current {@link #lessMessage(String) validation message}.
+ *
+ * @param number
+ * The number which the parsed decimal must be less than.
+ * @return This constraints instance for method chaining.
+ */
+ public DecimalConstraints less(double number) {
+ addValidator(DecimalRangeValidator.less(number, lessMessage,
+ decimalDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #less(double)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the {@link #less(double)}
+ * constraint. Can be parameterized with the number which the
+ * parsed decimal must be less than.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #less(double)
+ */
+ public DecimalConstraints lessMessage(String message) {
+ this.lessMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed decimal is less than or equal
+ * to the given number. Uses the current {@link #lessEqualMessage(String)
+ * validation message}.
+ *
+ * @param number
+ * The number which the parsed decimal must be less than or equal
+ * to.
+ * @return This constraints instance for method chaining.
+ */
+ public DecimalConstraints lessEqual(double number) {
+ addValidator(DecimalRangeValidator.greaterEqual(number,
+ lessEqualMessage, decimalDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #lessEqual(double)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #lessEqual(double)} constraint. Can be parameterized
+ * with the number which the parsed decimal must be less than or
+ * equal to.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #lessEqual(double)
+ */
+ public DecimalConstraints lessEqualMessage(String message) {
+ this.lessEqualMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed decimal is within the given
+ * range. Uses the current {@link #rangeMessage(String) validation message}.
+ *
+ * @param min
+ * The lower bound of the range (inclusive).
+ * @param max
+ * The upper bound of the range (inclusive).
+ * @return This constraints instance for method chaining.
+ */
+ public DecimalConstraints range(double min, double max) {
+ addValidator(DecimalRangeValidator.range(min, max, rangeMessage,
+ decimalDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the
+ * {@link #range(double, double)} constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #range(double, double)} constraint. Can be
+ * parameterized with the min and max values of the range in
+ * which the parsed decimal must lie.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #range(double, double)
+ */
+ public DecimalConstraints rangeMessage(String message) {
+ this.rangeMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed decimal is positive. Uses the
+ * current {@link #positiveMessage(String) validation message}.
+ *
+ * @return This constraints instance for method chaining.
+ */
+ public DecimalConstraints positive() {
+ addValidator(DecimalRangeValidator.positive(positiveMessage,
+ decimalDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message for the {@link #positive()} constraint.
+ *
+ * @param message
+ * The validation message for the {@link #positive()} constraint.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #positive()
+ */
+ public DecimalConstraints positiveMessage(String message) {
+ this.positiveMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed decimal is non-negative. Uses
+ * the current {@link #nonNegativeMessage(String) validation message}.
+ *
+ * @return This constraints instance for method chaining.
+ */
+ public DecimalConstraints nonNegative() {
+ addValidator(DecimalRangeValidator.nonNegative(nonNegativeMessage,
+ decimalDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message for the {@link #nonNegative()} constraint.
+ *
+ * @param message
+ * The validation message for the {@link #nonNegative()}
+ * constraint.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #nonNegative()
+ */
+ public DecimalConstraints nonNegativeMessage(String message) {
+ this.nonNegativeMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed decimal's scale is not greater
+ * than the given one. Uses the current {@link #maxScaleMessage(String)
+ * validation message}.
+ *
+ * @param scale
+ * The maximum scale to enforce on the parsed decimal.
+ * @return This constraints instance for method chaining.
+ */
+ public DecimalConstraints maxScale(int scale) {
+ addValidator(DecimalScaleValidator.maxScale(scale, maxScaleMessage,
+ integerDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #maxScale(int)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the {@link #maxScale(int)}
+ * constraint. Can be parameterized with the maximum scale of the
+ * decimal.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #maxScale(int)
+ */
+ public DecimalConstraints maxScaleMessage(String message) {
+ this.maxScaleMessage = message;
+ return this;
+ }
+}
Index: src/org/eclipse/core/databinding/validation/constraint/DateConstraints.java
===================================================================
RCS file: src/org/eclipse/core/databinding/validation/constraint/DateConstraints.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/databinding/validation/constraint/DateConstraints.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,252 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.databinding.validation.constraint;
+
+import java.util.Date;
+
+import org.eclipse.core.internal.databinding.validation.DateRangeValidator;
+import org.eclipse.core.internal.databinding.validation.NonNullValidator;
+
+import com.ibm.icu.text.DateFormat;
+
+/**
+ * @since 1.4
+ */
+public final class DateConstraints extends Constraints {
+
+ private DateFormat displayFormat = DateFormat.getDateInstance();
+
+ private String requiredMessage = null;
+
+ private String afterMessage = null;
+
+ private String afterEqualMessage = null;
+
+ private String beforeMessage = null;
+
+ private String beforeEqualMessage = null;
+
+ private String rangeMessage = null;
+
+ /**
+ * Sets the format to use when formatting a date to be included in any of
+ * the validation messages.
+ *
+ * null
.
+ * Uses the current {@link #requiredMessage(String) validation message}.
+ *
+ * @return This constraints instance for method chaining.
+ */
+ public DateConstraints required() {
+ addValidator(new NonNullValidator(requiredMessage));
+ return this;
+ }
+
+ /**
+ * Sets the validation message for the {@link #required()} constraint.
+ *
+ * @param message
+ * The validation message for the {@link #required()} constraint.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #required()
+ */
+ public DateConstraints requiredMessage(String message) {
+ this.requiredMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed date is after the given date.
+ * Uses the current {@link #afterMessage(String) validation message}.
+ *
+ * @param date
+ * The date which the parsed date must be after.
+ * @return This constraints instance for method chaining.
+ *
+ * @see Date#after(Date)
+ */
+ public DateConstraints after(Date date) {
+ addValidator(DateRangeValidator
+ .after(date, afterMessage, displayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #after(Date)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the {@link #after(Date)}
+ * constraint. Can be parameterized with the date which the
+ * parsed date must be after.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #after(Date)
+ */
+ public DateConstraints afterMessage(String message) {
+ this.afterMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed date is after or on the given
+ * date. Uses the current {@link #afterEqualMessage(String) validation
+ * message}.
+ *
+ * @param date
+ * The date which the parsed date must be after or on.
+ * @return This constraints instance for method chaining.
+ *
+ * @see Date#after(Date)
+ * @see Date#equals(Object)
+ */
+ public DateConstraints afterEqual(Date date) {
+ addValidator(DateRangeValidator.afterEqual(date, afterEqualMessage,
+ displayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #afterEqual(Date)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #afterEqual(Date)} constraint. Can be parameterized
+ * with the date which the parsed date must be after or on.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #afterEqual(Date)
+ */
+ public DateConstraints afterEqualMessage(String message) {
+ this.afterEqualMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed date is before the given date.
+ * Uses the current {@link #beforeMessage(String) validation message}.
+ *
+ * @param date
+ * The date which the parsed date must be before
+ * @return This constraints instance for method chaining.
+ *
+ * @see Date#before(Date)
+ */
+ public DateConstraints before(Date date) {
+ addValidator(DateRangeValidator.before(date, beforeMessage,
+ displayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #before(Date)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the {@link #before(Date)}
+ * constraint. Can be parameterized with the date which the
+ * parsed date must be before.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #before(Date)
+ */
+ public DateConstraints beforeMessage(String message) {
+ this.beforeMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed date is before or on the given
+ * date. Uses the current {@link #beforeEqualMessage(String) validation
+ * message}.
+ *
+ * @param date
+ * The date which the parsed date must be before or on.
+ * @return This constraints instance for method chaining.
+ *
+ * @see Date#before(Date)
+ * @see Date#equals(Object)
+ */
+ public DateConstraints beforeEqual(Date date) {
+ addValidator(DateRangeValidator.beforeEqual(date, beforeEqualMessage,
+ displayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #beforeEqual(Date)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #beforeEqual(Date)} constraint. Can be parameterized
+ * with the date which the parsed date must be before or on.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #beforeEqual(Date)
+ */
+ public DateConstraints beforeEqualMessage(String message) {
+ this.beforeEqualMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed date is within the given range.
+ * Uses the current {@link #rangeMessage(String) validation message}.
+ *
+ * @param minDate
+ * The lower bound of the range (inclusive).
+ * @param maxDate
+ * The upper bound of the range (inclusive).
+ * @return This constraints instance for method chaining.
+ */
+ public DateConstraints range(Date minDate, Date maxDate) {
+ addValidator(DateRangeValidator.range(minDate, maxDate, rangeMessage,
+ displayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #range(Date, Date)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #range(Date, Date)} constraint. Can be parameterized
+ * with the min and max dates of the range in which the parsed
+ * date must lie.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #range(Date, Date)
+ */
+ public DateConstraints rangeMessage(String message) {
+ this.rangeMessage = message;
+ return this;
+ }
+}
Index: src/org/eclipse/core/internal/databinding/conversion/StringTrimConverter.java
===================================================================
RCS file: src/org/eclipse/core/internal/databinding/conversion/StringTrimConverter.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/internal/databinding/conversion/StringTrimConverter.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding.conversion;
+
+import org.eclipse.core.databinding.conversion.Converter;
+
+/**
+ * @since 1.4
+ */
+public class StringTrimConverter extends Converter {
+
+ private final boolean trimToNull;
+
+ /**
+ *
+ * @param trimToNull
+ */
+ public StringTrimConverter(boolean trimToNull) {
+ super(String.class, String.class);
+ this.trimToNull = trimToNull;
+ }
+
+ public Object convert(Object fromObject) {
+ String string = (String) fromObject;
+
+ if (string != null) {
+ string = string.trim();
+
+ if (trimToNull && string.length() == 0) {
+ string = null;
+ }
+ }
+
+ return string;
+ }
+}
Index: src/org/eclipse/core/databinding/editing/BooleanEditing.java
===================================================================
RCS file: src/org/eclipse/core/databinding/editing/BooleanEditing.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/databinding/editing/BooleanEditing.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.databinding.editing;
+
+import org.eclipse.core.databinding.validation.constraint.BooleanConstraints;
+import org.eclipse.core.databinding.validation.constraint.Constraints;
+import org.eclipse.core.databinding.validation.constraint.StringConstraints;
+import org.eclipse.core.internal.databinding.conversion.BooleanToStringConverter;
+import org.eclipse.core.internal.databinding.conversion.StringToBooleanConverter;
+import org.eclipse.core.internal.databinding.validation.StringToBooleanValidator;
+
+/**
+ * @since 1.4
+ */
+public final class BooleanEditing extends Editing {
+
+ private BooleanEditing(String[] trueValues, String[] falseValues,
+ String parseErrorMessage) {
+ StringToBooleanConverter targetConverter = new StringToBooleanConverter();
+ BooleanToStringConverter modelConverter = new BooleanToStringConverter(
+ Boolean.class);
+
+ StringToBooleanValidator targetValidator = new StringToBooleanValidator();
+ if (parseErrorMessage != null) {
+ targetValidator.setParseErrorMessage(parseErrorMessage);
+ }
+
+ if (trueValues != null && falseValues != null) {
+ targetValidator.setSourceStrings(trueValues, falseValues);
+ targetConverter.setSourceStrings(trueValues, falseValues);
+ modelConverter.setTargetStrings(trueValues[0], falseValues[0]);
+ }
+
+ setTargetConverter(targetConverter);
+ setModelConverter(modelConverter);
+ targetConstraints().addValidator(targetValidator);
+ }
+
+ /**
+ * Creates a new editing object which uses the default set of string
+ * representations for boolean values for parsing and displaying.
+ *
+ * @return The new editing object for the default set of string
+ * representations for boolean values.
+ */
+ public static BooleanEditing withDefaults() {
+ return new BooleanEditing(null, null, null);
+ }
+
+ /**
+ * Creates a new editing object which uses the default set of string
+ * representations for boolean values for parsing and displaying. Uses the
+ * specified custom validation message.
+ *
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to an boolean.
+ * @return The new editing object for the default set of string
+ * representations for boolean values.
+ */
+ public static BooleanEditing withDefaults(String parseErrorMessage) {
+ return new BooleanEditing(null, null, parseErrorMessage);
+ }
+
+ /**
+ * Creates a new editing object which uses the given set of string
+ * representations for boolean values for parsing and displaying.
+ *
+ * true
value.
+ * @param falseValues
+ * The set of strings representing a false
value.
+ * @return The new editing object for the given set of string
+ * representations for boolean values.
+ */
+ public static BooleanEditing forStringValues(String[] trueValues,
+ String[] falseValues) {
+ return new BooleanEditing(trueValues, falseValues, null);
+ }
+
+ /**
+ * Creates a new editing object which uses the given set of string
+ * representations for boolean values for parsing and displaying. Uses the
+ * specified custom validation message.
+ *
+ * true
value.
+ * @param falseValues
+ * The set of strings representing a false
value.
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to an boolean.
+ * @return The new editing object for the given set of string
+ * representations for boolean values.
+ */
+ public static BooleanEditing forStringValues(String[] trueValues,
+ String[] falseValues, String parseErrorMessage) {
+ return new BooleanEditing(trueValues, falseValues, parseErrorMessage);
+ }
+
+ /**
+ * Returns the target constraints to apply.
+ *
+ * null
+ * . Uses the current {@link #requiredMessage(String) validation message}.
+ *
+ * @return This constraints instance for method chaining.
+ */
+ public BooleanConstraints required() {
+ addValidator(new NonNullValidator(requiredMessage));
+ return this;
+ }
+
+ /**
+ * Sets the validation message for the {@link #required()} constraint.
+ *
+ * @param message
+ * The validation message for the {@link #required()} constraint.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #required()
+ */
+ public BooleanConstraints requiredMessage(String message) {
+ this.requiredMessage = message;
+ return this;
+ }
+}
Index: src/org/eclipse/core/databinding/validation/constraint/Constraints.java
===================================================================
RCS file: src/org/eclipse/core/databinding/validation/constraint/Constraints.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/databinding/validation/constraint/Constraints.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.databinding.validation.constraint;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.databinding.util.Policy;
+import org.eclipse.core.databinding.validation.IValidator;
+import org.eclipse.core.internal.databinding.BindingMessages;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * @since 1.4
+ */
+public class Constraints {
+
+ /**
+ * Constant denoting an aggregation strategy that merges multiple non-OK
+ * status objects in a {@link MultiStatus}. Returns an OK status result if
+ * all statuses from the set of validators to apply are an OK status.
+ * Returns a single status if there is only one non-OK status.
+ *
+ * @see #aggregationPolicy(int)
+ */
+ public static final int AGGREGATION_MERGED = 1;
+
+ /**
+ * Constant denoting an aggregation strategy that always returns the most
+ * severe status from the set of validators to apply. If there is more than
+ * one status at the same severity level, it picks the first one it
+ * encounters.
+ *
+ * @see #aggregationPolicy(int)
+ */
+ public static final int AGGREGATION_MAX_SEVERITY = 2;
+
+ // Will be initialized lazily.
+ private List validators = null;
+
+ private IValidator cachedValidator = null;
+
+ private int aggregationPolicy = AGGREGATION_MAX_SEVERITY;
+
+ /**
+ * Adds a custom validator to the set of constraints to apply.
+ *
+ * @param validator
+ * The custom validator to add to the set of constraints.
+ * @return This constraints instance for method chaining.
+ */
+ public final Constraints addValidator(IValidator validator) {
+ if (validators == null) {
+ validators = new ArrayList(2);
+ }
+ validators.add(validator);
+ cachedValidator = null;
+ return this;
+ }
+
+ /**
+ * Sets the aggregation policy to apply to the individual validations which
+ * constitute this set of constraints.
+ *
+ * @param policy
+ * The validation aggregation policy to set. Must be one of
+ * {@link #AGGREGATION_MERGED} or
+ * {@link #AGGREGATION_MAX_SEVERITY}.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #AGGREGATION_MERGED
+ * @see #AGGREGATION_MAX_SEVERITY
+ */
+ public final Constraints aggregationPolicy(int policy) {
+ this.aggregationPolicy = policy;
+ cachedValidator = null;
+ return this;
+ }
+
+ /**
+ * Creates a validator which enforces the current set of constraints.
+ *
+ * null
in case the set of
+ * constraints to apply is empty.
+ * null
.
+ */
+ public final IValidator createValidator() {
+ if (validators != null && !validators.isEmpty()) {
+ if (cachedValidator == null) {
+ if (validators.size() == 1) {
+ cachedValidator = (IValidator) validators.get(0);
+ } else {
+ IValidator[] currentValidators = (IValidator[]) validators
+ .toArray(new IValidator[validators.size()]);
+ cachedValidator = new ConstraintsValidator(
+ currentValidators, aggregationPolicy);
+ }
+ }
+ return cachedValidator;
+ }
+ return null;
+ }
+
+ private static final class ConstraintsValidator implements IValidator {
+
+ private final IValidator[] validators;
+
+ private final int aggregationPolicy;
+
+ public ConstraintsValidator(IValidator[] validators,
+ int aggregationPolicy) {
+ this.validators = validators;
+ this.aggregationPolicy = aggregationPolicy;
+ }
+
+ public IStatus validate(Object value) {
+ return (aggregationPolicy == AGGREGATION_MERGED) ? validateMerged(value)
+ : validateMaxSeverity(value);
+ }
+
+ private IStatus validateMerged(Object value) {
+ List statuses = new ArrayList();
+ for (int i = 0; i < validators.length; i++) {
+ IValidator validator = validators[i];
+ IStatus status = validator.validate(value);
+ if (!status.isOK()) {
+ statuses.add(status);
+ }
+ }
+
+ if (statuses.size() == 1) {
+ return (IStatus) statuses.get(0);
+ }
+
+ if (!statuses.isEmpty()) {
+ MultiStatus result = new MultiStatus(Policy.JFACE_DATABINDING,
+ 0, BindingMessages
+ .getString(BindingMessages.MULTIPLE_PROBLEMS),
+ null);
+ for (Iterator it = statuses.iterator(); it.hasNext();) {
+ IStatus status = (IStatus) it.next();
+ result.merge(status);
+ }
+ return result;
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ private IStatus validateMaxSeverity(Object value) {
+ int maxSeverity = IStatus.OK;
+ IStatus maxStatus = Status.OK_STATUS;
+ for (int i = 0; i < validators.length; i++) {
+ IValidator validator = validators[i];
+ IStatus status = validator.validate(value);
+ if (status.getSeverity() > maxSeverity) {
+ maxSeverity = status.getSeverity();
+ maxStatus = status;
+ }
+ }
+ return maxStatus;
+ }
+ }
+}
Index: src/org/eclipse/core/internal/databinding/validation/StringToBooleanValidator.java
===================================================================
RCS file: src/org/eclipse/core/internal/databinding/validation/StringToBooleanValidator.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/internal/databinding/validation/StringToBooleanValidator.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding.validation;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.databinding.validation.IValidator;
+import org.eclipse.core.databinding.validation.ValidationStatus;
+import org.eclipse.core.internal.databinding.BindingMessages;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * @since 1.4
+ */
+public class StringToBooleanValidator implements IValidator {
+
+ // TODO: Some of this code is duplicated from StringToBooleanPrimitiveConverter!
+ private static final String[] DEFAULT_TRUE_VALUES;
+ private static final String[] DEFAULT_FALSE_VALUES;
+
+ static {
+ String delimiter = BindingMessages.getString(BindingMessages.VALUE_DELIMITER);
+ String values = BindingMessages.getString(BindingMessages.TRUE_STRING_VALUES);
+ DEFAULT_TRUE_VALUES = valuesToSortedArray(delimiter, values);
+
+ values = BindingMessages.getString(BindingMessages.FALSE_STRING_VALUES);
+ DEFAULT_FALSE_VALUES = valuesToSortedArray(delimiter, values);
+ }
+
+ private String[] trueValues = DEFAULT_TRUE_VALUES;
+ private String[] falseValues = DEFAULT_FALSE_VALUES;
+
+ private String parseErrorMessage = BindingMessages.getString(BindingMessages.VALIDATE_INVALID_BOOLEAN_STRING);
+
+ /**
+ * Returns a sorted array with all values converted to upper case.
+ *
+ * @param delimiter
+ * @param values
+ * @return sorted array of values
+ */
+ private static String[] valuesToSortedArray(String delimiter, String values) {
+ List list = new LinkedList();
+ StringTokenizer tokenizer = new StringTokenizer(values, delimiter);
+ while (tokenizer.hasMoreTokens()) {
+ list.add(tokenizer.nextToken().toUpperCase());
+ }
+
+ String[] array = (String[]) list.toArray(new String[list.size()]);
+ Arrays.sort(array);
+
+ return array;
+ }
+
+ /**
+ * Sets the validation message to be used in case the source string does not
+ * represent a valid boolean value.
+ *
+ * @param message
+ * The validation message to be used in case the source string
+ * does not represent a valid boolean value.
+ */
+ public final void setParseErrorMessage(String message) {
+ this.parseErrorMessage = message;
+ }
+
+ /**
+ * Sets the string values which are considered to represent a
+ * true
and false
value, respectively.
+ *
+ * true
value.
+ * @param falseValues
+ * The set of strings representing a false
value.
+ */
+ public final void setSourceStrings(String[] trueValues, String[] falseValues) {
+ this.trueValues = new String[trueValues.length];
+ for (int i = 0; i < trueValues.length; i++) {
+ this.trueValues[i] = trueValues[i].toUpperCase();
+ }
+ Arrays.sort(this.trueValues); // for binary search
+
+ this.falseValues = new String[falseValues.length];
+ for (int i = 0; i < falseValues.length; i++) {
+ this.falseValues[i] = falseValues[i].toUpperCase();
+ }
+ Arrays.sort(this.falseValues); // for binary search
+ }
+
+ public IStatus validate(Object value) {
+ String source = (String) value;
+ if (source != null && source.length() != 0) {
+ source = source.toUpperCase();
+ if (Arrays.binarySearch(trueValues, source) < 0
+ && Arrays.binarySearch(falseValues, source) < 0) {
+ return ValidationStatus.error(parseErrorMessage);
+ }
+ }
+ return ValidationStatus.ok();
+ }
+}
Index: src/org/eclipse/core/databinding/validation/constraint/StringConstraints.java
===================================================================
RCS file: src/org/eclipse/core/databinding/validation/constraint/StringConstraints.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/databinding/validation/constraint/StringConstraints.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.databinding.validation.constraint;
+
+import java.util.regex.Pattern;
+
+import org.eclipse.core.internal.databinding.validation.NonEmptyStringValidator;
+import org.eclipse.core.internal.databinding.validation.NonNullValidator;
+import org.eclipse.core.internal.databinding.validation.StringLengthValidator;
+import org.eclipse.core.internal.databinding.validation.StringRegexValidator;
+
+import com.ibm.icu.text.NumberFormat;
+
+/**
+ * @since 1.4
+ */
+public final class StringConstraints extends Constraints {
+
+ private NumberFormat integerDisplayFormat = NumberFormat
+ .getIntegerInstance();
+
+ private String requiredMessage = null;
+
+ private String nonEmptyMessage = null;
+
+ private String minLengthMessage = null;
+
+ private String maxLengthMessage = null;
+
+ private String lengthRangeMessage = null;
+
+ private String matchesMessage = null;
+
+ /**
+ * Sets the format to use when formatting an integer to be included in any
+ * of the validation messages.
+ *
+ * null
. Uses the current {@link #requiredMessage(String)
+ * validation message}.
+ *
+ * @return This constraints instance for method chaining.
+ */
+ public StringConstraints required() {
+ addValidator(new NonNullValidator(requiredMessage));
+ return this;
+ }
+
+ /**
+ * Sets the validation message for the {@link #required()} constraint.
+ *
+ * @param message
+ * The validation message for the {@link #required()} constraint.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #required()
+ */
+ public StringConstraints requiredMessage(String message) {
+ this.requiredMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed integer is not empty. Uses the
+ * current {@link #nonEmptyMessage(String) validation message}.
+ *
+ * @return This constraints instance for method chaining.
+ */
+ public StringConstraints nonEmpty() {
+ addValidator(new NonEmptyStringValidator(nonEmptyMessage));
+ return this;
+ }
+
+ /**
+ * Sets the validation message for the {@link #nonEmpty()} constraint.
+ *
+ * @param message
+ * The validation message for the {@link #nonEmpty()} constraint.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #nonEmpty()
+ */
+ public StringConstraints nonEmptyMessage(String message) {
+ this.nonEmptyMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the input string has at least the
+ * specified amount of characters. Uses the current
+ * {@link #minLengthMessage(String) validation message}.
+ *
+ * @param minLength
+ * The minimal length to be enforced on the input string.
+ * @return This constraints instance for method chaining.
+ */
+ public StringConstraints minLength(int minLength) {
+ addValidator(StringLengthValidator.minLength(minLength,
+ minLengthMessage, integerDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #minLength(int)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the {@link #minLength(int)}
+ * constraint. Can be parameterized with the minimum string
+ * length.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #minLength(int)
+ */
+ public StringConstraints minLengthMessage(String message) {
+ this.minLengthMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the input string has not more than the
+ * specified amount of characters. Uses the current
+ * {@link #maxLengthMessage(String) validation message}.
+ *
+ * @param maxLength
+ * The maximum length to be enforced on the input string.
+ * @return This constraints instance for method chaining.
+ */
+ public StringConstraints maxLength(int maxLength) {
+ addValidator(StringLengthValidator.maxLength(maxLength,
+ maxLengthMessage, integerDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #maxLength(int)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the {@link #maxLength(int)}
+ * constraint. Can be parameterized with the maximum string
+ * length.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #maxLength(int)
+ */
+ public StringConstraints maxLengthMessage(String message) {
+ this.maxLengthMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the length of the input string is between
+ * the given bounds. Uses the current {@link #lengthRangeMessage(String)
+ * validation message}.
+ *
+ * @param minLength
+ * The minimal length to be enforced on the input string.
+ * @param maxLength
+ * The maximum length to be enforced on the input string.
+ * @return This constraints instance for method chaining.
+ */
+ public StringConstraints lengthRange(int minLength, int maxLength) {
+ addValidator(StringLengthValidator.lengthRange(minLength, maxLength,
+ lengthRangeMessage, integerDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the
+ * {@link #lengthRange(int, int)} constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #lengthRange(int, int)} constraint. Can be
+ * parameterized with the minimum and maximum string lengths.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #lengthRange(int, int)
+ */
+ public StringConstraints lengthRangeMessage(String message) {
+ this.lengthRangeMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the input string
+ * {@link Pattern#matches(String, CharSequence) matches} the given regular
+ * expression. Uses the current {@link #matchesMessage(String) validation
+ * message}.
+ *
+ * @param regex
+ * The regular expression which the input string must match.
+ * @return This constraints instance for method chaining.
+ *
+ * @see Pattern#matches(String, CharSequence)
+ */
+ public StringConstraints matches(String regex) {
+ addValidator(new StringRegexValidator(regex, matchesMessage));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #matches(String)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #matches(String)} constraint. Can be parameterized with
+ * the pattern string which the parsed integer must match.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #matches(String)
+ */
+ public StringConstraints matchesMessage(String message) {
+ this.matchesMessage = message;
+ return this;
+ }
+}
Index: src/org/eclipse/core/databinding/editing/Editing.java
===================================================================
RCS file: src/org/eclipse/core/databinding/editing/Editing.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/databinding/editing/Editing.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,1010 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.databinding.editing;
+
+import org.eclipse.core.databinding.Binding;
+import org.eclipse.core.databinding.DataBindingContext;
+import org.eclipse.core.databinding.UpdateListStrategy;
+import org.eclipse.core.databinding.UpdateSetStrategy;
+import org.eclipse.core.databinding.UpdateValueStrategy;
+import org.eclipse.core.databinding.conversion.IConverter;
+import org.eclipse.core.databinding.observable.list.IObservableList;
+import org.eclipse.core.databinding.observable.set.IObservableSet;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.core.databinding.validation.IValidator;
+import org.eclipse.core.databinding.validation.constraint.Constraints;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+
+/**
+ * @since 1.4
+ */
+public class Editing {
+
+ private Constraints targetConstraints;
+
+ private Constraints modelConstraints;
+
+ private Constraints beforeSetModelConstraints;
+
+ private IConverter targetConverter;
+
+ private IConverter modelConverter;
+
+ /**
+ * Default constructor which creates an unconfigured editing instance.
+ */
+ protected Editing() {
+ // empty editing instance
+ }
+
+ /**
+ * Creates an unconfigured editing instance.
+ *
+ * @return A new, unconfigured editing instance.
+ */
+ public static Editing create() {
+ return new Editing();
+ }
+
+ /**
+ * Creates an editing instance with the given target-to-model and
+ * model-to-target converters.
+ *
+ * @param t2mConverter
+ * The target-to-model converter to set. May be null
+ * .
+ * @param m2tConverter
+ * The model-to-target converter to set. May be null
+ * .
+ * @return A new editing instance with the given target-to-model and
+ * model-to-target converters.
+ */
+ public static Editing withConverters(IConverter t2mConverter,
+ IConverter m2tConverter) {
+ Editing editing = new Editing();
+ editing.setTargetConverter(t2mConverter);
+ editing.setModelConverter(m2tConverter);
+ return editing;
+ }
+
+ /**
+ * Returns the target constraints to apply.
+ *
+ * @return The target constraints to apply.
+ *
+ * @see #createTargetConstraints()
+ */
+ public final Constraints targetConstraints() {
+ if (targetConstraints == null) {
+ targetConstraints = createTargetConstraints();
+ }
+ return targetConstraints;
+ }
+
+ /**
+ * Returns the model constraints to apply.
+ *
+ * @return The model constraints to apply.
+ *
+ * @see #createModelConstraints()
+ */
+ public final Constraints modelConstraints() {
+ if (modelConstraints == null) {
+ modelConstraints = createModelConstraints();
+ }
+ return modelConstraints;
+ }
+
+ /**
+ * Returns the before-set model constraints to apply.
+ *
+ * @return The before-set model constraints to apply.
+ *
+ * @see #createBeforeSetModelConstraints()
+ */
+ public final Constraints beforeSetModelConstraints() {
+ if (beforeSetModelConstraints == null) {
+ beforeSetModelConstraints = createBeforeSetModelConstraints();
+ }
+ return beforeSetModelConstraints;
+ }
+
+ /**
+ * Creates the target constraints to apply.
+ *
+ *
+ *
+ *
+ * The conversion process will be aborted by returning null
+ * whenever any of the applied validators produces a {@link IStatus
+ * validation status} having {@link IStatus#getSeverity() severity}
+ * IStatus.ERROR
or IStatus.CANCEL
. During the
+ * conversion process, any validation status whose severity is different
+ * from IStatus.OK
will be {@link MultiStatus#merge(IStatus)
+ * aggregated} on the given validationStatus
.
+ *
null
in case the
+ * conversion has been aborted due to a validation error.
+ */
+ public final Object convertToModel(Object targetValue,
+ MultiStatus validationStatus) {
+ IValidator targetValidator = createValidator(targetConstraints);
+ if (!applyValidator(targetValidator, targetValue, validationStatus)) {
+ return null;
+ }
+
+ Object modelValue = (targetConverter != null) ? targetConverter
+ .convert(targetValue) : targetValue;
+
+ IValidator modelValidator = createValidator(modelConstraints);
+ if (!applyValidator(modelValidator, modelValue, validationStatus)) {
+ return null;
+ }
+
+ IValidator beforeSetModelValidator = createValidator(beforeSetModelConstraints);
+ if (!applyValidator(beforeSetModelValidator, modelValue,
+ validationStatus)) {
+ return null;
+ }
+
+ return modelValue;
+ }
+
+ /**
+ * {@link #setModelConverter(IConverter) Converts} a model value to a target
+ * value.
+ *
+ * @param modelValue
+ * The model value to be converted to a target value.
+ * @return The converted target value.
+ */
+ public final Object convertToTarget(Object modelValue) {
+ return (modelConverter != null) ? modelConverter.convert(modelValue)
+ : modelValue;
+ }
+
+ /**
+ * Creates a binding between a target and model observable value on the
+ * given binding context by creating new update strategies which will be
+ * both configured with the state of this editing object before passing them
+ * to the binding.
+ *
+ * + * The target-to-model and model-to-target update strategies for the binding + * will be created by the methods {@link #createT2MValueStrategy()} and + * {@link #createM2TValueStrategy()}, respectively. + *
+ * + * @param dbc + * The binding context on which to create the value binding. + * @param targetObservableValue + * The target observable value of the binding. + * @param modelObservableValue + * The model observable value of the binding. + * @return The new value binding. + * + * @see #createT2MValueStrategy() + * @see #createM2TValueStrategy() + * @see DataBindingContext#bindValue(IObservableValue, IObservableValue, + * UpdateValueStrategy, UpdateValueStrategy) + */ + public final Binding bindValue(DataBindingContext dbc, + IObservableValue targetObservableValue, + IObservableValue modelObservableValue) { + return dbc.bindValue(targetObservableValue, modelObservableValue, + createT2MValueStrategy(), createM2TValueStrategy()); + } + + /** + * Creates a binding between a target and model observable value on the + * given binding context by creating new update strategies with the provided + * update policies which will be both configured with the state of this + * editing object before passing them to the binding. + * + * @param dbc + * The binding context on which to create the value binding. + * @param targetObservableValue + * The target observable value of the binding. + * @param modelObservableValue + * The model observable value of the binding. + * @param t2mUpdatePolicy + * The update policy for the target-to-model + * {@link UpdateValueStrategy} which is + * {@link #createT2MValueStrategy(int) created} and passed to the + * new binding. + * @param m2tUpdatePolicy + * The update policy for the model-to-target + * {@link UpdateValueStrategy} which is + * {@link #createM2TValueStrategy(int) created} and passed to the + * new binding. + * @return The new value binding. + * + * @see #createT2MValueStrategy(int) + * @see #createM2TValueStrategy(int) + * @see DataBindingContext#bindValue(IObservableValue, IObservableValue, + * UpdateValueStrategy, UpdateValueStrategy) + */ + public final Binding bindValue(DataBindingContext dbc, + IObservableValue targetObservableValue, + IObservableValue modelObservableValue, int t2mUpdatePolicy, + int m2tUpdatePolicy) { + return dbc.bindValue(targetObservableValue, modelObservableValue, + createT2MValueStrategy(t2mUpdatePolicy), + createM2TValueStrategy(m2tUpdatePolicy)); + } + + /** + * Creates a binding between a target and model observable value on the + * given binding context by using the provided update strategies which will + * be both configured with the state of this editing object before passing + * them to the binding. + * + * @param dbc + * The binding context on which to create the value binding. + * @param targetObservableValue + * The target observable value of the binding. + * @param modelObservableValue + * The model observable value of the binding. + * @param t2mUpdateStrategy + * The target-to-model {@link UpdateValueStrategy} of the binding + * to be {@link #applyToT2MValueStrategy(UpdateValueStrategy) + * configured} with the state of this editing object before + * passing it to the binding. + * @param m2tUpdateStrategy + * The model-to-target {@link UpdateValueStrategy} of the binding + * to be {@link #applyToM2TValueStrategy(UpdateValueStrategy) + * configured} with the state of this editing object before + * passing it to the binding. + * @return The new value binding. + * + * @see #applyToT2MValueStrategy(UpdateValueStrategy) + * @see #applyToM2TValueStrategy(UpdateValueStrategy) + * @see DataBindingContext#bindValue(IObservableValue, IObservableValue, + * UpdateValueStrategy, UpdateValueStrategy) + */ + public final Binding bindValue(DataBindingContext dbc, + IObservableValue targetObservableValue, + IObservableValue modelObservableValue, + UpdateValueStrategy t2mUpdateStrategy, + UpdateValueStrategy m2tUpdateStrategy) { + return dbc.bindValue(targetObservableValue, modelObservableValue, + applyToT2MValueStrategy(t2mUpdateStrategy), + applyToM2TValueStrategy(m2tUpdateStrategy)); + } + + /** + * Creates a binding between a target and model observable list on the given + * binding context by creating new update strategies which will be both + * configured with the state of this editing object before passing them to + * the binding. + * + *+ * The target-to-model and model-to-target update strategies for the binding + * will be created by the methods {@link #createT2MListStrategy()} and + * {@link #createM2TListStrategy()}, respectively. + *
+ * + * @param dbc + * The binding context on which to create the list binding. + * @param targetObservableList + * The target observable list of the binding. + * @param modelObservableList + * The model observable list of the binding. + * @return The new list binding. + * + * @see #createT2MListStrategy() + * @see #createM2TListStrategy() + * @see DataBindingContext#bindList(IObservableList, IObservableList, + * UpdateListStrategy, UpdateListStrategy) + */ + public final Binding bindList(DataBindingContext dbc, + IObservableList targetObservableList, + IObservableList modelObservableList) { + return dbc.bindList(targetObservableList, modelObservableList, + createT2MListStrategy(), createM2TListStrategy()); + } + + /** + * Creates a binding between a target and model observable list on the given + * binding context by creating new update strategies with the provided + * update policies which will be both configured with the state of this + * editing object before passing them to the binding. + * + * @param dbc + * The binding context on which to create the list binding. + * @param targetObservableList + * The target observable list of the binding. + * @param modelObservableList + * The model observable list of the binding. + * @param t2mUpdatePolicy + * The update policy for the target-to-model + * {@link UpdateListStrategy} which is + * {@link #createT2MListStrategy(int) created} and passed to the + * new binding. + * @param m2tUpdatePolicy + * The update policy for the model-to-target + * {@link UpdateListStrategy} which is + * {@link #createM2TListStrategy(int) created} and passed to the + * new binding. + * @return The new list binding. + * + * @see #createT2MListStrategy(int) + * @see #createM2TListStrategy(int) + * @see DataBindingContext#bindList(IObservableList, IObservableList, + * UpdateListStrategy, UpdateListStrategy) + */ + public final Binding bindList(DataBindingContext dbc, + IObservableList targetObservableList, + IObservableList modelObservableList, int t2mUpdatePolicy, + int m2tUpdatePolicy) { + return dbc.bindList(targetObservableList, modelObservableList, + createT2MListStrategy(t2mUpdatePolicy), + createM2TListStrategy(m2tUpdatePolicy)); + } + + /** + * Creates a binding between a target and model observable list on the given + * binding context by using the provided update strategies which will be + * both configured with the state of this editing object before passing them + * to the binding. + * + * @param dbc + * The binding context on which to create the list binding. + * @param targetObservableList + * The target observable list of the binding. + * @param modelObservableList + * The model observable list of the binding. + * @param t2mUpdateStrategy + * The target-to-model {@link UpdateListStrategy} of the binding + * to be {@link #applyToT2MListStrategy(UpdateListStrategy) + * configured} with the state of this editing object before + * passing it to the binding. + * @param m2tUpdateStrategy + * The model-to-target {@link UpdateListStrategy} of the binding + * to be {@link #applyToM2TListStrategy(UpdateListStrategy) + * configured} with the state of this editing object before + * passing it to the binding. + * @return The new list binding. + * + * @see #applyToT2MListStrategy(UpdateListStrategy) + * @see #applyToM2TListStrategy(UpdateListStrategy) + * @see DataBindingContext#bindList(IObservableList, IObservableList, + * UpdateListStrategy, UpdateListStrategy) + */ + public final Binding bindList(DataBindingContext dbc, + IObservableList targetObservableList, + IObservableList modelObservableList, + UpdateListStrategy t2mUpdateStrategy, + UpdateListStrategy m2tUpdateStrategy) { + return dbc.bindList(targetObservableList, modelObservableList, + applyToT2MListStrategy(t2mUpdateStrategy), + applyToM2TListStrategy(m2tUpdateStrategy)); + } + + /** + * Creates a binding between a target and model observable set on the given + * binding context by creating new update strategies which will be both + * configured with the state of this editing object before passing them to + * the binding. + * + *+ * The target-to-model and model-to-target update strategies for the binding + * will be created by the methods {@link #createT2MSetStrategy()} and + * {@link #createM2TSetStrategy()}, respectively. + *
+ * + * @param dbc + * The binding context on which to create the set binding. + * @param targetObservableSet + * The target observable set of the binding. + * @param modelObservableSet + * The model observable set of the binding. + * @return The new set binding. + * + * @see #createT2MSetStrategy() + * @see #createM2TSetStrategy() + * @see DataBindingContext#bindSet(IObservableSet, IObservableSet, + * UpdateSetStrategy, UpdateSetStrategy) + */ + public final Binding bindSet(DataBindingContext dbc, + IObservableSet targetObservableSet, + IObservableSet modelObservableSet) { + return dbc.bindSet(targetObservableSet, modelObservableSet, + createT2MSetStrategy(), createM2TSetStrategy()); + } + + /** + * Creates a binding between a target and model observable set on the given + * binding context by creating new update strategies with the provided + * update policies which will be both configured with the state of this + * editing object before passing them to the binding. + * + * @param dbc + * The binding context on which to create the set binding. + * @param targetObservableSet + * The target observable set of the binding. + * @param modelObservableSet + * The model observable set of the binding. + * @param t2mUpdatePolicy + * The update policy for the target-to-model + * {@link UpdateSetStrategy} which is + * {@link #createT2MSetStrategy(int) created} and passed to the + * new binding. + * @param m2tUpdatePolicy + * The update policy for the model-to-target + * {@link UpdateSetStrategy} which is + * {@link #createM2TSetStrategy(int) created} and passed to the + * new binding. + * @return The new set binding. + * + * @see #createT2MSetStrategy(int) + * @see #createM2TSetStrategy(int) + * @see DataBindingContext#bindSet(IObservableSet, IObservableSet, + * UpdateSetStrategy, UpdateSetStrategy) + */ + public final Binding bindSet(DataBindingContext dbc, + IObservableSet targetObservableSet, + IObservableSet modelObservableSet, int t2mUpdatePolicy, + int m2tUpdatePolicy) { + return dbc.bindSet(targetObservableSet, modelObservableSet, + createT2MSetStrategy(t2mUpdatePolicy), + createM2TSetStrategy(m2tUpdatePolicy)); + } + + /** + * Creates a binding between a target and model observable set on the given + * binding context by using the provided update strategies which will be + * both configured with the state of this editing object before passing them + * to the binding. + * + * @param dbc + * The binding context on which to create the set binding. + * @param targetObservableSet + * The target observable set of the binding. + * @param modelObservableSet + * The model observable set of the binding. + * @param t2mUpdateStrategy + * The target-to-model {@link UpdateSetStrategy} of the binding + * to be {@link #applyToT2MSetStrategy(UpdateSetStrategy) + * configured} with the state of this editing object before + * passing it to the binding. + * @param m2tUpdateStrategy + * The model-to-target {@link UpdateSetStrategy} of the binding + * to be {@link #applyToM2TSetStrategy(UpdateSetStrategy) + * configured} with the state of this editing object before + * passing it to the binding. + * @return The new set binding. + * + * @see #applyToT2MSetStrategy(UpdateSetStrategy) + * @see #applyToM2TSetStrategy(UpdateSetStrategy) + * @see DataBindingContext#bindSet(IObservableSet, IObservableSet, + * UpdateSetStrategy, UpdateSetStrategy) + */ + public final Binding bindSet(DataBindingContext dbc, + IObservableSet targetObservableSet, + IObservableSet modelObservableSet, + UpdateSetStrategy t2mUpdateStrategy, + UpdateSetStrategy m2tUpdateStrategy) { + return dbc.bindSet(targetObservableSet, modelObservableSet, + applyToT2MSetStrategy(t2mUpdateStrategy), + applyToM2TSetStrategy(m2tUpdateStrategy)); + } + + private static IValidator createValidator(Constraints constraints) { + return constraints != null ? constraints.createValidator() : null; + } + + private static boolean applyValidator(IValidator validator, Object value, + MultiStatus aggregateStatus) { + if (validator != null) { + IStatus validationStatus = validator.validate(value); + if (!validationStatus.isOK()) { + aggregateStatus.merge(validationStatus); + } + return isValid(validationStatus); + } + return true; + } + + private static boolean isValid(IStatus status) { + return status.isOK() || status.matches(IStatus.INFO | IStatus.WARNING); + } +} Index: src/org/eclipse/core/databinding/editing/IntegerEditing.java =================================================================== RCS file: src/org/eclipse/core/databinding/editing/IntegerEditing.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/databinding/editing/IntegerEditing.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,571 @@ +/******************************************************************************* + * Copyright (c) 2009 Ovidio Mallo 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: + * Ovidio Mallo - initial API and implementation (bug 183055) + ******************************************************************************/ + +package org.eclipse.core.databinding.editing; + +import org.eclipse.core.databinding.conversion.NumberToStringConverter; +import org.eclipse.core.databinding.conversion.StringToNumberConverter; +import org.eclipse.core.databinding.validation.constraint.Constraints; +import org.eclipse.core.databinding.validation.constraint.IntegerConstraints; +import org.eclipse.core.databinding.validation.constraint.StringConstraints; +import org.eclipse.core.internal.databinding.validation.AbstractStringToNumberValidator; +import org.eclipse.core.internal.databinding.validation.StringToByteValidator; +import org.eclipse.core.internal.databinding.validation.StringToIntegerValidator; +import org.eclipse.core.internal.databinding.validation.StringToLongValidator; +import org.eclipse.core.internal.databinding.validation.StringToShortValidator; + +import com.ibm.icu.text.NumberFormat; + +/** + * @since 1.4 + */ +public final class IntegerEditing extends Editing { + + private final NumberFormat displayFormat; + + private IntegerEditing(NumberFormat format, String parseErrorMessage, + String outOfRangeMessage, Class integerType) { + this.displayFormat = format; + + final StringToNumberConverter targetConverter; + final NumberToStringConverter modelConverter; + final AbstractStringToNumberValidator targetValidator; + if (Long.class.equals(integerType)) { + targetConverter = StringToNumberConverter.toLong(format, false); + modelConverter = NumberToStringConverter.fromLong(format, false); + targetValidator = new StringToLongValidator(targetConverter); + } else if (Integer.class.equals(integerType)) { + targetConverter = StringToNumberConverter.toInteger(format, false); + modelConverter = NumberToStringConverter.fromInteger(format, false); + targetValidator = new StringToIntegerValidator(targetConverter); + } else if (Short.class.equals(integerType)) { + targetConverter = StringToNumberConverter.toShort(format, false); + modelConverter = NumberToStringConverter.fromShort(format, false); + targetValidator = new StringToShortValidator(targetConverter); + } else if (Byte.class.equals(integerType)) { + targetConverter = StringToNumberConverter.toByte(format, false); + modelConverter = NumberToStringConverter.fromByte(format, false); + targetValidator = new StringToByteValidator(targetConverter); + } else { + throw new IllegalArgumentException( + "Unsupported integer type: " + integerType); //$NON-NLS-1$ + } + + if (parseErrorMessage != null) { + targetValidator.setParseErrorMessage(parseErrorMessage); + } + if (outOfRangeMessage != null) { + targetValidator.setOutOfRangeMessage(outOfRangeMessage); + } + + targetConstraints().addValidator(targetValidator); + setTargetConverter(targetConverter); + setModelConverter(modelConverter); + } + + /** + * Creates a new editing object for {@link Long}s which defaults the + * validations and conversions used for editing based on the platform's + * locale. Uses the default validation messages. + * + * @return The new editing object using the default validations and + * conversions for editing. + * + * @see NumberFormat#getIntegerInstance() + */ + public static IntegerEditing withLongDefaults() { + return withLongDefaults(null, null); + } + + /** + * Creates a new editing object for {@link Long}s which defaults the + * validations and conversions used for editing based on the platform's + * locale. Uses the specified custom validation messages. + * + * @param parseErrorMessage + * The validation message issued in case the input string cannot + * be parsed to an integer. + * @param outOfRangeMessage + * The validation message issued in case the input string + * represents an integer whose value is out of range. Can be + * parameterized by theLong.MIN_VALUE
and
+ * Long.MAX_VALUE
values.
+ * @return The new editing object using the default validations and
+ * conversions for editing.
+ *
+ * @see NumberFormat#getIntegerInstance()
+ */
+ public static IntegerEditing withLongDefaults(String parseErrorMessage,
+ String outOfRangeMessage) {
+ return new IntegerEditing(NumberFormat.getIntegerInstance(),
+ parseErrorMessage, outOfRangeMessage, Long.class);
+ }
+
+ /**
+ * Creates a new editing object for {@link Long}s whose validations and
+ * conversions used for editing are based on the given integer format. Uses
+ * the default validation messages.
+ *
+ * @param format
+ * The integer format defining the validations and conversions
+ * used for editing.
+ * @return The new editing object configured by the given integer format.
+ */
+ public static IntegerEditing forLongFormat(NumberFormat format) {
+ return forLongFormat(format, null, null);
+ }
+
+ /**
+ * Creates a new editing object for {@link Long}s whose validations and
+ * conversions used for editing are based on the given integer format. Uses
+ * the specified custom validation messages.
+ *
+ * @param format
+ * The integer format defining the validations and conversions
+ * used for editing.
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to an integer.
+ * @param outOfRangeMessage
+ * The validation message issued in case the input string
+ * represents an integer whose value is out of range. Can be
+ * parameterized by the Long.MIN_VALUE
and
+ * Long.MAX_VALUE
values.
+ * @return The new editing object configured by the given integer format.
+ */
+ public static IntegerEditing forLongFormat(NumberFormat format,
+ String parseErrorMessage, String outOfRangeMessage) {
+ return new IntegerEditing(format, parseErrorMessage, outOfRangeMessage,
+ Long.class);
+ }
+
+ /**
+ * Creates a new editing object for {@link Integer}s which defaults the
+ * validations and conversions used for editing based on the platform's
+ * locale. Uses the default validation messages.
+ *
+ * @return The new editing object using the default validations and
+ * conversions for editing.
+ *
+ * @see NumberFormat#getIntegerInstance()
+ */
+ public static IntegerEditing withIntegerDefaults() {
+ return withIntegerDefaults(null, null);
+ }
+
+ /**
+ * Creates a new editing object for {@link Integer}s which defaults the
+ * validations and conversions used for editing based on the platform's
+ * locale. Uses the specified custom validation messages.
+ *
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to an integer.
+ * @param outOfRangeMessage
+ * The validation message issued in case the input string
+ * represents an integer whose value is out of range. Can be
+ * parameterized by the Integer.MIN_VALUE
and
+ * Integer.MAX_VALUE
values.
+ * @return The new editing object using the default validations and
+ * conversions for editing.
+ *
+ * @see NumberFormat#getIntegerInstance()
+ */
+ public static IntegerEditing withIntegerDefaults(String parseErrorMessage,
+ String outOfRangeMessage) {
+ return new IntegerEditing(NumberFormat.getIntegerInstance(),
+ parseErrorMessage, outOfRangeMessage, Integer.class);
+ }
+
+ /**
+ * Creates a new editing object for {@link Integer}s whose validations and
+ * conversions used for editing are based on the given integer format. Uses
+ * the default validation messages.
+ *
+ * @param format
+ * The integer format defining the validations and conversions
+ * used for editing.
+ * @return The new editing object configured by the given integer format.
+ */
+ public static IntegerEditing forIntegerFormat(NumberFormat format) {
+ return forIntegerFormat(format, null, null);
+ }
+
+ /**
+ * Creates a new editing object for {@link Integer}s whose validations and
+ * conversions used for editing are based on the given integer format. Uses
+ * the specified custom validation messages.
+ *
+ * @param format
+ * The integer format defining the validations and conversions
+ * used for editing.
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to an integer.
+ * @param outOfRangeMessage
+ * The validation message issued in case the input string
+ * represents an integer whose value is out of range. Can be
+ * parameterized by the Integer.MIN_VALUE
and
+ * Integer.MAX_VALUE
values.
+ * @return The new editing object configured by the given integer format.
+ */
+ public static IntegerEditing forIntegerFormat(NumberFormat format,
+ String parseErrorMessage, String outOfRangeMessage) {
+ return new IntegerEditing(format, parseErrorMessage, outOfRangeMessage,
+ Integer.class);
+ }
+
+ /**
+ * Creates a new editing object for {@link Short}s which defaults the
+ * validations and conversions used for editing based on the platform's
+ * locale. Uses the default validation messages.
+ *
+ * @return The new editing object using the default validations and
+ * conversions for editing.
+ *
+ * @see NumberFormat#getIntegerInstance()
+ */
+ public static IntegerEditing withShortDefaults() {
+ return withShortDefaults(null, null);
+ }
+
+ /**
+ * Creates a new editing object for {@link Short}s which defaults the
+ * validations and conversions used for editing based on the platform's
+ * locale. Uses the specified custom validation messages.
+ *
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to an integer.
+ * @param outOfRangeMessage
+ * The validation message issued in case the input string
+ * represents an integer whose value is out of range. Can be
+ * parameterized by the Short.MIN_VALUE
and
+ * Short.MAX_VALUE
values.
+ * @return The new editing object using the default validations and
+ * conversions for editing.
+ *
+ * @see NumberFormat#getIntegerInstance()
+ */
+ public static IntegerEditing withShortDefaults(String parseErrorMessage,
+ String outOfRangeMessage) {
+ return new IntegerEditing(NumberFormat.getIntegerInstance(),
+ parseErrorMessage, outOfRangeMessage, Short.class);
+ }
+
+ /**
+ * Creates a new editing object for {@link Short}s whose validations and
+ * conversions used for editing are based on the given integer format. Uses
+ * the default validation messages.
+ *
+ * @param format
+ * The integer format defining the validations and conversions
+ * used for editing.
+ * @return The new editing object configured by the given integer format.
+ */
+ public static IntegerEditing forShortFormat(NumberFormat format) {
+ return forShortFormat(format, null, null);
+ }
+
+ /**
+ * Creates a new editing object for {@link Short}s whose validations and
+ * conversions used for editing are based on the given integer format. Uses
+ * the specified custom validation messages.
+ *
+ * @param format
+ * The integer format defining the validations and conversions
+ * used for editing.
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to an integer.
+ * @param outOfRangeMessage
+ * The validation message issued in case the input string
+ * represents an integer whose value is out of range. Can be
+ * parameterized by the Short.MIN_VALUE
and
+ * Short.MAX_VALUE
values.
+ * @return The new editing object configured by the given integer format.
+ */
+ public static IntegerEditing forShortFormat(NumberFormat format,
+ String parseErrorMessage, String outOfRangeMessage) {
+ return new IntegerEditing(format, parseErrorMessage, outOfRangeMessage,
+ Short.class);
+ }
+
+ /**
+ * Creates a new editing object for {@link Byte}s which defaults the
+ * validations and conversions used for editing based on the platform's
+ * locale. Uses the default validation messages.
+ *
+ * @return The new editing object using the default validations and
+ * conversions for editing.
+ *
+ * @see NumberFormat#getIntegerInstance()
+ */
+ public static IntegerEditing withByteDefaults() {
+ return withByteDefaults(null, null);
+ }
+
+ /**
+ * Creates a new editing object for {@link Byte}s which defaults the
+ * validations and conversions used for editing based on the platform's
+ * locale. Uses the specified custom validation messages.
+ *
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to an integer.
+ * @param outOfRangeMessage
+ * The validation message issued in case the input string
+ * represents an integer whose value is out of range. Can be
+ * parameterized by the Byte.MIN_VALUE
and
+ * Byte.MAX_VALUE
values.
+ * @return The new editing object using the default validations and
+ * conversions for editing.
+ *
+ * @see NumberFormat#getIntegerInstance()
+ */
+ public static IntegerEditing withByteDefaults(String parseErrorMessage,
+ String outOfRangeMessage) {
+ return new IntegerEditing(NumberFormat.getIntegerInstance(),
+ parseErrorMessage, outOfRangeMessage, Byte.class);
+ }
+
+ /**
+ * Creates a new editing object for {@link Byte}s whose validations and
+ * conversions used for editing are based on the given integer format. Uses
+ * the default validation messages.
+ *
+ * @param format
+ * The integer format defining the validations and conversions
+ * used for editing.
+ * @return The new editing object configured by the given integer format.
+ */
+ public static IntegerEditing forByteFormat(NumberFormat format) {
+ return forByteFormat(format, null, null);
+ }
+
+ /**
+ * Creates a new editing object for {@link Byte}s whose validations and
+ * conversions used for editing are based on the given integer format. Uses
+ * the specified custom validation messages.
+ *
+ * @param format
+ * The integer format defining the validations and conversions
+ * used for editing.
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to an integer.
+ * @param outOfRangeMessage
+ * The validation message issued in case the input string
+ * represents an integer whose value is out of range. Can be
+ * parameterized by the Byte.MIN_VALUE
and
+ * Byte.MAX_VALUE
values.
+ * @return The new editing object configured by the given integer format.
+ */
+ public static IntegerEditing forByteFormat(NumberFormat format,
+ String parseErrorMessage, String outOfRangeMessage) {
+ return new IntegerEditing(format, parseErrorMessage, outOfRangeMessage,
+ Byte.class);
+ }
+
+ /**
+ * Returns the target constraints to apply.
+ *
+ * + * This method provides a typesafe access to the {@link StringConstraints + * string target constraints} of this editing object and is equivalent to + * {@code (StringConstraints) targetConstraints()}. + *
+ * + * @return The target constraints to apply. + * + * @see #targetConstraints() + * @see StringConstraints + */ + public StringConstraints targetStringConstraints() { + return (StringConstraints) targetConstraints(); + } + + /** + * Returns the model constraints to apply. + * + *+ * This method provides a typesafe access to the {@link IntegerConstraints + * integer model constraints} of this editing object and is equivalent to + * {@code (IntegerConstraints) modelConstraints()}. + *
+ * + * @return The target constraints to apply. + * + * @see #modelConstraints() + * @see IntegerConstraints + */ + public IntegerConstraints modelIntegerConstraints() { + return (IntegerConstraints) modelConstraints(); + } + + /** + * Returns the before-set model constraints to apply. + * + *+ * This method provides a typesafe access to the {@link IntegerConstraints + * integer before-set model constraints} of this editing object and is + * equivalent to {@code (IntegerConstraints) beforeSetModelConstraints()}. + *
+ * + * @return The target constraints to apply. + * + * @see #beforeSetModelConstraints() + * @see IntegerConstraints + */ + public IntegerConstraints beforeSetModelIntegerConstraints() { + return (IntegerConstraints) beforeSetModelConstraints(); + } + + protected Constraints createTargetConstraints() { + return new StringConstraints(); + } + + protected Constraints createModelConstraints() { + return new IntegerConstraints().integerDisplayFormat(displayFormat); + } + + protected Constraints createBeforeSetModelConstraints() { + return new IntegerConstraints().integerDisplayFormat(displayFormat); + } + + /** + * Convenience method which adds a {@link IntegerConstraints#required() + * required constraint} to the set of {@link #modelIntegerConstraints()}. + * + * @return This editing instance for method chaining. + * + * @see IntegerConstraints#required() + * @see #modelIntegerConstraints() + */ + public IntegerEditing required() { + modelIntegerConstraints().required(); + return this; + } + + /** + * Convenience method which adds a {@link IntegerConstraints#greater(long) + * greater constraint} to the set of {@link #modelIntegerConstraints()}. + * + * @param number + * The number of the greater constraint. + * @return This editing instance for method chaining. + * + * @see IntegerConstraints#greater(long) + * @see #modelIntegerConstraints() + */ + public IntegerEditing greater(long number) { + modelIntegerConstraints().greater(number); + return this; + } + + /** + * Convenience method which adds a + * {@link IntegerConstraints#greaterEqual(long) greater-equal constraint} to + * the set of {@link #modelIntegerConstraints()}. + * + * @param number + * The number of the greater-equal constraint. + * @return This editing instance for method chaining. + * + * @see IntegerConstraints#greaterEqual(long) + * @see #modelIntegerConstraints() + */ + public IntegerEditing greaterEqual(long number) { + modelIntegerConstraints().greaterEqual(number); + return this; + } + + /** + * Convenience method which adds a {@link IntegerConstraints#less(long) less + * constraint} to the set of {@link #modelIntegerConstraints()}. + * + * @param number + * The number of the less constraint. + * @return This editing instance for method chaining. + * + * @see IntegerConstraints#less(long) + * @see #modelIntegerConstraints() + */ + public IntegerEditing less(long number) { + modelIntegerConstraints().less(number); + return this; + } + + /** + * Convenience method which adds a + * {@link IntegerConstraints#lessEqual(long) less-equal constraint} to the + * set of {@link #modelIntegerConstraints()}. + * + * @param number + * The number of the less-equal constraint. + * @return This editing instance for method chaining. + * + * @see IntegerConstraints#lessEqual(long) + * @see #modelIntegerConstraints() + */ + public IntegerEditing lessEqual(long number) { + modelIntegerConstraints().lessEqual(number); + return this; + } + + /** + * Convenience method which adds a + * {@link IntegerConstraints#range(long, long) range constraint} to the set + * of {@link #modelIntegerConstraints()}. + * + * @param min + * The min number of the range constraint. + * @param max + * The max number of the range constraint. + * @return This editing instance for method chaining. + * + * @see IntegerConstraints#range(long, long) + * @see #modelIntegerConstraints() + */ + public IntegerEditing range(long min, long max) { + modelIntegerConstraints().range(min, max); + return this; + } + + /** + * Convenience method which adds a {@link IntegerConstraints#positive() + * positive constraint} to the set of {@link #modelIntegerConstraints()}. + * + * @return This editing instance for method chaining. + * + * @see IntegerConstraints#positive() + * @see #modelIntegerConstraints() + */ + public IntegerEditing positive() { + modelIntegerConstraints().positive(); + return this; + } + + /** + * Convenience method which adds a {@link IntegerConstraints#nonNegative() + * non-negative constraint} to the set of {@link #modelIntegerConstraints()} + * . + * + * @return This editing instance for method chaining. + * + * @see IntegerConstraints#nonNegative() + * @see #modelIntegerConstraints() + */ + public IntegerEditing nonNegative() { + modelIntegerConstraints().nonNegative(); + return this; + } +} Index: src/org/eclipse/core/internal/databinding/validation/DecimalScaleValidator.java =================================================================== RCS file: src/org/eclipse/core/internal/databinding/validation/DecimalScaleValidator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/databinding/validation/DecimalScaleValidator.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2009 Ovidio Mallo 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: + * Ovidio Mallo - initial API and implementation (bug 183055) + ******************************************************************************/ + +package org.eclipse.core.internal.databinding.validation; + +import java.text.MessageFormat; + +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.internal.databinding.BindingMessages; +import org.eclipse.core.runtime.IStatus; + +import com.ibm.icu.math.BigDecimal; +import com.ibm.icu.text.NumberFormat; + +/** + * @since 1.4 + */ +public class DecimalScaleValidator implements IValidator { + + private static final String MAX_SCALE_VALIDATION_MESSAGE = BindingMessages + .getString(BindingMessages.VALIDATE_DECIMAL_MAX_SCALE); + + private final int maxScale; + + private final String validationMessage; + + private String formattedValidationMessage; + + private final NumberFormat integerDisplayFormat; + + private DecimalScaleValidator(int maxScale, String maxScaleMessage, + NumberFormat integerDisplayFormat) { + this.maxScale = maxScale; + this.validationMessage = maxScaleMessage != null ? maxScaleMessage + : MAX_SCALE_VALIDATION_MESSAGE; + this.integerDisplayFormat = integerDisplayFormat; + } + + /** + * + * @param maxScale + * @param maxScaleMessage + * @param integerDisplayFormat + * @return . + */ + public static DecimalScaleValidator maxScale(int maxScale, + String maxScaleMessage, NumberFormat integerDisplayFormat) { + return new DecimalScaleValidator(maxScale, maxScaleMessage, + integerDisplayFormat); + } + + public IStatus validate(Object value) { + if (value != null) { + Number number = (Number) value; + int scale = new BigDecimal(number.doubleValue()).scale(); + if (scale > maxScale) { + return ValidationStatus.error(getFormattedValidationMessage()); + } + } + return ValidationStatus.ok(); + } + + private synchronized String getFormattedValidationMessage() { + if (formattedValidationMessage == null) { + formattedValidationMessage = MessageFormat.format( + validationMessage, getValidationMessageArguments()); + } + return formattedValidationMessage; + } + + private String[] getValidationMessageArguments() { + synchronized (integerDisplayFormat) { + return new String[] { integerDisplayFormat.format(new Integer( + maxScale)) }; + } + } +} Index: src/org/eclipse/core/databinding/editing/DateEditing.java =================================================================== RCS file: src/org/eclipse/core/databinding/editing/DateEditing.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/databinding/editing/DateEditing.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,279 @@ +/******************************************************************************* + * Copyright (c) 2009 Ovidio Mallo 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: + * Ovidio Mallo - initial API and implementation (bug 183055) + ******************************************************************************/ + +package org.eclipse.core.databinding.editing; + +import java.util.Date; + +import org.eclipse.core.databinding.validation.constraint.Constraints; +import org.eclipse.core.databinding.validation.constraint.DateConstraints; +import org.eclipse.core.databinding.validation.constraint.StringConstraints; +import org.eclipse.core.internal.databinding.conversion.DateToStringConverter; +import org.eclipse.core.internal.databinding.conversion.StringToDateConverter; +import org.eclipse.core.internal.databinding.validation.StringToDateValidator; + +import com.ibm.icu.text.DateFormat; + +/** + * @since 1.4 + */ +public final class DateEditing extends Editing { + + private final DateFormat displayFormat; + + private DateEditing(DateFormat[] inputFormats, String parseErrorMessage, + DateFormat displayFormat) { + this.displayFormat = displayFormat; + + StringToDateConverter targetConverter = new StringToDateConverter(); + if (inputFormats != null) { + targetConverter.setFormatters(inputFormats); + } + + DateToStringConverter modelConverter = new DateToStringConverter(); + if (displayFormat != null) { + modelConverter.setFormatters(new DateFormat[] { displayFormat }); + } + + StringToDateValidator targetValidator = new StringToDateValidator( + targetConverter); + if (parseErrorMessage != null) { + targetValidator.setParseErrorMessage(parseErrorMessage); + } + + setTargetConverter(targetConverter); + setModelConverter(modelConverter); + targetConstraints().addValidator(targetValidator); + } + + /** + * Creates a new editing object which defaults the validations and + * conversions used for editing. Uses the default validation message. + * + * @return The new editing object using the default validations and + * conversions for editing. + */ + public static DateEditing withDefaults() { + return withDefaults(null); + } + + /** + * Creates a new editing object which defaults the validations and + * conversions used for editing. Uses the specified custom validation + * message. + * + * @param parseErrorMessage + * The validation message issued in case the input string cannot + * be parsed to a date. + * @return The new editing object using the default validations and + * conversions for editing. + */ + public static DateEditing withDefaults(String parseErrorMessage) { + return new DateEditing(null, parseErrorMessage, null); + } + + /** + * Creates a new editing object which supports all the given date input + * formats and which uses the specified format for displaying a date. Uses + * the default validation message. + * + * @param inputFormats + * The date formats supported for reading in dates. + * @param displayFormat + * The date format for displaying dates. + * @return The new editing object configured by the given date formats. + */ + public static DateEditing forFormats(DateFormat[] inputFormats, + DateFormat displayFormat) { + return new DateEditing(inputFormats, null, displayFormat); + } + + /** + * Creates a new editing object which supports all the given date input + * formats and which uses the specified format for displaying a date. Uses + * the specified custom validation message. + * + * @param inputFormats + * The date formats supported for reading in dates. + * @param parseErrorMessage + * The validation message issued in case the input string cannot + * be parsed to a date. + * @param displayFormat + * The date format for displaying dates. + * @return The new editing object configured by the given date formats. + */ + public static DateEditing forFormats(DateFormat[] inputFormats, + String parseErrorMessage, DateFormat displayFormat) { + return new DateEditing(inputFormats, parseErrorMessage, displayFormat); + } + + /** + * Returns the target constraints to apply. + * + *+ * This method provides a typesafe access to the {@link StringConstraints + * string target constraints} of this editing object and is equivalent to + * {@code (StringConstraints) targetConstraints()}. + *
+ * + * @return The target constraints to apply. + * + * @see #targetConstraints() + * @see StringConstraints + */ + public StringConstraints targetStringConstraints() { + return (StringConstraints) targetConstraints(); + } + + /** + * Returns the model constraints to apply. + * + *+ * This method provides a typesafe access to the {@link DateConstraints date + * model constraints} of this editing object and is equivalent to {@code + * (DateConstraints) modelConstraints()}. + *
+ * + * @return The target constraints to apply. + * + * @see #modelConstraints() + * @see DateConstraints + */ + public DateConstraints modelDateConstraints() { + return (DateConstraints) modelConstraints(); + } + + /** + * Returns the before-set model constraints to apply. + * + *+ * This method provides a typesafe access to the {@link DateConstraints date + * before-set model constraints} of this editing object and is equivalent to + * {@code (DateConstraints) beforeSetModelConstraints()}. + *
+ * + * @return The target constraints to apply. + * + * @see #beforeSetModelConstraints() + * @see DateConstraints + */ + public DateConstraints beforeSetModelDateConstraints() { + return (DateConstraints) beforeSetModelConstraints(); + } + + protected Constraints createTargetConstraints() { + return new StringConstraints(); + } + + protected Constraints createModelConstraints() { + return new DateConstraints().displayFormat(displayFormat); + } + + protected Constraints createBeforeSetModelConstraints() { + return new DateConstraints().displayFormat(displayFormat); + } + + /** + * Convenience method which adds a {@link DateConstraints#required() + * required constraint} to the set of {@link #modelDateConstraints()}. + * + * @return This editing instance for method chaining. + * + * @see DateConstraints#required() + * @see #modelDateConstraints() + */ + public DateEditing required() { + modelDateConstraints().required(); + return this; + } + + /** + * Convenience method which adds a {@link DateConstraints#after(Date) after + * constraint} to the set of {@link #modelDateConstraints()}. + * + * @param date + * The date of the after constraint. + * @return This editing instance for method chaining. + * + * @see DateConstraints#after(Date) + * @see #modelDateConstraints() + */ + public DateEditing after(Date date) { + modelDateConstraints().after(date); + return this; + } + + /** + * Convenience method which adds a {@link DateConstraints#afterEqual(Date) + * after-equal constraint} to the set of {@link #modelDateConstraints()}. + * + * @param date + * The date of the after-equal constraint. + * @return This editing instance for method chaining. + * + * @see DateConstraints#afterEqual(Date) + * @see #modelDateConstraints() + */ + public DateEditing afterEqual(Date date) { + modelDateConstraints().afterEqual(date); + return this; + } + + /** + * Convenience method which adds a {@link DateConstraints#before(Date) + * before constraint} to the set of {@link #modelDateConstraints()}. + * + * @param date + * The date of the before constraint. + * @return This editing instance for method chaining. + * + * @see DateConstraints#before(Date) + * @see #modelDateConstraints() + */ + public DateEditing before(Date date) { + modelDateConstraints().before(date); + return this; + } + + /** + * Convenience method which adds a {@link DateConstraints#beforeEqual(Date) + * after-equal constraint} to the set of {@link #modelDateConstraints()}. + * + * @param date + * The date of the after-equal constraint. + * @return This editing instance for method chaining. + * + * @see DateConstraints#afterEqual(Date) + * @see #modelDateConstraints() + */ + public DateEditing beforeEqual(Date date) { + modelDateConstraints().beforeEqual(date); + return this; + } + + /** + * Convenience method which adds a {@link DateConstraints#range(Date, Date) + * range constraint} to the set of {@link #modelDateConstraints()}. + * + * @param minDate + * The min date of the range constraint. + * @param maxDate + * The max date of the range constraint. + * @return This editing instance for method chaining. + * + * @see DateConstraints#range(Date, Date) + * @see #modelDateConstraints() + */ + public DateEditing range(Date minDate, Date maxDate) { + modelDateConstraints().range(minDate, maxDate); + return this; + } +} Index: src/org/eclipse/core/internal/databinding/validation/StringRegexValidator.java =================================================================== RCS file: src/org/eclipse/core/internal/databinding/validation/StringRegexValidator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/databinding/validation/StringRegexValidator.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2009 Ovidio Mallo 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: + * Ovidio Mallo - initial API and implementation (bug 183055) + ******************************************************************************/ + +package org.eclipse.core.internal.databinding.validation; + +import java.text.MessageFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.internal.databinding.BindingMessages; +import org.eclipse.core.runtime.IStatus; + +/** + * Provides validations for strings which must match a given regular expression. + * + * @since 1.4 + */ +public class StringRegexValidator implements IValidator { + + private static final String REGEX_VALIDATION_MESSAGE = BindingMessages + .getString(BindingMessages.VALIDATE_STRING_REGEX); + + private final Pattern pattern; + private final String validationMessage; + private String formattedValidationMessage; + + /** + * Creates a new regex validator. + * + * @param regex + * The regular expression which the input string must match. + * @param validationMessage + * The validation message pattern to use. Can be parameterized + * with the given regular expression string. + */ + public StringRegexValidator(String regex, String validationMessage) { + this.pattern = Pattern.compile(regex); + this.validationMessage = validationMessage != null ? validationMessage + : REGEX_VALIDATION_MESSAGE; + } + + public IStatus validate(Object value) { + String input = (String) value; + if (input != null) { + Matcher matcher = pattern.matcher(input); + if (!matcher.matches()) { + return ValidationStatus.error(getFormattedValidationMessage()); + } + } + return ValidationStatus.ok(); + } + + private String getFormattedValidationMessage() { + if (formattedValidationMessage == null) { + formattedValidationMessage = MessageFormat.format( + validationMessage, new String[] { pattern.pattern() }); + } + return formattedValidationMessage; + } +} Index: src/org/eclipse/core/databinding/editing/DecimalEditing.java =================================================================== RCS file: src/org/eclipse/core/databinding/editing/DecimalEditing.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/databinding/editing/DecimalEditing.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,425 @@ +/******************************************************************************* + * Copyright (c) 2009 Ovidio Mallo 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: + * Ovidio Mallo - initial API and implementation (bug 183055) + ******************************************************************************/ + +package org.eclipse.core.databinding.editing; + +import org.eclipse.core.databinding.conversion.NumberToStringConverter; +import org.eclipse.core.databinding.conversion.StringToNumberConverter; +import org.eclipse.core.databinding.validation.constraint.Constraints; +import org.eclipse.core.databinding.validation.constraint.DecimalConstraints; +import org.eclipse.core.databinding.validation.constraint.StringConstraints; +import org.eclipse.core.internal.databinding.validation.AbstractStringToNumberValidator; +import org.eclipse.core.internal.databinding.validation.StringToDoubleValidator; +import org.eclipse.core.internal.databinding.validation.StringToFloatValidator; + +import com.ibm.icu.text.NumberFormat; + +/** + * @since 1.4 + */ +public final class DecimalEditing extends Editing { + + private final NumberFormat displayFormat; + + private DecimalEditing(NumberFormat format, String parseErrorMessage, + String outOfRangeMessage, Class decimalType) { + this.displayFormat = format; + + final StringToNumberConverter targetConverter; + final NumberToStringConverter modelConverter; + final AbstractStringToNumberValidator targetValidator; + if (Double.class.equals(decimalType)) { + targetConverter = StringToNumberConverter.toDouble(format, false); + modelConverter = NumberToStringConverter.fromDouble(format, false); + targetValidator = new StringToDoubleValidator(targetConverter); + } else if (Float.class.equals(decimalType)) { + targetConverter = StringToNumberConverter.toFloat(format, false); + modelConverter = NumberToStringConverter.fromFloat(format, false); + targetValidator = new StringToFloatValidator(targetConverter); + } else { + throw new IllegalArgumentException( + "Unsupported decimal type: " + decimalType); //$NON-NLS-1$ + } + + if (parseErrorMessage != null) { + targetValidator.setParseErrorMessage(parseErrorMessage); + } + if (outOfRangeMessage != null) { + targetValidator.setOutOfRangeMessage(outOfRangeMessage); + } + + targetConstraints().addValidator(targetValidator); + setTargetConverter(targetConverter); + setModelConverter(modelConverter); + } + + /** + * Creates a new editing object for {@link Double}s which defaults the + * validations and conversions used for editing based on the platform's + * locale. Uses the default validation messages. + * + * @return The new editing object using the default validations and + * conversions for editing. + * + * @see NumberFormat#getNumberInstance() + */ + public static DecimalEditing withDoubleDefaults() { + return withDoubleDefaults(null, null); + } + + /** + * Creates a new editing object for {@link Double}s which defaults the + * validations and conversions used for editing based on the platform's + * locale. Uses the specified custom validation messages. + * + * @param parseErrorMessage + * The validation message issued in case the input string cannot + * be parsed to a double. + * @param outOfRangeMessage + * The validation message issued in case the input string + * represents a double whose value is out of range. Can be + * parameterized by the-Double.MAX_VALUE
and
+ * +Double.MAX_VALUE
values.
+ * @return The new editing object using the default validations and
+ * conversions for editing.
+ *
+ * @see NumberFormat#getNumberInstance()
+ */
+ public static DecimalEditing withDoubleDefaults(String parseErrorMessage,
+ String outOfRangeMessage) {
+ return new DecimalEditing(NumberFormat.getNumberInstance(),
+ parseErrorMessage, outOfRangeMessage, Double.class);
+ }
+
+ /**
+ * Creates a new editing object for {@link Double}s whose validations and
+ * conversions used for editing are based on the given number format. Uses
+ * the default validation messages.
+ *
+ * @param format
+ * The number format defining the validations and conversions
+ * used for editing.
+ * @return The new editing object configured by the given number format.
+ */
+ public static DecimalEditing forDoubleFormat(NumberFormat format) {
+ return forDoubleFormat(format, null, null);
+ }
+
+ /**
+ * Creates a new editing object for {@link Double}s whose validations and
+ * conversions used for editing are based on the given number format. Uses
+ * the specified custom validation messages.
+ *
+ * @param format
+ * The number format defining the validations and conversions
+ * used for editing.
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to a double.
+ * @param outOfRangeMessage
+ * The validation message issued in case the input string
+ * represents a double whose value is out of range. Can be
+ * parameterized by the -Double.MAX_VALUE
and
+ * +Double.MAX_VALUE
values.
+ * @return The new editing object configured by the given number format.
+ */
+ public static DecimalEditing forDoubleFormat(NumberFormat format,
+ String parseErrorMessage, String outOfRangeMessage) {
+ return new DecimalEditing(format, parseErrorMessage, outOfRangeMessage,
+ Double.class);
+ }
+
+ /**
+ * Creates a new editing object for {@link Float}s which defaults the
+ * validations and conversions used for editing based on the platform's
+ * locale. Uses the default validation messages.
+ *
+ * @return The new editing object using the default validations and
+ * conversions for editing.
+ *
+ * @see NumberFormat#getNumberInstance()
+ */
+ public static DecimalEditing withFloatDefaults() {
+ return withFloatDefaults(null, null);
+ }
+
+ /**
+ * Creates a new editing object for {@link Float}s which defaults the
+ * validations and conversions used for editing based on the platform's
+ * locale. Uses the specified custom validation messages.
+ *
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to a double.
+ * @param outOfRangeMessage
+ * The validation message issued in case the input string
+ * represents a float whose value is out of range. Can be
+ * parameterized by the -Float.MAX_VALUE
and
+ * +Float.MAX_VALUE
values.
+ * @return The new editing object using the default validations and
+ * conversions for editing.
+ *
+ * @see NumberFormat#getNumberInstance()
+ */
+ public static DecimalEditing withFloatDefaults(String parseErrorMessage,
+ String outOfRangeMessage) {
+ return new DecimalEditing(NumberFormat.getNumberInstance(),
+ parseErrorMessage, outOfRangeMessage, Float.class);
+ }
+
+ /**
+ * Creates a new editing object for {@link Float}s whose validations and
+ * conversions used for editing are based on the given number format. Uses
+ * the default validation messages.
+ *
+ * @param format
+ * The number format defining the validations and conversions
+ * used for editing.
+ * @return The new editing object configured by the given number format.
+ */
+ public static DecimalEditing forFloatFormat(NumberFormat format) {
+ return forFloatFormat(format, null, null);
+ }
+
+ /**
+ * Creates a new editing object for {@link Float}s whose validations and
+ * conversions used for editing are based on the given number format. Uses
+ * the specified custom validation messages.
+ *
+ * @param format
+ * The number format defining the validations and conversions
+ * used for editing.
+ * @param parseErrorMessage
+ * The validation message issued in case the input string cannot
+ * be parsed to a float.
+ * @param outOfRangeMessage
+ * The validation message issued in case the input string
+ * represents a float whose value is out of range. Can be
+ * parameterized by the -Float.MAX_VALUE
and
+ * +Float.MAX_VALUE
values.
+ * @return The new editing object configured by the given number format.
+ */
+ public static DecimalEditing forFloatFormat(NumberFormat format,
+ String parseErrorMessage, String outOfRangeMessage) {
+ return new DecimalEditing(format, parseErrorMessage, outOfRangeMessage,
+ Float.class);
+ }
+
+ /**
+ * Returns the target constraints to apply.
+ *
+ * + * This method provides a typesafe access to the {@link StringConstraints + * string target constraints} of this editing object and is equivalent to + * {@code (StringConstraints) targetConstraints()}. + *
+ * + * @return The target constraints to apply. + * + * @see #targetConstraints() + * @see StringConstraints + */ + public StringConstraints targetStringConstraints() { + return (StringConstraints) targetConstraints(); + } + + /** + * Returns the model constraints to apply. + * + *+ * This method provides a typesafe access to the {@link DecimalConstraints + * decimal model constraints} of this editing object and is equivalent to + * {@code (DecimalConstraints) modelConstraints()}. + *
+ * + * @return The target constraints to apply. + * + * @see #modelConstraints() + * @see DecimalConstraints + */ + public DecimalConstraints modelDecimalConstraints() { + return (DecimalConstraints) modelConstraints(); + } + + /** + * Returns the before-set model constraints to apply. + * + *+ * This method provides a typesafe access to the {@link DecimalConstraints + * decimal before-set model constraints} of this editing object and is + * equivalent to {@code (DecimalConstraints) beforeSetModelConstraints()}. + *
+ * + * @return The target constraints to apply. + * + * @see #beforeSetModelConstraints() + * @see DecimalConstraints + */ + public DecimalConstraints beforeSetModelDecimalConstraints() { + return (DecimalConstraints) beforeSetModelConstraints(); + } + + protected Constraints createTargetConstraints() { + return new StringConstraints(); + } + + protected Constraints createModelConstraints() { + return new DecimalConstraints().decimalDisplayFormat(displayFormat); + } + + protected Constraints createBeforeSetModelConstraints() { + return new DecimalConstraints().decimalDisplayFormat(displayFormat); + } + + /** + * Convenience method which adds a {@link DecimalConstraints#required() + * required constraint} to the set of {@link #modelDecimalConstraints()}. + * + * @return This editing instance for method chaining. + * + * @see DecimalConstraints#required() + * @see #modelDecimalConstraints() + */ + public DecimalEditing required() { + modelDecimalConstraints().required(); + return this; + } + + /** + * Convenience method which adds a + * {@link DecimalConstraints#greater(double) greater constraint} to the set + * of {@link #modelDecimalConstraints()}. + * + * @param number + * The number of the greater constraint. + * @return This editing instance for method chaining. + * + * @see DecimalConstraints#greater(double) + * @see #modelDecimalConstraints() + */ + public DecimalEditing greater(double number) { + modelDecimalConstraints().greater(number); + return this; + } + + /** + * Convenience method which adds a + * {@link DecimalConstraints#greaterEqual(double) greater-equal constraint} + * to the set of {@link #modelDecimalConstraints()}. + * + * @param number + * The number of the greater-equal constraint. + * @return This editing instance for method chaining. + * + * @see DecimalConstraints#greaterEqual(double) + * @see #modelDecimalConstraints() + */ + public DecimalEditing greaterEqual(double number) { + modelDecimalConstraints().greaterEqual(number); + return this; + } + + /** + * Convenience method which adds a {@link DecimalConstraints#less(double) + * less constraint} to the set of {@link #modelDecimalConstraints()}. + * + * @param number + * The number of the less constraint. + * @return This editing instance for method chaining. + * + * @see DecimalConstraints#less(double) + * @see #modelDecimalConstraints() + */ + public DecimalEditing less(double number) { + modelDecimalConstraints().less(number); + return this; + } + + /** + * Convenience method which adds a + * {@link DecimalConstraints#lessEqual(double) less-equal constraint} to the + * set of {@link #modelDecimalConstraints()}. + * + * @param number + * The number of the less-equal constraint. + * @return This editing instance for method chaining. + * + * @see DecimalConstraints#lessEqual(double) + * @see #modelDecimalConstraints() + */ + public DecimalEditing lessEqual(double number) { + modelDecimalConstraints().lessEqual(number); + return this; + } + + /** + * Convenience method which adds a + * {@link DecimalConstraints#range(double, double) range constraint} to the + * set of {@link #modelDecimalConstraints()}. + * + * @param min + * The min number of the range constraint. + * @param max + * The max number of the range constraint. + * @return This editing instance for method chaining. + * + * @see DecimalConstraints#range(double, double) + * @see #modelDecimalConstraints() + */ + public DecimalEditing range(double min, double max) { + modelDecimalConstraints().range(min, max); + return this; + } + + /** + * Convenience method which adds a {@link DecimalConstraints#positive() + * positive constraint} to the set of {@link #modelDecimalConstraints()}. + * + * @return This editing instance for method chaining. + * + * @see DecimalConstraints#positive() + * @see #modelDecimalConstraints() + */ + public DecimalEditing positive() { + modelDecimalConstraints().positive(); + return this; + } + + /** + * Convenience method which adds a {@link DecimalConstraints#nonNegative() + * non-negative constraint} to the set of {@link #modelDecimalConstraints()} + * . + * + * @return This editing instance for method chaining. + * + * @see DecimalConstraints#nonNegative() + * @see #modelDecimalConstraints() + */ + public DecimalEditing nonNegative() { + modelDecimalConstraints().nonNegative(); + return this; + } + + /** + * Convenience method which adds a {@link DecimalConstraints#maxScale(int) + * max-scale constraint} to the set of {@link #modelDecimalConstraints()} . + * + * @param scale + * @return This editing instance for method chaining. + * + * @see DecimalConstraints#maxScale(int) + * @see #modelDecimalConstraints() + */ + public DecimalEditing maxScale(int scale) { + modelDecimalConstraints().maxScale(scale); + return this; + } +} Index: src/org/eclipse/core/internal/databinding/validation/IntegerRangeValidator.java =================================================================== RCS file: src/org/eclipse/core/internal/databinding/validation/IntegerRangeValidator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/databinding/validation/IntegerRangeValidator.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,206 @@ +/******************************************************************************* + * Copyright (c) 2009 Ovidio Mallo 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: + * Ovidio Mallo - initial API and implementation (bug 183055) + ******************************************************************************/ + +package org.eclipse.core.internal.databinding.validation; + +import com.ibm.icu.text.NumberFormat; + +/** + * Provides validations for integer numbers which must lie within an open/closed + * range. + * + * @since 1.4 + */ +public class IntegerRangeValidator extends NumberRangeValidator { + + private static final Long ZERO = new Long(0); + private static final Long ONE = new Long(1); + + /** + * Single constructor which supports the individual integer range types. + * + * @param min + * The min integer of the range ornull
in case no
+ * lower bound is defined.
+ * @param max
+ * The max integer of the range or null
in case no
+ * upper bound is defined.
+ * @param minConstraint
+ * The type of constraint imposed by the lower bound of the
+ * range.
+ * @param maxConstraint
+ * The type of constraint imposed by the upper bound of the
+ * range.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized by
+ * the lower and upper bound of the range, if defined.
+ * @param format
+ * The integer format to use for formatting integers in the
+ * validation message.
+ */
+ private IntegerRangeValidator(Number min, Number max, int minConstraint,
+ int maxConstraint, String validationMessage, NumberFormat format) {
+ super(min, max, minConstraint, maxConstraint, validationMessage, format);
+ }
+
+ /**
+ * Creates a validator which checks that an input integer is greater than
+ * the given number.
+ *
+ * @param number
+ * The reference number of the greater constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference number.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static IntegerRangeValidator greater(long number,
+ String validationMessage, NumberFormat format) {
+ return new IntegerRangeValidator(new Long(number), null, GREATER,
+ UNDEFINED, defaultIfNull(validationMessage, GREATER_MESSAGE),
+ format);
+ }
+
+ /**
+ * Creates a validator which checks that an input integer is greater than or
+ * equal to the given number.
+ *
+ * @param number
+ * The reference number of the greater-equal constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference number.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static IntegerRangeValidator greaterEqual(long number,
+ String validationMessage, NumberFormat format) {
+ return new IntegerRangeValidator(new Long(number), null, GREATER_EQUAL,
+ UNDEFINED, defaultIfNull(validationMessage,
+ GREATER_EQUAL_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input integer is less than the
+ * given number.
+ *
+ * @param number
+ * The reference number of the less constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference number.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static IntegerRangeValidator less(long number,
+ String validationMessage, NumberFormat format) {
+ return new IntegerRangeValidator(null, new Long(number), UNDEFINED,
+ LESS, defaultIfNull(validationMessage, LESS_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input integer is less than or
+ * equal to the given number.
+ *
+ * @param number
+ * The reference number of the less-equal constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference number.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static IntegerRangeValidator lessEqual(long number,
+ String validationMessage, NumberFormat format) {
+ return new IntegerRangeValidator(null, new Long(number), UNDEFINED,
+ LESS_EQUAL,
+ defaultIfNull(validationMessage, LESS_EQUAL_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input integer is within the
+ * given range.
+ *
+ * @param min
+ * The lower bound of the range (inclusive).
+ * @param max
+ * The upper bound of the range (inclusive).
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the range's lower and upper bound.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static IntegerRangeValidator range(long min, long max,
+ String validationMessage, NumberFormat format) {
+ return new IntegerRangeValidator(new Long(min), new Long(max),
+ GREATER_EQUAL, LESS_EQUAL, defaultIfNull(validationMessage,
+ WITHIN_RANGE_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input integer is positive.
+ *
+ * @param validationMessage
+ * The validation message to use.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static IntegerRangeValidator positive(String validationMessage,
+ NumberFormat format) {
+ return new IntegerRangeValidator(ONE, null, GREATER_EQUAL, UNDEFINED,
+ defaultIfNull(validationMessage, POSITIVE_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input integer is non-negative.
+ *
+ * @param validationMessage
+ * The validation message to use.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static IntegerRangeValidator nonNegative(String validationMessage,
+ NumberFormat format) {
+ return new IntegerRangeValidator(ZERO, null, GREATER_EQUAL, UNDEFINED,
+ defaultIfNull(validationMessage, NON_NEGATIVE_MESSAGE), format);
+ }
+
+ protected int compare(Number number1, Number number2) {
+ long diff = number1.longValue() - number2.longValue();
+ if (diff < 0) {
+ return -1;
+ }
+ if (diff > 0) {
+ return +1;
+ }
+ return 0;
+ }
+
+ private static String defaultIfNull(String string, String defaultString) {
+ return (string != null) ? string : defaultString;
+ }
+}
Index: src/org/eclipse/core/internal/databinding/validation/NonNullValidator.java
===================================================================
RCS file: src/org/eclipse/core/internal/databinding/validation/NonNullValidator.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/internal/databinding/validation/NonNullValidator.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding.validation;
+
+import org.eclipse.core.databinding.validation.IValidator;
+import org.eclipse.core.databinding.validation.ValidationStatus;
+import org.eclipse.core.internal.databinding.BindingMessages;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * @since 1.4
+ */
+public class NonNullValidator implements IValidator {
+
+ private static final String NON_NULL_VALIDATION_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NON_NULL);
+
+ private final String validationMessage;
+
+ /**
+ * @param validationMessage
+ */
+ public NonNullValidator(String validationMessage) {
+ this.validationMessage = validationMessage != null ? validationMessage
+ : NON_NULL_VALIDATION_MESSAGE;
+ }
+
+ public IStatus validate(Object value) {
+ if (value == null) {
+ return ValidationStatus.error(validationMessage);
+ }
+ return ValidationStatus.ok();
+ }
+}
Index: src/org/eclipse/core/internal/databinding/validation/DecimalRangeValidator.java
===================================================================
RCS file: src/org/eclipse/core/internal/databinding/validation/DecimalRangeValidator.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/internal/databinding/validation/DecimalRangeValidator.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding.validation;
+
+import com.ibm.icu.text.NumberFormat;
+
+/**
+ * Provides validations for decimal numbers which must lie within an open/closed
+ * range.
+ *
+ * @since 1.4
+ */
+public class DecimalRangeValidator extends NumberRangeValidator {
+
+ private static final Double ZERO = new Double(0);
+ private static final Double ONE = new Double(1);
+
+ /**
+ * Single constructor which supports the individual decimal range types.
+ *
+ * @param min
+ * The min decimal of the range or null
in case no
+ * lower bound is defined.
+ * @param max
+ * The max decimal of the range or null
in case no
+ * upper bound is defined.
+ * @param minConstraint
+ * The type of constraint imposed by the lower bound of the
+ * range.
+ * @param maxConstraint
+ * The type of constraint imposed by the upper bound of the
+ * range.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized by
+ * the lower and upper bound of the range, if defined.
+ * @param format
+ * The decimal format to use for formatting integers in the
+ * validation message.
+ */
+ private DecimalRangeValidator(Number min, Number max, int minConstraint,
+ int maxConstraint, String validationMessage, NumberFormat format) {
+ super(min, max, minConstraint, maxConstraint, validationMessage, format);
+ }
+
+ /**
+ * Creates a validator which checks that an input decimal is greater than
+ * the given number.
+ *
+ * @param number
+ * The reference number of the greater constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference number.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DecimalRangeValidator greater(double number,
+ String validationMessage, NumberFormat format) {
+ return new DecimalRangeValidator(new Double(number), null, GREATER,
+ UNDEFINED, defaultIfNull(validationMessage, GREATER_MESSAGE),
+ format);
+ }
+
+ /**
+ * Creates a validator which checks that an input decimal is greater than or
+ * equal to the given number.
+ *
+ * @param number
+ * The reference number of the greater-equal constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference number.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DecimalRangeValidator greaterEqual(double number,
+ String validationMessage, NumberFormat format) {
+ return new DecimalRangeValidator(new Double(number), null,
+ GREATER_EQUAL, UNDEFINED, defaultIfNull(validationMessage,
+ GREATER_EQUAL_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input decimal is less than the
+ * given number.
+ *
+ * @param number
+ * The reference number of the less constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference number.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DecimalRangeValidator less(double number,
+ String validationMessage, NumberFormat format) {
+ return new DecimalRangeValidator(null, new Double(number), UNDEFINED,
+ LESS, defaultIfNull(validationMessage, LESS_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input decimal is less than or
+ * equal to the given number.
+ *
+ * @param number
+ * The reference number of the less-equal constraint.
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the given reference number.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DecimalRangeValidator lessEqual(double number,
+ String validationMessage, NumberFormat format) {
+ return new DecimalRangeValidator(null, new Double(number), UNDEFINED,
+ LESS_EQUAL,
+ defaultIfNull(validationMessage, LESS_EQUAL_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input decimal is within the
+ * given range.
+ *
+ * @param min
+ * The lower bound of the range (inclusive).
+ * @param max
+ * The upper bound of the range (inclusive).
+ * @param validationMessage
+ * The validation message pattern to use. Can be parameterized
+ * with the range's lower and upper bound.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DecimalRangeValidator range(double min, double max,
+ String validationMessage, NumberFormat format) {
+ return new DecimalRangeValidator(new Double(min), new Double(max),
+ GREATER_EQUAL, LESS_EQUAL, defaultIfNull(validationMessage,
+ WITHIN_RANGE_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input decimal is positive.
+ *
+ * @param validationMessage
+ * The validation message to use.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DecimalRangeValidator positive(String validationMessage,
+ NumberFormat format) {
+ return new DecimalRangeValidator(ONE, null, GREATER_EQUAL, UNDEFINED,
+ defaultIfNull(validationMessage, POSITIVE_MESSAGE), format);
+ }
+
+ /**
+ * Creates a validator which checks that an input decimal is non-negative.
+ *
+ * @param validationMessage
+ * The validation message to use.
+ * @param format
+ * The display format to use for formatting integers in the
+ * validation message.
+ * @return The validator instance.
+ */
+ public static DecimalRangeValidator nonNegative(String validationMessage,
+ NumberFormat format) {
+ return new DecimalRangeValidator(ZERO, null, GREATER_EQUAL, UNDEFINED,
+ defaultIfNull(validationMessage, NON_NEGATIVE_MESSAGE), format);
+ }
+
+ protected int compare(Number number1, Number number2) {
+ double diff = number1.doubleValue() - number2.doubleValue();
+ if (diff < 0) {
+ return -1;
+ }
+ if (diff > 0) {
+ return +1;
+ }
+ return 0;
+ }
+
+ private static String defaultIfNull(String string, String defaultString) {
+ return (string != null) ? string : defaultString;
+ }
+}
Index: src/org/eclipse/core/internal/databinding/conversion/BooleanToStringConverter.java
===================================================================
RCS file: src/org/eclipse/core/internal/databinding/conversion/BooleanToStringConverter.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/internal/databinding/conversion/BooleanToStringConverter.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding.conversion;
+
+import org.eclipse.core.databinding.conversion.Converter;
+
+/**
+ * @since 1.4
+ */
+public class BooleanToStringConverter extends Converter {
+
+ // Those are the defaults used up to now in UpdateStrategy where a simple
+ // ObjectToStringConverter was used for converting booleans to strings.
+ // FIXME: Should/may we change this to convert to a localized string?
+ private String trueValue = Boolean.TRUE.toString();
+ private String falseValue = Boolean.FALSE.toString();
+
+ /**
+ * Creates a new converter which converts a boolean to its default string
+ * representation.
+ *
+ * @param booleanType
+ * The boolean type. Must be one of {@code Boolean.TYPE} or
+ * {@code Boolean.class}.
+ */
+ public BooleanToStringConverter(Class booleanType) {
+ super(booleanType, String.class);
+ }
+
+ /**
+ * Sets the string values to which a true
and
+ * false
value should be converted.
+ *
+ * @param trueValue
+ * The string to which to convert a true
value.
+ * @param falseValue
+ * The string to which to convert a false
value.
+ */
+ public final void setTargetStrings(String trueValue, String falseValue) {
+ this.trueValue = trueValue;
+ this.falseValue = falseValue;
+ }
+
+ public Object convert(Object source) {
+ Boolean value = (Boolean) source;
+ if (value != null) {
+ return value.booleanValue() ? trueValue : falseValue;
+ }
+ return ""; //$NON-NLS-1$
+ }
+}
Index: src/org/eclipse/core/databinding/validation/constraint/IntegerConstraints.java
===================================================================
RCS file: src/org/eclipse/core/databinding/validation/constraint/IntegerConstraints.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/databinding/validation/constraint/IntegerConstraints.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.databinding.validation.constraint;
+
+import org.eclipse.core.internal.databinding.validation.IntegerRangeValidator;
+import org.eclipse.core.internal.databinding.validation.NonNullValidator;
+
+import com.ibm.icu.text.NumberFormat;
+
+/**
+ * @since 1.4
+ */
+public final class IntegerConstraints extends Constraints {
+
+ private NumberFormat integerDisplayFormat = NumberFormat
+ .getIntegerInstance();
+
+ private String requiredMessage = null;
+
+ private String greaterMessage = null;
+
+ private String greaterEqualMessage = null;
+
+ private String lessMessage = null;
+
+ private String lessEqualMessage = null;
+
+ private String rangeMessage = null;
+
+ private String positiveMessage = null;
+
+ private String nonNegativeMessage = null;
+
+ /**
+ * Sets the format to use when formatting an integer to be included in any
+ * of the validation messages.
+ *
+ * + * This integer format will be used for any subsequent constraints which are + * applied. + *
+ * + * @param format + * The format to use for displaying integers in validation + * messages. + * @return This constraints instance for method chaining. + */ + public IntegerConstraints integerDisplayFormat(NumberFormat format) { + this.integerDisplayFormat = format; + return this; + } + + /** + * Adds a validator ensuring that the parsed integer is not + *null
. Uses the current {@link #requiredMessage(String)
+ * validation message}.
+ *
+ * @return This constraints instance for method chaining.
+ */
+ public IntegerConstraints required() {
+ addValidator(new NonNullValidator(requiredMessage));
+ return this;
+ }
+
+ /**
+ * Sets the validation message for the {@link #required()} constraint.
+ *
+ * @param message
+ * The validation message for the {@link #required()} constraint.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #required()
+ */
+ public IntegerConstraints requiredMessage(String message) {
+ this.requiredMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed integer is greater than the
+ * given number. Uses the current {@link #greaterMessage(String) validation
+ * message}.
+ *
+ * @param number
+ * The number which the parsed integer must be greater than.
+ * @return This constraints instance for method chaining.
+ */
+ public IntegerConstraints greater(long number) {
+ addValidator(IntegerRangeValidator.greater(number, greaterMessage,
+ integerDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #greater(long)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the {@link #greater(long)}
+ * constraint. Can be parameterized with the number which the
+ * parsed integer must be greater than.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #greater(long)
+ */
+ public IntegerConstraints greaterMessage(String message) {
+ this.greaterMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed integer is greater than or
+ * equal to the given number. Uses the current
+ * {@link #greaterEqualMessage(String) validation message}.
+ *
+ * @param number
+ * The number which the parsed integer must be greater than or
+ * equal to.
+ * @return This constraints instance for method chaining.
+ */
+ public IntegerConstraints greaterEqual(long number) {
+ addValidator(IntegerRangeValidator.greaterEqual(number,
+ greaterEqualMessage, integerDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #greaterEqual(long)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #greaterEqual(long)} constraint. Can be parameterized
+ * with the number which the parsed integer must be greater than
+ * or equal to.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #greaterEqual(long)
+ */
+ public IntegerConstraints greaterEqualMessage(String message) {
+ this.greaterEqualMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed integer is less than the given
+ * number. Uses the current {@link #lessMessage(String) validation message}.
+ *
+ * @param number
+ * The number which the parsed integer must be less than.
+ * @return This constraints instance for method chaining.
+ */
+ public IntegerConstraints less(long number) {
+ addValidator(IntegerRangeValidator.less(number, lessMessage,
+ integerDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #less(long)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the {@link #less(long)}
+ * constraint. Can be parameterized with the number which the
+ * parsed integer must be less than.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #less(long)
+ */
+ public IntegerConstraints lessMessage(String message) {
+ this.lessMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed integer is less than or equal
+ * to the given number. Uses the current {@link #lessEqualMessage(String)
+ * validation message}.
+ *
+ * @param number
+ * The number which the parsed integer must be less than or equal
+ * to.
+ * @return This constraints instance for method chaining.
+ */
+ public IntegerConstraints lessEqual(long number) {
+ addValidator(IntegerRangeValidator.greaterEqual(number,
+ lessEqualMessage, integerDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #lessEqual(long)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #lessEqual(long)} constraint. Can be parameterized with
+ * the number which the parsed integer must be less than or equal
+ * to.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #lessEqual(long)
+ */
+ public IntegerConstraints lessEqualMessage(String message) {
+ this.lessEqualMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed integer is within the given
+ * range. Uses the current {@link #rangeMessage(String) validation message}.
+ *
+ * @param min
+ * The lower bound of the range (inclusive).
+ * @param max
+ * The upper bound of the range (inclusive).
+ * @return This constraints instance for method chaining.
+ */
+ public IntegerConstraints range(long min, long max) {
+ addValidator(IntegerRangeValidator.range(min, max, rangeMessage,
+ integerDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #range(long, long)}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the
+ * {@link #range(long, long)} constraint. Can be parameterized
+ * with the min and max values of the range in which the parsed
+ * integer must lie.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #range(long, long)
+ */
+ public IntegerConstraints rangeMessage(String message) {
+ this.rangeMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed integer is positive. Uses the
+ * current {@link #positiveMessage(String) validation message}.
+ *
+ * @return This constraints instance for method chaining.
+ */
+ public IntegerConstraints positive() {
+ addValidator(IntegerRangeValidator.positive(positiveMessage,
+ integerDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #positive()}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the {@link #positive()}
+ * constraint.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #positive()
+ */
+ public IntegerConstraints positiveMessage(String message) {
+ this.positiveMessage = message;
+ return this;
+ }
+
+ /**
+ * Adds a validator ensuring that the parsed integer is non-negative. Uses
+ * the current {@link #nonNegativeMessage(String) validation message}.
+ *
+ * @return This constraints instance for method chaining.
+ */
+ public IntegerConstraints nonNegative() {
+ addValidator(IntegerRangeValidator.nonNegative(nonNegativeMessage,
+ integerDisplayFormat));
+ return this;
+ }
+
+ /**
+ * Sets the validation message pattern for the {@link #nonNegative()}
+ * constraint.
+ *
+ * @param message
+ * The validation message pattern for the {@link #nonNegative()}
+ * constraint.
+ * @return This constraints instance for method chaining.
+ *
+ * @see #nonNegative()
+ */
+ public IntegerConstraints nonNegativeMessage(String message) {
+ this.nonNegativeMessage = message;
+ return this;
+ }
+}
Index: src/org/eclipse/core/internal/databinding/conversion/StringStripConverter.java
===================================================================
RCS file: src/org/eclipse/core/internal/databinding/conversion/StringStripConverter.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/internal/databinding/conversion/StringStripConverter.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding.conversion;
+
+import org.eclipse.core.databinding.conversion.Converter;
+
+/**
+ * @since 1.4
+ */
+public class StringStripConverter extends Converter {
+
+ private final boolean stripToNull;
+
+ /**
+ *
+ * @param stripToNull
+ */
+ public StringStripConverter(boolean stripToNull) {
+ super(String.class, String.class);
+ this.stripToNull = stripToNull;
+ }
+
+ public Object convert(Object fromObject) {
+ String string = (String) fromObject;
+
+ if (string != null && string.length() != 0) {
+ int stripStart = 0;
+ while (stripStart < string.length()
+ && Character.isWhitespace(string.charAt(stripStart))) {
+ stripStart++;
+ }
+
+ int stripEnd = string.length() - 1;
+ while (stripEnd >= 0
+ && Character.isWhitespace(string.charAt(stripEnd))) {
+ stripEnd--;
+ }
+
+ if (stripStart <= stripEnd) {
+ string = string.substring(stripStart, stripEnd + 1);
+ } else {
+ string = ""; //$NON-NLS-1$
+ }
+ }
+
+ if (stripToNull && string != null && string.length() == 0) {
+ string = null;
+ }
+
+ return string;
+ }
+}
Index: src/org/eclipse/core/internal/databinding/validation/NonEmptyStringValidator.java
===================================================================
RCS file: src/org/eclipse/core/internal/databinding/validation/NonEmptyStringValidator.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/internal/databinding/validation/NonEmptyStringValidator.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ovidio Mallo 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:
+ * Ovidio Mallo - initial API and implementation (bug 183055)
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding.validation;
+
+import org.eclipse.core.databinding.validation.IValidator;
+import org.eclipse.core.databinding.validation.ValidationStatus;
+import org.eclipse.core.internal.databinding.BindingMessages;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * @since 1.4
+ */
+public class NonEmptyStringValidator implements IValidator {
+
+ private static final String NON_EMPTY_STRING_VALIDATION_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NON_EMPTY_STRING);
+
+ private final String validationMessage;
+
+ /**
+ *
+ */
+ public NonEmptyStringValidator() {
+ this(null);
+ }
+
+ /**
+ * @param validationMessage
+ */
+ public NonEmptyStringValidator(String validationMessage) {
+ this.validationMessage = validationMessage != null ? validationMessage
+ : NON_EMPTY_STRING_VALIDATION_MESSAGE;
+ }
+
+ public IStatus validate(Object value) {
+ String input = (String) value;
+ if ("".equals(input)) { //$NON-NLS-1$
+ return ValidationStatus.error(validationMessage);
+ }
+ return ValidationStatus.ok();
+ }
+}