docs: @Override
      public void addNeighbor(final TrustGraphNodeId neighbor) {
          if (neighbor == null) {
              return;
          }
  
          // all modification operations are serialized
          synchronized(this) {
  
              // do not add this neighbor if it is already present
              if (contains(neighbor)) {
                  return;
              }
  
              /* If there is nothing in the table, route the neighbor to itself.
               * this condition is fixed during the next single addition since
               * the route is always selected to be split. The bulk add
               * operation also takes special care to perform a single addition
               * if this state exists before adding additional routes.
               */
              if (routingTable.isEmpty()) {
                  routingTable.put(neighbor, neighbor);
              }
              /* otherwise, pick a random existing route X->Y and 
               * split it into two routes, X->neighbor and neighbor->Y
               */
              else {
                  Map.Entry<TrustGraphNodeId,TrustGraphNodeId> split =
                      randomRoute();      
                  TrustGraphNodeId splitKey = split.getKey();
                  TrustGraphNodeId splitVal = split.getValue();
  
                  /*
                   * The new route neighbor->Y is inserted first. This 
                   * preserves the existing routing behavior for readers
                   * until the entire operation is complete.
                   */ 
                  routingTable.put(neighbor, splitVal);
                  routingTable.replace(splitKey, neighbor);
              }
              
              // add the neighbor to the ordering
              addNeighborToOrdering(neighbor);
          }
      }