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

com.github.molcikas.photon.PhotonEntityState Maven / Gradle / Ivy

The newest version!
package com.github.molcikas.photon;

import com.github.molcikas.photon.blueprints.entity.EntityBlueprint;
import com.github.molcikas.photon.blueprints.entity.EntityBlueprintAndKey;
import com.github.molcikas.photon.blueprints.entity.FieldBlueprint;
import com.github.molcikas.photon.blueprints.entity.FieldBlueprintAndKey;
import com.github.molcikas.photon.blueprints.table.TableBlueprint;
import com.github.molcikas.photon.blueprints.table.TableBlueprintAndKey;
import com.github.molcikas.photon.blueprints.table.TableValue;
import com.github.molcikas.photon.exceptions.PhotonException;
import com.github.molcikas.photon.query.ParameterValue;
import com.github.molcikas.photon.query.PopulatedEntity;
import com.github.molcikas.photon.query.PopulatedEntityMap;
import org.apache.commons.collections4.SetValuedMap;
import org.apache.commons.collections4.multimap.HashSetValuedHashMap;

import java.util.*;
import java.util.stream.Collectors;

public class PhotonEntityState
{
    private final Map> trackedValues;
    private final SetValuedMap trackedChildren;
    private final SetValuedMap trackedFlattenedCollectionValues;

    public PhotonEntityState()
    {
        this.trackedValues = new HashMap<>();
        this.trackedChildren = new HashSetValuedHashMap<>();
        this.trackedFlattenedCollectionValues = new HashSetValuedHashMap<>();
    }

    public void track(PopulatedEntity populatedEntity)
    {
        for(TableBlueprint tableBlueprint : populatedEntity.getEntityBlueprint().getTableBlueprintsForInsertOrUpdate())
        {
            Map values = populatedEntity
                .getParameterValuesForUpdate(tableBlueprint, populatedEntity.getParentPopulatedEntity(), null)
                .getValues();

            updateTrackedValues(tableBlueprint, populatedEntity.getPrimaryKey(), values);
        }

        for(FieldBlueprint fieldBlueprint : populatedEntity.getEntityBlueprint().getFieldsWithChildEntities())
        {
            FieldBlueprintAndKey parentBlueprintAndKey =
                new FieldBlueprintAndKey(fieldBlueprint, populatedEntity.getPrimaryKey());
            trackedChildren.remove(parentBlueprintAndKey);

            List childKeys = populatedEntity
                .getChildPopulatedEntitiesForField(fieldBlueprint)
                .stream()
                .map(PopulatedEntity::getPrimaryKey)
                .collect(Collectors.toList());

            for(TableValue childKey : childKeys)
            {
                trackedChildren.put(
                    parentBlueprintAndKey,
                    new EntityBlueprintAndKey(fieldBlueprint.getChildEntityBlueprint(), childKey));
            }
        }

        for(FieldBlueprint fieldBlueprint : populatedEntity.getEntityBlueprint().getFlattenedCollectionFields())
        {
            FieldBlueprintAndKey parentBlueprintAndKey =
                new FieldBlueprintAndKey(fieldBlueprint, populatedEntity.getPrimaryKey());
            trackedFlattenedCollectionValues.remove(parentBlueprintAndKey);

            Collection flattenedCollectionValues = (Collection) populatedEntity.getInstanceValue(fieldBlueprint, null);
            if(flattenedCollectionValues == null)
            {
                flattenedCollectionValues = Collections.emptyList();
            }
            trackedFlattenedCollectionValues.putAll(parentBlueprintAndKey, flattenedCollectionValues);
        }
    }

    public void track(PopulatedEntityMap populatedEntityMap)
    {
        populatedEntityMap.getAllPopulatedEntities().forEach(this::track);
    }

    public Map getTrackedValues(TableBlueprint tableBlueprint, TableValue primaryKey)
    {
        Map values = trackedValues.get(new TableBlueprintAndKey(tableBlueprint, primaryKey));
        return values != null ? values : Collections.emptyMap();
    }

    public List getTrackedKeys(TableBlueprint tableBlueprint, List primaryKeys)
    {
        return primaryKeys
            .stream()
            .filter(p -> (trackedValues.containsKey(new TableBlueprintAndKey(tableBlueprint, p))))
            .collect(Collectors.toList());
    }

    public void updateTrackedValues(TableBlueprint tableBlueprint, TableValue tableKey, Map values)
    {
        updateTrackedValues(new TableBlueprintAndKey(tableBlueprint, tableKey), values);
    }

    public void updateTrackedValues(TableBlueprintAndKey key, Map values)
    {
        if(!key.getTableBlueprint().isPrimaryKeyMappedToField())
        {
            // We can't track the entity if the primary key is not mapped to a field.
            return;
        }
        if(key.getPrimaryKey().getValue() == null)
        {
            throw new PhotonException("Null table primary keys are not allowed in tracking.");
        }
        trackedValues.remove(key);
        trackedValues.put(key, values);
    }

    public Set getTrackedChildrenKeys(FieldBlueprint fieldBlueprint, TableValue parentKey)
    {
        FieldBlueprintAndKey parentBlueprintAndKey = new FieldBlueprintAndKey(fieldBlueprint, parentKey);
        if (!trackedChildren.containsKey(parentBlueprintAndKey))
        {
            return null;
        }
        return trackedChildren
            .get(parentBlueprintAndKey)
            .stream()
            .map(EntityBlueprintAndKey::getPrimaryKey)
            .collect(Collectors.toSet());
    }

    public Collection getTrackedFlattenedCollectionValues(FieldBlueprint fieldBlueprint, TableValue primaryKey)
    {
        return trackedFlattenedCollectionValues.get(new FieldBlueprintAndKey(fieldBlueprint, primaryKey));
    }

    public void addTrackedChild(
        FieldBlueprint fieldBlueprint,
        TableValue parentKey,
        EntityBlueprint childEntityBlueprint,
        TableValue childKey)
    {
        if(parentKey.getValue() == null)
        {
            throw new PhotonException("Null table primary keys are not allowed in tracking.");
        }
        trackedChildren.put(
            new FieldBlueprintAndKey(fieldBlueprint, parentKey),
            new EntityBlueprintAndKey(childEntityBlueprint, childKey));
    }

    public void untrack(PopulatedEntity populatedEntity)
    {
        for (TableBlueprint tableBlueprint : populatedEntity.getEntityBlueprint().getTableBlueprintsForDelete())
        {
            TableBlueprintAndKey key = new TableBlueprintAndKey(tableBlueprint, populatedEntity.getPrimaryKey());
            trackedValues.remove(key);
        }

        for (FieldBlueprint fieldBlueprint : populatedEntity.getEntityBlueprint().getFlattenedCollectionFields())
        {
            trackedFlattenedCollectionValues.remove(fieldBlueprint);
        }

        for(FieldBlueprint fieldBlueprint : populatedEntity.getEntityBlueprint().getFieldsWithChildEntities())
        {
            for(TableBlueprint tableBlueprint : fieldBlueprint.getChildEntityBlueprint().getTableBlueprintsForDelete())
            {
                List childKeys = populatedEntity
                    .getChildPopulatedEntitiesForField(fieldBlueprint)
                    .stream()
                    .map(PopulatedEntity::getPrimaryKey)
                    .collect(Collectors.toList());

                untrackChildrenRecursive(
                    fieldBlueprint,
                    populatedEntity.getPrimaryKey(),
                    fieldBlueprint.getChildEntityBlueprint(),
                    tableBlueprint,
                    childKeys
                );
            }
        }
    }

    public void untrackChildrenRecursive(
        FieldBlueprint parentFieldBlueprint,
        TableValue parentKey,
        EntityBlueprint childEntityBlueprint,
        TableBlueprint childTableBlueprint,
        List childKeysToRemove)
    {
        for(TableValue childKey : childKeysToRemove)
        {
            TableBlueprintAndKey key = new TableBlueprintAndKey(childTableBlueprint, childKey);
            trackedValues.remove(key);
        }

        for(FieldBlueprint fieldBlueprint : childEntityBlueprint.getFlattenedCollectionFields())
        {
            trackedFlattenedCollectionValues.remove(fieldBlueprint);
        }

        if(parentFieldBlueprint == null)
        {
            return;
        }

        FieldBlueprintAndKey parentBlueprintAndKey = new FieldBlueprintAndKey(parentFieldBlueprint, parentKey);
        Set childKeys = trackedChildren.get(parentBlueprintAndKey);
        if(childKeys == null)
        {
            return;
        }

        childKeys.removeAll(
            childKeysToRemove.stream().map(o -> new EntityBlueprintAndKey(childEntityBlueprint, o)).collect(Collectors.toList()));

        // All children of orphans are also orphans and need to be removed as well.
        for(FieldBlueprint childFieldBlueprint : childEntityBlueprint.getFieldsWithChildEntities())
        {
            for(TableValue childKey : childKeysToRemove)
            {
                Set grandchildKeys = trackedChildren.get(new FieldBlueprintAndKey(childFieldBlueprint, childKey));
                if(grandchildKeys == null)
                {
                    return;
                }
                EntityBlueprint grandchildEntityBlueprint =childFieldBlueprint.getChildEntityBlueprint();
                for(TableBlueprint grandchildTableBlueprint : grandchildEntityBlueprint.getTableBlueprintsForDelete())
                untrackChildrenRecursive(
                    childFieldBlueprint,
                    childKey,
                    grandchildEntityBlueprint,
                    grandchildTableBlueprint,
                    grandchildKeys.stream().map(EntityBlueprintAndKey::getPrimaryKey).collect(Collectors.toList()));
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy