/** * Produce a comma delimited text from a JSONArray of JSONObjects using a provided list of names. * The list of names is not included in the output. * * @param names A JSONArray of strings. * @param ja A JSONArray of JSONObjects. * @return A comma delimited text. * @throws JSONException */ public static String toString(JSONArray names, JSONArray ja) throws JSONException { if (names == null || names.length() == 0) { return null; } StringBuffer sb = new StringBuffer(); for (int i = 0; i < ja.length(); i += 1) { JSONObject jo = ja.optJSONObject(i); if (jo != null) { sb.append(rowToString(jo.toJSONArray(names))); } } return sb.toString(); }
@SuppressWarnings("unchecked") protected <T> T[] getArray(JSONArray arr, Class<T> typeHint) throws JSONException { if (arr.length() == 0) { if (typeHint.equals(Object.class)) { return (T[]) new String[0]; } else { return (T[]) Array.newInstance(typeHint, 0); } } Object o = getObject(arr.get(0), typeHint); T[] array = (T[]) Array.newInstance(o.getClass(), arr.length()); for (int i = 0; i < arr.length(); i++) { array[i] = getObject(arr.get(i), typeHint); } return array; }
protected int getPermissionBitMap(JSONArray jsonArray) throws JSONException { int bitmap = 0; for (int i = 0; i < jsonArray.length(); i++) { bitmap = bitmap | Permissions.parse(jsonArray.getString(i).toLowerCase()).getPermission(); } return bitmap; }
@Override protected void init() { String versionName = "version"; String statusName = "status"; String contributeName = "contribute"; JSONObject versionJSON = JSONUtil.getJSONObject(json, versionName); if (versionJSON != null) version = new Version(versionJSON); JSONObject statusJSON = JSONUtil.getJSONObject(json, statusName); if (statusJSON != null) status = new Status(statusJSON); JSONObject contributeJSON = JSONUtil.getJSONObject(json, contributeName); if (contributeJSON == null) { JSONArray contributeArray = JSONUtil.getJSONArray(json, contributeName); if (contributeArray != null) { for (int i = 0; i < contributeArray.length(); i++) { JSONObject object = contributeArray.optJSONObject(i); if (object != null) addContribute(new Contribute(object, Contribute.CONTRIBUTETYPE.LIFECYCLE)); } } } else { addContribute(new Contribute(contributeJSON, Contribute.CONTRIBUTETYPE.LIFECYCLE)); } }
/** * Produce a comma delimited text row from a JSONArray. Values containing the comma character will * be quoted. * * @param ja A JSONArray of strings. * @return A string ending in NEWLINE. */ public static String rowToString(JSONArray ja) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < ja.length(); i += 1) { if (i > 0) { sb.append(','); } Object o = ja.opt(i); if (o != null) { String s = o.toString(); if (s.indexOf(',') >= 0) { if (s.indexOf('"') >= 0) { sb.append('\''); sb.append(s); sb.append('\''); } else { sb.append('"'); sb.append(s); sb.append('"'); } } else { sb.append(s); } } } sb.append('\n'); return sb.toString(); }
/** * Produce a JSONArray of JSONObjects from a comma delimited text string using a supplied * JSONArray as the source of element names. * * @param names A JSONArray of strings. * @param x A JSONTokener of the source text. * @return A JSONArray of JSONObjects. * @throws JSONException */ public static JSONArray toJSONArray(JSONArray names, JSONTokener x) throws JSONException { if (names == null || names.length() == 0) { return null; } JSONArray ja = new JSONArray(); for (; ; ) { JSONObject jo = rowToJSONObject(names, x); if (jo == null) { break; } ja.put(jo); } if (ja.length() == 0) { return null; } return ja; }
/** Access contentfinder below /content */ @Test public void testContentView() throws JSONException, ClientException { RequestExecutor exec = authorAuthor.http.doGet(CONTENTFINDER_ASSET_VIEW + "/content", 200); // verify via hits length JSONObject searchResultJson = new JSONObject(exec.getContent()); JSONArray hits = searchResultJson.getJSONArray("hits"); Assert.assertTrue("No hits found for search with query 'geometrixx'", hits.length() > 0); }
@Test public void testWithCurrentResource() throws Exception { context.currentResource( context.resourceResolver().getResource("/content/sample/en/jcr:content")); JSONArray result = getJsonResult(); assertEquals(2, result.length()); assertItem(result.getJSONObject(0), "/content/sample/en/page1", "title1"); assertItem(result.getJSONObject(1), "/content/sample/en/page2", "title2"); }
/** * Test bug #36640 - Resources are not searchable after moving/merging tags * * @see https://issues.adobe.com/browse/CQ5-13533 */ @Test @UseVersion(ANY_BUT_5_5) public void testPageViewSearchAfterMovingTags() throws JSONException, ClientException { TagClient tagClient = adminAuthor.getClient(TagClient.class); final String ns = "itnamespace"; final String tag = "tagOne"; final String tagID = getTagID(ns, tag); try { // create tag tagClient.createTag("Integration Tests", ns, "Created during IT tests.", null); tagClient.createTag("Test Tag", tag, "", getTagID(ns, null)); // tag some content tagClient.setTag(ROOT_PAGE_HANDLE, "+" + tagID); // test cf search JSONArray hits = searchPagesForTag(tagID); Assert.assertTrue("No hits found for tag ID '" + tagID + "'", hits.length() > 0); Assert.assertEquals(ROOT_PAGE_HANDLE, hits.getJSONObject(0).get("path")); // move tag final String newTag = "tagTwo"; final String newTagID = getTagID(ns, newTag); tagClient.moveTag(tagID, newTagID, 200); // test cf search with new tag id hits = searchPagesForTag(newTagID); Assert.assertTrue("No hits found for tag ID '" + newTagID + "'", hits.length() > 0); Assert.assertEquals(ROOT_PAGE_HANDLE, hits.getJSONObject(0).get("path")); // test cf search with old tag id hits = searchPagesForTag(tagID); Assert.assertTrue("No hits found for tag ID '" + tagID + "'", hits.length() > 0); Assert.assertEquals(ROOT_PAGE_HANDLE, hits.getJSONObject(0).get("path")); } finally { // raw node delete here for safe cleanup (deleteTag() does too much validation) tagClient.delete("/etc/tags/" + ns); } }
@Test public void testWithPath() throws Exception { context .request() .setParameterMap(ImmutableValueMap.of(AbstractPageProvider.RP_PATH, "/content/sample/en")); JSONArray result = getJsonResult(); assertEquals(2, result.length()); assertItem(result.getJSONObject(0), "/content/sample/en/page1", "title1"); assertItem(result.getJSONObject(1), "/content/sample/en/page2", "title2"); }
public static void extractTranslations( final JSONWriter writer, final Iterable<Resource> translations) throws JSONException, IOException { for (final Resource translation : translations) { final JSONArray timestampFields = new JSONArray(); final ValueMap vm = translation.adaptTo(ValueMap.class); if (!vm.containsKey("jcr:description")) { continue; // if there's no translation, we're done here } String languageLabel = translation.getName(); if (languageLabel.equals("nb")) { // SPECIAL CASE FOR LEGACY EXPORTER ONLY: // the label for norwegian changed between 6.0 and 6.1 // (i.e. this section must be removed for 6.1 exporter) languageLabel = "no"; } writer.key(languageLabel); JSONWriter translationObject = writer.object(); translationObject.key("jcr:description"); translationObject.value(URLEncoder.encode((String) vm.get("jcr:description"), "UTF-8")); if (vm.containsKey("jcr:createdBy")) { translationObject.key("jcr:createdBy"); translationObject.value(URLEncoder.encode((String) vm.get("jcr:createdBy"), "UTF-8")); } if (vm.containsKey("jcr:title")) { translationObject.key("jcr:title"); translationObject.value(URLEncoder.encode((String) vm.get("jcr:title"), "UTF-8")); } if (vm.containsKey("postEdited")) { translationObject.key("postEdited"); translationObject.value(vm.get("postEdited")); } if (vm.containsKey("translationDate")) { translationObject.key("translationDate"); translationObject.value(((Calendar) vm.get("translationDate")).getTimeInMillis()); timestampFields.put("translationDate"); } if (vm.containsKey("jcr:created")) { translationObject.key("jcr:created"); translationObject.value(((Calendar) vm.get("jcr:created")).getTimeInMillis()); timestampFields.put("jcr:created"); } if (timestampFields.length() > 0) { translationObject.key(ContentTypeDefinitions.LABEL_TIMESTAMP_FIELDS); translationObject.value(timestampFields); } translationObject.endObject(); } }
@Test public void testWithPredicate() throws Exception { context.registerService(PredicateProvider.class, new DummyPredicateProvider()); context .request() .setParameterMap( ImmutableValueMap.of( AbstractPageProvider.RP_PATH, "/content/sample/en", AbstractPageProvider.RP_PREDICATE, DummyPredicateProvider.PREDICATE_PAGENAME_PAGE1)); JSONArray result = getJsonResult(); assertEquals(1, result.length()); assertItem(result.getJSONObject(0), "/content/sample/en/page1", "title1"); }
/** Seach images in contentfinder below /content/dam */ @Test public void testDamSearch() throws JSONException, ClientException { String query = ".jpg"; // built the URL parameters URLParameterBuilder params = new URLParameterBuilder(); params.add(new BasicNameValuePair("query", query)); params.add(new BasicNameValuePair("mimeType", "image")); params.add(new BasicNameValuePair("_charset", "utf-8")); RequestExecutor exec = authorAuthor.http.doGet(CONTENTFINDER_ASSET_VIEW + "/content/dam", params, 200); // verify via hits length JSONObject searchResultJson = new JSONObject(exec.getContent()); JSONArray hits = searchResultJson.getJSONArray("hits"); Assert.assertTrue("No hits found for search with query 'geometrixx'", hits.length() > 0); }
/** * Takes the original request and starts the batching. * * @param request * @param response * @throws IOException */ protected void batchRequest( SlingHttpServletRequest request, SlingHttpServletResponse response, boolean allowModify) throws IOException { // Grab the JSON block out of it and convert it to RequestData objects we can use. String json = request.getParameter(REQUESTS_PARAMETER); List<RequestInfo> batchedRequests = new ArrayList<RequestInfo>(); try { JSONArray arr = new JSONArray(json); for (int i = 0; i < arr.length(); i++) { JSONObject obj = arr.getJSONObject(i); RequestInfo r = new RequestInfo(obj); if (allowModify || r.isSafe()) { batchedRequests.add(r); } } } catch (JSONException e) { response.sendError( HttpServletResponse.SC_BAD_REQUEST, "Failed to parse the " + REQUESTS_PARAMETER + " parameter"); LOGGER.warn("Failed to parse the " + REQUESTS_PARAMETER + " parameter"); return; } // Loop over the requests and handle each one. try { StringWriter sw = new StringWriter(); JSONWriter write = new JSONWriter(sw); write.object(); write.key("results"); write.array(); for (RequestInfo r : batchedRequests) { doRequest(request, response, r, write); } write.endArray(); write.endObject(); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(sw.getBuffer().toString()); } catch (JSONException e) { LOGGER.warn("Failed to create a JSON response"); response.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to write JSON response"); } }
@Test public void testProperPost() throws ServletException, IOException, RepositoryException, JSONException, AccessDeniedException, StorageClientException { SlingHttpServletRequest request = createMock(SlingHttpServletRequest.class); SlingHttpServletResponse response = createMock(SlingHttpServletResponse.class); javax.jcr.Session jcrSession = Mockito.mock( javax.jcr.Session.class, Mockito.withSettings().extraInterfaces(SessionAdaptable.class)); Session mockSession = mock(Session.class); ContentManager contentManager = mock(ContentManager.class); when(mockSession.getContentManager()).thenReturn(contentManager); Mockito.when(((SessionAdaptable) jcrSession).getSession()).thenReturn(mockSession); ResourceResolver resourceResolver = mock(ResourceResolver.class); Mockito.when(resourceResolver.adaptTo(javax.jcr.Session.class)).thenReturn(jcrSession); expect(request.getResourceResolver()).andReturn(resourceResolver); // Provide parameters String[] dimensions = new String[] {"16x16", "32x32"}; addStringRequestParameter(request, "img", "/~johndoe/people.png"); addStringRequestParameter(request, "save", "/~johndoe/breadcrumbs"); addStringRequestParameter(request, "x", "10"); addStringRequestParameter(request, "y", "10"); addStringRequestParameter(request, "width", "70"); addStringRequestParameter(request, "height", "70"); addStringRequestParameter(request, "dimensions", StringUtils.join(dimensions, 0, ';')); expect(request.getRemoteUser()).andReturn("johndoe"); String imagePath = "a:johndoe/people.png"; when(contentManager.getInputStream(imagePath)) .thenReturn(getClass().getClassLoader().getResourceAsStream("people.png")); when(contentManager.get(anyString())).thenReturn(new Content("foo", null)); SparseContentResource someResource = mock(SparseContentResource.class); when(someResource.adaptTo(Content.class)) .thenReturn( new Content( imagePath, ImmutableMap.of( "mimeType", (Object) "image/png", "_bodyLocation", "2011/lt/zz/x8"))); JackrabbitSession jrSession = mock(JackrabbitSession.class); SparseMapUserManager userManager = mock(SparseMapUserManager.class); when(userManager.getSession()).thenReturn(mockSession); when(jrSession.getUserManager()).thenReturn(userManager); when(resourceResolver.adaptTo(javax.jcr.Session.class)).thenReturn(jrSession); when(resourceResolver.getResource(anyString())).thenReturn(someResource); // Capture output. ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintWriter write = new PrintWriter(baos); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); expect(response.getWriter()).andReturn(write); replay(); servlet.doPost(request, response); write.flush(); String s = baos.toString("UTF-8"); JSONObject o = new JSONObject(s); JSONArray files = o.getJSONArray("files"); assertEquals(2, files.length()); for (int i = 0; i < files.length(); i++) { String url = files.getString(i); assertEquals("/~johndoe/breadcrumbs/" + dimensions[i] + "_people.png", url); } }
public static void extractJournalEntry( final JSONWriter entryObject, final JournalEntry entry, final Writer rawWriter) throws JSONException, IOException { final Resource thisResource = entry.getTextComment().getResource(); final ValueMap vm = thisResource.adaptTo(ValueMap.class); final JSONArray timestampFields = new JSONArray(); // make sure we only migrate the fields we want final Map<String, Boolean> fieldsToMigrate = new HashMap<String, Boolean>(); fieldsToMigrate.put("userIdentifier", true); fieldsToMigrate.put("authorizableId", true); fieldsToMigrate.put("published", true); fieldsToMigrate.put("jcr:description", true); fieldsToMigrate.put("jcr:title", true); fieldsToMigrate.put("negative", true); fieldsToMigrate.put("positive", true); fieldsToMigrate.put("sentiment", true); for (final Map.Entry<String, Object> prop : vm.entrySet()) { if (!fieldsToMigrate.containsKey(prop.getKey())) { continue; } final Object value = prop.getValue(); if (prop.getKey().equals("published") && value instanceof GregorianCalendar) { timestampFields.put("added"); entryObject.key("added"); entryObject.value(((Calendar) value).getTimeInMillis()); } else { entryObject.key(prop.getKey()); try { entryObject.value(URLEncoder.encode(prop.getValue().toString(), "UTF-8")); } catch (final UnsupportedEncodingException e) { throw new JSONException( "Unsupported encoding (UTF-8) for resource at " + thisResource.getPath(), e); } } } // resource type has changed, so ignore the current one and force the new one entryObject.key("sling:resourceType"); entryObject.value("social/journal/components/hbs/entry_topic"); if (timestampFields.length() > 0) { entryObject.key(ContentTypeDefinitions.LABEL_TIMESTAMP_FIELDS); entryObject.value(timestampFields); } final Resource translationResource = thisResource.getChild("translation"); if (null != translationResource) { extractTranslation(entryObject, translationResource); } if (entry.hasAttachments()) { entryObject.key(ContentTypeDefinitions.LABEL_ATTACHMENTS); JSONWriter attachmentsArray = entryObject.array(); List<Resource> attachmentList = entry.getAttachments(); for (final Resource attachment : attachmentList) { extractAttachment(rawWriter, attachmentsArray.object(), attachment); attachmentsArray.endObject(); } entryObject.endArray(); } if (entry.hasComments()) { final Iterator<Comment> posts = entry.getComments(); entryObject.key(ContentTypeDefinitions.LABEL_REPLIES); final JSONWriter replyWriter = entryObject.object(); while (posts.hasNext()) { final Comment childPost = posts.next(); replyWriter.key(childPost.getId()); extractComment( replyWriter.object(), childPost, entry.getResource().getResourceResolver(), rawWriter); replyWriter.endObject(); } entryObject.endObject(); } }
public static void extractProperties( final JSONWriter object, final Map<String, Object> properties, final Map<String, String> renamedProperties, final String resourceType) throws JSONException { final JSONArray timestampFields = new JSONArray(); boolean setResourceType = false; for (Map.Entry<String, Object> prop : properties.entrySet()) { Object value = prop.getValue(); String key; if (null != renamedProperties && renamedProperties.containsKey(prop.getKey())) { key = renamedProperties.get(prop.getKey()); if (null == key) { continue; // we're excluding this property from the export } } else { key = prop.getKey(); } if (null != resourceType && key.equals(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY)) { value = resourceType; setResourceType = true; } if (value instanceof String[]) { final JSONArray list = new JSONArray(); for (String v : (String[]) value) { try { list.put(URLEncoder.encode(v, "UTF-8")); } catch (final UnsupportedEncodingException e) { throw new JSONException( "String value cannot be encoded as UTF-8 for JSON transmission", e); } } object.key(key); object.value(list); } else if (value instanceof GregorianCalendar) { timestampFields.put(key); object.key(key); object.value(((Calendar) value).getTimeInMillis()); } else if (value instanceof InputStream) { object.key(ContentTypeDefinitions.LABEL_ENCODED_DATA_FIELDNAME); object.value(key); object.key(ContentTypeDefinitions.LABEL_ENCODED_DATA); try { final InputStream data = (InputStream) value; byte[] byteData = new byte[DATA_ENCODING_CHUNK_SIZE]; int read = 0; final StringBuilder stringBuilder = new StringBuilder(); while (read != -1) { read = data.read(byteData); if (read > 0 && read < DATA_ENCODING_CHUNK_SIZE) { // make a right-size container for the byte data actually read byte[] byteArray = new byte[read]; System.arraycopy(byteData, 0, byteArray, 0, read); byte[] encodedBytes = Base64.encodeBase64(byteArray); stringBuilder.append(new String(encodedBytes)); } else if (read == DATA_ENCODING_CHUNK_SIZE) { byte[] encodedBytes = Base64.encodeBase64(byteData); stringBuilder.append(new String(encodedBytes)); } } object.value(stringBuilder.toString()); } catch (IOException e) { object.value( ""); // if we error out on the first read attempt, we need a placeholder value still object.key(ContentTypeDefinitions.LABEL_ERROR); object.value("IOException while getting attachment: " + e.getMessage()); } } else { object.key(key); try { object.value(URLEncoder.encode(value.toString(), "UTF-8")); } catch (final UnsupportedEncodingException e) { throw new JSONException( "String value cannot be encoded as UTF-8 for JSON transmission", e); } } } if (null != resourceType && !setResourceType) { // make sure this gets included if it's been specified object.key(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY); object.value(resourceType); } if (timestampFields.length() > 0) { object.key(ContentTypeDefinitions.LABEL_TIMESTAMP_FIELDS); object.value(timestampFields); } }
public void execute(final WorkItem item, final WorkflowSession session, final MetaDataMap args) throws SocialModerationException { log.debug("In the workflow... (Flagged in JCR) "); try { validate(item); final JSONArray arr = new JSONArray((String) item.getWorkflowData().getPayload()); final ResourceResolver resolver = getResourceResolver(session.getSession()); for (int i = 0; i < arr.length(); i++) { final JSONObject obj = (JSONObject) arr.get(i); final String path = obj.getString(ModerationConstants.PATH); if (!obj.has(ModerationConstants.ACTION_FLAG)) { throw new SocialModerationException( FLAG_VERB_NOT_PRESENT_IN_PAYLOAD, ModerationConstants.ERR_FLAG_VERB_NOT_PRESENT_IN_PAYLOAD); } final boolean isFlagged = obj.getBoolean(ModerationConstants.ACTION_FLAG); final Resource resource = resolver.getResource(path); if (resource == null) { throw new SocialModerationException( ERR_SPECIFIED_RESOURCE_DOES_NOT_EXIST + path, ModerationConstants.ERR_SPECIFIED_RESOURCE_DOES_NOT_EXIST); } else { final Comment comment = resource.adaptTo(Comment.class); if (comment != null) { final Node node = resource.adaptTo(Node.class); node.setProperty(ModerationConstants.PROP_IS_FLAGGED, isFlagged); node.setProperty(ModerationConstants.PROP_IS_READ, true); addModHistory( profileMgr, resolver, node, ModerationConstants.PROP_IS_FLAGGED, String.valueOf(isFlagged), item.getWorkflow().getInitiator()); node.getSession().save(); replicator.replicate( session.getSession(), com.day.cq.replication.ReplicationActionType.ACTIVATE, path.substring(0, path.lastIndexOf('/')), null); // msgs[i] = "Comment " + verb + ": " + path; } else { throw new SocialModerationException( "Not a comment: " + path, ModerationConstants.ERR_NOT_A_COMMENT); } } } } catch (final JSONException je) { log.error(je.getLocalizedMessage(), je.getCause()); throw new SocialModerationException( je.getLocalizedMessage(), ModerationConstants.ERR_FLAGGED_ACTION, je.getCause()); } catch (final Exception e) { log.error(e.getLocalizedMessage(), e.getCause()); throw new SocialModerationException( e.getLocalizedMessage(), ModerationConstants.ERR_FLAGGED_ACTION, e.getCause()); } }
public static void extractTopic( final JSONWriter writer, final Post post, final ResourceResolver resolver, final String resourceType, final String childResourceType, final Writer responseWriter) throws JSONException, IOException { final ValueMap vm = post.getProperties(); final JSONArray timestampFields = new JSONArray(); for (final Map.Entry<String, Object> prop : vm.entrySet()) { final Object value = prop.getValue(); if (value instanceof String[]) { final JSONArray list = new JSONArray(); for (String v : (String[]) value) { list.put(v); } writer.key(prop.getKey()); writer.value(list); } else if (value instanceof GregorianCalendar) { timestampFields.put(prop.getKey()); writer.key(prop.getKey()); writer.value(((Calendar) value).getTimeInMillis()); } else if (prop.getKey().equals("sling:resourceType")) { writer.key(prop.getKey()); writer.value(resourceType); } else if (prop.getKey().equals("sentiment")) { writer.key(prop.getKey()); // 1 = 1, 2 = 3, 3 = 5, 4 = 8, 5 = 10 short shortValue = Short.parseShort(value.toString()); switch (shortValue) { case 1: writer.value(1); break; case 2: writer.value(3); break; case 3: writer.value(5); break; case 4: writer.value(8); break; case 5: writer.value(10); break; default: writer.value(value); } } else { writer.key(prop.getKey()); try { writer.value(URLEncoder.encode(prop.getValue().toString(), "UTF-8")); } catch (final UnsupportedEncodingException e) { throw new JSONException( "Unsupported encoding (UTF-8) for resource at " + post.getPath(), e); } } } if (timestampFields.length() > 0) { writer.key(ContentTypeDefinitions.LABEL_TIMESTAMP_FIELDS); writer.value(timestampFields); } final Resource thisResource = resolver.getResource(post.getPath()); final Resource attachments = thisResource.getChild("attachments"); if (attachments != null) { writer.key(ContentTypeDefinitions.LABEL_ATTACHMENTS); final JSONWriter attachmentsWriter = writer.array(); for (final Resource attachment : attachments.getChildren()) { UGCExportHelper.extractAttachment(responseWriter, attachmentsWriter.object(), attachment); attachmentsWriter.endObject(); } writer.endArray(); } final Iterable<Resource> children = thisResource.getChildren(); for (final Resource child : children) { if (child.isResourceType("social/tally/components/hbs/voting") || child.isResourceType("social/tally/components/voting")) { writer.key(ContentTypeDefinitions.LABEL_TALLY); final JSONWriter voteObjects = writer.array(); UGCExportHelper.extractTally(voteObjects, child, "Voting"); writer.endArray(); } else if (child.getName().equals("translation")) { extractTranslation(writer, child); } } final Iterator<Post> posts = post.getPosts(); if (posts.hasNext()) { writer.key(ContentTypeDefinitions.LABEL_REPLIES); final JSONWriter replyWriter = writer.object(); while (posts.hasNext()) { Post childPost = posts.next(); replyWriter.key(childPost.getId()); extractTopic( replyWriter.object(), childPost, resolver, childResourceType, childResourceType, responseWriter); replyWriter.endObject(); } writer.endObject(); } }