AnyValue增加copy和merge方法
This commit is contained in:
@@ -54,6 +54,8 @@ public abstract class AnyValue {
|
|||||||
|
|
||||||
private Entry<DefaultAnyValue>[] anyEntrys = new Entry[0];
|
private Entry<DefaultAnyValue>[] anyEntrys = new Entry[0];
|
||||||
|
|
||||||
|
private int parentArrayIndex = -1; //只可能被loadFromProperties方法赋值
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建空的DefaultAnyValue对象
|
* 创建空的DefaultAnyValue对象
|
||||||
*
|
*
|
||||||
@@ -135,6 +137,76 @@ public abstract class AnyValue {
|
|||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制一份对象
|
||||||
|
*
|
||||||
|
* @return DefaultAnyValue对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public DefaultAnyValue copy() {
|
||||||
|
DefaultAnyValue rs = new DefaultAnyValue(this.ignoreCase);
|
||||||
|
if (this.stringEntrys != null) {
|
||||||
|
rs.stringEntrys = new Entry[this.stringEntrys.length];
|
||||||
|
for (int i = 0; i < rs.stringEntrys.length; i++) {
|
||||||
|
Entry<String> en = this.stringEntrys[i];
|
||||||
|
if (en == null) continue;
|
||||||
|
rs.stringEntrys[i] = new Entry(en.name, en.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.anyEntrys != null) {
|
||||||
|
rs.anyEntrys = new Entry[this.anyEntrys.length];
|
||||||
|
for (int i = 0; i < rs.anyEntrys.length; i++) {
|
||||||
|
Entry<DefaultAnyValue> en = this.anyEntrys[i];
|
||||||
|
if (en == null) continue;
|
||||||
|
rs.anyEntrys[i] = new Entry(en.name, en.value == null ? null : en.value.copy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将另一个对象合并过来
|
||||||
|
*
|
||||||
|
* @param node0 代合并对象
|
||||||
|
*
|
||||||
|
* @return AnyValue
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public DefaultAnyValue merge(AnyValue node0) {
|
||||||
|
if (node0 == null) return this;
|
||||||
|
if (node0 == this) throw new IllegalArgumentException();
|
||||||
|
DefaultAnyValue node = (DefaultAnyValue) node0;
|
||||||
|
if (node.stringEntrys != null) {
|
||||||
|
for (Entry<String> en : node.stringEntrys) {
|
||||||
|
if (en == null) continue;
|
||||||
|
setValue(en.name, en.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.anyEntrys != null) {
|
||||||
|
for (Entry<DefaultAnyValue> en : node.anyEntrys) {
|
||||||
|
if (en == null) continue;
|
||||||
|
AnyValue[] ns = getAnyValues(en.name);
|
||||||
|
if (ns == null || ns.length < 1) {
|
||||||
|
addValue(en.name, en.value);
|
||||||
|
} else {
|
||||||
|
boolean ok = false;
|
||||||
|
for (AnyValue item : ns) {
|
||||||
|
if (item == null) continue;
|
||||||
|
if (en.value.parentArrayIndex == ((DefaultAnyValue) item).parentArrayIndex) {
|
||||||
|
item.merge(en.value);
|
||||||
|
ok = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
addValue(en.name, en.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合并两个AnyValue对象, 会去重, 没有的才增加
|
* 合并两个AnyValue对象, 会去重, 没有的才增加
|
||||||
*
|
*
|
||||||
@@ -147,7 +219,7 @@ public abstract class AnyValue {
|
|||||||
final Entry<String>[] strings = av.getStringEntrys();
|
final Entry<String>[] strings = av.getStringEntrys();
|
||||||
if (strings == null) return this;
|
if (strings == null) return this;
|
||||||
for (Entry<String> en : strings) {
|
for (Entry<String> en : strings) {
|
||||||
if (getValue(en.name) == null) this.addValue(en.name, en.value);
|
if (!existsValue(en.name)) this.addValue(en.name, en.value);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -311,7 +383,11 @@ public abstract class AnyValue {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toString(0);
|
return toString(0, (any, space) -> {
|
||||||
|
int index = ((DefaultAnyValue) any).parentArrayIndex;
|
||||||
|
if (index < 0) return null;
|
||||||
|
return new StringBuilder().append(space).append(" $index: ").append(index).append(",\r\n");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultAnyValue clear() {
|
public DefaultAnyValue clear() {
|
||||||
@@ -322,7 +398,7 @@ public abstract class AnyValue {
|
|||||||
|
|
||||||
public DefaultAnyValue setValue(String name, String value) {
|
public DefaultAnyValue setValue(String name, String value) {
|
||||||
if (name == null) return this;
|
if (name == null) return this;
|
||||||
if (getValue(name) == null) {
|
if (!existsValue(name)) {
|
||||||
this.addValue(name, value);
|
this.addValue(name, value);
|
||||||
} else {
|
} else {
|
||||||
for (Entry<String> en : this.stringEntrys) {
|
for (Entry<String> en : this.stringEntrys) {
|
||||||
@@ -337,7 +413,7 @@ public abstract class AnyValue {
|
|||||||
|
|
||||||
public DefaultAnyValue setValue(String name, AnyValue value) {
|
public DefaultAnyValue setValue(String name, AnyValue value) {
|
||||||
if (name == null) return this;
|
if (name == null) return this;
|
||||||
if (getValue(name) == null) {
|
if (!existsValue(name)) {
|
||||||
this.addValue(name, value);
|
this.addValue(name, value);
|
||||||
} else {
|
} else {
|
||||||
for (Entry<DefaultAnyValue> en : this.anyEntrys) {
|
for (Entry<DefaultAnyValue> en : this.anyEntrys) {
|
||||||
@@ -419,6 +495,14 @@ public abstract class AnyValue {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean existsValue(String name) {
|
||||||
|
for (Entry<String> en : this.stringEntrys) {
|
||||||
|
if (predicate.test(en.name, name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -662,8 +746,15 @@ public abstract class AnyValue {
|
|||||||
parent = child;
|
parent = child;
|
||||||
} else { //数组或Map结构, []中间是数字开头的视为数组,其他视为map
|
} else { //数组或Map结构, []中间是数字开头的视为数组,其他视为map
|
||||||
String itemField = item.substring(0, pos); //[前面一部分
|
String itemField = item.substring(0, pos); //[前面一部分
|
||||||
String itemIndex = item.substring(pos + 1, item.indexOf(']'));
|
String keyOrIndex = item.substring(pos + 1, item.indexOf(']'));
|
||||||
if (!itemIndex.isEmpty() && itemIndex.charAt(0) >= '0' && itemIndex.charAt(0) <= '9') { //数组
|
int realIndex = -1;
|
||||||
|
if (!keyOrIndex.isEmpty() && keyOrIndex.charAt(0) >= '0' && keyOrIndex.charAt(0) <= '9') {
|
||||||
|
try {
|
||||||
|
realIndex = Integer.parseInt(keyOrIndex);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (realIndex >= 0) { //数组
|
||||||
String prefixKey = "";
|
String prefixKey = "";
|
||||||
for (int j = 0; j < i; j++) {
|
for (int j = 0; j < i; j++) {
|
||||||
prefixKey += keys[j] + ".";
|
prefixKey += keys[j] + ".";
|
||||||
@@ -684,7 +775,9 @@ public abstract class AnyValue {
|
|||||||
if (!keymap.containsKey(prefixKey2)) {
|
if (!keymap.containsKey(prefixKey2)) {
|
||||||
DefaultAnyValue vv = new DefaultAnyValue();
|
DefaultAnyValue vv = new DefaultAnyValue();
|
||||||
keymap.put(prefixKey2, vv);
|
keymap.put(prefixKey2, vv);
|
||||||
sortmap.put(Integer.parseInt(ks[ii].substring(ks[ii].indexOf('[') + 1, ks[ii].lastIndexOf(']'))), vv);
|
int aindex = Integer.parseInt(ks[ii].substring(ks[ii].indexOf('[') + 1, ks[ii].lastIndexOf(']')));
|
||||||
|
vv.parentArrayIndex = aindex;
|
||||||
|
sortmap.put(aindex, vv);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
prefixArray.putAll(keymap);
|
prefixArray.putAll(keymap);
|
||||||
@@ -699,11 +792,11 @@ public abstract class AnyValue {
|
|||||||
field = new DefaultAnyValue();
|
field = new DefaultAnyValue();
|
||||||
parent.addValue(itemField, field);
|
parent.addValue(itemField, field);
|
||||||
}
|
}
|
||||||
DefaultAnyValue index = (DefaultAnyValue) field.getAnyValue(itemIndex);
|
DefaultAnyValue index = (DefaultAnyValue) field.getAnyValue(keyOrIndex);
|
||||||
if (index == null) {
|
if (index == null) {
|
||||||
index = new DefaultAnyValue();
|
index = new DefaultAnyValue();
|
||||||
if (nameName != null) index.setValue(nameName, itemIndex);
|
if (nameName != null) index.setValue(nameName, keyOrIndex);
|
||||||
field.addValue(itemIndex, index);
|
field.addValue(keyOrIndex, index);
|
||||||
}
|
}
|
||||||
parent = index;
|
parent = index;
|
||||||
}
|
}
|
||||||
@@ -838,25 +931,46 @@ public abstract class AnyValue {
|
|||||||
/**
|
/**
|
||||||
* 当前AnyValue对象字符串化
|
* 当前AnyValue对象字符串化
|
||||||
*
|
*
|
||||||
* @param indent 缩进长度
|
* @param indent 缩进长度
|
||||||
|
* @param prefixFunc 扩展函数
|
||||||
*
|
*
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
public String toString(int indent) { //indent: 缩进长度
|
public String toString(int indent, BiFunction<AnyValue, String, CharSequence> prefixFunc) { //indent: 缩进长度
|
||||||
if (indent < 0) indent = 0;
|
if (indent < 0) indent = 0;
|
||||||
final String space = " ".repeat(indent);
|
final String space = " ".repeat(indent);
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("{\r\n");
|
sb.append("{\r\n");
|
||||||
|
if (prefixFunc != null) {
|
||||||
|
CharSequence v = prefixFunc.apply(this, space);
|
||||||
|
if (v != null) sb.append(v);
|
||||||
|
}
|
||||||
for (Entry<String> en : getStringEntrys()) {
|
for (Entry<String> en : getStringEntrys()) {
|
||||||
sb.append(space).append(" '").append(en.name).append("': '").append(en.value).append("',\r\n");
|
sb.append(space).append(" '").append(en.name).append("': '").append(en.value).append("',\r\n");
|
||||||
}
|
}
|
||||||
for (Entry<AnyValue> en : getAnyEntrys()) {
|
for (Entry<AnyValue> en : getAnyEntrys()) {
|
||||||
sb.append(space).append(" '").append(en.name).append("': ").append(en.value.toString(indent + 4)).append(",\r\n");
|
sb.append(space).append(" '").append(en.name).append("': ").append(en.value.toString(indent + 4, prefixFunc)).append(",\r\n");
|
||||||
}
|
}
|
||||||
sb.append(space).append('}');
|
sb.append(space).append('}');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制一份
|
||||||
|
*
|
||||||
|
* @return AnyValue
|
||||||
|
*/
|
||||||
|
public abstract AnyValue copy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将另一个对象合并过来
|
||||||
|
*
|
||||||
|
* @param node 代合并对象
|
||||||
|
*
|
||||||
|
* @return AnyValue
|
||||||
|
*/
|
||||||
|
public abstract AnyValue merge(AnyValue node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 回调子节点
|
* 回调子节点
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -34,46 +34,76 @@ public class AnyValuePropertiesTest {
|
|||||||
properties.put("redkale.mmm.node[20]", "n20");
|
properties.put("redkale.mmm.node[20]", "n20");
|
||||||
|
|
||||||
String result = "{\r\n"
|
String result = "{\r\n"
|
||||||
+ " 'redkale': '{\r\n"
|
+ " 'redkale': {\r\n"
|
||||||
+ " 'source': '{\r\n"
|
+ " 'source': {\r\n"
|
||||||
+ " 'my': '{\r\n"
|
+ " 'my': {\r\n"
|
||||||
+ " 'sss': 'my s',\r\n"
|
+ " 'sss': 'my s',\r\n"
|
||||||
+ " 'ttt': 'my t',\r\n"
|
+ " 'ttt': 'my t',\r\n"
|
||||||
+ " }',\r\n"
|
+ " },\r\n"
|
||||||
+ " 'you': '{\r\n"
|
+ " 'you': {\r\n"
|
||||||
+ " 'ttt': 'you t',\r\n"
|
+ " 'ttt': 'you t',\r\n"
|
||||||
+ " 'sss': 'you s',\r\n"
|
+ " 'sss': 'you s',\r\n"
|
||||||
+ " }',\r\n"
|
+ " },\r\n"
|
||||||
+ " }',\r\n"
|
+ " },\r\n"
|
||||||
+ " 'ddd': '{\r\n"
|
+ " 'ddd': {\r\n"
|
||||||
|
+ " $index: 0,\r\n"
|
||||||
+ " 'ww': 'ww 0',\r\n"
|
+ " 'ww': 'ww 0',\r\n"
|
||||||
+ " 'nn': 'nn 0',\r\n"
|
+ " 'nn': 'nn 0',\r\n"
|
||||||
+ " }',\r\n"
|
+ " },\r\n"
|
||||||
+ " 'ddd': '{\r\n"
|
+ " 'ddd': {\r\n"
|
||||||
|
+ " $index: 2,\r\n"
|
||||||
+ " 'ww': 'ww 2',\r\n"
|
+ " 'ww': 'ww 2',\r\n"
|
||||||
+ " 'nn': 'nn 2',\r\n"
|
+ " 'nn': 'nn 2',\r\n"
|
||||||
+ " }',\r\n"
|
+ " },\r\n"
|
||||||
+ " 'ddd': '{\r\n"
|
+ " 'ddd': {\r\n"
|
||||||
|
+ " $index: 10,\r\n"
|
||||||
+ " 'ww': 'ww 10',\r\n"
|
+ " 'ww': 'ww 10',\r\n"
|
||||||
+ " 'nn': 'nn 10',\r\n"
|
+ " 'nn': 'nn 10',\r\n"
|
||||||
+ " }',\r\n"
|
+ " },\r\n"
|
||||||
+ " 'mmm': '{\r\n"
|
+ " 'mmm': {\r\n"
|
||||||
+ " 'node': 'n0',\r\n"
|
+ " 'node': 'n0',\r\n"
|
||||||
+ " 'node': 'n5',\r\n"
|
+ " 'node': 'n5',\r\n"
|
||||||
+ " 'node': 'n20',\r\n"
|
+ " 'node': 'n20',\r\n"
|
||||||
+ " }',\r\n"
|
+ " },\r\n"
|
||||||
+ " 'bbb': '{\r\n"
|
+ " 'bbb': {\r\n"
|
||||||
+ " 'sss': 'value s',\r\n"
|
+ " 'sss': 'value s',\r\n"
|
||||||
+ " 'qqq': '{\r\n"
|
+ " 'qqq': {\r\n"
|
||||||
+ " 'rrr': 'value r',\r\n"
|
+ " 'rrr': 'value r',\r\n"
|
||||||
+ " }',\r\n"
|
+ " },\r\n"
|
||||||
+ " }',\r\n"
|
+ " },\r\n"
|
||||||
+ " 'aaa': '{\r\n"
|
+ " 'aaa': {\r\n"
|
||||||
+ " 'ppp': 'value p',\r\n"
|
+ " 'ppp': 'value p',\r\n"
|
||||||
+ " 'ooo': 'value o',\r\n"
|
+ " 'ooo': 'value o',\r\n"
|
||||||
+ " }',\r\n"
|
+ " },\r\n"
|
||||||
+ " }',\r\n"
|
+ " },\r\n"
|
||||||
+ "}";
|
+ "}";
|
||||||
Assertions.assertEquals(result, AnyValue.loadFromProperties(properties).toString());
|
Assertions.assertEquals(result, AnyValue.loadFromProperties(properties).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void run2() {
|
||||||
|
Properties prop = new Properties();
|
||||||
|
prop.put("redkale.name", "myname");
|
||||||
|
prop.put("redkale.node[3].id", "333");
|
||||||
|
prop.put("redkale.node[3].desc", "haha3");
|
||||||
|
prop.put("redkale.node[1].id", "111");
|
||||||
|
prop.put("redkale.node[1].desc", "haha1");
|
||||||
|
prop.put("redkale.node[2].id", "222");
|
||||||
|
prop.put("redkale.node[2].desc", "haha2");
|
||||||
|
|
||||||
|
AnyValue conf = AnyValue.loadFromProperties(prop);
|
||||||
|
//System.out.println(conf);
|
||||||
|
|
||||||
|
Properties prop2 = new Properties();
|
||||||
|
prop2.put("redkale.name", "myname too");
|
||||||
|
prop2.put("redkale.node[3].id", "999");
|
||||||
|
prop2.put("redkale.node[3].desc", "haha9");
|
||||||
|
prop2.put("redkale.node[4].id", "444");
|
||||||
|
prop2.put("redkale.node[4].desc", "haha4");
|
||||||
|
AnyValue conf2 = AnyValue.loadFromProperties(prop2);
|
||||||
|
//System.out.println(conf2);
|
||||||
|
|
||||||
|
//System.out.println(conf.copy().merge(conf2));
|
||||||
|
//System.out.println(conf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user