All Downloads are FREE. Search and download functionalities are using the official Maven repository.

overflowdb.NodeLayoutInformation Maven / Gradle / Ivy

There is a newer version: 1.115
Show newest version
package overflowdb;

import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * Contains all static node-specific information for serialization / deserialization.
 * 

* Please make sure to instantiate only one instance per node type to not waste memory. */ public class NodeLayoutInformation { /** unique id for this node's label * This is mostly an optimization for storage - we could as well serialize labels as string, but numbers are more efficient. * Since we know our schema at compile time, we can assign unique ids for each label. * */ public final int labelId; private final Set propertyKeys; private final String[] allowedOutEdgeLabels; private final String[] allowedInEdgeLabels; /* position for given OUT edge label in edgeOffsets */ private final Map outEdgeToOffsetPosition; /* position for given IN edge label in edgeOffsets */ private final Map inEdgeToOffsetPosition; /* possible edge property keys, grouped by edge label. * n.b. property keys are of type `HashSet` (rather than just `Set`) to ensure `.size` has constant time */ private final Map> edgePropertyKeysByLabel; /* maps offsetPos -> number of edge properties*/ private final int[] edgePropertyCountByOffsetPosition; /* position in stride (entry within `adjacentNodesWithProperties`) for a given edge label and edge property key * 1-based, because index `0` is the adjacent node ref */ private final Map edgeLabelAndKeyToStrideIndex; public NodeLayoutInformation(int labelId, Set propertyKeys, List outEdgeLayouts, List inEdgeLayouts) { this.labelId = labelId; this.propertyKeys = propertyKeys; Set allEdgeLayouts = new HashSet<>(); allEdgeLayouts.addAll(outEdgeLayouts); allEdgeLayouts.addAll(inEdgeLayouts); edgePropertyKeysByLabel = createEdgePropertyKeysByLabel(allEdgeLayouts); edgeLabelAndKeyToStrideIndex = createEdgeLabelAndKeyToStrideIndex(allEdgeLayouts); /* create unique offsets for each edge type and direction * ordered by input order (first out, then in, same order as in outEdgeLayouts) * this ensures that (1) we get the same offsets between restarts and (2) the offsets are easily apparent from the * constructor call. Downstream may rely on the offsets, beware before changing! * schema changes will change layout*/ allowedOutEdgeLabels = new String[outEdgeLayouts.size()]; allowedInEdgeLabels = new String[inEdgeLayouts.size()]; int offsetPosition = 0; edgePropertyCountByOffsetPosition = new int[outEdgeLayouts.size() + inEdgeLayouts.size()]; int i = 0; outEdgeToOffsetPosition = new HashMap<>(outEdgeLayouts.size()); for (EdgeLayoutInformation edgeLayout : outEdgeLayouts) { edgePropertyCountByOffsetPosition[offsetPosition] = edgePropertyKeysByLabel.get(edgeLayout.label).size(); outEdgeToOffsetPosition.put(edgeLayout.label, offsetPosition++); allowedOutEdgeLabels[i++] = edgeLayout.label; } i = 0; inEdgeToOffsetPosition = new HashMap<>(inEdgeLayouts.size()); for (EdgeLayoutInformation edgeLayout : inEdgeLayouts) { edgePropertyCountByOffsetPosition[offsetPosition] = edgePropertyKeysByLabel.get(edgeLayout.label).size(); inEdgeToOffsetPosition.put(edgeLayout.label, offsetPosition++); allowedInEdgeLabels[i++] = edgeLayout.label; } } private Map> createEdgePropertyKeysByLabel(Set allEdgeLayouts) { Map> edgePropertyKeysByLabel = new HashMap<>(allEdgeLayouts.size()); for (EdgeLayoutInformation edgeLayout : allEdgeLayouts) { edgePropertyKeysByLabel.put(edgeLayout.label, new HashSet<>(edgeLayout.propertyKeys)); } return edgePropertyKeysByLabel; } private Map createEdgeLabelAndKeyToStrideIndex(Set allEdgeLayouts) { Map edgeLabelAndKeyToStrideIndex = new HashMap<>(allEdgeLayouts.size()); for (EdgeLayoutInformation edgeLayout : allEdgeLayouts) { /* 1-based, because index `0` is the adjacent node ref */ int strideIndex = 1; /* sort property keys to ensure we get the same offsets between restarts * n.b. this doesn't support schema changes */ for (String propertyKey : sorted(edgeLayout.propertyKeys)) { edgeLabelAndKeyToStrideIndex.put(new LabelAndKey(edgeLayout.label, propertyKey), strideIndex++); } } return edgeLabelAndKeyToStrideIndex; } private Iterable sorted(Set propertyKeys) { SortedSet sortedSet = new TreeSet<>(String::compareTo); sortedSet.addAll(propertyKeys); return sortedSet; } private SortedSet sortByLabel(List outEdgeLayouts) { SortedSet sorted = new TreeSet<>(Comparator.comparing(a -> a.label)); sorted.addAll(outEdgeLayouts); return sorted; } public Set propertyKeys() { return propertyKeys; } public String[] allowedOutEdgeLabels() { return allowedOutEdgeLabels; } public String[] allowedInEdgeLabels() { return allowedInEdgeLabels; } public Set edgePropertyKeys(String edgeLabel) { return edgePropertyKeysByLabel.get(edgeLabel); } /* The number fo different IN|OUT edge relations. E.g. a node has AST edges in and out, then we would have 2. * If in addition it has incoming ref edges it would have 3. */ public int numberOfDifferentAdjacentTypes() { return outEdgeToOffsetPosition.size() + inEdgeToOffsetPosition.size(); } /* position for given OUT edge label in OverflowDbNode.edgeOffsets */ public Integer outEdgeToOffsetPosition(String edgeLabel) { return outEdgeToOffsetPosition.get(edgeLabel); } /* position for given IN edge label in OverflowDbNode.edgeOffsets */ public Integer inEdgeToOffsetPosition(String edgeLabel) { return inEdgeToOffsetPosition.get(edgeLabel); } /** * @return The offset relative to the adjacent node in the adjacentNodesWithProperties array starting from 1. * Return -1 if key does not exist for given edgeLabel. */ public int getOffsetRelativeToAdjacentNodeRef(String edgeLabel, String key) { return edgeLabelAndKeyToStrideIndex.getOrDefault(new LabelAndKey(edgeLabel, key), -1); } /* gets edge property count by offsetPos*/ public final int getEdgePropertyCountByOffsetPos(int offsetPos) { return edgePropertyCountByOffsetPosition[offsetPos]; } class LabelAndKey { final String label; final String propertyKey; LabelAndKey(String label, String propertyKey) { this.label = label; this.propertyKey = propertyKey; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; LabelAndKey that = (LabelAndKey) o; return label.equals(that.label) && propertyKey.equals(that.propertyKey); } @Override public int hashCode() { return Objects.hash(label, propertyKey); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy