Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.weavechain.core.data.Records Maven / Gradle / Ivy
package com.weavechain.core.data;
import com.google.gson.*;
import com.weavechain.core.encoding.ContentEncoder;
import com.weavechain.core.encoding.Utils;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.*;
@Getter
@NoArgsConstructor
public class Records {
static final Logger logger = LoggerFactory.getLogger(Records.class);
public String table;
private List> items;
@Setter
private transient String serialization;
@Setter
private transient String encoding;
@Setter
private List integrity = null;
public Records(String table, List> items, String serialization, String encoding) {
this.table = table;
this.items = items;
this.serialization = serialization;
this.encoding = encoding;
}
public static class IntegrityPair {
/** A Records object can contain merged data from many parts, where all parts have their signature
* A Records object holds an ordered list of IntegrityPairs (ordered by intervalStart)
* Each IntegrityPair contains the signature for interval
* Records.items.get(intervalStart_current) -> Records.items.get(intervalStart_next - 1) */
private final Integer intervalStart;
private final Map sig = new TreeMap<>();
public int getIntervalStart() {
return intervalStart != null ? intervalStart : 0;
}
public Map getSignature() {
return sig;
}
public IntegrityPair(int intervalStart, Map sig) {
this.intervalStart = intervalStart;
this.sig.putAll(sig);
}
}
public static Object getRecordId(List item, DataLayout layout) {
//TODO: Review, we need to unify with getLongRecordId and keep dual support for string ids (with limited functionality when hashing to smart contracts)
Integer idx = layout.getIdColumnIndex();
try {
if (idx != null) {
return item.size() > idx ? ConvertUtils.convertToLong(item.get(idx)) : null;
} else {
Integer idxTs = layout.getTimestampColumnIndex();
return idxTs != null && item.size() > idxTs ? ConvertUtils.convertToLong(item.get(idxTs)) : null;
}
} catch (Exception e) {
if (idx != null) {
return item.size() > idx ? item.get(idx) : null;
} else {
Integer idxTs = layout.getTimestampColumnIndex();
return idxTs != null && item.size() > idxTs ? item.get(idxTs) : null;
}
}
}
public static Long getLongRecordId(List item, DataLayout layout) {
//TODO: Review, we need to unify with getRecordId and keep dual support for string ids (with limited functionality when hashing to smart contracts)
Integer idx = layout.getIdColumnIndex();
if (idx != null) {
return item.size() > idx ? ConvertUtils.convertToLong(item.get(idx)) : null;
} else {
Integer idxTs = layout.getTimestampColumnIndex();
return idxTs != null && item.size() > idxTs ? ConvertUtils.convertToLong(item.get(idxTs)) : null;
}
}
public static void standardize(List record, DataLayout layout) {
//make sure the write and read order and representation are the same when serializing
for (int i = 0; i < layout.size(); i++) {
if (i < record.size()) {
Object conv = ConvertUtils.convert(record.get(i), layout.getType(i));
if (conv instanceof Double && conv.toString().endsWith(".0")) {
conv = ((Double)conv).longValue(); //remove ending .0 from serializations
}
record.set(i, conv);
} else {
record.add(null);
}
}
if (layout.getSignatureColumnIndex() != null && "".equals(record.get(layout.getSignatureColumnIndex()))) {
record.set(layout.getSignatureColumnIndex(), null);
}
}
public static List standardizeWithoutOwner(List record, DataLayout layout) {
List result = new ArrayList<>();
for (int i = 0; i < layout.size(); i++) {
if (layout.getOwnerColumnIndex() != null && layout.getOwnerColumnIndex() == i
|| layout.getSignatureColumnIndex() != null && layout.getSignatureColumnIndex() == i
|| layout.getSourceIpColumnIndex() != null && layout.getSourceIpColumnIndex() == i
|| layout.getEncryptSaltColumnIndex() != null && layout.getEncryptSaltColumnIndex() == i
) {
while (result.size() <= i) {
result.add(null);
}
} else {
Object conv;
try {
conv = ConvertUtils.convert(record.get(i), layout.getType(i));
if (conv instanceof Double && conv.toString().endsWith(".0")) {
conv = ((Double) conv).longValue(); //remove ending .0 from serializations
}
} catch (Exception e) {
logger.trace("Failed converting, fallback to original value", e);
conv = record.get(i) != null ? record.get(i).toString() : null;
}
if (i < result.size()) {
result.add(i, conv);
} else {
while (result.size() < i) {
result.add(null);
}
result.add(conv);
}
}
}
return result;
}
@SuppressWarnings("unchecked")
public static List recordToList(Object record, DataLayout layout) {
if (record instanceof Map) {
List result = new ArrayList<>();
Map item = (Map)record;
for (int i = 0; i < layout.size(); i++) {
result.add(item.get(layout.getColumn(i)));
}
return result;
} else {
return (List)record;
}
}
public static Records of(String table, List... items) {
return new Records(table, Arrays.asList(items), null, null);
}
public static Records of(String table, List> items) {
return new Records(table, items, null, null);
}
public static Records ofMap(String table, List columns, DataLayout layout, Object... items) {
return new Records(table, buildItems(columns, layout, items), null, null);
}
public static Records ofRow(String table, DataLayout layout, Object item) {
return new Records(table, buildItems(layout, Collections.singletonList(item)), null, null);
}
public static Records ofRows(String table, DataLayout layout, List> items) {
return new Records(table, buildItems(layout, items), null, null);
}
public static List> buildItems(DataLayout layout, Object... items) {
return buildItems(null, layout, items);
}
@SuppressWarnings("unchecked")
public static List> buildItems(List columns, DataLayout layout, Object... items) {
List> result = new ArrayList<>();
for (Object data : items) {
if (data == null) {
continue;
}
Set colsWithFailure = new HashSet<>();
for (Object item : (List)data) {
if (item instanceof List) {
result.add((List) item);
} else if (item instanceof Map) {
Map it = (Map) item;
DataLayout tableLayout = layout != null ? layout : DataLayout.DEFAULT;
List row = new ArrayList<>();
for (int i = 0; i < tableLayout.size(); i++) {
String column = tableLayout.getColumn(i);
if (columns != null && columns.size() > 0 && !columns.contains(column)) {
continue;
}
DataType type = tableLayout.getType(i);
Object value = it.get(column);
try {
row.add(ConvertUtils.convert(value, type));
} catch (Exception e) {
if (!colsWithFailure.contains(column)) {
logger.warn("Failed converting value column " + column + " to " + type.name() + ", using original");
colsWithFailure.add(column);
}
row.add(value);
}
}
result.add(row);
} else {
logger.error("Unhandled record type");
}
}
}
return result;
}
@SuppressWarnings("unchecked")
public static Records fromObject(Object records, ContentEncoder encoder, DataLayout layout) {
if (records instanceof String) {
try {
return encoder.decode(records.toString(), layout);
} catch (IOException e) {
logger.error("Failed parsing records", e);
return null;
}
} else if (records instanceof Map) {
Map data = (Map)records;
return new Records(
ConvertUtils.convertToString(data.get("table")),
(List)data.get("items"),
null,
null
);
} else {
return null;
}
}
public void applyTimestamp(Long now, DataLayout layout, boolean keepIfExists) {
Integer idx = layout.getTimestampColumnIndex();
if (idx != null) {
for (List record : items) {
int size = record.size();
if (idx < size && (!keepIfExists || record.get(idx) == null)) {
if (record.get(idx) == null) {
record.set(idx, now);
}
} else if (idx >= size) {
for (int j = 0; j < idx - size; j++) {
record.add(null);
}
record.add(now);
}
}
}
}
public String toJson(DataLayout layout) {
if (items != null) {
List> data = new ArrayList<>();
for (List it : items) {
Map row = new LinkedHashMap<>();
for (int i = 0; i < layout.size(); i++) {
row.put(layout.getColumn(i), i < it.size() ? it.get(i) : null);
}
data.add(row);
}
return Utils.getGson().toJson(data);
} else {
return null;
}
}
public static class Serializer implements JsonSerializer {
public JsonElement serialize(Records data, Type typeOfSrc, JsonSerializationContext context) {
JsonObject element = new JsonObject();
element.add("table", new JsonPrimitive(data.getTable()));
element.add("items", Utils.getGson().toJsonTree(data.getItems()).getAsJsonArray());
return element;
}
}
}