All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bluenimble.platform.Json Maven / Gradle / Ivy

There is a newer version: 2.50.0
Show newest version
/*
 * 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.bluenimble.platform;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.text.ParseException;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import com.bluenimble.platform.encoding.Base64;
import com.bluenimble.platform.json.JsonArray;
import com.bluenimble.platform.json.JsonEntity;
import com.bluenimble.platform.json.JsonException;
import com.bluenimble.platform.json.JsonObject;
import com.bluenimble.platform.security.EncryptionProvider;
import com.bluenimble.platform.security.EncryptionProvider.Mode;
import com.bluenimble.platform.security.EncryptionProviderException;
import com.bluenimble.platform.templating.ExpressionCompiler;
import com.bluenimble.platform.templating.VariableResolver;
import com.bluenimble.platform.templating.impls.BasicVariableResolver;

public class Json {

	public static JsonObject object () {
		return new JsonObject ();
	}
	
	public static JsonArray array () {
		return new JsonArray ();
	}
	
	public static JsonObject load (String name) throws Exception {
		return load (Thread.currentThread ().getContextClassLoader (), name);
	}
	
	public static JsonObject load (InputStream stream) throws Exception {
		return load (stream, null);
	}
	
	public static JsonObject load (InputStream stream, String salt) throws Exception {
		if (!Lang.isNullOrEmpty (salt)) {
			ByteArrayOutputStream out = new ByteArrayOutputStream ();
			EncryptionProvider.Default.crypt (stream, out, salt, Mode.Decrypt);
			stream = new ByteArrayInputStream (out.toByteArray ());
		}
		return new JsonObject (IOUtils.toString (stream));
	}
    
	public static JsonObject load (File file) throws Exception {
		return load (file, null);
	}
	
	public static JsonObject load (File file, String salt) throws Exception {
		
		if (!file.exists ()) {
			return null;
		}
		
		InputStream stream = null;
		
		try {
			stream = new FileInputStream (file);
			return load (stream, salt);
		} finally {
			IOUtils.closeQuietly (stream);
		}
		
	}
    
	public static JsonObject load (ClassLoader loader, String name) throws Exception {
		if (Lang.isNullOrEmpty (name)) {
			throw new NullPointerException ("load with no parameters");
		}
		InputStream is = null;
		try { 
			
			if (name.indexOf (Lang.URL_ACCESSOR) > 0) {
				URL url = new URL (name);
				is = url.openStream ();
			} else {
				is = loader.getResourceAsStream (name);
			}
			
			return new JsonObject (IOUtils.toString (is));
			
		} finally {
			if (is != null) {
				try {
					is.close ();
				} catch (IOException ex) {
					ex.printStackTrace (System.err);
				}
			}
		}
	}
    
    public static void store (JsonObject source, File file) throws IOException {
    	store (source, file, false);
    }
    
    public static void store (JsonObject source, File file, boolean cast) throws IOException {
    	store (source, file, null, false, cast);
    }
    
    public static void store (JsonObject source, File file, String paraphrase) throws IOException {
    	store (source, file, paraphrase, false);
    }

    public static void store (JsonObject source, File file, String paraphrase, boolean base64) throws IOException {
    	store (source, file, paraphrase, base64, false);
    }
    public static void store (JsonObject source, File file, String paraphrase, boolean base64, boolean cast) throws IOException {
    	if (source == null) {
    		source = new JsonObject ();
    	}
    	OutputStream os = null;
    	try {
    		os = Lang.isNullOrEmpty (paraphrase) ? new FileOutputStream (file) : new ByteArrayOutputStream ();
    		IOUtils.copy (new ByteArrayInputStream (source.toString (2, cast).getBytes ()), os);
    	} finally {
    		if (Lang.isNullOrEmpty (paraphrase)) {
        		IOUtils.closeQuietly (os);
    		}
    	}
    	
    	if (!Lang.isNullOrEmpty (paraphrase)) {
    		OutputStream out = null;
    		try {
    			out = base64 ? new ByteArrayOutputStream () : new FileOutputStream (file);
    			EncryptionProvider.Default.crypt (
    				new ByteArrayInputStream (((ByteArrayOutputStream)os).toByteArray ()), 
    				out, pad (paraphrase), Mode.Encrypt
    			);
    			
    			if (base64) {
    				byte [] bytes = Base64.encodeBase64 (((ByteArrayOutputStream)out).toByteArray ());
    				out = new FileOutputStream (file);
    				out.write (bytes);
    				out.flush ();
    			}
    		} catch (EncryptionProviderException e) {
    			throw new IOException (e.getMessage (), e);
			} finally {
        		IOUtils.closeQuietly (out);
        	}
    	}
    }
    
    public static void encrypt (JsonObject source, String paraphrase, OutputStream out) throws EncryptionProviderException {
    	
    	EncryptionProvider.Default.crypt (
    		new ByteArrayInputStream (source.toString ().getBytes ()), 
			out, pad (paraphrase), Mode.Encrypt
		);
    	
    }

    public static JsonObject getObject (JsonObject source, String name) {
    	if (source == null || Lang.isNullOrEmpty (name)) {
    		return null;
    	}
    	return (JsonObject)source.get (name);
    }

    public static JsonArray getArray (JsonObject source, String name) {
    	if (source == null) {
    		return null;
    	}
    	return (JsonArray)source.get (name);
    }

    public static String getString (JsonObject source, String name) {
    	return getString (source, name, null);
    }

    public static String getString (JsonObject source, String name, String defaultValue) {
    	if (source == null) {
    		return defaultValue;
    	}
    	String v = source.getString (name);
    	if (v == null) {
    		return defaultValue;
    	}
    	return v;
    }

    public static int getInteger (JsonObject source, String name, int defaultValue) {
    	
    	int value = defaultValue;
    	
    	if (source == null || source.get (name) == null) {
    		return value;
    	}

    	String sInteger = String.valueOf (source.get (name));
		if (!Lang.isNullOrEmpty (sInteger)) {
			try {
				value = Integer.parseInt (sInteger.trim ());
			} catch (NumberFormatException nfex) {
				// Ignore
			}
		}
		return value;
    }

    public static long getLong (JsonObject source, String name, long defaultValue) {
    	
    	long value = defaultValue;
    	
    	if (source == null || source.get (name) == null) {
    		return value;
    	}

    	String sLong = String.valueOf (source.get (name));
		if (!Lang.isNullOrEmpty (sLong)) {
			try {
				value = Long.parseLong (sLong.trim ());
			} catch (NumberFormatException nfex) {
				// Ignore
			}
		}
		return value;
    }

    public static boolean getBoolean (JsonObject source, String name, boolean defaultValue) {
    	
    	boolean value = defaultValue;
    	
    	if (source == null || source.get (name) == null) {
    		return value;
    	}

    	String sBoolean = String.valueOf (source.get (name));
		if (!Lang.isNullOrEmpty (sBoolean)) {
			value = Lang.TrueValues.contains (sBoolean.trim ().toLowerCase ());
		}
		return value;
    }

    public static double getDouble (JsonObject source, String name, double defaultValue) {
    	
    	double value = defaultValue;
    	
    	if (source == null || source.get (name) == null) {
    		return value;
    	}

    	String sDouble = String.valueOf (source.get (name));
		if (!Lang.isNullOrEmpty (sDouble)) {
			try {
				value = Double.parseDouble (sDouble.trim ());
			} catch (NumberFormatException nfex) {
				// Ignore
			}
		}
		return value;
    }

    public static float getFloat (JsonObject source, String name, float defaultValue) {
    	
    	float value = defaultValue;
    	
    	if (source == null || source.get (name) == null) {
    		return value;
    	}

    	String sFloat = String.valueOf (source.get (name));
		if (!Lang.isNullOrEmpty (sFloat)) {
			try {
				value = Float.parseFloat (sFloat.trim ());
			} catch (NumberFormatException nfex) {
				// Ignore
			}
		}
		return value;
    }

    public static Date getDate (JsonObject source, String name) throws ParseException {
    	
    	if (source == null || source.get (name) == null) {
    		return null;
    	}
    	
    	Object oDate = source.get (name);
    	if (oDate instanceof Date) {
    		return (Date)oDate;
    	}
    	
		return Lang.toUTC (String.valueOf (oDate));
		
    }

    public static String escape (String value) {
		if (value == null || value.length () == 0) {
			return Lang.BLANK;
		}
		char b;
		char c = 0;
		int i;
		int len = value.length();
		
        StringBuilder sb = new StringBuilder(len + 4);
		String t;
        
		for (i = 0; i < len; i += 1) {
			b = c;
			c = value.charAt(i);
			switch (c) {
			case '\\':
			case '"':
				sb.append('\\');
				sb.append(c);
				break;
			case '/':
				if (b == '<') {
					sb.append('\\');
				}
				sb.append(c);
				break;
			case '\b':
				sb.append("\\b");
				break;
			case '\t':
				sb.append("\\t");
				break;
			case '\n':
				sb.append("\\n");
				break;
			case '\f':
				sb.append("\\f");
				break;
			case '\r':
				sb.append("\\r");
				break;
			default:
				if (c < ' ' || (c >= '\u0080' && c < '\u00a0')
						|| (c >= '\u2000' && c < '\u2100')) {
					t = "000" + Integer.toHexString(c);
					sb.append("\\u" + t.substring(t.length() - 4));
				} else {
					sb.append(c);
				}
			}
		}
		String s = sb.toString();
        sb.setLength (0);
        sb = null;
        return s;
    }
    
    public static Object find (JsonObject target, String... path) {
    	
    	if (path == null || path.length == 0) {
    		return null;
    	}

    	Object value = target;
    	
    	for (String name : path) {
			if (value instanceof JsonObject) {
				value = ((JsonObject)value).get (name);
			} else if (value instanceof JsonArray) {
				int index = 0;
				try {
					index = Integer.valueOf (name.trim ());
					value = ((JsonArray)value).get (index);
				} catch (NumberFormatException nfex) {
					value = null;
				}
			} 
			if (value == null) {
				break;
			}
			if (!JsonEntity.class.isAssignableFrom (value.getClass ())) {
				break;
			}
		}
		
		return value;
    }
    
    public static void set (JsonObject target, String property, Object value) {
    	
    	if (value == null || Lang.isNullOrEmpty (property)) {
    		return;
    	}
    	
    	String [] path = Lang.split (property, Lang.DOT);
    	if (path.length == 1) {
    		target.set (path [0], value);
    		return;
    	}
    	
    	JsonObject current = target;
    	
    	for (int i = 0; i < path.length - 1; i++) {
    		
    		String name = path [i];
    		
    		Object next = current.get (name);
    		if (next == null) {
    			next = new JsonObject ();
    			current.set (name, next);
    		} else if (!(next instanceof JsonObject)) {
    			return;
    		}
    		current = (JsonObject)next; 
		}
    	
    	current.set (path [path.length - 1], value);
    }
    
    public static void remove (JsonObject target, String... path) {
		
    	if (path == null || path.length == 0) {
    		return;
    	}
    	
    	if (path.length == 1) {
    		target.remove (path [0]);
    		return;
    	}
    	
    	Object value = target;
    	
    	for (int i = 0; i < path.length - 1; i++) {
    		
    		String name = path [i];
    		
			if (value instanceof JsonObject) {
				value = ((JsonObject)value).get (name);
			} else if (value instanceof JsonArray) {
				int index = 0;
				try {
					index = Integer.valueOf (name.trim ());
					value = ((JsonArray)value).get (index);
				} catch (NumberFormatException nfex) {
					value = null;
				}
			} 
			if (value == null) {
				break;
			}
			if (!JsonEntity.class.isAssignableFrom (value.getClass ())) {
				break;
			}
		}
    	
    	if (value == null || !JsonEntity.class.isAssignableFrom (value.getClass ())) {
			return;
		}
    	
    	if (value instanceof JsonObject) {
			((JsonObject)value).remove (path [path.length - 1]);
		} else if (value instanceof JsonArray) {
			int index = 0;
			try {
				index = Integer.valueOf (path [path.length - 1].trim ());
				((JsonArray)value).remove (index);
			} catch (NumberFormatException nfex) {
			}
		} 
		
    }
    
    public static JsonObject template (JsonObject template, JsonObject data, boolean withScripting) {
    	if (Json.isNullOrEmpty (template) || Json.isNullOrEmpty (data)) {
    		return template;
    	}
    	return (JsonObject)resolve (
    		template.duplicate (), 
    		withScripting ? Lang.ScriptedExpressionCompiler : Lang.ExpressionCompiler, 
    		new BasicVariableResolver (data)
    	);
    }
    
	public static Object resolve (Object obj, ExpressionCompiler compiler, VariableResolver vr) {
		if (obj == null || vr == null) {
			return obj;
		}
		if (obj instanceof JsonObject) {
			JsonObject o = (JsonObject)obj;
			if (o.isEmpty ()) {
				return o;
			}
			Set removed = null;
			Iterator keys = o.keys ();
			while (keys.hasNext ()) {
				String key = keys.next ();
				Object v = resolve (o.get (key), compiler, vr);
				if (v == null) {
					if (removed == null) {
						removed = new HashSet ();
					}
					removed.add (key);
				} else {
					o.set (key, v);
				}
			}
			// remove nulls
			if (removed != null && !removed.isEmpty ()) {
				for (String k : removed) {
					o.remove (k);
				}
			}
			return o;
		} else if (obj instanceof JsonArray) {
			JsonArray array = (JsonArray)obj;
			for (int i = 0; i < array.count (); i++) {
				Object resolved = resolve (array.get (i), compiler, vr);
				array.remove (i); 
				array.add (i, resolved); 
			}
			return array;
		} else if (obj instanceof String) {
			String exp = String.valueOf (obj);
			if (Lang.isNullOrEmpty (exp)) {
				return obj;
			}
			return compiler.compile (exp, null).eval (vr);
		} 
		return obj;
	}
	
	public static boolean isNullOrEmpty (JsonObject o) {
		return o == null || o.isEmpty ();
	}
	
	public static boolean isNullOrEmpty (JsonArray a) {
		return a == null || a.isEmpty ();
	}
	
	public static boolean areEqual (Object leftValue, Object rightValue) {
		if (leftValue == null && rightValue == null) {
			return true;
		}
		if (leftValue == null && rightValue != null) {
			return false;
		}
		if (leftValue != null && rightValue == null) {
			return false;
		}
		
		if (leftValue instanceof JsonObject) {
			if (! (rightValue instanceof JsonObject) ) {
				return false;
			}
			boolean areEqual = jsonEqual ((JsonObject)leftValue, (JsonObject)rightValue);
			if (!areEqual) {
				return false;
			}
		} else if (leftValue instanceof JsonArray) {
			if (! (rightValue instanceof JsonArray) ) {
				return false;
			}
			JsonArray aLeftValue 	= (JsonArray)leftValue;
			JsonArray aRightValue 	= (JsonArray)rightValue;
			if (aLeftValue.count () != aRightValue.count ()) {
				return false;
			}
			for (int i = 0; i < aLeftValue.count (); i++) {
				boolean areEqual = areEqual (aLeftValue.get (i), aRightValue.get (i));
				if (!areEqual) {
					return false;
				}
			}
		} else {
			return leftValue.equals (rightValue);
		}
		return true;
	}
	
	public static boolean jsonEqual (JsonObject left, JsonObject right) {
		if (Json.isNullOrEmpty (left) && Json.isNullOrEmpty (right)) {
			return true;
		}
		if (Json.isNullOrEmpty (left) && !Json.isNullOrEmpty (right)) {
			return false;
		}
		if (!Json.isNullOrEmpty (left) && Json.isNullOrEmpty (right)) {
			return false;
		}
		
		Iterator leftKeys = left.keys ();
		while (leftKeys.hasNext ()) {
			String key = leftKeys.next ();
			Object leftValue 	= left.get (key);
			
			Object rightValue 	= right.get (key);
			if (rightValue == null) {
				return false;
			}
			
			boolean areEqual = areEqual (leftValue, rightValue);
			if (!areEqual) {
				return false;
			}
		}
		
		Iterator rightKeys = right.keys ();
		while (rightKeys.hasNext ()) {
			boolean hasKey = left.containsKey (rightKeys.next ());
			if (!hasKey) {
				return false;
			}
		}
		
		return true;
	}
	
	private static String pad (String paraphrase) {
		if (paraphrase.length () == 16) {
			return paraphrase;
		} else if (paraphrase.length () > 16) {
			return paraphrase.substring (0, 15);
		} else {
			StringBuilder sb = new StringBuilder (paraphrase);
			
			for (int i = 0; i < (16 - paraphrase.length ()); i++) {
				sb.append ("0");
			}
			String s = sb.toString ();
			sb.setLength (0);
			return s;
		}
	}

    public static void main (String [] args) throws JsonException {
    	JsonObject template = new JsonObject ("{scheduler:'[node]', job: '[id]', expression: '[expression]', service: '[service]'}");
    	JsonObject data = new JsonObject ("{node: alpha, id: jobId, expression: '0 0 0 0', service:{a: 'value'}}");
		System.out.println (Json.template (template, data, false));
		
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy