All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.agrest.cayenne.processor.select.ViaQueryWithParentExpResolver Maven / Gradle / Ivy

There is a newer version: 5.0.M19
Show newest version
package io.agrest.cayenne.processor.select;

import io.agrest.AgObjectId;
import io.agrest.CompoundObjectId;
import io.agrest.NestedResourceEntity;
import io.agrest.SimpleObjectId;
import io.agrest.cayenne.persister.ICayennePersister;
import io.agrest.cayenne.processor.CayenneProcessor;
import io.agrest.cayenne.processor.ICayenneQueryAssembler;
import io.agrest.meta.AgAttribute;
import io.agrest.property.NestedEntityListResultReader;
import io.agrest.property.NestedEntityResultReader;
import io.agrest.property.PropertyReader;
import io.agrest.resolver.BaseNestedDataResolver;
import io.agrest.runtime.processor.select.SelectContext;
import org.apache.cayenne.DataObject;
import org.apache.cayenne.query.SelectQuery;

import java.util.*;
import java.util.function.BiConsumer;

/**
 * A nested resolver that builds a database query using a qualifier from the parent entity. This is the default nested
 * resolver used by Cayenne backend.
 *
 * @since 3.4
 */
public class ViaQueryWithParentExpResolver extends BaseNestedDataResolver {

    protected ICayenneQueryAssembler queryAssembler;
    protected ICayennePersister persister;

    public ViaQueryWithParentExpResolver(ICayenneQueryAssembler queryAssembler, ICayennePersister persister) {
        this.queryAssembler = queryAssembler;
        this.persister = persister;
    }

    @Override
    protected void doOnParentQueryAssembled(NestedResourceEntity entity, SelectContext context) {
        CayenneProcessor.setQuery(entity, queryAssembler.createQueryWithParentQualifier(entity));
    }

    @Override
    protected Iterable doOnParentDataResolved(
            NestedResourceEntity entity,
            Iterable parentData,
            SelectContext context) {

        // no parents, no need to fetch children
        Iterator parentIt = parentData.iterator();
        if (!parentIt.hasNext()) {
            return Collections.emptyList();
        }

        SelectQuery select = CayenneProcessor.getQuery(entity);
        List result = persister.sharedContext().select(select);
        indexResultByParentId(entity, result);

        return result.isEmpty()
                ? Collections.emptyList()
                // transform Iterable to Iterable
                : () -> new SingleColumnIterator<>(result.iterator(), 0);
    }

    @Override
    public PropertyReader reader(NestedResourceEntity entity) {
        return entity.getIncoming().isToMany()
                ? new NestedEntityListResultReader(entity)
                : new NestedEntityResultReader(entity);
    }

    protected void indexResultByParentId(NestedResourceEntity entity, List result) {

        BiConsumer resultAccum = entity.getIncoming().isToMany()
                ? (i, o) -> entity.addToManyResult(i, o)
                : (i, o) -> entity.setToOneResult(i, o);

        AgAttribute[] idAttributes = entity.getParent().getAgEntity().getIds().toArray(new AgAttribute[0]);

        for (Object[] row : result) {

            // position 0 - the object itself
            // position 1..N-1 - parent id components
            T object = (T) row[0];

            if (row.length == 2) {
                resultAccum.accept(new SimpleObjectId(row[1]), object);
            } else {

                Map idParts = new LinkedHashMap<>();
                for (int i = 1; i < row.length; i++) {
                    idParts.put(idAttributes[i - 1].getName(), row[i]);
                }

                resultAccum.accept(new CompoundObjectId(idParts), object);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy