Java tutorial
/** * 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; } }