/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Matt MacIvor - 2.5.1 - Initial Implementation
package org.eclipse.persistence.internal.jaxb.json.schema;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.jaxb.json.schema.model.JsonSchema;
import org.eclipse.persistence.internal.jaxb.json.schema.model.JsonType;
import org.eclipse.persistence.internal.jaxb.json.schema.model.Property;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.QNameInheritancePolicy;
import org.eclipse.persistence.internal.oxm.XMLBinaryDataHelper;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.mappings.BinaryDataCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.BinaryDataMapping;
import org.eclipse.persistence.internal.oxm.mappings.ChoiceCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.ChoiceObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.CollectionReferenceMapping;
import org.eclipse.persistence.internal.oxm.mappings.CompositeCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.CompositeObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.DirectCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.DirectMapping;
import org.eclipse.persistence.internal.oxm.mappings.InverseReferenceMapping;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
import org.eclipse.persistence.internal.oxm.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.internal.oxm.record.namespaces.MapNamespacePrefixMapper;
import org.eclipse.persistence.jaxb.JAXBContext;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.jaxb.JAXBEnumTypeConverter;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.oxm.NamespacePrefixMapper;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.mappings.XMLAnyAttributeMapping;
import org.eclipse.persistence.oxm.mappings.XMLAnyCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLAnyObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLFragmentCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLFragmentMapping;
import org.eclipse.persistence.sessions.Project;

/**
 * INTERNAL:
 * <p><b>Purpose:</b> This class generates an instance of JsonSchema based on an EclipseLink
 * project and given a root class. The descriptor for the root class' mappings are traversed and
 * the associated schema artifacts are created.
 *
 */
public class JsonSchemaGenerator {
    Project project;
    JsonSchema schema;
    Map contextProperties;
    String attributePrefix;
    Class rootClass;
    boolean namespaceAware;
    NamespaceResolver resolver;
    String NAMESPACE_SEPARATOR = ".";
    NamespacePrefixMapper prefixMapper = null;
    Property[] xopIncludeProp = null;
    XMLContext xmlContext;
    Property rootProperty = null;
    private JAXBContext jaxbContext;

    private static String DEFINITION_PATH="#/definitions";

    private static HashMap<Class, JsonType> javaTypeToJsonType;


    public JsonSchemaGenerator(JAXBContext jaxbContext, Map properties) {
        //this.project = project;
        this.xmlContext = jaxbContext.getXMLContext();
        this.jaxbContext = jaxbContext;
        this.contextProperties = properties;
        if(properties != null) {
            attributePrefix = (String)properties.get(JAXBContextProperties.JSON_ATTRIBUTE_PREFIX);
            Object prefixMapperValue = properties.get(JAXBContextProperties.NAMESPACE_PREFIX_MAPPER);
            if(prefixMapperValue != null) {
                if(prefixMapperValue instanceof Map){
                    prefixMapper = new MapNamespacePrefixMapper((Map)prefixMapperValue);
                }else{
                    prefixMapper = (NamespacePrefixMapper)prefixMapperValue;
                }
            }
            if(prefixMapper != null) {
                //check for customer separator
                String namespaceSeparator = (String) properties.get(JAXBContextProperties.JSON_NAMESPACE_SEPARATOR);
                if(namespaceSeparator != null) {
                    this.NAMESPACE_SEPARATOR = namespaceSeparator;
                }
            }
        }
    }

    public JsonSchema generateSchema(Class rootClass) {
        this.rootClass = rootClass;
        schema = new JsonSchema();
        schema.setTitle(rootClass.getName());

        if(rootClass.isEnum()) {
            Class generatedWrapper = jaxbContext.getClassToGeneratedClasses().get(rootClass.getName());
            if(generatedWrapper != null) {
                rootClass = generatedWrapper;
            } else {
                schema.setType(JsonType.STRING);
                return schema;
            }
        }
        //Check for simple type
        JsonType rootType = getJsonTypeForJavaType(rootClass);
        if(rootType != JsonType.OBJECT) {
            if(rootType == JsonType.BINARYTYPE) {
                schema.setAnyOf(getXopIncludeProperties());
                return schema;
            } else {
                schema.setType(rootType);
                return schema;
            }
        }

        Map<String, Property> properties = null;
        //Check for root level list or array
        if(rootClass.isArray() || isCollection(rootClass)) {
            schema.setType(JsonType.ARRAY);
            schema.setItems(new Property());
            Class<Object> itemType = Object.class;

            if(rootClass.isArray()) {
                itemType = rootClass.getComponentType();
            } else {
                Type pType = rootClass.getGenericSuperclass();
                if(pType instanceof ParameterizedType) {
                    itemType = (Class)((ParameterizedType)pType).getActualTypeArguments()[0];
                }
            }
            rootType = getJsonTypeForJavaType(itemType);
            schema.getItems().setType(rootType);
            if(rootType != JsonType.OBJECT) {
                return schema;
            }
            rootClass = itemType;
            properties = schema.getItems().getProperties();

        } else {
            schema.setType(JsonType.OBJECT);
            properties = schema.getProperties();
        }
        this.project = this.xmlContext.getSession(rootClass).getProject();

        XMLDescriptor descriptor = (XMLDescriptor)project.getDescriptor(rootClass);

        Boolean includeRoot = Boolean.TRUE;
        if(contextProperties != null) {
            includeRoot = (Boolean) this.contextProperties.get(JAXBContextProperties.JSON_INCLUDE_ROOT);
            if(includeRoot == null) {
                includeRoot = Boolean.TRUE;
            }
        }
        if(Boolean.TRUE.equals(includeRoot)) {
            XMLField field = descriptor.getDefaultRootElementField();
            if(field != null) {
                rootProperty = new Property();
                rootProperty.setType(JsonType.OBJECT);
                rootProperty.setName(getNameForFragment(field.getXPathFragment()));
                properties.put(rootProperty.getName(), rootProperty);
                properties = rootProperty.getProperties();
            }
        }

        boolean allowsAdditionalProperties = hasAnyMappings(descriptor);
        if(descriptor.hasInheritance()) {
            //handle inheritence
            //schema.setAnyOf(new Property[descriptor.getInheritancePolicy().getAllChildDescriptors().size()]);
            List<ClassDescriptor> descriptors = this.getAllDescriptorsForInheritance(descriptor);
            Property[] props = new Property[descriptors.size()];
            for(int i = 0; i < props.length; i++) {
                XMLDescriptor nextDescriptor = (XMLDescriptor)descriptors.get(i);

                Property ref = new Property();
                ref.setRef(getReferenceForDescriptor(nextDescriptor, true));
                props[i] = ref;
            }
            if(rootProperty != null) {
                rootProperty.setAnyOf(props);
                rootProperty.setProperties(null);
                rootProperty.setType(null);
                rootProperty.setAdditionalProperties(null);
                rootProperty.setAdditionalProperties(null);
            } else {
                this.schema.setAnyOf(props);
                this.schema.setProperties(null);
                this.schema.setType(null);
                this.schema.setAdditionalProperties(null);
            }
        } else {
            JsonType type = populateProperties(properties, descriptor);
            if(type != null) {
                if(type == JsonType.BINARYTYPE) {
                    if(rootProperty != null) {
                        rootProperty.setAnyOf(getXopIncludeProperties());
                        rootProperty.setProperties(null);
                        rootProperty.setAdditionalProperties(null);
                        rootProperty.setType(null);
                    } else {
                        this.schema.setAnyOf(getXopIncludeProperties());
                        this.schema.setProperties(null);
                        this.schema.setType(null);
                        this.schema.setAdditionalProperties(null);
                    }
                } else if(type == JsonType.ENUMTYPE) {
                    if(rootProperty != null) {
                        rootProperty.setType(JsonType.STRING);
                        rootProperty.setProperties(null);
                        rootProperty.setEnumeration(getEnumeration(descriptor));
                    } else {
                        this.schema.setType(JsonType.STRING);
                        this.schema.setProperties(null);
                        this.schema.setEnumeration(getEnumeration(descriptor));
                }
                } else {
                    if(rootProperty != null) {
                        rootProperty.setType(type);
                    } else {
                        schema.setType(type);
                    }
                }
            } else {
                if(rootProperty != null) {
                    rootProperty.setAdditionalProperties(allowsAdditionalProperties);
                } else {
                    this.schema.setAdditionalProperties(allowsAdditionalProperties);
                }
            }
        }
        return schema;
    }

    private List<String> getEnumeration(XMLDescriptor desc) {
        return getEnumeration(getTextMapping(desc));
    }

    private List<String> getEnumeration(DatabaseMapping textMapping) {
        JAXBEnumTypeConverter converter = null;
        if(textMapping.isAbstractDirectMapping()) {
            converter = (JAXBEnumTypeConverter) ((DirectMapping)textMapping).getConverter();
        } else if(textMapping.isAbstractCompositeDirectCollectionMapping()) {
            converter = (JAXBEnumTypeConverter) ((DirectCollectionMapping)textMapping).getValueConverter();
        }
        if(converter == null) {
            return null;
        }
        List<String> enumeration = new ArrayList<String>();
        for(Object nextValue: converter.getAttributeToFieldValues().values()) {
            enumeration.add(nextValue.toString());
        }
        return enumeration;
    }

    private boolean hasAnyMappings(XMLDescriptor descriptor) {
        for(DatabaseMapping next:descriptor.getMappings()) {
            if(next instanceof XMLAnyAttributeMapping ||
                    next instanceof XMLAnyObjectMapping ||
                    next instanceof XMLAnyCollectionMapping ||
                    next instanceof XMLFragmentCollectionMapping ||
                    next instanceof XMLFragmentMapping

             ) {
                return true;
            } else if(next instanceof CompositeCollectionMapping) {
                CompositeCollectionMapping ccm = (CompositeCollectionMapping)next;
                if(ccm.getReferenceDescriptor() == null && ((XMLField)ccm.getField()).isSelfField()) {
                    return true;
                }
            } else if(next instanceof CompositeObjectMapping) {
                CompositeObjectMapping ccm = (CompositeObjectMapping)next;
                if(ccm.getReferenceDescriptor() == null && ((XMLField)ccm.getField()).isSelfField()) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Populates the map of properties based on the mappings in this descriptor. If the descriptor represents a
     * simple type (a single direct mapping with xpath of text) then the name of the simple type is returned.
     * Otherwise null is returned.
     *
     * @return null for a complex type, the simple type name for a simple type.
     */
    private JsonType populateProperties(Map<String, Property> properties, XMLDescriptor descriptor) {

        List<DatabaseMapping> mappings = descriptor.getMappings();
        if(mappings == null || mappings.isEmpty()) {
            return null;
        }

        if(isSimpleType(descriptor)) {
            //check for simple type
            DatabaseMapping mapping = getTextMapping(descriptor);
            if(mapping.isAbstractDirectMapping()) {
                DirectMapping directMapping = (DirectMapping)mapping;
                if(directMapping.getConverter() instanceof JAXBEnumTypeConverter) {
                    return JsonType.ENUMTYPE;
                }
                return getJsonTypeForJavaType(directMapping.getAttributeClassification());
            } else if(mapping.isAbstractCompositeDirectCollectionMapping()) {
                DirectCollectionMapping directMapping = (DirectCollectionMapping)mapping;
                if(directMapping.getValueConverter() instanceof JAXBEnumTypeConverter) {
                    return JsonType.ENUMTYPE;
                }
                Class type = directMapping.getAttributeElementClass();
                if(type == null) {
                    type = CoreClassConstants.STRING;
                }
                return getJsonTypeForJavaType(type);
            } else {
                //only other option is binary
                return JsonType.BINARYTYPE;
            }
        }
        for(DatabaseMapping next:mappings) {
            if(next instanceof ChoiceObjectMapping) {
                ChoiceObjectMapping coMapping = (ChoiceObjectMapping)next;
                for(Object nestedMapping:coMapping.getChoiceElementMappingsByClass().values()) {
                    Property prop = generateProperty((Mapping)nestedMapping, descriptor, properties);
                    if(prop != null && !(properties.containsKey(prop.getName()))) {
                        properties.put(prop.getName(), prop);
                    }
                }
            } else if(next instanceof ChoiceCollectionMapping) {
                ChoiceCollectionMapping coMapping = (ChoiceCollectionMapping)next;
                for(Object nestedMapping:coMapping.getChoiceElementMappingsByClass().values()) {
                    Property prop = generateProperty((Mapping)nestedMapping, descriptor, properties);
                    if(prop != null && !(properties.containsKey(prop.getName()))) {
                        properties.put(prop.getName(), prop);
                    }
                }
            } else {
                Property prop = generateProperty((Mapping)next, descriptor, properties);
                if(prop != null && !(properties.containsKey(prop.getName()))) {
                    properties.put(prop.getName(), prop);
                }
            }
        }
        return null;
    }

    private DatabaseMapping getTextMapping(XMLDescriptor descriptor) {
        for(DatabaseMapping next:descriptor.getMappings()) {
            if(next.isAbstractDirectMapping()) {
                DirectMapping mapping = (DirectMapping)next;
                if(((XMLField)mapping.getField()).getXPathFragment().nameIsText()) {
                    return next;
                }
            }
            if(next.isAbstractCompositeDirectCollectionMapping()) {
                DirectCollectionMapping mapping = (DirectCollectionMapping)next;
                if(((XMLField)mapping.getField()).getXPathFragment().nameIsText()) {
                    return next;
                }
            }
            if(next instanceof BinaryDataMapping) {
                BinaryDataMapping mapping = (BinaryDataMapping)next;
                if(((XMLField)mapping.getField()).isSelfField()) {
                    return next;
                }
            }
            if(next instanceof BinaryDataCollectionMapping) {
                BinaryDataCollectionMapping mapping = (BinaryDataCollectionMapping)next;
                if(((XMLField)mapping.getField()).isSelfField()) {
                    return next;
                }
            }
        }
        return null;
    }

    private boolean isSimpleType(XMLDescriptor descriptor) {
        DatabaseMapping mapping = null;
        if(descriptor.getMappings().size() == 1) {
            mapping = descriptor.getMappings().get(0);
        } else if(descriptor.getMappings().size() == 2) {
            boolean hasInverseRef = false;
            for(DatabaseMapping next:descriptor.getMappings()) {
                if(next instanceof InverseReferenceMapping) {
                    hasInverseRef = true;
                } else {
                    mapping = next;
                }
            }
            if(!hasInverseRef) {
                return false;
            }
        } else {
            return false;
        }

        if(mapping.isAbstractDirectMapping()) {
            if(((XMLField)mapping.getField()).getXPathFragment().nameIsText()) {
                return true;
            }
        }
        if(mapping.isAbstractCompositeDirectCollectionMapping()) {
            if(((XMLField)mapping.getField()).getXPathFragment().nameIsText()) {
                return true;
            }
        }
        if(mapping instanceof BinaryDataMapping) {
            if(((XMLField)mapping.getField()).isSelfField()) {
                return true;
            }
        }
        if(mapping instanceof BinaryDataCollectionMapping) {
            if(((XMLField)mapping.getField()).isSelfField()) {
                return true;
            }
        }
        return false;
    }

    private Property generateProperty(Mapping next, XMLDescriptor descriptor, Map<String, Property> properties) {
        Property prop = null;
        if(next.isCollectionMapping()) {
            if(next instanceof CollectionReferenceMapping) {
                CollectionReferenceMapping mapping = (CollectionReferenceMapping)next;
                Set<XMLField> sourceFields = mapping.getSourceToTargetKeyFieldAssociations().keySet();
                XMLDescriptor reference = (XMLDescriptor) mapping.getReferenceDescriptor();
                for(XMLField nextField: sourceFields) {
                    XPathFragment frag = nextField.getXPathFragment();
                    String propertyName = getNameForFragment(frag);

                    XMLField targetField = (XMLField) mapping.getSourceToTargetKeyFieldAssociations().get(nextField);
                    Class<String> type = CoreClassConstants.STRING;
                    if(reference != null) {
                        type = getTypeForTargetField(targetField, reference);
                    }

                    prop = properties.get(propertyName);
                    if(prop == null) {
                        prop = new Property();
                        prop.setName(propertyName);
                    }
                    Property nestedProperty = getNestedPropertyForFragment(frag, prop);
                    nestedProperty.setType(JsonType.ARRAY);
                    nestedProperty.setItem(new Property());
                    nestedProperty.getItem().setType(getJsonTypeForJavaType(type));
                    if(!properties.containsKey(prop.getName())) {
                        properties.put(prop.getName(), prop);
                    }
                }
                return prop;
            } else if(next.isAbstractCompositeCollectionMapping()) {
                CompositeCollectionMapping mapping = (CompositeCollectionMapping)next;
                XMLField field = (XMLField)mapping.getField();
                XPathFragment frag = field.getXPathFragment();
                String propName = getNameForFragment(frag);
                //for paths, there may already be an existing property
                prop = properties.get(propName);
                if(prop == null) {
                    prop = new Property();
                    prop.setName(propName);
                }
                Property nestedProperty = getNestedPropertyForFragment(frag, prop);
                nestedProperty.setType(JsonType.ARRAY);
                nestedProperty.setItem(new Property());
                XMLDescriptor referenceDescriptor = (XMLDescriptor)mapping.getReferenceDescriptor();
                if(referenceDescriptor != null && referenceDescriptor.hasInheritance()) {
                    //handle inheritence
                    //schema.setAnyOf(new Property[descriptor.getInheritancePolicy().getAllChildDescriptors().size()]);
                    List<ClassDescriptor> descriptors = getAllDescriptorsForInheritance(referenceDescriptor);
                    Property[] props = new Property[descriptors.size()];
                    for(int i = 0; i < props.length; i++) {
                        XMLDescriptor nextDescriptor = null;
                        nextDescriptor = (XMLDescriptor)descriptors.get(i);
                        Property ref = new Property();
                        ref.setRef(getReferenceForDescriptor(nextDescriptor, true));
                        props[i] = ref;
                    }
                    nestedProperty.getItem().setAnyOf(props);
                } else {
                    nestedProperty.getItem().setRef(getReferenceForDescriptor(referenceDescriptor, false));
                    //populateProperties(nestedProperty.getItem().getProperties(), (XMLDescriptor)mapping.getReferenceDescriptor());
                }
            } else if(next.isAbstractCompositeDirectCollectionMapping()) {
                DirectCollectionMapping mapping = (DirectCollectionMapping)next;
                XMLField field = (XMLField)mapping.getField();
                XPathFragment frag = field.getXPathFragment();
                List<String> enumeration = null;
                if(mapping.getValueConverter() instanceof JAXBEnumTypeConverter) {
                    enumeration = getEnumeration((DatabaseMapping)next);
                }
                String propertyName = getNameForFragment(frag);
                if(frag.nameIsText()) {
                    propertyName = (String)this.contextProperties.get(MarshallerProperties.JSON_VALUE_WRAPPER);
                }

                if(frag.isAttribute() && this.attributePrefix != null) {
                    propertyName = attributePrefix + propertyName;
                }
                prop = properties.get(propertyName);
                if(prop == null) {
                    prop = new Property();
                    prop.setName(propertyName);
                }
                Property nestedProperty = getNestedPropertyForFragment(frag, prop);
                nestedProperty.setType(JsonType.ARRAY);
                nestedProperty.setItem(new Property());
                if(enumeration != null) {
                    nestedProperty.getItem().setEnumeration(enumeration);
                }
                Class type = mapping.getAttributeElementClass();
                if(type == null) {
                    type = CoreClassConstants.STRING;
                }
                nestedProperty.getItem().setType(getJsonTypeForJavaType(type));
                return prop;
            } else if(next instanceof BinaryDataCollectionMapping) {
                BinaryDataCollectionMapping mapping = (BinaryDataCollectionMapping)next;
                XMLField field = (XMLField)mapping.getField();
                XPathFragment frag = field.getXPathFragment();

                String propertyName = getNameForFragment(frag);
                if(frag.isSelfFragment()) {
                    propertyName = Constants.VALUE_WRAPPER;
                    if(this.contextProperties != null)  {
                        String valueWrapper = (String) this.contextProperties.get(JAXBContextProperties.JSON_VALUE_WRAPPER);
                        if(valueWrapper != null) {
                            propertyName = valueWrapper;
                        }
                    }
                }

                if(frag.isAttribute() && this.attributePrefix != null) {
                    propertyName = attributePrefix + propertyName;
                }
                prop = properties.get(propertyName);
                if(prop == null) {
                    prop = new Property();
                    prop.setName(propertyName);
                }
                Property nestedProperty = getNestedPropertyForFragment(frag, prop);
                nestedProperty.setType(JsonType.ARRAY);
                nestedProperty.setItem(new Property());

                if(mapping.shouldInlineBinaryData()) {
                    nestedProperty.getItem().setType(JsonType.STRING);
                } else {
                    nestedProperty.getItem().setAnyOf(getXopIncludeProperties());
                }
                return prop;
            }
        } else {
            if(next.isAbstractDirectMapping()) {
                //handle direct mapping
                DirectMapping directMapping = (DirectMapping)next;
                XMLField field = (XMLField)directMapping.getField();
                XPathFragment frag = field.getXPathFragment();
                List<String> enumeration = null;
                if(directMapping.getConverter() instanceof JAXBEnumTypeConverter) {
                    enumeration = getEnumeration((DatabaseMapping)directMapping);
                }
                String propertyName = getNameForFragment(frag);
                if(frag.nameIsText()) {
                    propertyName = Constants.VALUE_WRAPPER;
                    if(this.contextProperties != null)  {
                        String valueWrapper = (String) this.contextProperties.get(JAXBContextProperties.JSON_VALUE_WRAPPER);
                        if(valueWrapper != null) {
                            propertyName = valueWrapper;
                        }
                    }
                }
                if(frag.isAttribute() && this.attributePrefix != null) {
                    propertyName = attributePrefix + propertyName;
                }
                prop = properties.get(propertyName);
                if(prop == null) {
                    prop = new Property();
                    prop.setName(propertyName);
                }
                Property nestedProperty = getNestedPropertyForFragment(frag, prop);
                if(enumeration != null) {
                    nestedProperty.setEnumeration(enumeration);
                }
                if(directMapping instanceof BinaryDataMapping) {
                    BinaryDataMapping binaryMapping = (BinaryDataMapping)directMapping;
                    if(binaryMapping.shouldInlineBinaryData() || binaryMapping.isSwaRef()) {
                        nestedProperty.setType(JsonType.STRING);
                    } else {
                        if(this.xopIncludeProp == null) {
                            initXopIncludeProp();
                        }
                        nestedProperty.setAnyOf(this.xopIncludeProp);
                    }
                } else {
                    nestedProperty.setType(getJsonTypeForJavaType(directMapping.getAttributeClassification()));
                }
                return prop;
            } else if(next instanceof ObjectReferenceMapping) {
                ObjectReferenceMapping mapping = (ObjectReferenceMapping)next;
                Set<XMLField> sourceFields = mapping.getSourceToTargetKeyFieldAssociations().keySet();
                XMLDescriptor reference = (XMLDescriptor) mapping.getReferenceDescriptor();
                for(XMLField nextField: sourceFields) {
                    XPathFragment frag = nextField.getXPathFragment();
                    String propName = getNameForFragment(frag);
                    XMLField targetField = (XMLField) mapping.getSourceToTargetKeyFieldAssociations().get(nextField);
                    Class<String> type = CoreClassConstants.STRING;
                    if(reference != null) {
                        type = getTypeForTargetField(targetField, reference);
                    }

                    prop = properties.get(propName);
                    if(prop == null) {
                        prop = new Property();
                        prop.setName(propName);
                    }
                    Property nestedProperty = getNestedPropertyForFragment(frag, prop);
                    //nestedProperty.setType(JsonType.ARRAY);
                    //nestedProperty.setItem(new Property());
                    nestedProperty.setType(getJsonTypeForJavaType(type));
                    if(!properties.containsKey(prop.getName())) {
                        properties.put(prop.getName(), prop);
                    }
                }
                return prop;
            } else if(next.isAbstractCompositeObjectMapping()) {
                CompositeObjectMapping mapping = (CompositeObjectMapping)next;
                XMLDescriptor nextDescriptor = (XMLDescriptor)mapping.getReferenceDescriptor();
                XMLField field = (XMLField)mapping.getField();
                XPathFragment firstFragment = field.getXPathFragment();
                if(firstFragment.isSelfFragment() || firstFragment.nameIsText()) {
                    if(nextDescriptor != null) {
                        populateProperties(properties, nextDescriptor);
                    }
                } else {
                    String propName = getNameForFragment(firstFragment);
                    prop = properties.get(propName);
                    if(prop == null) {
                        prop = new Property();
                        prop.setName(propName);
                    }
                    //prop.setType(JsonType.OBJECT);
                    prop.setName(propName);
                    Property nestedProperty = getNestedPropertyForFragment(firstFragment, prop);
                    XMLDescriptor referenceDescriptor = (XMLDescriptor)mapping.getReferenceDescriptor();
                    if(referenceDescriptor != null && referenceDescriptor.hasInheritance()) {
                        //handle inheritence
                        //schema.setAnyOf(new Property[descriptor.getInheritancePolicy().getAllChildDescriptors().size()]);
                        List<ClassDescriptor> descriptors = getAllDescriptorsForInheritance(referenceDescriptor);
                        Property[] props = new Property[descriptors.size()];
                        for(int i = 0; i < props.length; i++) {
                            XMLDescriptor nextDesc = (XMLDescriptor)descriptors.get(i);
                            Property ref = new Property();
                            ref.setRef(getReferenceForDescriptor(nextDesc, true));
                            props[i] = ref;
                        }
                        nestedProperty.setAnyOf(props);
                    } else {
                        nestedProperty.setRef(getReferenceForDescriptor(referenceDescriptor, false));
                        //populateProperties(nestedProperty.getItem().getProperties(), (XMLDescriptor)mapping.getReferenceDescriptor());
                    }                    //populateProperties(nestedProperty.getProperties(), nextDescriptor);
                }
            } else if(next instanceof BinaryDataMapping) {
                BinaryDataMapping binaryMapping = (BinaryDataMapping)next;
                XMLField field = (XMLField)binaryMapping.getField();
                XPathFragment frag = field.getXPathFragment();
                String propertyName = getNameForFragment(frag);
                if(frag.isSelfFragment()) {
                    propertyName = Constants.VALUE_WRAPPER;
                    if(this.contextProperties != null)  {
                        String valueWrapper = (String) this.contextProperties.get(MarshallerProperties.JSON_VALUE_WRAPPER);
                        if(valueWrapper != null) {
                            propertyName = valueWrapper;
                        }
                    }
                }
                if(frag.isAttribute() && this.attributePrefix != null) {
                    propertyName = attributePrefix + propertyName;
                }
                prop = properties.get(propertyName);
                if(prop == null) {
                    prop = new Property();
                    prop.setName(propertyName);
                }
                Property nestedProperty = getNestedPropertyForFragment(frag, prop);
                if(binaryMapping.shouldInlineBinaryData() || binaryMapping.isSwaRef()) {
                    nestedProperty.setType(JsonType.STRING);
                } else {
                    if(this.xopIncludeProp == null) {
                        initXopIncludeProp();
                    }
                    nestedProperty.setAnyOf(this.xopIncludeProp);
                }
                return prop;
            }
        }

        return prop;
    }

    private String getNameForFragment(XPathFragment frag) {
        String name = frag.getLocalName();

        if(this.prefixMapper != null) {
            String namespaceUri = frag.getNamespaceURI();
            if(namespaceUri != null && namespaceUri.length() != 0) {
                String prefix = prefixMapper.getPreferredPrefix(namespaceUri, null, true);
                if(prefix != null) {
                    name = prefix + NAMESPACE_SEPARATOR + name;
                }
            }
        }
        return name;
    }

    private void initXopIncludeProp() {
        this.xopIncludeProp = new Property[2];
        Property p = new Property();
        p.setType(JsonType.STRING);
        this.xopIncludeProp[0] = p;

        p = new Property();
        this.xopIncludeProp[1] = p;
        p.setType(JsonType.OBJECT);
        Property includeProperty = new Property();
        includeProperty.setName("Include");
        includeProperty.setType(JsonType.OBJECT);
        p.getProperties().put(includeProperty.getName(), includeProperty);

        Property hrefProp = new Property();
        String propName = "href";
        if(this.attributePrefix != null) {
            propName = this.attributePrefix + propName;
        }
        hrefProp.setName(propName);
        hrefProp.setType(JsonType.STRING);
        includeProperty.getProperties().put(propName, hrefProp);


    }



    private String getReferenceForDescriptor(XMLDescriptor referenceDescriptor, boolean generateRoot) {
        if(referenceDescriptor == null) {
            return null;
        }
        String className = referenceDescriptor.getJavaClass().getSimpleName();
        String referenceName = DEFINITION_PATH + "/" + className;

        if(referenceDescriptor.getJavaClass() == this.rootClass && !generateRoot) {
            String ref = "#";
            if(this.rootProperty != null) {
                ref += "/properties/" + rootProperty.getName();
            }
            return ref;
        }
        if(!this.schema.getDefinitions().containsKey(className)) {
            Property definition = new Property();
            definition.setName(className);
            this.schema.getDefinitions().put(definition.getName(), definition);
            definition.setType(JsonType.OBJECT);
            if(referenceDescriptor.hasInheritance() && referenceDescriptor.getInheritancePolicy().hasClassIndicator()) {
                XMLField f = (XMLField)referenceDescriptor.getInheritancePolicy().getClassIndicatorField();
                Property indicatorProp = new Property();
                indicatorProp.setName(getNameForFragment(f.getXPathFragment()));
                indicatorProp.setType(JsonType.STRING);
                definition.getProperties().put(indicatorProp.getName(), indicatorProp);
            }
            JsonType jType = populateProperties(definition.getProperties(), referenceDescriptor);
            if(jType != null) {
                if(jType == JsonType.BINARYTYPE) {
                    definition.setAnyOf(getXopIncludeProperties());
                    definition.setProperties(null);
                    definition.setAdditionalProperties(null);
                    definition.setType(null);
                } else {
                    //this represents a simple type
                    definition.setType(jType);
                    definition.setProperties(null);
                }
            }
            definition.setAdditionalProperties(hasAnyMappings(referenceDescriptor));
        }
        // TODO Auto-generated method stub
        return referenceName;
    }

    private Class getTypeForTargetField(XMLField targetField, XMLDescriptor reference) {
        for(DatabaseMapping next: reference.getMappings()) {
            if(next.isDirectToFieldMapping()) {
                DirectMapping directMapping = (DirectMapping)next;
                if(directMapping.getField().equals(targetField)) {
                    return directMapping.getAttributeClassification();
                }
            }
        }
        return null;
    }

    private JsonType getJsonTypeForJavaType(Class attributeClassification) {
        if(attributeClassification.isEnum()) {
            return JsonType.ENUMTYPE;
        }
        HashMap<Class, JsonType> types = getJavaTypeToJsonType();
        JsonType jsonType = types.get(attributeClassification);
        if(jsonType == null) {
            return JsonType.OBJECT;
        }
        return jsonType;
    }

    private static HashMap<Class, JsonType> getJavaTypeToJsonType() {
        if(javaTypeToJsonType == null) {
            initJavaTypeToJsonType();
        }
        return javaTypeToJsonType;
    }

    private static void initJavaTypeToJsonType() {
        javaTypeToJsonType = new HashMap<Class, JsonType>();
        javaTypeToJsonType.put(CoreClassConstants.APBYTE, JsonType.ARRAY);
        javaTypeToJsonType.put(CoreClassConstants.BIGDECIMAL, JsonType.NUMBER);
        javaTypeToJsonType.put(CoreClassConstants.BIGINTEGER, JsonType.INTEGER);
        javaTypeToJsonType.put(CoreClassConstants.PBOOLEAN, JsonType.BOOLEAN);
        javaTypeToJsonType.put(CoreClassConstants.PBYTE, JsonType.NUMBER);
        javaTypeToJsonType.put(CoreClassConstants.CALENDAR, JsonType.STRING);
        javaTypeToJsonType.put(CoreClassConstants.PDOUBLE, JsonType.NUMBER);
        javaTypeToJsonType.put(CoreClassConstants.PFLOAT, JsonType.NUMBER);
        javaTypeToJsonType.put(CoreClassConstants.PINT, JsonType.INTEGER);
        javaTypeToJsonType.put(CoreClassConstants.PLONG, JsonType.NUMBER);
        javaTypeToJsonType.put(CoreClassConstants.PSHORT, JsonType.NUMBER);
        javaTypeToJsonType.put(CoreClassConstants.STRING, JsonType.STRING);
        javaTypeToJsonType.put(CoreClassConstants.CHAR, JsonType.STRING);
        // other pairs
        javaTypeToJsonType.put(CoreClassConstants.ABYTE, JsonType.ARRAY);
        javaTypeToJsonType.put(CoreClassConstants.BOOLEAN, JsonType.BOOLEAN);
        javaTypeToJsonType.put(CoreClassConstants.BYTE, JsonType.NUMBER);
        javaTypeToJsonType.put(CoreClassConstants.CLASS, JsonType.STRING);
        javaTypeToJsonType.put(CoreClassConstants.GREGORIAN_CALENDAR, JsonType.STRING);
        javaTypeToJsonType.put(CoreClassConstants.DOUBLE, JsonType.NUMBER);
        javaTypeToJsonType.put(CoreClassConstants.FLOAT, JsonType.NUMBER);
        javaTypeToJsonType.put(CoreClassConstants.INTEGER, JsonType.INTEGER);
        javaTypeToJsonType.put(CoreClassConstants.LONG, JsonType.NUMBER);
        javaTypeToJsonType.put(CoreClassConstants.OBJECT, JsonType.OBJECT);
        javaTypeToJsonType.put(CoreClassConstants.SHORT, JsonType.NUMBER);
        javaTypeToJsonType.put(CoreClassConstants.UTILDATE, JsonType.STRING);
        javaTypeToJsonType.put(CoreClassConstants.SQLDATE, JsonType.STRING);
        javaTypeToJsonType.put(CoreClassConstants.TIME, JsonType.STRING);
        javaTypeToJsonType.put(CoreClassConstants.TIMESTAMP, JsonType.STRING);
        javaTypeToJsonType.put(CoreClassConstants.DURATION, JsonType.STRING);
        javaTypeToJsonType.put(Constants.QNAME_CLASS, JsonType.STRING);
        javaTypeToJsonType.put(Constants.URI, JsonType.STRING);
        javaTypeToJsonType.put(Constants.UUID, JsonType.STRING);

        javaTypeToJsonType.put(XMLBinaryDataHelper.getXMLBinaryDataHelper().DATA_HANDLER, JsonType.BINARYTYPE);
        javaTypeToJsonType.put(XMLBinaryDataHelper.getXMLBinaryDataHelper().IMAGE, JsonType.BINARYTYPE);
        javaTypeToJsonType.put(XMLBinaryDataHelper.getXMLBinaryDataHelper().SOURCE, JsonType.BINARYTYPE);
        javaTypeToJsonType.put(XMLBinaryDataHelper.getXMLBinaryDataHelper().MULTIPART, JsonType.BINARYTYPE);

    }

    private Property getNestedPropertyForFragment(XPathFragment frag, Property prop) {
        if(frag.getNextFragment() == null  || frag.getNextFragment().nameIsText() ) {
            return prop;
        }
        Map<String, Property> currentProperties = prop.getProperties();
        prop.setProperties(currentProperties);
        prop.setType(JsonType.OBJECT);
        frag = frag.getNextFragment();
        String propertyName = getNameForFragment(frag);
        if(frag.isAttribute() && this.attributePrefix != null) {
            propertyName = this.attributePrefix + "propertyName";
        }
        while(frag != null && !frag.nameIsText()) {
            Property nestedProperty = prop.getProperty(propertyName);
            if(nestedProperty == null) {
                nestedProperty = new Property();
                nestedProperty.setName(propertyName);
            }
            currentProperties.put(nestedProperty.getName(), nestedProperty);
            if(frag.getNextFragment() == null || frag.getNextFragment().nameIsText()) {
                return nestedProperty;
            } else {
                nestedProperty.setType(JsonType.OBJECT);

                currentProperties = nestedProperty.getProperties();
            }
            frag = frag.getNextFragment();
            propertyName = getNameForFragment(frag);
        }
        return null;
    }

    private Property[] getXopIncludeProperties() {
        if(this.xopIncludeProp == null) {
            this.initXopIncludeProp();
        }
        return this.xopIncludeProp;
    }

    private boolean isCollection(Class type) {
        if (CoreClassConstants.Collection_Class.isAssignableFrom(type)
                || CoreClassConstants.List_Class.isAssignableFrom(type)
                || CoreClassConstants.Set_Class.isAssignableFrom(type)) {
            return true;
        }
        return false;
    }

    private List<ClassDescriptor> getAllDescriptorsForInheritance(XMLDescriptor descriptor) {
        ArrayList<ClassDescriptor> descriptors = new ArrayList<ClassDescriptor>();
        QNameInheritancePolicy policy = (QNameInheritancePolicy) descriptor.getInheritancePolicy();
        descriptors.add(descriptor);
        descriptors.addAll(policy.getAllChildDescriptors());
        ClassDescriptor parent = policy.getParentDescriptor();
        while(parent != null) {
            descriptors.add(parent);
            parent = parent.getInheritancePolicy().getParentDescriptor();
        }
        return descriptors;

    }

}
