/* * Copyright 2014, The Sporting Exchange Limited * * 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.util; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import com.betfair.cougar.api.RequestContext; import com.betfair.cougar.api.Result; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MockUtils { final static Logger LOGGER = LoggerFactory.getLogger(MockUtils.class); public static <T> T generateMockResponse(Class<T> responseClass, RequestContext ctx, Object... params ) { try { Generator generator = new Generator(); // T responseObject = responseClass.newInstance(); T responseObject = generateObject(responseClass, generator); return responseObject; } catch (Exception e) { throw new RuntimeException("Failed to generate response object: "+e.getMessage(), e); } } @SuppressWarnings("unchecked") private static <T> T generateObject(Class<T> clazz, Generator generator) throws Exception { if (Result.class.isAssignableFrom(clazz)) { T object = clazz.newInstance(); Method[] methods = clazz.getMethods(); for (Method m: methods) { if (m.getName().startsWith("set") && m.getParameterTypes().length == 1) { populateMethod(m, object, generator); } } return object; } else { return (T)getValueIfbasicType(clazz, generator); } } private static void populateMethod(Method method, Object object, Generator generator) throws Exception { Class<?> fieldType = method.getParameterTypes()[0]; Object result = getValueIfbasicType(fieldType, generator); if (result != null) { method.invoke(object, result); } else if ((List.class.isAssignableFrom(fieldType)) || (Set.class.isAssignableFrom(fieldType))) { Class<?> fieldArgClass; Type genericFieldType = method.getGenericParameterTypes()[0]; if(genericFieldType instanceof ParameterizedType){ ParameterizedType aType = (ParameterizedType) genericFieldType; Type[] fieldArgTypes = aType.getActualTypeArguments(); fieldArgClass = (Class<?>) fieldArgTypes[0]; } else { throw new RuntimeException("parametised list not mockable - "+genericFieldType.getClass()); } Collection<Object> coll; if (Set.class.isAssignableFrom(fieldType)) { coll = new HashSet<Object>(); } else { coll = new ArrayList<Object>(); } int length = (generator.getNumber() % 5) + 2; for (int i = 0; i < length; ++i) { Object listMember = generateObject(fieldArgClass, generator); coll.add(listMember); } method.invoke(object, coll); } else if (Map.class.isAssignableFrom(fieldType)) { Class<?> fieldArgKeyClass; Class<?> fieldArgValueClass; Type genericFieldType = method.getGenericParameterTypes()[0]; if(genericFieldType instanceof ParameterizedType){ ParameterizedType aType = (ParameterizedType) genericFieldType; Type[] fieldArgTypes = aType.getActualTypeArguments(); fieldArgKeyClass = (Class<?>) fieldArgTypes[0]; fieldArgValueClass = (Class<?>) fieldArgTypes[1]; } else { throw new RuntimeException("parametised list not mockable - "+genericFieldType.getClass()); } Map<Object, Object> map = new HashMap<Object, Object>(); int length = (generator.getNumber() % 5) + 2; for (int i = 0; i < length; ++i) { Object key = generateObject(fieldArgKeyClass, generator); Object value = generateObject(fieldArgValueClass, generator); map.put(key, value); } method.invoke(object, map); } else if (Result.class.isAssignableFrom(fieldType)) { result = generateObject(fieldType, generator); method.invoke(object, result); } else { LOGGER.info("Could not mock data of type {} into method {}", fieldType, method.getName()); } } private static Object getValueIfbasicType(Class<?> fieldType, Generator generator) { if (fieldType == Byte.class) { return (byte)generator.getNumber(); } else if (fieldType == Short.class) { return (short)generator.getNumber(); } else if (fieldType == Integer.class) { return generator.getNumber(); } else if (fieldType == Long.class) { return (long)generator.getNumber(); } else if (fieldType == Float.class) { return (float)generator.getNumber(); } else if (fieldType == Double.class) { return (double)generator.getNumber(); } else if (fieldType == Boolean.class) { return generator.getBoolean(); } else if (fieldType == Character.class) { return (char)generator.getNumber(); } else if (fieldType == String.class) { return generator.getString(); } else if (fieldType == Date.class) { return generator.getDate(); } else if (fieldType.isEnum()) { Object[] constants = fieldType.getEnumConstants(); return constants[generator.getNumber()%constants.length]; } return null; } private static class Generator { private int count = 1; String getString() { return "String-"+(count++); } int getNumber() { return count++; } boolean getBoolean() { return (count++)%2==0?true:false; } Date getDate() { return new Date(count++); } } }