docs: public List<Object> fromRDF(final RDFDataset dataset, boolean noDuplicatesInDataset)
              throws JsonLdError {
          // 1)
          final Map<String, NodeMapNode> defaultGraph = new LinkedHashMap<String, NodeMapNode>(4);
          // 2)
          final Map<String, Map<String, NodeMapNode>> graphMap = new LinkedHashMap<String, Map<String, NodeMapNode>>(
                  4);
          graphMap.put(JsonLdConsts.DEFAULT, defaultGraph);
  
          // 3/3.1)
          for (final String name : dataset.graphNames()) {
  
              final List<RDFDataset.Quad> graph = dataset.getQuads(name);
  
              // 3.2+3.4)
              final Map<String, NodeMapNode> nodeMap = graphMap.computeIfAbsent(name,
                      k -> new LinkedHashMap<String, NodeMapNode>());
  
              // 3.3)
              if (!JsonLdConsts.DEFAULT.equals(name)) {
                  // Existing entries in the default graph are not overwritten
                  defaultGraph.computeIfAbsent(name, k -> new NodeMapNode(k));
              }
  
              // 3.5)
              final Map<String, List<Node>> nodes = new HashMap<>();
  
              for (final RDFDataset.Quad triple : graph) {
                  final String subject = triple.getSubject().getValue();
                  final String predicate = triple.getPredicate().getValue();
                  final RDFDataset.Node object = triple.getObject();
                  nodes.computeIfAbsent(subject, k -> new ArrayList<>())
                          .add(new Node(predicate, object));
              }
              for (final Map.Entry<String, List<Node>> nodeEntry : nodes.entrySet()) {
                  final String subject = nodeEntry.getKey();
  
                  for (final Node n : nodeEntry.getValue()) {
                      final String predicate = n.predicate;
                      final RDFDataset.Node object = n.object;
  
                      // 3.5.1+3.5.2)
                      final NodeMapNode node = nodeMap.computeIfAbsent(subject,
                              k -> new NodeMapNode(k));
  
                      // 3.5.3)
                      if ((object.isIRI() || object.isBlankNode())) {
                          nodeMap.computeIfAbsent(object.getValue(), k -> new NodeMapNode(k));
                      }
  
                      // 3.5.4)
                      if (RDF_TYPE.equals(predicate) && (object.isIRI() || object.isBlankNode())
                              && !opts.getUseRdfType() && !nodes.containsKey(object.getValue())) {
                          JsonLdUtils.mergeValue(node, JsonLdConsts.TYPE, object.getValue());
                          continue;
                      }
  
                      // 3.5.5)
                      final Map<String, Object> value = object.toObject(opts.getUseNativeTypes());
  
                      // 3.5.6+7)
                      if (noDuplicatesInDataset) {
                          JsonLdUtils.laxMergeValue(node, predicate, value);
                      } else {
                          JsonLdUtils.mergeValue(node, predicate, value);
                      }
  
                      // 3.5.8)
                      if (object.isBlankNode() || object.isIRI()) {
                          // 3.5.8.1-3)
                          nodeMap.get(object.getValue()).usages
                                  .add(new UsagesNode(node, predicate, value));
                      }
                  }
              }
          }
  
          // 4)
          for (final String name : graphMap.keySet()) {
              final Map<String, NodeMapNode> graph = graphMap.get(name);
  
              // 4.1)
              if (!graph.containsKey(RDF_NIL)) {
                  continue;
              }
  
              // 4.2)
              final NodeMapNode nil = graph.get(RDF_NIL);
              // 4.3)
              for (final UsagesNode usage : nil.usages) {
                  // 4.3.1)
                  NodeMapNode node = usage.node;
                  String property = usage.property;
                  Map<String, Object> head = usage.value;
                  // 4.3.2)
                  final List<Object> list = new ArrayList<Object>(4);
                  final List<String> listNodes = new ArrayList<String>(4);
                  // 4.3.3)
                  while (RDF_REST.equals(property) && node.isWellFormedListNode()) {
                      // 4.3.3.1)
                      list.add(((List<Object>) node.get(RDF_FIRST)).get(0));
                      // 4.3.3.2)
                      listNodes.add((String) node.get(JsonLdConsts.ID));
                      // 4.3.3.3)
                      final UsagesNode nodeUsage = node.usages.get(0);
                      // 4.3.3.4)
                      node = nodeUsage.node;
                      property = nodeUsage.property;
                      head = nodeUsage.value;
                      // 4.3.3.5)
                      if (!JsonLdUtils.isBlankNode(node)) {
                          break;
                      }
                  }
                  // 4.3.4)
                  if (RDF_FIRST.equals(property)) {
                      // 4.3.4.1)
                      if (RDF_NIL.equals(node.get(JsonLdConsts.ID))) {
                          continue;
                      }
                      // 4.3.4.3)
                      final String headId = (String) head.get(JsonLdConsts.ID);
                      // 4.3.4.4-5)
                      head = (Map<String, Object>) ((List<Object>) graph.get(headId).get(RDF_REST))
                              .get(0);
                      // 4.3.4.6)
                      list.remove(list.size() - 1);
                      listNodes.remove(listNodes.size() - 1);
                  }
                  // 4.3.5)
                  head.remove(JsonLdConsts.ID);
                  // 4.3.6)
                  Collections.reverse(list);
                  // 4.3.7)
                  head.put(JsonLdConsts.LIST, list);
                  // 4.3.8)
                  for (final String nodeId : listNodes) {
                      graph.remove(nodeId);
                  }
              }
          }
  
          // 5)
          final List<Object> result = new ArrayList<Object>(4);
          // 6)
          final List<String> ids = new ArrayList<String>(defaultGraph.keySet());
          Collections.sort(ids);
          for (final String subject : ids) {
              final NodeMapNode node = defaultGraph.get(subject);
              // 6.1)
              if (graphMap.containsKey(subject)) {
                  // 6.1.1)
                  final List<Object> nextGraph = new ArrayList<Object>(4);
                  node.put(JsonLdConsts.GRAPH, nextGraph);
                  // 6.1.2)
                  final Map<String, NodeMapNode> nextSubjectMap = graphMap.get(subject);
                  final List<String> keys = new ArrayList<String>(nextSubjectMap.keySet());
                  Collections.sort(keys);
                  for (final String s : keys) {
                      final NodeMapNode n = nextSubjectMap.get(s);
                      if (n.size() == 1 && n.containsKey(JsonLdConsts.ID)) {
                          continue;
                      }
                      nextGraph.add(n.serialize());
                  }
              }
              // 6.2)
              if (node.size() == 1 && node.containsKey(JsonLdConsts.ID)) {
                  continue;
              }
              result.add(node.serialize());
          }
  
          return result;
      }