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

com.gs.fw.common.mithra.finder.SingleLinkDeepFetchStrategy Maven / Gradle / Ivy

There is a newer version: 18.1.0
Show newest version
/*
 Copyright 2016 Goldman Sachs.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */

package com.gs.fw.common.mithra.finder;

import com.gs.collections.impl.list.mutable.FastList;
import com.gs.collections.impl.map.mutable.UnifiedMap;
import com.gs.fw.common.mithra.MithraList;
import com.gs.fw.common.mithra.attribute.Attribute;
import com.gs.fw.common.mithra.finder.asofop.AsOfEqOperation;
import com.gs.fw.common.mithra.finder.orderby.OrderBy;
import com.gs.fw.common.mithra.list.DelegatingList;
import com.gs.fw.common.mithra.querycache.CachedQuery;
import com.gs.fw.common.mithra.tempobject.TupleTempContext;
import com.gs.fw.common.mithra.util.ListFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;


public abstract class SingleLinkDeepFetchStrategy extends DeepFetchStrategy
{

    static private Logger logger = LoggerFactory.getLogger(SingleLinkDeepFetchStrategy.class.getName());

    protected static final List DONT_CACHE_LIST = new FastList(0);

    protected final Mapper mapper;
    protected final Mapper parentMapper;
    protected final OrderBy orderBy;
    protected final AsOfEqOperation[] defaultAsOfOperation;
    protected final Operation defaultAsOfOperationAsSingleOp;
    private final Mapper alternateMapper;
    protected final boolean isResolvableInCache;
    protected final int chainPosition;

    protected SingleLinkDeepFetchStrategy(Mapper mapper, OrderBy orderBy, Mapper alternateMapper)
    {
        this(mapper, orderBy, alternateMapper, 0);
    }

    protected SingleLinkDeepFetchStrategy(Mapper mapper, OrderBy orderBy, Mapper alternateMapper, int chainPosition)
    {
        this.mapper = mapper;
        this.alternateMapper = alternateMapper;
        this.parentMapper = mapper.getParentMapper();
        this.orderBy = orderBy;
        this.defaultAsOfOperation = mapper.getDefaultAsOfOperation(ListFactory.EMPTY_LIST);
        this.chainPosition = chainPosition;
        Operation op = null;
        if (defaultAsOfOperation != null)
        {
            op = defaultAsOfOperation[0];
            for(int i=1;i tempOperationPool = new UnifiedMap();
        Operation cacheOp = this.mapper.getPrototypeOperation(tempOperationPool);
        cacheOp = addDefaultAsOfOp(cacheOp);
        this.isResolvableInCache = cacheOp.usesUniqueIndex() && cacheOp.zEstimateMaxReturnSize() <= 1;
    }

    public int getChainPosition()
    {
        return chainPosition;
    }

    protected SingleLinkDeepFetchStrategy(Mapper mapper, OrderBy orderBy)
    {
        this(mapper, orderBy, null);
    }

    protected Mapper getAlternateMapper()
    {
        return alternateMapper;
    }

    protected Mapper getMapper()
    {
        return this.mapper;
    }

    protected List mapOpToList(DeepFetchNode node)
    {
        Mapper mapper = this.mapper;
        if (alternateMapper != null) mapper = alternateMapper;
        Operation result = node.createMappedOperationForDeepFetch(mapper);
        result = addDefaultAsOfOp(result);
        return result.getResultObjectPortal().getFinder().findMany(result);
    }

    protected Operation addDefaultAsOfOp(Operation result)
    {
        if (defaultAsOfOperation != null)
        {
            Operation newOp = result.zInsertAsOfEqOperationOnLeft(defaultAsOfOperation);
            if (newOp == result)
            {
                result = result.and(defaultAsOfOperationAsSingleOp);
            }
            else
            {
                result = newOp;
            }
        }
        return result;
    }

    protected static Logger getLogger()
    {
        return logger;
    }

    protected MithraList findMany(Operation op)
    {
        return op.getResultObjectPortal().getFinder().findMany(op);
    }

    protected List cacheResults(HashMap opToListMap, int doNotCacheCount)
    {
        int initialCapacity = opToListMap.size() - doNotCacheCount;
        if (initialCapacity <= 0 ) initialCapacity = 1;
        FastList cachedQueries = new FastList(initialCapacity);
        Set> entries = opToListMap.entrySet();
        CachedQuery first = null;
        for (Iterator> it = entries.iterator(); it.hasNext();)
        {
            Map.Entry entry = it.next();
            Operation op = entry.getKey();
            List resultList = entry.getValue();
            if (resultList != DONT_CACHE_LIST)
            {
                CachedQuery cachedQuery = new CachedQuery(op, this.orderBy, first);
                if (this.orderBy != null && resultList.size() > 1) Collections.sort(resultList, this.orderBy);
                cachedQuery.setResult(resultList);
                cachedQuery.cacheQueryForRelationship();
                cachedQueries.add(cachedQuery);
                if (first == null) first = cachedQuery;
            }
        }
        return cachedQueries;
    }

    protected int associateResultsWithOps(List list, HashMap opToListMap, int roughSize, UnifiedMap opToParentMap)
    {
        int doNotCacheCount = 0;
        Map tempOperationPool = new UnifiedMap();
        for (int i = 0; i < list.size(); i++)
        {
            Object related = list.get(i);
            Operation op = this.mapper.getOperationFromResult(related, tempOperationPool);
            op = addDefaultAsOfOp(op);
            if (opToParentMap != null)
            {
                opToParentMap.remove(op);
            }
            List existing = opToListMap.get(op);
            if (existing == ListFactory.EMPTY_LIST)
            {
                if (this.isResolvableInCache)
                {
                    opToListMap.put(op, DONT_CACHE_LIST);
                    existing = DONT_CACHE_LIST;
                    doNotCacheCount++;
                }
                else
                {
                    existing = new FastList(roughSize);
                    opToListMap.put(op, existing);
                }
            }
            if (existing != null && existing != DONT_CACHE_LIST) // it is possible for this to happen when the database is changing under our feet.
            {
                existing.add(related);
            }
            else if (existing != DONT_CACHE_LIST)
            {
                this.getLogger().warn("Brought back more related objects than we should. " +
                        "Ignoring them for now. The database is changing as it's being queried. " +
                        "If you need better consistency, you must use a transaction.");
            }
        }
        return doNotCacheCount;
    }

    protected HashMap populateOpToListMapWithEmptyList(List immediateParentList)
    {
        HashMap opToListMap = new HashMap();
        Map tempOperationPool = new UnifiedMap();
        for (int i = 0; i < immediateParentList.size(); i++)
        {
            Object from = immediateParentList.get(i);
            Operation op = this.mapper.getOperationFromOriginal(from, tempOperationPool);
            op = addDefaultAsOfOp(op);
            opToListMap.put(op, ListFactory.EMPTY_LIST);
        }
        return opToListMap;
    }

    protected List getImmediateParentList(DeepFetchNode node)
    {
        List originalParentList = node.getImmediateParentList(this.chainPosition);
        List filteredParentList = this.mapper.filterLeftObjectList(originalParentList);
        if (filteredParentList == null) filteredParentList = originalParentList;
        return filteredParentList;
    }

    protected void associateSimplifiedResult(Operation op, MithraList list)
    {
        List resultList = new FastList(list);
        if (this.orderBy != null && resultList.size() > 1) Collections.sort(resultList, this.orderBy);
        associateSimplifiedResult(op, resultList);
    }

    protected void associateSimplifiedResult(Operation op, List resultList)
    {
        CachedQuery cachedQuery = new CachedQuery(op, this.orderBy);
        if (this.orderBy != null && resultList.size() > 1) Collections.sort(resultList, this.orderBy);
        cachedQuery.setResult(resultList);
        cachedQuery.cacheQuery(false);
    }

    protected void associateResultsWithAlternateMapper(Operation originalOp, MithraList list)
    {
        if (this.alternateMapper != null)
        {
            associateSimplifiedResult(this.mapper.createMappedOperationForDeepFetch(originalOp), list);
        }
    }

    protected void associateResultsWithAlternateMapper(Operation originalOp, List list)
    {
        if (this.alternateMapper != null)
        {
            associateSimplifiedResult(this.mapper.createMappedOperationForDeepFetch(originalOp), list);
        }
    }

    protected MithraList createListForAdHocDeepFetch(TupleTempContext tempContext, Object parentPrototype)
    {
        Map attributeMap = tempContext.getPrototypeToTupleAttributeMap();
        Mapper mapper = this.mapper;
        if (alternateMapper != null) mapper = alternateMapper;
        mapper = mapper.createMapperForTempJoin(attributeMap, parentPrototype, this.chainPosition);
        Operation op;
        if (tempContext.hasSourceAttribute())
        {
            op = tempContext.getSourceOperation(tempContext.getPrototypeSourceAttribute().valueOf(parentPrototype), this.mapper.getFromPortal().getFinder().getSourceAttribute());
        }
        else
        {
            op = tempContext.all();
        }
        Operation result = mapper.createMappedOperationForDeepFetch(op);
        result = addDefaultAsOfOp(result);
        return result.getResultObjectPortal().getFinder().findMany(result);
    }

    protected List cacheEmptyResult(DeepFetchNode node)
    {
        MithraList complexList = (MithraList) this.mapOpToList(node);
        CachedQuery query = new CachedQuery(complexList.getOperation(), null);
        query.setResult(ListFactory.EMPTY_LIST);
        node.setResolvedList(ListFactory.EMPTY_LIST, chainPosition);
        query.cacheQuery(true);
        return FastList.newListWith(query);
    }

    protected void cacheComplexQuery(CachedQuery cachedQuery, boolean forRelationship)
    {
        AnalyzedOperation analyzedOperation = new AnalyzedOperation(cachedQuery.getOperation());
        if (analyzedOperation.isAnalyzedOperationDifferent())
        {
            cachedQuery.setWasDefaulted();
        }
        cachedQuery.cacheQuery(forRelationship);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy