Java tutorial
/******************************************************************************* * Copyright 2015, The IKANOW Open Source Project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.ikanow.aleph2.shared.crud.mongodb.utils; import static org.junit.Assert.*; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; import org.junit.Test; import org.mongojack.internal.MongoJackModule; import scala.Tuple2; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableMap; import com.ikanow.aleph2.data_model.utils.CrudUtils; import com.ikanow.aleph2.data_model.utils.CrudUtils.MultiQueryComponent; import com.ikanow.aleph2.data_model.utils.CrudUtils.SingleQueryComponent; import com.ikanow.aleph2.data_model.utils.CrudUtils.UpdateComponent; import com.ikanow.aleph2.data_model.utils.BeanTemplateUtils; import com.ikanow.aleph2.data_model.utils.BeanTemplateUtils.BeanTemplate; import com.ikanow.aleph2.data_model.utils.Tuples; import com.ikanow.aleph2.shared.crud.mongodb.utils.MongoDbUtils; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.QueryBuilder; public class TestMongoDbUtils { // Test objects public static class TestBean { public static class NestedNestedTestBean { public String nested_nested_string_field() { return nested_nested_string_field; } private String nested_nested_string_field; } public static class NestedTestBean { public String nested_string_field() { return nested_string_field; } public NestedNestedTestBean nested_object() { return nested_object; } public List<String> nested_string_list() { return nested_string_list; } private List<String> nested_string_list; private String nested_string_field; private NestedNestedTestBean nested_object; } public String string_field() { return string_field; } public List<String> string_fields() { return string_fields; } public Boolean bool_field() { return bool_field; } public Long long_field() { return long_field; } public List<NestedTestBean> nested_list() { return nested_list; } public Map<String, String> map() { return map; } public NestedTestBean nested_object() { return nested_object; } public EnumField enum_field() { return enum_field; } protected TestBean() { } private String string_field; private List<String> string_fields; private Boolean bool_field; private Long long_field; private List<NestedTestBean> nested_list; private Map<String, String> map; private NestedTestBean nested_object; public enum EnumField { test1, test2 }; private EnumField enum_field; } /////////////////////////////////////////////// // QUERY CREATION TESTING @Test public void emptyQuery() { // No meta: final SingleQueryComponent<TestBean> query_comp_1 = CrudUtils.allOf(BeanTemplate.of(new TestBean())); final Tuple2<DBObject, DBObject> query_meta_1 = MongoDbUtils.convertToMongoQuery(query_comp_1); assertEquals("{ }", query_meta_1._1().toString()); assertEquals("{ }", query_meta_1._2().toString()); // Meta fields BeanTemplate<TestBean> template2 = BeanTemplateUtils.build(TestBean.class) .with(TestBean::string_field, null).done(); final SingleQueryComponent<TestBean> query_comp_2 = CrudUtils.anyOf(template2) .orderBy(Tuples._2T("test_field_1", 1), Tuples._2T("test_field_2", -1)); final Tuple2<DBObject, DBObject> query_meta_2 = MongoDbUtils.convertToMongoQuery(query_comp_2); assertEquals("{ }", query_meta_2._1().toString()); final BasicDBObject expected_meta_nested = new BasicDBObject("test_field_1", 1); expected_meta_nested.put("test_field_2", -1); final BasicDBObject expected_meta = new BasicDBObject("$sort", expected_meta_nested); assertEquals(expected_meta.toString(), query_meta_2._2().toString()); } @Test public void basicSingleTest() { // Queries starting with allOf // Very simple BeanTemplate<TestBean> template1 = BeanTemplateUtils.build(TestBean.class) .with(TestBean::string_field, "string_field").done(); final SingleQueryComponent<TestBean> query_comp_1 = CrudUtils.allOf(template1).when(TestBean::bool_field, true); final SingleQueryComponent<TestBean> query_comp_1b = CrudUtils.allOf(TestBean.class) .when("bool_field", true).when("string_field", "string_field"); final Tuple2<DBObject, DBObject> query_meta_1 = MongoDbUtils.convertToMongoQuery(query_comp_1); final Tuple2<DBObject, DBObject> query_meta_1b = MongoDbUtils.convertToMongoQuery(query_comp_1b); final DBObject expected_1 = QueryBuilder.start().and(QueryBuilder.start("bool_field").is(true).get(), QueryBuilder.start("string_field").is("string_field").get()).get(); assertEquals(expected_1.toString(), query_meta_1._1().toString()); assertEquals(expected_1.toString(), query_meta_1b._1().toString()); assertEquals("{ }", query_meta_1._2().toString()); // Includes extra + all the checks except the range checks final SingleQueryComponent<TestBean> query_comp_2 = CrudUtils.anyOf(TestBean.class) .when(TestBean::string_field, "string_field").withPresent(TestBean::bool_field) .withNotPresent(TestBean::long_field) .withAny(TestBean::string_field, Arrays.asList("test1a", "test1b")) .withAll(TestBean::long_field, Arrays.asList(10, 11, 12)).whenNot(TestBean::long_field, 13) .when(TestBean::enum_field, TestBean.EnumField.test1).limit(100); // (include +ve enums) final SingleQueryComponent<TestBean> query_comp_2b = CrudUtils.anyOf(TestBean.class) .when("string_field", "string_field").withPresent("bool_field").withNotPresent("long_field") .withAny("string_field", Arrays.asList("test1a", "test1b")) .withAll("long_field", Arrays.asList(10, 11, 12)).whenNot("long_field", 13) .when("enum_field", TestBean.EnumField.test1).limit(100); final Tuple2<DBObject, DBObject> query_meta_2 = MongoDbUtils.convertToMongoQuery(query_comp_2); final Tuple2<DBObject, DBObject> query_meta_2b = MongoDbUtils.convertToMongoQuery(query_comp_2b); final DBObject expected_2 = QueryBuilder.start() .or(QueryBuilder.start("string_field").is("string_field").get(), QueryBuilder.start("string_field").in(Arrays.asList("test1a", "test1b")).get(), QueryBuilder.start("bool_field").exists(true).get(), QueryBuilder.start("long_field").exists(false).get(), QueryBuilder.start("long_field").all(Arrays.asList(10, 11, 12)).get(), QueryBuilder.start("long_field").notEquals(13).get(), QueryBuilder.start("enum_field").is("test1").get()) .get(); assertEquals(expected_2.toString(), query_meta_2._1().toString()); assertEquals(expected_2.toString(), query_meta_2b._1().toString()); assertEquals("{ \"$limit\" : 100}", query_meta_2._2().toString()); } @Test public void testAllTheRangeQueries() { final SingleQueryComponent<TestBean> query_comp_1 = CrudUtils.allOf(TestBean.class) .rangeAbove(TestBean::string_field, "bbb", true).rangeBelow(TestBean::string_field, "fff", false) .rangeIn(TestBean::string_field, "ccc", false, "ddd", true) .rangeIn(TestBean::string_field, "xxx", false, "yyy", false) .rangeAbove(TestBean::long_field, 1000, false).rangeBelow(TestBean::long_field, 10000, true) .rangeIn(TestBean::long_field, 2000, true, 20000, true) .rangeIn(TestBean::long_field, 3000, true, 30000, false) .rangeIn(TestBean::enum_field, TestBean.EnumField.test1, true, TestBean.EnumField.test2, false) .orderBy(Tuples._2T("test_field_1", 1), Tuples._2T("test_field_2", -1)).limit(200); //(inc enums) final SingleQueryComponent<TestBean> query_comp_1b = CrudUtils.allOf(TestBean.class) .rangeAbove("string_field", "bbb", true).rangeBelow("string_field", "fff", false) .rangeIn("string_field", "ccc", false, "ddd", true) .rangeIn("string_field", "xxx", false, "yyy", false) .rangeAbove("long_field", 1000, false).rangeBelow("long_field", 10000, true) .rangeIn("long_field", 2000, true, 20000, true).rangeIn("long_field", 3000, true, 30000, false) .rangeIn("enum_field", TestBean.EnumField.test1, true, TestBean.EnumField.test2, false) .orderBy(Tuples._2T("test_field_1", 1)).orderBy(Tuples._2T("test_field_2", -1)).limit(200); final Tuple2<DBObject, DBObject> query_meta_1 = MongoDbUtils.convertToMongoQuery(query_comp_1); final Tuple2<DBObject, DBObject> query_meta_1b = MongoDbUtils.convertToMongoQuery(query_comp_1b); final DBObject expected_1 = QueryBuilder.start() .and(QueryBuilder.start("string_field").greaterThan("bbb").get(), QueryBuilder.start("string_field").lessThanEquals("fff").get(), QueryBuilder.start("string_field").greaterThanEquals("ccc").lessThan("ddd").get(), QueryBuilder.start("string_field").greaterThanEquals("xxx").lessThanEquals("yyy").get(), QueryBuilder.start("long_field").greaterThanEquals(1000).get(), QueryBuilder.start("long_field").lessThan(10000).get(), QueryBuilder.start("long_field").greaterThan(2000).lessThan(20000).get(), QueryBuilder.start("long_field").greaterThan(3000).lessThanEquals(30000).get(), QueryBuilder.start("enum_field").greaterThan("test1").lessThanEquals("test2").get() ).get(); final BasicDBObject expected_meta_nested = new BasicDBObject("test_field_1", 1); expected_meta_nested.put("test_field_2", -1); final BasicDBObject expected_meta = new BasicDBObject("$limit", 200); expected_meta.put("$sort", expected_meta_nested); assertEquals(expected_1.toString(), query_meta_1._1().toString()); assertEquals(expected_1.toString(), query_meta_1b._1().toString()); assertEquals(expected_meta.toString(), query_meta_1._2().toString()); } @Test public void testNestedQueries() { // 1 level of nesting final SingleQueryComponent<TestBean> query_comp_1 = CrudUtils.allOf(TestBean.class) .when(TestBean::string_field, "a").whenNot(TestBean::enum_field, TestBean.EnumField.test1) .nested(TestBean::nested_list, CrudUtils.anyOf(TestBean.NestedTestBean.class) .when(TestBean.NestedTestBean::nested_string_field, "x") .withAny(TestBean.NestedTestBean::nested_string_field, Arrays.asList("x", "y")) .rangeIn("nested_string_field", "ccc", false, "ddd", true).limit(1000) // (should be ignored) .orderBy(Tuples._2T("test_field_1", 1)) // (should be ignored) ).withPresent("long_field").limit(5).orderBy(Tuples._2T("test_field_2", -1)); final Tuple2<DBObject, DBObject> query_meta_1 = MongoDbUtils.convertToMongoQuery(query_comp_1); final DBObject expected_1 = QueryBuilder.start() .and(QueryBuilder.start("string_field").is("a").get(), QueryBuilder.start("enum_field").notEquals("test1").get(), QueryBuilder.start("nested_list.nested_string_field").is("x").get(), QueryBuilder.start("nested_list.nested_string_field").in(Arrays.asList("x", "y")).get(), QueryBuilder.start("nested_list.nested_string_field").greaterThanEquals("ccc") .lessThan("ddd").get(), QueryBuilder.start("long_field").exists(true).get()) .get(); final BasicDBObject expected_meta_nested = new BasicDBObject("test_field_2", -1); final BasicDBObject expected_meta = new BasicDBObject("$limit", 5); expected_meta.put("$sort", expected_meta_nested); assertEquals(expected_1.toString(), query_meta_1._1().toString()); assertEquals(expected_meta.toString(), query_meta_1._2().toString()); // 2 levels of nesting BeanTemplate<TestBean.NestedTestBean> nestedBean = BeanTemplateUtils.build(TestBean.NestedTestBean.class) .with("nested_string_field", "x").done(); final SingleQueryComponent<TestBean> query_comp_2 = CrudUtils.allOf(TestBean.class) .when(TestBean::string_field, "a") .nested(TestBean::nested_list, CrudUtils.anyOf(nestedBean) .when(TestBean.NestedTestBean::nested_string_field, "y") .nested(TestBean.NestedTestBean::nested_object, CrudUtils.allOf(TestBean.NestedNestedTestBean.class) .when(TestBean.NestedNestedTestBean::nested_nested_string_field, "z") .withNotPresent(TestBean.NestedNestedTestBean::nested_nested_string_field) .limit(1000) // (should be ignored) .orderBy(Tuples._2T("test_field_1", 1)) // (should be ignored) ).withAny(TestBean.NestedTestBean::nested_string_field, Arrays.asList("x", "y")) .rangeIn("nested_string_field", "ccc", false, "ddd", true)) .withPresent("long_field"); final Tuple2<DBObject, DBObject> query_meta_2 = MongoDbUtils.convertToMongoQuery(query_comp_2); final DBObject expected_2 = QueryBuilder.start().and(QueryBuilder.start("string_field").is("a").get(), QueryBuilder.start("nested_list.nested_string_field").is("x").get(), QueryBuilder.start("nested_list.nested_string_field").is("y").get(), QueryBuilder.start("nested_list.nested_string_field").in(Arrays.asList("x", "y")).get(), QueryBuilder.start("nested_list.nested_string_field").greaterThanEquals("ccc").lessThan("ddd") .get(), QueryBuilder.start("nested_list.nested_object.nested_nested_string_field").is("z").get(), QueryBuilder.start("nested_list.nested_object.nested_nested_string_field").exists(false).get(), QueryBuilder.start("long_field").exists(true).get()).get(); assertEquals(expected_2.toString(), query_meta_2._1().toString()); assertEquals("{ }", query_meta_2._2().toString()); } @Test public void testMultipleQueries() { // Just to test .. single node versions final SingleQueryComponent<TestBean> query_comp_1 = CrudUtils.allOf(TestBean.class) .rangeAbove(TestBean::string_field, "bbb", true).rangeBelow(TestBean::string_field, "fff", false) .rangeIn(TestBean::string_field, "ccc", false, "ddd", true) .rangeIn(TestBean::string_field, "xxx", false, "yyy", false) .rangeAbove(TestBean::long_field, 1000, false).rangeBelow(TestBean::long_field, 10000, true) .rangeIn(TestBean::long_field, 2000, true, 20000, true) .rangeIn(TestBean::long_field, 3000, true, 30000, false) .orderBy(Tuples._2T("test_field_1", 1)) // should be ignored .limit(200); // should be ignored final MultiQueryComponent<TestBean> multi_query_1 = CrudUtils.<TestBean>allOf(query_comp_1) .orderBy(Tuples._2T("test_field_2", -1)).limit(5); final MultiQueryComponent<TestBean> multi_query_2 = CrudUtils.<TestBean>anyOf(query_comp_1); final QueryBuilder expected_1 = QueryBuilder.start().and( QueryBuilder.start("string_field").greaterThan("bbb").get(), QueryBuilder.start("string_field").lessThanEquals("fff").get(), QueryBuilder.start("string_field").greaterThanEquals("ccc").lessThan("ddd").get(), QueryBuilder.start("string_field").greaterThanEquals("xxx").lessThanEquals("yyy").get(), QueryBuilder.start("long_field").greaterThanEquals(1000).get(), QueryBuilder.start("long_field").lessThan(10000).get(), QueryBuilder.start("long_field").greaterThan(2000).lessThan(20000).get(), QueryBuilder.start("long_field").greaterThan(3000).lessThanEquals(30000).get() ); final Tuple2<DBObject, DBObject> query_meta_1 = MongoDbUtils.convertToMongoQuery(multi_query_1); final Tuple2<DBObject, DBObject> query_meta_2 = MongoDbUtils.convertToMongoQuery(multi_query_2); final DBObject multi_expected_1 = QueryBuilder.start().and((DBObject) expected_1.get()).get(); final DBObject multi_expected_2 = QueryBuilder.start().or((DBObject) expected_1.get()).get(); assertEquals(multi_expected_1.toString(), query_meta_1._1().toString()); assertEquals(multi_expected_2.toString(), query_meta_2._1().toString()); final BasicDBObject expected_meta_nested = new BasicDBObject("test_field_2", -1); final BasicDBObject expected_meta = new BasicDBObject("$limit", 5); expected_meta.put("$sort", expected_meta_nested); assertEquals(expected_meta.toString(), query_meta_1._2().toString()); assertEquals("{ }", query_meta_2._2().toString()); // Multiple nested final SingleQueryComponent<TestBean> query_comp_2 = CrudUtils.allOf(TestBean.class) .when(TestBean::string_field, "a") .nested(TestBean::nested_list, CrudUtils.anyOf(TestBean.NestedTestBean.class) .when(TestBean.NestedTestBean::nested_string_field, "x") .nested(TestBean.NestedTestBean::nested_object, CrudUtils.allOf(TestBean.NestedNestedTestBean.class) .when(TestBean.NestedNestedTestBean::nested_nested_string_field, "z") .withNotPresent(TestBean.NestedNestedTestBean::nested_nested_string_field) .limit(1000) // (should be ignored) .orderBy(Tuples._2T("test_field_1", 1)) // (should be ignored) ).withAny(TestBean.NestedTestBean::nested_string_field, Arrays.asList("x", "y")) .rangeIn("nested_string_field", "ccc", false, "ddd", true)) .withPresent("long_field"); final MultiQueryComponent<TestBean> multi_query_3 = CrudUtils.allOf(query_comp_1, query_comp_2).limit(5); final MultiQueryComponent<TestBean> multi_query_4 = CrudUtils.anyOf(query_comp_1, query_comp_2) .orderBy(Tuples._2T("test_field_2", -1)); final MultiQueryComponent<TestBean> multi_query_5 = CrudUtils.<TestBean>allOf(query_comp_1) .also(query_comp_2).limit(5); final MultiQueryComponent<TestBean> multi_query_6 = CrudUtils.<TestBean>anyOf(query_comp_1) .also(query_comp_2).orderBy().orderBy(Tuples._2T("test_field_2", -1)); final Tuple2<DBObject, DBObject> query_meta_3 = MongoDbUtils.convertToMongoQuery(multi_query_3); final Tuple2<DBObject, DBObject> query_meta_4 = MongoDbUtils.convertToMongoQuery(multi_query_4); final Tuple2<DBObject, DBObject> query_meta_5 = MongoDbUtils.convertToMongoQuery(multi_query_5); final Tuple2<DBObject, DBObject> query_meta_6 = MongoDbUtils.convertToMongoQuery(multi_query_6); final QueryBuilder expected_2 = QueryBuilder.start().and(QueryBuilder.start("string_field").is("a").get(), QueryBuilder.start("nested_list.nested_string_field").is("x").get(), QueryBuilder.start("nested_list.nested_string_field").in(Arrays.asList("x", "y")).get(), QueryBuilder.start("nested_list.nested_string_field").greaterThanEquals("ccc").lessThan("ddd") .get(), QueryBuilder.start("nested_list.nested_object.nested_nested_string_field").is("z").get(), QueryBuilder.start("nested_list.nested_object.nested_nested_string_field").exists(false).get(), QueryBuilder.start("long_field").exists(true).get()); final DBObject multi_expected_3 = QueryBuilder.start() .and((DBObject) expected_1.get(), (DBObject) expected_2.get()).get(); final DBObject multi_expected_4 = QueryBuilder.start() .or((DBObject) expected_1.get(), (DBObject) expected_2.get()).get(); assertEquals(multi_expected_3.toString(), query_meta_3._1().toString()); assertEquals(multi_expected_4.toString(), query_meta_4._1().toString()); assertEquals(multi_expected_3.toString(), query_meta_5._1().toString()); assertEquals(multi_expected_4.toString(), query_meta_6._1().toString()); final BasicDBObject expected_meta_nested_2 = new BasicDBObject("test_field_2", -1); final BasicDBObject expected_meta_2 = new BasicDBObject("$sort", expected_meta_nested_2); assertEquals("{ \"$limit\" : 5}", query_meta_3._2().toString()); assertEquals(expected_meta_2.toString(), query_meta_4._2().toString()); assertEquals("{ \"$limit\" : 5}", query_meta_5._2().toString()); assertEquals(expected_meta_2.toString(), query_meta_6._2().toString()); } @Test public void testNestedMultiQuery() throws IOException { final BeanTemplate<TestBean> template1a = BeanTemplateUtils.build(TestBean.class) .with(TestBean::string_field, "string_field").done(); final SingleQueryComponent<TestBean> query_comp_1a = CrudUtils.anyOf(template1a); final SingleQueryComponent<TestBean> query_comp_2a = CrudUtils.allOf(TestBean.class) .when(TestBean::bool_field, true); final MultiQueryComponent<TestBean> multi_query_1 = CrudUtils .allOf(Arrays.asList(query_comp_1a, query_comp_2a)); final BeanTemplate<TestBean> template1b = BeanTemplateUtils.build(TestBean.class) .with(TestBean::string_field, "string_field_b").done(); final SingleQueryComponent<TestBean> query_comp_1b = CrudUtils.allOf(template1b); final SingleQueryComponent<TestBean> query_comp_2b = CrudUtils.anyOf(TestBean.class) .when(TestBean::bool_field, false); final MultiQueryComponent<TestBean> multi_query_2 = CrudUtils.allOf(query_comp_1b, query_comp_2b); final MultiQueryComponent<TestBean> multi_query_test_1 = CrudUtils.anyOf(multi_query_1, multi_query_2); final MultiQueryComponent<TestBean> multi_query_test_2 = CrudUtils.allOf(multi_query_1, query_comp_1b); final Tuple2<DBObject, DBObject> multi_query_meta_1 = MongoDbUtils.convertToMongoQuery(multi_query_test_1); final Tuple2<DBObject, DBObject> multi_query_meta_2 = MongoDbUtils.convertToMongoQuery(multi_query_test_2); final DBObject expected_1 = QueryBuilder .start().or( QueryBuilder.start() .and(QueryBuilder.start() .or(QueryBuilder.start("string_field").is("string_field").get()).get(), QueryBuilder.start().and(QueryBuilder.start("bool_field").is(true).get()) .get()) .get(), QueryBuilder.start().and( QueryBuilder.start() .and(QueryBuilder.start("string_field").is("string_field_b").get()).get(), QueryBuilder.start().or(QueryBuilder.start("bool_field").is(false).get()).get()) .get()) .get(); final DBObject expected_2 = QueryBuilder .start().and( QueryBuilder.start().and( QueryBuilder.start().or(QueryBuilder.start("string_field").is("string_field").get()) .get(), QueryBuilder.start().and(QueryBuilder.start("bool_field").is(true).get()).get()) .get(), QueryBuilder.start().and(QueryBuilder.start("string_field").is("string_field_b").get()) .get()) .get(); assertEquals(expected_1.toString(), multi_query_meta_1._1().toString()); assertEquals(expected_2.toString(), multi_query_meta_2._1().toString()); } /////////////////////////////////////////////// // UPDATE CREATION TESTING /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // UPDATE TESTING - BEAN @Test public void updateBeanTest() { // Test 1 - getter fields final BeanTemplate<TestBean.NestedTestBean> nested1 = BeanTemplateUtils.build(TestBean.NestedTestBean.class) .with("nested_string_field", "test1").done(); //(2) final UpdateComponent<TestBean> test1 = CrudUtils.update(TestBean.class) .add(TestBean::string_fields, "AA", false) //(0) .increment(TestBean::long_field, 4) //(1) .nested(TestBean::nested_list, CrudUtils.update(nested1) //(2) .unset(TestBean.NestedTestBean::nested_string_field) //(3a) .remove(TestBean.NestedTestBean::nested_string_list, Arrays.asList("x", "y", "z")) //(4) .add(TestBean.NestedTestBean::nested_string_list, "A", true) // (5) ).unset(TestBean::bool_field) //(3b) .unset(TestBean::nested_object) //(3c) .remove(TestBean::nested_list, CrudUtils.allOf(TestBean.NestedTestBean.class).when("nested_string_field", "1")) //6) .set(TestBean::enum_field, TestBean.EnumField.test1); final DBObject result1 = MongoDbUtils.createUpdateObject(test1); final String expected1 = "{ \"$push\" : { \"string_fields\" : \"AA\"} , \"$inc\" : { \"long_field\" : 4} , \"$set\" : { \"nested_list.nested_string_field\" : \"test1\" , \"enum_field\" : \"test1\"} , \"$unset\" : { \"nested_list.nested_string_field\" : 1 , \"bool_field\" : 1 , \"nested_object\" : 1} , \"$pullAll\" : { \"nested_list.nested_string_list\" : [ \"x\" , \"y\" , \"z\"]} , \"$addToSet\" : { \"nested_list.nested_string_list\" : \"A\"} , \"$pull\" : { \"nested_list\" : { \"$and\" : [ { \"nested_string_field\" : \"1\"}]}}}"; // (see above for analysis of results) assertEquals(expected1, result1.toString()); // Test 1b - string fields final BeanTemplate<TestBean.NestedTestBean> nested1b = BeanTemplateUtils .build(TestBean.NestedTestBean.class).with("nested_string_field", "test1").done(); //(2) final UpdateComponent<TestBean> test1b = CrudUtils.update(TestBean.class).add("string_fields", "AA", false) //(0) .increment("long_field", 4) //(1) .nested("nested_list", CrudUtils.update(nested1b) //(2) .unset("nested_string_field") //(3a) .remove("nested_string_list", Arrays.asList("x", "y", "z")) //(4) .add("nested_string_list", "A", true) // (5) ).unset("bool_field") //(3b) .unset("nested_object") //(3c) .remove("nested_list", CrudUtils.allOf(TestBean.NestedTestBean.class).when("nested_string_field", "1")) //6) ; final DBObject result1b = MongoDbUtils.createUpdateObject(test1b); final String expected1b = "{ \"$push\" : { \"string_fields\" : \"AA\"} , \"$inc\" : { \"long_field\" : 4} , \"$set\" : { \"nested_list.nested_string_field\" : \"test1\"} , \"$unset\" : { \"nested_list.nested_string_field\" : 1 , \"bool_field\" : 1 , \"nested_object\" : 1} , \"$pullAll\" : { \"nested_list.nested_string_list\" : [ \"x\" , \"y\" , \"z\"]} , \"$addToSet\" : { \"nested_list.nested_string_list\" : \"A\"} , \"$pull\" : { \"nested_list\" : { \"$and\" : [ { \"nested_string_field\" : \"1\"}]}}}"; // (see above for analysis of results) assertEquals(expected1b, result1b.toString()); // Test2 - more coverage final BeanTemplate<TestBean> testbean2 = BeanTemplateUtils.build(TestBean.class) .with(TestBean::map, ImmutableMap.<String, String>builder().put("a", "b").build()).done(); final UpdateComponent<TestBean> test2 = CrudUtils.update(testbean2) //(3) .set(TestBean::string_fields, "A").add(TestBean::string_fields, Arrays.asList("a", "b", "c"), true) //(1) .set("long_field", 1L).nested("nested_list", CrudUtils.update(TestBean.NestedTestBean.class) .add(TestBean.NestedTestBean::nested_string_list, "A", false) // (will be overwritten) ).add("nested_list.nested_string_list", Arrays.asList("x", "y"), false); //(2) final DBObject result2 = MongoDbUtils.createUpdateObject(test2); final String expected2 = "{ \"$set\" : { \"string_fields\" : \"A\" , \"long_field\" : 1 , \"map\" : { \"a\" : \"b\"}} , \"$addToSet\" : { \"string_fields\" : { \"$each\" : [ \"a\" , \"b\" , \"c\"]}} , \"$push\" : { \"nested_list.nested_string_list\" : { \"$each\" : [ \"x\" , \"y\"]}}}"; // (see above for analysis of results) assertEquals(expected2, result2.toString()); // Test3 - delete object final UpdateComponent<TestBean> test3 = CrudUtils.update(TestBean.class).deleteObject(); final DBObject result3 = MongoDbUtils.createUpdateObject(test3); assertEquals("{ \"$unset\" : null }", result3.toString()); // Test4 - bean templates as JsonNode (see _json for the other way round!) final BeanTemplate<TestBean.NestedTestBean> nested4a = BeanTemplateUtils .build(TestBean.NestedTestBean.class).with("nested_string_field", "test4a").done(); //(2) final BeanTemplate<TestBean.NestedTestBean> nested4b = BeanTemplateUtils .build(TestBean.NestedTestBean.class).with("nested_string_field", "test4b").done(); //(2) //convert to JsonNode: final ObjectMapper object_mapper = MongoJackModule .configure(BeanTemplateUtils.configureMapper(Optional.empty())); JsonNode nested4a_json = object_mapper.valueToTree(nested4a.get()); JsonNode nested4b_json = object_mapper.valueToTree(nested4b.get()); final UpdateComponent<TestBean> test4 = CrudUtils.update(TestBean.class) .set(TestBean::nested_object, nested4a_json) .add(TestBean::nested_list, Arrays.asList(nested4a_json, nested4b_json), false); final DBObject result4 = MongoDbUtils.createUpdateObject(test4); assertEquals( "{ \"$set\" : { \"nested_object\" : { \"nested_string_field\" : \"test4a\"}} , \"$push\" : { \"nested_list\" : { \"$each\" : [ { \"nested_string_field\" : \"test4a\"} , { \"nested_string_field\" : \"test4b\"}]}}}", result4.toString()); } ////////////////////////// @Test public void updateBeanTest_json() { // Test 1 - getters final BeanTemplate<TestBean.NestedTestBean> nested1 = BeanTemplateUtils.build(TestBean.NestedTestBean.class) .with("nested_string_field", "test1").done(); //(2) final UpdateComponent<JsonNode> test1 = CrudUtils.update_json(TestBean.class) .add(TestBean::string_fields, "AA", false) //(0) .increment(TestBean::long_field, 4) //(1) .nested(TestBean::nested_list, CrudUtils.update(nested1) //(2) .unset(TestBean.NestedTestBean::nested_string_field) //(3a) .remove(TestBean.NestedTestBean::nested_string_list, Arrays.asList("x", "y", "z")) //(4) .add(TestBean.NestedTestBean::nested_string_list, "A", true) // (5) ).unset(TestBean::bool_field) //(3b) .unset(TestBean::nested_object) //(3c) .remove(TestBean::nested_list, CrudUtils.allOf(TestBean.NestedTestBean.class).when("nested_string_field", "1")) //6) ; final DBObject result1 = MongoDbUtils.createUpdateObject(test1); final String expected1 = "{ \"$push\" : { \"string_fields\" : \"AA\"} , \"$inc\" : { \"long_field\" : 4} , \"$set\" : { \"nested_list.nested_string_field\" : \"test1\"} , \"$unset\" : { \"nested_list.nested_string_field\" : 1 , \"bool_field\" : 1 , \"nested_object\" : 1} , \"$pullAll\" : { \"nested_list.nested_string_list\" : [ \"x\" , \"y\" , \"z\"]} , \"$addToSet\" : { \"nested_list.nested_string_list\" : \"A\"} , \"$pull\" : { \"nested_list\" : { \"$and\" : [ { \"nested_string_field\" : \"1\"}]}}}"; // (see above for analysis of results) assertEquals(expected1, result1.toString()); // Test 1b - string fields final BeanTemplate<TestBean.NestedTestBean> nested1b = BeanTemplateUtils .build(TestBean.NestedTestBean.class).with("nested_string_field", "test1").done(); //(2) final UpdateComponent<JsonNode> test1b = CrudUtils.update_json(TestBean.class) .add("string_fields", "AA", false) //(0) .increment("long_field", 4) //(1) .nested("nested_list", CrudUtils.update(nested1b) //(2) .unset("nested_string_field") //(3a) .remove("nested_string_list", "x") //(4) .add("nested_string_list", "A", true) // (5) ).unset("bool_field") //(3b) .unset("nested_object") //(3c) .remove("nested_list", CrudUtils.allOf(TestBean.NestedTestBean.class).when("nested_string_field", "1")) //6) ; final DBObject result1b = MongoDbUtils.createUpdateObject(test1b); final String expected1b = "{ \"$push\" : { \"string_fields\" : \"AA\"} , \"$inc\" : { \"long_field\" : 4} , \"$set\" : { \"nested_list.nested_string_field\" : \"test1\"} , \"$unset\" : { \"nested_list.nested_string_field\" : 1 , \"bool_field\" : 1 , \"nested_object\" : 1} , \"$pullAll\" : { \"nested_list.nested_string_list\" : [ \"x\"]} , \"$addToSet\" : { \"nested_list.nested_string_list\" : \"A\"} , \"$pull\" : { \"nested_list\" : { \"$and\" : [ { \"nested_string_field\" : \"1\"}]}}}"; // (see above for analysis of results) assertEquals(expected1b, result1b.toString()); // Test2 - More coverage final BeanTemplate<TestBean> testbean2 = BeanTemplateUtils.build(TestBean.class) .with(TestBean::map, ImmutableMap.<String, String>builder().put("a", "b").build()).done(); final UpdateComponent<JsonNode> test2 = CrudUtils.update_json(testbean2) //(3) .set(TestBean::string_fields, "A").add(TestBean::string_fields, Arrays.asList("a", "b", "c"), true) //(1) .set("long_field", 1L).nested("nested_list", CrudUtils.update(TestBean.NestedTestBean.class) .add(TestBean.NestedTestBean::nested_string_list, "A", false) // (will be overwritten) ).add("nested_list.nested_string_list", Arrays.asList("x", "y"), false); //(2) final DBObject result2 = MongoDbUtils.createUpdateObject(test2); final String expected2 = "{ \"$set\" : { \"string_fields\" : \"A\" , \"long_field\" : 1 , \"map\" : { \"a\" : \"b\"}} , \"$addToSet\" : { \"string_fields\" : { \"$each\" : [ \"a\" , \"b\" , \"c\"]}} , \"$push\" : { \"nested_list.nested_string_list\" : { \"$each\" : [ \"x\" , \"y\"]}}}"; // (see above for analysis of results) assertEquals(expected2, result2.toString()); // Test3 - delete object final UpdateComponent<JsonNode> test3 = CrudUtils.update_json(TestBean.class).deleteObject(); final DBObject result3 = MongoDbUtils.createUpdateObject(test3); assertEquals("{ \"$unset\" : null }", result3.toString()); // Test4 - bean templates final BeanTemplate<TestBean.NestedTestBean> nested4a = BeanTemplateUtils .build(TestBean.NestedTestBean.class).with("nested_string_field", "test4a").done(); //(2) final BeanTemplate<TestBean.NestedTestBean> nested4b = BeanTemplateUtils .build(TestBean.NestedTestBean.class).with("nested_string_field", "test4b").done(); //(2) final UpdateComponent<JsonNode> test4 = CrudUtils.update_json(TestBean.class) .set(TestBean::nested_object, nested4a) .add(TestBean::nested_list, Arrays.asList(nested4a, nested4b), false); final DBObject result4 = MongoDbUtils.createUpdateObject(test4); assertEquals( "{ \"$set\" : { \"nested_object\" : { \"nested_string_field\" : \"test4a\"}} , \"$push\" : { \"nested_list\" : { \"$each\" : [ { \"nested_string_field\" : \"test4a\"} , { \"nested_string_field\" : \"test4b\"}]}}}", result4.toString()); } }