package org.vertexium.accumulo.iterator.util;
import org.apache.hadoop.io.Text;
import org.vertexium.accumulo.iterator.model.EdgeInfo;
import org.vertexium.accumulo.iterator.model.EdgesWithEdgeInfo;
import org.vertexium.accumulo.iterator.model.PropertyMetadata;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;
public class DataOutputStreamUtils {
public static final Charset CHARSET = Charset.forName("utf8");
public static final byte EDGE_LABEL_ONLY_MARKER = 1;
public static final byte EDGE_LABEL_WITH_REFS_MARKER = 2;
public static void encodeTextList(DataOutputStream out, Collection<Text> texts) throws IOException {
if (texts == null) {
out.writeInt(-1);
return;
}
out.writeInt(texts.size());
for (Text text : texts) {
encodeText(out, text);
}
}
public static void encodeStringSet(DataOutputStream out, Set<String> set) throws IOException {
if (set == null) {
out.writeInt(-1);
return;
}
out.writeInt(set.size());
for (String item : set) {
encodeString(out, item);
}
}
public static void encodeText(DataOutputStream out, Text text) throws IOException {
if (text == null) {
out.writeInt(-1);
return;
}
out.writeInt(text.getLength());
out.write(text.getBytes(), 0, text.getLength());
}
public static void encodeByteArray(DataOutputStream out, byte[] bytes) throws IOException {
if (bytes == null) {
out.writeInt(-1);
return;
}
out.writeInt(bytes.length);
out.write(bytes);
}
public static void encodeString(DataOutputStream out, String text) throws IOException {
if (text == null) {
out.writeInt(-1);
return;
}
byte[] bytes = text.getBytes(CHARSET);
out.writeInt(bytes.length);
out.write(bytes, 0, bytes.length);
}
public static void encodePropertyMetadata(DataOutputStream out, PropertyMetadata metadata) throws IOException {
if (metadata == null) {
out.writeInt(0);
return;
}
out.writeInt(metadata.entries.size());
for (Map.Entry<String, PropertyMetadata.Entry> propertyMetadata : metadata.entries.entrySet()) {
encodePropertyMetadataEntry(out, propertyMetadata.getValue());
}
}
public static void encodePropertyMetadataEntry(DataOutputStream out, PropertyMetadata.Entry metadataEntry) throws IOException {
encodeString(out, metadataEntry.metadataKey);
encodeString(out, metadataEntry.metadataVisibility);
out.writeInt(metadataEntry.value.length);
out.write(metadataEntry.value);
}
public static void encodeEdges(DataOutputStream out, EdgesWithEdgeInfo edges, boolean edgeLabelsOnly) throws IOException {
out.write(edgeLabelsOnly ? EDGE_LABEL_ONLY_MARKER : EDGE_LABEL_WITH_REFS_MARKER);
Map<ByteArrayWrapper, List<Map.Entry<Text, EdgeInfo>>> edgesByLabels = getEdgesByLabel(edges);
out.writeInt(edgesByLabels.size());
for (Map.Entry<ByteArrayWrapper, List<Map.Entry<Text, EdgeInfo>>> entry : edgesByLabels.entrySet()) {
encodeByteArray(out, entry.getKey().getData());
out.writeInt(entry.getValue().size());
if (!edgeLabelsOnly) {
for (Map.Entry<Text, EdgeInfo> edgeEntry : entry.getValue()) {
encodeText(out, edgeEntry.getKey());
out.writeLong(edgeEntry.getValue().getTimestamp());
encodeString(out, edgeEntry.getValue().getVertexId());
}
}
}
}
private static Map<ByteArrayWrapper, List<Map.Entry<Text, EdgeInfo>>> getEdgesByLabel(EdgesWithEdgeInfo edges) throws IOException {
Map<ByteArrayWrapper, List<Map.Entry<Text, EdgeInfo>>> edgesByLabels = new HashMap<>();
for (Map.Entry<Text, EdgeInfo> edgeEntry : edges.getEntries()) {
ByteArrayWrapper label = new ByteArrayWrapper(edgeEntry.getValue().getLabelBytes());
List<Map.Entry<Text, EdgeInfo>> edgesByLabel = edgesByLabels.get(label);
if (edgesByLabel == null) {
edgesByLabel = new ArrayList<>();
edgesByLabels.put(label, edgesByLabel);
}
edgesByLabel.add(edgeEntry);
}
return edgesByLabels;
}
public static void encodeSetOfStrings(DataOutputStream out, Set<String> strings) throws IOException {
out.writeInt(strings.size());
for (String string : strings) {
encodeString(out, string);
}
}
}