feat[storage]: support primitive int-object and long-object storage

This commit is contained in:
godotg
2023-03-24 22:54:44 +08:00
parent 02af867305
commit 951e0ce133
4 changed files with 244 additions and 41 deletions
@@ -131,8 +131,7 @@ public class StorageManager implements IStorageManager {
var clazz = definition.getClazz();
var resource = definition.getResource();
var fileExtName = FileUtils.fileExtName(resource.getFilename());
Storage<?, ?> storage = new Storage<>();
storage.init(resource.getInputStream(), definition.getClazz(), fileExtName);
Storage<?, ?> storage = Storage.parse(resource.getInputStream(), clazz, fileExtName);
storageMap.putIfAbsent(clazz, storage);
}
} catch (Exception e) {
@@ -30,34 +30,37 @@ import java.util.*;
*/
public class Storage<K, V> {
private Class<V> clazz;
// 当前配置表是否在当前项目中使用,没有被使用的会清楚data数据,以达到节省内存的目的
private boolean recycle = true;
private Map<K, V> dataMap = new HashMap<>();
// 非唯一索引
private Map<String, Map<Object, List<V>>> indexMap = new HashMap<>();
protected Map<String, Map<Object, List<V>>> indexMap = new HashMap<>();
// 唯一索引
private Map<String, Map<Object, V>> uniqueIndexMap = new HashMap<>();
protected Map<String, Map<Object, V>> uniqueIndexMap = new HashMap<>();
private IdDef idDef;
private Map<String, IndexDef> indexDefMap;
protected Class<?> clazz;
protected IdDef idDef;
protected Map<String, IndexDef> indexDefMap;
// 当前配置表是否在当前项目中使用,没有被使用的会清楚data数据,以达到节省内存的目的
protected boolean recycle = true;
public void init(InputStream inputStream, Class<?> resourceClazz, String suffix) {
public static Storage<?, ?> parse(InputStream inputStream, Class<?> resourceClazz, String suffix) {
try {
this.clazz = (Class<V>) resourceClazz;
idDef = IdDef.valueOf(resourceClazz);
indexDefMap = IndexDef.createResourceIndexes(resourceClazz);
Storage<?, ?> storage = new Storage<>();
storage.clazz = resourceClazz;
var idDef = IdDef.valueOf(resourceClazz);
storage.idDef = idDef;
storage.indexDefMap = IndexDef.createResourceIndexes(resourceClazz);
var list = ResourceInterpreter.read(inputStream, resourceClazz, suffix);
dataMap.clear();
indexMap.clear();
uniqueIndexMap.clear();
for (var object : list) {
put((V) object);
storage.put(object);
}
var idType = idDef.getField().getType();
if (idType == int.class || idType == Integer.class) {
return new StorageInt<>(storage);
} else if (idType == long.class || idType == Long.class) {
return new StorageLong<>(storage);
} else {
return storage;
}
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
@@ -66,6 +69,32 @@ public class Storage<K, V> {
}
}
public boolean contain(K key) {
return dataMap.containsKey(key);
}
public boolean contain(int key) {
return contain((K) Integer.valueOf(key));
}
public boolean contain(long key) {
return contain((K) Long.valueOf(key));
}
public V get(K id) {
V result = dataMap.get(id);
AssertionUtils.notNull(result, "The static resource represented as [id:{}] in the static resource [resource:{}] does not exist", id, clazz.getSimpleName());
return result;
}
public V get(int id) {
return get((K) Integer.valueOf(id));
}
public V get(long id) {
return get((K) Long.valueOf(id));
}
public void recycleStorage() {
recycle = true;
dataMap = null;
@@ -84,7 +113,7 @@ public class Storage<K, V> {
}
public Collection<V> getAll() {
return Collections.unmodifiableCollection(dataMap.values());
return dataMap.values();
}
public Map<K, V> getData() {
@@ -95,16 +124,6 @@ public class Storage<K, V> {
return idDef;
}
public boolean contain(K key) {
return dataMap.containsKey(key);
}
public V get(K id) {
V result = dataMap.get(id);
AssertionUtils.notNull(result, "The static resource represented as [id:{}] in the static resource [resource:{}] does not exist", id, clazz.getSimpleName());
return result;
}
public List<V> getIndex(String indexName, Object key) {
var indexValues = indexMap.get(indexName);
AssertionUtils.notNull(indexValues, "The index of [indexName:{}] does not exist in the static resource [resource:{}]", indexName, clazz.getSimpleName());
@@ -123,8 +142,11 @@ public class Storage<K, V> {
return value;
}
public int size() {
return dataMap.size();
}
private V put(V value) {
private V put(Object value) {
var key = (K) ReflectionUtils.getField(idDef.getField(), value);
if (key == null) {
@@ -136,7 +158,7 @@ public class Storage<K, V> {
}
// 添加资源
var result = dataMap.put(key, value);
var result = dataMap.put(key, (V) value);
// 添加索引
for (var def : indexDefMap.values()) {
@@ -145,20 +167,16 @@ public class Storage<K, V> {
var indexValue = ReflectionUtils.getField(def.getField(), value);
if (def.isUnique()) {// 唯一索引
var index = uniqueIndexMap.computeIfAbsent(indexKey, k -> new HashMap<>());
if (index.put(indexValue, value) != null) {
if (index.put(indexValue, (V) value) != null) {
throw new RuntimeException(StringUtils.format("Duplicate unique index [index:{}][value:{}] of static resource [class:{}]", indexKey, indexValue, clazz.getName()));
}
} else {// 不是唯一索引
var index = indexMap.computeIfAbsent(indexKey, k -> new HashMap<>());
var list = index.computeIfAbsent(indexValue, k -> new ArrayList<V>());
list.add(value);
list.add((V) value);
}
}
return result;
}
public int size() {
return dataMap.size();
}
}
@@ -0,0 +1,92 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.storage.model.vo;
import com.zfoo.protocol.util.AssertionUtils;
import io.netty.util.collection.IntObjectHashMap;
import java.util.*;
/**
* @author godotg
* @version 4.0
*/
public class StorageInt<K, V> extends Storage<K, V> {
private IntObjectHashMap<V> dataMap = new IntObjectHashMap<V>();
public StorageInt(Storage<K, V> storage) {
super.indexMap = storage.indexMap;
super.uniqueIndexMap = storage.uniqueIndexMap;
super.clazz = storage.clazz;
super.idDef = storage.idDef;
super.indexDefMap = storage.indexDefMap;
super.recycle = storage.recycle;
this.dataMap.putAll((Map<? extends Integer, ? extends V>) storage.getData());
}
@Override
public boolean contain(K key) {
return contain((int) key);
}
@Override
public boolean contain(int key) {
return dataMap.containsKey(key);
}
@Override
public boolean contain(long key) {
return contain((int) key);
}
@Override
public V get(K id) {
return get((int) id);
}
@Override
public V get(int id) {
V result = dataMap.get(id);
AssertionUtils.notNull(result, "The static resource represented as [id:{}] in the static resource [resource:{}] does not exist", id, clazz.getSimpleName());
return result;
}
@Override
public V get(long id) {
return get((int) id);
}
@Override
public int size() {
return dataMap.size();
}
@Override
public void recycleStorage() {
super.recycleStorage();
dataMap = null;
}
@Override
public Collection<V> getAll() {
return dataMap.values();
}
@Override
public Map<K, V> getData() {
return (Map<K, V>) Collections.unmodifiableMap(dataMap);
}
}
@@ -0,0 +1,94 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.storage.model.vo;
import com.zfoo.protocol.util.AssertionUtils;
import io.netty.util.collection.LongObjectHashMap;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
/**
* @author godotg
* @version 4.0
*/
public class StorageLong<K, V> extends Storage<K, V> {
private LongObjectHashMap<V> dataMap = new LongObjectHashMap<V>();
public StorageLong(Storage<K, V> storage) {
super.indexMap = storage.indexMap;
super.uniqueIndexMap = storage.uniqueIndexMap;
super.clazz = storage.clazz;
super.idDef = storage.idDef;
super.indexDefMap = storage.indexDefMap;
super.recycle = storage.recycle;
this.dataMap.putAll((Map<? extends Long, ? extends V>) storage.getData());
}
@Override
public boolean contain(K key) {
return contain((long) key);
}
@Override
public boolean contain(int key) {
return contain((long) key);
}
@Override
public boolean contain(long key) {
return dataMap.containsKey(key);
}
@Override
public V get(K id) {
return get((long) id);
}
@Override
public V get(int id) {
return get((long) id);
}
@Override
public V get(long id) {
V result = dataMap.get(id);
AssertionUtils.notNull(result, "The static resource represented as [id:{}] in the static resource [resource:{}] does not exist", id, clazz.getSimpleName());
return result;
}
@Override
public int size() {
return dataMap.size();
}
@Override
public void recycleStorage() {
super.recycleStorage();
dataMap = null;
}
@Override
public Collection<V> getAll() {
return dataMap.values();
}
@Override
public Map<K, V> getData() {
return (Map<K, V>) Collections.unmodifiableMap(dataMap);
}
}