MinimalJsonToVertex.java

/*
 * Copyright © 2014 - 2021 Leipzig University (Database Research Group)
 *
 * 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.gradoop.dataintegration.importer.impl.json.functions;

import org.apache.flink.api.common.functions.MapFunction;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import org.gradoop.common.model.api.entities.VertexFactory;
import org.gradoop.common.model.impl.pojo.EPGMVertex;
import org.gradoop.common.model.impl.properties.Properties;
import org.gradoop.common.model.impl.properties.PropertyValue;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

/**
 * Reads vertex data from a json document. The document contains at least
 * the vertex id, an embedded data document and an embedded meta document.
 * The data document contains all key-value pairs stored at the vertex, the
 * meta document contains the vertex label and an optional list of graph
 * identifiers the vertex is contained in.
 * <p>
 * Example:
 * <p>
 * {@code {
 * "id":0,
 * "name":"Alice","gender":"female","age":42
 * }}
 */
public class MinimalJsonToVertex implements MapFunction<String, EPGMVertex> {

  /**
   * The default label used for the newly created vertices.
   */
  public static final String JSON_VERTEX_LABEL = "JsonRowVertex";

  /**
   * Reduce object instantiations.
   */
  private final EPGMVertex reuse;

  /**
   * Creates a new instance of this JSON string to vertex converting function.
   *
   * @param vertexFactory The vertex factory used to create new vertices.
   */
  public MinimalJsonToVertex(VertexFactory<EPGMVertex> vertexFactory) {
    this.reuse = Objects.requireNonNull(vertexFactory).createVertex(JSON_VERTEX_LABEL);
    this.reuse.setProperties(Properties.create());
  }

  /**
   * Constructs a vertex from a given JSON string representation.
   *
   * @param jsonString The String representation of a JSON object.
   * @return A new vertex from the JSON object.
   * @throws Exception on failure
   */
  @Override
  public EPGMVertex map(String jsonString) throws Exception {
    JSONObject jsonVertex = new JSONObject(jsonString);

    Properties properties = reuse.getProperties();
    if (properties == null) {
      properties = Properties.create();
      reuse.setProperties(properties);
    }
    properties.clear();

    for (Iterator it = jsonVertex.keys(); it.hasNext();) {
      String key = (String) it.next();

      PropertyValue propertyValue = getPropertyValue(jsonVertex, key);
      properties.set(key, propertyValue);
    }
    return reuse;
  }

  /**
   * Convert a value of a JSON object to a {@link PropertyValue}.
   *
   * @param jsonObject The JSON object.
   * @param key        The key associated with the value to convert into a property value.
   * @return The converted value.
   */
  private PropertyValue getPropertyValue(JSONObject jsonObject, String key) {
    PropertyValue propertyValue = new PropertyValue();
    if (jsonObject.optJSONArray(key) != null) {
      JSONArray array = jsonObject.optJSONArray(key);
      // is it list or object?
      boolean listOrObject = array.optJSONObject(0) != null;

      List<PropertyValue> propertyList = new ArrayList<>();

      for (int i = 0; i < array.length(); i++) {
        String stringValue = listOrObject ? array.optJSONObject(i).toString() : array.optString(i);

        PropertyValue listElement = PropertyValue.create(stringValue);
        propertyList.add(listElement);
        propertyValue.setList(propertyList);
      }
    } else if (jsonObject.optString(key) != null) {
      String text = jsonObject.optString(key);
      propertyValue.setString(text);
    } else {
      propertyValue.setObject(null);
    }
    return propertyValue;
  }
}