blob: 17caff33d97cc2540ca41d78b0aad99c063c9b4e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation 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:
* IBM Corporation - initial API and implementation
******************************************************************************/
package org.eclipse.jface.internal.databinding.internal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.internal.databinding.provisional.Binding;
import org.eclipse.jface.internal.databinding.provisional.observable.Diffs;
import org.eclipse.jface.internal.databinding.provisional.observable.IChangeListener;
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
import org.eclipse.jface.internal.databinding.provisional.observable.list.ListDiff;
import org.eclipse.jface.internal.databinding.provisional.observable.list.ListDiffEntry;
import org.eclipse.jface.internal.databinding.provisional.observable.list.ObservableList;
import org.eclipse.jface.internal.databinding.provisional.observable.list.WritableList;
import org.eclipse.jface.internal.databinding.provisional.observable.value.IObservableValue;
import org.eclipse.jface.internal.databinding.provisional.validation.ValidationError;
/**
* @since 1.0
*
*/
public class ValidationErrorList extends ObservableList {
private boolean isDirty = true;
private final WritableList bindings;
private final boolean usePartialErrors;
private List dependencies = new ArrayList();
private IChangeListener markDirtyChangeListener = new IChangeListener() {
public void handleChange(IObservable source) {
markDirty();
}
};
/**
* @param bindings
* @param usePartialErrors
*/
public ValidationErrorList(WritableList bindings,
boolean usePartialErrors) {
super(new ArrayList(), ValidationError.class);
this.bindings = bindings;
this.usePartialErrors = usePartialErrors;
bindings.addChangeListener(markDirtyChangeListener);
}
protected void getterCalled() {
recompute();
super.getterCalled();
}
private void markDirty() {
// since we are dirty, we don't need to listen anymore
removeElementChangeListener();
final List oldList = wrappedList;
// lazy computation of diff
ListDiff listDiff = new ListDiff() {
ListDiffEntry[] cachedDifferences = null;
public ListDiffEntry[] getDifferences() {
if(cachedDifferences==null) {
recompute();
cachedDifferences = Diffs.computeListDiff(oldList, wrappedList).getDifferences();
}
return cachedDifferences;
}
};
wrappedList = new ArrayList();
isDirty = true;
fireListChange(listDiff);
}
private void recompute() {
if (isDirty) {
List newContents = new ArrayList();
for (Iterator it = bindings.iterator(); it.hasNext();) {
Binding binding = (Binding) it.next();
IObservableValue validationError = usePartialErrors ? binding
.getPartialValidationError() : binding
.getValidationError();
dependencies.add(validationError);
validationError.addChangeListener(markDirtyChangeListener);
Object validationErrorValue = validationError.getValue();
if (validationErrorValue != null) {
newContents.add(validationErrorValue);
}
}
wrappedList.addAll(newContents);
isDirty = false;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.internal.databinding.provisional.observable.list.ObservableList#dispose()
*/
public void dispose() {
bindings.removeChangeListener(markDirtyChangeListener);
removeElementChangeListener();
super.dispose();
}
private void removeElementChangeListener() {
for (Iterator it = dependencies.iterator(); it.hasNext();) {
IObservableValue observableValue = (IObservableValue) it.next();
observableValue.removeChangeListener(markDirtyChangeListener);
}
}
public Object getElementType() {
return ValidationError.class;
}
}