Java tutorial
/** * 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 com.msopentech.odatajclient.testservice.utils; import static com.msopentech.odatajclient.testservice.utils.Constants.*; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.ws.rs.NotFoundException; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; public class JSONUtilities extends AbstractUtilities { public JSONUtilities(final ODataVersion version) throws Exception { super(version); } @Override protected Accept getDefaultFormat() { return Accept.JSON_FULLMETA; } @Override protected InputStream addLinks(final String entitySetName, final String entitykey, final InputStream is, final Set<String> links) throws Exception { final ObjectMapper mapper = new ObjectMapper(); final ObjectNode srcNode = (ObjectNode) mapper.readTree(is); IOUtils.closeQuietly(is); for (String link : links) { srcNode.set(link + JSON_NAVIGATION_SUFFIX, new TextNode(Commons.getLinksURI(version, entitySetName, entitykey, link))); } return IOUtils.toInputStream(srcNode.toString()); } @Override protected Set<String> retrieveAllLinkNames(InputStream is) throws Exception { final ObjectMapper mapper = new ObjectMapper(); final ObjectNode srcNode = (ObjectNode) mapper.readTree(is); IOUtils.closeQuietly(is); final Set<String> links = new HashSet<String>(); final Iterator<String> fieldIter = srcNode.fieldNames(); while (fieldIter.hasNext()) { final String field = fieldIter.next(); if (field.endsWith(JSON_NAVIGATION_BIND_SUFFIX) || field.endsWith(JSON_NAVIGATION_SUFFIX) || field.endsWith(JSON_MEDIA_SUFFIX) || field.endsWith(JSON_EDITLINK_NAME)) { if (field.indexOf('@') > 0) { links.add(field.substring(0, field.indexOf('@'))); } else { links.add(field); } } } return links; } /** * {@inheritDoc } */ @Override protected NavigationLinks retrieveNavigationInfo(final String entitySetName, final InputStream is) throws Exception { final ObjectMapper mapper = new ObjectMapper(); final ObjectNode srcNode = (ObjectNode) mapper.readTree(is); IOUtils.closeQuietly(is); final NavigationLinks links = new NavigationLinks(); final Iterator<Map.Entry<String, JsonNode>> fieldIter = srcNode.fields(); while (fieldIter.hasNext()) { final Map.Entry<String, JsonNode> field = fieldIter.next(); if (field.getKey().endsWith(JSON_NAVIGATION_BIND_SUFFIX)) { final String title = field.getKey().substring(0, field.getKey().indexOf('@')); final List<String> hrefs = new ArrayList<String>(); if (field.getValue().isArray()) { for (JsonNode href : ((ArrayNode) field.getValue())) { final String uri = href.asText(); hrefs.add(uri.substring(uri.lastIndexOf('/') + 1)); } } else { final String uri = field.getValue().asText(); hrefs.add(uri.substring(uri.lastIndexOf('/') + 1)); } links.addLinks(title, hrefs); } else if (Commons.linkInfo.get(version).exists(entitySetName, field.getKey())) { links.addInlines(field.getKey(), IOUtils.toInputStream(field.getValue().toString())); } } return links; } /** * {@inheritDoc } */ @Override protected InputStream normalizeLinks(final String entitySetName, final String entityKey, final InputStream is, final NavigationLinks links) throws Exception { final ObjectMapper mapper = new ObjectMapper(); final ObjectNode srcNode = (ObjectNode) mapper.readTree(is); if (links != null) { for (String linkTitle : links.getLinkNames()) { // normalize link srcNode.remove(linkTitle + JSON_NAVIGATION_BIND_SUFFIX); srcNode.set(linkTitle + JSON_NAVIGATION_SUFFIX, new TextNode(String.format("%s(%s)/%s", entitySetName, entityKey, linkTitle))); } for (String linkTitle : links.getInlineNames()) { // normalize link if exist; declare a new one if missing srcNode.remove(linkTitle + JSON_NAVIGATION_BIND_SUFFIX); srcNode.set(linkTitle + JSON_NAVIGATION_SUFFIX, new TextNode(String.format("%s(%s)/%s", entitySetName, entityKey, linkTitle))); // remove inline srcNode.remove(linkTitle); // remove from links links.removeLink(linkTitle); } } srcNode.set(JSON_EDITLINK_NAME, new TextNode(Constants.DEFAULT_SERVICE_URL + entitySetName + "(" + entityKey + ")")); return IOUtils.toInputStream(srcNode.toString()); } protected static InputStream getJsonPropertyValue(final InputStream src, final String name) throws Exception { ObjectMapper mapper = new ObjectMapper(); final JsonNode srcNode = mapper.readTree(src); JsonNode node = getJsonProperty(srcNode, new String[] { name }, 0); return IOUtils.toInputStream(node.asText()); } public static InputStream getJsonProperty(final InputStream src, final String[] path, final String edmType) throws Exception { final ObjectMapper mapper = new ObjectMapper(); final JsonNode srcNode = mapper.readTree(src); final ObjectNode property = new ObjectNode(JsonNodeFactory.instance); if (StringUtils.isNotBlank(edmType)) { property.put(JSON_ODATAMETADATA_NAME, ODATA_METADATA_PREFIX + edmType); } JsonNode jsonNode = getJsonProperty(srcNode, path, 0); if (jsonNode.isObject()) { property.putAll((ObjectNode) jsonNode); } else { property.put("value", jsonNode.asText()); } final ByteArrayOutputStream bos = new ByteArrayOutputStream(); mapper.writeValue(bos, property); final InputStream res = new ByteArrayInputStream(bos.toByteArray()); IOUtils.closeQuietly(bos); return res; } private static JsonNode getJsonProperty(final JsonNode node, final String[] path, final int index) throws NotFoundException { final Iterator<Map.Entry<String, JsonNode>> iter = node.fields(); while (iter.hasNext()) { final Map.Entry<String, JsonNode> entry = iter.next(); if (path[index].equals(entry.getKey())) { if (path.length - 1 == index) { return entry.getValue(); } else { return getJsonProperty(entry.getValue(), path, index + 1); } } } throw new NotFoundException(); } public InputStream addJsonInlinecount(final InputStream src, final int count, final Accept accept) throws Exception { final ObjectMapper mapper = new ObjectMapper(); final JsonNode srcNode = mapper.readTree(src); ((ObjectNode) srcNode).put(ODATA_COUNT_NAME, count); final ByteArrayOutputStream bos = new ByteArrayOutputStream(); mapper.writeValue(bos, srcNode); final InputStream res = new ByteArrayInputStream(bos.toByteArray()); IOUtils.closeQuietly(bos); return res; } public InputStream wrapJsonEntities(final InputStream entities) throws Exception { final ObjectMapper mapper = new ObjectMapper(); final JsonNode node = mapper.readTree(entities); final ObjectNode res; final JsonNode value = node.get(JSON_VALUE_NAME); if (value.isArray()) { res = mapper.createObjectNode(); res.set("value", value); final JsonNode next = node.get(JSON_NEXTLINK_NAME); if (next != null) { res.set(JSON_NEXTLINK_NAME, next); } } else { res = (ObjectNode) value; } final ByteArrayOutputStream bos = new ByteArrayOutputStream(); mapper.writeValue(bos, res); final InputStream is = new ByteArrayInputStream(bos.toByteArray()); IOUtils.closeQuietly(bos); return is; } @Override public InputStream selectEntity(final InputStream src, final String[] propertyNames) throws Exception { final ObjectMapper mapper = new ObjectMapper(); final ObjectNode srcNode = (ObjectNode) mapper.readTree(src); final Set<String> retain = new HashSet<String>(); retain.add(JSON_ID_NAME); retain.add(JSON_TYPE_NAME); retain.add(JSON_EDITLINK_NAME); retain.add(JSON_NEXTLINK_NAME); retain.add(JSON_ODATAMETADATA_NAME); retain.add(JSON_VALUE_NAME); for (String name : propertyNames) { retain.add(name); retain.add(name + JSON_NAVIGATION_SUFFIX); retain.add(name + JSON_MEDIA_SUFFIX); retain.add(name + JSON_TYPE_SUFFIX); } srcNode.retain(retain); return IOUtils.toInputStream(srcNode.toString()); } @Override public InputStream readEntities(final List<String> links, final String linkName, final String next, final boolean forceFeed) throws Exception { if (links.isEmpty()) { throw new NotFoundException(); } final ObjectMapper mapper = new ObjectMapper(); final ObjectNode node = mapper.createObjectNode(); final ByteArrayOutputStream bos = new ByteArrayOutputStream(); if (forceFeed || links.size() > 1) { bos.write("[".getBytes()); } for (String link : links) { try { final Map.Entry<String, String> uri = Commons.parseEntityURI(link); final Map.Entry<String, InputStream> entity = readEntity(uri.getKey(), uri.getValue(), Accept.JSON_FULLMETA); if (bos.size() > 1) { bos.write(",".getBytes()); } IOUtils.copy(entity.getValue(), bos); } catch (Exception e) { // log and ignore link LOG.warn("Error parsing uri {}", link, e); } } if (forceFeed || links.size() > 1) { bos.write("]".getBytes()); } node.set(JSON_VALUE_NAME, mapper.readTree(new ByteArrayInputStream(bos.toByteArray()))); if (StringUtils.isNotBlank(next)) { node.set(JSON_NEXTLINK_NAME, new TextNode(next)); } return IOUtils.toInputStream(node.toString()); } @Override protected InputStream replaceLink(final InputStream toBeChanged, final String linkName, final InputStream replacement) throws Exception { final ObjectMapper mapper = new ObjectMapper(); final ObjectNode toBeChangedNode = (ObjectNode) mapper.readTree(toBeChanged); final ObjectNode replacementNode = (ObjectNode) mapper.readTree(replacement); if (toBeChangedNode.get(linkName + JSON_NAVIGATION_SUFFIX) == null) { throw new NotFoundException(); } toBeChangedNode.set(linkName, replacementNode.get(JSON_VALUE_NAME)); final JsonNode next = replacementNode.get(linkName + JSON_NEXTLINK_NAME); if (next != null) { toBeChangedNode.set(linkName + JSON_NEXTLINK_SUFFIX, next); } return IOUtils.toInputStream(toBeChangedNode.toString()); } @Override protected Map<String, InputStream> getChanges(final InputStream src) throws Exception { final Map<String, InputStream> res = new HashMap<String, InputStream>(); final ObjectMapper mapper = new ObjectMapper(); final JsonNode srcObject = mapper.readTree(src); final Iterator<Map.Entry<String, JsonNode>> fields = srcObject.fields(); while (fields.hasNext()) { final Map.Entry<String, JsonNode> field = fields.next(); res.put(field.getKey(), IOUtils.toInputStream(field.getValue().toString())); } return res; } @Override protected InputStream setChanges(final InputStream toBeChanged, final Map<String, InputStream> properties) throws Exception { final ObjectMapper mapper = new ObjectMapper(); final ObjectNode toBeChangedObject = (ObjectNode) mapper.readTree(toBeChanged); for (Map.Entry<String, InputStream> property : properties.entrySet()) { final JsonNode propertyNode = mapper.readTree(property.getValue()); toBeChangedObject.set(property.getKey(), propertyNode); } return IOUtils.toInputStream(toBeChangedObject.toString()); } public static Map.Entry<String, List<String>> extractLinkURIs(final InputStream is) throws Exception { final ObjectMapper mapper = new ObjectMapper(); final ObjectNode srcNode = (ObjectNode) mapper.readTree(is); IOUtils.closeQuietly(is); final List<String> links = new ArrayList<String>(); JsonNode uris = srcNode.get("value"); if (uris == null) { final JsonNode url = srcNode.get("url"); if (url != null) { links.add(url.textValue()); } } else { final Iterator<JsonNode> iter = ((ArrayNode) uris).iterator(); while (iter.hasNext()) { links.add(iter.next().get("url").textValue()); } } final JsonNode next = srcNode.get(JSON_NEXTLINK_NAME); return new SimpleEntry<String, List<String>>(next == null ? null : next.asText(), links); } }