org.neo4j.values.SequenceValue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-values Show documentation
Show all versions of neo4j-values Show documentation
Neo4j property value system.
/*
* Copyright (c) "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.values;
import java.util.Comparator;
import java.util.Iterator;
import static org.neo4j.values.SequenceValue.IterationPreference.RANDOM_ACCESS;
/**
* Values that represent sequences of values (such as Lists or Arrays) need to implement this interface.
* Thus we can get an equality check that is based on the values (e.g. List.equals(ArrayValue) )
* Values that implement this interface also need to overwrite isSequence() to return true!
*
* Note that even though SequenceValue extends Iterable iterating over the sequence using iterator() might not be the
* most performant method. Branch using iterationPreference() in performance critical code paths.
*/
public interface SequenceValue extends Iterable
{
/**
* The preferred way to iterate this sequence. Preferred in this case means the method which is expected to be
* the most performant.
*/
enum IterationPreference
{
RANDOM_ACCESS,
ITERATION
}
int length();
default boolean isEmpty()
{
return length() == 0;
}
AnyValue value( int offset );
@Override
Iterator iterator();
IterationPreference iterationPreference();
default boolean equals( SequenceValue other )
{
if ( other == null )
{
return false;
}
IterationPreference pref = iterationPreference();
IterationPreference otherPref = other.iterationPreference();
if ( pref == RANDOM_ACCESS && otherPref == RANDOM_ACCESS )
{
return equalsUsingRandomAccess( this, other );
}
else
{
return equalsUsingIterators( this, other );
}
}
static boolean equalsUsingRandomAccess( SequenceValue a, SequenceValue b )
{
int i = 0;
boolean areEqual = a.length() == b.length();
while ( areEqual && i < a.length() )
{
areEqual = a.value( i ).equals( b.value( i ) );
i++;
}
return areEqual;
}
static Equality ternaryEqualsUsingRandomAccess( SequenceValue a, SequenceValue b )
{
int length = a.length();
if ( length != b.length() )
{
return Equality.FALSE;
}
int i = 0;
Equality equivalenceResult = Equality.TRUE;
while ( i < length )
{
Equality areEqual = a.value( i ).ternaryEquals( b.value( i ) );
if ( areEqual == Equality.UNDEFINED )
{
equivalenceResult = Equality.UNDEFINED;
}
else if ( areEqual == Equality.FALSE )
{
return Equality.FALSE;
}
i++;
}
return equivalenceResult;
}
static boolean equalsUsingIterators( SequenceValue a, SequenceValue b )
{
boolean areEqual = true;
Iterator aIterator = a.iterator();
Iterator bIterator = b.iterator();
while ( areEqual && aIterator.hasNext() && bIterator.hasNext() )
{
areEqual = aIterator.next().equals( bIterator.next() );
}
return areEqual && aIterator.hasNext() == bIterator.hasNext();
}
static Equality ternaryEqualsUsingIterators( SequenceValue a, SequenceValue b )
{
Equality equivalenceResult = Equality.TRUE;
Iterator aIterator = a.iterator();
Iterator bIterator = b.iterator();
while ( aIterator.hasNext() && bIterator.hasNext() )
{
Equality areEqual = aIterator.next().ternaryEquals( bIterator.next() );
if ( areEqual == Equality.UNDEFINED )
{
equivalenceResult = Equality.UNDEFINED;
}
else if ( areEqual == Equality.FALSE )
{
return Equality.FALSE;
}
}
return !aIterator.hasNext() && !bIterator.hasNext() ? equivalenceResult : Equality.FALSE;
}
default int compareToSequence( SequenceValue other, Comparator comparator )
{
IterationPreference pref = iterationPreference();
IterationPreference otherPref = other.iterationPreference();
if ( pref == RANDOM_ACCESS && otherPref == RANDOM_ACCESS )
{
return compareUsingRandomAccess( this, other, comparator );
}
else
{
return compareUsingIterators( this, other, comparator );
}
}
default Comparison ternaryCompareToSequence( SequenceValue other, TernaryComparator comparator )
{
IterationPreference pref = iterationPreference();
IterationPreference otherPref = other.iterationPreference();
if ( pref == RANDOM_ACCESS && otherPref == RANDOM_ACCESS )
{
return ternaryCompareUsingRandomAccess( this, other, comparator );
}
else
{
return ternaryCompareUsingIterators( this, other, comparator );
}
}
static int compareUsingRandomAccess( SequenceValue a, SequenceValue b, Comparator comparator )
{
int i = 0;
int x = 0;
int length = Math.min( a.length(), b.length() );
while ( x == 0 && i < length )
{
x = comparator.compare( a.value( i ), b.value( i ) );
i++;
}
if ( x == 0 )
{
x = a.length() - b.length();
}
return x;
}
static int compareUsingIterators( SequenceValue a, SequenceValue b, Comparator comparator )
{
int x = 0;
Iterator aIterator = a.iterator();
Iterator bIterator = b.iterator();
while ( x == 0 && aIterator.hasNext() && bIterator.hasNext() )
{
x = comparator.compare( aIterator.next(), bIterator.next() );
}
if ( x == 0 )
{
x = Boolean.compare( aIterator.hasNext(), bIterator.hasNext() );
}
return x;
}
static Comparison ternaryCompareUsingRandomAccess( SequenceValue a, SequenceValue b, TernaryComparator comparator )
{
Comparison cmp = Comparison.EQUAL;
int i = 0;
int length = Math.min( a.length(), b.length() );
while ( cmp == Comparison.EQUAL && i < length )
{
cmp = comparator.ternaryCompare( a.value( i ), b.value( i ) );
i++;
}
if ( cmp == Comparison.EQUAL )
{
cmp = Comparison.from( a.length() - b.length() );
}
return cmp;
}
static Comparison ternaryCompareUsingIterators( SequenceValue a, SequenceValue b, TernaryComparator comparator )
{
Comparison cmp = Comparison.EQUAL;
Iterator aIterator = a.iterator();
Iterator bIterator = b.iterator();
while ( cmp == Comparison.EQUAL && aIterator.hasNext() && bIterator.hasNext() )
{
cmp = comparator.ternaryCompare( aIterator.next(), bIterator.next() );
}
if ( cmp == Comparison.EQUAL )
{
cmp = Comparison.from( Boolean.compare( aIterator.hasNext(), bIterator.hasNext() ) );
}
return cmp;
}
default Equality ternaryEquality( SequenceValue other )
{
IterationPreference pref = iterationPreference();
IterationPreference otherPref = other.iterationPreference();
if ( pref == RANDOM_ACCESS && otherPref == RANDOM_ACCESS )
{
return ternaryEqualsUsingRandomAccess(this, other );
}
else
{
return ternaryEqualsUsingIterators( this, other );
}
}
}