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

com.gs.fw.common.mithra.finder.AsOfEqualityChecker 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.fw.common.mithra.MithraBusinessException;
import com.gs.fw.common.mithra.attribute.TemporalAttribute;
import com.gs.fw.common.mithra.tempobject.TupleTempContext;
import com.gs.fw.common.mithra.util.CollectionUtil;
import com.gs.fw.common.mithra.util.InternalList;
import com.gs.fw.common.mithra.attribute.AsOfAttribute;
import com.gs.fw.common.mithra.finder.asofop.AsOfEdgePointOperation;
import com.gs.fw.common.mithra.finder.asofop.AsOfEqOperation;
import com.gs.fw.common.mithra.finder.asofop.AsOfOperation;
import com.gs.fw.common.mithra.finder.orderby.OrderBy;
import com.gs.collections.impl.set.mutable.UnifiedSet;
import com.gs.collections.impl.map.mutable.UnifiedMap;
import com.gs.fw.common.mithra.util.Pair;

import java.util.*;



public class AsOfEqualityChecker implements MapperStack
{
    private static final ObjectWithMapperStack[] EMPTY_ARRAY = new ObjectWithMapperStack[0];
    private static final AsOfAttributeWithStackComparator AS_OF_ATTRIBUTE_WITH_STACK_COMPARATOR = new AsOfAttributeWithStackComparator();

    private UnifiedMap, ObjectWithMapperStack> asOfOperationMap;
    private UnifiedMap, InternalList> equalityAsOfOperationMap;
    private FastList> multiInTempContexts;
    private boolean processedAsOfEqualities = false;
    private boolean hasAsOfAttributes;
    private ObjectWithMapperStack[] allAsOfAttributesWithMapperStack;
    private Set> registeredAsOfAttributesWithMapperStack;
    private MapperStackImpl mapperStackImpl = new MapperStackImpl();
    private UnifiedMap asOfAttributeWithMapperStackToInsert;
    private InternalList[] allToInsert;

    private ObjectWithMapperStack temp;
    private UnifiedMap msiPool;

    private Operation op;
    private OrderBy orderBy;
    private static final Comparator DEEP_FIRST = new DeepFirstComparator();

    public AsOfEqualityChecker(Operation op, OrderBy orderBy)
    {
        this.op = op;
        this.orderBy = orderBy;
        this.processOperation();
    }

    protected void processOperation()
    {
        registerAsOfAttributes();

        if (hasAsOfAttributes)
        {
            populateAllAsOfAttributes();
            lookForMissingDefaults();
            insertEqualitiesAndDefaults();
        }
    }

    private void insertEqualitiesAndDefaults()
    {
        if (asOfAttributeWithMapperStackToInsert != null)
        {
            boolean insertedDefault = false;
            allToInsert = new InternalList[asOfAttributeWithMapperStackToInsert.size()];
            asOfAttributeWithMapperStackToInsert.values().toArray(allToInsert);
            Arrays.sort(allToInsert, DEEP_FIRST);
            AtomicOperation[] arrayOfOne = new AtomicOperation[1];
            for(InternalList toInsertList: allToInsert)
            {
                AtomicOperation[] arrayToInsert = arrayOfOne;
                if (toInsertList.size() == 1)
                {
                    arrayToInsert[0] = ((ObjectWithMapperStackAndAsOfOperation) toInsertList.get(0)).asOfOperation;
                }
                else
                {
                    arrayToInsert = new AtomicOperation[toInsertList.size()];
                    for(int i=0;i 1) CollectionUtil.psort(allAsOfAttributesWithMapperStack, AS_OF_ATTRIBUTE_WITH_STACK_COMPARATOR);
        for(int i=0;i asOfAttributeWithMapperStack = allAsOfAttributesWithMapperStack[i];
            if (this.getAsOfOperation(asOfAttributeWithMapperStack) == null)
            {
                TemporalAttribute temporalAttribute = asOfAttributeWithMapperStack.getObject();
                if (temporalAttribute.isAsOfAttribute())
                {
                    AsOfAttribute asOfAttribute = (AsOfAttribute) temporalAttribute;
                    if (asOfAttribute.getDefaultDate() != null)
                    {
                        AsOfOperation asOfOperation = (AsOfOperation)asOfAttribute.eq(asOfAttribute.getDefaultDate());
                        addToInsert(asOfAttributeWithMapperStack, (AtomicOperation) asOfOperation);
                        this.setAsOfOperation(asOfAttributeWithMapperStack, asOfOperation);
                        this.processedAsOfEqualities = false;
                    }
                }
            }
        }
    }

    private void addToInsert(ObjectWithMapperStack asOfAttributeWithMapperStack, AtomicOperation asOfOperation)
    {
        if (asOfOperation == null) return;
        InternalList value;
        if (asOfAttributeWithMapperStackToInsert == null)
        {
            asOfAttributeWithMapperStackToInsert = new UnifiedMap(4);
            value = new InternalList(2);
            asOfAttributeWithMapperStackToInsert.put(asOfAttributeWithMapperStack.getMapperStack(), value);
        }
        else
        {
            value = asOfAttributeWithMapperStackToInsert.get(asOfAttributeWithMapperStack.getMapperStack());
            if (value == null)
            {
                value = new InternalList(2);
                asOfAttributeWithMapperStackToInsert.put(asOfAttributeWithMapperStack.getMapperStack(), value);
            }
        }
        value.add(new ObjectWithMapperStackAndAsOfOperation(asOfAttributeWithMapperStack, asOfOperation));
    }

    private void populateAllAsOfAttributes()
    {
        this.allAsOfAttributesWithMapperStack = new ObjectWithMapperStack[registeredAsOfAttributesWithMapperStack.size()];
        int count = 0;
        for(Iterator it = registeredAsOfAttributesWithMapperStack.iterator(); it.hasNext(); count++)
        {
            this.allAsOfAttributesWithMapperStack[count] = (ObjectWithMapperStack) it.next();
        }
    }

    private void registerAsOfAttributes()
    {
        op.registerAsOfAttributesAndOperations(this);
        if (this.orderBy != null)
        {
            orderBy.registerAsOfAttributes(this);
        }
//        this.registerAsOfAttributes(op.getResultObjectPortal().getFinder().getAsOfAttributes());

        this.hasAsOfAttributes = this.registeredAsOfAttributesWithMapperStack != null;
    }

    public ObjectWithMapperStack[] getAllAsOfAttributesWithMapperStack()
    {
        if (!this.hasAsOfAttributes)
        {
            return EMPTY_ARRAY;
        }
        return allAsOfAttributesWithMapperStack;
    }

    public Operation getOperation()
    {
        return op;
    }

    public void pushMapper(Mapper mapper)
    {
        mapperStackImpl.pushMapper(mapper);
    }

    public Mapper popMapper()
    {
        return mapperStackImpl.popMapper();
    }

    public void pushMapperContainer(Object mapper)
    {
        mapperStackImpl.pushMapperContainer(mapper);
    }

    public void popMapperContainer()
    {
        mapperStackImpl.popMapperContainer();
    }

    public ObjectWithMapperStack constructWithMapperStack(Object o)
    {
        return mapperStackImpl.constructWithMapperStack(o, getMsiPool());
    }

    public ObjectWithMapperStack constructWithMapperStackWithoutLastMapper(Object o)
    {
        return mapperStackImpl.constructWithMapperStackWithoutLastMapper(o, getMsiPool());
    }

    public MapperStackImpl getCurrentMapperList()
    {
        return mapperStackImpl.getCurrentMapperList();
    }

    public void setEqualityAsOfOperation(TemporalAttribute left, TemporalAttribute right)
    {
        ObjectWithMapperStack leftWithMapperStack = this.constructWithMapperStackWithoutLastMapper(left);
        ObjectWithMapperStack rightWithMapperStack = this.constructWithMapperStack(right);
        addEqualityAsOfOperation(leftWithMapperStack, rightWithMapperStack);
        addEqualityAsOfOperation(rightWithMapperStack, leftWithMapperStack);
    }

    private void addEqualityAsOfOperation(ObjectWithMapperStack left, ObjectWithMapperStack right)
    {
        InternalList existing = this.getEqualityAsOfOperationMap().get(left);
        if (existing == null)
        {
            existing = new InternalList(4);
            this.getEqualityAsOfOperationMap().put(left, existing);
        }
        existing.add(right);
    }

    public void setAsOfOperation(ObjectWithMapperStack attributeWithMapperStack, AsOfOperation op)
    {
        MapperStackImpl atBoundary = this.mapperStackImpl.ifAtContainerBoundaryCloneAndPop();
        this.setAsOfOperation(attributeWithMapperStack, new ObjectWithMapperStack(atBoundary, op, getMsiPool()));
    }

    private boolean setAsOfOperation(ObjectWithMapperStack attributeWithMapperStack, ObjectWithMapperStack op)
    {
        ObjectWithMapperStack asOfEqOp = this.getAsOfOperationMap().get(attributeWithMapperStack);
        if (asOfEqOp == null)
        {
            return setAsOfOperationUnconditionally(attributeWithMapperStack, op);
        }
        else
        {

            AsOfOperation newAsOfOperation = op.getObject();
            AsOfOperation existingAsOfOperation = (AsOfOperation) asOfEqOp.getObject();
            if (existingAsOfOperation.zGetAsOfOperationPriority() < newAsOfOperation.zGetAsOfOperationPriority())
            {
                return setAsOfOperationUnconditionally(attributeWithMapperStack, op);
            }
            else if (newAsOfOperation instanceof AsOfEqOperation && existingAsOfOperation instanceof AsOfEqOperation)
            {
                AsOfEqOperation first = (AsOfEqOperation) newAsOfOperation;
                AsOfEqOperation second = (AsOfEqOperation) existingAsOfOperation;
                if (!first.getParameter().equals(second.getParameter())) throw new MithraBusinessException("can't have multiple asOf operations");
            }

        }

        return false;
    }

    private boolean setAsOfOperationUnconditionally(ObjectWithMapperStack attributeWithMapperStack, ObjectWithMapperStack op)
    {
        MapperStackImpl mapperStack = attributeWithMapperStack.getMapperStack();
        if (mapperStack.isAtContainerBoundry())
        {
            MapperStackImpl copy = mapperStack.ifAtContainerBoundaryCloneAndPop();
            this.getAsOfOperationMap().put(new ObjectWithMapperStack(copy, attributeWithMapperStack.getObject(), getMsiPool()), op);
        }
        else
        {
            this.getAsOfOperationMap().put(attributeWithMapperStack, op);
        }
        return true;
    }

    public void setAsOfEqOperation(AsOfEqOperation op)
    {
        this.setAsOfOperation(new ObjectWithMapperStack(this.mapperStackImpl, (TemporalAttribute) op.getAttribute(), getMsiPool()), op);
    }

    public void setAsOfEdgePointOperation(AsOfEdgePointOperation op)
    {
        this.setAsOfOperation(new ObjectWithMapperStack(this.mapperStackImpl, op.getAsOfAttribute(), getMsiPool()), op);
    }

    public UnifiedMap getMsiPool()
    {
        if (msiPool == null) msiPool = UnifiedMap.newMap();
        return msiPool;
    }

    public ObjectWithMapperStack getAsOfOperation(ObjectWithMapperStack asOfAttributeWithMapperStack)
    {
        if (this.equalityAsOfOperationMap != null && !processedAsOfEqualities)
        {
            processAsOfAttributeEqualities();
        }
        ObjectWithMapperStack aop = this.getAsOfOperationMap().get(asOfAttributeWithMapperStack);
        if (aop == null && asOfAttributeWithMapperStack.getMapperStack().isAtContainerBoundry())
        {
            MapperStackImpl copy =  asOfAttributeWithMapperStack.getMapperStack().ifAtContainerBoundaryCloneAndPop();
            aop = this.getAsOfOperationMap().get(new ObjectWithMapperStack(copy, asOfAttributeWithMapperStack.getObject(), getMsiPool()));
        }
        return aop;
    }

    private void processAsOfAttributeEqualities()
    {
        InternalList attributesToProcess = new InternalList(this.getEqualityAsOfOperationMap().keySet());
        int numProcessedThisLoop;
        do
        {
            numProcessedThisLoop = 0;
            for (int i=0;i asOfAttribute = (ObjectWithMapperStack) attributesToProcess.get(i);
                if (processAsOfEquality(asOfAttribute))
                {
                    attributesToProcess.remove(i);
                    numProcessedThisLoop++;
                }
                else i++;
            }
        }
        while (numProcessedThisLoop > 0);
        this.processedAsOfEqualities = true;
    }

    private boolean processAsOfEquality(ObjectWithMapperStack attribute)
    {
        InternalList equalities = this.equalityAsOfOperationMap.get(attribute);
        if (equalities != null)
        {
            ObjectWithMapperStack currentAsOfOperation = this.getAsOfOperationMap().get(attribute);
            if (currentAsOfOperation != null)
            {
                for(int i=0;i rightAttribute = (ObjectWithMapperStack)equalities.get(i);
                    if (this.setAsOfOperation(rightAttribute, currentAsOfOperation))
                    {
                        addToInsert(rightAttribute,
                                currentAsOfOperation.getObject().createAsOfOperationCopy(rightAttribute.getObject(), this.op));
                    }
                }
                return true;
            }
        }
        return false;
    }

    private UnifiedMap, ObjectWithMapperStack> getAsOfOperationMap()
    {
        if (asOfOperationMap == null) asOfOperationMap = UnifiedMap.newMap(3);
        return asOfOperationMap;
    }

    private UnifiedMap, InternalList> getEqualityAsOfOperationMap()
    {
        if (equalityAsOfOperationMap == null) equalityAsOfOperationMap = UnifiedMap.newMap(3);
        return equalityAsOfOperationMap;
    }

    public boolean hasAsOfAttributes()
    {
        return this.hasAsOfAttributes;
    }

    private ObjectWithMapperStack getOrCreateTemp()
    {
        if (temp == null) temp = new ObjectWithMapperStack(null, null);
        temp.resetWithoutClone(null, null);
        return temp;
    }

    public void registerAsOfAttributes(AsOfAttribute[] asOfAttributes)
    {
        if (asOfAttributes != null)
        {
            initRegisteredAsOfAttributesWithMapperStack();
            //todo: pop to container boundry
            ObjectWithMapperStack tempObject = getOrCreateTemp();
            MapperStackImpl atBoundary = this.mapperStackImpl.ifAtContainerBoundaryCloneAndPop();
            for(int i=0;i>(8);
        }
    }

    public TupleTempContext getOrCreateMultiInTempContext(MultiInOperation op)
    {
        if (this.multiInTempContexts == null)
        {
            this.multiInTempContexts = FastList.newList(2);
            return createAndAddTempContext(op);
        }
        for(int i=0;i tupleTempContextPair = multiInTempContexts.get(i);
            if (tupleTempContextPair.getOne() == op)
            {
                return tupleTempContextPair.getTwo();
            }
        }
        return createAndAddTempContext(op);
    }

    private TupleTempContext createAndAddTempContext(MultiInOperation op)
    {
        TupleTempContext result = op.createTempContext();
        this.multiInTempContexts.add(new Pair(op, result));
        return result;
    }

    public void registerTimestampTemporalAttribute(ObjectWithMapperStack attribute)
    {
        initRegisteredAsOfAttributesWithMapperStack();
        this.registeredAsOfAttributesWithMapperStack.add(attribute);
    }

    private static final class ObjectWithMapperStackAndAsOfOperation
    {
        private ObjectWithMapperStack asOfAttributeWithMapperStack;
        private AtomicOperation asOfOperation;

        private ObjectWithMapperStackAndAsOfOperation(ObjectWithMapperStack asOfAttributeWithMapperStack, AtomicOperation asOfOperation)
        {
            this.asOfAttributeWithMapperStack = asOfAttributeWithMapperStack;
            this.asOfOperation = asOfOperation;
        }
    }

    private static final class DeepFirstComparator implements Comparator
    {
        public int compare(InternalList leftList, InternalList rightList)
        {
            ObjectWithMapperStackAndAsOfOperation left = (ObjectWithMapperStackAndAsOfOperation) leftList.get(0);
            ObjectWithMapperStackAndAsOfOperation right = (ObjectWithMapperStackAndAsOfOperation) rightList.get(0);
            int result = right.asOfAttributeWithMapperStack.getMapperStack().getMapperStack().size() -
                    left.asOfAttributeWithMapperStack.getMapperStack().getMapperStack().size();
            if (result == 0)
            {
                result = right.asOfAttributeWithMapperStack.getMapperStack().getMapperContainerStack().size() -
                        left.asOfAttributeWithMapperStack.getMapperStack().getMapperContainerStack().size();
            }
            return result;
        }
    }

    private static class AsOfAttributeWithStackComparator implements Comparator>
    {
        public int compare(ObjectWithMapperStack o1, ObjectWithMapperStack o2)
        {
            int result = o1.getMapperStack().compareTo(o2.getMapperStack());
            if (result == 0)
            {
                int leftWeight = 0;
                int rightWeight = 0;
                if (o1.getObject().isAsOfAttribute())
                {
                    leftWeight = ((AsOfAttribute)o1.getObject()).isProcessingDate() ? 100 : 50;
                }
                if (o2.getObject().isAsOfAttribute())
                {
                    rightWeight = ((AsOfAttribute)o2.getObject()).isProcessingDate() ? 100 : 50;
                }
                result = leftWeight - rightWeight;
            }
            return result;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy