/* * Copyright 2015, Simon Matić Langford * * 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.betfair.cougar.test.socket.tester.common; import com.betfair.cougar.api.ExecutionContext; import com.betfair.cougar.api.RequestUUID; import com.betfair.cougar.api.geolocation.GeoLocationDetails; import com.betfair.cougar.api.security.Identity; import com.betfair.cougar.api.security.IdentityChain; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * */ public class Conversion { public static Object convert(Object o, Class src, Class target) { if (!canTransferBetween(src,target)) { throw new RuntimeException("Can't convert between "+src+" and "+target); } if (o instanceof ExecutionContext) { ExecutionContextTO ret = new ExecutionContextTO(); transfer(ExecutionContext.class, o,ret); return ret; } if (o instanceof GeoLocationDetails) { GeoLocationDetailsTO ret = new GeoLocationDetailsTO(); transfer(GeoLocationDetails.class,o,ret); return ret; } if (src.getName().startsWith("java.lang")) { return o; } if (src.isPrimitive()) { return o; } if (src.getName().startsWith("java.util.List")) { return new ArrayList((List)o); } if (src.getName().startsWith("java.util.Date")) { return o; } if (src == IdentityChain.class) { List<IdentityTO> ret = new ArrayList<>(); IdentityChain chain = (IdentityChain) o; if (chain.getIdentities() != null) { for (Identity id : chain.getIdentities()) { IdentityTO newId = new IdentityTO(); newId.setPrincipal(id.getPrincipal().getName()); newId.setCredential((String) id.getCredential().getValue()); ret.add(newId); } } return ret; } if (src == RequestUUID.class && target == String.class) { return o.toString(); } throw new IllegalStateException("Can't convert between "+src+" and "+target); } private static void transfer(Class srcClass, Object src, Object target) { Map<String, Method> targetSettersByPropertyName = new HashMap<>(); for (Method m : target.getClass().getDeclaredMethods()) { if (m.getName().startsWith("set")) { targetSettersByPropertyName.put(m.getName().substring(3).toLowerCase(), m); } } for (Method m : srcClass.getDeclaredMethods()) { // System.out.println("Processing "+m); String candidateMethod = m.getName().toLowerCase(); if (tryProcess(targetSettersByPropertyName, candidateMethod, m, src, target)) { continue; } if (candidateMethod.startsWith("get")) { candidateMethod = candidateMethod.substring(3); if (tryProcess(targetSettersByPropertyName, candidateMethod, m, src, target)) { continue; } } if (candidateMethod.startsWith("is") && (m.getReturnType() == Boolean.class || m.getReturnType() == boolean.class)) { candidateMethod = candidateMethod.substring(2); if (tryProcess(targetSettersByPropertyName, candidateMethod, m, src, target)) { continue; } } throw new RuntimeException("Couldn't find match for source method "+m+" on "+target.getClass()); } } private static boolean tryProcess(Map<String, Method> targetSettersByPropertyName, String candidateMethod, Method sourceMethod, Object sourceObject, Object targetObject) { if (targetSettersByPropertyName.containsKey(candidateMethod)) { Method m = targetSettersByPropertyName.remove(candidateMethod); Class sourceType = sourceMethod.getReturnType(); Class targetType = m.getParameterTypes()[0]; if (canTransferBetween(targetType,sourceType)) { try { m.invoke(targetObject, convert(sourceMethod.invoke(sourceObject), sourceType, targetType)); return true; } catch (Exception e) { e.printStackTrace(); return false; } } } return false; } private static boolean canTransferBetween(Class a, Class b) { return canTransferBetween(a,b,true); } private static boolean canTransferBetween(Class a, Class b, boolean flipIfNoMatch) { if (a == GeoLocationDetailsTO.class && b == GeoLocationDetails.class) { return true; } if (a == ExecutionContextTO.class && b == ExecutionContext.class) { return true; } if (a == List.class && b == IdentityChain.class) { return true; } if (a == String.class && b == RequestUUID.class) { return true; } if (flipIfNoMatch) { return canTransferBetween(b,a,false); } return a == b; } }