public void setElementMatchPaths(String... paths) {
        resetResults();
        this.elementPaths = paths;
        this.elementKeyPaths = null;
        this.elementNonKeyPaths = null;
    }

public void setElementMatchPaths ( String ... paths ) { resetResults ( ) ; this . elementPaths = paths ; this . elementKeyPaths = null ; this . elementNonKeyPaths = null ; }

Set the paths for which we will inspect differences across the two states

@param paths the paths for inspection


public void setElementKeyPaths(String... paths) {
        resetResults();
        elementKeyPaths = new BitSet(elementPaths.length);
        for(int i=0;i<paths.length;i++) {
            int elementPathIdx = getElementPathIdx(paths[i]);
            if(elementPathIdx == -1)
                throw new IllegalArgumentException("Key path must have been specified as an element match path.  Offending path: " + paths[i]);
            elementKeyPaths.set(elementPathIdx);
        }

        elementNonKeyPaths = new BitSet(elementPaths.length);
        elementNonKeyPaths.set(0, elementPaths.length);
        elementNonKeyPaths.andNot(elementKeyPaths);
    }

Optionally specify paths for which we will match records within an individual type's hierarchy

@param paths the paths for matching

Optionally specify paths for which we will match records within an individual type s hierarchy


public void calculate() {
        resetResults();
        SimultaneousExecutor executor = new SimultaneousExecutor(getClass(), "calculate");
        final int numThreads = executor.getCorePoolSize();

        for(int i=0;i<numThreads;i++) {
            final int threadNumber = i;
            executor.execute(new Runnable() {
                public void run() {
                    HollowIndexerValueTraverser fromTraverser = new HollowIndexerValueTraverser(from, type, elementPaths);
                    HollowIndexerValueTraverser toTraverser = new HollowIndexerValueTraverser(to, type, elementPaths);

                    int hashedResults[] = new int[16];

                    for(int i=threadNumber;i<matcher.getMatchedOrdinals().size();i += numThreads) {
                        long ordinalPair = matcher.getMatchedOrdinals().get(i);
                        int fromOrdinal = (int)(ordinalPair >>> 32);
                        int toOrdinal = (int)ordinalPair;

                        fromTraverser.traverse(fromOrdinal);
                        toTraverser.traverse(toOrdinal);

                        if(fromTraverser.getNumMatches() * 2 > hashedResults.length)
                            hashedResults = new int[hashTableSize(fromTraverser.getNumMatches())];

                        populateHashTable(fromTraverser, hashedResults);

                        countMatches(fromTraverser, toTraverser, hashedResults);
                    }

                    for(int i=threadNumber;i<matcher.getExtraInFrom().size();i+=numThreads) {
                        fromTraverser.traverse(matcher.getExtraInFrom().get(i));
                        totalUnmatchedFromElements.addAndGet(fromTraverser.getNumMatches());
                    }

                    for(int i=threadNumber;i<matcher.getExtraInTo().size();i+=numThreads) {
                        toTraverser.traverse(matcher.getExtraInTo().get(i));
                        totalUnmatchedToElements.addAndGet(toTraverser.getNumMatches());
                    }
                }
            });
        }

        try {
            executor.awaitSuccessfulCompletion();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

public void calculate ( ) { resetResults ( ) ; SimultaneousExecutor executor = new SimultaneousExecutor ( getClass ( ) , "calculate" ) ; final int numThreads = executor . getCorePoolSize ( ) ; for ( int i = 0 ; i < numThreads ; i ++ ) { final int threadNumber = i ; executor . execute ( new Runnable ( ) { public void run ( ) { HollowIndexerValueTraverser fromTraverser = new HollowIndexerValueTraverser ( from , type , elementPaths ) ; HollowIndexerValueTraverser toTraverser = new HollowIndexerValueTraverser ( to , type , elementPaths ) ; int hashedResults [ ] = new int [ 16 ] ; for ( int i = threadNumber ; i < matcher . getMatchedOrdinals ( ) . size ( ) ; i += numThreads ) { long ordinalPair = matcher . getMatchedOrdinals ( ) . get ( i ) ; int fromOrdinal = ( int ) ( ordinalPair >>> 32 ) ; int toOrdinal = ( int ) ordinalPair ; fromTraverser . traverse ( fromOrdinal ) ; toTraverser . traverse ( toOrdinal ) ; if ( fromTraverser . getNumMatches ( ) * 2 > hashedResults . length ) hashedResults = new int [ hashTableSize ( fromTraverser . getNumMatches ( ) ) ] ; populateHashTable ( fromTraverser , hashedResults ) ; countMatches ( fromTraverser , toTraverser , hashedResults ) ; } for ( int i = threadNumber ; i < matcher . getExtraInFrom ( ) . size ( ) ; i += numThreads ) { fromTraverser . traverse ( matcher . getExtraInFrom ( ) . get ( i ) ) ; totalUnmatchedFromElements . addAndGet ( fromTraverser . getNumMatches ( ) ) ; } for ( int i = threadNumber ; i < matcher . getExtraInTo ( ) . size ( ) ; i += numThreads ) { toTraverser . traverse ( matcher . getExtraInTo ( ) . get ( i ) ) ; totalUnmatchedToElements . addAndGet ( toTraverser . getNumMatches ( ) ) ; } } } ) ; } try { executor . awaitSuccessfulCompletion ( ) ; } catch ( Exception ex ) { throw new RuntimeException ( ex ) ; } }


public void restoreFromLastState() {
        producer.initializeDataModel(dataModel);
        long latestAnnouncedVersion = announcementWatcher.getLatestVersion();
        if (latestAnnouncedVersion == HollowFilesystemAnnouncementWatcher.NO_ANNOUNCEMENT_AVAILABLE || latestAnnouncedVersion < 0) {
            return;
        }

        restore(latestAnnouncedVersion, blobRetriever);
    }

public void restoreFromLastState ( ) { producer . initializeDataModel ( dataModel ) ; long latestAnnouncedVersion = announcementWatcher . getLatestVersion ( ) ; if ( latestAnnouncedVersion == HollowFilesystemAnnouncementWatcher . NO_ANNOUNCEMENT_AVAILABLE || latestAnnouncedVersion < 0 ) { return ; } restore ( latestAnnouncedVersion , blobRetriever ) ; }

Initializes the data model and restores from existing state.

Initializes the data model and restores from existing state .


public long runCycle() {
        long recordsRemoved = countRecordsToRemove();
        long recordsAddedOrModified = this.mutations.values().size() - recordsRemoved;
        try {
            long version = producer.runCycle(populator);
            if(version == lastSucessfulCycle) {
                return version;
            }
            listeners.fireIncrementalCycleComplete(version, recordsAddedOrModified, recordsRemoved, new HashMap<String, Object>(cycleMetadata));
            //Only clean changes when the version is new.
            clearChanges();
            lastSucessfulCycle = version;
            return version;
        } catch (Exception e) {
            listeners.fireIncrementalCycleFail(e, recordsAddedOrModified, recordsRemoved, new HashMap<String, Object>(cycleMetadata));
            return FAILED_VERSION;
        } finally {
            clearCycleMetadata();
        }
    }

Runs a Hollow Cycle, if successful, cleans the mutations map.

@return the version of the cycle if successful, otherwise the {@link #FAILED_VERSION}
@since 2.9.9

Runs a Hollow Cycle if successful cleans the mutations map .


public void excludeKey(HollowPrimaryKeyIndex idx, Object... key) {
        int excludeOrdinal = idx.getMatchingOrdinal(key);

        if(excludeOrdinal >= 0) {
            BitSet excludedOrdinals = this.excludedOrdinals.get(idx.getTypeState());

            if(excludedOrdinals == null) {
                excludedOrdinals = new BitSet(idx.getTypeState().maxOrdinal()+1);
                this.excludedOrdinals.put(idx.getTypeState(), excludedOrdinals);
            }

            excludedOrdinals.set(excludeOrdinal);
        }
    }

public void excludeKey ( HollowPrimaryKeyIndex idx , Object ... key ) { int excludeOrdinal = idx . getMatchingOrdinal ( key ) ; if ( excludeOrdinal >= 0 ) { BitSet excludedOrdinals = this . excludedOrdinals . get ( idx . getTypeState ( ) ) ; if ( excludedOrdinals == null ) { excludedOrdinals = new BitSet ( idx . getTypeState ( ) . maxOrdinal ( ) + 1 ) ; this . excludedOrdinals . put ( idx . getTypeState ( ) , excludedOrdinals ) ; } excludedOrdinals . set ( excludeOrdinal ) ; } }

Exclude the record which matches the specified key.

@param idx the index in which to query for the key
@param key the key

Exclude the record which matches the specified key .


public void excludeReferencedObjects() {
        Set<HollowReadStateEngine> stateEngines = new HashSet<HollowReadStateEngine>();
        for(Map.Entry<HollowTypeReadState, BitSet> entry : excludedOrdinals.entrySet())
            stateEngines.add(entry.getKey().getStateEngine());

        for(HollowReadStateEngine stateEngine : stateEngines) {
            Map<String, BitSet> typeBitSetsForStateEngine = new HashMap<String, BitSet>();

            for(Map.Entry<HollowTypeReadState, BitSet> entry : excludedOrdinals.entrySet()) {
                if(entry.getKey().getStateEngine() == stateEngine) {
                    String type = entry.getKey().getSchema().getName();
                    typeBitSetsForStateEngine.put(type, BitSet.valueOf(entry.getValue().toLongArray()));
                }
            }

            TransitiveSetTraverser.addTransitiveMatches(stateEngine, typeBitSetsForStateEngine);

            for(Map.Entry<String, BitSet> entry : typeBitSetsForStateEngine.entrySet())
                excludedOrdinals.put(stateEngine.getTypeState(entry.getKey()), entry.getValue());
        }
    }

public void excludeReferencedObjects ( ) { Set < HollowReadStateEngine > stateEngines = new HashSet < HollowReadStateEngine > ( ) ; for ( Map . Entry < HollowTypeReadState , BitSet > entry : excludedOrdinals . entrySet ( ) ) stateEngines . ( entry . getKey ( ) . getStateEngine ( ) ) ; for ( HollowReadStateEngine stateEngine : stateEngines ) { Map < String , BitSet > typeBitSetsForStateEngine = new HashMap < String , BitSet > ( ) ; for ( Map . Entry < HollowTypeReadState , BitSet > entry : excludedOrdinals . entrySet ( ) ) { if ( entry . getKey ( ) . getStateEngine ( ) == stateEngine ) { String type = entry . getKey ( ) . getSchema ( ) . getName ( ) ; typeBitSetsForStateEngine . put ( type , BitSet . valueOf ( entry . getValue ( ) . toLongArray ( ) ) ) ; } } TransitiveSetTraverser . addTransitiveMatches ( stateEngine , typeBitSetsForStateEngine ) ; for ( Map . Entry < String , BitSet > entry : typeBitSetsForStateEngine . entrySet ( ) ) excludedOrdinals . put ( stateEngine . getTypeState ( entry . getKey ( ) ) , entry . getValue ( ) ) ; } }

Exclude any objects which are referenced by excluded objects.

Exclude any objects which are referenced by excluded objects .


public void writeHeader(HollowBlobHeader header, DataOutputStream dos) throws IOException {
        /// save 4 bytes to indicate FastBlob version header.  This will be changed to indicate backwards incompatibility.
        dos.writeInt(HollowBlobHeader.HOLLOW_BLOB_VERSION_HEADER);

        /// Write randomized tag data -- every state gets a random 64-bit tag.
        /// When attempting to apply a delta, the originating state's random 64-bit tag is compared against the current 64-bit tag.
        /// This prevents deltas from being applied to incorrect states.
        dos.writeLong(header.getOriginRandomizedTag());
        dos.writeLong(header.getDestinationRandomizedTag());

        /// write the schemas contained in this blob to the stream in the pre v2.2.0 backwards compatibility envelope
        ByteArrayOutputStream schemasStream = new ByteArrayOutputStream();
        VarInt.writeVInt(schemasStream, header.getSchemas().size());
        for(HollowSchema schema : header.getSchemas())
            schema.writeTo(schemasStream);
        byte[] schemasData = schemasStream.toByteArray();

        VarInt.writeVInt(dos, schemasData.length + 1); // plus one byte for new backwards compatibility envelope.
        dos.write(schemasData);

        ///backwards compatibility -- new data can be added here by first indicating number of bytes used, will be skipped by existing readers.
        VarInt.writeVInt(dos, 0);

        /// write the header tags -- intended to include input source data versions
        dos.writeShort(header.getHeaderTags().size());

        for (Map.Entry<String, String> headerTag : header.getHeaderTags().entrySet()) {
            dos.writeUTF(headerTag.getKey());
            dos.writeUTF(headerTag.getValue());
        }
    }

Write the header to the data output stream
@param header the blob header
@param dos the data output stream to write the blov header
@throws IOException if the blob header could not be written


void calculateTypeMetrics(HollowReadStateEngine hollowReadStateEngine) {
        Collection<HollowTypeReadState> typeStates = hollowReadStateEngine.getTypeStates();
        if (typeStates == null)
            return;

        totalHeapFootprint = 0L;
        totalPopulatedOrdinals = 0;
        for (HollowTypeReadState typeState : typeStates) {
            long heapCost = typeState.getApproximateHeapFootprintInBytes();
            totalHeapFootprint += heapCost;

            int populatedOrdinals = typeState.getPopulatedOrdinals().cardinality();
            totalPopulatedOrdinals += populatedOrdinals;
            String type = typeState.getSchema().getName();
            typeHeapFootprint.put(type, heapCost);
            typePopulatedOrdinals.put(type, populatedOrdinals);
        }
    }

void calculateTypeMetrics ( HollowReadStateEngine hollowReadStateEngine ) { Collection < HollowTypeReadState > typeStates = hollowReadStateEngine . getTypeStates ( ) ; if ( typeStates == null ) return ; totalHeapFootprint = 0L ; totalPopulatedOrdinals = 0 ; for ( HollowTypeReadState typeState : typeStates ) { long heapCost = typeState . getApproximateHeapFootprintInBytes ( ) ; totalHeapFootprint += heapCost ; int populatedOrdinals = typeState . getPopulatedOrdinals ( ) . cardinality ( ) ; totalPopulatedOrdinals += populatedOrdinals ; String type = typeState . getSchema ( ) . getName ( ) ; typeHeapFootprint . put ( type , heapCost ) ; typePopulatedOrdinals . put ( type , populatedOrdinals ) ; } }

Calculates the memory heap footprint and populated ordinals per type and total
@param hollowReadStateEngine


public void writeDataTo(ByteDataBuffer buf) {
        for (int i = 0; i < fieldData.length; i++) {
            writeField(buf, i);
        }
    }

public void writeDataTo ( ByteDataBuffer buf ) { for ( int i = 0 ; i < fieldData . length ; i ++ ) { writeField ( buf , i ) ; } }

Concatenates all fields, in order, to the ByteDataBuffer supplied.  This concatenation is the
verbatim serialized representation in the FastBlob.

@param buf the data buffer to write data to

Concatenates all fields in order to the ByteDataBuffer supplied . This concatenation is the verbatim serialized representation in the FastBlob .


private static void writeFixedLengthInt(ByteDataBuffer fieldBuffer, int intBits) {
        fieldBuffer.write((byte) (intBits >>> 24));
        fieldBuffer.write((byte) (intBits >>> 16));
        fieldBuffer.write((byte) (intBits >>> 8));
        fieldBuffer.write((byte) (intBits));
    }

private static void writeFixedLengthInt ( ByteDataBuffer fieldBuffer , int intBits ) { fieldBuffer . write ( ( byte ) ( intBits >>> 24 ) ) ; fieldBuffer . write ( ( byte ) ( intBits >>> 16 ) ) ; fieldBuffer . write ( ( byte ) ( intBits >>> 8 ) ) ; fieldBuffer . write ( ( byte ) ( intBits ) ) ; }


private static void writeFixedLengthLong(ByteDataBuffer fieldBuffer, long intBits) {
        fieldBuffer.write((byte) (intBits >>> 56));
        fieldBuffer.write((byte) (intBits >>> 48));
        fieldBuffer.write((byte) (intBits >>> 40));
        fieldBuffer.write((byte) (intBits >>> 32));
        fieldBuffer.write((byte) (intBits >>> 24));
        fieldBuffer.write((byte) (intBits >>> 16));
        fieldBuffer.write((byte) (intBits >>> 8));
        fieldBuffer.write((byte) (intBits));
    }

private static void writeFixedLengthLong ( ByteDataBuffer fieldBuffer , long intBits ) { fieldBuffer . write ( ( byte ) ( intBits >>> 56 ) ) ; fieldBuffer . write ( ( byte ) ( intBits >>> 48 ) ) ; fieldBuffer . write ( ( byte ) ( intBits >>> 40 ) ) ; fieldBuffer . write ( ( byte ) ( intBits >>> 32 ) ) ; fieldBuffer . write ( ( byte ) ( intBits >>> 24 ) ) ; fieldBuffer . write ( ( byte ) ( intBits >>> 16 ) ) ; fieldBuffer . write ( ( byte ) ( intBits >>> 8 ) ) ; fieldBuffer . write ( ( byte ) ( intBits ) ) ; }


public void returnOrdinalToPool(int ordinal) {
        if(size == freeOrdinals.length) {
            freeOrdinals = Arrays.copyOf(freeOrdinals, freeOrdinals.length * 3 / 2);
        }

        freeOrdinals[size] = ordinal;
        size++;
    }

public void returnOrdinalToPool ( int ordinal ) { if ( size == freeOrdinals . length ) { freeOrdinals = Arrays . copyOf ( freeOrdinals , freeOrdinals . length * 3 / 2 ) ; } freeOrdinals [ size ] = ordinal ; size ++ ; }

Return an ordinal to the pool after the object to which it was assigned is discarded.

@param ordinal the ordinal

Return an ordinal to the pool after the object to which it was assigned is discarded .


public void sort() {
        Arrays.sort(freeOrdinals, 0, size);

        /// reverse the ordering
        int midpoint = size / 2;
        for(int i=0;i<midpoint;i++) {
            int temp = freeOrdinals[i];
            freeOrdinals[i] = freeOrdinals[size-i-1];
            freeOrdinals[size-i-1] = temp;
        }
    }

public
void
sort
(
)
{
Arrays
.
sort
(
freeOrdinals
,
0
,
size
)
;
/// reverse the ordering
int
midpoint
=
size
/
2
;
for
(
int
i
=
0
;
i
<
midpoint
;
i
++
)
{
int
temp
=
freeOrdinals
[
i
]
;
freeOrdinals
[
i
]
=
freeOrdinals
[
size
i
1
]
;
freeOrdinals
[
size
i
1
]
=
temp
;
}
}

Ensure that all future ordinals are returned in ascending order.

Ensure that all future ordinals are returned in ascending order .


public static int hash(Object key[], FieldType fieldType[]) {
        int hash = 0;

        for (int i = 0; i < key.length; i++) {
            hash *= 31;
            hash ^= hash(key[i], fieldType[i]);
        }

        return hash;
    }

public static int hash ( Object key [ ] , FieldType fieldType [ ] ) { int hash = 0 ; for ( int i = 0 ; i < key . length ; i ++ ) { hash *= 31 ; hash ^= hash ( key [ i ] , fieldType [ i ] ) ; } return hash ; }

Hash a key

@param key the key
@param fieldType the respective FieldTypes of each key.
@return the hash code


public static int hash(Object key, FieldType fieldType) {
        switch(fieldType) {
        case INT:
            return HashCodes.hashInt(((Integer)key).intValue());
        case LONG:
            long longVal = ((Long)key).longValue();
            return HashCodes.hashInt((int)(longVal ^ (longVal >>> 32)));
        case REFERENCE:
            return HashCodes.hashInt(((Integer)key).intValue());
        case BYTES:
            return HashCodes.hashInt(HashCodes.hashCode((byte[])key));
        case STRING:
            return HashCodes.hashInt(key.hashCode());
        case BOOLEAN:
            return HashCodes.hashInt(((Boolean)key).booleanValue() ? 1231 : 1237);
        case DOUBLE:
            long longBits = Double.doubleToRawLongBits(((Double)key).doubleValue());
            return HashCodes.hashInt((int)(longBits ^ (longBits >>> 32)));
        case FLOAT:
            return HashCodes.hashInt(Float.floatToRawIntBits(((Float)key).floatValue()));
        default:
            throw new IllegalArgumentException("Unknown field type: " + fieldType);
        }
    }

public
static
int
hash
(
Object
key
,
FieldType
fieldType
)
{
switch
(
fieldType
)
{
case
INT
:
return
HashCodes
.
hashInt
(
(
(
Integer
)
key
)
.
intValue
(
)
)
;
case
LONG
:
long
longVal
=
(
(
Long
)
key
)
.
longValue
(
)
;
return
HashCodes
.
hashInt
(
(
int
)
(
longVal
^
(
longVal
>>>
32
)
)
)
;
case
REFERENCE
:
return
HashCodes
.
hashInt
(
(
(
Integer
)
key
)
.
intValue
(
)
)
;
case
BYTES
:
return
HashCodes
.
hashInt
(
HashCodes
.
hashCode
(
(
byte
[
]
)
key
)
)
;
case
STRING
:
return
HashCodes
.
hashInt
(
key
.
hashCode
(
)
)
;
case
BOOLEAN
:
return
HashCodes
.
hashInt
(
(
(
Boolean
)
key
)
.
booleanValue
(
)
1231
:
1237
)
;
case
DOUBLE
:
long
longBits
=
Double
.
doubleToRawLongBits
(
(
(
Double
)
key
)
.
doubleValue
(
)
)
;
return
HashCodes
.
hashInt
(
(
int
)
(
longBits
^
(
longBits
>>>
32
)
)
)
;
case
FLOAT
:
return
HashCodes
.
hashInt
(
Float
.
floatToRawIntBits
(
(
(
Float
)
key
)
.
floatValue
(
)
)
)
;
default
:
throw
new
IllegalArgumentException
(
"Unknown field type: "
+
fieldType
)
;
}
}

Hash a single key field

@param key the key
@param fieldType the FieldType of the key.
@return the hash code


private void resizeStorage() {
        int currentElementsPerNode = maxElementsPerNode;
        int newElementsPerNode = (int) (currentElementsPerNode * RESIZE_MULTIPLE);
        if (newElementsPerNode <= currentElementsPerNode) {
            throw new IllegalStateException("cannot resize fixed length array from "
                    + currentElementsPerNode + " to " + newElementsPerNode);
        }
        FixedLengthElementArray newStorage = new FixedLengthElementArray(memoryRecycler,
                numNodes * bitsPerElement * newElementsPerNode);
        LongStream.range(0, numNodes).forEach(nodeIndex -> {
            long currentBucketStart = nodeIndex * currentElementsPerNode * bitsPerElement;
            long newBucketStart = nodeIndex * newElementsPerNode * bitsPerElement;
            for (int offset = 0; offset < currentElementsPerNode; offset++) {
                long element = storage.getElementValue(currentBucketStart + offset * bitsPerElement,
                        bitsPerElement, elementMask);
                if (element == NO_ELEMENT) {
                    break; // we have exhausted the elements at this index
                }
                newStorage.setElementValue(
                        newBucketStart + offset * bitsPerElement, bitsPerElement, element);
            }
        });
        storage.destroy(memoryRecycler);
        storage = newStorage;
        maxElementsPerNode = newElementsPerNode;
    }

Resize the underlying storage to a multiple of what it currently is. This method is not
thread-safe.

Resize the underlying storage to a multiple of what it currently is . This method is not thread - safe .


private int findFreeOrdinal(int preferredOrdinal) {
        if (preferredOrdinal != -1 && unusedPreviousOrdinals.get(preferredOrdinal)) {
            unusedPreviousOrdinals.clear(preferredOrdinal);
            return preferredOrdinal;
        }

        return freeOrdinalTracker.getFreeOrdinal();
    }

private int findFreeOrdinal ( int preferredOrdinal ) { if ( preferredOrdinal != - 1 && unusedPreviousOrdinals . get ( preferredOrdinal ) ) { unusedPreviousOrdinals . clear ( preferredOrdinal ) ; return preferredOrdinal ; } return freeOrdinalTracker . getFreeOrdinal ( ) ; }

If the preferredOrdinal has not already been used, mark it and use it.  Otherwise,
delegate to the FreeOrdinalTracker.

If the preferredOrdinal has not already been used mark it and use it . Otherwise delegate to the FreeOrdinalTracker .


public void prepareForWrite() {
        int maxOrdinal = 0;
        AtomicLongArray pao = pointersAndOrdinals;

        for (int i = 0; i < pao.length(); i++) {
            long key = pao.get(i);
            if (key != EMPTY_BUCKET_VALUE) {
                int ordinal = (int) (key >>> BITS_PER_POINTER);
                if (ordinal > maxOrdinal) {
                    maxOrdinal = ordinal;
                }
            }
        }

        long[] pbo = new long[maxOrdinal + 1];
        Arrays.fill(pbo, -1);

        for (int i = 0; i < pao.length(); i++) {
            long key = pao.get(i);
            if (key != EMPTY_BUCKET_VALUE) {
                int ordinal = (int) (key >>> BITS_PER_POINTER);
                pbo[ordinal] = key & POINTER_MASK;
            }
        }

        pointersByOrdinal = pbo;
    }

public void prepareForWrite ( ) { int maxOrdinal = 0 ; AtomicLongArray pao = pointersAndOrdinals ; for ( int i = 0 ; i < pao . length ( ) ; i ++ ) { long key = pao . get ( i ) ; if ( key != EMPTY_BUCKET_VALUE ) { int ordinal = ( int ) ( key >>> BITS_PER_POINTER ) ; if ( ordinal > maxOrdinal ) { maxOrdinal = ordinal ; } } } long [ ] pbo = new long [ maxOrdinal + 1 ] ; Arrays . fill ( pbo , - 1 ) ; for ( int i = 0 ; i < pao . length ( ) ; i ++ ) { long key = pao . get ( i ) ; if ( key != EMPTY_BUCKET_VALUE ) { int ordinal = ( int ) ( key >>> BITS_PER_POINTER ) ; pbo [ ordinal ] = key & POINTER_MASK ; } } pointersByOrdinal = pbo ; }

Create an array mapping the ordinals to pointers, so that they can be easily looked up
when writing to blob streams.

Create an array mapping the ordinals to pointers so that they can be easily looked up when writing to blob streams .


private boolean compare(ByteDataBuffer serializedRepresentation, long key) {
        long position = key & POINTER_MASK;

        int sizeOfData = VarInt.readVInt(byteData.getUnderlyingArray(), position);

        if (sizeOfData != serializedRepresentation.length()) {
            return false;
        }

        position += VarInt.sizeOfVInt(sizeOfData);

        for (int i = 0; i < sizeOfData; i++) {
            if (serializedRepresentation.get(i) != byteData.get(position++)) {
                return false;
            }
        }

        return true;
    }

private boolean compare ( ByteDataBuffer serializedRepresentation , long key ) { long position = key & POINTER_MASK ; int sizeOfData = VarInt . readVInt ( byteData . getUnderlyingArray ( ) , position ) ; if ( sizeOfData != serializedRepresentation . length ( ) ) { return false ; } position += VarInt . sizeOfVInt ( sizeOfData ) ; for ( int i = 0 ; i < sizeOfData ; i ++ ) { if ( serializedRepresentation . get ( i ) != byteData . get ( position ++ ) ) { return false ; } } return true ; }

Compare the byte sequence contained in the supplied ByteDataBuffer with the
sequence contained in the map pointed to by the specified key, byte by byte.

Compare the byte sequence contained in the supplied ByteDataBuffer with the sequence contained in the map pointed to by the specified key byte by byte .


private void growKeyArray() {
        int newSize = pointersAndOrdinals.length() << 1;
        if (newSize < 0) {
            throw new IllegalStateException("New size computed to grow the underlying array for the map is negative. " +
                    "This is most likely due to the total number of keys added to map has exceeded the max capacity of the keys map can hold. "
                    +
                    "Current array size :" + pointersAndOrdinals.length() + " and size to grow :" + newSize);
        }
        growKeyArray(newSize);
    }

Grow the key array.  All of the values in the current array must be re-hashed and added to the new array.

Grow the key array . All of the values in the current array must be re - hashed and added to the new array .


private int rehashPreviouslyAddedData(long key) {
        long position = key & POINTER_MASK;

        int sizeOfData = VarInt.readVInt(byteData.getUnderlyingArray(), position);
        position += VarInt.sizeOfVInt(sizeOfData);

        return HashCodes.hashCode(byteData.getUnderlyingArray(), position, sizeOfData);
    }

private int rehashPreviouslyAddedData ( long key ) { long position = key & POINTER_MASK ; int sizeOfData = VarInt . readVInt ( byteData . getUnderlyingArray ( ) , position ) ; position += VarInt . sizeOfVInt ( sizeOfData ) ; return HashCodes . hashCode ( byteData . getUnderlyingArray ( ) , position , sizeOfData ) ; }

Get the hash code for the byte array pointed to by the specified key.

Get the hash code for the byte array pointed to by the specified key .


private AtomicLongArray emptyKeyArray(int size) {
        AtomicLongArray arr = new AtomicLongArray(size);
        // Volatile store not required, could use plain store
        // See VarHandles for JDK >= 9
        for (int i = 0; i < arr.length(); i++) {
            arr.lazySet(i, EMPTY_BUCKET_VALUE);
        }
        return arr;
    }

Create an AtomicLongArray of the specified size, each value in the array will be EMPTY_BUCKET_VALUE

Create an AtomicLongArray of the specified size each value in the array will be EMPTY_BUCKET_VALUE


public boolean isMatchEqual(int matchIdx, HollowIndexerValueTraverser otherTraverser, int otherMatchIdx) {
        for(int i=0;i<getNumFieldPaths();i++) {
            if(!HollowReadFieldUtils.fieldsAreEqual((HollowObjectTypeDataAccess)fieldTypeDataAccess[i], fieldMatchLists[i].get(matchIdx), fieldSchemaPosition[i],
                    (HollowObjectTypeDataAccess)otherTraverser.fieldTypeDataAccess[i], otherTraverser.fieldMatchLists[i].get(otherMatchIdx), otherTraverser.fieldSchemaPosition[i]))
                return false;
        }
        return true;
    }

public boolean isMatchEqual ( int matchIdx , HollowIndexerValueTraverser otherTraverser , int otherMatchIdx ) { for ( int i = 0 ; i < getNumFieldPaths ( ) ; i ++ ) { if ( ! HollowReadFieldUtils . fieldsAreEqual ( ( HollowObjectTypeDataAccess ) fieldTypeDataAccess [ i ] , fieldMatchLists [ i ] . get ( matchIdx ) , fieldSchemaPosition [ i ] , ( HollowObjectTypeDataAccess ) otherTraverser . fieldTypeDataAccess [ i ] , otherTraverser . fieldMatchLists [ i ] . get ( otherMatchIdx ) , otherTraverser . fieldSchemaPosition [ i ] ) ) return false ; } return true ; }

This method assumes the other traverser has the same match fields specified in the same order.

@param matchIdx the match index
@param otherTraverser the other traverser
@param otherMatchIdx the other match index
@return true if this and the other traverser are equal

This method assumes the other traverser has the same match fields specified in the same order .


public T findMatch(Q key) {
        Object[] keyArray = matchFields.stream().map(mf -> mf.extract(key)).toArray();

        int ordinal = hpki.getMatchingOrdinal(keyArray);
        if (ordinal == -1) {
            return null;
        }

        return uniqueTypeExtractor.extract(api, ordinal);
    }

public T findMatch ( Q key ) { Object [ ] keyArray = matchFields . stream ( ) . map ( mf -> mf . extract ( key ) ) . toArray ( ) ; int ordinal = hpki . getMatchingOrdinal ( keyArray ) ; if ( ordinal == - 1 ) { return null ; } return uniqueTypeExtractor . extract ( api , ordinal ) ; }

Finds the unique object, an instance of the unique type, for a given key.

@param key the key
@return the unique object

Finds the unique object an instance of the unique type for a given key .


ReadStateHelper swap() {
        return new ReadStateHelper(newReadState(current.getVersion(), pending.getStateEngine()),
                newReadState(pending.getVersion(), current.getStateEngine()));
    }

ReadStateHelper swap ( ) { return new ReadStateHelper ( newReadState ( current . getVersion ( ) , pending . getStateEngine ( ) ) , newReadState ( pending . getVersion ( ) , current . getStateEngine ( ) ) ) ; }

Swap underlying state engines between current and pending while keeping the versions consistent;
used after delta integrity checks have altered the underlying state engines.

@return

Swap underlying state engines between current and pending while keeping the versions consistent ; used after delta integrity checks have altered the underlying state engines .


public static int hashTableSize(int numElements) throws IllegalArgumentException {
        if (numElements < 0) {
            throw new IllegalArgumentException("cannot be negative; numElements="+numElements);
        } else if (numElements > HASH_TABLE_MAX_SIZE) {
            throw new IllegalArgumentException("exceeds maximum number of buckets; numElements="+numElements);
        }

        if (numElements == 0)
            return 1;
        if (numElements < 3)
            return numElements * 2;

        // Apply load factor to number of elements and determine next
        // largest power of 2 that fits in an int
        int sizeAfterLoadFactor = (int)((long)numElements * 10 / 7);
        int bits = 32 - Integer.numberOfLeadingZeros(sizeAfterLoadFactor - 1);
        return 1 << bits;
    }

Determine size of hash table capable of storing the specified number of elements with a load
factor applied.

@param numElements number of elements to be stored in the table
@return size of hash table, always a power of 2
@throws IllegalArgumentException when numElements is negative or exceeds
{@link com.netflix.hollow.core.HollowConstants#HASH_TABLE_MAX_SIZE}

Determine size of hash table capable of storing the specified number of elements with a load factor applied .


public long runCompactionCycle(HollowCompactor.CompactionConfig config) {
        if (config != null && readStates.hasCurrent()) {
            final HollowCompactor compactor = new HollowCompactor(getWriteEngine(),
                    readStates.current().getStateEngine(), config);
            if (compactor.needsCompaction()) {
                return runCycle(newState -> compactor.compact());
            }
        }

        return NO_ANNOUNCEMENT_AVAILABLE;
    }

public long runCompactionCycle ( HollowCompactor . CompactionConfig config ) { if ( config != null && readStates . hasCurrent ( ) ) { final HollowCompactor compactor = new HollowCompactor ( getWriteEngine ( ) , readStates . current ( ) . getStateEngine ( ) , config ) ; if ( compactor . needsCompaction ( ) ) { return runCycle ( newState -> compactor . compact ( ) ) ; } } return NO_ANNOUNCEMENT_AVAILABLE ; }

Run a compaction cycle, will produce a data state with exactly the same data as currently, but
reorganized so that ordinal holes are filled.  This may need to be run multiple times to arrive
at an optimal state.

@param config specifies what criteria to use to determine whether a compaction is necessary
@return the version identifier of the produced state, or AnnouncementWatcher.NO_ANNOUNCEMENT_AVAILABLE if compaction was unnecessary.

Run a compaction cycle will produce a data state with exactly the same data as currently but reorganized so that ordinal holes are filled . This may need to be run multiple times to arrive at an optimal state .


public void writeSnapshot(OutputStream os) throws IOException {
        stateEngine.prepareForWrite();

        DataOutputStream dos = new DataOutputStream(os);
        writeHeader(dos, stateEngine.getSchemas(), false);

        VarInt.writeVInt(dos, stateEngine.getOrderedTypeStates().size());

        SimultaneousExecutor executor = new SimultaneousExecutor(getClass(), "write-snapshot");

        for(final HollowTypeWriteState typeState : stateEngine.getOrderedTypeStates()) {
            executor.execute(new Runnable() {
                public void run() {
                    typeState.calculateSnapshot();
                }
            });
        }

        try {
            executor.awaitSuccessfulCompletion();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        for(HollowTypeWriteState typeState : stateEngine.getOrderedTypeStates()) {
            HollowSchema schema = typeState.getSchema();
            schema.writeTo(dos);

            writeNumShards(dos, typeState.getNumShards());

            typeState.writeSnapshot(dos);
        }
        os.flush();
    }

public void writeSnapshot ( OutputStream os ) throws IOException { stateEngine . prepareForWrite ( ) ; DataOutputStream dos = new DataOutputStream ( os ) ; writeHeader ( dos , stateEngine . getSchemas ( ) , false ) ; VarInt . writeVInt ( dos , stateEngine . getOrderedTypeStates ( ) . size ( ) ) ; SimultaneousExecutor executor = new SimultaneousExecutor ( getClass ( ) , "write-snapshot" ) ; for ( final HollowTypeWriteState typeState : stateEngine . getOrderedTypeStates ( ) ) { executor . execute ( new Runnable ( ) { public void run ( ) { typeState . calculateSnapshot ( ) ; } } ) ; } try { executor . awaitSuccessfulCompletion ( ) ; } catch ( Exception e ) { throw new RuntimeException ( e ) ; } for ( HollowTypeWriteState typeState : stateEngine . getOrderedTypeStates ( ) ) { HollowSchema schema = typeState . getSchema ( ) ; schema . writeTo ( dos ) ; writeNumShards ( dos , typeState . getNumShards ( ) ) ; typeState . writeSnapshot ( dos ) ; } os . flush ( ) ; }

Write the current state as a snapshot blob.
@param os the output stream to write the snapshot blob
@throws IOException if the snapshot blob could not be written

Write the current state as a snapshot blob .


public void writeDelta(OutputStream os) throws IOException {
        stateEngine.prepareForWrite();

        if(stateEngine.isRestored())
            stateEngine.ensureAllNecessaryStatesRestored();

        List<HollowSchema> changedTypes = changedTypes();

        DataOutputStream dos = new DataOutputStream(os);
        writeHeader(dos, changedTypes, false);

        VarInt.writeVInt(dos, changedTypes.size());

        SimultaneousExecutor executor = new SimultaneousExecutor(getClass(), "write-delta");

        for(final HollowTypeWriteState typeState : stateEngine.getOrderedTypeStates()) {
            executor.execute(new Runnable() {
                public void run() {
                    if(typeState.hasChangedSinceLastCycle())
                        typeState.calculateDelta();
                }
            });
        }

        try {
            executor.awaitSuccessfulCompletion();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        for(HollowTypeWriteState typeState : stateEngine.getOrderedTypeStates()) {
            if(typeState.hasChangedSinceLastCycle()) {
                HollowSchema schema = typeState.getSchema();
                schema.writeTo(dos);

                writeNumShards(dos, typeState.getNumShards());

                typeState.writeDelta(dos);
            }
        }
        os.flush();
    }

public void writeDelta ( OutputStream os ) throws IOException { stateEngine . prepareForWrite ( ) ; if ( stateEngine . isRestored ( ) ) stateEngine . ensureAllNecessaryStatesRestored ( ) ; List < HollowSchema > changedTypes = changedTypes ( ) ; DataOutputStream dos = new DataOutputStream ( os ) ; writeHeader ( dos , changedTypes , false ) ; VarInt . writeVInt ( dos , changedTypes . size ( ) ) ; SimultaneousExecutor executor = new SimultaneousExecutor ( getClass ( ) , "write-delta" ) ; for ( final HollowTypeWriteState typeState : stateEngine . getOrderedTypeStates ( ) ) { executor . execute ( new Runnable ( ) { public void run ( ) { if ( typeState . hasChangedSinceLastCycle ( ) ) typeState . calculateDelta ( ) ; } } ) ; } try { executor . awaitSuccessfulCompletion ( ) ; } catch ( Exception e ) { throw new RuntimeException ( e ) ; } for ( HollowTypeWriteState typeState : stateEngine . getOrderedTypeStates ( ) ) { if ( typeState . hasChangedSinceLastCycle ( ) ) { HollowSchema schema = typeState . getSchema ( ) ; schema . writeTo ( dos ) ; writeNumShards ( dos , typeState . getNumShards ( ) ) ; typeState . writeDelta ( dos ) ; } } os . flush ( ) ; }

Serialize the changes necessary to transition a consumer from the previous state
to the current state as a delta blob.

@param os the output stream to write the delta blob
@throws IOException if the delta blob could not be written
@throws IllegalStateException if the current state is restored from the previous state
and current state contains unrestored state for one or more types.  This indicates those
types have not been declared to the producer as part it's initialized data model.
@see com.netflix.hollow.api.producer.HollowProducer#initializeDataModel(Class[])

Serialize the changes necessary to transition a consumer from the previous state to the current state as a delta blob .


private void addToSetIfNotPrimitiveOrCollection(Set<String> schemaNameSet, String... schemaNames) {
        for (String schemaName : schemaNames) {
            // collections schemas get brought in by a star import
            if (!HollowCodeGenerationUtils.isCollectionType(schemaName, dataset) &&
                    !HollowCodeGenerationUtils.isPrimitiveType(schemaName)) {
                schemaNameSet.add(schemaName);
            }
        }
    }

Adds the schema name to the set if the schema name doesn't correspond to a Hollow
primitive type. Factored out to prevent bloat in the switch statement it is called
from.

Adds the schema name to the set if the schema name doesn t correspond to a Hollow primitive type . Factored out to prevent bloat in the switch statement it is called from .


public static String normalizeFieldPathToParamName(String fieldPath) {
        String result = null;
        if (fieldPath.contains(".")) {
            String[] parts = fieldPath.split("\\.");
            StringBuilder sb = new StringBuilder();
            sb.append(lowercase(parts[0]));
            for (int i = 1; i < parts.length; i++) {
                sb.append(uppercase(parts[i]));
            }
            result = sb.toString();
        } else {
            result = lowercase(fieldPath);
        }

        if (result.endsWith("!")) {
            return result.substring(0, result.length() - 1);
        }
        return result;
    }

public static String normalizeFieldPathToParamName ( String fieldPath ) { String result = null ; if ( fieldPath . contains ( "." ) ) { String [ ] parts = fieldPath . split ( "\\." ) ; StringBuilder sb = new StringBuilder ( ) ; sb . append ( lowercase ( parts [ 0 ] ) ) ; for ( int i = 1 ; i < parts . length ; i ++ ) { sb . append ( uppercase ( parts [ i ] ) ) ; } result = sb . toString ( ) ; } else { result = lowercase ( fieldPath ) ; } if ( result . endsWith ( "!" ) ) { return result . substring ( 0 , result . length ( ) - 1 ) ; } return result ; }

Convert field path into Param name

Eg:
- Actor {@literal->} actor
- Actor.name {@literal->} actorName

@param fieldPath the field path
@return the param name


private void reindexHashIndex() {
        HollowHashIndexBuilder builder = new HollowHashIndexBuilder(stateEngine, type, selectField, matchFields);

        builder.buildIndex();

        this.hashStateVolatile = new HollowHashIndexState(builder);
    }

private void reindexHashIndex ( ) { HollowHashIndexBuilder builder = new HollowHashIndexBuilder ( stateEngine , type , selectField , matchFields ) ; builder . buildIndex ( ) ; this . hashStateVolatile = new HollowHashIndexState ( builder ) ; }


public HollowHashIndexResult findMatches(Object... query) {
        int hashCode = 0;

        for(int i=0;i<query.length;i++) {
            if(query[i] == null)
                throw new IllegalArgumentException("querying by null unsupported; i=" + i);
            hashCode ^= HashCodes.hashInt(keyHashCode(query[i], i));
        }

        HollowHashIndexResult result;
        HollowHashIndexState hashState;
        do {
            result = null;
            hashState = hashStateVolatile;
            long bucket = hashCode & hashState.getMatchHashMask();
            long hashBucketBit = bucket * hashState.getBitsPerMatchHashEntry();
            boolean bucketIsEmpty = hashState.getMatchHashTable().getElementValue(hashBucketBit, hashState.getBitsPerTraverserField()[0]) == 0;

            while (!bucketIsEmpty) {
                if (matchIsEqual(hashState.getMatchHashTable(), hashBucketBit, query)) {
                    int selectSize = (int) hashState.getMatchHashTable().getElementValue(hashBucketBit + hashState.getBitsPerMatchHashKey(), hashState.getBitsPerSelectTableSize());
                    long selectBucketPointer = hashState.getMatchHashTable().getElementValue(hashBucketBit + hashState.getBitsPerMatchHashKey() + hashState.getBitsPerSelectTableSize(), hashState.getBitsPerSelectTablePointer());

                    result = new HollowHashIndexResult(hashState, selectBucketPointer, selectSize);
                    break;
                }

                bucket = (bucket + 1) & hashState.getMatchHashMask();
                hashBucketBit = bucket * hashState.getBitsPerMatchHashEntry();
                bucketIsEmpty = hashState.getMatchHashTable().getElementValue(hashBucketBit, hashState.getBitsPerTraverserField()[0]) == 0;
            }
        } while (hashState != hashStateVolatile);

        return result;
    }

public
HollowHashIndexResult
findMatches
(
Object
...
query
)
{
int
hashCode
=
0
;
for
(
int
i
=
0
;
i
<
query
.
length
;
i
++
)
{
if
(
query
[
i
]
==
)
throw
new
IllegalArgumentException
(
"querying by null unsupported; i="
+
i
)
;
hashCode
^=
HashCodes
.
hashInt
(
keyHashCode
(
query
[
i
]
,
i
)
)
;
}
HollowHashIndexResult
result
;
HollowHashIndexState
hashState
;
do
{
result
=
;
hashState
=
hashStateVolatile
;
long
bucket
=
hashCode
&
hashState
.
getMatchHashMask
(
)
;
long
hashBucketBit
=
bucket
*
hashState
.
getBitsPerMatchHashEntry
(
)
;
boolean
bucketIsEmpty
=
hashState
.
getMatchHashTable
(
)
.
getElementValue
(
hashBucketBit
,
hashState
.
getBitsPerTraverserField
(
)
[
0
]
)
==
0
;
while
(
!
bucketIsEmpty
)
{
if
(
matchIsEqual
(
hashState
.
getMatchHashTable
(
)
,
hashBucketBit
,
query
)
)
{
int
selectSize
=
(
int
)
hashState
.
getMatchHashTable
(
)
.
getElementValue
(
hashBucketBit
+
hashState
.
getBitsPerMatchHashKey
(
)
,
hashState
.
getBitsPerSelectTableSize
(
)
)
;
long
selectBucketPointer
=
hashState
.
getMatchHashTable
(
)
.
getElementValue
(
hashBucketBit
+
hashState
.
getBitsPerMatchHashKey
(
)
+
hashState
.
getBitsPerSelectTableSize
(
)
,
hashState
.
getBitsPerSelectTablePointer
(
)
)
;
result
=
new
HollowHashIndexResult
(
hashState
,
selectBucketPointer
,
selectSize
)
;
break
;
}
bucket
=
(
bucket
+
1
)
&
hashState
.
getMatchHashMask
(
)
;
hashBucketBit
=
bucket
*
hashState
.
getBitsPerMatchHashEntry
(
)
;
bucketIsEmpty
=
hashState
.
getMatchHashTable
(
)
.
getElementValue
(
hashBucketBit
,
hashState
.
getBitsPerTraverserField
(
)
[
0
]
)
==
0
;
}
}
while
(
hashState
!=
hashStateVolatile
)
;
return
result
;
}

Query the index.

@param query the query
@return the hash index result to gather the matched ordinals. A {@code null} value indicated no matches were
found.


public void triggerAsyncRefreshWithRandomDelay(int maxDelayMillis) {
        Random rand = new Random();
        int delayMillis = maxDelayMillis > 0 ? rand.nextInt(maxDelayMillis) : 0;
        triggerAsyncRefreshWithDelay(delayMillis);
    }

public void triggerAsyncRefreshWithRandomDelay ( int maxDelayMillis ) { Random rand = new Random ( ) ; int delayMillis = maxDelayMillis > 0 ? rand . nextInt ( maxDelayMillis ) : 0 ; triggerAsyncRefreshWithDelay ( delayMillis ) ; }

Triggers async refresh after some random number of milliseconds have passed,
between now and the specified maximum number of milliseconds.

Any subsequent calls for async refresh will not begin until after the specified delay
has completed.

@param maxDelayMillis the maximum delay in milliseconds

Triggers async refresh after some random number of milliseconds have passed between now and the specified maximum number of milliseconds .


public void triggerAsyncRefreshWithDelay(int delayMillis) {
        final HollowClient client = this.client;
        final long targetBeginTime = System.currentTimeMillis() + delayMillis;

        refreshExecutor.execute(new Runnable() {
            public void run() {
                try {
                    long delay = targetBeginTime - System.currentTimeMillis();
                    if(delay > 0)
                        Thread.sleep(delay);
                    client.triggerRefresh();
                } catch(Throwable th) {
                    log.log(Level.SEVERE, "Async refresh failed", th);
                }
            }
        });
    }

public
void
triggerAsyncRefreshWithDelay
(
int
delayMillis
)
{
final
HollowClient
client
=
this
.
client
;
final
long
targetBeginTime
=
System
.
currentTimeMillis
(
)
+
delayMillis
;
refreshExecutor
.
execute
(
new
Runnable
(
)
{
public
void
run
(
)
{
try
{
long
delay
=
targetBeginTime
System
.
currentTimeMillis
(
)
;
if
(
delay
>
0
)
Thread
.
sleep
(
delay
)
;
client
.
triggerRefresh
(
)
;
}
catch
(
Throwable
th
)
{
log
.
log
(
Level
.
SEVERE
,
"Async refresh failed"
,
th
)
;
}
}
}
)
;
}

Triggers async refresh after the specified number of milliseconds has passed.

Any subsequent calls for async refresh will not begin until after the specified delay
has completed.

@param delayMillis the delay in milliseconds

Triggers async refresh after the specified number of milliseconds has passed .


public HollowTypeDiff addTypeDiff(String type, String... primaryKeyPaths) {
        HollowTypeDiff typeDiff = new HollowTypeDiff(this, type, primaryKeyPaths);
        if(typeDiff.hasAnyData())
            typeDiffs.put(type, typeDiff);
        return typeDiff;
    }

public HollowTypeDiff addTypeDiff ( String type , String ... primaryKeyPaths ) { HollowTypeDiff typeDiff = new HollowTypeDiff ( this , type , primaryKeyPaths ) ; if ( typeDiff . hasAnyData ( ) ) typeDiffs . put ( type , typeDiff ) ; return typeDiff ; }

Add a type to be included in the diff report

@param type the type name
@param primaryKeyPaths the path(s) to the field(s) which comprise the type's primary key
@return the diff type


public void calculateDiffs() {
        long startTime = System.currentTimeMillis();

        prepareForDiffCalculation();

        long endTime = System.currentTimeMillis();

        log.info("PREPARED IN " + (endTime - startTime) + "ms");

        for(HollowTypeDiff typeDiff : typeDiffs.values()) {
            typeDiff.calculateDiffs();
        }
    }

public
void
calculateDiffs
(
)
{
long
startTime
=
System
.
currentTimeMillis
(
)
;
prepareForDiffCalculation
(
)
;
long
endTime
=
System
.
currentTimeMillis
(
)
;
log
.
info
(
"PREPARED IN "
+
(
endTime
startTime
)
+
"ms"
)
;
for
(
HollowTypeDiff
typeDiff
:
typeDiffs
.
values
(
)
)
{
typeDiff
.
calculateDiffs
(
)
;
}
}


public static void writeVLong(OutputStream out, long value) throws IOException {
        if(value < 0)                                out.write((byte)0x81);
        if(value > 0xFFFFFFFFFFFFFFL || value < 0)   out.write((byte)(0x80 | ((value >>> 56) & 0x7FL)));
        if(value > 0x1FFFFFFFFFFFFL || value < 0)    out.write((byte)(0x80 | ((value >>> 49) & 0x7FL)));
        if(value > 0x3FFFFFFFFFFL || value < 0)      out.write((byte)(0x80 | ((value >>> 42) & 0x7FL)));
        if(value > 0x7FFFFFFFFL || value < 0)        out.write((byte)(0x80 | ((value >>> 35) & 0x7FL)));
        if(value > 0xFFFFFFFL || value < 0)          out.write((byte)(0x80 | ((value >>> 28) & 0x7FL)));
        if(value > 0x1FFFFFL || value < 0)           out.write((byte)(0x80 | ((value >>> 21) & 0x7FL)));
        if(value > 0x3FFFL || value < 0)             out.write((byte)(0x80 | ((value >>> 14) & 0x7FL)));
        if(value > 0x7FL || value < 0)               out.write((byte)(0x80 | ((value >>>  7) & 0x7FL)));

        out.write((byte)(value & 0x7FL));
    }

public static void writeVLong ( OutputStream out , long value ) throws IOException { if ( value < 0 ) out . write ( ( byte ) 0x81 ) ; if ( value > 0xFFFFFFFFFFFFFF L || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 56 ) & 0x7F L ) ) ) ; if ( value > 0x1FFFFFFFFFFFF L || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 49 ) & 0x7F L ) ) ) ; if ( value > 0x3FFFFFFFFFF L || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 42 ) & 0x7F L ) ) ) ; if ( value > 0x7FFFFFFFF L || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 35 ) & 0x7F L ) ) ) ; if ( value > 0xFFFFFFF L || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 28 ) & 0x7F L ) ) ) ; if ( value > 0x1FFFFF L || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 21 ) & 0x7F L ) ) ) ; if ( value > 0x3FFF L || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 14 ) & 0x7F L ) ) ) ; if ( value > 0x7F L || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 7 ) & 0x7F L ) ) ) ; out . write ( ( byte ) ( value & 0x7F L ) ) ; }

Encode the specified long as a variable length integer into the supplied OuputStream

@param out the output stream to write to
@param value the long value
@throws IOException if the value cannot be written to the output stream


public static void writeVInt(OutputStream out, int value) throws IOException {
        if(value > 0x0FFFFFFF || value < 0) out.write((byte)(0x80 | ((value >>> 28))));
        if(value > 0x1FFFFF || value < 0)   out.write((byte)(0x80 | ((value >>> 21) & 0x7F)));
        if(value > 0x3FFF || value < 0)     out.write((byte)(0x80 | ((value >>> 14) & 0x7F)));
        if(value > 0x7F || value < 0)       out.write((byte)(0x80 | ((value >>>  7) & 0x7F)));

        out.write((byte)(value & 0x7F));
    }

public static void writeVInt ( OutputStream out , int value ) throws IOException { if ( value > 0x0FFFFFFF || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 28 ) ) ) ) ; if ( value > 0x1FFFFF || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 21 ) & 0x7F ) ) ) ; if ( value > 0x3FFF || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 14 ) & 0x7F ) ) ) ; if ( value > 0x7F || value < 0 ) out . write ( ( byte ) ( 0x80 | ( ( value >>> 7 ) & 0x7F ) ) ) ; out . write ( ( byte ) ( value & 0x7F ) ) ; }

Encode the specified int as a variable length integer into the supplied OutputStream

@param out the output stream to write to
@param value the int value
@throws IOException if the value cannot be written to the output stream


public static int writeVInt(byte data[], int pos, int value) {
        if(value > 0x0FFFFFFF || value < 0) data[pos++] = ((byte)(0x80 | ((value >>> 28))));
        if(value > 0x1FFFFF || value < 0)   data[pos++] = ((byte)(0x80 | ((value >>> 21) & 0x7F)));
        if(value > 0x3FFF || value < 0)     data[pos++] = ((byte)(0x80 | ((value >>> 14) & 0x7F)));
        if(value > 0x7F || value < 0)       data[pos++] = ((byte)(0x80 | ((value >>>  7) & 0x7F)));

        data[pos++] = (byte)(value & 0x7F);

        return pos;
    }

public static int writeVInt ( byte data [ ] , int pos , int value ) { if ( value > 0x0FFFFFFF || value < 0 ) data [ pos ++ ] = ( ( byte ) ( 0x80 | ( ( value >>> 28 ) ) ) ) ; if ( value > 0x1FFFFF || value < 0 ) data [ pos ++ ] = ( ( byte ) ( 0x80 | ( ( value >>> 21 ) & 0x7F ) ) ) ; if ( value > 0x3FFF || value < 0 ) data [ pos ++ ] = ( ( byte ) ( 0x80 | ( ( value >>> 14 ) & 0x7F ) ) ) ; if ( value > 0x7F || value < 0 ) data [ pos ++ ] = ( ( byte ) ( 0x80 | ( ( value >>> 7 ) & 0x7F ) ) ) ; data [ pos ++ ] = ( byte ) ( value & 0x7F ) ; return pos ; }

Write the value as a VarInt into the array, starting at the specified position.

@param data the byte array to write to
@param pos the position in the byte array
@param value the int value
@return the next position after the VarInt has been written.

Write the value as a VarInt into the array starting at the specified position .


public static int readVInt(InputStream in) throws IOException {
        byte b = (byte)in.read();

        if(b == (byte) 0x80)
            throw new RuntimeException("Attempting to read null value as int");

        int value = b & 0x7F;
        while ((b & 0x80) != 0) {
          b = (byte)in.read();
          value <<= 7;
          value |= (b & 0x7F);
        }

        return value;
    }

public
static
int
readVInt
(
InputStream
in
)
throws
IOException
{
byte
b
=
(
byte
)
in
.
read
(
)
;
if
(
b
==
(
byte
)
0x80
)
throw
new
RuntimeException
(
"Attempting to read null value as int"
)
;
int
value
=
b
&
0x7F
;
while
(
(
b
&
0x80
)
!=
0
)
{
b
=
(
byte
)
in
.
read
(
)
;
value
<<=
7
;
value
|=
(
b
&
0x7F
)
;
}
return
value
;
}

Read a variable length integer from the supplied InputStream
@param in the input stream to read from
@return the int value
@throws IOException if the value cannot be read from the input stream


public static long readVLong(InputStream in) throws IOException {
        byte b = (byte)in.read();

        if(b == (byte) 0x80)
            throw new RuntimeException("Attempting to read null value as long");

        long value = b & 0x7F;
        while ((b & 0x80) != 0) {
          b = (byte)in.read();
          value <<= 7;
          value |= (b & 0x7F);
        }

        return value;
    }

public
static
long
readVLong
(
InputStream
in
)
throws
IOException
{
byte
b
=
(
byte
)
in
.
read
(
)
;
if
(
b
==
(
byte
)
0x80
)
throw
new
RuntimeException
(
"Attempting to read null value as long"
)
;
long
value
=
b
&
0x7F
;
while
(
(
b
&
0x80
)
!=
0
)
{
b
=
(
byte
)
in
.
read
(
)
;
value
<<=
7
;
value
|=
(
b
&
0x7F
)
;
}
return
value
;
}

Read a variable length long from the supplied InputStream.
@param in the input stream to read from
@return the long value
@throws IOException if the value cannot be read from the input stream

Read a variable length long from the supplied InputStream .


protected final void addViewInternal(View child, int index, ViewGroup.LayoutParams params) {
		super.addView(child, index, params);
	}

protected final void addViewInternal ( View child , int index , ViewGroup . LayoutParams params ) { super . addView ( child , index , params ) ; }

Used internally for adding view. Need because we override addView to
pass-through to the Refreshable View

Used internally for adding view . Need because we override addView to pass - through to the Refreshable View


protected final void refreshLoadingViewsSize() {
		final int maximumPullScroll = (int) (getMaximumPullScroll() * 1.2f);

		int pLeft = getPaddingLeft();
		int pTop = getPaddingTop();
		int pRight = getPaddingRight();
		int pBottom = getPaddingBottom();

		switch (getPullToRefreshScrollDirection()) {
			case HORIZONTAL:
				if (mMode.showHeaderLoadingLayout()) {
					mHeaderLayout.setWidth(maximumPullScroll);
					pLeft = -maximumPullScroll;
				} else {
					pLeft = 0;
				}

				if (mMode.showFooterLoadingLayout()) {
					mFooterLayout.setWidth(maximumPullScroll);
					pRight = -maximumPullScroll;
				} else {
					pRight = 0;
				}
				break;

			case VERTICAL:
				if (mMode.showHeaderLoadingLayout()) {
					mHeaderLayout.setHeight(maximumPullScroll);
					pTop = -maximumPullScroll;
				} else {
					pTop = 0;
				}

				if (mMode.showFooterLoadingLayout()) {
					mFooterLayout.setHeight(maximumPullScroll);
					pBottom = -maximumPullScroll;
				} else {
					pBottom = 0;
				}
				break;
		}

		if (DEBUG) {
			Log.d(LOG_TAG, String.format("Setting Padding. L: %d, T: %d, R: %d, B: %d", pLeft, pTop, pRight, pBottom));
		}
		setPadding(pLeft, pTop, pRight, pBottom);
	}

Re-measure the Loading Views height, and adjust internal padding as
necessary

Re - measure the Loading Views height and adjust internal padding as necessary


protected void updateUIForMode() {
		// We need to use the correct LayoutParam values, based on scroll
		// direction
		final LinearLayout.LayoutParams lp = getLoadingLayoutLayoutParams();

		// Remove Header, and then add Header Loading View again if needed
		if (this == mHeaderLayout.getParent()) {
			removeView(mHeaderLayout);
		}
		if (mMode.showHeaderLoadingLayout()) {
			addViewInternal(mHeaderLayout, 0, lp);
		}

		// Remove Footer, and then add Footer Loading View again if needed
		if (this == mFooterLayout.getParent()) {
			removeView(mFooterLayout);
		}
		if (mMode.showFooterLoadingLayout()) {
			addViewInternal(mFooterLayout, lp);
		}

		// Hide Loading Views
		refreshLoadingViewsSize();

		// If we're not using Mode.BOTH, set mCurrentMode to mMode, otherwise
		// set it to pull down
		mCurrentMode = (mMode != Mode.BOTH) ? mMode : Mode.PULL_FROM_START;
	}

Updates the View State when the mode has been set. This does not do any
checking that the mode is different to current state so always updates.

Updates the View State when the mode has been set . This does not do any checking that the mode is different to current state so always updates .


private void pullEvent() {
		final int newScrollValue;
		final int itemDimension;
		final float initialMotionValue, lastMotionValue;

		switch (getPullToRefreshScrollDirection()) {
			case HORIZONTAL:
				initialMotionValue = mInitialMotionX;
				lastMotionValue = mLastMotionX;
				break;
			case VERTICAL:
			default:
				initialMotionValue = mInitialMotionY;
				lastMotionValue = mLastMotionY;
				break;
		}

		switch (mCurrentMode) {
			case PULL_FROM_END:
				newScrollValue = Math.round(Math.max(initialMotionValue - lastMotionValue, 0) / FRICTION);
				itemDimension = getFooterSize();
				break;
			case PULL_FROM_START:
			default:
				newScrollValue = Math.round(Math.min(initialMotionValue - lastMotionValue, 0) / FRICTION);
				itemDimension = getHeaderSize();
				break;
		}

		setHeaderScroll(newScrollValue);

		if (newScrollValue != 0 && !isRefreshing()) {
			float scale = Math.abs(newScrollValue) / (float) itemDimension;
			switch (mCurrentMode) {
				case PULL_FROM_END:
					mFooterLayout.onPull(scale);
					break;
				case PULL_FROM_START:
				default:
					mHeaderLayout.onPull(scale);
					break;
			}

			if (mState != State.PULL_TO_REFRESH && itemDimension >= Math.abs(newScrollValue)) {
				setState(State.PULL_TO_REFRESH);
			} else if (mState == State.PULL_TO_REFRESH && itemDimension < Math.abs(newScrollValue)) {
				setState(State.RELEASE_TO_REFRESH);
			}
		}
	}

private void pullEvent ( ) { final int newScrollValue ; final int itemDimension ; final float initialMotionValue , lastMotionValue ; switch ( getPullToRefreshScrollDirection ( ) ) { case HORIZONTAL : initialMotionValue = mInitialMotionX ; lastMotionValue = mLastMotionX ; break ; case VERTICAL : default : initialMotionValue = mInitialMotionY ; lastMotionValue = mLastMotionY ; break ; } switch ( mCurrentMode ) { case PULL_FROM_END : newScrollValue = Math . round ( Math . max ( initialMotionValue - lastMotionValue , 0 ) / FRICTION ) ; itemDimension = getFooterSize ( ) ; break ; case PULL_FROM_START : default : newScrollValue = Math . round ( Math . min ( initialMotionValue - lastMotionValue , 0 ) / FRICTION ) ; itemDimension = getHeaderSize ( ) ; break ; } setHeaderScroll ( newScrollValue ) ; if ( newScrollValue != 0 && ! isRefreshing ( ) ) { float scale = Math . abs ( newScrollValue ) / ( float ) itemDimension ; switch ( mCurrentMode ) { case PULL_FROM_END : mFooterLayout . onPull ( scale ) ; break ; case PULL_FROM_START : default : mHeaderLayout . onPull ( scale ) ; break ; } if ( mState != State . PULL_TO_REFRESH && itemDimension >= Math . abs ( newScrollValue ) ) { setState ( State . PULL_TO_REFRESH ) ; } else if ( mState == State . PULL_TO_REFRESH && itemDimension < Math . abs ( newScrollValue ) ) { setState ( State . RELEASE_TO_REFRESH ) ; } } }

Actions a Pull Event

@return true if the Event has been handled, false if there has been no
change


public static void overScrollBy(final PullToRefreshBase<?> view, final int deltaX, final int scrollX,
			final int deltaY, final int scrollY, final int scrollRange, final int fuzzyThreshold,
			final float scaleFactor, final boolean isTouchEvent) {

		final int deltaValue, currentScrollValue, scrollValue;
		switch (view.getPullToRefreshScrollDirection()) {
			case HORIZONTAL:
				deltaValue = deltaX;
				scrollValue = scrollX;
				currentScrollValue = view.getScrollX();
				break;
			case VERTICAL:
			default:
				deltaValue = deltaY;
				scrollValue = scrollY;
				currentScrollValue = view.getScrollY();
				break;
		}

		// Check that OverScroll is enabled and that we're not currently
		// refreshing.
		if (view.isPullToRefreshOverScrollEnabled() && !view.isRefreshing()) {
			final Mode mode = view.getMode();

			// Check that Pull-to-Refresh is enabled, and the event isn't from
			// touch
			if (mode.permitsPullToRefresh() && !isTouchEvent && deltaValue != 0) {
				final int newScrollValue = (deltaValue + scrollValue);

				if (PullToRefreshBase.DEBUG) {
					Log.d(LOG_TAG, "OverScroll. DeltaX: " + deltaX + ", ScrollX: " + scrollX + ", DeltaY: " + deltaY
							+ ", ScrollY: " + scrollY + ", NewY: " + newScrollValue + ", ScrollRange: " + scrollRange
							+ ", CurrentScroll: " + currentScrollValue);
				}

				if (newScrollValue < (0 - fuzzyThreshold)) {
					// Check the mode supports the overscroll direction, and
					// then move scroll
					if (mode.showHeaderLoadingLayout()) {
						// If we're currently at zero, we're about to start
						// overscrolling, so change the state
						if (currentScrollValue == 0) {
							view.setState(State.OVERSCROLLING);
						}

						view.setHeaderScroll((int) (scaleFactor * (currentScrollValue + newScrollValue)));
					}
				} else if (newScrollValue > (scrollRange + fuzzyThreshold)) {
					// Check the mode supports the overscroll direction, and
					// then move scroll
					if (mode.showFooterLoadingLayout()) {
						// If we're currently at zero, we're about to start
						// overscrolling, so change the state
						if (currentScrollValue == 0) {
							view.setState(State.OVERSCROLLING);
						}

						view.setHeaderScroll((int) (scaleFactor * (currentScrollValue + newScrollValue - scrollRange)));
					}
				} else if (Math.abs(newScrollValue) <= fuzzyThreshold
						|| Math.abs(newScrollValue - scrollRange) <= fuzzyThreshold) {
					// Means we've stopped overscrolling, so scroll back to 0
					view.setState(State.RESET);
				}
			} else if (isTouchEvent && State.OVERSCROLLING == view.getState()) {
				// This condition means that we were overscrolling from a fling,
				// but the user has touched the View and is now overscrolling
				// from touch instead. We need to just reset.
				view.setState(State.RESET);
			}
		}
	}

Helper method for Overscrolling that encapsulates all of the necessary
function. This is the advanced version of the call.

@param view - PullToRefreshView that is calling this.
@param deltaX - Change in X in pixels, passed through from from
overScrollBy call
@param scrollX - Current X scroll value in pixels before applying deltaY,
passed through from from overScrollBy call
@param deltaY - Change in Y in pixels, passed through from from
overScrollBy call
@param scrollY - Current Y scroll value in pixels before applying deltaY,
passed through from from overScrollBy call
@param scrollRange - Scroll Range of the View, specifically needed for
ScrollView
@param fuzzyThreshold - Threshold for which the values how fuzzy we
should treat the other values. Needed for WebView as it
doesn't always scroll back to it's edge. 0 = no fuzziness.
@param scaleFactor - Scale Factor for overscroll amount
@param isTouchEvent - true if this scroll operation is the result of a
touch event, passed through from from overScrollBy call

Helper method for Overscrolling that encapsulates all of the necessary function . This is the advanced version of the call .


GivenRuleBuilder<T, U> given(String name, T value) {
    return given(new Fact<T>(name, value));
  }

GivenRuleBuilder < T , U > given ( String name , T value ) { return given ( new Fact < T > ( name , value ) ) ; }

Adds a fact to the Rule.
@param name  the name of the fact
@param value the value of the fact
@return      a GivenRuleBuilder


@SafeVarargs
  public final GivenRuleBuilder<T, U> given(NameValueReferable... facts) {
    _rule.addFacts(facts);
    return this;
  }

@ SafeVarargs public final GivenRuleBuilder < T , U > given ( NameValueReferable ... facts ) { _rule . addFacts ( facts ) ; return this ; }

Adds one or more facts into the Rule.
@param   facts one or more facts
@return  the current builder object


public static RuleBuilder<Object, Object> create(Class<? extends Rule> ruleClass,
                                                   RuleChainActionType actionType) {
    return new RuleBuilder<>(ruleClass, actionType);
  }

public static RuleBuilder < Object , Object > create ( Class < ? extends Rule > ruleClass , RuleChainActionType actionType ) { return new RuleBuilder <> ( ruleClass , actionType ) ; }

Returns a new RuleBuilder for the specified Rule class.
@param ruleClass   the class of Rule to build
@param actionType  if STOP_ON_FAILURE, stops the rule chain if RuleState is BREAK only if the rule fails
(for supported rule classes); if ERROR_ON_FAILURE, allows exceptions to be thrown from rule;
default is CONTINUE_ON_FAILURE
@return            a new RuleBuilder

Returns a new RuleBuilder for the specified Rule class .


public static RuleBuilder<Object, Object> create() {
    RuleBuilder<Object, Object> rule = new RuleBuilder<>(GoldenRule.class);
    rule._factType = Object.class;
    return rule;
  }

public static RuleBuilder < Object , Object > create ( ) { RuleBuilder < Object , Object > rule = new RuleBuilder <> ( GoldenRule . class ) ; rule . _factType = Object . class ; return rule ; }

Returns a new RuleBuilder for the default Rule type.
@return  a new RuleBuilder

Returns a new RuleBuilder for the default Rule type .


public <S> RuleBuilder<S, U> withFactType(Class<S> factType) {
    RuleBuilder<S, U> builder = new RuleBuilder<>(_ruleClass);
    builder._factType = factType;
    builder._resultType = _resultType;
    builder._actionType = _actionType;
    return builder;
  }

public < S > RuleBuilder < S , U > withFactType ( Class < S > factType ) { RuleBuilder < S , U > builder = new RuleBuilder <> ( _ruleClass ) ; builder . _factType = factType ; builder . _resultType = _resultType ; builder . _actionType = _actionType ; return builder ; }

Specifies the fact type for the Rule being built.
@param factType  the type of facts to be used in the Rule
@param <S>       the type of facts
@return          a builder using the new fact type for building a Rule

Specifies the fact type for the Rule being built .


public <S> RuleBuilder<T, S> withResultType(Class<S> resultType) {
    RuleBuilder<T, S> builder = new RuleBuilder<>(_ruleClass);
    builder._factType = _factType;
    builder._resultType = resultType;
    builder._actionType = _actionType;
    builder._name = _name;
    return builder;
  }

public < S > RuleBuilder < T , S > withResultType ( Class < S > resultType ) { RuleBuilder < T , S > builder = new RuleBuilder <> ( _ruleClass ) ; builder . _factType = _factType ; builder . _resultType = resultType ; builder . _actionType = _actionType ; builder . _name = _name ; return builder ; }

Specifies the Result type for the Rule being built.
@param resultType  the type of the Result to be used in the Rule
@param <S>         the type of Result
@return            a builder using a new result type for building a Rule

Specifies the Result type for the Rule being built .


@SuppressWarnings("unchecked")
  public GivenRuleBuilder<T, U> given(String name, T value) {
    Rule<T, U> rule = _name.map(ruleName -> (Rule<T, U>)new AuditableRule<T, U>(newRule(), ruleName)).orElse(newRule());
    if (rule == null) {
      throw new IllegalStateException("No Rule is instantiated; An invalid Rule class may have been provided");
    }
    return new GivenRuleBuilder<T, U>(rule, new Fact<T>(name, value));
  }

Adds a fact to the Rule using a name value pair to specify a new fact.
@param name    the name of the fact
@param value   the value of the fact
@return        a builder for building rules after a 'given' statement

Adds a fact to the Rule using a name value pair to specify a new fact .


@SuppressWarnings("unchecked")
  @SafeVarargs
  public final GivenRuleBuilder<T, U> given(NameValueReferable... facts) {
    Rule<T, U> rule = _name.map(name -> (Rule<T, U>)new AuditableRule<T, U>(newRule(), name)).orElse(newRule());
    if (rule == null) {
      throw new IllegalStateException("No Rule is instantiated; An invalid Rule class may have been provided");
    }
    return new GivenRuleBuilder<T, U>(rule, facts);
  }

Adds one or more facts to the Rule.
@param facts the facts to be added to the Rule
@return  a builder for building rules after a 'given' statement


@SuppressWarnings("unchecked")
  public ThenRuleBuilder<T, U> then(Consumer<NameValueReferableTypeConvertibleMap<T>> action) {
    Rule<T, U> rule = _name.map(name -> (Rule<T, U>)new AuditableRule<T, U>(newRule(), name)).orElse(newRule());
    if (rule == null) {
      throw new IllegalStateException("No Rule is instantiated; An invalid Rule class may have been provided");
    }
    return new ThenRuleBuilder<T, U>(rule, action);
  }

Adds an action as a Consumer to the Rule.
@param action  a Consumer action to be added to the Rule that accepts the facts specified for the Rule
@return        a builder for building rules after a 'then' action is specified

Adds an action as a Consumer to the Rule .


protected Object getRuleInstance(Class<?> rule) {
    try {
      return rule.newInstance();
    } catch (InstantiationException | IllegalAccessException ex) {
      LOGGER.warn("Unable to create instance of rule using '" + rule + "'", ex);
    }
    return null;
  }

Returns a rule instance

<p>For container aware contexts (like Spring, Guice, Weld, etc.) override this method and instantiate the rule
via the container.
@param rule The rule class
@return The rule instance


public static Optional<Field> getAnnotatedField(Class annotation, Class clazz) {
    List<Field> fields = getAnnotatedFields(annotation, clazz);
    return Optional.ofNullable(fields.size() > 0 ? fields.get(0) : null);
  }

public static Optional < Field > getAnnotatedField ( Class annotation , Class clazz ) { List < Field > fields = getAnnotatedFields ( annotation , clazz ) ; return Optional . ofNullable ( fields . size ( ) > 0 ? fields . get ( 0 ) : null ) ; }

Method getAnnotatedField gets the first annotated field of the type of annotation specified.
@param annotation      the type of the annotation
@param clazz           the annotated class
@return                the first annotated field found in clazz of the type annotation

Method getAnnotatedField gets the first annotated field of the type of annotation specified .


public static Optional<Method> getAnnotatedMethod(Class annotation, Class clazz) {
    List<Method> methods = getAnnotatedMethods(annotation, clazz);
    return Optional.ofNullable(methods.size() > 0 ? methods.get(0) : null);
  }

public static Optional < Method > getAnnotatedMethod ( Class annotation , Class clazz ) { List < Method > methods = getAnnotatedMethods ( annotation , clazz ) ; return Optional . ofNullable ( methods . size ( ) > 0 ? methods . get ( 0 ) : null ) ; }

Method getAnnotatedMethod the first annotated method of the type of annotation specified.
@param annotation      the type of the annotation
@param clazz           the annotated class
@return                the first annotated field found in clazz of the type annotation

Method getAnnotatedMethod the first annotated method of the type of annotation specified .


@SuppressWarnings("unchecked")
  public static <A extends Annotation> A getAnnotation(Class<A> annotation, Class<?> clazz) {
    return Optional.ofNullable(clazz.getAnnotation(annotation)).orElse((A)
      Arrays.stream(clazz.getDeclaredAnnotations())
        .flatMap(anno -> Arrays.stream(anno.getClass().getInterfaces())
          .flatMap(iface -> Arrays.stream(iface.getDeclaredAnnotations())))
        .filter(annotation::isInstance)
        .findFirst().orElse(null)
    );
  }

@ SuppressWarnings ( "unchecked" ) public static < A extends Annotation > A getAnnotation ( Class < A > annotation , Class < ? > clazz ) { return Optional . ofNullable ( clazz . getAnnotation ( annotation ) ) . orElse ( ( A ) Arrays . stream ( clazz . getDeclaredAnnotations ( ) ) . flatMap ( anno -> Arrays . stream ( anno . getClass ( ) . getInterfaces ( ) ) . flatMap ( iface -> Arrays . stream ( iface . getDeclaredAnnotations ( ) ) ) ) . filter ( annotation :: isInstance ) . findFirst ( ) . orElse ( null ) ) ; }

Method getAnnotation returns the annotation on a class or its parent annotation.
@param clazz       the annotated class
@param annotation  the annotation to find
@param <A>         the type of the annotation
@return            the actual annotation used or null if it doesn't exist

Method getAnnotation returns the annotation on a class or its parent annotation .


public void registerRule(Auditable rule) {
    _lock.writeLock().lock();
    try {
      _auditMap.put(rule.getName(), new HashMap<>());
    } finally {
      _lock.writeLock().unlock();
    }
  }

public void registerRule ( Auditable rule ) { _lock . writeLock ( ) . lock ( ) ; try { _auditMap . put ( rule . getName ( ) , new HashMap <> ( ) ) ; } finally { _lock . writeLock ( ) . unlock ( ) ; } }

Registers a rule to be audited.
@param rule  and {@link Auditable} rule


public void updateRuleStatus(Auditable rule, RuleStatus status) {
    _lock.readLock().lock();
    try {
      if (_auditMap.containsKey(rule.getName())) {
        _lock.readLock().unlock();
        _lock.writeLock().lock();
        try {
          _auditMap.get(rule.getName()).put(Thread.currentThread().getId(), status);
          _lock.readLock().lock();
        } finally {
          _lock.writeLock().unlock();
        }
      }
    } finally {
      _lock.readLock().unlock();
    }
  }

public void updateRuleStatus ( Auditable rule , RuleStatus status ) { _lock . readLock ( ) . lock ( ) ; try { if ( _auditMap . containsKey ( rule . getName ( ) ) ) { _lock . readLock ( ) . unlock ( ) ; _lock . writeLock ( ) . lock ( ) ; try { _auditMap . get ( rule . getName ( ) ) . put ( Thread . currentThread ( ) . getId ( ) , status ) ; _lock . readLock ( ) . lock ( ) ; } finally { _lock . writeLock ( ) . unlock ( ) ; } } } finally { _lock . readLock ( ) . unlock ( ) ; } }

Updates the status of the rule & stores the status with the Auditor.
@param rule    the rule in question
@param status  the status of the rule

Updates the status of the rule & stores the status with the Auditor .


public Map<String, RuleStatus> getRuleStatusMap() {
    _lock.readLock().lock();
    try {
      return _auditMap.keySet().stream()
          .collect(
              Collectors.toMap(key -> key,
                  key -> _auditMap.get(key).getOrDefault(Thread.currentThread().getId(), RuleStatus.PENDING)));
    } finally {
      _lock.readLock().unlock();
    }
  }

public Map < String , RuleStatus > getRuleStatusMap ( ) { _lock . readLock ( ) . lock ( ) ; try { return _auditMap . keySet ( ) . stream ( ) . collect ( Collectors . toMap ( key -> key , key -> _auditMap . get ( key ) . getOrDefault ( Thread . currentThread ( ) . getId ( ) , RuleStatus . PENDING ) ) ) ; } finally { _lock . readLock ( ) . unlock ( ) ; } }

Gets a map of each rule name with its associated status.
@return  a map of rule names and their associated status

Gets a map of each rule name with its associated status .


public <U> RuleBookWithResultTypeBuilder<U> withResultType(Class<U> resultType) {
    _resultType = resultType;
    return new RuleBookWithResultTypeBuilder<U>((new RuleBookBuilder<U>(this)).newRuleBook());
  }

public < U > RuleBookWithResultTypeBuilder < U > withResultType ( Class < U > resultType ) { _resultType = resultType ; return new RuleBookWithResultTypeBuilder < U > ( ( new RuleBookBuilder < U > ( this ) ) . newRuleBook ( ) ) ; }

Specifies the Result type for the RuleBook.
@param resultType  result class
@param <U>         type of the result class
@return            a builder with the new Result type

Specifies the Result type for the RuleBook .


public ThenRuleBuilder<T, U> then(Consumer<NameValueReferableTypeConvertibleMap<T>> action) {
    _rule.addAction(action);
    return this;
  }

public ThenRuleBuilder < T , U > then ( Consumer < NameValueReferableTypeConvertibleMap < T > > action ) { _rule . addAction ( action ) ; return this ; }

Adds a then action into the Rule.
@param action  an action that the rule will execute based on the condition
@return        a builder that allows for the Rule to be built following the 'then' statement


public ThenRuleBuilder<T, U> then(BiConsumer<NameValueReferableTypeConvertibleMap<T>, Result<U>> action) {
    _rule.addAction(action);
    return this;
  }

public ThenRuleBuilder < T , U > then ( BiConsumer < NameValueReferableTypeConvertibleMap < T > , Result < U > > action ) { _rule . addAction ( action ) ; return this ; }

Addds a then action into the Rule.
@param action  an action that the rule will execute based on the condition; accepts facts and the result
@return        a builder that allows for the Rule to be built following the 'then' statement


public void reset() {
    _lock.readLock().lock();
    try {
      if (_defaultValue == null) {
        return;
      }
    } finally {
      _lock.readLock().unlock();
    }
    setValue(_defaultValue);
  }

public void reset ( ) { _lock . readLock ( ) . lock ( ) ; try { if ( _defaultValue == null ) { return ; } } finally { _lock . readLock ( ) . unlock ( ) ; } setValue ( _defaultValue ) ; }

Resets the value of the Result to its default value.

Resets the value of the Result to its default value .


@SuppressWarnings("unchecked")
  public <T> RuleBookRuleWithFactTypeBuilder<T, U> withFactType(Class<T> factType) {
    Rule<T, U> rule = (Rule<T, U>)RuleBuilder.create(_ruleClass).withFactType(factType).build();
    _ruleBook.addRule(rule);
    return new RuleBookRuleWithFactTypeBuilder<>(rule);
  }

@ SuppressWarnings ( "unchecked" ) public < T > RuleBookRuleWithFactTypeBuilder < T , U > withFactType ( Class < T > factType ) { Rule < T , U > rule = ( Rule < T , U > ) RuleBuilder . create ( _ruleClass ) . withFactType ( factType ) . build ( ) ; _ruleBook . addRule ( rule ) ; return new RuleBookRuleWithFactTypeBuilder <> ( rule ) ; }

Specifies the fact type
@param factType  the type of object that facts are restricted to in the Rule.
@param <T>       the generic fact type
@return          RuleBookRuleWithFactTypeBuilder for building RuleBook Rules with a specific fact type


protected List<Class<?>> getPojoRules() {
    Reflections reflections = new Reflections(_package);

    List<Class<?>> rules = reflections
        .getTypesAnnotatedWith(com.deliveredtechnologies.rulebook.annotation.Rule.class).stream()
        .filter(rule -> rule.getAnnotatedSuperclass() != null) // Include classes only, exclude interfaces, etc.
        .filter(rule -> _subPkgMatch.test(rule.getPackage().getName()))
        .collect(Collectors.toList());

    rules.sort(comparingInt(aClass ->
        getAnnotation(com.deliveredtechnologies.rulebook.annotation.Rule.class, aClass).order()));

    return rules;
  }

Gets the POJO Rules to be used by the RuleBook via reflection of the specified package.
@return  a List of POJO Rules

Gets the POJO Rules to be used by the RuleBook via reflection of the specified package .


private String readEmptyLineOrEndTable(final BufferedReader tableContent) throws IOException {
        final String column = tableContent.readLine();

        if (column != null && column.startsWith(END_TABLE)) {
            return END_TABLE;
        }

        if(column == null || !column.isEmpty()) {
            throw new IllegalArgumentException(String.format("Trying to read an empty line for end of row, but content %s was found or EOF", column));
        }

        return "";
    }

Reads empty line or throw an exception if a none empty line was found.

Reads empty line or throw an exception if a none empty line was found .


private Service[] toArray(List<Service> services) {
        if (services == null) {
            return new Service[0];
        }
        if (services instanceof ArrayList) {
            return ((ArrayList<Service>) services).toArray(new Service[services.size()]);
        } else {
            Service[] ret = new Service[services.size()];
            for (int i = 0; i < services.size(); i++) {
                ret[i] = services.get(i);
            }
            return ret;
        }
    }

private Service [ ] toArray ( List < Service > services ) { if ( services == null ) { return new Service [ 0 ] ; } if ( services instanceof ArrayList ) { return ( ( ArrayList < Service > ) services ) . toArray ( new Service [ services . size ( ) ] ) ; } else { Service [ ] ret = new Service [ services . size ( ) ] ; for ( int i = 0 ; i < services . size ( ) ; i ++ ) { ret [ i ] = services . get ( i ) ; } return ret ; } }

convert list to array, never returns null.

convert list to array never returns null .


private List<String> getPortsFromBuildConfiguration(ImageConfiguration image) {
        // No build, no default service (doesn't make much sense to have no build config, though)
        BuildImageConfiguration buildConfig = image.getBuildConfiguration();
        if (buildConfig == null) {
            return Collections.emptyList();
        }

        return buildConfig.getPorts();
    }

Examine images for build configuration and extract all ports


private List<ServicePort> extractPortsFromConfig() {
        List<ServicePort> ret = new LinkedList<>();
        String ports = getConfig(Config.port);
        if (ports != null) {
            for (String port : StringUtils.split(ports, ",")) {
                ret.add(parsePortMapping(port));
            }
        }
        return ret;
    }

private List < ServicePort > extractPortsFromConfig ( ) { List < ServicePort > ret = new LinkedList <> ( ) ; String ports = getConfig ( Config . port ) ; if ( ports != null ) { for ( String port : StringUtils . split ( ports , "," ) ) { ret . add ( parsePortMapping ( port ) ) ; } } return ret ; }


private ServicePort parsePortMapping(String port) {
        Matcher matcher = PORT_MAPPING_PATTERN.matcher(port);
        if (!matcher.matches()) {
            log.error("Invalid 'port' configuration '%s'. Must match <port>(:<targetPort>)?,<port2>?,...", port);
            throw new IllegalArgumentException("Invalid port mapping specification " + port);
        }

        int servicePort = Integer.parseInt(matcher.group("port"));
        String optionalTargetPort = matcher.group("targetPort");
        String protocol = getProtocol(matcher.group("protocol"));

        ServicePortBuilder builder = new ServicePortBuilder()
            .withPort(servicePort)
            .withProtocol(protocol)
            .withName(getDefaultPortName(servicePort, protocol));

        // leave empty if not set. will be filled up with the port from the image config
        if (optionalTargetPort != null) {
            builder.withNewTargetPort(Integer.parseInt(optionalTargetPort));
        }
        return builder.build();
    }


private void addPortIfNotNull(List<ServicePort> ret, ServicePort port) {
        if (port != null) {
            ret.add(port);
        }
    }

private void addPortIfNotNull ( List < ServicePort > ret , ServicePort port ) { if ( port != null ) { ret . add ( port ) ; } }

null ports can happen for ignored mappings


private ServicePort shiftOrNull(List<ServicePort> ports) {
        if (!ports.isEmpty()) {
            return ports.remove(0);
        }
        return null;
    }

private ServicePort shiftOrNull ( List < ServicePort > ports ) { if ( ! ports . isEmpty ( ) ) { return ports . remove ( 0 ) ; } return null ; }

remove first element of list or null if list is empty


private void addMissingServiceParts(ServiceBuilder service, Service defaultService) {

        // If service has no spec -> take over the complete spec from default service
        if (!service.hasSpec()) {
            service.withNewSpecLike(defaultService.getSpec()).endSpec();
            return;
        }

        // If service has no ports -> take over ports from default service
        List<ServicePort> ports = service.buildSpec().getPorts();
        if (ports == null || ports.isEmpty()) {
            service.editSpec().withPorts(defaultService.getSpec().getPorts()).endSpec();
            return;
        }

        // Complete missing parts:
        service.editSpec()
               .withPorts(addMissingDefaultPorts(ports, defaultService))
               .endSpec();
    }

Merge services of same name with the default service


public void appendImageStreamResource(ImageName imageName, File target) throws MojoExecutionException {
        String tag = StringUtils.isBlank(imageName.getTag()) ? "latest" : imageName.getTag();
        try {
            ImageStream is = new ImageStreamBuilder()
                    .withNewMetadata()
                    .withName(imageName.getSimpleName())
                    .endMetadata()

                    .withNewSpec()
                    .addNewTag()
                      .withName(tag)
                      .withNewFrom().withKind("ImageStreamImage").endFrom()
                    .endTag()
                    .endSpec()

                    .build();
            createOrUpdateImageStreamTag(client, imageName, is);
            appendImageStreamToFile(is, target);
            log.info("ImageStream %s written to %s", imageName.getSimpleName(), target);
        } catch (KubernetesClientException e) {
            KubernetesResourceUtil.handleKubernetesClientException(e, this.log);
        } catch (IOException e) {
            throw new MojoExecutionException(String.format("Cannot write ImageStream descriptor for %s to %s : %s",
                                                           imageName.getFullName(), target.getAbsoluteFile(), e.getMessage()),e);
        }
    }

Save the images stream to a file
@param imageName name of the image for which the stream should be extracted
@param target file to store the image stream


private static boolean portsMatch(ServicePort servicePort, IntOrString intOrString) {
        if (intOrString != null) {
            Integer port = servicePort.getPort();
            Integer intVal = intOrString.getIntVal();
            String strVal = intOrString.getStrVal();
            if (intVal != null) {
                if (port != null) {
                    return port.intValue() == intVal.intValue();
                } else {
                    /// should we find the port by name now?
                }
            } else if (strVal != null ){
                return Objects.equal(strVal, servicePort.getName());
            }
        }
        return false;
    }

Returns true if the given servicePort matches the intOrString value


private static String serviceToPortOrBlank(String serviceName) {
        String envVarName = toServicePortEnvironmentVariable(serviceName);
        return getEnvVarOrSystemProperty(envVarName, "");
    }

private static String serviceToPortOrBlank ( String serviceName ) { String envVarName = toServicePortEnvironmentVariable ( serviceName ) ; return getEnvVarOrSystemProperty ( envVarName , "" ) ; }

Returns the named port for the given service name or blank


private static String getServiceHostAndPort(String serviceName, String defaultHost, String defaultPort) {
        String serviceEnvVarPrefix = getServiceEnvVarPrefix(serviceName);
        String hostEnvVar = serviceEnvVarPrefix + "_HOST";
        String portEnvVar = serviceEnvVarPrefix + "_PORT";

        String host = getEnvVarOrSystemProperty(hostEnvVar, hostEnvVar, defaultHost);
        String port = getEnvVarOrSystemProperty(portEnvVar, portEnvVar, defaultPort);

        String answer = host + ":" + port;
        return answer;
    }

private static String getServiceHostAndPort ( String serviceName , String defaultHost , String defaultPort ) { String serviceEnvVarPrefix = getServiceEnvVarPrefix ( serviceName ) ; String hostEnvVar = serviceEnvVarPrefix + "_HOST" ; String portEnvVar = serviceEnvVarPrefix + "_PORT" ; String host = getEnvVarOrSystemProperty ( hostEnvVar , hostEnvVar , defaultHost ) ; String port = getEnvVarOrSystemProperty ( portEnvVar , portEnvVar , defaultPort ) ; String answer = host + ":" + port ; return answer ; }

Returns the service host and port for the given environment variable name.

@param serviceName the name of the service which is used as a prefix to access the ${serviceName}_SERVICE_HOST and ${serviceName}_SERVICE_PORT environment variables to find the hos and port
@param defaultHost the default host to use if not injected via an environment variable (e.g. localhost)
@parma defaultPort the default port to use to connect to the service if there is not an environment variable defined

Returns the service host and port for the given environment variable name .


public static void putIfAbsent(Map<String, String> map, String name, String value) {
        if (!map.containsKey(name)) {
            map.put(name, value);
        }
    }

public static void putIfAbsent ( Map < String , String > map , String name , String value ) { if ( ! map . containsKey ( name ) ) { map . put ( name , value ) ; } }

Adds the given key and value pair into the map if the map does not already contain a value for that key


public static void mergeIfAbsent(Map<String, String> map, Map<String, String> toMerge) {
        for (Map.Entry<String, String> entry : toMerge.entrySet()) {
            putIfAbsent(map, entry.getKey(), entry.getValue());;
        }
    }

public static void mergeIfAbsent ( Map < String , String > map , Map < String , String > toMerge ) { for ( Map . Entry < String , String > entry : toMerge . entrySet ( ) ) { putIfAbsent ( map , entry . getKey ( ) , entry . getValue ( ) ) ; ; } }

Add all values of a map to another map, but onlfy if not already existing.
@param map target map
@param toMerge the values to ad

Add all values of a map to another map but onlfy if not already existing .


public static <K,V> Map<K,V> mergeMaps(Map<K, V> map1, Map<K, V> map2) {
        Map<K, V> answer = new HashMap<>();
        if (map2 != null) {
            answer.putAll(map2);
        }
        if (map1 != null) {
            answer.putAll(map1);
        }
        return answer;

    }

public static < K , V > Map < K , V > mergeMaps ( Map < K , V > map1 , Map < K , V > map2 ) { Map < K , V > answer = new HashMap <> ( ) ; if ( map2 != null ) { answer . putAll ( map2 ) ; } if ( map1 != null ) { answer . putAll ( map1 ) ; } return answer ; }

Returns a new map with all the entries of map1 and any from map2 which don't override map1.

Can handle either maps being null. Always returns a new mutable map

Returns a new map with all the entries of map1 and any from map2 which don t override map1 .


public static void putAllIfNotNull(Map<String, String> ret, Map<String, String> toPut) {
        if (toPut != null) {
            ret.putAll(toPut);
        }
    }

public static void putAllIfNotNull ( Map < String , String > ret , Map < String , String > toPut ) { if ( toPut != null ) { ret . putAll ( toPut ) ; } }

Copies all of the elements i.e., the mappings, from toPut map into ret, if toPut isn't null.
@param ret
@param toPut

Copies all of the elements i . e . the mappings from toPut map into ret if toPut isn t null .


private void waitUntilPodIsReady(String podName, int nAwaitTimeout, final Logger log) throws InterruptedException {
        final CountDownLatch readyLatch = new CountDownLatch(1);
        try (Watch watch = client.pods().withName(podName).watch(new Watcher<Pod>() {
            @Override
            public void eventReceived(Action action, Pod aPod) {
                if(KubernetesHelper.isPodReady(aPod)) {
                    readyLatch.countDown();
                }
            }

            @Override
            public void onClose(KubernetesClientException e) {
                // Ignore
            }
        })) {
            readyLatch.await(nAwaitTimeout, TimeUnit.SECONDS);
        } catch (KubernetesClientException | InterruptedException e) {
            log.error("Could not watch pod", e);
        }
    }

private
void
waitUntilPodIsReady
(
String
podName
,
int
nAwaitTimeout
,
final
Logger
log
)
throws
InterruptedException
{
final
CountDownLatch
readyLatch
=
new
CountDownLatch
(
1
)
;
try
(
Watch
watch
=
client
.
pods
(
)
.
withName
(
podName
)
.
watch
(
new
Watcher
<
Pod
>
(
)
{
@
Override
public
void
eventReceived
(
Action
action
,
Pod
aPod
)
{
if
(
KubernetesHelper
.
isPodReady
(
aPod
)
)
{
readyLatch
.
countDown
(
)
;
}
}
@
Override
public
void
onClose
(
KubernetesClientException
e
)
{
// Ignore
}
}
)
)
{
readyLatch
.
await
(
nAwaitTimeout
,
TimeUnit
.
SECONDS
)
;
}
catch
(
KubernetesClientException
|
InterruptedException
e
)
{
log
.
error
(
"Could not watch pod"
,
e
)
;
}
}

A Simple utility function to watch over pod until it gets ready

@param podName Name of the pod
@param nAwaitTimeout Time in seconds upto which pod must be watched
@param log Logger object
@throws InterruptedException


public static String validateKubernetesId(String currentValue, String description) throws IllegalArgumentException {
        if (StringUtils.isBlank(currentValue)) {
            throw new IllegalArgumentException("No " + description + " is specified!");
        }
        int size = currentValue.length();
        for (int i = 0; i < size; i++) {
            char ch = currentValue.charAt(i);
            if (Character.isUpperCase(ch)) {
                throw new IllegalArgumentException("Invalid upper case letter '" + ch + "' at index " + i + " for " + description + " value: " + currentValue);
            }
        }
        return currentValue;
    }

public
static
String
validateKubernetesId
(
String
currentValue
,
String
description
)
throws
IllegalArgumentException
{
if
(
StringUtils
.
isBlank
(
currentValue
)
)
{
throw
new
IllegalArgumentException
(
"No "
+
description
+
" is specified!"
)
;
}
int
size
=
currentValue
.
length
(
)
;
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
char
ch
=
currentValue
.
charAt
(
i
)
;
if
(
Character
.
isUpperCase
(
ch
)
)
{
throw
new
IllegalArgumentException
(
"Invalid upper case letter '"
+
ch
+
"' at index "
+
i
+
" for "
+
description
+
" value: "
+
currentValue
)
;
}
}
return
currentValue
;
}

Validates that the given value is valid according to the kubernetes ID parsing rules, throwing an exception if not.

Validates that the given value is valid according to the kubernetes ID parsing rules throwing an exception if not .


@SuppressWarnings("unchecked")
    public static List<HasMetadata> toItemList(Object entity) throws IOException {
        if (entity instanceof List) {
            return (List<HasMetadata>) entity;
        } else if (entity instanceof HasMetadata[]) {
            HasMetadata[] array = (HasMetadata[]) entity;
            return Arrays.asList(array);
        } else if (entity instanceof KubernetesList) {
            KubernetesList config = (KubernetesList) entity;
            return config.getItems();
        } else if (entity instanceof Template) {
            Template objects = (Template) entity;
            return objects.getObjects();
        } else {
            List<HasMetadata> answer = new ArrayList<>();
            if (entity instanceof HasMetadata) {
                answer.add((HasMetadata) entity);
            }
            return answer;
        }
    }

@ SuppressWarnings ( "unchecked" ) public static List < HasMetadata > toItemList ( Object entity ) throws IOException { if ( entity instanceof List ) { return ( List < HasMetadata > ) entity ; } else if ( entity instanceof HasMetadata [ ] ) { HasMetadata [ ] array = ( HasMetadata [ ] ) entity ; return Arrays . asList ( array ) ; } else if ( entity instanceof KubernetesList ) { KubernetesList config = ( KubernetesList ) entity ; return config . getItems ( ) ; } else if ( entity instanceof Template ) { Template objects = ( Template ) entity ; return objects . getObjects ( ) ; } else { List < HasMetadata > answer = new ArrayList <> ( ) ; if ( entity instanceof HasMetadata ) { answer . add ( ( HasMetadata ) entity ) ; } return answer ; } }

Loads the Kubernetes JSON and converts it to a list of entities