Package org.camunda.spin.impl.json.tree

Source Code of org.camunda.spin.impl.json.tree.SpinJsonJacksonTreeNode

/* 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 org.camunda.spin.impl.json.tree;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JavaType;
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.JsonNodeType;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.JsonPath;
import org.camunda.spin.SpinList;
import org.camunda.spin.impl.SpinListImpl;
import org.camunda.spin.json.SpinJsonNode;
import org.camunda.spin.json.SpinJsonTreeNodeException;
import org.camunda.spin.json.SpinJsonTreePathQuery;
import org.camunda.spin.logging.SpinLogger;
import org.camunda.spin.spi.SpinJsonDataFormatException;

import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static org.camunda.spin.impl.util.SpinEnsure.ensureNotNull;

/**
* Wrapper for a Jackson Json Tree Node.
*
* @author Thorben Lindhauer
* @author Stefan Hentschel
*/
public class SpinJsonJacksonTreeNode extends SpinJsonNode {

  private static final JsonJacksonTreeLogger LOG = SpinLogger.JSON_TREE_LOGGER;

  protected final JsonNode jsonNode;
  protected final JsonJacksonTreeDataFormat dataFormat;


  public SpinJsonJacksonTreeNode(JsonNode jsonNode, JsonJacksonTreeDataFormat dataFormat) {
    this.jsonNode = jsonNode;
    this.dataFormat = dataFormat;
  }

  public String getDataFormatName() {
    return dataFormat.getName();
  }

  public JsonNode unwrap() {
    return jsonNode;
  }

  public String toString() {
    return writeToWriter(new StringWriter()).toString();
  }

  public OutputStream toStream() {
    OutputStream out = new ByteArrayOutputStream();
    return writeToStream(out);
  }

  public <S extends OutputStream> S writeToStream(S outputStream) {
    ObjectMapper mapper = dataFormat.getConfiguredObjectMapper();
    JsonFactory factory = mapper.getFactory();

    try {
      JsonGenerator generator = factory.createGenerator(outputStream);
      mapper.writeTree(generator, jsonNode);
    } catch (IOException e) {
      throw LOG.unableToWriteJsonNode(e);
    }

    return outputStream;
  }

  public <W extends Writer> W writeToWriter(W writer) {
    ObjectMapper mapper = dataFormat.getConfiguredObjectMapper();
    JsonFactory factory = mapper.getFactory();

    try {
      JsonGenerator generator = factory.createGenerator(writer);
      mapper.writeTree(generator, jsonNode);
    } catch (IOException e) {
      throw LOG.unableToWriteJsonNode(e);
    }

    return writer;
  }

  /**
   * fetch correct array index if index is less than 0
   *
   * ArrayNode will convert all negative integers into 0...
   *
   * @param index wanted index
   * @return {@link Integer} new index
   */
  protected Integer getCorrectIndex(Integer index) {
    Integer size = jsonNode.size();
    Integer newIndex = index;

    // reverse walking through the array
    if(index < 0) {
      newIndex = size + index;
    }

    // the negative index would be greater than the size a second time!
    if(newIndex < 0) {
      throw LOG.indexOutOfBounds(index, size);
    }

    // the index is greater as the actual size
    if(index > size) {
     throw LOG.indexOutOfBounds(index, size);
    }

    return newIndex;
  }

  public Integer indexOf(Object searchObject) {
    ensureNotNull("searchObject", searchObject);
    if(this.isArray()) {
      Integer i = 0;
      JsonNode node = dataFormat.createJsonNode(searchObject);
      for (Iterator<JsonNode> nodeIterator = jsonNode.elements(); nodeIterator.hasNext(); i++) {
        JsonNode n = nodeIterator.next();
        if (n.equals(node)) {
          return i;
        }
      }

      // when searchObject is not found
      throw LOG.unableToFindProperty(node.asText());
    } else {
      throw LOG.unableToGetIndex(jsonNode.getNodeType().name());
    }
  }

  public Integer lastIndexOf(Object searchObject) {
    ensureNotNull("searchObject", searchObject);
    if(this.isArray()) {
      Integer i = 0;
      Integer j = -1;
      JsonNode node = dataFormat.createJsonNode(searchObject);
      for (Iterator<JsonNode> nodeIterator = jsonNode.elements(); nodeIterator.hasNext(); i++) {
        JsonNode n = nodeIterator.next();
        if (n.equals(node)) {
          j = i;
        }
      }

      // when searchObject is not found
      if(j == -1) {
        throw LOG.unableToFindProperty(node.getNodeType().name());
      }

      return j;
    } else {
      throw LOG.unableToGetIndex(jsonNode.getNodeType().name());
    }
  }

  public boolean isObject() {
    return jsonNode.isObject();
  }

  public boolean hasProp(String name) {
    return jsonNode.has(name);
  }

  public SpinJsonNode prop(String name) {
    ensureNotNull("name", name);
    if(jsonNode.has(name)) {
      JsonNode property = jsonNode.get(name);
      return dataFormat.createWrapperInstance(property);
    } else {
      throw LOG.unableToFindProperty(name);
    }
  }

  public SpinJsonNode prop(String name, String newProperty) {
    ObjectNode node = (ObjectNode) jsonNode;

    node.put(name, newProperty);

    return this;
  }

  public SpinJsonNode prop(String name, Number newProperty) {
    ObjectNode node = (ObjectNode) jsonNode;

    // Numbers magic because Jackson has no native .put(Number value)
    if(newProperty instanceof Long) {
      node.put(name, newProperty.longValue());
    } else if(newProperty instanceof Integer) {
      node.put(name, newProperty.intValue());
    } else if(newProperty instanceof Float) {
        node.put(name, newProperty.floatValue());
    } else {
      // convert any other sub class of Number into Float
      node.put(name, newProperty.floatValue());
    }

    return this;
  }

  public SpinJsonNode prop(String name, int newProperty) {
    return prop(name, (Number) newProperty);
  }

  public SpinJsonNode prop(String name, float newProperty) {
    return prop(name, (Number) newProperty);
  }

  public SpinJsonNode prop(String name, long newProperty) {
    return prop(name, (Number) newProperty);
  }

  public SpinJsonNode prop(String name, boolean newProperty) {
    return prop(name, (Boolean) newProperty);
  }

  public SpinJsonNode prop(String name, Boolean newProperty) {
    ObjectNode node = (ObjectNode) jsonNode;

    node.put(name, newProperty);

    return this;
  }

  public SpinJsonNode prop(String name, List<Object> newProperty) {
    ObjectNode node = (ObjectNode) jsonNode;

    node.set(name, dataFormat.createJsonNode(newProperty));

    return this;
  }

  public SpinJsonNode prop(String name, Map<String, Object> newProperty) {
    ObjectNode node = (ObjectNode) jsonNode;

    node.set(name, dataFormat.createJsonNode(newProperty));

    return this;
  }

  public SpinJsonNode prop(String name, SpinJsonNode newProperty) {
    ObjectNode node = (ObjectNode) jsonNode;

    node.set(name, (JsonNode) newProperty.unwrap());

    return this;
  }

  public SpinJsonNode deleteProp(String name) {
    ensureNotNull("name", name);

    if(jsonNode.has(name)) {
      ObjectNode node = (ObjectNode) jsonNode;
      node.remove(name);
      return this;
    } else {
      throw LOG.unableToFindProperty(name);
    }
  }

  public SpinJsonNode deleteProp(List<String> names) {
    ensureNotNull("names", names);

    for(String name: names) {
      deleteProp(name);
    }

    return this;
  }

  public SpinJsonNode append(Object property) {
    ensureNotNull("property", property);
    if(jsonNode.isArray()) {
      ArrayNode node = (ArrayNode) jsonNode;

      node.add(dataFormat.createJsonNode(property));

      return this;
    } else {
      throw LOG.unableToModifyNode(jsonNode.getNodeType().name());
    }
  }

  public SpinJsonNode insertAt(int index, Object property) {
    ensureNotNull("property", property);

    if(jsonNode.isArray()) {
      index = getCorrectIndex(index);
      ArrayNode node = (ArrayNode) jsonNode;

      node.insert(index, dataFormat.createJsonNode(property));

      return this;
    } else {
      throw LOG.unableToModifyNode(jsonNode.getNodeType().name());
    }
  }

  public SpinJsonNode insertBefore(Object searchObject, Object insertObject) {
    ensureNotNull("searchObject", searchObject);
    ensureNotNull("insertObject", insertObject);
    if(this.isArray()) {
      Integer i = indexOf(searchObject);

      return insertAt(i, insertObject);

    } else {
      throw LOG.unableToCreateNode(jsonNode.getNodeType().name());
    }
  }

  public SpinJsonNode insertAfter(Object searchObject, Object insertObject) {
    ensureNotNull("searchObject", searchObject);
    ensureNotNull("insertObject", insertObject);
    if(this.isArray()) {
      Integer i = indexOf(searchObject);

      return insertAt(i + 1, insertObject);

    } else {
      throw LOG.unableToCreateNode(jsonNode.getNodeType().name());
    }
  }

  public SpinJsonNode remove(Object property) {
    return removeAt(indexOf(property));
  }

  public SpinJsonNode removeLast(Object property) {
    return removeAt(lastIndexOf(property));
  }

  public SpinJsonNode removeAt(int index) {
    if(this.isArray()) {
      ArrayNode node = (ArrayNode) jsonNode;

      node.remove(getCorrectIndex(index));

      return this;
    } else {
      throw LOG.unableToModifyNode(jsonNode.getNodeType().name());
    }
  }

  public Boolean isBoolean() {
    return jsonNode.isBoolean();
  }

  public Boolean boolValue() {
    if(jsonNode.isBoolean()) {
      return jsonNode.booleanValue();
    } else {
      throw LOG.unableToParseValue(Boolean.class.getSimpleName(), jsonNode.getNodeType());
    }
  }

  public Boolean isNumber() {
    return jsonNode.isNumber();
  }

  public Number numberValue() {
    if(jsonNode.isNumber()) {
      return jsonNode.numberValue();
    } else {
      throw LOG.unableToParseValue(Number.class.getSimpleName(), jsonNode.getNodeType());
    }
  }

  public Boolean isString() {
    return jsonNode.isTextual();
  }

  public String stringValue() {
    if(jsonNode.isTextual()) {
      return jsonNode.textValue();
    } else {
      throw LOG.unableToParseValue(String.class.getSimpleName(), jsonNode.getNodeType());
    }
  }

  public Boolean isValue() {
    return jsonNode.isValueNode();
  }

  public Object value() {
    if(jsonNode.isBoolean()) {
      return jsonNode.booleanValue();
    }

    if(jsonNode.isNumber()) {
      return jsonNode.numberValue();
    }

    if(jsonNode.isTextual()) {
      return jsonNode.textValue();
    }

    throw LOG.unableToParseValue("String/Number/Boolean", jsonNode.getNodeType());
  }

  public Boolean isArray() {
    return jsonNode.isArray();
  }

  public SpinList<SpinJsonNode> elements() {
    if(jsonNode.isArray()) {
      Iterator<JsonNode> iterator = jsonNode.elements();
      SpinList<SpinJsonNode> list = new SpinListImpl<SpinJsonNode>();
      while(iterator.hasNext()) {
        SpinJsonNode node = dataFormat.createWrapperInstance(iterator.next());
        list.add(node);
      }

      return list;
    } else {
      throw LOG.unableToParseValue(SpinList.class.getSimpleName(), jsonNode.getNodeType());
    }
  }

  public List<String> fieldNames() {
    if(jsonNode.isContainerNode()) {
      Iterator<String> iterator = jsonNode.fieldNames();
      List<String> list = new ArrayList<String>();
      while(iterator.hasNext()) {
        list.add(iterator.next());
      }

      return list;
    } else {
      throw LOG.unableToParseValue("Array/Object", jsonNode.getNodeType());
    }
  }

  public JsonNodeType getNodeType() {
    return jsonNode.getNodeType();
  }

  public SpinJsonTreePathQuery jsonPath(String expression) {
    ensureNotNull("expression", expression);
    try {
      JsonPath query = JsonPath.compile(expression);
      return new SpinJsonJacksonPathQuery(this, query, dataFormat);
    } catch(InvalidPathException pex) {
      throw LOG.unableToCompileJsonPathExpression(expression, pex);
    } catch(IllegalArgumentException aex) {
      throw LOG.unableToCompileJsonPathExpression(expression, aex);
    }
  }

  /**
   * Maps the json represented by this object to a java object of the given type.
   *
   * @throws SpinJsonTreeNodeException if the json representation cannot be mapped to the specified type
   */
  public <C> C mapTo(Class<C> type) {
    JsonJacksonTreeDataFormatMapper mapper = dataFormat.getMapper();
    return mapper.mapInternalToJava(jsonNode, type);
  }

  /**
   * Maps the json represented by this object to a java object of the given type.
   * Argument is to be supplied in Jackson's canonical type string format
   * (see {@link JavaType#toCanonical()}).
   *
   * @throws SpinJsonTreeNodeException if the json representation cannot be mapped to the specified type
   * @throws SpinJsonDataFormatException if the parameter does not match a valid type
   */
  public <C> C mapTo(String type) {
    JsonJacksonTreeDataFormatMapper mapper = dataFormat.getMapper();
    return mapper.mapInternalToJava(jsonNode, type);
  }

  /**
   * Maps the json represented by this object to a java object of the given type.
   *
   * @throws SpinJsonTreeNodeException if the json representation cannot be mapped to the specified type
   */
  public <C> C mapTo(JavaType type) {
    JsonJacksonTreeDataFormatMapper mapper = dataFormat.getMapper();
    return mapper.mapInternalToJava(jsonNode, type);
  }
}
TOP

Related Classes of org.camunda.spin.impl.json.tree.SpinJsonJacksonTreeNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.