Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
// Copyright 2020 connectifex
//
// 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 com.connectifex.base;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;
import java.util.TreeMap;
import java.util.TreeSet;
import org.dmd.dmc.DmcInputStreamIF;
import org.dmd.dmc.DmcOutputStreamIF;
import org.dmd.dmc.DmcValueException;
import org.dmd.dmc.types.CheapSplitter;
import org.dmd.util.exceptions.ResultException;
import org.dmd.util.formatting.PrintfFormat;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* The JSONSmartPath provides mechanisms for specifying a path through a JSON
* structure with optional, in-line "filters" that allow selection of objects
* from arrays of objects.
*
* NOTE: current limitation - we don't take care of comparison values that might include slashes
*/
public class JSONSmartPath {
private static String PATHSEP = "/";
private static String OPEN = "[";
private static String CLOSE = "]";
private static String EQUALS = "==";
private String path;
private ArrayList nodes;
public JSONSmartPath() {
path = null;
}
public JSONSmartPath(String path) throws DmcValueException {
this.path = path;
initialize();
}
/**
* A small hack to allow us to throw a ResultException instead of a DmcValueException when we're
* using this internally.
* @param path
* @throws ResultException
* @throws DmcValueException
*/
public JSONSmartPath(String path, boolean throwResultException) throws ResultException {
this.path = path;
try {
initialize();
} catch (DmcValueException e) {
ResultException ex = new ResultException(e);
ex.moreMessages("You've screwed things up using this internally!");
throw(ex);
}
}
public JSONSmartPath(JSONSmartPath jsp) {
path = new String(jsp.path);
try {
initialize();
} catch (DmcValueException e) {
throw new IllegalStateException(e);
}
}
public void serializeIt(DmcOutputStreamIF dos) throws Exception {
dos.writeUTF(path);
}
public void deserializeIt(DmcInputStreamIF dis) throws Exception {
path = dis.readUTF();
}
private void initialize() throws DmcValueException {
if (path == null)
throw(new DmcValueException("The value for a JSONSmartPath cannot be null"));
if (path.length() == 0)
throw(new DmcValueException("The value for a JSONSmartPath cannot be zero length"));
if (!path.startsWith(PATHSEP))
throw(new DmcValueException("The value for a JSONSmartPath must start with: " + PATHSEP));
nodes = new ArrayList<>();
// Note, we don't trim the tokens
ArrayList tokens = CheapSplitter.split(path, '/', false, false);
for(String token: tokens) {
if (token.startsWith(OPEN)) {
nodes.add(parseFilter(token));
}
else {
nodes.add(new PathNode(token.trim()));
}
}
}
/**
* @return the number of elements in the path, this includes keys and filters
*/
public int pathElements() {
return(nodes.size());
}
public String toString() {
return(path);
}
/**
* Analyzes the specified object and provides representative smart paths for all possible
* paths through the hierarchy.
* @param object the object to be analyzed
* @return a sorted set of paths along with example values for the primitives
*/
static public TreeMap> getPaths(JSONObject object){
// TreeSet rc = new TreeSet<>();
TreeMap> pathAndValue = new TreeMap<>(Collator.getInstance(Locale.ENGLISH));
descendObject("/", object, pathAndValue);
return(pathAndValue);
}
/**
* Analyzes the specified object and provides representative smart paths for all possible
* paths through the hierarchy along with example values.
* @param object the object to be analyzed
* @return a sorted set of paths along with example values for the primitives
*/
static public String getPathsAndExamplesAsString(JSONObject object){
return(getPathsAndExamplesAsString(object, -1));
}
/**
* Analyzes the specified object and provides representative smart paths for all possible
* paths through the hierarchy along with example values.
* @param object
* @param display the number of example values to display. If 0, we display none, if < 0, we display all, if > 0 we display up to that number.
* @return
*/
static public String getPathsAndExamplesAsString(JSONObject object, int display) {
StringBuilder sb = new StringBuilder();
TreeMap> pathAndValue = getPaths(object);
int longest = 0;
for(String key: pathAndValue.keySet()) {
if (key.length() > longest)
longest = key.length();
}
PrintfFormat format = new PrintfFormat("%-" + longest + "s");
for(String key: pathAndValue.keySet()) {
TreeSet examples = pathAndValue.get(key);
if (examples == null)
System.out.println(key);
else {
if (display == 0) {
// Don't display examples
sb.append(format.sprintf(key));
}
else {
sb.append(format.sprintf(key) + " -- ");
int displayed = 1;
Iterator it = examples.iterator();
while(it.hasNext()) {
String ex = it.next();
sb.append(ex);
if (display > 0) {
// Only display the specified number of examples
if (displayed == display)
break;
displayed++;
}
if (it.hasNext())
sb.append(", ");
}
sb.append("\n");
}
}
}
return(sb.toString());
}
static private void descendObject(String basePath, JSONObject object, TreeMap> pathAndValue) {
Iterator keys = object.keys();
while(keys.hasNext()) {
String key = keys.next();
Object value = object.get(key);
String newPath = basePath + key;
if (value instanceof JSONObject) {
pathAndValue.put(newPath, null);
descendObject(newPath + "/", (JSONObject) value, pathAndValue);
}
else if (value instanceof JSONArray) {
pathAndValue.put(newPath, null);
descendArray(newPath + "/", (JSONArray) value, pathAndValue);
}
else {
TreeSet examples = pathAndValue.get(newPath);
if (examples == null) {
examples = new TreeSet<>();
pathAndValue.put(newPath, examples);
}
examples.add(value.toString());
}
}
}
static private void descendArray(String basePath, JSONArray array, TreeMap> pathAndValue) {
if (array.isEmpty())
return;
// We only bother with arrays of objects
if (array.get(0) instanceof JSONObject) {
if (array.length() == 1) {
// If just one object, we don't bother indicating that we need filtering
descendObject(basePath, (JSONObject)array.get(0), pathAndValue);
}
else {
String filterPath = basePath + "[key==value]/";
Iterator