Package org.apache.pivot.json

Source Code of org.apache.pivot.json.JSON

/*
* 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 org.apache.pivot.json;

import org.apache.pivot.beans.BeanAdapter;
import org.apache.pivot.collections.ArrayList;
import org.apache.pivot.collections.Dictionary;
import org.apache.pivot.collections.List;
import org.apache.pivot.collections.Map;
import org.apache.pivot.collections.Sequence;

/**
* Contains utility methods for working with JSON or JSON-like data structures.
*/
public class JSON {
    /**
     * Returns the value at the given path.
     *
     * @param root
     * The root object; must be an instance of {@link org.apache.pivot.collections.Map}
     * or {@link org.apache.pivot.collections.List}.
     *
     * @param path
     * The path to the value, in JavaScript path notation.
     *
     * @return
     * The value at the given path.
     */
    public static Object get(Object root, String path) {
        if (root == null) {
            throw new IllegalArgumentException("root is null.");
        }

        if (path == null) {
            throw new IllegalArgumentException("path is null.");
        }

        return get(root, split(path));
    }

    @SuppressWarnings("unchecked")
    private static Object get(Object root, Sequence<String> keys) {
        Object value = root;

        for (int i = 0, n = keys.getLength(); i < n; i++) {
            String key = keys.get(i);

            if (value instanceof Sequence<?>) {
                Sequence<Object> sequence = (Sequence<Object>)value;
                value = sequence.get(Integer.parseInt(key));
            } else {
                Dictionary<String, Object> dictionary;
                if (value instanceof Dictionary<?, ?>) {
                    dictionary = (Dictionary<String, Object>)value;
                    value = dictionary.get(key);
                } else {
                    dictionary = new BeanAdapter(value);
                }

                if (dictionary.containsKey(key)) {
                    value = dictionary.get(key);
                } else {
                    value = null;
                    break;
                }
            }
        }

        return value;
    }

    /**
     * Returns the value at the given path as a string.
     *
     * @param root
     * @param path
     *
     * @see #get(Object, String)
     */
    public static String getString(Object root, String path) {
        return (String)get(root, path);
    }

    /**
     * Returns the value at the given path as a number.
     *
     * @param root
     * @param path
     *
     * @see #get(Object, String)
     */
    public static Number getNumber(Object root, String path) {
        return (Number)get(root, path);
    }

    /**
     * Returns the value at the given path as a short.
     *
     * @param root
     * @param path
     *
     * @see #get(Object, String)
     */
    public static Short getShort(Object root, String path) {
        Number number = getNumber(root, path);
        return (number == null) ? null : number.shortValue();
    }

    /**
     * Returns the value at the given path as an integer.
     *
     * @param root
     * @param path
     *
     * @see #get(Object, String)
     */
    public static Integer getInteger(Object root, String path) {
        Number number = getNumber(root, path);
        return (number == null) ? null : number.intValue();
    }

    /**
     * Returns the value at the given path as a long.
     *
     * @param root
     * @param path
     *
     * @see #get(Object, String)
     */
    public static Long getLong(Object root, String path) {
        Number number = getNumber(root, path);
        return (number == null) ? null : number.longValue();
    }

    /**
     * Returns the value at the given path as a float.
     *
     * @param root
     * @param path
     *
     * @see #get(Object, String)
     */
    public static Float getFloat(Object root, String path) {
        Number number = getNumber(root, path);
        return (number == null) ? null : number.floatValue();
    }

    /**
     * Returns the value at the given path as a double.
     *
     * @param root
     * @param path
     *
     * @see #get(Object, String)
     */
    public static Double getDouble(Object root, String path) {
        Number number = getNumber(root, path);
        return (number == null) ? null : number.doubleValue();
    }

    /**
     * Returns the value at the given path as a boolean.
     *
     * @param root
     * @param path
     *
     * @see #get(Object, String)
     */
    public static Boolean getBoolean(Object root, String path) {
        return (Boolean)get(root, path);
    }

    /**
     * Returns the value at the given path as a list.
     *
     * @param root
     * @param path
     *
     * @see #get(Object, String)
     */
    public static List<?> getList(Object root, String path) {
        return (List<?>)get(root, path);
    }

    /**
     * Returns the value at the given path as a map.
     *
     * @param root
     * @param path
     *
     * @see #get(Object, String)
     */
    @SuppressWarnings("unchecked")
    public static Map<String, ?> getMap(Object root, String path) {
        return (Map<String, ?>)get(root, path);
    }

    /**
     * Sets the value at the given path.
     *
     * @param root
     * @param path
     * @param value
     *
     * @return
     * The value previously associated with the path.
     */
    @SuppressWarnings("unchecked")
    public static Object put(Object root, String path, Object value) {
        if (root == null) {
            throw new IllegalArgumentException("root is null.");
        }

        if (path == null) {
            throw new IllegalArgumentException("path is null.");
        }

        Object previousValue;

        Sequence<String> keys = split(path);
        if (keys.getLength() == 0) {
            throw new IllegalArgumentException("Bad path.");
        }

        String key = keys.remove(keys.getLength() - 1, 1).get(0);

        Object parent = get(root, keys);
        if (parent instanceof Sequence<?>) {
            Sequence<Object> sequence = (Sequence<Object>)parent;
            previousValue = sequence.update(Integer.parseInt(key), value);
        } else {
            Dictionary<String, Object> dictionary;
            if (parent instanceof Dictionary<?, ?>) {
                dictionary = (Dictionary<String, Object>)parent;
            } else {
                dictionary = new BeanAdapter(parent);
            }

            previousValue = dictionary.put(key, value);
        }

        return previousValue;
    }

    /**
     * Removes the value at the given path.
     *
     * @param root
     * @param path
     *
     * @return
     * The value that was removed.
     */
    @SuppressWarnings("unchecked")
    public static Object remove(Object root, String path) {
        if (root == null) {
            throw new IllegalArgumentException("root is null.");
        }

        if (path == null) {
            throw new IllegalArgumentException("path is null.");
        }

        Object previousValue;

        Sequence<String> keys = split(path);
        if (keys.getLength() == 0) {
            throw new IllegalArgumentException("Bad path.");
        }

        String key = keys.remove(keys.getLength() - 1, 1).get(0);

        Object parent = get(root, keys);
        if (parent instanceof Sequence<?>) {
            Sequence<Object> sequence = (Sequence<Object>)parent;
            previousValue = sequence.remove(Integer.parseInt(key), 1).get(0);
        } else {
            Dictionary<String, Object> dictionary;
            if (parent instanceof Dictionary<?, ?>) {
                dictionary = (Dictionary<String, Object>)parent;
            } else {
                dictionary = new BeanAdapter(parent);
            }

            previousValue = dictionary.remove(key);
        }

        return previousValue;
    }

    /**
     * Tests the existence of a path in a given object.
     *
     * @param root
     * @param path
     *
     * @return
     * <tt>true</tt> if the path exists; <tt>false</tt>, otherwise.
     */
    @SuppressWarnings("unchecked")
    public static boolean containsKey(Object root, String path) {
        if (root == null) {
            throw new IllegalArgumentException("root is null.");
        }

        if (path == null) {
            throw new IllegalArgumentException("path is null.");
        }

        boolean containsKey;

        Sequence<String> keys = split(path);
        if (keys.getLength() == 0) {
            throw new IllegalArgumentException("Bad path.");
        }

        String key = keys.remove(keys.getLength() - 1, 1).get(0);

        Object parent = get(root, keys);
        if (parent instanceof Sequence<?>) {
            Sequence<Object> sequence = (Sequence<Object>)parent;
            containsKey = (sequence.getLength() > Integer.parseInt(key));
        } else {
            Dictionary<String, Object> dictionary;
            if (parent instanceof Dictionary<?, ?>) {
                dictionary = (Dictionary<String, Object>)parent;
            } else {
                dictionary = new BeanAdapter(parent);
            }

            containsKey = dictionary.containsKey(key);
        }

        return containsKey;
    }

    private static Sequence<String> split(String path) {
        ArrayList<String> keys = new ArrayList<String>();

        int i = 0;
        int n = path.length();

        while (i < n) {
            char c = path.charAt(i++);

            StringBuilder identifierBuilder = new StringBuilder();

            boolean bracketed = (c == '[');
            if (bracketed
                && i < n) {
                c = path.charAt(i++);

                char quote = Character.UNASSIGNED;

                boolean quoted = (c == '"'
                    || c == '\'');
                if (quoted
                    && i < n) {
                    quote = c;
                    c = path.charAt(i++);
                }

                while (i <= n
                    && bracketed) {
                    bracketed = quoted || (c != ']');

                    if (bracketed) {
                        if (c == quote) {
                            if (i < n) {
                                c = path.charAt(i++);
                                quoted = (c == quote);
                            }
                        }

                        if (quoted || c != ']') {
                            if (Character.isISOControl(c)) {
                                throw new IllegalArgumentException("Illegal identifier character.");
                            }

                            identifierBuilder.append(c);

                            if (i < n) {
                                c = path.charAt(i++);
                            }
                        }
                    }
                }

                if (quoted) {
                    throw new IllegalArgumentException("Unterminated quoted identifier.");
                }

                if (bracketed) {
                    throw new IllegalArgumentException("Unterminated bracketed identifier.");
                }

                if (i < n) {
                    c = path.charAt(i);

                    if (c == '.') {
                        i++;
                    }
                }
            } else {
                while(i <= n
                    && c != '.'
                    && c != '[') {
                    if (!Character.isJavaIdentifierPart(c)) {
                        throw new IllegalArgumentException("Illegal identifier character.");
                    }

                    identifierBuilder.append(c);

                    if (i < n) {
                        c = path.charAt(i);
                    }

                    i++;
                }

                if (c == '[') {
                    i--;
                }
            }

            if (c == '.'
                && i == n) {
                throw new IllegalArgumentException("Path cannot end with a '.' character.");
            }

            if (identifierBuilder.length() == 0) {
                throw new IllegalArgumentException("Missing identifier.");
            }

            keys.add(identifierBuilder.toString());
        }

        return keys;
    }
}
TOP

Related Classes of org.apache.pivot.json.JSON

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.