package org.archstudio.bna.logics.hints.synchronizers;
import static com.google.common.base.Preconditions.checkArgument;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import org.archstudio.bna.IBNAWorld;
import org.archstudio.bna.IThing;
import org.archstudio.bna.keys.IThingKey;
import org.archstudio.bna.logics.hints.IHintRepository;
import org.archstudio.bna.logics.hints.IHintRepository.HintValue;
import org.archstudio.bna.utils.BNAUtils;
import org.archstudio.bna.utils.UserEditableUtils;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
public class PropertyHintSynchronizer extends AbstractHintSynchronizer {
public boolean DEBUG = false;
protected final IThingKey<Object> propertyName;
protected final Function<Object, Object> propertyTranslator;
protected final Class<?> requiredThingClass;
protected final Predicate<IThing> filter;
protected final String[] editableQualities;
public <T> PropertyHintSynchronizer(IBNAWorld world, String hintName, IThingKey<T> propertyName,
Function<Object, Object> propertyTranslator, Class<?> requiredThingClass, String... editableQualities) {
this(world, hintName, propertyName, propertyTranslator, requiredThingClass, Predicates.<IThing> alwaysTrue(),
editableQualities);
}
@SuppressWarnings("unchecked")
public <T> PropertyHintSynchronizer(IBNAWorld world, String hintName, IThingKey<T> propertyName,
Function<Object, Object> propertyTranslator, Class<?> requiredThingClass, Predicate<IThing> filter,
String... editableQualities) {
super(world, hintName);
this.propertyName = (IThingKey<Object>) propertyName;
this.propertyTranslator = propertyTranslator;
this.requiredThingClass = requiredThingClass;
this.filter = filter;
this.editableQualities = editableQualities;
}
@Override
public Collection<IThingKey<?>> getThingPropertiesOfInterest() {
return Collections.<IThingKey<?>> singleton(propertyName);
}
@Override
public void restoreHints(IHintRepository repository, Object context, IThing thing, String hintName,
HintValue hintValue) {
BNAUtils.checkLock();
checkArgument(this.hintName.equals(hintName));
if (wasIgnored(context)) {
return;
}
if (filter.apply(thing) && requiredThingClass.isInstance(thing)
&& UserEditableUtils.isEditableForAllQualities(thing, editableQualities)) {
if (hintValue.isPresent()) {
if (DEBUG) {
System.err.println("Restoring: " + propertyName);
}
Object o = hintValue.getValue();
if (propertyTranslator != null) {
o = propertyTranslator.apply(o);
}
if (o != null) {
thing.set(propertyName, o);
}
else {
thing.remove(propertyName);
}
}
}
}
@Override
public void storeHints(IHintRepository repository, Object context, IThing thing, IThingKey<?> key) {
BNAUtils.checkLock();
if (filter.apply(thing) && requiredThingClass.isInstance(thing)
&& UserEditableUtils.isEditableForAllQualities(thing, editableQualities)) {
Object value = thing.get(propertyName);
if (DEBUG) {
System.err.println(" Storing: " + hintName);
}
if (value != null && value instanceof Serializable) {
if (repository.storeHint(context, hintName, (Serializable) value)) {
ignore(context);
}
}
else {
if (repository.removeHint(context, hintName)) {
ignore(context);
}
}
}
}
@Override
public String toString() {
return hintName + "=" + propertyName;
}
}