@Test
  public void directDataLinkToQuads() throws IOException {
    // first make a file of quads to load later
    final Model model = createDefaultModel();
    final Path quads = createTempFile("quadExample", ".nq");
    final Resource quadsURI = model.createResource(quads.toFile().toURI().toString());
    final Resource simpleExample = model.createResource("test:simpleExample");
    simpleExample.addProperty(type, DatasetAssemblerVocab.tDatasetTxnMem);
    simpleExample.addProperty(data, quadsURI);

    final DatasetGraph dsg = createTxnMem().asDatasetGraph();
    model
        .listStatements()
        .mapWith(Statement::asTriple)
        .mapWith(t -> new Quad(quadsURI.asNode(), t))
        .forEachRemaining(dsg::add);
    try (OutputStream out = new FileOutputStream(quads.toFile())) {
      write(out, dsg, NQUADS);
    }

    final Dataset dataset = assemble(simpleExample);
    final Model assembledDefaultModel = dataset.getDefaultModel();
    final Model assembledNamedModel = dataset.getNamedModel(quadsURI.getURI());
    assertTrue(assembledDefaultModel.isEmpty());
    assertTrue(
        assembledNamedModel.contains(
            assembledNamedModel.createStatement(simpleExample, data, quadsURI)));
  }
  @Test
  public void directDataLinkForDefaultAndNamedGraphs() throws IOException {
    // first make a file of triples to load later
    final Model model = createDefaultModel();
    final Path triples = createTempFile("simpleExample", ".nt");
    final Resource triplesURI = model.createResource(triples.toFile().toURI().toString());
    final Resource simpleExample = model.createResource("test:simpleExample");
    simpleExample.addProperty(type, DatasetAssemblerVocab.tDatasetTxnMem);
    // add a default graph
    simpleExample.addProperty(data, triplesURI);
    // add a named graph
    final Resource namedGraphDef = model.createResource("test:namedGraphDef");
    simpleExample.addProperty(pNamedGraph, namedGraphDef);
    final Resource namedGraphName = model.createResource("test:namedGraphExample");
    namedGraphDef.addProperty(type, MemoryModel);
    namedGraphDef.addProperty(pGraphName, namedGraphName);
    namedGraphDef.addProperty(data, triplesURI);

    try (OutputStream out = new FileOutputStream(triples.toFile())) {
      write(out, model, NTRIPLES);
    }

    final Dataset dataset = assemble(simpleExample);
    final Model assembledDefaultModel = dataset.getDefaultModel();
    final Model assembledNamedModel = dataset.getNamedModel(namedGraphName.getURI());

    // we put the same triples in each model, so we check for the same triples in each model
    for (final Model m : new Model[] {assembledDefaultModel, assembledNamedModel}) {
      assertTrue(m.contains(simpleExample, pNamedGraph, namedGraphDef));
      assertTrue(m.contains(namedGraphDef, pGraphName, namedGraphName));
      assertTrue(m.contains(simpleExample, data, triplesURI));
    }
    final Iterator<Node> graphNodes = dataset.asDatasetGraph().listGraphNodes();
    assertTrue(graphNodes.hasNext());
    assertEquals(namedGraphName.asNode(), graphNodes.next());
    assertFalse(graphNodes.hasNext());
  }
  @Override
  public EntityDefinition open(Assembler a, Resource root, Mode mode) {
    String prologue = "PREFIX : <" + NS + ">   PREFIX list: <http://jena.apache.org/ARQ/list#> ";
    Model model = root.getModel();

    String qs1 =
        StrUtils.strjoinNL(
            prologue,
            "SELECT * {",
            "  ?eMap  :entityField  ?entityField ;",
            "         :map ?map ;",
            "         :defaultField ?dftField .",
            "  OPTIONAL {",
            "    ?eMap :graphField ?graphField",
            "  }",
            "  OPTIONAL {",
            "    ?eMap :langField ?langField",
            "  }",
            "  OPTIONAL {",
            "    ?eMap :uidField ?uidField",
            "  }",
            "}");
    ParameterizedSparqlString pss = new ParameterizedSparqlString(qs1);
    pss.setIri("eMap", root.getURI());

    Query query1 = QueryFactory.create(pss.toString());
    QueryExecution qexec1 = QueryExecutionFactory.create(query1, model);
    ResultSet rs1 = qexec1.execSelect();
    List<QuerySolution> results = ResultSetFormatter.toList(rs1);
    if (results.size() == 0) {
      Log.warn(this, "Failed to find a valid EntityMap for : " + root);
      throw new TextIndexException("Failed to find a valid EntityMap for : " + root);
    }

    if (results.size() != 1) {
      Log.warn(this, "Multiple matches for EntityMap for : " + root);
      throw new TextIndexException("Multiple matches for EntityMap for : " + root);
    }

    QuerySolution qsol1 = results.get(0);
    String entityField = qsol1.getLiteral("entityField").getLexicalForm();
    String graphField =
        qsol1.contains("graphField") ? qsol1.getLiteral("graphField").getLexicalForm() : null;
    String langField =
        qsol1.contains("langField") ? qsol1.getLiteral("langField").getLexicalForm() : null;
    String defaultField =
        qsol1.contains("dftField") ? qsol1.getLiteral("dftField").getLexicalForm() : null;
    String uniqueIdField =
        qsol1.contains("uidField") ? qsol1.getLiteral("uidField").getLexicalForm() : null;

    Multimap<String, Node> mapDefs = HashMultimap.create();
    Map<String, Analyzer> analyzerDefs = new HashMap<>();

    Statement listStmt = root.getProperty(TextVocab.pMap);
    while (listStmt != null) {
      RDFNode n = listStmt.getObject();
      if (!n.isResource()) {
        throw new TextIndexException("Text list node is not a resource : " + n);
      }
      Resource listResource = n.asResource();
      if (listResource.equals(RDF.nil)) {
        break; // end of the list
      }

      Statement listEntryStmt = listResource.getProperty(RDF.first);
      if (listEntryStmt == null) {
        throw new TextIndexException("Text map list is not well formed.  No rdf:first property");
      }
      n = listEntryStmt.getObject();
      if (!n.isResource()) {
        throw new TextIndexException("Text map list entry is not a resource : " + n);
      }
      Resource listEntry = n.asResource();

      Statement fieldStatement = listEntry.getProperty(TextVocab.pField);
      if (fieldStatement == null) {
        throw new TextIndexException("Text map entry has no field property");
      }
      n = fieldStatement.getObject();
      if (!n.isLiteral()) {
        throw new TextIndexException("Text map entry field property has no literal value : " + n);
      }
      String field = n.asLiteral().getLexicalForm();

      Statement predicateStatement = listEntry.getProperty(TextVocab.pPredicate);
      if (predicateStatement == null) {
        throw new TextIndexException("Text map entry has no predicate property");
      }
      n = predicateStatement.getObject();
      if (!n.isURIResource()) {
        throw new TextIndexException(
            "Text map entry predicate property has non resource value : " + n);
      }
      mapDefs.put(field, n.asNode());

      Statement analyzerStatement = listEntry.getProperty(TextVocab.pAnalyzer);
      if (analyzerStatement != null) {
        n = analyzerStatement.getObject();
        if (!n.isResource()) {
          throw new TextIndexException("Text map entry analyzer property is not a resource : " + n);
        }
        Resource analyzerResource = n.asResource();
        Analyzer analyzer = (Analyzer) a.open(analyzerResource);
        analyzerDefs.put(field, analyzer);
      }

      // move on to the next element in the list
      listStmt = listResource.getProperty(RDF.rest);
    }

    // Primary field/predicate
    if (defaultField != null) {
      Collection<Node> c = mapDefs.get(defaultField);
      if (c.isEmpty())
        throw new TextIndexException("No definition of primary field '" + defaultField + "'");
    }

    EntityDefinition docDef = new EntityDefinition(entityField, defaultField);
    docDef.setGraphField(graphField);
    docDef.setLangField(langField);
    docDef.setUidField(uniqueIdField);
    for (String f : mapDefs.keys()) {
      for (Node p : mapDefs.get(f)) docDef.set(f, p);
    }
    for (String f : analyzerDefs.keySet()) {
      docDef.setAnalyzer(f, analyzerDefs.get(f));
    }
    return docDef;
  }