package fr.inria.diversify.logger.logger; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; /** * User: Simon * Date: 16/06/15 * Time: 11:09 */ public class ClassObserver { protected Class aClass; protected Field[] fields; protected Method[] getters; protected String[] previousObservation; private static Map<Class, String> classToId; public ClassObserver(Class aClass) { this.aClass = aClass; } protected void observe(Object object, PrintWriter writer) throws IOException, InterruptedException { if(fields == null) { intGettersAndFields(writer); } String[] results = new String[getters.length + fields.length]; int i = 0; for(; i < getters.length ; i++) { try { results[i] = formatVar(getters[i].invoke(object)); } catch (Exception e) { results[i] = "null"; } } int j= 0; for(; i < results.length ; i++) { try { results[i] = formatVar(fields[j].get(object)); } catch (Exception e) { results[i] = "null"; } j++; } StringBuilder sameValue = new StringBuilder(); List<String> result = new ArrayList<String>(); boolean sameValues = true; if(previousObservation != null) { for (i = 0; i < results.length; i++) { if (previousObservation[i].equals(results[i])) { sameValue.append("0"); } else { sameValues = false; sameValue.append("1"); result.add(results[i]); previousObservation[i] = results[i]; } } } else { sameValues = false; previousObservation = new String[results.length]; for (i = 0; i < results.length; i++) { sameValue.append("1"); result.add(results[i]); previousObservation[i] = results[i]; } } String classId = getClassId(writer); if(sameValues) { writer.write(classId); } else { writer.write( classId + KeyWord.simpleSeparator + sameValue.toString() + KeyWord.separator + join(result, KeyWord.separator)); } } protected String getClassId(PrintWriter writer) throws IOException, InterruptedException { String className; if(aClass == null) { className = "NullClass"; } else { className = aClass.getName(); } int count = classToId.size() + 1; if(!classToId.containsKey(aClass)) { classToId.put(aClass, count + ""); writer.append(KeyWord.endLine + KeyWord.classKeyWord + KeyWord.simpleSeparator + className + KeyWord.simpleSeparator + count); } return classToId.get(aClass); } protected String join(List<String> list, String conjunction) { StringBuilder sb = new StringBuilder(); boolean first = true; for (String item : list) { if (first) first = false; else sb.append(conjunction); sb.append(item); } return sb.toString(); } protected String formatVar(Object object) { if (object == null) { return "null"; } String string; if (object.getClass().isArray()) { string = Arrays.toString((Object[]) object); } else { string = object + ""; } if(string.length() > 1000) string = string.length() + ""; return string; } protected void intGettersAndFields(PrintWriter writer) throws IOException, InterruptedException { if(aClass == null) { getters = new Method[0]; fields = new Field[0]; } else { getters = findGetters(); fields = findFields(); } String classId = getClassId(writer); writer.append(KeyWord.endLine + KeyWord.getterKeyWord + KeyWord.simpleSeparator + classId); for(Method method : getters) { writer.append(KeyWord.simpleSeparator + method.getName()); } for(Field field : fields) { writer.append(KeyWord.simpleSeparator + field.getName()); } } protected Field[] findFields() { List<Field> fields = new ArrayList<Field>(); for(Field field : aClass.getFields()) { if(Modifier.isPublic(field.getModifiers())) { fields.add(field); } } Field[] ret = new Field[fields.size()]; for(int i = 0; i < fields.size(); i++) { ret[i] = fields.get(i); } return ret; } protected Method[] findGetters(){ List<Method> getters = new ArrayList<Method>(); for(Method method : aClass.getMethods()){ if((isGetter(method) || isIs(method)) && !methodDefinedInObject(method)) { getters.add(method); } } try { Method toStringMethod = aClass.getMethod("toString"); if(!methodDefinedInObject(toStringMethod)) { getters.add(toStringMethod); } } catch (NoSuchMethodException e) {} Method[] ret = new Method[getters.size()]; for(int i = 0; i< ret.length; i++ ) { ret[i] = getters.get(i); } return ret; } protected boolean isIs(Method method) { return method.getName().startsWith("is") && method.getParameterTypes().length == 0; } protected boolean isGetter(Method method) { return method.getName().startsWith("get") && method.getParameterTypes().length == 0; } protected boolean methodDefinedInObject(Method method) { for(Method objectMethod : Object.class.getMethods()) { if(objectMethod.equals(method)) { return true; } } return false; } }