docs: void graphToRDF(String graphName, Map<String, Object> graph) {
          // 4.2)
          final List<Quad> triples = new ArrayList<Quad>();
          // 4.3)
          final List<String> subjects = new ArrayList<String>(graph.keySet());
          // Collections.sort(subjects);
          for (final String id : subjects) {
              if (JsonLdUtils.isRelativeIri(id)) {
                  continue;
              }
              final Map<String, Object> node = (Map<String, Object>) graph.get(id);
              final List<String> properties = new ArrayList<String>(node.keySet());
              Collections.sort(properties);
              for (String property : properties) {
                  final List<Object> values;
                  // 4.3.2.1)
                  if ("@type".equals(property)) {
                      values = (List<Object>) node.get("@type");
                      property = RDF_TYPE;
                  }
                  // 4.3.2.2)
                  else if (isKeyword(property)) {
                      continue;
                  }
                  // 4.3.2.3)
                  else if (property.startsWith("_:") && !api.opts.getProduceGeneralizedRdf()) {
                      continue;
                  }
                  // 4.3.2.4)
                  else if (JsonLdUtils.isRelativeIri(property)) {
                      continue;
                  } else {
                      values = (List<Object>) node.get(property);
                  }
  
                  Node subject;
                  if (id.indexOf("_:") == 0) {
                      // NOTE: don't rename, just set it as a blank node
                      subject = new BlankNode(id);
                  } else {
                      subject = new IRI(id);
                  }
  
                  // RDF predicates
                  Node predicate;
                  if (property.startsWith("_:")) {
                      predicate = new BlankNode(property);
                  } else {
                      predicate = new IRI(property);
                  }
  
                  for (final Object item : values) {
                      // convert @list to triples
                      if (isList(item)) {
                          final List<Object> list = (List<Object>) ((Map<String, Object>) item)
                                  .get("@list");
                          Node last = null;
                          Node firstBNode = nil;
                          if (!list.isEmpty()) {
                              last = objectToRDF(list.get(list.size() - 1));
                              firstBNode = new BlankNode(api.generateBlankNodeIdentifier());
                          }
                          triples.add(new Quad(subject, predicate, firstBNode, graphName));
                          for (int i = 0; i < list.size() - 1; i++) {
                              final Node object = objectToRDF(list.get(i));
                              triples.add(new Quad(firstBNode, first, object, graphName));
                              final Node restBNode = new BlankNode(api.generateBlankNodeIdentifier());
                              triples.add(new Quad(firstBNode, rest, restBNode, graphName));
                              firstBNode = restBNode;
                          }
                          if (last != null) {
                              triples.add(new Quad(firstBNode, first, last, graphName));
                              triples.add(new Quad(firstBNode, rest, nil, graphName));
                          }
                      }
                      // convert value or node object to triple
                      else {
                          final Node object = objectToRDF(item);
                          if (object != null) {
                              triples.add(new Quad(subject, predicate, object, graphName));
                          }
                      }
                  }
              }
          }
          put(graphName, triples);
      }