/*
 * 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<?> 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<?> 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<?> 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;

    }

}
