com.xzchaoo.commons.basic.config.DefaultCompositeConfig Maven / Gradle / Ivy
package com.xzchaoo.commons.basic.config;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
/**
* created at 2020-08-07
*
* @author xiangfeng.xzc
*/
@SuppressWarnings("WeakerAccess")
public class DefaultCompositeConfig extends AbstractConfig
implements Config.Composite {
private volatile State state = new State(emptyList());
private final ChildListener childListener = new ChildListener();
public DefaultCompositeConfig(Manager manager) {
super(manager);
this.state = new State(emptyList());
}
public DefaultCompositeConfig(Manager manager, Config... configs) {
super(manager);
List children = new ArrayList<>(configs.length);
lock();
try {
for (Config config : configs) {
if (config.manager() != manager) {
throw new IllegalArgumentException();
}
Child child = new Child(config, childListener);
children.add(child);
}
for (Child c : children) {
c.listen();
}
this.state = new State(children);
} finally {
unlock();
}
}
public DefaultCompositeConfig(Manager manager, List configs) {
super(manager);
List children = new ArrayList<>(configs.size());
lock();
try {
for (Config config : configs) {
if (config.manager() != manager) {
throw new IllegalArgumentException();
}
Child child = new Child(config, childListener);
children.add(child);
}
for (Child c : children) {
c.listen();
}
this.state = new State(children);
} finally {
unlock();
}
}
public void addFirst(Config config) {
add(config, true);
}
public void addLast(Config config) {
add(config, false);
}
@Override
public Map asMap() {
return state.merged;
}
@Override
public String getString(String key) {
return state.merged.get(key);
}
@Override
public List children() {
return state.childrenConfigs;
}
public void remove(Config config) {
lock();
try {
State oldState = this.state;
Child child = oldState.findChild(config);
if (child == null) {
return;
}
child.unListen();
List newConfigs = new ArrayList<>(oldState.children);
newConfigs.remove(child);
this.state = new State(newConfigs);
fireChange();
} finally {
unlock();
}
}
private void add(Config config, boolean first) {
if (config.manager() != manager) {
throw new IllegalArgumentException("");
}
lock();
try {
State oldState = this.state;
Child child = oldState.findChild(config);
if (child != null) {
throw new IllegalStateException("duplicated config");
}
child = new Child(config, childListener);
child.listen();
List newConfigs =
new ArrayList<>(oldState.children.size() + 1);
if (first) {
newConfigs.add(child);
newConfigs.addAll(oldState.children);
} else {
newConfigs.addAll(oldState.children);
newConfigs.add(child);
}
this.state = new State(newConfigs);
fireChange();
} finally {
unlock();
}
}
private void onChildChange() {
lock();
try {
State state = this.state;
this.state = new State(state.children);
fireChange();
} finally {
unlock();
}
}
private static class State {
final Map merged;
final List children;
final List childrenConfigs;
State(List children) {
this.children = unmodifiableList(new ArrayList<>(children));
this.childrenConfigs = new ArrayList<>(children.size());
Map merged = new HashMap<>();
for (Child child : children) {
this.childrenConfigs.add(child.config);
merged.putAll(child.config.asMap());
}
this.merged = unmodifiableMap(merged);
}
public Child findChild(Config config) {
for (Child child : children) {
if (child.config == config) {
return child;
}
}
return null;
}
}
public class Child {
final Config config;
final Listener listener;
public Child(Config config, Listener listener) {
this.config = config;
this.listener = listener;
}
public void listen() {
config.addListener(listener);
}
public void unListen() {
config.removeListener(listener);
}
}
private class ChildListener implements Listener {
@Override
public void onEvent(Event event) {
onChildChange();
}
}
}