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

org.neo4j.kernel.impl.api.state.PropertyContainerStateImpl Maven / Gradle / Ivy

Go to download

ONgDB kernel is a lightweight, embedded Java database designed to store data structured as graphs rather than tables. For more information, see https://graphfoundation.org.

There is a newer version: 3.6.2
Show newest version
/*
 * Copyright (c) 2018-2020 "Graph Foundation,"
 * Graph Foundation, Inc. [https://graphfoundation.org]
 *
 * This file is part of ONgDB.
 *
 * ONgDB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
/*
 * Copyright (c) 2002-2020 "Neo4j,"
 * Neo4j Sweden AB [http://neo4j.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package org.neo4j.kernel.impl.api.state;

import java.util.Iterator;
import java.util.Set;
import java.util.function.Predicate;

import org.neo4j.helpers.collection.Iterators;
import org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException;
import org.neo4j.kernel.api.properties.PropertyKeyValue;
import org.neo4j.kernel.impl.util.VersionedHashMap;
import org.neo4j.storageengine.api.StorageProperty;
import org.neo4j.storageengine.api.txstate.PropertyContainerState;
import org.neo4j.values.storable.Value;

import static java.util.Collections.emptyIterator;
import static java.util.Collections.newSetFromMap;

class PropertyContainerStateImpl implements PropertyContainerState
{
    private final long id;

    private VersionedHashMap addedProperties;
    private VersionedHashMap changedProperties;
    private Set removedProperties;

    private final Predicate excludePropertiesWeKnowAbout = new Predicate()
    {
        @Override
        public boolean test( StorageProperty item )
        {
            return (removedProperties == null || !removedProperties.contains( item.propertyKeyId() ))
                    && (addedProperties == null || !addedProperties.containsKey( item.propertyKeyId() ))
                    && (changedProperties == null || !changedProperties.containsKey( item.propertyKeyId() ));
        }
    };

    PropertyContainerStateImpl( long id )
    {
        this.id = id;
    }

    public long getId()
    {
        return id;
    }

    void clear()
    {
        if ( changedProperties != null )
        {
            changedProperties.clear();
        }
        if ( addedProperties != null )
        {
            addedProperties.clear();
        }
        if ( removedProperties != null )
        {
            removedProperties.clear();
        }
    }

    void changeProperty( int propertyKeyId, Value value )
    {
        if ( addedProperties != null && addedProperties.containsKey( propertyKeyId ) )
        {
            addedProperties.put( propertyKeyId, value );
            return;
        }

        if ( changedProperties == null )
        {
            changedProperties = new VersionedHashMap<>();
        }
        changedProperties.put( propertyKeyId, value );

        if ( removedProperties != null )
        {
            removedProperties.remove( propertyKeyId );
        }
    }

    void addProperty( int propertyKeyId, Value value )
    {
        if ( removedProperties != null && removedProperties.remove( propertyKeyId ) )
        {
            // This indicates the user did remove+add as two discrete steps, which should be translated to
            // a single change operation.
            changeProperty( propertyKeyId, value );
            return;
        }
        if ( addedProperties == null )
        {
            addedProperties = new VersionedHashMap<>();
        }
        addedProperties.put( propertyKeyId, value );
    }

    void removeProperty( int propertyKeyId )
    {
        if ( addedProperties != null && addedProperties.remove( propertyKeyId ) != null )
        {
            return;
        }
        if ( removedProperties == null )
        {
            removedProperties = newSetFromMap( new VersionedHashMap<>() );
        }
        removedProperties.add( propertyKeyId );
        if ( changedProperties != null )
        {
            changedProperties.remove( propertyKeyId );
        }
    }

    @Override
    public Iterator addedProperties()
    {
        return toPropertyIterator( addedProperties );
    }

    @Override
    public Iterator changedProperties()
    {
        return toPropertyIterator( changedProperties );
    }

    @Override
    public Iterator removedProperties()
    {
        return removedProperties != null ? removedProperties.iterator() : emptyIterator();
    }

    @Override
    public Iterator addedAndChangedProperties()
    {
        if ( addedProperties == null )
        {
            return toPropertyIterator( changedProperties );
        }
        if ( changedProperties == null )
        {
            return toPropertyIterator( addedProperties );
        }
        return Iterators.concat( toPropertyIterator( addedProperties ), toPropertyIterator( changedProperties ) );
    }

    @Override
    public Iterator augmentProperties( Iterator iterator )
    {
        if ( removedProperties != null || addedProperties != null || changedProperties != null )
        {
            iterator = Iterators.filter( excludePropertiesWeKnowAbout, iterator );

            if ( addedProperties != null && !addedProperties.isEmpty() )
            {
                iterator = Iterators.concat( iterator, toPropertyIterator( addedProperties ) );
            }
            if ( changedProperties != null && !changedProperties.isEmpty() )
            {
                iterator = Iterators.concat( iterator, toPropertyIterator( changedProperties ) );
            }
        }

        return iterator;
    }

    @Override
    public void accept( Visitor visitor ) throws ConstraintValidationException
    {
        if ( addedProperties != null || removedProperties != null || changedProperties != null )
        {
            visitor.visitPropertyChanges( id, addedProperties(), changedProperties(), removedProperties() );
        }
    }

    @Override
    public boolean hasPropertyChanges()
    {
        return addedProperties != null || removedProperties != null || changedProperties != null;
    }

    @Override
    public StorageProperty getChangedProperty( int propertyKeyId )
    {
        return changedProperties == null ? null : getPropertyOrNull( changedProperties, propertyKeyId );
    }

    @Override
    public StorageProperty getAddedProperty( int propertyKeyId )
    {
        return addedProperties == null ? null : getPropertyOrNull( addedProperties, propertyKeyId );
    }

    @Override
    public boolean isPropertyChangedOrRemoved( int propertyKey )
    {
        return (removedProperties != null && removedProperties.contains( propertyKey ))
               || (changedProperties != null && changedProperties.containsKey( propertyKey ));
    }

    @Override
    public boolean isPropertyRemoved( int propertyKeyId )
    {
        return removedProperties != null && removedProperties.contains( propertyKeyId );
    }

    private Iterator toPropertyIterator( VersionedHashMap propertyMap )
    {
        return propertyMap == null ? emptyIterator() :
               Iterators.map(
                    entry -> new PropertyKeyValue( entry.getKey(), entry.getValue() ),
                    propertyMap.entrySet().iterator()
                );
    }

    private PropertyKeyValue getPropertyOrNull( VersionedHashMap propertyMap, int propertyKeyId )
    {
        Value value = propertyMap.get( propertyKeyId );
        return value == null ? null : new PropertyKeyValue( propertyKeyId, value );
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy