package com.netflix.fabricator.properties;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Supplier;
import com.netflix.fabricator.ConfigurationNode;
import com.netflix.fabricator.supplier.ListenableSupplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.Properties;
import java.util.Set;
public class PropertiesComponentConfiguration extends AbstractPropertiesComponentConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(PropertiesComponentConfiguration.class);
private final Properties props;
public PropertiesComponentConfiguration(String id, String type, Properties props, String fullName) {
super(id, type, fullName);
this.props = props;
}
public PropertiesComponentConfiguration(String id, String type, Properties props) {
super(id, type);
this.props = props;
}
public static abstract class StaticListenableSupplier<T> implements ListenableSupplier<T> {
StaticListenableSupplier() {
}
@Override
public void onChange(Function<T, Void> func) {
// noop
}
}
@SuppressWarnings("unchecked")
@Override
public <T> ListenableSupplier<T> getDynamicValue(Class<T> type) {
if ( String.class.isAssignableFrom(type) ) {
return (ListenableSupplier<T>) new StaticListenableSupplier<String>() {
@Override
public String get() {
final String value = props.getProperty(getFullName());
if (value == null)
return null;
return value;
}
};
}
else if ( Boolean.class.isAssignableFrom(type)
|| Boolean.TYPE.isAssignableFrom(type)
|| boolean.class.equals(type)) {
return (ListenableSupplier<T>) new StaticListenableSupplier<Boolean>() {
@Override
public Boolean get() {
final String value = props.getProperty(getFullName());
if (value == null)
return null;
return Boolean.valueOf(value);
}
};
}
else if ( Integer.class.isAssignableFrom(type)
|| Integer.TYPE.isAssignableFrom(type)
|| int.class.equals(type)) {
return (ListenableSupplier<T>) new StaticListenableSupplier<Integer>() {
@Override
public Integer get() {
final String value = props.getProperty(getFullName());
if (value == null)
return null;
return Integer.valueOf(value);
}
};
}
else if ( Long.class.isAssignableFrom(type)
|| Long.TYPE.isAssignableFrom(type)
|| long.class.equals(type)) {
return (ListenableSupplier<T>) new StaticListenableSupplier<Long>() {
@Override
public Long get() {
final String value = props.getProperty(getFullName());
if (value == null)
return null;
return Long.valueOf(value);
}
};
}
else if ( Double.class.isAssignableFrom(type)
|| Double.TYPE.isAssignableFrom(type)
|| double.class.equals(type)) {
return (ListenableSupplier<T>) new StaticListenableSupplier<Double>() {
@Override
public Double get() {
final String value = props.getProperty(getFullName());
if (value == null)
return null;
return Double.valueOf(value);
}
};
}
else if ( Properties.class.isAssignableFrom(type)) {
return (ListenableSupplier<T>) new StaticListenableSupplier<Properties>() {
@Override
public Properties get() {
if (props.containsKey(getFullName())) {
throw new RuntimeException(getFullName() + " is not a root for a properties structure");
}
String prefix = getFullName() + ".";
Properties result = new Properties();
for (String prop : props.stringPropertyNames()) {
if (prop.startsWith(prefix)) {
result.setProperty(prop.substring(prefix.length()), props.getProperty(prop));
}
}
return result;
}
};
}
else {
LOG.warn(String.format("Unknown type '%s' for property '%s'", type.getCanonicalName(), getFullName()));
return null;
}
}
@Override
public ConfigurationNode getChild(String name) {
String fullName = Joiner.on(".").skipNulls().join(getFullName(), name);
return new PropertiesComponentConfiguration(
name,
props.getProperty(Joiner.on(".").join(fullName, "type")), // TODO: Make 'type' configurable
props,
fullName);
}
@Override
public boolean isSingle() {
return props.containsKey(getFullName());
}
@Override
public boolean hasChild(String propertyName) {
return props.containsKey(Joiner.on(".").skipNulls().join(getFullName(), propertyName));
}
@Override
public Set<String> getUnknownProperties(Set<String> supportedProperties) {
return Collections.emptySet();
}
@Override
public <T> T getValue(Class<T> type) {
Supplier<T> supplier = this.getDynamicValue(type);
if (supplier != null)
return supplier.get();
return null;
}
@Override
public String toString() {
return new StringBuilder()
.append("PropertiesComponentConfiguration[")
.append("id=").append(getId())
.append(",type=").append(getType())
.append(",full=").append(getFullName())
.append(",props=").append(props)
.append("]")
.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((props == null) ? 0 : props.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PropertiesComponentConfiguration other = (PropertiesComponentConfiguration) obj;
if (props == null) {
if (other.props != null)
return false;
} else if (!props.equals(other.props))
return false;
return true;
}
}