/*
 *  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.
 *
 */

/*
 *                        AT&T - PROPRIETARY
 *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
 *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
 *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
 *
 *          Copyright (c) 2013 AT&T Knowledge Ventures
 *              Unpublished and Not for Publication
 *                     All Rights Reserved
 */
package org.apache.openaz.xacml.std.json;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigInteger;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.security.auth.x500.X500Principal;
import javax.xml.XMLConstants;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.openaz.xacml.api.Attribute;
import org.apache.openaz.xacml.api.AttributeValue;
import org.apache.openaz.xacml.api.DataType;
import org.apache.openaz.xacml.api.DataTypeFactory;
import org.apache.openaz.xacml.api.Identifier;
import org.apache.openaz.xacml.api.Request;
import org.apache.openaz.xacml.api.RequestAttributes;
import org.apache.openaz.xacml.api.RequestAttributesReference;
import org.apache.openaz.xacml.api.RequestReference;
import org.apache.openaz.xacml.api.SemanticString;
import org.apache.openaz.xacml.api.XACML3;
import org.apache.openaz.xacml.std.IdentifierImpl;
import org.apache.openaz.xacml.std.StdAttribute;
import org.apache.openaz.xacml.std.StdAttributeValue;
import org.apache.openaz.xacml.std.StdMutableRequest;
import org.apache.openaz.xacml.std.StdMutableRequestAttributes;
import org.apache.openaz.xacml.std.StdMutableRequestReference;
import org.apache.openaz.xacml.std.StdRequest;
import org.apache.openaz.xacml.std.StdRequestAttributesReference;
import org.apache.openaz.xacml.std.StdRequestDefaults;
import org.apache.openaz.xacml.std.datatypes.DataTypes;
import org.apache.openaz.xacml.std.datatypes.ExtendedNamespaceContext;
import org.apache.openaz.xacml.std.datatypes.StringNamespaceContext;
import org.apache.openaz.xacml.std.datatypes.XPathExpressionWrapper;
import org.apache.openaz.xacml.std.dom.DOMUtil;
import org.apache.openaz.xacml.util.FactoryException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 * JSONRequest is used to convert JSON into {@link org.apache.openaz.xacml.api.Request} objects. Instances are
 * only generated by loading a file, string, or InputStream representing the Request.
 */
public class JSONRequest {
    private static final Log logger = LogFactory.getLog(JSONRequest.class);

    /*
     * Map of Data Type Identifiers used to map shorthand notation for DataTypes into the full Identifer. This
     * is loaded the first time a Request is processed. Loading is done using Reflection. The map contains
     * keys for both the short form and the long form of each DataType. For example both of the following are
     * in the table: http://www.w3.org/2001/XMLSchema#base64Binary =
     * http://www.w3.org/2001/XMLSchema#base64Binary base64Binary =
     * http://www.w3.org/2001/XMLSchema#base64Binary (Note difference in structure and usage from
     * JSONResponse.)
     */
    private static Map<String, Identifier> shorthandMap = null;

    /*
     * To check the individual data attributes for being the correct type, we need an instance of the
     * DataTypeFactory
     */
    private static DataTypeFactory dataTypeFactory = null;

    /*
     * Prevent creation of instances - this class contains only static methods that return other object types.
     */
    protected JSONRequest() {
    }

    //
    // HELPER METHODS used in Parsing
    //

    /**
     * Allow both JSON boolean and Strings containing JSON booleans. If value is null, assume it is optional
     * and just return null. If Boolean, return same value. If String, note in log that it was string and
     * return converted value. Otherwise throw exception.
     *
     * @param value
     * @param location
     * @return
     * @throws JSONStructureException
     */
    private static Boolean makeBoolean(Object value, String location) throws JSONStructureException {
        if (value == null || value instanceof Boolean) {
            return (Boolean)value;
        }
        try {
            Boolean b = DataTypes.DT_BOOLEAN.convert(value);
            logger.warn(location + " has string containing boolean, should be unquoted boolean value");
            return b;
        } catch (Exception e) {
            throw new JSONStructureException(location + " must be Boolean");
        }
    }

    /**
     * Check the given map for all components having been removed (i.e. everything in the map was known and
     * used). If anything remains, throw an exception based on the component and the keys left in the map
     */
    private static void checkUnknown(String component, Map<?, ?> map) throws JSONStructureException {
        if (map.size() == 0) {
            return;
        }

        String keys = null;
        Iterator<?> it = map.keySet().iterator();
        while (it.hasNext()) {
            if (keys == null) {
                keys = "'" + it.next().toString() + "'";
            } else {
                keys += ", '" + it.next().toString() + "'";
            }
        }

        String message = component + " contains unknown element" + ((map.size() == 1) ? " " : "s ") + keys;
        throw new JSONStructureException(message);
    }

    /**
     * Convert a JSON representation of an XPathExpression into the internal objects. XPathExpression is the
     * only DataType that has a complex multi-part description. It includes - XPathCategory - required - XPath
     * - required - Namespaces - optional; a list of complex structures
     *
     * @param valueMap
     * @return
     * @throws JSONStructureException
     */
    private static AttributeValue<Object> convertXPathExpressionMapToAttributeValue(Map<?, ?> valueMap)
        throws JSONStructureException {
        // get required elements
        Object xpathCategoryObject = valueMap.remove("XPathCategory");
        Object xpathObject = valueMap.remove("XPath");
        if (!(xpathCategoryObject instanceof String) || !(xpathObject instanceof String)) {
            throw new JSONStructureException("XpathCategory and XPath must both be strings");
        }
        String xpathCategoryString = (String)xpathCategoryObject;
        String xpathString = (String)xpathObject;
        if (xpathCategoryString == null || xpathCategoryString.length() == 0 || xpathString == null
            || xpathString.length() == 0) {
            throw new JSONStructureException("XPathCategory or XPath missing or 0-length");
        }

        Identifier xpathCategoryId = new IdentifierImpl(xpathCategoryString);

        // get the Namespaces, if any.
        // Use StringNamespaceContext because we need to use the add functions to incrementally add the
        // namespaces
        StringNamespaceContext namespaceContext = null;

        Object namespacesObject = valueMap.remove("Namespaces");
        if (namespacesObject != null) {
            if (!(namespacesObject instanceof List)) {
                throw new JSONStructureException("Namespaces must be an array");
            }
            List<?> namespacesList = (List<?>)namespacesObject;

            if (namespacesList.size() > 0) {
                // create a NamespaceContext object to hold the namespaces
                namespaceContext = new StringNamespaceContext();

                for (Object n : namespacesList) {
                    if (!(n instanceof Map)) {
                        throw new JSONStructureException("Namespace within Namespaces array must be object");
                    }
                    Map<?, ?> namespaceMap = (Map<?, ?>)n;

                    Object namespaceObject = namespaceMap.remove("Namespace");
                    if (namespaceObject == null || !(namespaceObject instanceof String)) {
                        throw new JSONStructureException(
                                                         "Namespace object within Namespaces array must contain Namespace string member");
                    }

                    Object prefixObject = namespaceMap.remove("Prefix");
                    if (prefixObject != null && !(prefixObject instanceof String)) {
                        throw new JSONStructureException(
                                                         "Namespace object within Namespaces array Prefix must be string");
                    }

                    checkUnknown("Namespaces item", namespaceMap);

                    // add this namespace to the NamespaceContext
                    try {
                        namespaceContext.add((String)prefixObject, (String)namespaceObject);
                    } catch (Exception e) {
                        throw new JSONStructureException("Unable to add namespace prefix='" + prefixObject
                                                         + "' URI='" + namespaceObject + "'");
                    }
                }
            }
        }

        // create the XPathExpressionWrapper to contain this value
        XPathExpressionWrapper xpathExpressionWrapper = new XPathExpressionWrapper(namespaceContext,
                                                                                   xpathString);

        AttributeValue<Object> attributeValue = new StdAttributeValue<Object>(
                                                                              DataTypes.DT_XPATHEXPRESSION
                                                                                  .getId(),
                                                                              xpathExpressionWrapper,
                                                                              xpathCategoryId);

        checkUnknown("XPathExpression", valueMap);

        return attributeValue;
    }

    /**
     * Use reflection to load the map with all the names of all DataTypes, both the long name and the
     * shorthand, and point each name to the appropriate Identifier. The shorthand map is used differently in
     * JSONRequest than in JSONResponse, so there are similarities and differences in the implementation. This
     * is done once the first time a Request is processed.
     */
    private static void initShorthandMap() throws JSONStructureException {
        Field[] declaredFields = XACML3.class.getDeclaredFields();
        shorthandMap = new HashMap<String, Identifier>();
        for (Field field : declaredFields) {
            if (Modifier.isStatic(field.getModifiers()) && field.getName().startsWith("ID_DATATYPE")
                && Modifier.isPublic(field.getModifiers())) {
                try {
                    Identifier id = (Identifier)field.get(null);
                    String longName = id.stringValue();
                    // most names start with 'http://www.w3.org/2001/XMLSchema#'
                    int sharpIndex = longName.lastIndexOf("#");
                    if (sharpIndex <= 0) {
                        // some names start with 'urn:oasis:names:tc:xacml:1.0:data-type:'
                        // or urn:oasis:names:tc:xacml:2.0:data-type:
                        if (longName.contains(":data-type:")) {
                            sharpIndex = longName.lastIndexOf(":");
                        } else {
                            continue;
                        }
                    }
                    String shortName = longName.substring(sharpIndex + 1);
                    // put both the full name and the short name in the table
                    shorthandMap.put(longName, id);
                    shorthandMap.put(shortName, id);
                } catch (Exception e) {
                    throw new JSONStructureException("Error loading ID Table, e=" + e);
                }
            }
        }
    }

    //
    // MAIN PARSING CODE
    //

    /**
     * Handle a List of Attributes for a Category
     *
     * @param categoryID
     * @param attributes
     * @param stdMutableRequest
     * @throws JSONStructureException
     */
    private static List<Attribute> parseAttribute(Identifier categoryID, ArrayList<?> attributes)
        throws JSONStructureException {
        Iterator<?> iterAttributes = attributes.iterator();

        List<Attribute> collectedAttributes = new ArrayList<Attribute>();

        while (iterAttributes.hasNext()) {
            Map<?, ?> attributeMap = (Map<?, ?>)iterAttributes.next();
            if (!(attributeMap instanceof Map)) {
                throw new JSONStructureException("Expect Attribute content to be Map got "
                                                 + attributeMap.getClass());
            }
            Attribute attribute = parseAttribute(categoryID, attributeMap);
            collectedAttributes.add(attribute);
        }

        // return list of all attributes for this Category
        return collectedAttributes;
    }

    /**
     * Given the map of the parsed JSON representation of an Attribute, create the Attribute from the map.
     *
     * @param categoryID
     * @param attributeMap
     * @param stdMutableRequest
     * @return
     * @throws JSONStructureException
     */
    private static Attribute parseAttribute(Identifier categoryID, Map<?, ?> attributeMap)
        throws JSONStructureException {

        // TODO - ASSUME that the spec will remove the requirement that we MUST "handle" JavaScript special
        // values NaN, INF, -INF, none of which make sense on this interface.

        // TODO - ASSUME that the spec will fix inconsistency between AttributeId and Id (both are mentioned),
        // but we have code using both so allow both on input.
        Object idString = attributeMap.remove("AttributeId");
        if (idString == null) {
            //
            // This is an annoying message, and since we have PEP's that already use it
            // make this a debugging message. Otherwise it will clog our log file.
            //
            if (logger.isDebugEnabled()) {
                logger.debug("Attribute missing AttributeId, looking for Id");
            }
            idString = attributeMap.remove("Id");
            if (idString == null) {
                throw new JSONStructureException("Attribute missing AttributeId (and Id)");
            }
        } else {
            // we have the AttributeId - should not also have Id
            if (attributeMap.remove("Id") != null) {
                throw new JSONStructureException("Found both AttributeId '" + idString
                                                 + "' and Id field.  Please use only AttributeId.");
            }
        }
        if (!(idString instanceof String)) {
            throw new JSONStructureException("AttributeId must be String, got " + idString.getClass());
        }
        Identifier id = new IdentifierImpl(idString.toString());

        Object Value = attributeMap.remove("Value");
        if (Value == null) {
            throw new JSONStructureException("Attribute missing Value");
        }

        String Issuer = (String)attributeMap.remove("Issuer");

        Object includeInResultObject = attributeMap.remove("IncludeInResult");
        Boolean includeInResult = makeBoolean(includeInResultObject, "IncludeInResult");
        if (includeInResult == null) {
            includeInResult = Boolean.FALSE;
        }

        //
        // Data Type is complicated because:
        // - it may use shorthand (e.g. "integer" instead of full Id)
        // - it may be missing and have to be inferred
        // - inference on Arrays of values is tricky
        // - arrays must all use the same DataType
        // - we are limited in the data types that the Jackson parser is able to infer
        //
        Object DataType = attributeMap.remove("DataType");
        if (DataType != null && !(DataType instanceof String)) {
            throw new JSONStructureException("DataType must be String, got " + DataType.getClass());
        }
        // get Identifier for either long-form or shorthand notation of DataType
        String dataTypeString = null;
        if (DataType != null) {
            dataTypeString = DataType.toString();
        }
        Identifier dataTypeId = shorthandMap.get(dataTypeString);

        // check for unknown DataType
        if (DataType != null && dataTypeId == null) {
            // attribute contained a DataType but it was not known
            throw new JSONStructureException("Unknown DataType '" + dataTypeString + "'");
        }

        // At this point the dataTypeId may be null if no explicit DataType was given.
        // In that case we need to infer the data type from the value object.
        // The best we can do is infer based on the JSON data type, so we recognize boolean, integer, and
        // double, and everything else is handled as a string.
        // Unfortunately the value may be an array of values, so we need to look at all of them before making
        // a decision.
        // The algorithm for arrays is:
        // - take the dataType of the first element in the array as the array's data type
        // - if the array is of type Integer and we see a Double, make the array be Double.
        // Try to determine the over-all type for the list based on the contents.
        // The only mixing that is allowed is Integers and Doubles, in which case the list is Double

        // Values are converted to the current DataType wherever possible.
        // This includes converting doubles, integers and booleans into Strings if the DataType is String.
        // Auto-conversions generate warning messages to the logger.

        // TODO - ASSUME that we need to infer data type for array if not given. Spec is inconsistent on this
        // point, but author seems to want to do it.
        // TODO - Also ASSUME that
        // - everything other than JSON integer, double and boolean is handled as a string, and
        // - the only mixture of data types allowed within the same array is integer and double, yielding the
        // DataType for the array = Double, and
        // - an array of the same JSON data type has the same data type; for strings this means type=string
        // irrespective of what the strings represent (e.g. Date, URI, etc).

        if (Value instanceof List) {
            List<?> valueList = (List<?>)Value;
            // if nothing in the list then we don't care about the type
            if (valueList.size() > 0) {
                Identifier inferredDataTypeId = null;
                if (dataTypeId == null) {
                    // DataType was not given in Attribute - must infer it
                    for (Object item : (List<?>)Value) {
                        // figure out what data type to use for this array
                        if (inferredDataTypeId == null) {
                            // first item, need to set provisional inferred data type
                            if (item instanceof Boolean) {
                                inferredDataTypeId = DataTypes.DT_BOOLEAN.getId();
                            } else if (item instanceof Integer) {
                                inferredDataTypeId = DataTypes.DT_INTEGER.getId();
                            } else if (item instanceof Double) {
                                inferredDataTypeId = DataTypes.DT_DOUBLE.getId();
                            } else {
                                inferredDataTypeId = DataTypes.DT_STRING.getId();
                            }

                        } else if (inferredDataTypeId.equals(DataTypes.DT_INTEGER.getId())
                            && item instanceof Double) {
                            // special case - Double seen in Integer list means whole list is really
                            // Double
                            inferredDataTypeId = DataTypes.DT_DOUBLE.getId();
                        }
                    }
                    // we have inferred a data type for the whole array
                    dataTypeId = inferredDataTypeId;

                }
            }
        } else {
            // single-value attribute
            if (dataTypeId == null) {
                // single value with no DataType defined - Infer the XACML DataType for JSON data types
                if (Value instanceof Integer) {
                    dataTypeId = DataTypes.DT_INTEGER.getId();
                } else if (Value instanceof Double) {
                    dataTypeId = DataTypes.DT_DOUBLE.getId();
                } else if (Value instanceof Boolean) {
                    dataTypeId = DataTypes.DT_BOOLEAN.getId();
                } else {
                    // the Default DataType if none is given is String
                    dataTypeId = DataTypes.DT_STRING.getId();
                }
            }
            // all other data types are not explicitly checked for compatibility
        }

        // we now have the DataType to convert the values into.

        // create a single Attribute to return (it may contain multiple AttributeValues)
        Attribute attribute = null;

        DataType<?> dataType = dataTypeFactory.getDataType(dataTypeId);

        // Variable to use for reporting errors
        Object incomingValue = null;
        try {
            if (Value instanceof List) {
                // this attribute has a list of values
                List<AttributeValue<?>> attributeValueList = new ArrayList<AttributeValue<?>>();
                for (Object o : (List<?>)Value) {
                    // for error reporting we make a copy visible to the Catch clause
                    incomingValue = o;
                    AttributeValue<Object> attributeValue;
                    if (dataType.getId().equals(DataTypes.DT_XPATHEXPRESSION.getId())) {
                        if (!(o instanceof Map)) {
                            throw new JSONStructureException(
                                                             "XPathExpression must contain object, not simple value");
                        }
                        attributeValue = convertXPathExpressionMapToAttributeValue((Map<?, ?>)o);
                    } else {
                        Object convertedValue = dataType.convert(o);
                        attributeValue = new StdAttributeValue<Object>(dataTypeId, convertedValue);
                        if ((convertedValue instanceof Integer || convertedValue instanceof Boolean || convertedValue instanceof Double) && o instanceof String
                            || convertedValue instanceof Double && o instanceof Integer
                            || convertedValue instanceof String && (o instanceof Integer
                                                                     || o instanceof Boolean || o instanceof Double)) {
                            // we converted a String to something else
                            logger.warn("Attribute Id '" + id.stringValue() + "' Value '" + incomingValue
                                        + "' in Array auto-converted from '" + o.getClass().getName()
                                        + "' to type '" + dataType.getId().stringValue());
                        }
                    }
                    attributeValueList.add(attributeValue);
                }
                attribute = new StdAttribute(categoryID, id, attributeValueList, Issuer, includeInResult);
            } else {
                // for error reporting we make a copy visible to the Catch clause
                incomingValue = Value;
                // this attribute has a single value
                AttributeValue<Object> attributeValue;
                if (dataType.getId().equals(DataTypes.DT_XPATHEXPRESSION.getId())) {
                    if (!(Value instanceof Map)) {
                        throw new JSONStructureException(
                                                         "XPathExpression must contain object, not simple value");
                    }
                    attributeValue = convertXPathExpressionMapToAttributeValue((Map<?, ?>)Value);
                } else {
                    Object convertedValue = dataType.convert(Value);
                    attributeValue = new StdAttributeValue<Object>(dataTypeId, convertedValue);
                    // some auto-conversions should be logged because they shouldn't be necessary
                    if ((convertedValue instanceof BigInteger || convertedValue instanceof Boolean || convertedValue instanceof Double) && Value instanceof String
                        || convertedValue instanceof Double && Value instanceof Integer
                        || convertedValue instanceof String && (Value instanceof Integer
                                                                 || Value instanceof Boolean || Value instanceof Double)) {
                        // we converted a String to something else
                        logger.warn("Attribute Id '" + id.stringValue() + "' Value '" + incomingValue
                                    + "' auto-converted from '" + Value.getClass().getName() + "' to type '"
                                    + dataType.getId().stringValue());
                    }
                }
                attribute = new StdAttribute(categoryID, id, attributeValue, Issuer, includeInResult);
            }
        } catch (Exception e) {
            throw new JSONStructureException("In Id='" + id.stringValue()
                                             + "' Unable to convert Attribute Value '" + incomingValue
                                             + "' to type '" + dataTypeId.stringValue() + "'");
        }

        checkUnknown(id.stringValue() + "Attribute '" + idString.toString() + "'", attributeMap);

        return attribute;
    }

    /**
     * Convert the contents of a Content element from XML into XML Node
     *
     * @param xmlContent
     * @return Node
     * @throws Exception
     */
    public static Node parseXML(String xmlContent) throws JSONStructureException {

        if (xmlContent == null || xmlContent.length() == 0) {
            return null;
        }

        //
        // First of all, the String is possible escaped.
        //
        // The meaning of "escaped" is defined in section 4.2.3.1 in the JSON spec
        //
        String unescapedContent = xmlContent.replace("\\\"", "\"");
        unescapedContent = unescapedContent.replace("\\\\", "\\");

        // logger.info("Escaped content: \n" + unescapedContent);

        try (InputStream is = new ByteArrayInputStream(unescapedContent.getBytes("UTF-8"))) {
            Document doc = DOMUtil.loadDocument(is);
            if (doc != null) {
                return doc.getDocumentElement();
            }
            return null;
        } catch (Exception ex) {
            throw new JSONStructureException("Unable to parse Content '" + xmlContent + "'");
        }
    }

    /**
     * Helper to parse all components of one Category or default Category
     *
     * @param categoryMap
     * @param request
     */
    private static void parseCategory(Map<?, ?> categoryMap, String categoryName,
                                      Identifier defaultCategoryId, StdMutableRequest stdMutableRequest)
        throws JSONStructureException {

        Identifier categoryId = defaultCategoryId;
        Object categoryIDString = ((Map<?, ?>)categoryMap).remove("CategoryId");
        if (categoryIDString == null && defaultCategoryId == null) {
            throw new JSONStructureException("Category is missing CategoryId");
        }
        if (categoryIDString != null) {
            if (!(categoryIDString instanceof String)) {
                throw new JSONStructureException("Expect '" + categoryName + "' CategoryId to be String got "
                                                 + categoryIDString.getClass());
            } else {
                // TODO Spec says CategoryId may be shorthand, but none have been specified
                categoryId = new IdentifierImpl(categoryIDString.toString());
            }
        }
        // if we know the category, make sure user gave correct Id
        if (defaultCategoryId != null && !defaultCategoryId.equals(categoryId)) {
            throw new JSONStructureException(categoryName + " given CategoryId '" + categoryId
                                             + "' which does not match default id '" + defaultCategoryId
                                             + "'");
        }

        // get the Id, a.k.a xmlId
        String xmlId = (String)((Map<?, ?>)categoryMap).remove("Id");

        // get the Attributes for this Category, if any
        List<Attribute> attributeList = new ArrayList<Attribute>();
        Object attributesMap = ((Map<?, ?>)categoryMap).remove("Attribute");
        if (attributesMap != null) {
            if (attributesMap instanceof ArrayList) {
                attributeList = parseAttribute(categoryId, (ArrayList<?>)attributesMap);
            } else if (attributesMap instanceof Map) {
                // underlying code expects only collections of Attributes, so create a collection of one to
                // pass this single value
                ArrayList<Map<?, ?>> listForOne = new ArrayList<Map<?, ?>>();
                listForOne.add((Map<?, ?>)attributesMap);
                attributeList = parseAttribute(categoryId, listForOne);
            } else {
                throw new JSONStructureException("Category '" + categoryName
                                                 + "' saw unexpected Attribute class "
                                                 + attributesMap.getClass());
            }
        }

        // Get the Content node for this Category, if any
        Node contentRootNode = null;
        Object content = categoryMap.remove("Content");
        if (content != null) {
            if (content instanceof String) {
                //
                // Is it Base64 Encoded?
                //
                if (Base64.isBase64(((String)content).getBytes())) {
                    //
                    // Attempt to decode it
                    //
                    byte[] realContent = Base64.decodeBase64((String)content);
                    //
                    // Now what is it? JSON or XML? Should be XML.
                    //
                    try {
                        contentRootNode = parseXML(new String(realContent, "UTF-8"));
                    } catch (UnsupportedEncodingException e) {
                        throw new JSONStructureException("Category '" + categoryName
                                                         + "' Unsupported encoding in Content");
                    }
                } else {
                    //
                    // No, so what is it? Should be XML escaped
                    //
                    contentRootNode = parseXML((String)content);
                }
            } else if (content instanceof byte[]) {
                //
                // Should be Base64
                //
                if (Base64.isBase64(((String)content).getBytes())) {
                    //
                    // Attempt to decode it
                    //
                    byte[] realContent = Base64.decodeBase64((String)content);
                    //
                    // Now what is it? JSON or XML? Should be XML.
                    //
                    try {
                        contentRootNode = parseXML(new String(realContent, "UTF-8"));
                    } catch (UnsupportedEncodingException e) {
                        throw new JSONStructureException("Category '" + categoryName
                                                         + "' Unsupported encoding in Content");
                    }
                } else {
                    throw new JSONStructureException("Category '" + categoryName
                                                     + "' Content expected Base64 value");
                }
            } else {
                throw new JSONStructureException("Category '" + categoryName
                                                 + "' Unable to determine what Content is "
                                                 + content.getClass());
            }
        }

        checkUnknown(categoryName, categoryMap);

        StdMutableRequestAttributes attributeCategory = new StdMutableRequestAttributes(categoryId,
                                                                                        attributeList,
                                                                                        contentRootNode,
                                                                                        xmlId);

        stdMutableRequest.add(attributeCategory);

    }

    /**
     * Load the "Default Category" objects, if any. This is used for the special cases of AccessSubject,
     * Action, Resource, and Environment
     *
     * @param jsonRequestMap
     * @param categoryName
     * @param categoryIdString
     * @param stdMutableRequest
     * @throws JSONStructureException
     */
    private static void parseDefaultCategory(Map<?, ?> jsonRequestMap, String categoryName,
                                             String categoryIdString, StdMutableRequest stdMutableRequest)
        throws JSONStructureException {
        Object categoryMap = jsonRequestMap.remove(categoryName);
        if (categoryMap != null) {
            Identifier defaultIdentifier = new IdentifierImpl(categoryIdString);
            // The contents may be either a single item (whose attributes are in a Map)
            // or a list of items
            if (categoryMap instanceof Map) {
                // default category contains a single object
                parseCategory((Map<?, ?>)categoryMap, categoryName, defaultIdentifier, stdMutableRequest);
            } else if (categoryMap instanceof List) {
                // Array (for Multiple Decision) of this default category - create separate element for each
                // item in list using same CategoryId for all
                List<?> categoryList = (List<?>)categoryMap;
                for (Object subCategory : categoryList) {
                    if (!(subCategory instanceof Map)) {
                        throw new JSONStructureException(
                                                         categoryName
                                                             + " array can only contain objects within curly braces");
                    }
                    parseCategory((Map<?, ?>)subCategory, categoryName, defaultIdentifier, stdMutableRequest);
                }
            } else {
                // do not understand this
                throw new JSONStructureException(
                                                 categoryName
                                                     + " must have one object contained within curly braces ({}) or an array of objects ([{}{}])");
            }
        }

    }

    //
    // Primary interface methods
    //

    /**
     * Parse and JSON string into a {@link org.apache.openaz.xacml.api.Request} object.
     *
     * @param jsonString
     * @return
     * @throws JSONStructureException
     */
    public static Request load(String jsonString) throws JSONStructureException {
        Request request = null;
        try (InputStream is = new ByteArrayInputStream(jsonString.getBytes("UTF-8"))) {
            request = JSONRequest.load(is);
        } catch (Exception ex) {
            throw new JSONStructureException("Exception loading String Request: " + ex.getMessage(), ex);
        }
        return request;
    }

    /**
     * Read a file containing the JSON description of a XACML Request and parse it into a
     * {@link org.apache.openaz.xacml.api.Request} Object. This is only used for testing. In normal operation a
     * Request arrives through the RESTful interface and is processed using
     * <code>load(String jsonString)</code>.
     *
     * @param fileRequest
     * @return
     * @throws JSONStructureException
     */
    public static Request load(File fileRequest) throws JSONStructureException {
        Request request = null;
        try (FileInputStream fis = new FileInputStream(fileRequest)) {
            request = JSONRequest.load(fis);
        } catch (Exception ex) {
            throw new JSONStructureException("Exception loading File Request: " + ex.getMessage(), ex);
        }
        return request;
    }

    /**
     * Read characters from the given <code>InputStream</code> and parse them into an XACML
     * {@link org.apache.openaz.xacml.api.Request} object.
     *
     * @param is
     * @return
     * @throws JSONStructureException
     */
    public static Request load(InputStream is) throws JSONStructureException {

        // TODO - ASSUME that order of members within an object does not matter (Different from XML, in JSON
        // everything is handled as Maps so order does not matter)

        // ensure shorthand map is set up
        if (shorthandMap == null) {
            initShorthandMap();
        }

        // ensure that we have an instance of the DataTypeFactory for generating AttributeValues by DataType
        if (dataTypeFactory == null) {
            try {
                dataTypeFactory = DataTypeFactory.newInstance();
                if (dataTypeFactory == null) {
                    throw new NullPointerException("No DataTypeFactory found");
                }
            } catch (FactoryException e) {
                throw new JSONStructureException("Unable to find DataTypeFactory, e=" + e);
            }
        }

        // create a new Request object to be filled in
        StdMutableRequest stdMutableRequest = null;

        String json = null;
        ObjectMapper mapper = null;
        try {

            // read the inputStream into a buffer (trick found online scans entire input looking for
            // end-of-file)
            java.util.Scanner scanner = new java.util.Scanner(is);
            scanner.useDelimiter("\\A");
            json = scanner.hasNext() ? scanner.next() : "";
            scanner.close();

            mapper = new ObjectMapper().setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

            // TODO - ASSUME that any duplicated component is a bad thing (probably indicating an error in the
            // incoming JSON)
            mapper.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true);

            Map<?, ?> root = mapper.readValue(json, Map.class);

            //
            // Does the request exist?
            //
            Map<?, ?> jsonRequestMap = (Map<?, ?>)root.remove("Request");
            if (jsonRequestMap == null) {
                throw new JSONStructureException("No \"Request\" property found.");
            }

            checkUnknown("Top-level message", root);

            stdMutableRequest = new StdMutableRequest();

            //
            // Is there a Category?
            //
            Object categoryList = jsonRequestMap.remove("Category");
            if (categoryList != null && !(categoryList instanceof List)) {
                throw new JSONStructureException("Category must contain list of objects, not '"
                                                 + categoryList.getClass() + "'");
            }
            if (categoryList != null) {
                //
                // Iterate each Category
                //
                Iterator<?> iter = ((List<?>)categoryList).iterator();
                while (iter.hasNext()) {
                    Object category = iter.next();
                    if (!(category instanceof Map)) {
                        throw new JSONStructureException(
                                                         "Category list must contain objects contained within curly braces ({})");
                    }

                    parseCategory((Map<?, ?>)category, "Category", null, stdMutableRequest);

                }
            }

            // The following may be either a single instance or an array. This allows multiple decisions to
            // work with the Default Category objects.
            // Example:
            // "AccessSubject" : [ {attributes group one},
            // {attributes group two}
            // ]

            //
            // Look for default Shorthand AccessSubject
            //
            parseDefaultCategory(jsonRequestMap, "AccessSubject",
                                 "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject",
                                 stdMutableRequest);
            //
            // Provide backward compatibility for our PEP's
            //
            parseDefaultCategory(jsonRequestMap, "Subject",
                                 "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject",
                                 stdMutableRequest);

            //
            // Look for default Shorthand Action
            //
            parseDefaultCategory(jsonRequestMap, "Action",
                                 "urn:oasis:names:tc:xacml:3.0:attribute-category:action", stdMutableRequest);

            //
            // Look for default Shorthand Resource
            //
            parseDefaultCategory(jsonRequestMap, "Resource",
                                 "urn:oasis:names:tc:xacml:3.0:attribute-category:resource",
                                 stdMutableRequest);

            //
            // Look for default Shorthand Environment
            //
            parseDefaultCategory(jsonRequestMap, "Environment",
                                 "urn:oasis:names:tc:xacml:3.0:attribute-category:environment",
                                 stdMutableRequest);

            //
            // Look for default Shorthand RecipientSubject
            //
            parseDefaultCategory(jsonRequestMap, "RecipientSubject",
                                 "urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject",
                                 stdMutableRequest);

            //
            // Look for default Shorthand IntermediarySubject
            //
            parseDefaultCategory(jsonRequestMap, "IntermediarySubject",
                                 "urn:oasis:names:tc:xacml:1.0:subject-category:intermediary-subject",
                                 stdMutableRequest);

            //
            // Look for default Shorthand Codebase
            //
            parseDefaultCategory(jsonRequestMap, "Codebase",
                                 "urn:oasis:names:tc:xacml:1.0:subject-category:codebase", stdMutableRequest);

            //
            // Look for default Shorthand RequestingMachine
            //
            parseDefaultCategory(jsonRequestMap, "RequestingMachine",
                                 "urn:oasis:names:tc:xacml:1.0:subject-category:requesting-machine",
                                 stdMutableRequest);

            //
            // MultiRequest
            //
            Map<?, ?> multiRequests = (Map<?, ?>)jsonRequestMap.remove("MultiRequests");
            if (multiRequests != null) {
                if (!(multiRequests instanceof Map)) {
                    throw new JSONStructureException(
                                                     "MultiRequests must be object structure, not single value");
                }

                List<?> requestReferenceList = (List<?>)multiRequests.remove("RequestReference");
                if (requestReferenceList == null) {
                    throw new JSONStructureException("MultiRequest must contain a RequestReference element");
                }
                if (requestReferenceList.size() < 1) {
                    throw new JSONStructureException(
                                                     "MultiRequest must contain at least one element in the RequestReference list");
                }

                checkUnknown("MultiRequest", multiRequests);

                for (Object requestReferenceMapObject : requestReferenceList) {
                    if (!(requestReferenceMapObject instanceof Map)) {
                        throw new JSONStructureException("MultiRequest RequestReference must be object");
                    }
                    Map<?, ?> requestReferenceMap = (Map<?, ?>)requestReferenceMapObject;

                    // each object within the list must contain a ReferenceId and only a ReferenceId
                    Object referenceIdListObject = requestReferenceMap.remove("ReferenceId");
                    if (referenceIdListObject == null) {
                        throw new JSONStructureException(
                                                         "MultiRequest RequestReference list element must contain ReferenceId");
                    }
                    List<?> referenceIdList = (List<?>)referenceIdListObject;
                    if (referenceIdList.size() == 0) {
                        // the spec does not disallow empty list RequestReference objects
                        continue;
                    }

                    checkUnknown("RequestReference", requestReferenceMap);

                    // create reference corresponding to RequestReference list element
                    StdMutableRequestReference requestReference = new StdMutableRequestReference();

                    for (Object referenceId : referenceIdList) {
                        // add attributes to the reference
                        // Since the order of the JSON is not constrained, we could process this section
                        // before the section containing attribute being referenced,
                        // so we cannot do a cross-check here to verify that the attribute reference exists.
                        // That will happen later when the PDP attempts to find the attribute.
                        StdRequestAttributesReference requestAttributesReference = new StdRequestAttributesReference(
                                                                                                                     (String)referenceId);
                        requestReference.add(requestAttributesReference);
                    }
                    stdMutableRequest.add(requestReference);
                }
            }

            //
            // ReturnPolicyIdList
            //
            // If omitted this is set to a default of false by the StdMutableRequest constructor.
            //
            Object returnPolicyIdList = jsonRequestMap.remove("ReturnPolicyIdList");
            Boolean returnPolicyIdListBoolean = makeBoolean(returnPolicyIdList, "ReturnPolicyIdList");
            if (returnPolicyIdList != null) {
                stdMutableRequest.setReturnPolicyIdList(returnPolicyIdListBoolean);
            }

            //
            // CombinedDecision
            //
            // If omitted this is set to a default of false by the StdMutableRequest constructor.
            //
            Object combinedDecision = jsonRequestMap.remove("CombinedDecision");
            Boolean combinedDecisionBoolean = makeBoolean(combinedDecision, "CombinedDecision");
            if (combinedDecision != null) {
                stdMutableRequest.setCombinedDecision(combinedDecisionBoolean);
            }

            //
            // XPath
            //

            // The JSON spec says that this has a default value, implying that if it is missing in the Request
            // we should fill it in.
            // However the XML (DOM) version does not do that. If the value is missing it leaves the
            // requestDefaults object blank.
            // We are following the XML approach and ignoring the Default value for this field in the spec.

            // TODO - Assume that no value for XPathVersion means "leave as null", not "fill in the default
            // value from spec. This violates the JSON spec
            Object xPath = jsonRequestMap.remove("XPathVersion");
            if (xPath != null) {
                // XPath is given in the JSON input
                if (!(xPath instanceof String)) {
                    throw new JSONStructureException("XPathVersion not a URI passed as a String");
                }
                URI xPathUri = null;
                try {
                    xPathUri = new URI(xPath.toString());
                } catch (Exception e) {
                    throw new JSONStructureException("XPathVersion not a valid URI: '" + xPath + "'", e);
                }

                StdRequestDefaults requestDefaults = new StdRequestDefaults(xPathUri);
                stdMutableRequest.setRequestDefaults(requestDefaults);
            }

            checkUnknown("Request", jsonRequestMap);

        } catch (JsonParseException e) {
            // try to point to problem area in JSON input, if possible
            JsonLocation location = e.getLocation();
            String locationOfError = "(unavailable)";
            if (location != null && location != JsonLocation.NA) {
                String jsonText = json;
                if (location.getLineNr() > 1) {
                    String[] jsonArray = jsonText.split("\\r?\\n|\\r");
                    jsonText = jsonArray[location.getLineNr()];
                }
                if (location.getCharOffset() < jsonText.length()) {
                    if (location.getCharOffset() > 0) {
                        locationOfError = jsonText.substring((int)location.getCharOffset() - 1);
                    }
                    if (locationOfError.length() > 30) {
                        locationOfError = locationOfError.substring(0, 30);
                    }
                }
            }
            throw new JSONStructureException("Unable to parse JSON starting at text'" + locationOfError
                                             + "', input was '" + json + "', exception: " + e, e);
        } catch (JsonMappingException e) {
            throw new JSONStructureException("Unable to map JSON '" + json + "', exception: " + e, e);
        } catch (IOException e) {
            throw new JSONStructureException("Unable to read JSON input, exception: " + e, e);
        }

        // all done
        return new StdRequest(stdMutableRequest);
    }

    //
    // Generate JSON string from a Request object created by another means (e.g. XML).
    //

    /**
     * Convert the {@link org.apache.openaz.xacml.api.Request} into an JSON string with pretty-printing.
     *
     * @param request
     * @return
     * @throws Exception
     */
    public static String toString(Request request) throws Exception {
        return toString(request, true);
    }

    /**
     * Convert the {@link org.apache.openaz.xacml.api.Response} into an JSON string, pretty-printing is
     * optional. 
     *
     * @param response
     * @param prettyPrint
     * @return
     * @throws Exception
     */
    public static String toString(Request request, boolean prettyPrint) throws Exception {
        String outputString = null;
        try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
            convert(request, os, prettyPrint);
            outputString = new String(os.toByteArray(), "UTF-8");
        } catch (Exception ex) {
            throw ex;
        }
        return outputString;
    }

    /**
     * Convert the {@link org.apache.openaz.xacml.api.Request} object into a string suitable for output.
     * IMPORTANT: This method does NOT close the outputStream. It is the responsibility of the caller to (who
     * opened the stream) to close it.
     *
     * @param request
     * @param outputStream
     * @throws java.io.IOException
     * @throws JSONStructureException
     */
    public static void convert(Request request, OutputStream outputStream) throws IOException,
        JSONStructureException {
        convert(request, outputStream, false);
    }

    /**
     * Do the work of converting the {@link org.apache.openaz.xacml.api.Request} object to a string, allowing
     * for pretty-printing if desired. IMPORTANT: This method does NOT close the outputStream. It is the
     * responsibility of the caller to (who opened the stream) to close it.
     *
     * @param request
     * @param outputStream
     * @param prettyPrint
     * @throws java.io.IOException #throws JSONStructureException
     */
    public static void convert(Request request, OutputStream outputStream, boolean prettyPrint)
        throws IOException, JSONStructureException {

        if (request == null) {
            throw new NullPointerException("No Request in convert");
        }

        Map<String, Object> requestMap = new HashMap<String, Object>();

        // ReturnPolicyIdList
        requestMap.put("ReturnPolicyIdList", request.getReturnPolicyIdList());
        // Combined
        requestMap.put("CombinedDecision", request.getCombinedDecision());
        // XPath
        if (request.getRequestDefaults() != null) {
            requestMap.put("XPathVersion", request.getRequestDefaults().getXPathVersion());
        }

        // Categories
        Iterator<RequestAttributes> rait = request.getRequestAttributes().iterator();
        List<Map<String, Object>> generalCategoriesList = new ArrayList<Map<String, Object>>();
        while (rait.hasNext()) {
            RequestAttributes ra = rait.next();

            // create a new map for the category
            Map<String, Object> categoryMap = new HashMap<String, Object>();

            // fill in the category
            if (ra.getXmlId() != null) {
                categoryMap.put("Id", ra.getXmlId());
            }
            if (ra.getContentRoot() != null) {
                StringWriter writer = new StringWriter();
                Transformer transformer = null;
                try {
                    transformer = TransformerFactory.newInstance().newTransformer();
                    transformer.transform(new DOMSource(ra.getContentRoot()), new StreamResult(writer));
                } catch (Exception e) {
                    throw new JSONStructureException("Unable to Content node to string; e=" + e);
                }

                String xml = writer.toString();

                categoryMap.put("Content", xml);
            }

            Iterator<Attribute> attrIt = ra.getAttributes().iterator();
            List<Map<String, Object>> attributesList = new ArrayList<Map<String, Object>>();
            while (attrIt.hasNext()) {
                Attribute attr = attrIt.next();
                Map<String, Object> attrMap = new HashMap<String, Object>();
                attrMap.put("AttributeId", attr.getAttributeId().stringValue());
                if (attr.getIssuer() != null) {
                    attrMap.put("Issuer", attr.getIssuer());
                }
                attrMap.put("IncludeInResult", attr.getIncludeInResults());
                Collection<AttributeValue<?>> valuesCollection = attr.getValues();
                Iterator<AttributeValue<?>> valuesIt = valuesCollection.iterator();

                if (valuesCollection.size() == 1) {
                    // single-value
                    AttributeValue<?> attrValue = valuesIt.next();
                    attrMap.put("DataType", attrValue.getDataTypeId().stringValue());

                    attrMap.put("Value", jsonOutputObject(attrValue.getValue(), attrValue));

                } else if (valuesCollection.size() > 1) {
                    // multiple values
                    List<Object> attrValueList = new ArrayList<Object>();
                    while (valuesIt.hasNext()) {
                        AttributeValue<?> attrValue = valuesIt.next();
                        // assume all have the same type, so last one in list is fine
                        attrMap.put("DataType", attrValue.getDataTypeId().stringValue());

                        attrValueList.add(jsonOutputObject(attrValue.getValue(), attrValue));

                    }
                    attrMap.put("Value", attrValueList);

                }

                attributesList.add(attrMap);
            }
            if (attributesList.size() > 0) {
                categoryMap.put("Attribute", attributesList);
            }

            // We do not use the "Default" category objects because the XML may have multiples of the same
            // Category.
            // This is fine when the categories are contained in the array of Category objects,
            // but if we use the Default category objects we might end up with multiples of the same Category
            // name,
            // and the Jackson parser does not handle that well.
            // Example: This is ok because the AccessSubjects are independent items within the list:
            // { "Request" : {
            // "Category" : [
            // { "CategoryId" : ""subject", " },
            // { "CategoryId" : ""subject", " }
            // ]
            // }}
            //
            // This is NOT ok because the Subjects are seen as duplicate elements:
            // { "Request" : {
            // "AccessSubject" : {"},
            // "AccessSubject" : {"},
            // }}

            categoryMap.put("CategoryId", ra.getCategory().stringValue());
            generalCategoriesList.add(categoryMap);

        }

        if (generalCategoriesList.size() > 0) {
            requestMap.put("Category", generalCategoriesList);
        }

        // MultiRequests
        if (request.getMultiRequests() != null) {
            Collection<RequestReference> referenceCollection = request.getMultiRequests();

            Map<String, Object> multiRequestMap = new HashMap<String, Object>();
            List<Map<String, Object>> requestReferenceList = new ArrayList<Map<String, Object>>();

            Iterator<RequestReference> rrIt = referenceCollection.iterator();
            while (rrIt.hasNext()) {
                RequestReference rr = rrIt.next();
                Map<String, Object> requestReferenceMap = new HashMap<String, Object>();

                Collection<RequestAttributesReference> rarCollection = rr.getAttributesReferences();
                List<Object> ridList = new ArrayList<Object>();
                Iterator<RequestAttributesReference> rarIt = rarCollection.iterator();
                while (rarIt.hasNext()) {
                    RequestAttributesReference rar = rarIt.next();
                    ridList.add(rar.getReferenceId());
                }

                if (ridList.size() > 0) {
                    requestReferenceMap.put("ReferenceId", ridList);
                }

                if (requestReferenceMap.size() > 0) {
                    requestReferenceList.add(requestReferenceMap);
                }

                if (requestReferenceList.size() > 0) {
                    multiRequestMap.put("RequestReference", requestReferenceList);
                }
            }

            if (multiRequestMap.size() > 0) {
                requestMap.put("MultiRequests", multiRequestMap);
            }
        }

        //
        // Create the overall Request map
        //
        Map<String, Object> theWholeRequest = new HashMap<String, Object>();
        theWholeRequest.put("Request", requestMap);
        //
        // Create a string buffer
        //
        ObjectMapper mapper = new ObjectMapper().setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
        mapper.configure(SerializationFeature.INDENT_OUTPUT, prettyPrint);
        try (OutputStreamWriter osw = new OutputStreamWriter(outputStream)) {

            // convert the request to json string
            String json = mapper.writeValueAsString(theWholeRequest);

            // write it
            osw.write(json);

            // force output
            osw.flush();
        } catch (Exception e) {
            logger.error("Failed to write to json string: " + e.getLocalizedMessage(), e);
        }

    }

    /**
     * Create the appropriate object for JSON output. This needs to be a Boolean, Integer or Double for those
     * data types so that the ObjectMapper knows how to format the JSON text. For objects implementing
     * stringValue we use that string. for XPathExpressions use the Path. Otherwise default to using toString.
     *
     * @param obj
     * @return
     */
    private static Object jsonOutputObject(Object obj, AttributeValue<?> attrValue)
        throws JSONStructureException {
        if (obj instanceof String || obj instanceof Boolean || obj instanceof BigInteger) {
            return obj;
        } else if (obj instanceof Double) {
            Double d = (Double)obj;
            if (d == Double.NaN) {
                return "NaN";
            } else if (d == Double.POSITIVE_INFINITY) {
                return "INF";
            } else if (d == Double.NEGATIVE_INFINITY) {
                return "-INF";
            }
            return obj;
        } else if (obj instanceof SemanticString) {
            return ((SemanticString)obj).stringValue();
        } else if (obj instanceof X500Principal || obj instanceof URI) {
            // something is very weird with X500Principal data type. If left on its own the output is a map
            // that includes encoding.
            return obj.toString();
        } else if (obj instanceof XPathExpressionWrapper) {
            // create a map containing the complex value for the XPathExpression
            Map<String, Object> xpathExpressionMap = new HashMap<String, Object>();
            Identifier xpathCategoryId = attrValue.getXPathCategory();
            if (xpathCategoryId == null) {
                throw new JSONStructureException("XPathExpression is missing XPathCategory");
            }
            xpathExpressionMap.put("XPathCategory", attrValue.getXPathCategory().stringValue());

            XPathExpressionWrapper xw = (XPathExpressionWrapper)obj;
            xpathExpressionMap.put("XPath", xw.getPath());

            ExtendedNamespaceContext namespaceContext = xw.getNamespaceContext();
            if (namespaceContext != null) {
                List<Object> namespaceList = new ArrayList<Object>();

                // get the list of all namespace prefixes
                Iterator<String> prefixIt = namespaceContext.getAllPrefixes();
                while (prefixIt.hasNext()) {
                    String prefix = prefixIt.next();
                    String namespaceURI = namespaceContext.getNamespaceURI(prefix);
                    Map<String, Object> namespaceMap = new HashMap<String, Object>();
                    if (prefix != null && !prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
                        namespaceMap.put("Prefix", prefix);
                    }
                    namespaceMap.put("Namespace", namespaceURI);
                    namespaceList.add(namespaceMap);
                }

                xpathExpressionMap.put("Namespaces", namespaceList);
            }
            return xpathExpressionMap;

        } else {
            throw new JSONStructureException("Unhandled data type='" + obj.getClass().getName() + "'");
        }
    }

}

/*
 * Place to put very long output strings for editing during debugging
 */
