| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.ambari.server.controller.internal; |
| |
| import com.google.gson.Gson; |
| import org.apache.ambari.server.controller.AmbariManagementController; |
| import org.apache.ambari.server.controller.spi.Predicate; |
| import org.apache.ambari.server.controller.spi.Request; |
| import org.apache.ambari.server.controller.spi.RequestStatus; |
| import org.apache.ambari.server.controller.spi.Resource; |
| import org.apache.ambari.server.controller.utilities.PredicateBuilder; |
| import org.apache.ambari.server.orm.dao.ArtifactDAO; |
| import org.apache.ambari.server.orm.entities.ArtifactEntity; |
| import org.apache.ambari.server.state.Cluster; |
| import org.apache.ambari.server.state.Clusters; |
| import org.easymock.Capture; |
| import org.easymock.IAnswer; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import javax.persistence.EntityManager; |
| |
| import java.lang.reflect.Field; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeMap; |
| |
| import static org.easymock.EasyMock.anyString; |
| import static org.easymock.EasyMock.capture; |
| import static org.easymock.EasyMock.createMock; |
| import static org.easymock.EasyMock.createStrictMock; |
| import static org.easymock.EasyMock.eq; |
| import static org.easymock.EasyMock.expect; |
| import static org.easymock.EasyMock.getCurrentArguments; |
| import static org.easymock.EasyMock.newCapture; |
| import static org.easymock.EasyMock.replay; |
| import static org.easymock.EasyMock.reset; |
| import static org.easymock.EasyMock.verify; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| /** |
| * ArtifactResourceProvider unit tests. |
| */ |
| @SuppressWarnings("unchecked") |
| public class ArtifactResourceProviderTest { |
| |
| private ArtifactDAO dao = createStrictMock(ArtifactDAO.class); |
| private EntityManager em = createStrictMock(EntityManager.class); |
| private AmbariManagementController controller = createStrictMock(AmbariManagementController.class); |
| private Request request = createMock(Request.class); |
| private Clusters clusters = createMock(Clusters.class); |
| private Cluster cluster = createMock(Cluster.class); |
| private ArtifactEntity entity = createMock(ArtifactEntity.class); |
| private ArtifactEntity entity2 = createMock(ArtifactEntity.class); |
| |
| ArtifactResourceProvider resourceProvider; |
| |
| @Before |
| public void setUp() throws Exception { |
| reset(dao, em, controller, request, clusters, cluster, entity, entity2); |
| resourceProvider = new ArtifactResourceProvider(controller); |
| setPrivateField(resourceProvider, "artifactDAO", dao); |
| } |
| |
| @Test |
| public void testGetResources_instance() throws Exception { |
| Set<String> propertyIds = new HashSet<String>(); |
| TreeMap<String, String> foreignKeys = new TreeMap<String, String>(); |
| foreignKeys.put("cluster", "500"); |
| |
| Map<String, Object> childMap = new TreeMap<String, Object>(); |
| childMap.put("childKey", "childValue"); |
| Map<String, Object> child2Map = new TreeMap<String, Object>(); |
| childMap.put("child2", child2Map); |
| child2Map.put("child2Key", "child2Value"); |
| Map<String, Object> child3Map = new TreeMap<String, Object>(); |
| child2Map.put("child3", child3Map); |
| Map<String, Object> child4Map = new TreeMap<String, Object>(); |
| child3Map.put("child4", child4Map); |
| child4Map.put("child4Key", "child4Value"); |
| |
| Map<String, Object> artifact_data = new TreeMap<String, Object>(); |
| artifact_data.put("foo", "bar"); |
| artifact_data.put("child", childMap); |
| |
| Map<String, String> responseForeignKeys = new HashMap<String, String>(); |
| responseForeignKeys.put("cluster", "500"); |
| |
| // expectations |
| expect(controller.getClusters()).andReturn(clusters).anyTimes(); |
| expect(clusters.getCluster("test-cluster")).andReturn(cluster).anyTimes(); |
| expect(clusters.getClusterById(500L)).andReturn(cluster).anyTimes(); |
| expect(cluster.getClusterId()).andReturn(500L).anyTimes(); |
| expect(cluster.getClusterName()).andReturn("test-cluster").anyTimes(); |
| |
| expect(request.getPropertyIds()).andReturn(propertyIds).anyTimes(); |
| |
| expect(dao.findByNameAndForeignKeys(eq("test-artifact"), eq(foreignKeys))).andReturn(entity).once(); |
| expect(entity.getArtifactName()).andReturn("test-artifact").anyTimes(); |
| expect(entity.getForeignKeys()).andReturn(responseForeignKeys).anyTimes(); |
| expect(entity.getArtifactData()).andReturn(artifact_data).anyTimes(); |
| |
| // end of expectation setting |
| replay(dao, em, controller, request, clusters, cluster, entity, entity2); |
| |
| // test |
| PredicateBuilder pb = new PredicateBuilder(); |
| Predicate predicate = pb.begin().property("Artifacts/cluster_name").equals("test-cluster").and(). |
| property("Artifacts/artifact_name").equals("test-artifact").end().toPredicate(); |
| |
| Set<Resource> response = resourceProvider.getResources(request, predicate); |
| assertEquals(1, response.size()); |
| Resource resource = response.iterator().next(); |
| Map<String, Map<String, Object>> responseProperties = resource.getPropertiesMap(); |
| assertEquals(5, responseProperties.size()); |
| |
| Map<String, Object> artifactDataMap = responseProperties.get("artifact_data"); |
| assertEquals("bar", artifactDataMap.get("foo")); |
| |
| assertEquals("test-artifact", resource.getPropertyValue("Artifacts/artifact_name")); |
| assertEquals("test-cluster", resource.getPropertyValue("Artifacts/cluster_name")); |
| assertEquals("bar", resource.getPropertyValue("artifact_data/foo")); |
| assertEquals("childValue", resource.getPropertyValue("artifact_data/child/childKey")); |
| assertEquals("child2Value", resource.getPropertyValue("artifact_data/child/child2/child2Key")); |
| assertEquals("child4Value", resource.getPropertyValue("artifact_data/child/child2/child3/child4/child4Key")); |
| } |
| |
| @Test |
| public void testGetResources_collection() throws Exception { |
| Set<String> propertyIds = new HashSet<String>(); |
| TreeMap<String, String> foreignKeys = new TreeMap<String, String>(); |
| foreignKeys.put("cluster", "500"); |
| |
| List<ArtifactEntity> entities = new ArrayList<ArtifactEntity>(); |
| entities.add(entity); |
| entities.add(entity2); |
| |
| Map<String, Object> artifact_data = Collections.<String, Object>singletonMap("foo", "bar"); |
| Map<String, Object> artifact_data2 = Collections.<String, Object>singletonMap("foo2", "bar2"); |
| |
| Map<String, String> responseForeignKeys = new HashMap<String, String>(); |
| responseForeignKeys.put("cluster", "500"); |
| |
| // expectations |
| expect(controller.getClusters()).andReturn(clusters).anyTimes(); |
| expect(clusters.getCluster("test-cluster")).andReturn(cluster).anyTimes(); |
| expect(clusters.getClusterById(500L)).andReturn(cluster).anyTimes(); |
| expect(cluster.getClusterId()).andReturn(500L).anyTimes(); |
| expect(cluster.getClusterName()).andReturn("test-cluster").anyTimes(); |
| |
| expect(request.getPropertyIds()).andReturn(propertyIds).anyTimes(); |
| |
| expect(dao.findByForeignKeys(eq(foreignKeys))).andReturn(entities).anyTimes(); |
| expect(entity.getArtifactName()).andReturn("test-artifact").anyTimes(); |
| expect(entity.getForeignKeys()).andReturn(responseForeignKeys).anyTimes(); |
| expect(entity.getArtifactData()).andReturn(artifact_data).anyTimes(); |
| expect(entity2.getArtifactName()).andReturn("test-artifact2").anyTimes(); |
| expect(entity2.getForeignKeys()).andReturn(responseForeignKeys).anyTimes(); |
| expect(entity2.getArtifactData()).andReturn(artifact_data2).anyTimes(); |
| |
| // end of expectation setting |
| replay(dao, em, controller, request, clusters, cluster, entity, entity2); |
| |
| // test |
| PredicateBuilder pb = new PredicateBuilder(); |
| Predicate predicate = pb.begin().property("Artifacts/cluster_name").equals("test-cluster").end().toPredicate(); |
| |
| Set<Resource> response = resourceProvider.getResources(request, predicate); |
| assertEquals(2, response.size()); |
| |
| boolean artifact1Returned = false; |
| boolean artifact2Returned = false; |
| for (Resource resource : response) { |
| if (resource.getPropertyValue("Artifacts/artifact_name").equals("test-artifact")) { |
| artifact1Returned = true; |
| assertEquals("bar", resource.getPropertyValue("artifact_data/foo")); |
| assertEquals("test-cluster", resource.getPropertyValue("Artifacts/cluster_name")); |
| } else if (resource.getPropertyValue("Artifacts/artifact_name").equals("test-artifact2")) { |
| artifact2Returned = true; |
| assertEquals("bar2", resource.getPropertyValue("artifact_data/foo2")); |
| assertEquals("test-cluster", resource.getPropertyValue("Artifacts/cluster_name")); |
| } else { |
| fail("unexpected artifact name"); |
| } |
| } |
| assertTrue(artifact1Returned); |
| assertTrue(artifact2Returned); |
| } |
| |
| @Test |
| public void testCreateResource() throws Exception { |
| Capture<ArtifactEntity> createEntityCapture = newCapture(); |
| Map<String, Object> outerMap = new TreeMap<String, Object>(); |
| Map<String, Object> childMap = new TreeMap<String, Object>(); |
| outerMap.put("child", childMap); |
| childMap.put("childKey", "childValue"); |
| Map<String, Object> child2Map = new TreeMap<String, Object>(); |
| childMap.put("child2", child2Map); |
| child2Map.put("child2Key", "child2Value"); |
| Map<String, Object> child3Map = new TreeMap<String, Object>(); |
| child2Map.put("child3", child3Map); |
| Map<String, Object> child4Map = new TreeMap<String, Object>(); |
| child3Map.put("child4", child4Map); |
| child4Map.put("child4Key", "child4Value"); |
| |
| Set<Map<String, Object>> propertySet = new HashSet<Map<String, Object>>(); |
| propertySet.add(outerMap); |
| propertySet.add(child4Map); |
| |
| Map<String, Object> artifact_data = new TreeMap<String, Object>(); |
| artifact_data.put("foo", "bar"); |
| artifact_data.put("child", childMap); |
| artifact_data.put("collection", propertySet); |
| |
| TreeMap<String, String> foreignKeys = new TreeMap<String, String>(); |
| foreignKeys.put("cluster", "500"); |
| |
| Map<String, String> requestInfoProps = new HashMap<String, String>(); |
| requestInfoProps.put(Request.REQUEST_INFO_BODY_PROPERTY, bodyJson); |
| |
| |
| // map with flattened properties |
| Map<String, Object> properties = new HashMap<String, Object>(); |
| properties.put("Artifacts/artifact_name", "test-artifact"); |
| properties.put("Artifacts/cluster_name", "test-cluster"); |
| properties.put("artifact_data/foo", "bar"); |
| properties.put("artifact_data/child/childKey", "childValue"); |
| properties.put("artifact_data/child/child2/child2Key", "child2Value"); |
| properties.put("artifact_data/child/child2/child3/child4/child4Key", "child4Value"); |
| |
| Collection<Object> collectionProperties = new HashSet<Object>(); |
| properties.put("artifact_data/collection", collectionProperties); |
| |
| // collection with maps of flattened properties |
| Map<String, Object> map1 = new TreeMap<String, Object>(); |
| collectionProperties.add(map1); |
| map1.put("foo", "bar"); |
| map1.put("child/childKey", "childValue"); |
| map1.put("child/child2/child2Key", "child2Value"); |
| map1.put("child/child2/child3/child4/child4Key", "child4Value"); |
| |
| Map<String, Object> map2 = new TreeMap<String, Object>(); |
| collectionProperties.add(map2); |
| map2.put("child4Key", "child4Value"); |
| |
| Set<Map<String, Object>> requestProperties = Collections.singleton(properties); |
| |
| // expectations |
| expect(request.getRequestInfoProperties()).andReturn(requestInfoProps).anyTimes(); |
| expect(request.getProperties()).andReturn(requestProperties).anyTimes(); |
| expect(controller.getClusters()).andReturn(clusters).anyTimes(); |
| expect(clusters.getCluster("test-cluster")).andReturn(cluster).anyTimes(); |
| expect(clusters.getClusterById(500L)).andReturn(cluster).anyTimes(); |
| expect(cluster.getClusterId()).andReturn(500L).anyTimes(); |
| expect(cluster.getClusterName()).andReturn("test-cluster").anyTimes(); |
| |
| // check to see if entity already exists |
| expect(dao.findByNameAndForeignKeys(eq("test-artifact"), eq(foreignKeys))).andReturn(null).once(); |
| // create |
| dao.create(capture(createEntityCapture)); |
| |
| // end of expectation setting |
| replay(dao, em, controller, request, clusters, cluster, entity, entity2); |
| |
| resourceProvider.createResources(request); |
| |
| ArtifactEntity createEntity = createEntityCapture.getValue(); |
| assertEquals("test-artifact", createEntity.getArtifactName()); |
| Map<String, Object> actualArtifactData = createEntity.getArtifactData(); |
| // need to decompose actualArtifactData because actualArtifactData.get("collection") returns a set |
| // implementation that does not equal an identical(same elements) HashSet instance |
| assertEquals(artifact_data.size(), actualArtifactData.size()); |
| assertEquals(artifact_data.get("foo"), actualArtifactData.get("foo")); |
| assertEquals(artifact_data.get("child"), actualArtifactData.get("child")); |
| assertEquals(artifact_data.get("collection"), new HashSet(((Collection) actualArtifactData.get("collection")))); |
| assertEquals(foreignKeys, createEntity.getForeignKeys()); |
| } |
| |
| @Test |
| public void testUpdateResources() throws Exception { |
| Map<String, String> requestInfoProps = new HashMap<String, String>(); |
| requestInfoProps.put(Request.REQUEST_INFO_BODY_PROPERTY, bodyJson); |
| |
| Capture<ArtifactEntity> updateEntityCapture = newCapture(); |
| Capture<ArtifactEntity> updateEntityCapture2 = newCapture(); |
| Set<String> propertyIds = new HashSet<String>(); |
| TreeMap<String, String> foreignKeys = new TreeMap<String, String>(); |
| foreignKeys.put("cluster", "500"); |
| |
| List<ArtifactEntity> entities = new ArrayList<ArtifactEntity>(); |
| entities.add(entity); |
| entities.add(entity2); |
| |
| Map<String, Object> artifact_data = Collections.<String, Object>singletonMap("foo", "bar"); |
| Map<String, Object> artifact_data2 = Collections.<String, Object>singletonMap("foo2", "bar2"); |
| |
| Map<String, String> responseForeignKeys = new HashMap<String, String>(); |
| responseForeignKeys.put("cluster", "500"); |
| |
| // map with flattened properties |
| Map<String, Object> properties = new HashMap<String, Object>(); |
| properties.put("Artifacts/artifact_name", "test-artifact"); |
| properties.put("Artifacts/cluster_name", "test-cluster"); |
| properties.put("artifact_data/foo", "bar"); |
| properties.put("artifact_data/child/childKey", "childValue"); |
| properties.put("artifact_data/child/child2/child2Key", "child2Value"); |
| properties.put("artifact_data/child/child2/child3/child4/child4Key", "child4Value"); |
| |
| Set<Map<String, Object>> requestProperties = Collections.singleton(properties); |
| |
| properties.put("artifact_data/collection", Collections.emptySet()); |
| |
| // expectations |
| expect(request.getProperties()).andReturn(requestProperties).anyTimes(); |
| expect(request.getRequestInfoProperties()).andReturn(requestInfoProps).anyTimes(); |
| expect(controller.getClusters()).andReturn(clusters).anyTimes(); |
| expect(clusters.getCluster("test-cluster")).andReturn(cluster).anyTimes(); |
| expect(clusters.getClusterById(500L)).andReturn(cluster).anyTimes(); |
| expect(cluster.getClusterId()).andReturn(500L).anyTimes(); |
| expect(cluster.getClusterName()).andReturn("test-cluster").anyTimes(); |
| |
| expect(request.getPropertyIds()).andReturn(propertyIds).anyTimes(); |
| |
| expect(dao.findByForeignKeys(eq(foreignKeys))).andReturn(entities).anyTimes(); |
| expect(entity.getArtifactName()).andReturn("test-artifact").anyTimes(); |
| expect(entity.getForeignKeys()).andReturn(responseForeignKeys).anyTimes(); |
| expect(entity.getArtifactData()).andReturn(artifact_data).anyTimes(); |
| expect(entity2.getArtifactName()).andReturn("test-artifact2").anyTimes(); |
| expect(entity2.getForeignKeys()).andReturn(responseForeignKeys).anyTimes(); |
| expect(entity2.getArtifactData()).andReturn(artifact_data2).anyTimes(); |
| |
| expect(dao.merge(capture(updateEntityCapture))).andReturn(entity).once(); |
| expect(dao.merge(capture(updateEntityCapture2))).andReturn(entity2).once(); |
| |
| // end of expectation setting |
| replay(dao, em, controller, request, clusters, cluster, entity, entity2); |
| |
| PredicateBuilder pb = new PredicateBuilder(); |
| Predicate predicate = pb.begin().property("Artifacts/cluster_name").equals("test-cluster").end().toPredicate(); |
| |
| RequestStatus response = resourceProvider.updateResources(request, predicate); |
| ArtifactEntity updateEntity = updateEntityCapture.getValue(); |
| ArtifactEntity updateEntity2 = updateEntityCapture2.getValue(); |
| |
| Gson serializer = new Gson(); |
| ArtifactEntity expected = new ArtifactEntity(); |
| expected.setArtifactData((Map<String, Object>) serializer.<Map<String, Object>>fromJson( |
| bodyJson, Map.class).get("artifact_data")); |
| |
| assertEquals(expected.getArtifactData(), updateEntity.getArtifactData()); |
| assertEquals(expected.getArtifactData(), updateEntity2.getArtifactData()); |
| |
| if (updateEntity.getArtifactName().equals("test-artifact")) { |
| assertEquals("test-artifact2",updateEntity2.getArtifactName() ); |
| } else if (updateEntity.getArtifactName().equals("test-artifact2")) { |
| assertEquals("test-artifact", updateEntity2.getArtifactName()); |
| } else { |
| fail ("Unexpected artifact name: " + updateEntity.getArtifactName()); |
| } |
| |
| assertEquals(foreignKeys, updateEntity.getForeignKeys()); |
| assertEquals(foreignKeys, updateEntity2.getForeignKeys()); |
| |
| assertEquals(RequestStatus.Status.Complete, response.getStatus()); |
| |
| verify(dao, em, controller, request, clusters, cluster, entity, entity2); |
| } |
| |
| @Test |
| public void testDeleteResources() throws Exception { |
| |
| Capture<ArtifactEntity> deleteEntityCapture = newCapture(); |
| Capture<ArtifactEntity> deleteEntityCapture2 = newCapture(); |
| TreeMap<String, String> foreignKeys = new TreeMap<String, String>(); |
| foreignKeys.put("cluster", "500"); |
| |
| List<ArtifactEntity> entities = new ArrayList<ArtifactEntity>(); |
| entities.add(entity); |
| entities.add(entity2); |
| |
| Map<String, Object> artifact_data = Collections.<String, Object>singletonMap("foo", "bar"); |
| Map<String, Object> artifact_data2 = Collections.<String, Object>singletonMap("foo2", "bar2"); |
| |
| Map<String, String> responseForeignKeys = new HashMap<String, String>(); |
| responseForeignKeys.put("cluster", "500"); |
| |
| // expectations |
| expect(controller.getClusters()).andReturn(clusters).anyTimes(); |
| expect(clusters.getCluster("test-cluster")).andReturn(cluster).anyTimes(); |
| expect(clusters.getClusterById(500L)).andReturn(cluster).anyTimes(); |
| expect(cluster.getClusterId()).andReturn(500L).anyTimes(); |
| expect(cluster.getClusterName()).andReturn("test-cluster").anyTimes(); |
| |
| |
| expect(entity.getArtifactName()).andReturn("test-artifact").anyTimes(); |
| expect(entity.getForeignKeys()).andReturn(responseForeignKeys).anyTimes(); |
| expect(entity.getArtifactData()).andReturn(artifact_data).anyTimes(); |
| expect(entity2.getArtifactName()).andReturn("test-artifact2").anyTimes(); |
| expect(entity2.getForeignKeys()).andReturn(responseForeignKeys).anyTimes(); |
| expect(entity2.getArtifactData()).andReturn(artifact_data2).anyTimes(); |
| |
| IAnswer<ArtifactEntity> findByNameAndForeignKeys = new IAnswer<ArtifactEntity>() { |
| @Override |
| public ArtifactEntity answer() throws Throwable { |
| String artifactName = (String) getCurrentArguments()[0]; |
| |
| if ("test-artifact".equals(artifactName)) { |
| return entity; |
| } else if ("test-artifact2".equals(artifactName)) { |
| return entity2; |
| } else { |
| return null; |
| } |
| } |
| }; |
| |
| expect(dao.findByForeignKeys(eq(foreignKeys))).andReturn(entities).once(); |
| expect(dao.findByNameAndForeignKeys(anyString(), eq(foreignKeys))).andAnswer(findByNameAndForeignKeys).once(); |
| dao.remove(capture(deleteEntityCapture)); |
| expect(dao.findByNameAndForeignKeys(anyString(), eq(foreignKeys))).andAnswer(findByNameAndForeignKeys).once(); |
| dao.remove(capture(deleteEntityCapture2)); |
| |
| // end of expectation setting |
| replay(dao, em, controller, request, clusters, cluster, entity, entity2); |
| |
| PredicateBuilder pb = new PredicateBuilder(); |
| Predicate predicate = pb.begin().property("Artifacts/cluster_name").equals("test-cluster").end().toPredicate(); |
| |
| RequestStatus response = resourceProvider.deleteResources(new RequestImpl(null, null, null, null), predicate); |
| ArtifactEntity deleteEntity = deleteEntityCapture.getValue(); |
| ArtifactEntity deleteEntity2 = deleteEntityCapture2.getValue(); |
| |
| if (deleteEntity.getArtifactName().equals("test-artifact")) { |
| assertEquals("test-artifact2", deleteEntity2.getArtifactName()); |
| } else if (deleteEntity.getArtifactName().equals("test-artifact2")) { |
| assertEquals("test-artifact", deleteEntity2.getArtifactName()); |
| } else { |
| fail ("Unexpected artifact name: " + deleteEntity.getArtifactName()); |
| } |
| |
| assertEquals(foreignKeys, deleteEntity.getForeignKeys()); |
| assertEquals(foreignKeys, deleteEntity2.getForeignKeys()); |
| |
| assertEquals(RequestStatus.Status.Complete, response.getStatus()); |
| |
| verify(dao, em, controller, request, clusters, cluster, entity, entity2); |
| } |
| |
| |
| private void setPrivateField(Object o, String field, Object value) throws Exception{ |
| Class<?> c = o.getClass(); |
| Field f = c.getDeclaredField(field); |
| f.setAccessible(true); |
| f.set(o, value); |
| } |
| |
| private String bodyJson = |
| "{ " + |
| " \"artifact_data\" : {" + |
| " \"foo\" : \"bar\"," + |
| " \"child\" : {" + |
| " \"childKey\" : \"childValue\"," + |
| " \"child2\" : {" + |
| " \"child2Key\" : \"child2Value\"," + |
| " \"child3\" : {" + |
| " \"child4\" : {" + |
| " \"child4Key\" : \"child4Value\"" + |
| " }" + |
| " }" + |
| " }" + |
| " }," + |
| " \"collection\" : [" + |
| " {" + |
| " \"child\" : {" + |
| " \"childKey\" : \"childValue\"," + |
| " \"child2\" : {" + |
| " \"child2Key\" : \"child2Value\"," + |
| " \"child3\" : {" + |
| " \"child4\" : {" + |
| " \"child4Key\" : \"child4Value\"" + |
| " }" + |
| " }" + |
| " }" + |
| " }" + |
| " }," + |
| " {" + |
| " \"child4Key\" : \"child4Value\"" + |
| " } " + |
| " ]" + |
| " }" + |
| "}"; |
| } |