package org.vertexium.accumulo; import com.google.common.base.Function; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Value; import org.apache.hadoop.io.Text; import org.vertexium.*; import org.vertexium.accumulo.iterator.EdgeIterator; import org.vertexium.accumulo.iterator.model.ElementData; import org.vertexium.accumulo.util.DataInputStreamUtils; import org.vertexium.mutation.ExistingEdgeMutation; import org.vertexium.mutation.PropertyDeleteMutation; import org.vertexium.mutation.PropertySoftDeleteMutation; import org.vertexium.util.IterableUtils; import javax.annotation.Nullable; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Map; public class AccumuloEdge extends AccumuloElement implements Edge { public static final Text CF_SIGNAL = EdgeIterator.CF_SIGNAL; public static final Text CF_OUT_VERTEX = EdgeIterator.CF_OUT_VERTEX; public static final Text CF_IN_VERTEX = EdgeIterator.CF_IN_VERTEX; private final String outVertexId; private final String inVertexId; private final String label; private final String newEdgeLabel; public AccumuloEdge( Graph graph, String id, String outVertexId, String inVertexId, String label, String newEdgeLabel, Visibility visibility, Iterable<Property> properties, Iterable<PropertyDeleteMutation> propertyDeleteMutations, Iterable<PropertySoftDeleteMutation> propertySoftDeleteMutations, Iterable<Visibility> hiddenVisibilities, ImmutableSet<String> extendedDataTableNames, long timestamp, EnumSet<FetchHint> fetchHints, Authorizations authorizations ) { super( graph, id, visibility, properties, propertyDeleteMutations, propertySoftDeleteMutations, hiddenVisibilities, extendedDataTableNames, timestamp, fetchHints, authorizations ); this.outVertexId = outVertexId; this.inVertexId = inVertexId; this.label = label; this.newEdgeLabel = newEdgeLabel; } public static Edge createFromIteratorValue( AccumuloGraph graph, Key key, Value value, EnumSet<FetchHint> fetchHints, Authorizations authorizations ) { try { String edgeId; Visibility vertexVisibility; Iterable<Property> properties; Iterable<PropertyDeleteMutation> propertyDeleteMutations = new ArrayList<>(); Iterable<PropertySoftDeleteMutation> propertySoftDeleteMutations = new ArrayList<>(); Iterable<Visibility> hiddenVisibilities; Map<String, org.vertexium.accumulo.iterator.model.EdgeInfo> inEdges; Map<String, org.vertexium.accumulo.iterator.model.EdgeInfo> outEdges; long timestamp; ByteArrayInputStream bain = new ByteArrayInputStream(value.get()); final DataInputStream in = new DataInputStream(bain); DataInputStreamUtils.decodeHeader(in, ElementData.TYPE_ID_EDGE); edgeId = DataInputStreamUtils.decodeText(in).toString(); timestamp = in.readLong(); vertexVisibility = new Visibility(DataInputStreamUtils.decodeText(in).toString()); hiddenVisibilities = Iterables.transform(DataInputStreamUtils.decodeTextList(in), new Function<Text, Visibility>() { @Nullable @Override public Visibility apply(Text input) { return new Visibility(input.toString()); } }); properties = DataInputStreamUtils.decodeProperties(graph, in, fetchHints); ImmutableSet<String> extendedDataTableNames = DataInputStreamUtils.decodeStringSet(in); String inVertexId = DataInputStreamUtils.decodeText(in).toString(); String outVertexId = DataInputStreamUtils.decodeText(in).toString(); String label = graph.getNameSubstitutionStrategy().inflate(DataInputStreamUtils.decodeText(in)); return new AccumuloEdge( graph, edgeId, outVertexId, inVertexId, label, null, vertexVisibility, properties, propertyDeleteMutations, propertySoftDeleteMutations, hiddenVisibilities, extendedDataTableNames, timestamp, fetchHints, authorizations ); } catch (IOException ex) { throw new VertexiumException("Could not read vertex", ex); } } String getNewEdgeLabel() { return newEdgeLabel; } @Override public String getLabel() { return label; } @Override public String getVertexId(Direction direction) { switch (direction) { case OUT: return outVertexId; case IN: return inVertexId; default: throw new IllegalArgumentException("Unexpected direction: " + direction); } } @Override public Vertex getVertex(Direction direction, Authorizations authorizations) { return getVertex(direction, getGraph().getDefaultFetchHints(), authorizations); } @Override public String getOtherVertexId(String myVertexId) { if (inVertexId.equals(myVertexId)) { return outVertexId; } else if (outVertexId.equals(myVertexId)) { return inVertexId; } throw new VertexiumException("myVertexId(" + myVertexId + ") does not appear on edge (" + getId() + ") in either the in (" + inVertexId + ") or the out (" + outVertexId + ")."); } @Override public Vertex getOtherVertex(String myVertexId, Authorizations authorizations) { return getOtherVertex(myVertexId, getGraph().getDefaultFetchHints(), authorizations); } @Override public Vertex getOtherVertex(String myVertexId, EnumSet<FetchHint> fetchHints, Authorizations authorizations) { return getGraph().getVertex(getOtherVertexId(myVertexId), fetchHints, authorizations); } @Override public EdgeVertices getVertices(Authorizations authorizations) { return getVertices(getGraph().getDefaultFetchHints(), authorizations); } @Override public EdgeVertices getVertices(EnumSet<FetchHint> fetchHints, Authorizations authorizations) { List<String> ids = new ArrayList<>(); ids.add(getVertexId(Direction.OUT)); ids.add(getVertexId(Direction.IN)); Map<String, Vertex> vertices = IterableUtils.toMapById(getGraph().getVertices(ids, fetchHints, authorizations)); return new EdgeVertices( vertices.get(getVertexId(Direction.OUT)), vertices.get(getVertexId(Direction.IN)) ); } @Override public Vertex getVertex(Direction direction, EnumSet<FetchHint> fetchHints, Authorizations authorizations) { return getGraph().getVertex(getVertexId(direction), fetchHints, authorizations); } @Override @SuppressWarnings("unchecked") public ExistingEdgeMutation prepareMutation() { return new ExistingEdgeMutation(this) { @Override public Edge save(Authorizations authorizations) { saveExistingElementMutation(this, authorizations); return getElement(); } }; } }