// This test has set response to JSON and pass StringHandle with format as JSON, expectint it to
  // work, logged an issue 82
  @Test
  public void testBulkSearchSQDwithResponseFormatandStringHandle() throws Exception {
    loadJSONDocuments();
    JSONDocumentManager docMgr = client.newJSONDocumentManager();

    QueryManager queryMgr = client.newQueryManager();
    StructuredQueryBuilder qb = new StructuredQueryBuilder();
    StructuredQueryDefinition qd = qb.and(qb.term("dog1", "dog11"));
    queryMgr.search(qd, new SearchHandle());

    docMgr.setNonDocumentFormat(Format.JSON);
    docMgr.setSearchView(QueryView.METADATA);
    docMgr.setMetadataCategories(Metadata.PERMISSIONS);

    StringHandle results = new StringHandle().withFormat(Format.JSON);
    DocumentPage page = docMgr.search(qd, 1, results);
    DocumentMetadataHandle mh = new DocumentMetadataHandle();
    while (page.hasNext()) {
      DocumentRecord rec = page.next();
      validateRecord(rec, Format.JSON);
      docMgr.readMetadata(rec.getUri(), mh);
      assertTrue("Records has permissions? ", mh.getPermissions().containsKey("flexrep-eval"));
      assertTrue("Record has collections ?", mh.getCollections().isEmpty());
    }
    assertFalse("Search handle contains", results.get().isEmpty());
  }
  @Test
  public void testJSON() {
    QueryManager queryMgr = Common.client.newQueryManager();
    StructuredQueryBuilder qb = queryMgr.newStructuredQueryBuilder();
    StructuredQueryDefinition t = qb.term("leaf3");

    // create a handle for the search results
    StringHandle resultsHandle = new StringHandle().withFormat(Format.JSON);

    // run the search
    queryMgr.search(t, resultsHandle);

    assertEquals("{", resultsHandle.get().substring(0, 1)); // It's JSON, right?
  }
    public void createDictionary(String uri, String[] words)
        throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException {
      StringBuilder builder = new StringBuilder();
      builder.append("<?xml version='1.0' encoding='UTF-8'?>\n");
      builder.append("<dictionary xmlns='http://marklogic.com/xdmp/spell'>\n");
      for (String word : words) {
        builder.append("<word>");
        builder.append(word);
        builder.append("</word>\n");
      }
      builder.append("</dictionary>\n");

      StringHandle writeHandle = new StringHandle();
      writeHandle.set(builder.toString());

      // delegate
      docMgr.write(uri, writeHandle);
    }
  // Searching for Id as Number in JSON using string should not return any results
  @Test
  public void testPOJOSearchWithStringHandle() throws JsonProcessingException, IOException {
    PojoRepository<Artifact, Long> products = client.newPojoRepository(Artifact.class, Long.class);
    PojoPage<Artifact> p;
    this.loadSimplePojos(products);
    QueryManager queryMgr = client.newQueryManager();
    StringQueryDefinition qd = queryMgr.newStringDefinition();
    qd.setCriteria("5");
    StringHandle results = new StringHandle();
    JacksonHandle jh = new JacksonHandle();
    p = products.search(qd, 1, jh);

    long pageNo = 1, count = 0;
    do {
      count = 0;
      p = products.search(qd, pageNo, results.withFormat(Format.JSON));

      while (p.iterator().hasNext()) {
        Artifact a = p.iterator().next();
        validateArtifact(a);
        count++;
        //				System.out.println(a.getId()+" "+a.getManufacturer().getName() +"  "+count);
      }
      assertEquals("Page total results", 0, p.getTotalSize());
      pageNo = pageNo + p.getPageSize();
      //				System.out.println(results.get().toString());
    } while (!p.isLastPage() && pageNo < p.getTotalSize());
    assertFalse("String handle is not empty", results.get().isEmpty());
    assertTrue("String handle contains results", results.get().contains("results"));
    assertFalse("String handle contains format", results.get().contains("\"format\":\"json\""));

    ObjectMapper mapper = new ObjectMapper();
    JsonNode actNode = mapper.readTree(results.get()).get("total");
    //		System.out.println(expNode.equals(actNode)+"\n"+
    // expNode.toString()+"\n"+actNode.toString());

    assertEquals("Total search results resulted are ", actNode.asInt(), 0);
  }
  // Searching for Id as Number in JSON using range query
  @Test(expected = ClassCastException.class)
  public void testPOJOcombinedSearchforNumberWithStringHandle()
      throws JsonProcessingException, IOException {
    PojoRepository<Artifact, Long> products = client.newPojoRepository(Artifact.class, Long.class);
    PojoPage<Artifact> p;
    this.loadSimplePojos(products);

    QueryManager queryMgr = client.newQueryManager();
    String queryAsString =
        "{\"search\":{\"query\":{"
            + "\"range-constraint-query\":{\"constraint-name\":\"id\", \"value\":[5,10,15,20,25,30]}},"
            + "\"options\":{\"return-metrics\":false, \"constraint\":{\"name\":\"id\", \"range\":{\"type\": \"xs:long\",\"json-property\":\"id\"}}}"
            + "}}";
    PojoQueryDefinition qd =
        (PojoQueryDefinition)
            queryMgr.newRawCombinedQueryDefinition(
                new StringHandle(queryAsString).withFormat(Format.JSON));

    StringHandle results = new StringHandle();
    JacksonHandle jh = new JacksonHandle();
    p = products.search(qd, 1, jh);

    long pageNo = 1, count = 0;
    do {
      count = 0;
      p = products.search(qd, pageNo, results.withFormat(Format.JSON));

      while (p.iterator().hasNext()) {
        Artifact a = p.iterator().next();
        validateArtifact(a);
        count++;
      }
      assertEquals("Page total results", count, p.getTotalSize());
      pageNo = pageNo + p.getPageSize();
      System.out.println(results.get().toString());
    } while (!p.isLastPage() && pageNo < p.getTotalSize());
    assertFalse("String handle is not empty", results.get().isEmpty());
    assertTrue("String handle contains results", results.get().contains("results"));
    assertTrue("String handle contains format", results.get().contains("\"format\":\"json\""));
    ObjectMapper mapper = new ObjectMapper();
    JsonNode actNode = mapper.readTree(results.get()).get("total");
    assertEquals("Total search results resulted are ", 6, actNode.asInt());
  }
  /* Searching for boolean and string in XML element using value query.
   * Purpose: To validate QueryBuilder's new value methods (in 8.0) in XML document using an element.
   *
   * Load a file that has a boolean value in a XML attribute and use query def to search on that boolean value
   *
   * Methods used : value(StructuredQueryBuilder.TextIndex index, boolean)
   *                value(StructuredQueryBuilder.TextIndex index, String)
   */
  @Test
  public void testQueryBuilderValueWithBooleanAndString()
      throws XpathException, SAXException, IOException {

    String docId[] = {"play-persons.xml"};

    TextDocumentManager docMgr = client.newTextDocumentManager();
    QueryManager queryMgr = client.newQueryManager();
    DocumentWriteSet writeset = docMgr.newWriteSet();

    // Put meta-data

    DocumentMetadataHandle metadataHandle = new DocumentMetadataHandle();
    metadataHandle.getCollections().addAll("my-collection1", "my-collection2");
    metadataHandle.getPermissions().add("app-user", Capability.UPDATE, Capability.READ);
    metadataHandle.getProperties().put("reviewed", true);
    metadataHandle.getProperties().put("myString", "foo");
    metadataHandle.getProperties().put("myInteger", 10);
    metadataHandle.getProperties().put("myDecimal", 34.56678);
    metadataHandle.getProperties().put("myCalendar", Calendar.getInstance().get(Calendar.YEAR));
    metadataHandle.setQuality(23);

    writeset.addDefault(metadataHandle);

    // Create a new document using StringHandle
    StringBuffer strBuf = new StringBuffer();

    strBuf.append("<PLAY>");
    strBuf.append("<TITLE>All's Well That Ends Well</TITLE>");
    strBuf.append("<PERSONAE>");
    strBuf.append("<TITLE>Dramatis Personae</TITLE>");

    strBuf.append("<PGROUP>");
    strBuf.append("<subgroup>true</subgroup>");

    strBuf.append("<PERSONA>KING OF FRANCE</PERSONA>");
    strBuf.append("<PERSONA>DUKE OF FLORENCE</PERSONA>");
    strBuf.append("<PERSONA>BERTRAM, Count of Rousillon.</PERSONA>");
    strBuf.append("<PERSONA>LAFEU, an old lord.</PERSONA>");
    strBuf.append("</PGROUP>");

    strBuf.append("<PGROUP>");
    strBuf.append("<subgroup>false</subgroup>");

    strBuf.append("<PERSONA>PAROLLES, a follower of Bertram.</PERSONA>");
    strBuf.append("<PERSONA>A Page. </PERSONA>");
    strBuf.append("</PGROUP>");

    strBuf.append("<PGROUP>");
    strBuf.append("<subgroup>false</subgroup>");
    strBuf.append("<PERSONA>COUNTESS OF ROUSILLON, mother to Bertram. </PERSONA>");
    strBuf.append("<PERSONA>HELENA, a gentlewoman protected by the Countess.</PERSONA>");
    strBuf.append("<PERSONA>An old Widow of Florence. </PERSONA>");
    strBuf.append("<PERSONA>DIANA, daughter to the Widow.</PERSONA>");
    strBuf.append("</PGROUP>");

    strBuf.append("<PGROUP>");
    strBuf.append("<subgroup>false</subgroup>");
    strBuf.append("<PERSONA>VIOLENTA</PERSONA>");
    strBuf.append("<PERSONA>MARIANA</PERSONA>");
    strBuf.append("<GRPDESCR>neighbours and friends to the Widow.</GRPDESCR>");
    strBuf.append("</PGROUP>");

    strBuf.append("<PERSONA>Lords, Officers, Soldiers, &amp;c., French and Florentine.</PERSONA>");
    strBuf.append("</PERSONAE>");
    strBuf.append("</PLAY>");

    writeset.add("/1/" + docId[0], new StringHandle().with(strBuf.toString()));
    docMgr.write(writeset);

    docMgr.write(writeset);

    // Search for the range with attribute value true in rangeRelativeBucketConstraintOpt.xml
    // document.
    StructuredQueryBuilder qb = new StructuredQueryBuilder();

    // Build an object that represents StructuredQueryBuilder.ElementAttribute for use in values
    // method
    // that is of type StructuredQueryBuilder.TextIndex

    QueryDefinition qd = qb.value(qb.element("subgroup"), false);

    // Create handle for the result
    StringHandle resultsHandle = new StringHandle().withFormat(Format.XML);
    queryMgr.search(qd, resultsHandle);

    // Get the result
    String resultDoc = resultsHandle.get();

    System.out.println(resultDoc);
    // Verify that search response has found 1 element attribute
    assertXpathEvaluatesTo(
        "fn:doc(\"/1/play-persons.xml\")",
        "string(//*[local-name()='response']//*[local-name()='result']//@*[local-name()='path'])",
        resultDoc);
    assertXpathEvaluatesTo(
        "3", "count(//*[local-name()='response']//*[local-name()='match'])", resultDoc);

    // Search for the following royal (XML ELEMENT) in all-well.xml document.
    StructuredQueryBuilder qbStr = new StructuredQueryBuilder();
    QueryDefinition qdStr =
        qbStr.value(
            qbStr.element("PERSONA"),
            "KING OF FRANCE",
            "DUKE OF FLORENCE",
            "BERTRAM, Count of Rousillon.",
            "LAFEU, an old lord.");

    // Create handle for the result
    StringHandle resultsHandleStr = new StringHandle().withFormat(Format.XML);
    queryMgr.search(qdStr, resultsHandleStr);

    // Get the result
    String resultDocStr = resultsHandleStr.get();

    System.out.println(resultDocStr);
    // Verify that search response has found 4 PERSONA elements under /PLAY/PERSONAE
    assertXpathEvaluatesTo(
        "fn:doc(\"/1/play-persons.xml\")",
        "string(//*[local-name()='response']//*[local-name()='result']//@*[local-name()='path'])",
        resultDocStr);
    assertXpathEvaluatesTo(
        "4", "count(//*[local-name()='response']//*[local-name()='match'])", resultDocStr);
  }