package org.ovirt.engine.core.bll.scheduling.policyunits;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.ovirt.engine.core.common.businessentities.BusinessEntity;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.compat.Guid;
public class AbstractPolicyUnitTest {
String fieldToSetterName(String name) {
return "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
}
public static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss", Locale.ENGLISH);
@SuppressWarnings("unchecked")
Object convert(Class<?> type, String value, Map<Guid, BusinessEntity<Guid>> cache) throws ParseException {
/* Direct assignment possible */
if (type.equals(String.class)) {
return value;
}
/* Primitive values */
if (type.equals(int.class)) {
return Integer.valueOf(value);
} else if (type.equals(float.class)) {
return Float.valueOf(value);
} else if (type.equals(double.class)) {
return Double.valueOf(value);
} else if (type.equals(boolean.class)) {
return Boolean.valueOf(value);
} else if (type.equals(long.class)) {
return Long.valueOf(value);
} else if (type.equals(Date.class)) {
return TIME_FORMAT.parse(value);
}
/* Relationships between entities */
if (BusinessEntity.class.isAssignableFrom(type)
&& cache.containsKey(new Guid(value))) {
return cache.get(new Guid(value));
}
/* This supports string, integers, floats */
try {
Method converter = type.getMethod("valueOf", String.class);
if (converter != null) {
return converter.invoke(type, value);
}
} catch (NoSuchMethodException|InvocationTargetException|IllegalAccessException ex) {
// ignore and try the next method
}
/* Fallback tries to use a constructor(String) to prepare the value,
* this is needed for Guid
* */
try {
Constructor<?> constructor = type.getConstructor(String.class);
if (constructor == null) {
return null;
}
return constructor.newInstance(value);
} catch (NoSuchMethodException|InstantiationException|IllegalAccessException|InvocationTargetException ex) {
// ignore and try the next method
}
return null;
}
<E> E setField(E entity, String fieldName, String value, Map<Guid, BusinessEntity<Guid>> cache)
throws NoSuchFieldException, IllegalAccessException, InstantiationException, InvocationTargetException,
ParseException {
String[] components = fieldName.split("\\.");
/* The last intermediate object */
Object ptr = entity;
/* Make sure all intermediate objects exist */
for (int i=0; i<components.length - 1; i++) {
Field f = ptr.getClass().getField(components[i]);
if (f.get(ptr) == null) {
Class<?> fieldType = f.getType();
Object tmp = fieldType.newInstance();
f.set(ptr, tmp);
ptr = tmp;
} else {
ptr = f.get(ptr);
}
}
/* Set the value */
Class<?> type;
/* Look up a setter method */
String setterName = fieldToSetterName(components[components.length - 1]);
for (Method m: ptr.getClass().getMethods()) {
if (!m.getName().equals(setterName)) {
continue;
}
if (m.getParameterTypes().length != 1) {
continue;
}
/* Try converting the value to the requested type */
Object candidateValue = convert(m.getParameterTypes()[0], value, cache);
if (candidateValue == null) {
continue;
}
m.invoke(ptr, candidateValue);
return entity;
}
/* Use field introspection as a backup */
Field f = ptr.getClass().getField(components[components.length - 1]);
type = f.getType();
Object realValue = convert(type, value, cache);
if (realValue == null) {
throw new NoSuchFieldException();
}
f.set(ptr, realValue);
return entity;
}
<T extends BusinessEntity<Guid>> Map<Guid, T> loadEntities(Class<T> type, String fixtureName, Map<Guid, BusinessEntity<Guid>> cache)
throws NoSuchFieldException, InvocationTargetException, NoSuchMethodException, InstantiationException,
IllegalAccessException, IOException, ParseException {
Map<Guid, T> entities = new HashMap<>();
InputStream inputStream = getClass().getResourceAsStream("/scheduling/" + fixtureName);
// Make sure the reader is closed
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
/* First line contains the field names */
String header = bufferedReader.readLine();
String[] fields = header.split(",");
String line = bufferedReader.readLine();
while (line != null) {
T entity = type.newInstance();
String[] values = line.split(",");
for (int i = 0; i < Math.min(values.length, fields.length); i++) {
String value = values[i].trim();
if (value.isEmpty()) {
continue;
}
setField(entity, fields[i], value, cache);
}
entities.put(entity.getId(), entity);
cache.put(entity.getId(), entity);
line = bufferedReader.readLine();
}
return entities;
}
}
public Map<Guid, VDS> loadHosts(String fixtureName, Map<Guid, BusinessEntity<Guid>> cache)
throws NoSuchMethodException, InstantiationException, IOException, IllegalAccessException,
InvocationTargetException, NoSuchFieldException, ParseException {
return loadEntities(VDS.class, fixtureName, cache);
}
public Map<Guid, VM> loadVMs(String fixtureName, Map<Guid, BusinessEntity<Guid>> cache)
throws NoSuchMethodException, InstantiationException, IOException, IllegalAccessException,
InvocationTargetException, NoSuchFieldException, ParseException {
return loadEntities(VM.class, fixtureName, cache);
}
public Map<Guid, BusinessEntity<Guid>> newCache() {
return new HashMap<>();
}
}