org.infinispan.commons.configuration.attributes.Attribute Maven / Gradle / Ivy
package org.infinispan.commons.configuration.attributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.infinispan.commons.CacheException;
import org.infinispan.commons.configuration.io.ConfigurationWriter;
import org.infinispan.commons.logging.Log;
/**
* Attribute. This class implements a configuration attribute value holder. A configuration attribute is defined by an
* {@link AttributeDefinition}. An attribute contains an optional value (or defers to its AttributeDefinition for the
* default value). It is possible to determine whether a value has been changed with respect to its initial value. An
* Attribute remains modifiable until it is protected. At which point it can only be modified if its AttributeDefinition
* allows it to be mutable. Additionally it is possible to register listeners when values change so that code can react
* to these changes.
*
* @author Tristan Tarrant
* @since 7.2
*/
public final class Attribute implements Cloneable, Matchable>, Updatable> {
private final AttributeDefinition definition;
private T value;
private boolean protect;
private boolean modified;
private List> listeners;
Attribute(AttributeDefinition definition) {
this.definition = definition;
this.value = definition.getDefaultValue();
}
public String name() {
return definition.name();
}
public T get() {
return value;
}
public T orElse(T other) {
return modified ? value : other;
}
public T getInitialValue() {
return definition.getDefaultValue();
}
public void validate() {
definition.validate(value);
}
public Attribute protect() {
if (!protect && definition.isImmutable()) {
this.protect = true;
}
return this;
}
public void set(T value) {
if (protect) {
throw Log.CONFIG.protectedAttribute(definition.name());
}
T oldValue = this.value;
this.value = value;
this.modified = true;
this.fireValueChanged(oldValue);
}
public void setImplied(T value) {
if (protect) {
throw Log.CONFIG.protectedAttribute(definition.name());
}
T oldValue = this.value;
this.value = value;
this.modified = false;
this.fireValueChanged(oldValue);
}
public void fromString(String value) {
set(definition.parse(value));
}
public T computeIfAbsent(Supplier supplier) {
if (value == null)
set(supplier.get());
return value;
}
public boolean isImmutable() {
return definition.isImmutable();
}
public boolean isPersistent() {
return definition.isAutoPersist();
}
public boolean isModified() {
return modified;
}
public boolean isRepeated() {
return definition.isRepeated();
}
public void addListener(AttributeListener listener) {
if (isImmutable() && isProtect()) {
throw new UnsupportedOperationException();
}
if (listeners == null) {
listeners = new ArrayList<>();
}
listeners.add(listener);
}
public void removeListener(AttributeListener listener) {
if (listeners != null) {
listeners.remove(listener);
}
}
public void removeListener(Predicate> filter) {
listeners.removeIf(filter);
}
public boolean isNull() {
return value == null;
}
boolean isProtect() {
return protect;
}
public AttributeDefinition getAttributeDefinition() {
return definition;
}
private void fireValueChanged(T oldValue) {
if (listeners != null) {
for (AttributeListener listener : listeners) {
listener.attributeChanged(this, oldValue);
}
}
}
@SuppressWarnings("unchecked")
@Override
protected Attribute clone() {
Attribute clone;
try {
clone = (Attribute) super.clone();
clone.modified = this.modified;
clone.listeners = null;
clone.protect = false;
return clone;
} catch (CloneNotSupportedException e) {
throw new CacheException(e);
}
}
public void read(Attribute other) {
AttributeCopier copier = definition.copier();
if (copier == null) {
Attribute clone = other.clone();
this.value = clone.value;
} else {
this.value = copier.copyAttribute(other.value);
}
this.modified = other.modified;
}
public void merge(Attribute other) {
Collection