com.qualogy.qafe.business.integration.adapter.MappingAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.qualogy.qafe.business.integration.adapter.MappingAdapter.java

Source

/**
 * Copyright 2008-2015 Qualogy Solutions B.V.
 *
 * Licensed 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 com.qualogy.qafe.business.integration.adapter;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang.StringUtils;

import com.qualogy.qafe.bind.commons.type.AdapterAttribute;
import com.qualogy.qafe.bind.commons.type.AdapterMapping;
import com.qualogy.qafe.bind.commons.type.AttributeMapping;
import com.qualogy.qafe.bind.commons.type.In;
import com.qualogy.qafe.business.integration.builder.PredefinedClassTypeConverter;
import com.qualogy.qafe.core.datastore.DataIdentifier;
import com.qualogy.qafe.core.datastore.DataMap;
import com.qualogy.qafe.core.datastore.DataStore;

/**
 * Adapter for adapting an object (map or servicedefined outcome) to a complex type, defined within the type-definition tag.
 * 
 * @author mvanderwurff
 */
public class MappingAdapter {

    private static final Logger logger = Logger.getLogger(MappingAdapter.class.getName());

    //TODO: check if correct method is used
    //TODO: implement adapt all
    //TODO: deal with conversion inside the adapters ==> string to int
    /**
     * method knows toBeMapped is not an instance of any type of Collection or is an array!
     * @param toBeMapped
     * @param mapping
     * @param result
     * @return
     */
    protected static Object adaptFromService(Object toBeMapped, AdapterMapping mapping) {
        Object result = null;
        //TODO: check 3 nested parents...since object is null every time
        //its cheaper to convert all than doing a nested get on each and every attribute of the mapping
        toBeMapped = ObjectMapConverter.convert(toBeMapped);

        if (mapping.hasParent()) {
            result = adaptFromService(toBeMapped, mapping.getParent());
        }

        List<AdapterAttribute> attributes = mapping.getAdapterAttributes();
        if (attributes != null) {
            if (result == null) {
                //            result = new CaseInsensitiveMap();
                result = new DataMap();
            }

            for (Iterator<AdapterAttribute> iter = attributes.iterator(); iter.hasNext();) {
                AdapterAttribute attribute = (AdapterAttribute) iter.next();
                Object value = null;
                if (attribute instanceof AttributeMapping) {//simple attribute or complex attribute with adapter
                    AttributeMapping attrmapping = (AttributeMapping) attribute;
                    if (attrmapping.getAdapter() != null) {//attribute has an adapter
                        value = adaptFromService(((Map) toBeMapped).remove(attrmapping.getName()),
                                attrmapping.getAdapter());
                    } else {//simple attribute
                        value = ((Map) toBeMapped).remove(attrmapping.getName());//TODO:simple conversion
                    }
                } else if (attribute instanceof AdapterMapping) {//internal adapter
                    AdapterMapping adaptermapping = (AdapterMapping) attribute;
                    value = adaptFromService(toBeMapped, adaptermapping);
                }
                ((Map) result).put(attribute.getName(), value);
            }
        }
        if (mapping.adaptAll() && ((result == null && toBeMapped != null && !((Map) toBeMapped).isEmpty())
                || result instanceof Map)) { //adaptall left (removed adapted ones)
            if (result == null) {
                //            result = new CaseInsensitiveMap();
                result = new DataMap();
            }
            ((Map) result).putAll((Map) toBeMapped);
        }

        return result;
    }

    /**
     * Adapts data in the datastore for key name from the in parameter to a
     * value form specified in the in's parameter adaptermapping. 
     * @param id
     * @param in
     * @param jarFileLocation
     * @return
     */
    protected static Object adaptToService(ClassLoader classLoader, DataIdentifier id, In in) {
        return adaptToService(id, in, in.getAdapter(), null, classLoader);
    }

    private static Object createServiceObj(String className, ClassLoader classLoader) {
        Object result = null;
        try {
            if (className == null)
                throw new UnableToAdaptException("Adapter states null outputclass");

            Class<?> clazz = classLoader.loadClass(className);

            Constructor<?> c = clazz.getConstructor(new Class[0]);
            c.setAccessible(true);
            result = c.newInstance(new Object[0]);
        } catch (InstantiationException e) {
            throw new UnableToAdaptException(
                    "Cannot instantiate [" + className + "], hint: define a default constructor", e);
        } catch (IllegalAccessException e) {
            throw new UnableToAdaptException(e);
        } catch (Exception e) {
            throw new UnableToAdaptException(e);
        }
        return result;
    }

    private static Object adaptToService(DataIdentifier id, In in, AdapterMapping mapping, Object result,
            ClassLoader externalClassLoader) {
        if (result == null)
            result = createServiceObj(mapping.getOutputClass(), externalClassLoader);

        if (mapping.hasParent()) {
            result = adaptToService(id, in, mapping.getParent(), result, externalClassLoader);
        }

        List<AdapterAttribute> attributes = mapping.getAdapterAttributes();

        if (attributes != null) {
            for (Iterator<AdapterAttribute> iter = attributes.iterator(); iter.hasNext();) {
                AdapterAttribute attribute = (AdapterAttribute) iter.next();
                Object value = null;

                String ref = ((in.getRef() == null || StringUtils.isBlank(in.getRef().stringValueOf())) ? ""
                        : (in.getRef().toString() + ".")) + attribute.getName();
                if (attribute instanceof AttributeMapping) {//simple attribute or complex attribute with adapter
                    AttributeMapping attrmapping = (AttributeMapping) attribute;
                    if (attrmapping.getAdapter() != null) {//attribute has an adapter
                        value = adaptToService(id, in, attrmapping.getAdapter(), null, externalClassLoader);
                    } else {//simple attribute
                        value = DataStore.findValue(id, ref);//TODO:simple conversion
                    }
                } else if (attribute instanceof AdapterMapping) {//internal adapter
                    AdapterMapping adaptermapping = (AdapterMapping) attribute;
                    value = adaptToService(id, in, adaptermapping, null, externalClassLoader);
                }

                result = adaptToJavaObject(mapping.getId(), attribute.getName(), result, value,
                        externalClassLoader);

            }
        }
        return result;
    }

    private static Object adaptToJavaObject(String mappingId, String attributeName, Object result,
            Object valueToAdapt, ClassLoader classLoader) {
        try {
            if (valueToAdapt != null) {
                Class resultClazz = classLoader.loadClass(result.getClass().getName());

                Field field = resultClazz.getDeclaredField(attributeName);
                field.setAccessible(true);
                String fieldName = field.getType().getName();
                String valueName = valueToAdapt.getClass().getName();
                logger.info(field.getType().getName());

                if (!fieldName.equals(valueName)) {
                    if (PredefinedClassTypeConverter.isPredefined(field.getType()))
                        valueToAdapt = PredefinedAdapterFactory.create(field.getType()).convert(valueToAdapt);
                    else
                        throw new IllegalArgumentException("Object passed [" + valueToAdapt
                                + "] cannot be converted to type wanted[" + field.getType() + "] for field["
                                + field.getName() + "] in adapter[" + mappingId + "]");
                } else {
                    if (!PredefinedClassTypeConverter.isPredefined(field.getType())) {
                        Class paramClazz = classLoader.loadClass(fieldName);
                        valueToAdapt = paramClazz.cast(valueToAdapt);
                    }
                }
                field.set(result, valueToAdapt);
            }
        } catch (IllegalArgumentException e) {
            throw new UnableToAdaptException(
                    "arg [" + valueToAdapt + "] is illegal for field with name [" + attributeName + "]", e);
        } catch (SecurityException e) {
            throw new UnableToAdaptException(e);
        } catch (IllegalAccessException e) {
            throw new UnableToAdaptException(
                    "field [" + attributeName + "] does not accessible on class [" + result.getClass() + "]", e);
        } catch (NoSuchFieldException e) {
            logger.log(Level.WARNING,
                    "field [" + attributeName + "] does not exist on class [" + result.getClass() + "]", e);
        } catch (ClassNotFoundException e) {
            throw new UnableToAdaptException(
                    "field [" + attributeName + "] class not found [" + result.getClass() + "]", e);
        }
        return result;
    }
}