app/src/main/java/db/juhaku/juhakudb/core/android/EntityConverter.java
/**
     * Alter entity's field with fetch join values from root. If root contains fetch joins they are
     * converted and placed to entity's corresponding field.
     *
     * @param cursor {@link Cursor}'s row to be converted to entity and placed to entity's field.
     * @param root {@link Root} of joins that are going to be altered to the entity.
     * @param entity {@link Object} that is being altered with conversion objects.
     *
     * @since 1.2.0
     *
     * @hide
     */
Alter entity's field with fetch join values from root. If root contains fetch joins they are
converted and placed to entity's corresponding field.

@param cursor  Cursor's row to be converted to entity and placed to entity's field.
@param root  Root of joins that are going to be altered to the entity.
@param entity  Object that is being altered with conversion objects.



@hide
Alter entity ' s field with fetch join values from root . If root contains fetch joins they are converted and placed to entity ' s corresponding field . @param cursor Cursor ' s row to be converted to entity and placed to entity ' s field . @param root Root of joins that are going to be altered to the entity . @param entity Object that is being altered with conversion objects . @hide
private <T> void alterEntityConvertJoins(Cursor cursor, Root<?> root, T entity) {
        for (Root r : root.getJoins()) {
            Join join = (Join) r;
            if (join.isFetch()) {
                T fieldEntity = convertCursorToEntity(cursor, join.getModel());
                Field targetField = ReflectionUtils.findField(root.getModel(), join.getTarget());
                Object id = ReflectionUtils.getIdFieldValue(fieldEntity);
                /*
                 * Determine whether field is a collection or object and act accordingly.
                 * Update the collection fields and replace other values.
                 *
                 * This is because collections must be gradually altered since each row from database
                 * result has its own value to collection.
                 */
                if (Collection.class.isAssignableFrom(targetField.getType())) {
                    Collection value = ReflectionUtils.getFieldValue(entity, targetField);
                    if (value == null) {
                        if (List.class.isAssignableFrom(targetField.getType())) {
                            value = instantiateByDefaultConstructor(ArrayList.class);
                        } else if (Set.class.isAssignableFrom(targetField.getType())) {
                            value= instantiateByDefaultConstructor(TreeSet.class);
                        } else {
                            value = instantiateByDefaultConstructor(targetField.getType());
                        }
                        ReflectionUtils.setFieldValue(targetField, entity, value);
                    }
                    /*
                     * Do found checking only for entities, other typed values does not have joins
                     * forward so they can be safely added to the collection.
                     */
                    if (fieldEntity.getClass().isAnnotationPresent(Entity.class)) {
                        /*
                         * If id of the entity is not null add the entity otherwise skip it as it is
                         * an empty row from database caused by fetch join.
                         */
                        if (findEntityById(id, value) == null && id != null) {
                            value.add(fieldEntity);
                        }
                    } else {
                        value.add(fieldEntity);
                    }
                } else {
                    /*
                     * If id of the entity is not null add the entity otherwise skip it as it is
                     * an empty row from database caused by fetch join.
                     */
                    if (id != null) {
                        ReflectionUtils.setFieldValue(targetField, entity, fieldEntity);
                    }
                }
                if (!join.getJoins().isEmpty()) {
                    Object parentEntity = ReflectionUtils.getFieldValue(join.getTarget(), entity);
                    if (Collection.class.isAssignableFrom(targetField.getType())) {
                        Object parent = findEntityById(ReflectionUtils.getIdFieldValue(fieldEntity), (Collection<Object>) parentEntity);
                        alterEntityConvertJoins(cursor, join, parent == null ? fieldEntity : parent);
                    } else {
                        alterEntityConvertJoins(cursor, join, parentEntity == null ? fieldEntity : parentEntity);
                    }
                }
            }
        }
    }
private < T > void alterEntityConvertJoins ( Cursor cursor , Root < ? > root , T entity ) { for ( Root r : root . getJoins ( ) ) { Join join = ( Join ) r ; if ( join . isFetch ( ) ) { T fieldEntity = convertCursorToEntity ( cursor , join . getModel ( ) ) ; Field targetField = ReflectionUtils . findField ( root . getModel ( ) , join . getTarget ( ) ) ; Object id = ReflectionUtils . getIdFieldValue ( fieldEntity ) ; /*
                 * Determine whether field is a collection or object and act accordingly.
                 * Update the collection fields and replace other values.
                 *
                 * This is because collections must be gradually altered since each row from database
                 * result has its own value to collection.
                 */ if ( Collection . class . isAssignableFrom ( targetField . getType ( ) ) ) { Collection value = ReflectionUtils . getFieldValue ( entity , targetField ) ; if ( value == null ) { if ( List . class . isAssignableFrom ( targetField . getType ( ) ) ) { value = instantiateByDefaultConstructor ( ArrayList . class ) ; } else if ( Set . class . isAssignableFrom ( targetField . getType ( ) ) ) { value = instantiateByDefaultConstructor ( TreeSet . class ) ; } else { value = instantiateByDefaultConstructor ( targetField . getType ( ) ) ; } ReflectionUtils . setFieldValue ( targetField , entity , value ) ; } /*
                     * Do found checking only for entities, other typed values does not have joins
                     * forward so they can be safely added to the collection.
                     */ if ( fieldEntity . getClass ( ) . isAnnotationPresent ( Entity . class ) ) { /*
                         * If id of the entity is not null add the entity otherwise skip it as it is
                         * an empty row from database caused by fetch join.
                         */ if ( findEntityById ( id , value ) == null && id != null ) { value . add ( fieldEntity ) ; } } else { value . add ( fieldEntity ) ; } } else { /*
                     * If id of the entity is not null add the entity otherwise skip it as it is
                     * an empty row from database caused by fetch join.
                     */ if ( id != null ) { ReflectionUtils . setFieldValue ( targetField , entity , fieldEntity ) ; } } if ( ! join . getJoins ( ) . isEmpty ( ) ) { Object parentEntity = ReflectionUtils . getFieldValue ( join . getTarget ( ) , entity ) ; if ( Collection . class . isAssignableFrom ( targetField . getType ( ) ) ) { Object parent = findEntityById ( ReflectionUtils . getIdFieldValue ( fieldEntity ) , ( Collection < Object > ) parentEntity ) ; alterEntityConvertJoins ( cursor , join , parent == null ? fieldEntity : parent ) ; } else { alterEntityConvertJoins ( cursor , join , parentEntity == null ? fieldEntity : parentEntity ) ; } } } } }
Alter entity's field with fetch join values from root.
Alter entity ' s field with fetch join values from root .
// convert field entity and add it to the object. // Take the id of the converted entity //TODO support maps? // If converted entity is not found from the collection add it. // If join has joins to even further convert them as well. // Find the actual parent from the collection.