// Path: src/main/java/no/gorman/database/DBFunctions.java
// public static Object get(Field f, Object instance) {
//     try {
//         return f.get(instance);
//     }catch (IllegalAccessException e) {
//         throw new RuntimeException(e);
//     }
// }
// 
// Path: src/main/java/no/gorman/database/DBFunctions.java
// public static List<Field> getMappedFields(Class<?> clazz) {
//     List<Field> columnFields = asList(clazz.getDeclaredFields()).stream()
//             .filter(f -> f.isAnnotationPresent(Column.class))
//             .collect(toList());
//     columnFields.forEach(f->f.setAccessible(true));
// 
//     if (clazz.getSuperclass() != null) {
//         columnFields.addAll(getMappedFields(clazz.getSuperclass()));
//     }
//     return columnFields;
// }
// 
// Path: src/main/java/no/gorman/database/DBFunctions.java
// public static <T> Field getPrimaryKeyField(T obj) {
//     return getMappedFields(obj.getClass()).stream().filter(f-> getColumn(f).getType() == PrimaryKey).findFirst().orElseThrow(() -> new IllegalArgumentException(obj.getClass().getName() + " has no primary key defined"));
// }


import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static no.gorman.database.DBFunctions.get;
import static no.gorman.database.DBFunctions.getMappedFields;
import static no.gorman.database.DBFunctions.getPrimaryKeyField;
     * plus the foreign references referring to this entry. For example
     * the Schedule table's schedule_child_id=42
     *
     */
    public static <T> Collection<RowIdentifier> findRowsToSpyOn(T suspect) {
        List<RowIdentifier> keys = new ArrayList<>();
        Field pkField = getPrimaryKeyField(suspect);
        Object suspectId = get(pkField, suspect);
        DatabaseColumns pkColumn = pkField.getAnnotation(Column.class).column();
        keys.add(new RowIdentifier(pkColumn, suspectId));
        DatabaseColumns.incomingReferenceColumns(pkColumn.getTable()).forEach(col -> keys.add(new RowIdentifier(col, suspectId)));
        return keys;
    }

    /**
     * Example:
     * findWhoMightBeInterested(<child with child_id=23 and child_daycare_id=2>) would return the
     * primary key row of the child table: child_id=23, and would also
     * return rows this child "belongs to". Like the day care center with daycare_id=2.
     * It won't return any other fields than what the type <T> actually has defined.
     * If T is a child-class, but does not specify any link to the daycare center,
     * those listening for updates on the daycare center won't be notified.
     * Could fix this by querying the database from here, will maybe have to do this later,
     * but haven't had the need to so far.
     */
    public static <T> Collection<RowIdentifier> findWhoMightBeInterested(T suspect) {
        List<RowIdentifier> keys = new ArrayList<>();
        Field pkField = getPrimaryKeyField(suspect);
        Object suspectId = get(pkField, suspect);
        keys.add(new RowIdentifier(pkField.getAnnotation(Column.class).column(), suspectId));
// Path: src/main/java/no/gorman/database/DBFunctions.java
// public static Object get(Field f, Object instance) {
//     try {
//         return f.get(instance);
//     }catch (IllegalAccessException e) {
//         throw new RuntimeException(e);
//     }
// }
// 
// Path: src/main/java/no/gorman/database/DBFunctions.java
// public static List<Field> getMappedFields(Class<?> clazz) {
//     List<Field> columnFields = asList(clazz.getDeclaredFields()).stream()
//             .filter(f -> f.isAnnotationPresent(Column.class))
//             .collect(toList());
//     columnFields.forEach(f->f.setAccessible(true));
// 
//     if (clazz.getSuperclass() != null) {
//         columnFields.addAll(getMappedFields(clazz.getSuperclass()));
//     }
//     return columnFields;
// }
// 
// Path: src/main/java/no/gorman/database/DBFunctions.java
// public static <T> Field getPrimaryKeyField(T obj) {
//     return getMappedFields(obj.getClass()).stream().filter(f-> getColumn(f).getType() == PrimaryKey).findFirst().orElseThrow(() -> new IllegalArgumentException(obj.getClass().getName() + " has no primary key defined"));
// }


// Path: src/main/java/no/gorman/database/BigBrother.java
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static no.gorman.database.DBFunctions.get;
import static no.gorman.database.DBFunctions.getMappedFields;
import static no.gorman.database.DBFunctions.getPrimaryKeyField;

     * plus the foreign references referring to this entry. For example
     * the Schedule table's schedule_child_id=42
     *
     */
    public static <T> Collection<RowIdentifier> findRowsToSpyOn(T suspect) {
        List<RowIdentifier> keys = new ArrayList<>();
        Field pkField = getPrimaryKeyField(suspect);
        Object suspectId = get(pkField, suspect);
        DatabaseColumns pkColumn = pkField.getAnnotation(Column.class).column();
        keys.add(new RowIdentifier(pkColumn, suspectId));
        DatabaseColumns.incomingReferenceColumns(pkColumn.getTable()).forEach(col -> keys.add(new RowIdentifier(col, suspectId)));
        return keys;
    }

    /**
     * Example:
     * findWhoMightBeInterested(<child with child_id=23 and child_daycare_id=2>) would return the
     * primary key row of the child table: child_id=23, and would also
     * return rows this child "belongs to". Like the day care center with daycare_id=2.
     * It won't return any other fields than what the type <T> actually has defined.
     * If T is a child-class, but does not specify any link to the daycare center,
     * those listening for updates on the daycare center won't be notified.
     * Could fix this by querying the database from here, will maybe have to do this later,
     * but haven't had the need to so far.
     */
    public static <T> Collection<RowIdentifier> findWhoMightBeInterested(T suspect) {
        List<RowIdentifier> keys = new ArrayList<>();
        Field pkField = getPrimaryKeyField(suspect);
        Object suspectId = get(pkField, suspect);
        keys.add(new RowIdentifier(pkField.getAnnotation(Column.class).column(), suspectId));
        for (Field f : getMappedFields(suspect.getClass())){