boolean isInVertex = false;
// Buffered Edge Data
String edgeId = null;
String edgeLabel = null;
Vertex edgeInVertex = null;
Vertex edgeOutVertex = null;
Map<String, Object> edgeProps = null;
boolean isInEdge = false;
while (reader.hasNext()) {
final Integer eventType = reader.next();
if (eventType.equals(XMLEvent.START_ELEMENT)) {
final String elementName = reader.getName().getLocalPart();
switch (elementName) {
case GraphMLTokens.KEY:
final String id = reader.getAttributeValue(null, GraphMLTokens.ID);
final String attributeName = reader.getAttributeValue(null, GraphMLTokens.ATTR_NAME);
final String attributeType = reader.getAttributeValue(null, GraphMLTokens.ATTR_TYPE);
keyIdMap.put(id, attributeName);
keyTypesMaps.put(id, attributeType);
break;
case GraphMLTokens.NODE:
vertexId = reader.getAttributeValue(null, GraphMLTokens.ID);
isInVertex = true;
vertexProps = new HashMap<>();
break;
case GraphMLTokens.EDGE:
edgeId = reader.getAttributeValue(null, GraphMLTokens.ID);
final String vertexIdOut = reader.getAttributeValue(null, GraphMLTokens.SOURCE);
final String vertexIdIn = reader.getAttributeValue(null, GraphMLTokens.TARGET);
// graphml allows edges and vertices to be mixed in terms of how they are positioned
// in the xml therefore it is possible that an edge is created prior to its definition
// as a vertex.
edgeOutVertex = Optional.ofNullable(graph.v(vertexIdOut))
.orElseGet(() -> graph.addVertex(T.id, vertexIdOut));
edgeInVertex = Optional.ofNullable(graph.v(vertexIdIn))
.orElseGet(() -> graph.addVertex(T.id, vertexIdIn));
isInEdge = true;
edgeProps = new HashMap<>();
break;
case GraphMLTokens.DATA:
final String key = reader.getAttributeValue(null, GraphMLTokens.KEY);
final String dataAttributeName = keyIdMap.get(key);
if (dataAttributeName != null) {
final String value = reader.getElementText();
if (isInVertex) {
if (key.equals(vertexLabelKey))
vertexLabel = value;
else
vertexProps.put(dataAttributeName, typeCastValue(key, value, keyTypesMaps));
} else if (isInEdge) {
if (key.equals(edgeLabelKey))
edgeLabel = value;
else if (key.equals(edgeIdKey))
edgeId = value;
else
edgeProps.put(dataAttributeName, typeCastValue(key, value, keyTypesMaps));
}
}
break;
}
} else if (eventType.equals(XMLEvent.END_ELEMENT)) {
final String elementName = reader.getName().getLocalPart();
if (elementName.equals(GraphMLTokens.NODE)) {
final String currentVertexId = vertexId;
final String currentVertexLabel = Optional.ofNullable(vertexLabel).orElse(Vertex.DEFAULT_LABEL);
final Object[] propsAsArray = vertexProps.entrySet().stream().flatMap(e -> Stream.of(e.getKey(), e.getValue())).toArray();
// if incremental loading is on in batchgraph it handles graphml spec where it states that
// order of edges/vertices may be mixed such that an edge may be created before an vertex.
graph.addVertex(Stream.concat(Stream.of(T.id, currentVertexId, T.label, currentVertexLabel),
Stream.of(propsAsArray)).toArray());
vertexId = null;
vertexLabel = null;
vertexProps = null;
isInVertex = false;
} else if (elementName.equals(GraphMLTokens.EDGE)) {
final Object[] propsAsArray = edgeProps.entrySet().stream().flatMap(e -> Stream.of(e.getKey(), e.getValue())).toArray();
edgeOutVertex.addEdge(edgeLabel, edgeInVertex, Stream.concat(Stream.of(T.id, edgeId),
Stream.of(propsAsArray)).toArray());
edgeId = null;
edgeLabel = null;
edgeOutVertex = null;