AnyValue增加copy和merge方法

This commit is contained in:
Redkale
2022-12-07 21:28:12 +08:00
parent c0c5cb7e93
commit 1972e6308c
2 changed files with 179 additions and 35 deletions

View File

@@ -54,6 +54,8 @@ public abstract class AnyValue {
private Entry<DefaultAnyValue>[] anyEntrys = new Entry[0];
private int parentArrayIndex = -1; //只可能被loadFromProperties方法赋值
/**
* 创建空的DefaultAnyValue对象
*
@@ -135,6 +137,76 @@ public abstract class AnyValue {
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对象 会去重, 没有的才增加
*
@@ -147,7 +219,7 @@ public abstract class AnyValue {
final Entry<String>[] strings = av.getStringEntrys();
if (strings == null) return this;
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;
}
@@ -311,7 +383,11 @@ public abstract class AnyValue {
@Override
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() {
@@ -322,7 +398,7 @@ public abstract class AnyValue {
public DefaultAnyValue setValue(String name, String value) {
if (name == null) return this;
if (getValue(name) == null) {
if (!existsValue(name)) {
this.addValue(name, value);
} else {
for (Entry<String> en : this.stringEntrys) {
@@ -337,7 +413,7 @@ public abstract class AnyValue {
public DefaultAnyValue setValue(String name, AnyValue value) {
if (name == null) return this;
if (getValue(name) == null) {
if (!existsValue(name)) {
this.addValue(name, value);
} else {
for (Entry<DefaultAnyValue> en : this.anyEntrys) {
@@ -419,6 +495,14 @@ public abstract class AnyValue {
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;
} else { //数组或Map结构, []中间是数字开头的视为数组其他视为map
String itemField = item.substring(0, pos); //[前面一部分
String itemIndex = item.substring(pos + 1, item.indexOf(']'));
if (!itemIndex.isEmpty() && itemIndex.charAt(0) >= '0' && itemIndex.charAt(0) <= '9') { //数组
String keyOrIndex = item.substring(pos + 1, item.indexOf(']'));
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 = "";
for (int j = 0; j < i; j++) {
prefixKey += keys[j] + ".";
@@ -684,7 +775,9 @@ public abstract class AnyValue {
if (!keymap.containsKey(prefixKey2)) {
DefaultAnyValue vv = new DefaultAnyValue();
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);
@@ -699,11 +792,11 @@ public abstract class AnyValue {
field = new DefaultAnyValue();
parent.addValue(itemField, field);
}
DefaultAnyValue index = (DefaultAnyValue) field.getAnyValue(itemIndex);
DefaultAnyValue index = (DefaultAnyValue) field.getAnyValue(keyOrIndex);
if (index == null) {
index = new DefaultAnyValue();
if (nameName != null) index.setValue(nameName, itemIndex);
field.addValue(itemIndex, index);
if (nameName != null) index.setValue(nameName, keyOrIndex);
field.addValue(keyOrIndex, index);
}
parent = index;
}
@@ -838,25 +931,46 @@ public abstract class AnyValue {
/**
* 当前AnyValue对象字符串化
*
* @param indent 缩进长度
* @param indent 缩进长度
* @param prefixFunc 扩展函数
*
* @return String
*/
public String toString(int indent) { //indent: 缩进长度
public String toString(int indent, BiFunction<AnyValue, String, CharSequence> prefixFunc) { //indent: 缩进长度
if (indent < 0) indent = 0;
final String space = " ".repeat(indent);
StringBuilder sb = new StringBuilder();
sb.append("{\r\n");
if (prefixFunc != null) {
CharSequence v = prefixFunc.apply(this, space);
if (v != null) sb.append(v);
}
for (Entry<String> en : getStringEntrys()) {
sb.append(space).append(" '").append(en.name).append("': '").append(en.value).append("',\r\n");
}
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('}');
return sb.toString();
}
/**
* 复制一份
*
* @return AnyValue
*/
public abstract AnyValue copy();
/**
* 将另一个对象合并过来
*
* @param node 代合并对象
*
* @return AnyValue
*/
public abstract AnyValue merge(AnyValue node);
/**
* 回调子节点
*

View File

@@ -34,46 +34,76 @@ public class AnyValuePropertiesTest {
properties.put("redkale.mmm.node[20]", "n20");
String result = "{\r\n"
+ " 'redkale': '{\r\n"
+ " 'source': '{\r\n"
+ " 'my': '{\r\n"
+ " 'redkale': {\r\n"
+ " 'source': {\r\n"
+ " 'my': {\r\n"
+ " 'sss': 'my s',\r\n"
+ " 'ttt': 'my t',\r\n"
+ " }',\r\n"
+ " 'you': '{\r\n"
+ " },\r\n"
+ " 'you': {\r\n"
+ " 'ttt': 'you t',\r\n"
+ " 'sss': 'you s',\r\n"
+ " }',\r\n"
+ " }',\r\n"
+ " 'ddd': '{\r\n"
+ " },\r\n"
+ " },\r\n"
+ " 'ddd': {\r\n"
+ " $index: 0,\r\n"
+ " 'ww': 'ww 0',\r\n"
+ " 'nn': 'nn 0',\r\n"
+ " }',\r\n"
+ " 'ddd': '{\r\n"
+ " },\r\n"
+ " 'ddd': {\r\n"
+ " $index: 2,\r\n"
+ " 'ww': 'ww 2',\r\n"
+ " 'nn': 'nn 2',\r\n"
+ " }',\r\n"
+ " 'ddd': '{\r\n"
+ " },\r\n"
+ " 'ddd': {\r\n"
+ " $index: 10,\r\n"
+ " 'ww': 'ww 10',\r\n"
+ " 'nn': 'nn 10',\r\n"
+ " }',\r\n"
+ " 'mmm': '{\r\n"
+ " },\r\n"
+ " 'mmm': {\r\n"
+ " 'node': 'n0',\r\n"
+ " 'node': 'n5',\r\n"
+ " 'node': 'n20',\r\n"
+ " }',\r\n"
+ " 'bbb': '{\r\n"
+ " },\r\n"
+ " 'bbb': {\r\n"
+ " 'sss': 'value s',\r\n"
+ " 'qqq': '{\r\n"
+ " 'qqq': {\r\n"
+ " 'rrr': 'value r',\r\n"
+ " }',\r\n"
+ " }',\r\n"
+ " 'aaa': '{\r\n"
+ " },\r\n"
+ " },\r\n"
+ " 'aaa': {\r\n"
+ " 'ppp': 'value p',\r\n"
+ " 'ooo': 'value o',\r\n"
+ " }',\r\n"
+ " }',\r\n"
+ " },\r\n"
+ " },\r\n"
+ "}";
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);
}
}