blob: ea35bc8a27950e8f8d4c539f87773dbd602fd595 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You 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 org.apache.hugegraph.backend.serializer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.backend.BackendException;
import org.apache.hugegraph.backend.id.EdgeId;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.id.IdGenerator;
import org.apache.hugegraph.backend.id.IdUtil;
import org.apache.hugegraph.backend.query.Condition;
import org.apache.hugegraph.backend.query.ConditionQuery;
import org.apache.hugegraph.backend.query.Query;
import org.apache.hugegraph.backend.store.BackendEntry;
import org.apache.hugegraph.type.HugeType;
import org.apache.hugegraph.util.JsonUtil;
import org.apache.hugegraph.config.HugeConfig;
import org.apache.hugegraph.schema.EdgeLabel;
import org.apache.hugegraph.schema.IndexLabel;
import org.apache.hugegraph.schema.PropertyKey;
import org.apache.hugegraph.schema.SchemaElement;
import org.apache.hugegraph.schema.SchemaLabel;
import org.apache.hugegraph.schema.VertexLabel;
import org.apache.hugegraph.structure.HugeEdge;
import org.apache.hugegraph.structure.HugeEdgeProperty;
import org.apache.hugegraph.structure.HugeElement;
import org.apache.hugegraph.structure.HugeIndex;
import org.apache.hugegraph.structure.HugeProperty;
import org.apache.hugegraph.structure.HugeVertex;
import org.apache.hugegraph.structure.HugeVertexProperty;
import org.apache.hugegraph.type.define.AggregateType;
import org.apache.hugegraph.type.define.Cardinality;
import org.apache.hugegraph.type.define.DataType;
import org.apache.hugegraph.type.define.Directions;
import org.apache.hugegraph.type.define.Frequency;
import org.apache.hugegraph.type.define.HugeKeys;
import org.apache.hugegraph.type.define.IdStrategy;
import org.apache.hugegraph.type.define.IndexType;
import org.apache.hugegraph.type.define.SchemaStatus;
import org.apache.hugegraph.type.define.SerialEnum;
import org.apache.hugegraph.type.define.WriteType;
import org.apache.hugegraph.util.E;
public abstract class TableSerializer extends AbstractSerializer {
public TableSerializer(HugeConfig config) {
super(config);
}
@Override
public TableBackendEntry newBackendEntry(HugeType type, Id id) {
return new TableBackendEntry(type, id);
}
protected TableBackendEntry newBackendEntry(HugeElement e) {
return newBackendEntry(e.type(), e.id());
}
protected TableBackendEntry newBackendEntry(SchemaElement e) {
return newBackendEntry(e.type(), e.id());
}
protected TableBackendEntry newBackendEntry(HugeIndex index) {
return newBackendEntry(index.type(), index.id());
}
protected abstract TableBackendEntry newBackendEntry(TableBackendEntry.Row row);
@Override
protected abstract TableBackendEntry convertEntry(BackendEntry backendEntry);
protected void formatProperty(HugeProperty<?> property,
TableBackendEntry.Row row) {
long pkid = property.propertyKey().id().asLong();
row.column(HugeKeys.PROPERTIES, pkid, this.writeProperty(property));
}
protected void parseProperty(Id key, Object colValue, HugeElement owner) {
// Get PropertyKey by PropertyKey id
PropertyKey pkey = owner.graph().propertyKey(key);
// Parse value
Object value = this.readProperty(pkey, colValue);
// Set properties of vertex/edge
if (pkey.cardinality() == Cardinality.SINGLE) {
owner.addProperty(pkey, value);
} else {
if (!(value instanceof Collection)) {
throw new BackendException(
"Invalid value of non-single property: %s", value);
}
owner.addProperty(pkey, value);
}
}
protected Object writeProperty(HugeProperty<?> property) {
return this.writeProperty(property.propertyKey(), property.value());
}
protected Object writeProperty(PropertyKey propertyKey, Object value) {
return JsonUtil.toJson(value);
}
@SuppressWarnings("unchecked")
protected <T> T readProperty(PropertyKey pkey, Object value) {
Class<T> clazz = (Class<T>) pkey.implementClazz();
T result = JsonUtil.fromJson(value.toString(), clazz);
if (pkey.cardinality() != Cardinality.SINGLE) {
Collection<?> values = (Collection<?>) result;
List<Object> newValues = new ArrayList<>(values.size());
for (Object v : values) {
newValues.add(JsonUtil.castNumber(v, pkey.dataType().clazz()));
}
result = (T) newValues;
}
return result;
}
protected TableBackendEntry.Row formatEdge(HugeEdge edge) {
EdgeId id = edge.idWithDirection();
TableBackendEntry.Row row = new TableBackendEntry.Row(edge.type(), id);
if (edge.hasTtl()) {
row.ttl(edge.ttl());
row.column(HugeKeys.EXPIRED_TIME, edge.expiredTime());
}
// Id: ownerVertex + direction + edge-label + sortValues + otherVertex
row.column(HugeKeys.OWNER_VERTEX, this.writeId(id.ownerVertexId()));
row.column(HugeKeys.DIRECTION, id.directionCode());
row.column(HugeKeys.LABEL, id.edgeLabelId().asLong());
row.column(HugeKeys.SORT_VALUES, id.sortValues());
row.column(HugeKeys.OTHER_VERTEX, this.writeId(id.otherVertexId()));
this.formatProperties(edge, row);
return row;
}
/**
* Parse an edge from a entry row
* @param row edge entry
* @param vertex null or the source vertex
* @param graph the HugeGraph context object
* @return the source vertex
*/
protected HugeEdge parseEdge(TableBackendEntry.Row row,
HugeVertex vertex, HugeGraph graph) {
Object ownerVertexId = row.column(HugeKeys.OWNER_VERTEX);
Number dir = row.column(HugeKeys.DIRECTION);
boolean direction = EdgeId.isOutDirectionFromCode(dir.byteValue());
Number label = row.column(HugeKeys.LABEL);
String sortValues = row.column(HugeKeys.SORT_VALUES);
Object otherVertexId = row.column(HugeKeys.OTHER_VERTEX);
Number expiredTime = row.column(HugeKeys.EXPIRED_TIME);
if (vertex == null) {
Id ownerId = this.readId(ownerVertexId);
vertex = new HugeVertex(graph, ownerId, VertexLabel.NONE);
}
EdgeLabel edgeLabel = graph.edgeLabelOrNone(this.toId(label));
Id otherId = this.readId(otherVertexId);
// Construct edge
HugeEdge edge = HugeEdge.constructEdge(vertex, direction, edgeLabel,
sortValues, otherId);
// Parse edge properties
this.parseProperties(edge, row);
// The expired time is null when the edge is non-ttl
long expired = edge.hasTtl() ? expiredTime.longValue() : 0L;
edge.expiredTime(expired);
return edge;
}
@Override
public BackendEntry writeVertex(HugeVertex vertex) {
if (vertex.olap()) {
return this.writeOlapVertex(vertex);
}
TableBackendEntry entry = newBackendEntry(vertex);
if (vertex.hasTtl()) {
entry.ttl(vertex.ttl());
entry.column(HugeKeys.EXPIRED_TIME, vertex.expiredTime());
}
entry.column(HugeKeys.ID, this.writeId(vertex.id()));
entry.column(HugeKeys.LABEL, vertex.schemaLabel().id().asLong());
// Add all properties of a Vertex
this.formatProperties(vertex, entry.row());
return entry;
}
@Override
public BackendEntry writeVertexProperty(HugeVertexProperty<?> prop) {
HugeVertex vertex = prop.element();
TableBackendEntry entry = newBackendEntry(vertex);
if (vertex.hasTtl()) {
entry.ttl(vertex.ttl());
entry.column(HugeKeys.EXPIRED_TIME, vertex.expiredTime());
}
entry.subId(IdGenerator.of(prop.key()));
entry.column(HugeKeys.ID, this.writeId(vertex.id()));
entry.column(HugeKeys.LABEL, vertex.schemaLabel().id().asLong());
this.formatProperty(prop, entry.row());
return entry;
}
@Override
public HugeVertex readVertex(HugeGraph graph, BackendEntry backendEntry) {
E.checkNotNull(graph, "serializer graph");
if (backendEntry == null) {
return null;
}
TableBackendEntry entry = this.convertEntry(backendEntry);
assert entry.type().isVertex();
Id id = this.readId(entry.column(HugeKeys.ID));
Number label = entry.column(HugeKeys.LABEL);
Number expiredTime = entry.column(HugeKeys.EXPIRED_TIME);
VertexLabel vertexLabel = VertexLabel.NONE;
if (label != null) {
vertexLabel = graph.vertexLabelOrNone(this.toId(label));
}
HugeVertex vertex = new HugeVertex(graph, id, vertexLabel);
// Parse all properties of a Vertex
this.parseProperties(vertex, entry.row());
// Parse all edges of a Vertex
for (TableBackendEntry.Row edge : entry.subRows()) {
this.parseEdge(edge, vertex, graph);
}
// The expired time is null when this is fake vertex of edge or non-ttl
if (expiredTime != null) {
vertex.expiredTime(expiredTime.longValue());
}
return vertex;
}
@Override
public BackendEntry writeEdge(HugeEdge edge) {
return newBackendEntry(this.formatEdge(edge));
}
@Override
public BackendEntry writeEdgeProperty(HugeEdgeProperty<?> prop) {
HugeEdge edge = prop.element();
EdgeId id = edge.idWithDirection();
TableBackendEntry.Row row = new TableBackendEntry.Row(edge.type(), id);
if (edge.hasTtl()) {
row.ttl(edge.ttl());
row.column(HugeKeys.EXPIRED_TIME, edge.expiredTime());
}
// Id: ownerVertex + direction + edge-label + sortValues + otherVertex
row.column(HugeKeys.OWNER_VERTEX, this.writeId(id.ownerVertexId()));
row.column(HugeKeys.DIRECTION, id.directionCode());
row.column(HugeKeys.LABEL, id.edgeLabelId().asLong());
row.column(HugeKeys.SORT_VALUES, id.sortValues());
row.column(HugeKeys.OTHER_VERTEX, this.writeId(id.otherVertexId()));
// Format edge property
this.formatProperty(prop, row);
TableBackendEntry entry = newBackendEntry(row);
entry.subId(IdGenerator.of(prop.key()));
return entry;
}
@Override
public HugeEdge readEdge(HugeGraph graph, BackendEntry backendEntry) {
E.checkNotNull(graph, "serializer graph");
if (backendEntry == null) {
return null;
}
TableBackendEntry entry = this.convertEntry(backendEntry);
return this.parseEdge(entry.row(), null, graph);
}
@Override
public BackendEntry writeIndex(HugeIndex index) {
TableBackendEntry entry = newBackendEntry(index);
/*
* When field-values is null and elementIds size is 0, it is
* meaningful for deletion of index data in secondary/range index.
*/
if (index.fieldValues() == null && index.elementIds().size() == 0) {
entry.column(HugeKeys.INDEX_LABEL_ID, index.indexLabel().longId());
} else {
entry.column(HugeKeys.FIELD_VALUES, index.fieldValues());
entry.column(HugeKeys.INDEX_LABEL_ID, index.indexLabel().longId());
entry.column(HugeKeys.ELEMENT_IDS, this.writeId(index.elementId()));
entry.subId(index.elementId());
if (index.hasTtl()) {
entry.ttl(index.ttl());
entry.column(HugeKeys.EXPIRED_TIME, index.expiredTime());
}
}
return entry;
}
@Override
public HugeIndex readIndex(HugeGraph graph, ConditionQuery query,
BackendEntry backendEntry) {
E.checkNotNull(graph, "serializer graph");
if (backendEntry == null) {
return null;
}
TableBackendEntry entry = this.convertEntry(backendEntry);
Object indexValues = entry.column(HugeKeys.FIELD_VALUES);
Number indexLabelId = entry.column(HugeKeys.INDEX_LABEL_ID);
Set<Object> elemIds = this.parseIndexElemIds(entry);
Number expiredTime = entry.column(HugeKeys.EXPIRED_TIME);
IndexLabel indexLabel = graph.indexLabel(this.toId(indexLabelId));
HugeIndex index = new HugeIndex(graph, indexLabel);
index.fieldValues(indexValues);
long expired = index.hasTtl() ? expiredTime.longValue() : 0L;
for (Object elemId : elemIds) {
index.elementIds(this.readId(elemId), expired);
}
return index;
}
@Override
public BackendEntry writeId(HugeType type, Id id) {
return newBackendEntry(type, id);
}
@Override
protected Id writeQueryId(HugeType type, Id id) {
if (type.isEdge()) {
if (!(id instanceof EdgeId)) {
id = EdgeId.parse(id.asString());
}
} else if (type.isGraph()) {
id = IdGenerator.of(this.writeId(id));
}
return id;
}
@Override
protected Query writeQueryEdgeCondition(Query query) {
query = this.writeQueryCondition(query);
return query.idsSize() == 0 ? query : null;
}
@Override
protected Query writeQueryCondition(Query query) {
ConditionQuery result = (ConditionQuery) query;
// No user-prop when serialize
assert result.allSysprop();
for (Condition.Relation r : result.relations()) {
if (!r.value().equals(r.serialValue())) {
// Has been serialized before (maybe share a query multi times)
continue;
}
HugeKeys key = (HugeKeys) r.key();
if (r.relation() == Condition.RelationType.IN) {
E.checkArgument(r.value() instanceof List,
"Expect list value for IN condition: %s", r);
List<?> values = (List<?>) r.value();
List<Object> serializedValues = new ArrayList<>(values.size());
for (Object v : values) {
serializedValues.add(this.serializeValue(key, v));
}
r.serialValue(serializedValues);
} else if (r.relation() == Condition.RelationType.CONTAINS_VALUE &&
query.resultType().isGraph()) {
r.serialValue(this.writeProperty(null, r.value()));
} else {
r.serialValue(this.serializeValue(key, r.value()));
}
}
return result;
}
@Override
public BackendEntry writeVertexLabel(VertexLabel vertexLabel) {
TableBackendEntry entry = newBackendEntry(vertexLabel);
entry.column(HugeKeys.ID, vertexLabel.id().asLong());
entry.column(HugeKeys.NAME, vertexLabel.name());
entry.column(HugeKeys.ID_STRATEGY, vertexLabel.idStrategy().code());
entry.column(HugeKeys.PROPERTIES,
this.toLongSet(vertexLabel.properties()));
entry.column(HugeKeys.PRIMARY_KEYS,
this.toLongList(vertexLabel.primaryKeys()));
entry.column(HugeKeys.NULLABLE_KEYS,
this.toLongSet(vertexLabel.nullableKeys()));
entry.column(HugeKeys.INDEX_LABELS,
this.toLongSet(vertexLabel.indexLabels()));
this.writeEnableLabelIndex(vertexLabel, entry);
this.writeUserdata(vertexLabel, entry);
entry.column(HugeKeys.STATUS, vertexLabel.status().code());
entry.column(HugeKeys.TTL, vertexLabel.ttl());
entry.column(HugeKeys.TTL_START_TIME,
vertexLabel.ttlStartTime().asLong());
return entry;
}
@Override
public BackendEntry writeEdgeLabel(EdgeLabel edgeLabel) {
TableBackendEntry entry = newBackendEntry(edgeLabel);
entry.column(HugeKeys.ID, edgeLabel.id().asLong());
entry.column(HugeKeys.NAME, edgeLabel.name());
entry.column(HugeKeys.FREQUENCY, edgeLabel.frequency().code());
entry.column(HugeKeys.SOURCE_LABEL, edgeLabel.sourceLabel().asLong());
entry.column(HugeKeys.TARGET_LABEL, edgeLabel.targetLabel().asLong());
entry.column(HugeKeys.PROPERTIES,
this.toLongSet(edgeLabel.properties()));
entry.column(HugeKeys.SORT_KEYS,
this.toLongList(edgeLabel.sortKeys()));
entry.column(HugeKeys.NULLABLE_KEYS,
this.toLongSet(edgeLabel.nullableKeys()));
entry.column(HugeKeys.INDEX_LABELS,
this.toLongSet(edgeLabel.indexLabels()));
this.writeEnableLabelIndex(edgeLabel, entry);
this.writeUserdata(edgeLabel, entry);
entry.column(HugeKeys.STATUS, edgeLabel.status().code());
entry.column(HugeKeys.TTL, edgeLabel.ttl());
entry.column(HugeKeys.TTL_START_TIME,
edgeLabel.ttlStartTime().asLong());
return entry;
}
@Override
public BackendEntry writePropertyKey(PropertyKey propertyKey) {
TableBackendEntry entry = newBackendEntry(propertyKey);
entry.column(HugeKeys.ID, propertyKey.id().asLong());
entry.column(HugeKeys.NAME, propertyKey.name());
entry.column(HugeKeys.DATA_TYPE, propertyKey.dataType().code());
entry.column(HugeKeys.CARDINALITY, propertyKey.cardinality().code());
entry.column(HugeKeys.AGGREGATE_TYPE,
propertyKey.aggregateType().code());
entry.column(HugeKeys.WRITE_TYPE,
propertyKey.writeType().code());
entry.column(HugeKeys.PROPERTIES,
this.toLongSet(propertyKey.properties()));
this.writeUserdata(propertyKey, entry);
entry.column(HugeKeys.STATUS, propertyKey.status().code());
return entry;
}
@Override
public VertexLabel readVertexLabel(HugeGraph graph,
BackendEntry backendEntry) {
if (backendEntry == null) {
return null;
}
TableBackendEntry entry = this.convertEntry(backendEntry);
Number id = schemaColumn(entry, HugeKeys.ID);
String name = schemaColumn(entry, HugeKeys.NAME);
IdStrategy idStrategy = schemaEnum(entry, HugeKeys.ID_STRATEGY,
IdStrategy.class);
Object properties = schemaColumn(entry, HugeKeys.PROPERTIES);
Object primaryKeys = schemaColumn(entry, HugeKeys.PRIMARY_KEYS);
Object nullableKeys = schemaColumn(entry, HugeKeys.NULLABLE_KEYS);
Object indexLabels = schemaColumn(entry, HugeKeys.INDEX_LABELS);
SchemaStatus status = schemaEnum(entry, HugeKeys.STATUS,
SchemaStatus.class);
Number ttl = schemaColumn(entry, HugeKeys.TTL);
Number ttlStartTime = schemaColumn(entry, HugeKeys.TTL_START_TIME);
VertexLabel vertexLabel = new VertexLabel(graph, this.toId(id), name);
vertexLabel.idStrategy(idStrategy);
vertexLabel.properties(this.toIdArray(properties));
vertexLabel.primaryKeys(this.toIdArray(primaryKeys));
vertexLabel.nullableKeys(this.toIdArray(nullableKeys));
vertexLabel.addIndexLabels(this.toIdArray(indexLabels));
vertexLabel.status(status);
vertexLabel.ttl(ttl.longValue());
vertexLabel.ttlStartTime(this.toId(ttlStartTime));
this.readEnableLabelIndex(vertexLabel, entry);
this.readUserdata(vertexLabel, entry);
return vertexLabel;
}
@Override
public EdgeLabel readEdgeLabel(HugeGraph graph, BackendEntry backendEntry) {
if (backendEntry == null) {
return null;
}
TableBackendEntry entry = this.convertEntry(backendEntry);
Number id = schemaColumn(entry, HugeKeys.ID);
String name = schemaColumn(entry, HugeKeys.NAME);
Frequency frequency = schemaEnum(entry, HugeKeys.FREQUENCY,
Frequency.class);
Number sourceLabel = schemaColumn(entry, HugeKeys.SOURCE_LABEL);
Number targetLabel = schemaColumn(entry, HugeKeys.TARGET_LABEL);
Object sortKeys = schemaColumn(entry, HugeKeys.SORT_KEYS);
Object nullableKeys = schemaColumn(entry, HugeKeys.NULLABLE_KEYS);
Object properties = schemaColumn(entry, HugeKeys.PROPERTIES);
Object indexLabels = schemaColumn(entry, HugeKeys.INDEX_LABELS);
SchemaStatus status = schemaEnum(entry, HugeKeys.STATUS,
SchemaStatus.class);
Number ttl = schemaColumn(entry, HugeKeys.TTL);
Number ttlStartTime = schemaColumn(entry, HugeKeys.TTL_START_TIME);
EdgeLabel edgeLabel = new EdgeLabel(graph, this.toId(id), name);
edgeLabel.frequency(frequency);
edgeLabel.sourceLabel(this.toId(sourceLabel));
edgeLabel.targetLabel(this.toId(targetLabel));
edgeLabel.properties(this.toIdArray(properties));
edgeLabel.sortKeys(this.toIdArray(sortKeys));
edgeLabel.nullableKeys(this.toIdArray(nullableKeys));
edgeLabel.addIndexLabels(this.toIdArray(indexLabels));
edgeLabel.status(status);
edgeLabel.ttl(ttl.longValue());
edgeLabel.ttlStartTime(this.toId(ttlStartTime));
this.readEnableLabelIndex(edgeLabel, entry);
this.readUserdata(edgeLabel, entry);
return edgeLabel;
}
@Override
public PropertyKey readPropertyKey(HugeGraph graph,
BackendEntry backendEntry) {
if (backendEntry == null) {
return null;
}
TableBackendEntry entry = this.convertEntry(backendEntry);
Number id = schemaColumn(entry, HugeKeys.ID);
String name = schemaColumn(entry, HugeKeys.NAME);
DataType dataType = schemaEnum(entry, HugeKeys.DATA_TYPE,
DataType.class);
Cardinality cardinality = schemaEnum(entry, HugeKeys.CARDINALITY,
Cardinality.class);
AggregateType aggregateType = schemaEnum(entry, HugeKeys.AGGREGATE_TYPE,
AggregateType.class);
WriteType writeType = schemaEnumOrDefault(
entry, HugeKeys.WRITE_TYPE,
WriteType.class, WriteType.OLTP);
Object properties = schemaColumn(entry, HugeKeys.PROPERTIES);
SchemaStatus status = schemaEnum(entry, HugeKeys.STATUS,
SchemaStatus.class);
PropertyKey propertyKey = new PropertyKey(graph, this.toId(id), name);
propertyKey.dataType(dataType);
propertyKey.cardinality(cardinality);
propertyKey.aggregateType(aggregateType);
propertyKey.writeType(writeType);
propertyKey.properties(this.toIdArray(properties));
propertyKey.status(status);
this.readUserdata(propertyKey, entry);
return propertyKey;
}
@Override
public BackendEntry writeIndexLabel(IndexLabel indexLabel) {
TableBackendEntry entry = newBackendEntry(indexLabel);
entry.column(HugeKeys.ID, indexLabel.id().asLong());
entry.column(HugeKeys.NAME, indexLabel.name());
entry.column(HugeKeys.BASE_TYPE, indexLabel.baseType().code());
entry.column(HugeKeys.BASE_VALUE, indexLabel.baseValue().asLong());
entry.column(HugeKeys.INDEX_TYPE, indexLabel.indexType().code());
entry.column(HugeKeys.FIELDS,
this.toLongList(indexLabel.indexFields()));
this.writeUserdata(indexLabel, entry);
entry.column(HugeKeys.STATUS, indexLabel.status().code());
return entry;
}
@Override
public IndexLabel readIndexLabel(HugeGraph graph,
BackendEntry backendEntry) {
if (backendEntry == null) {
return null;
}
TableBackendEntry entry = this.convertEntry(backendEntry);
Number id = schemaColumn(entry, HugeKeys.ID);
String name = schemaColumn(entry, HugeKeys.NAME);
HugeType baseType = schemaEnum(entry, HugeKeys.BASE_TYPE,
HugeType.class);
Number baseValueId = schemaColumn(entry, HugeKeys.BASE_VALUE);
IndexType indexType = schemaEnum(entry, HugeKeys.INDEX_TYPE,
IndexType.class);
Object indexFields = schemaColumn(entry, HugeKeys.FIELDS);
SchemaStatus status = schemaEnum(entry, HugeKeys.STATUS,
SchemaStatus.class);
IndexLabel indexLabel = new IndexLabel(graph, this.toId(id), name);
indexLabel.baseType(baseType);
indexLabel.baseValue(this.toId(baseValueId));
indexLabel.indexType(indexType);
indexLabel.indexFields(this.toIdArray(indexFields));
indexLabel.status(status);
this.readUserdata(indexLabel, entry);
return indexLabel;
}
protected abstract Id toId(Number number);
protected abstract Id[] toIdArray(Object object);
protected abstract Object toLongSet(Collection<Id> ids);
protected abstract Object toLongList(Collection<Id> ids);
protected abstract Set<Object> parseIndexElemIds(TableBackendEntry entry);
protected abstract void formatProperties(HugeElement element,
TableBackendEntry.Row row);
protected abstract void parseProperties(HugeElement element,
TableBackendEntry.Row row);
protected Object writeId(Id id) {
return IdUtil.writeStoredString(id);
}
protected Id readId(Object id) {
return IdUtil.readStoredString(id.toString());
}
protected Object serializeValue(HugeKeys key, Object value) {
if (value instanceof Directions) {
value = ((Directions) value).type().code();
} else if (value instanceof Id) {
if (key == HugeKeys.OWNER_VERTEX || key == HugeKeys.OTHER_VERTEX) {
// Serialize vertex id
value = this.writeId((Id) value);
} else {
// Serialize other id value, like label id
value = ((Id) value).asObject();
}
}
return value;
}
protected void writeEnableLabelIndex(SchemaLabel schema,
TableBackendEntry entry) {
entry.column(HugeKeys.ENABLE_LABEL_INDEX, schema.enableLabelIndex());
}
protected void readEnableLabelIndex(SchemaLabel schema,
TableBackendEntry entry) {
Boolean enableLabelIndex = schemaColumn(entry,
HugeKeys.ENABLE_LABEL_INDEX);
schema.enableLabelIndex(enableLabelIndex);
}
protected abstract void writeUserdata(SchemaElement schema,
TableBackendEntry entry);
protected abstract void readUserdata(SchemaElement schema,
TableBackendEntry entry);
private static <T> T schemaColumn(TableBackendEntry entry, HugeKeys key) {
assert entry.type().isSchema();
T value = entry.column(key);
E.checkState(value != null,
"Not found key '%s' from entry %s", key, entry);
return value;
}
private static <T extends SerialEnum> T schemaEnum(TableBackendEntry entry,
HugeKeys key,
Class<T> clazz) {
Number value = schemaColumn(entry, key);
return SerialEnum.fromCode(clazz, value.byteValue());
}
private static <T extends SerialEnum> T schemaEnumOrDefault(
TableBackendEntry entry,
HugeKeys key, Class<T> clazz,
T defaultValue) {
assert entry.type().isSchema();
Number value = entry.column(key);
if (value == null) {
return defaultValue;
}
return SerialEnum.fromCode(clazz, value.byteValue());
}
}