@Test
public void testFindDataObjectsQuerySerialization() throws IOException {

    Assert.assertEquals(
            DXJSON.parseJson("{\"scope\": {\"project\":\"project-000000000000000000000000\"}}"),
            mapper.valueToTree(DXSearch.findDataObjects()
                    .inProject(DXProject.getInstance("project-000000000000000000000000"))
                    .buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"scope\": {\"project\":\"project-000000000000000000000000\", \"folder\": \"/my/subfolder\", \"recurse\": false}}"),
            mapper.valueToTree(DXSearch
                    .findDataObjects()
                    .inFolder(DXProject.getInstance("project-000000000000000000000000"),
                            "/my/subfolder").buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"scope\": {\"project\": \"project-000000000000000000000000\"}, \"name\": \"dnanexus\"}"),
            mapper.valueToTree(DXSearch.findDataObjects()
                    .inProject(DXProject.getInstance("project-000000000000000000000000"))
                    .nameMatchesExactly("dnanexus").buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"name\": \"dnanexus\"}"),
            mapper.valueToTree(DXSearch.findDataObjects().nameMatchesExactly("dnanexus")
                    .buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"name\": {\"regexp\": \"(DNA|dna)nexus\"}}"),
            mapper.valueToTree(DXSearch.findDataObjects().nameMatchesRegexp("(DNA|dna)nexus")
                    .buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"name\": {\"regexp\": \"[dr]nanexus\"}}"),
            mapper.valueToTree(DXSearch.findDataObjects()
                    .nameMatchesRegexp("[dr]nanexus", false).buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"name\": {\"regexp\": \"[dr]nanexus\", \"flags\": \"i\"}}"),
            mapper.valueToTree(DXSearch.findDataObjects()
                    .nameMatchesRegexp("[dr]nanexus", true).buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"name\": {\"glob\": \"*nexus\"}}"),
            mapper.valueToTree(DXSearch.findDataObjects().nameMatchesGlob("*nexus")
                    .buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"visibility\": \"hidden\"}"),
            mapper.valueToTree(DXSearch.findDataObjects()
                    .withVisibility(DXSearch.VisibilityQuery.HIDDEN).buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"level\": \"ADMINISTER\"}"),
            mapper.valueToTree(DXSearch.findDataObjects()
                    .withMinimumAccessLevel(AccessLevel.ADMINISTER).buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"describe\": true}"),
            mapper.valueToTree(DXSearch.findDataObjects().includeDescribeOutput()
                    .buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"describe\": {\"properties\": true}}"),
            mapper.valueToTree(DXSearch.findDataObjects()
                    .includeDescribeOutput(DXDataObject.DescribeOptions.get().withProperties())
                    .buildRequestHash()));
    Assert.assertEquals(DXJSON.parseJson("{\"tags\": \"a\"}"),
            mapper.valueToTree(DXSearch.findDataObjects().withTag("a").buildRequestHash()));
    Assert.assertEquals(DXJSON
            .parseJson("{\"tags\": {\"$or\": [{\"$and\": [\"a\", \"b\"]}, \"c\"]}}"), mapper
            .valueToTree(DXSearch
                    .findDataObjects()
                    .withTags(
                            DXSearch.TagsQuery.anyOf(DXSearch.TagsQuery.allOf("a", "b"),
                                    DXSearch.TagsQuery.of("c"))).buildRequestHash()));
    Assert.assertEquals(DXJSON.parseJson("{\"type\": \"a\"}"),
            mapper.valueToTree(DXSearch.findDataObjects().withType("a").buildRequestHash()));
    Assert.assertEquals(DXJSON
            .parseJson("{\"type\": {\"$or\": [{\"$and\": [\"a\", \"b\"]}, \"c\"]}}"), mapper
            .valueToTree(DXSearch
                    .findDataObjects()
                    .withTypes(
                            DXSearch.TypeQuery.anyOf(DXSearch.TypeQuery.allOf("a", "b"),
                                    DXSearch.TypeQuery.of("c"))).buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"properties\": {\"foo\": true}}"),
            mapper.valueToTree(DXSearch.findDataObjects().withProperty("foo")
                    .buildRequestHash()));
    Assert.assertEquals(DXJSON
            .parseJson("{\"properties\": {\"$and\": [{\"foo\": true}, {\"bar\": \"a\"}]}}"),
            mapper.valueToTree(DXSearch.findDataObjects().withProperty("foo")
                    .withProperty("bar", "a").buildRequestHash()));
    Assert.assertEquals(
            DXJSON.parseJson("{\"properties\": {\"$and\": [{\"foo\": true}, {\"bar\": \"a\"}, {\"baz\": \"b\"}]}}"),
            mapper.valueToTree(DXSearch.findDataObjects().withProperty("foo")
                    .withProperty("bar", "a")
                    .withProperties(PropertiesQuery.withKeyAndValue("baz", "b"))
                    .buildRequestHash()));
    Assert.assertEquals(DXJSON.parseJson("{\"id\": [\"record-111100000000000000000000\"]}"),
            mapper.valueToTree(DXSearch
                    .findDataObjects()
                    .withIdsIn(
                            ImmutableList.of(DXRecord
                                    .getInstance("record-111100000000000000000000")))
                    .buildRequestHash()));
    try {
        DXSearch.findDataObjects()
                .inProject(DXProject.getInstance("project-000000000000000000000000"))
                .inProject(DXProject.getInstance("project-111100000000000000000000"));
        Assert.fail("Expected double setting of inProject to fail");
    } catch (IllegalStateException e) {
        // Expected
    }
    try {
        DXSearch.findDataObjects()
                .inFolder(DXProject.getInstance("project-000000000000000000000000"), "/1")
                .inFolder(DXProject.getInstance("project-000000000000000000000000"), "/2");
        Assert.fail("Expected double setting of inFolder to fail");
    } catch (IllegalStateException e) {
        // Expected
    }
    try {
        DXSearch.findDataObjects().nameMatchesExactly("ab").nameMatchesGlob("*b");
        Assert.fail("Expected double setting of name parameters to fail");
    } catch (IllegalStateException e) {
        // Expected
    }
    try {
        DXSearch.findDataObjects().withMinimumAccessLevel(AccessLevel.NONE);
        Assert.fail("Expected minimumAccessLevel=NONE to fail");
    } catch (IllegalArgumentException e) {
        // Expected
    }
    try {
        DXSearch.findDataObjects().withClassApplet().withClassFile();
        Assert.fail("Expected setting multiple class constraints to fail");
    } catch (IllegalStateException e) {
        // Expected
    }
    try {
        DXSearch.findDataObjects().withIdsIn(ImmutableList.<DXDataObject>of())
                .withIdsIn(ImmutableList.<DXDataObject>of());
        Assert.fail("Expected double setting of withIdsIn to fail");
    } catch (IllegalStateException e) {
        // Expected
    }
}