// =====================================================================
//
// Copyright (C) 2012 - 2016, Philip Graf
//
// 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
//
// =====================================================================
package ch.acanda.eclipse.pmd.ui.model;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import com.google.common.collect.ImmutableSet;
/**
* Base class for a view model.
*
* @author Philip Graf
*/
@SuppressWarnings("PMD.TooManyMethods")
public abstract class ViewModel {
public static final String DIRTY_PROPERTY = "dirty";
public static final String VALID_PROPERTY = "valid";
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
private ImmutableSet<String> validatedProperties;
private boolean isDirty;
private boolean isValid;
private ValidationResult validationResult;
public void addPropertyChangeListener(final String propertyName, final PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}
public void addPropertyChangeListener(final PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(final String propertyName, final PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListener(final PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
protected <T> void setProperty(final String propertyName, final T oldValue, final T newValue) {
propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
final boolean newIsDirty = updateDirty();
propertyChangeSupport.firePropertyChange(DIRTY_PROPERTY, isDirty, isDirty = newIsDirty);
if (validatedProperties == null) {
validatedProperties = createValidatedPropertiesSet();
}
if (validatedProperties.contains(propertyName)) {
final ValidationJob job = new ValidationJob(this, propertyName);
job.schedule();
}
}
/**
* Checks if the model was changed (is dirty). The implementation must not invoke
* {@link ViewModel#setProperty(String, Object, Object)} as this would result in an infinite recursion.
*
* @return {@code true} if the model is valid, {@code false} if the model is invalid.
*/
protected abstract boolean updateDirty();
/**
* Validates the model. The implementation must validate the entire model. The provided {@code propertyName} merely
* indicates which property has changed. The implementation must not invoke
* {@link ViewModel#setProperty(String, Object, Object)} for validated properties as this would result in an
* infinite recursion.
*
* @param propertyName The name of the property that has changed.
* @param validationResult
*/
protected abstract void validate(String propertyName, ValidationResult validationResult);
/**
* Returns the names of the properties that are validated. If a property is changed and its name is not in this set,
* {@link #validate(String)} will not be invoked. This method is only called once (before the first time
* {@link #validate(String)} is invoked), so the method does not have to be optimized.
*
* @return An immutable set of the names of validated properties.
*/
protected abstract ImmutableSet<String> createValidatedPropertiesSet();
public boolean isValid() {
return isValid;
}
void setValidationResult(final ValidationResult result) {
isValid = result.isValid();
propertyChangeSupport.firePropertyChange(VALID_PROPERTY, validationResult, validationResult = result);
}
public void addDirtyChangeListener(final PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(DIRTY_PROPERTY, listener);
}
public void removeDirtyChangeListener(final PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(DIRTY_PROPERTY, listener);
}
public void addValidationChangeListener(final PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(VALID_PROPERTY, listener);
}
public void removeValidationChangeListener(final PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(VALID_PROPERTY, listener);
}
}