package com.revolsys.properties;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.PreDestroy;
import com.revolsys.collection.map.MapEx;
import com.revolsys.collection.map.ThreadSharedProperties;
import com.revolsys.datatype.DataType;
import com.revolsys.io.map.MapObjectFactory;
import com.revolsys.logging.Logs;
import com.revolsys.util.Property;
public interface ObjectWithProperties {
@SuppressWarnings("unchecked")
static <C> C getProperty(final ObjectWithProperties object, final Map<String, Object> properties,
final String name) {
if (properties == null) {
return null;
} else {
Object value = properties.get(name);
if (value instanceof Reference) {
final Reference<C> reference = (Reference<C>)value;
if (reference.isEnqueued()) {
value = null;
} else {
value = reference.get();
}
if (value == null) {
properties.remove(name);
}
}
if (value instanceof ObjectPropertyProxy) {
final ObjectPropertyProxy<C, Object> proxy = (ObjectPropertyProxy<C, Object>)value;
value = proxy.getValue(object);
}
return (C)value;
}
}
static void setProperties(final Object object, final Map<String, ? extends Object> properties) {
if (properties != null) {
if (object instanceof ObjectWithProperties) {
final ObjectWithProperties objectWithProperties = (ObjectWithProperties)object;
objectWithProperties.setProperties(properties);
} else if (object != null) {
for (final Entry<String, ? extends Object> entry : properties.entrySet()) {
final String name = entry.getKey();
final Object value = entry.getValue();
setProperty(object, name, value);
}
}
}
}
static void setProperty(final Object object, final String name, final Object value) {
try {
Property.setSimple(object, name, value);
} catch (final Throwable e) {
}
}
@SuppressWarnings("unchecked")
default <V extends ObjectWithProperties> V addProperty(final String name, final Object value) {
setProperty(name, value);
return (V)this;
}
default void clearProperties() {
final Map<String, Object> properties = getProperties();
properties.clear();
}
@PreDestroy
default void close() {
clearProperties();
}
MapEx getProperties();
default <C> C getProperty(final String name) {
C value = Property.getSimple(this, name);
if (value == null) {
final Map<String, Object> properties = getProperties();
value = getProperty(this, properties, name);
}
return value;
}
@SuppressWarnings("unchecked")
default <C> C getProperty(final String name, final C defaultValue) {
final C value = (C)getProperty(name);
if (value == null) {
return defaultValue;
} else {
return value;
}
}
default Map<String, Object> getThreadProperties() {
Map<String, Object> properties = ThreadSharedProperties.getProperty(this);
if (properties == null) {
properties = new HashMap<>();
ThreadSharedProperties.setProperty(this, properties);
}
return properties;
}
@SuppressWarnings("unchecked")
default <T> T getThreadProperty(final String name) {
final Map<String, Object> properties = getThreadProperties();
final T value = (T)properties.get(name);
return value;
}
default boolean hasProperty(final String name) {
final Object value = getProperty(name);
return Property.hasValue(value);
}
default boolean isPropertyEqual(final String name, final Object value) {
final Object propertyValue = getProperty(name);
return DataType.equal(value, propertyValue);
}
default void removeProperty(final String propertyName) {
final Map<String, Object> properties = getProperties();
properties.remove(propertyName);
}
default void setProperties(final Map<String, ? extends Object> properties) {
if (properties != null) {
for (final Entry<String, ? extends Object> entry : properties.entrySet()) {
final String name = entry.getKey();
final Object value = entry.getValue();
setProperty(name, value);
}
}
}
default void setProperty(final String name, final Object value) {
try {
if (!Property.setSimple(this, name, value)) {
final Map<String, Object> properties = getProperties();
if (!MapObjectFactory.TYPE.equals(name)) {
properties.put(name, value);
}
}
} catch (final Throwable e) {
setPropertyError(name, value, e);
}
}
default void setPropertyError(final String name, final Object value, final Throwable e) {
Logs.debug(this, "Error setting " + name + '=' + value, e);
}
default void setPropertySoft(final String name, final Object value) {
setProperty(name, new SoftReference<>(value));
}
default void setPropertyWeak(final String name, final Object value) {
setProperty(name, new WeakReference<>(value));
}
default void setThreadProperty(final String name, final Object value) {
final Map<String, Object> properties = getThreadProperties();
properties.put(name, value);
}
}