/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.axis2.jaxws.wrapper.impl;

import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.utility.PropertyDescriptorPlus;
import org.apache.axis2.jaxws.utility.XMLRootElementUtil;
import org.apache.axis2.jaxws.wrapper.JAXBWrapperTool;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * The JAXBWrapper tool is used to create a JAXB Object from a series of child objects (wrap) or get
 * the child objects from a JAXB Object (unwrap)
 */
public class JAXBWrapperToolImpl implements JAXBWrapperTool {

    private static final Log log = LogFactory.getLog(JAXBWrapperTool.class);

    /**
     * unwrap Returns the list of child objects of the jaxb object
     *
     * @param jaxbObject that represents the type
     * @param childNames list of xml child names as String
     * @param pdMap      PropertyDescriptor map for this jaxbObject
     * @return list of Objects in the same order as the element names.
     */
    public Object[] unWrap(Object jaxbObject,
                           List<String> childNames,
                           Map<String, PropertyDescriptorPlus> pdMap) throws JAXBWrapperException {


        if (jaxbObject == null) {
            throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr1"));
        }
        if (childNames == null) {
            throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr2"));
        }

        // Get the object that will have the property descriptors (i.e. the object representing the complexType)
        Object jaxbComplexTypeObj = jaxbObject;

        if (log.isDebugEnabled()) {
            log.debug("Invoking unWrap() method with jaxb object:" +
                    jaxbComplexTypeObj.getClass().getName());
            log.debug("The input child xmlnames are: " + toString(childNames));
        }
        
        // Check the PropertyDescriptorPlus map if debug is enabled.
        // The method makes sure that each child name has a matching jaxb property
        if (log.isDebugEnabled()) {
            checkPropertyDescriptorMap(jaxbComplexTypeObj.getClass(), childNames, pdMap);
        }

        // Get the corresponsing objects from the jaxb bean
        ArrayList<Object> objList = new ArrayList<Object>();
        for (String childName : childNames) {
            PropertyDescriptorPlus propInfo = pdMap.get(childName);
            Object object = null;
            if (propInfo == null) {
                throw new JAXBWrapperException(
                      Messages.getMessage("JAXBWrapperErr6", 
                      jaxbComplexTypeObj.getClass().getName(), 
                      childName));
            }
            try {
                object = propInfo.get(jaxbComplexTypeObj);
            } catch (Throwable e) {
                if (log.isDebugEnabled()) {
                    log.debug("An exception " + e.getClass() +
                            "occurred while trying to call get() on " + propInfo);
                    log.debug("The corresponding xml child name is: " + childName);
                }
                throw new JAXBWrapperException(e);
            }
            objList.add(object);
        }
        Object[] jaxbObjects = objList.toArray();
        objList = null;
        return jaxbObjects;

    }

    /**
     * wrap Creates a jaxb object that is initialized with the child objects.
     * <p/>
     * Note that the jaxbClass must be the class the represents the complexType. (It should never be
     * JAXBElement)
     *
     * @param jaxbClass
     * @param childNames    list of xml child names as String
     * @param childObjects, component type objects
     * @param pdMap         PropertyDescriptor map for this jaxbObject
     */
    public Object wrap(Class jaxbClass,
                       List<String> childNames,
                       Map<String, Object> childObjects,
                       Map<String, Class> declaredClassMap,
                       Map<String, PropertyDescriptorPlus> pdMap) throws JAXBWrapperException {


        if (childNames == null || childObjects == null) {
            throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr3"));
        }
        if (childNames.size() != childObjects.size()) {
            throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr4"));
        }

        if (log.isDebugEnabled()) {
            log.debug("Invoking unwrap() method to create jaxb object:" + jaxbClass.getName());
            log.debug("The input child xmlnames are: " + toString(childNames));
        }

        // Just like unWrap, check the property descriptor map to make sure it is accurate
        if (log.isDebugEnabled()) {
            checkPropertyDescriptorMap(jaxbClass, childNames, pdMap);
        }

        // The jaxb object always has a default constructor.  Create the object
        Object jaxbObject = null;
        try {
            jaxbObject = jaxbClass.newInstance();
        } catch (Throwable t) {
            if (log.isDebugEnabled()) {
                log.debug("An exception " + t.getClass() +
                        "occurred while trying to create jaxbobject  " + jaxbClass.getName());
            }
            throw new JAXBWrapperException(t);
        }

        // Now set each object onto the jaxb object
        for (String childName : childNames) {
            PropertyDescriptorPlus propInfo = pdMap.get(childName);
            Object value = childObjects.get(childName);
            Class dclClass = declaredClassMap.get(childName);
            if (propInfo == null) {
                throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr6", 
                                                                   jaxbClass.getName(), 
                                                                   childName));
            }
            try {
                propInfo.set(jaxbObject, value, dclClass);
            } catch (Throwable t) {

                if (log.isDebugEnabled()) {
                    log.debug("An exception " + t.getClass() +
                            "occurred while trying to call set() on  " + propInfo);
                    log.debug("The corresponding xml child name is: " + childName);
                    String name = (value == null) ? "<null>" : value.getClass().getName();
                    log.debug("The corresponding value object is: " + name);
                }
                throw new JAXBWrapperException(t);
            }
        }

        // Return the jaxb object 
        return jaxbObject;
    }

    /** 
     * This code checks the pdMap to make sure that a PropertyDescriptor
     * exists for each child name.  This code should only be called when
     * debug is enabled or an exception occurs.  (It is too slow for the mainline path) 
     * @param jaxbClass
     * @param xmlChildNames
     * @param pdMap
     * @throws JAXBWrapperException
     */
    private void checkPropertyDescriptorMap(Class jaxbClass,
                                            List<String> xmlChildNames,
                                            Map<String, PropertyDescriptorPlus> pdMap)
    throws JAXBWrapperException {
        for (int i = 0; i < xmlChildNames.size(); i++) {
            String xmlChildName = xmlChildNames.get(i);
            PropertyDescriptorPlus pd = pdMap.get(xmlChildName);
            if (pd == null) {
                // Each xml child name must have a matching property.  
                if (log.isDebugEnabled()) {
                    log.debug(
                    "Error occurred trying to match an xml name to a child of a jaxb object");
                    log.debug("  The JAXBClass is:" + jaxbClass.getName());
                    log.debug("  The child name that we are looking for is:" + xmlChildName);
                    log.debug("  The JAXBClass has the following child xml names:" +
                              toString(pdMap.keySet()));
                    log.debug("  Complete list of child names that we are looking for:" +
                              toString(xmlChildNames));
                }

                throw new JAXBWrapperException(
                                               Messages.getMessage("JAXBWrapperErr6", jaxbClass.getName(), xmlChildName));
            }
        }
    }


    /**
     * @param collection
     * @return list of the names in the collection
     */
    private String toString(Collection<String> collection) {
        String text = "[";
        if (collection == null) {
            return "[]";
        }
        boolean first = true;
        for (String name : collection) {
            if (first) {
                first = false;
                text += name;
            } else {
                text += "," + name;
            }
        }
        return text + "]";
    }

    public Object[] unWrap(Object jaxbObject, List<String> childNames) throws JAXBWrapperException {
        // Get the property descriptor map for this JAXBClass
        Class jaxbClass = jaxbObject.getClass();
        Map<String, PropertyDescriptorPlus>  pdMap = null;
        try {
            pdMap = XMLRootElementUtil.createPropertyDescriptorMap(jaxbClass);
        } catch (Throwable t) {
            log.debug("Error occurred to build the PropertyDescriptor map");
            log.debug("  The JAXBClass is:" + jaxbClass.getName());
            throw new JAXBWrapperException(t);
        }

        // Delegate
        return unWrap(jaxbObject, childNames, pdMap);
    }

    public Object wrap(Class jaxbClass, List<String> childNames, Map<String, Object> childObjects)
            throws JAXBWrapperException {
        // Get the property descriptor map
        Map<String, PropertyDescriptorPlus>  pdMap = null;
        try {
            pdMap = XMLRootElementUtil.createPropertyDescriptorMap(jaxbClass);
        } catch (Throwable t) {
            log.debug("Error occurred to build the PropertyDescriptor map");
            log.debug("  The JAXBClass is:" + jaxbClass.getName());
            throw new JAXBWrapperException(t);
        }
        HashMap<String, Class> declaringClass = new HashMap<String, Class>();
        // Delegate
        return wrap(jaxbClass, childNames, childObjects, declaringClass, pdMap);
    }


}
