private int registerCluster(final OCluster cluster) {
    final int id;

    if (cluster != null) {
      // CHECK FOR DUPLICATION OF NAMES
      if (clusterMap.containsKey(cluster.getName().toLowerCase(configuration.getLocaleInstance()))) {
        throw new OConfigurationException(
            "Cannot add cluster '" + cluster.getName() + "' because it is already registered in database '" + name + "'");
      }
      // CREATE AND ADD THE NEW REF SEGMENT
      clusterMap.put(cluster.getName().toLowerCase(configuration.getLocaleInstance()), cluster);
      id = cluster.getId();
    } else {
      id = clusters.size();
    }

    setCluster(id, cluster);

    return id;
  }

Register the cluster internally.

@param cluster OCluster implementation

@return The id (physical position into the array) of the new cluster just created. First is 0.


public Object setProperty(final String iName, final Object iValue) {
    if (iValue != null) {
      return properties.put(iName.toLowerCase(Locale.ENGLISH), iValue);
    } else {
      return properties.remove(iName.toLowerCase(Locale.ENGLISH));
    }
  }

public Object setProperty ( final String iName , final Object iValue ) { if ( iValue != null ) { return properties . put ( iName . toLowerCase ( Locale . ENGLISH ) , iValue ) ; } else { return properties . remove ( iName . toLowerCase ( Locale . ENGLISH ) ) ; } }

Sets a property value

@param iName  Property name
@param iValue new value to set

@return The previous value if any, otherwise null


public Object execute(final Map<Object, Object> iArgs) {
    if (className == null)
      throw new OCommandExecutionException("Cannot execute the command because it has not been parsed yet");

    final ODatabaseDocument database = getDatabase();

    boolean alreadyExists = database.getMetadata().getSchema().existsClass(className);
    if (!alreadyExists || !ifNotExists) {
      if (clusters != null)
        database.getMetadata().getSchema().createClass(className, clusters, superClasses.toArray(new OClass[0]));
      else
        database.getMetadata().getSchema().createClass(className, clusterIds, superClasses.toArray(new OClass[0]));
    }
    return database.getMetadata().getSchema().getClasses().size();
  }


public Object execute(final Map<Object, Object> iArgs) {
    final ODatabaseDocumentInternal database = getDatabase();
    database.checkSecurity(ORule.ResourceGeneric.DATABASE, "sync", ORole.PERMISSION_UPDATE);

    final OStorage stg = database.getStorage();
    if (!(stg instanceof ODistributedStorage))
      throw new ODistributedException("SYNC DATABASE command cannot be executed against a non distributed server");

    final ODistributedStorage dStg = (ODistributedStorage) stg;

    final OHazelcastPlugin dManager = (OHazelcastPlugin) dStg.getDistributedManager();
    if (dManager == null || !dManager.isEnabled())
      throw new OCommandExecutionException("OrientDB is not started in distributed mode");

    final String databaseName = database.getName();

    return dManager.installDatabase(true, databaseName, parsedStatement.isForce(), !parsedStatement.isFull());
  }


public ODatabase<ORecord> delete(final ORID iRecord, final int iVersion) {
    ORecord record = load(iRecord);
    ORecordInternal.setVersion(record, iVersion);
    delete(record);
    return this;
  }

public ODatabase < ORecord > delete ( final ORID iRecord , final int iVersion ) { ORecord record = load ( iRecord ) ; ORecordInternal . setVersion ( record , iVersion ) ; delete ( record ) ; return this ; }

Deletes the record checking the version.

Deletes the record checking the version .


public ORecordHook.RESULT callbackHooks(final ORecordHook.TYPE type, final OIdentifiable id) {
    if (id == null || hooks.isEmpty() || id.getIdentity().getClusterId() == 0)
      return ORecordHook.RESULT.RECORD_NOT_CHANGED;

    final ORecordHook.SCOPE scope = ORecordHook.SCOPE.typeToScope(type);
    final int scopeOrdinal = scope.ordinal();

    final ORID identity = id.getIdentity().copy();
    if (!pushInHook(identity))
      return ORecordHook.RESULT.RECORD_NOT_CHANGED;

    try {
      final ORecord rec = id.getRecord();
      if (rec == null)
        return ORecordHook.RESULT.RECORD_NOT_CHANGED;

      final OScenarioThreadLocal.RUN_MODE runMode = OScenarioThreadLocal.INSTANCE.getRunMode();

      boolean recordChanged = false;
      for (ORecordHook hook : hooksByScope[scopeOrdinal]) {
        switch (runMode) {
        case DEFAULT: // NON_DISTRIBUTED OR PROXIED DB
          if (getStorage().isDistributed()
              && hook.getDistributedExecutionMode() == ORecordHook.DISTRIBUTED_EXECUTION_MODE.TARGET_NODE)
            // SKIP
            continue;
          break; // TARGET NODE
        case RUNNING_DISTRIBUTED:
          if (hook.getDistributedExecutionMode() == ORecordHook.DISTRIBUTED_EXECUTION_MODE.SOURCE_NODE)
            continue;
        }

        final ORecordHook.RESULT res = hook.onTrigger(type, rec);

        if (res == ORecordHook.RESULT.RECORD_CHANGED)
          recordChanged = true;
        else if (res == ORecordHook.RESULT.SKIP_IO)
          // SKIP IO OPERATION
          return res;
        else if (res == ORecordHook.RESULT.SKIP)
          // SKIP NEXT HOOKS AND RETURN IT
          return res;
        else if (res == ORecordHook.RESULT.RECORD_REPLACED)
          return res;
      }

      return recordChanged ? ORecordHook.RESULT.RECORD_CHANGED : ORecordHook.RESULT.RECORD_NOT_CHANGED;

    } finally {
      popInHook(identity);
    }
  }

public
ORecordHook
.
RESULT
callbackHooks
(
final
ORecordHook
.
TYPE
type
,
final
OIdentifiable
id
)
{
if
(
id
==
||
hooks
.
isEmpty
(
)
||
id
.
getIdentity
(
)
.
getClusterId
(
)
==
0
)
return
ORecordHook
.
RESULT
.
RECORD_NOT_CHANGED
;
final
ORecordHook
.
SCOPE
scope
=
ORecordHook
.
SCOPE
.
typeToScope
(
type
)
;
final
int
scopeOrdinal
=
scope
.
ordinal
(
)
;
final
ORID
identity
=
id
.
getIdentity
(
)
.
copy
(
)
;
if
(
!
pushInHook
(
identity
)
)
return
ORecordHook
.
RESULT
.
RECORD_NOT_CHANGED
;
try
{
final
ORecord
rec
=
id
.
getRecord
(
)
;
if
(
rec
==
)
return
ORecordHook
.
RESULT
.
RECORD_NOT_CHANGED
;
final
OScenarioThreadLocal
.
RUN_MODE
runMode
=
OScenarioThreadLocal
.
INSTANCE
.
getRunMode
(
)
;
boolean
recordChanged
=
false
;
for
(
ORecordHook
hook
:
hooksByScope
[
scopeOrdinal
]
)
{
switch
(
runMode
)
{
case
DEFAULT
:
// NON_DISTRIBUTED OR PROXIED DB
if
(
getStorage
(
)
.
isDistributed
(
)
&&
hook
.
getDistributedExecutionMode
(
)
==
ORecordHook
.
DISTRIBUTED_EXECUTION_MODE
.
TARGET_NODE
)
// SKIP
continue
;
break
;
// TARGET NODE
case
RUNNING_DISTRIBUTED
:
if
(
hook
.
getDistributedExecutionMode
(
)
==
ORecordHook
.
DISTRIBUTED_EXECUTION_MODE
.
SOURCE_NODE
)
continue
;
}
final
ORecordHook
.
RESULT
res
=
hook
.
onTrigger
(
type
,
rec
)
;
if
(
res
==
ORecordHook
.
RESULT
.
RECORD_CHANGED
)
recordChanged
=
true
;
else
if
(
res
==
ORecordHook
.
RESULT
.
SKIP_IO
)
// SKIP IO OPERATION
return
res
;
else
if
(
res
==
ORecordHook
.
RESULT
.
SKIP
)
// SKIP NEXT HOOKS AND RETURN IT
return
res
;
else
if
(
res
==
ORecordHook
.
RESULT
.
RECORD_REPLACED
)
return
res
;
}
return
recordChanged
ORecordHook
.
RESULT
.
RECORD_CHANGED
:
ORecordHook
.
RESULT
.
RECORD_NOT_CHANGED
;
}
finally
{
popInHook
(
identity
)
;
}
}

Callback the registered hooks if any.

@param type Hook type. Define when hook is called.
@param id   Record received in the callback

@return True if the input record is changed, otherwise false


public ODatabaseDocument delete(final ORID iRecord) {
    checkOpenness();
    checkIfActive();

    final ORecord rec = load(iRecord);
    if (rec != null)
      delete(rec);
    return this;
  }

public ODatabaseDocument delete ( final ORID iRecord ) { checkOpenness ( ) ; checkIfActive ( ) ; final ORecord rec = load ( iRecord ) ; if ( rec != null ) delete ( rec ) ; return this ; }

Deletes the record without checking the version.

Deletes the record without checking the version .


public long countView(final String viewName) {
    final OView cls = getMetadata().getImmutableSchemaSnapshot().getView(viewName);
    if (cls == null)
      throw new IllegalArgumentException("View '" + cls + "' not found in database");

    return countClass(cls, false);
  }

public
long
countView
(
final
String
viewName
)
{
final
OView
cls
=
getMetadata
(
)
.
getImmutableSchemaSnapshot
(
)
.
getView
(
viewName
)
;
if
(
cls
==
)
throw
new
IllegalArgumentException
(
"View '"
+
cls
+
"' not found in database"
)
;
return
countClass
(
cls
,
false
)
;
}

Returns the number of the records of the class iClassName.

Returns the number of the records of the class iClassName .


public long countClass(final String iClassName, final boolean iPolymorphic) {
    final OClass cls = getMetadata().getImmutableSchemaSnapshot().getClass(iClassName);
    if (cls == null)
      throw new IllegalArgumentException("Class '" + cls + "' not found in database");

    return countClass(cls, iPolymorphic);
  }

public
long
countClass
(
final
String
iClassName
,
final
boolean
iPolymorphic
)
{
final
OClass
cls
=
getMetadata
(
)
.
getImmutableSchemaSnapshot
(
)
.
getClass
(
iClassName
)
;
if
(
cls
==
)
throw
new
IllegalArgumentException
(
"Class '"
+
cls
+
"' not found in database"
)
;
return
countClass
(
cls
,
iPolymorphic
)
;
}

Returns the number of the records of the class iClassName considering also sub classes if polymorphic is true.

Returns the number of the records of the class iClassName considering also sub classes if polymorphic is true .


@Override
  public ODatabaseDocumentAbstract activateOnCurrentThread() {
    final ODatabaseRecordThreadLocal tl = ODatabaseRecordThreadLocal.instance();
    if (tl != null)
      tl.set(this);
    return this;
  }

@ Override public ODatabaseDocumentAbstract activateOnCurrentThread ( ) { final ODatabaseRecordThreadLocal tl = ODatabaseRecordThreadLocal . instance ( ) ; if ( tl != null ) tl . set ( this ) ; return this ; }

Activates current database instance on current thread.

Activates current database instance on current thread .


public void register(final OEncryption iEncryption) {
    try {
      final String name = iEncryption.name();

      if (instances.containsKey(name))
        throw new IllegalArgumentException("Encryption with name '" + name + "' was already registered");

      if (classes.containsKey(name))
        throw new IllegalArgumentException("Encryption with name '" + name + "' was already registered");

      instances.put(name, iEncryption);
    } catch (Exception e) {
      OLogManager.instance().error(this, "Cannot register storage encryption algorithm '%s'", e, iEncryption);
    }
  }

Registers a stateful implementations, a new instance will be created for each storage.

@param iEncryption
Encryption instance

Registers a stateful implementations a new instance will be created for each storage .


private int getRelativeIndex(long pos) {
    int currentSize = 0;
    currentChunkIndex = 0;

    // loop until we find the chuks holding the given position
    while (pos >= (currentSize += binaryDataChunks.get(currentChunkIndex).length))
      currentChunkIndex++;

    currentChunk = binaryDataChunks.get(currentChunkIndex);
    currentSize -= currentChunk.length;
    // the position referred to the target binary chunk
    int relativePosition = (int) (pos - currentSize);
    // the index of the first byte to be returned
    return relativePosition - 1;
  }

Calculates the index within a binary chunk corresponding to the given absolute position within this BLOB

@param pos
@return


protected String parserOptionalWord(final boolean iUpperCase) {
    parserPreviousPos = parserCurrentPos;

    parserNextWord(iUpperCase);
    if (parserLastWord.length() == 0)
      return null;
    return parserLastWord.toString();
  }

protected String parserOptionalWord ( final boolean iUpperCase ) { parserPreviousPos = parserCurrentPos ; parserNextWord ( iUpperCase ) ; if ( parserLastWord . length ( ) == 0 ) return null ; return parserLastWord . toString ( ) ; }

Parses the next word. It returns the word parsed if any.

@param iUpperCase
True if must return UPPERCASE, otherwise false
@return The word parsed if any, otherwise null

Parses the next word . It returns the word parsed if any .


protected String parserRequiredWord(final boolean iUpperCase, final String iCustomMessage, String iSeparators) {
    if (iSeparators == null)
      iSeparators = " ()=><,\r\n";

    parserNextWord(iUpperCase, iSeparators);
    if (parserLastWord.length() == 0)
      throwSyntaxErrorException(iCustomMessage);
    if (parserLastWord.charAt(0) == '`' && parserLastWord.charAt(parserLastWord.length() - 1) == '`') {
      return parserLastWord.substring(1, parserLastWord.length() - 1);
    }
    return parserLastWord.toString();
  }

protected
String
parserRequiredWord
(
final
boolean
iUpperCase
,
final
String
iCustomMessage
,
String
iSeparators
)
{
if
(
iSeparators
==
)
iSeparators
=
" ()=><,\r\n"
;
parserNextWord
(
iUpperCase
,
iSeparators
)
;
if
(
parserLastWord
.
length
(
)
==
0
)
throwSyntaxErrorException
(
iCustomMessage
)
;
if
(
parserLastWord
.
charAt
(
0
)
==
'
'
&&
parserLastWord
.
charAt
(
parserLastWord
.
length
(
)
1
)
==
'
'
)
{
return
parserLastWord
.
substring
(
1
,
parserLastWord
.
length
(
)
1
)
;
}
return
parserLastWord
.
toString
(
)
;
}

Parses the next word. If no word is found or the parsed word is not present in the word array received as parameter then a
SyntaxError exception with the custom message received as parameter is thrown. It returns the word parsed if any.

@param iUpperCase
True if must return UPPERCASE, otherwise false
@param iCustomMessage
Custom message to include in case of SyntaxError exception
@param iSeparators
Separator characters
@return The word parsed

Parses the next word . If no word is found or the parsed word is not present in the word array received as parameter then a SyntaxError exception with the custom message received as parameter is thrown . It returns the word parsed if any .


protected int parserNextChars(final boolean iUpperCase, final boolean iMandatory, final String... iCandidateWords) {
    parserPreviousPos = parserCurrentPos;
    parserSkipWhiteSpaces();

    parserEscapeSequenceCount = 0;
    parserLastWord.setLength(0);

    final String[] processedWords = Arrays.copyOf(iCandidateWords, iCandidateWords.length);

    // PARSE THE CHARS
    final String text2Use = iUpperCase ? parserTextUpperCase : parserText;
    final int max = text2Use.length();

    parserCurrentPos = parserCurrentPos + parserTextUpperCase.length() - parserText.length();
    // PARSE TILL 1 CHAR AFTER THE END TO SIMULATE A SEPARATOR AS EOF
    for (int i = 0; parserCurrentPos <= max; ++i) {
      final char ch = parserCurrentPos < max ? text2Use.charAt(parserCurrentPos) : '\n';
      final boolean separator = ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t' || ch == '(';
      if (!separator)
        parserLastWord.append(ch);

      // CLEAR CANDIDATES
      int candidatesWordsCount = 0;
      int candidatesWordsPos = -1;
      for (int c = 0; c < processedWords.length; ++c) {
        final String w = processedWords[c];
        if (w != null) {
          final int wordSize = w.length();
          if ((separator && wordSize > i) || (!separator && (i > wordSize - 1 || w.charAt(i) != ch)))
            // DISCARD IT
            processedWords[c] = null;
          else {
            candidatesWordsCount++;
            if (candidatesWordsCount == 1)
              // REMEMBER THE POSITION
              candidatesWordsPos = c;
          }
        }
      }

      if (candidatesWordsCount == 1) {
        // ONE RESULT, CHECKING IF FOUND
        final String w = processedWords[candidatesWordsPos];
        if (w.length() == i + (separator ? 0 : 1) && !Character.isLetter(ch))
          // FOUND!
          return candidatesWordsPos;
      }

      if (candidatesWordsCount == 0 || separator)
        break;

      parserCurrentPos++;
    }

    if (iMandatory)
      throwSyntaxErrorException("Found unexpected keyword '" + parserLastWord + "' while it was expected '"
          + Arrays.toString(iCandidateWords) + "'");

    return -1;
  }

Parses the next sequence of chars.

@return The position of the word matched if any, otherwise -1 or an exception if iMandatory is true


protected boolean parserOptionalKeyword(final String... iWords) {
    parserNextWord(true, " \r\n,");
    if (parserLastWord.length() == 0)
      return false;

    // FOUND: CHECK IF IT'S IN RANGE
    boolean found = iWords.length == 0;
    for (String w : iWords) {
      if (parserLastWord.toString().equals(w)) {
        found = true;
        break;
      }
    }

    if (!found)
      throwSyntaxErrorException("Found unexpected keyword '" + parserLastWord + "' while it was expected '"
          + Arrays.toString(iWords) + "'");

    return true;
  }

protected
boolean
parserOptionalKeyword
(
final
String
...
iWords
)
{
parserNextWord
(
true
,
" \r\n,"
)
;
if
(
parserLastWord
.
length
(
)
==
0
)
return
false
;
// FOUND: CHECK IF IT'S IN RANGE
boolean
found
=
iWords
.
length
==
0
;
for
(
String
w
:
iWords
)
{
if
(
parserLastWord
.
toString
(
)
.
equals
(
w
)
)
{
found
=
true
;
break
;
}
}
if
(
!
found
)
throwSyntaxErrorException
(
"Found unexpected keyword '"
+
parserLastWord
+
"' while it was expected '"
+
Arrays
.
toString
(
iWords
)
+
"'"
)
;
return
true
;
}

Parses optional keywords between the iWords. If a keyword is found but doesn't match with iWords then a SyntaxError is raised.

@param iWords
Optional words to match as keyword. If at least one is passed, then the check is made
@return true if a keyword was found, otherwise false

Parses optional keywords between the iWords . If a keyword is found but doesn t match with iWords then a SyntaxError is raised .


private boolean parserCheckSeparator(final char c, final String iSeparatorChars) {
    for (int sepIndex = 0; sepIndex < iSeparatorChars.length(); ++sepIndex) {
      if (iSeparatorChars.charAt(sepIndex) == c) {
        parserLastSeparator = c;
        return true;
      }
    }
    return false;
  }

private boolean parserCheckSeparator ( final char c , final String iSeparatorChars ) { for ( int sepIndex = 0 ; sepIndex < iSeparatorChars . length ( ) ; ++ sepIndex ) { if ( iSeparatorChars . charAt ( sepIndex ) == c ) { parserLastSeparator = c ; return true ; } } return false ; }

Check for a separator

@param c
@param iSeparatorChars
@return


public Object execute(final Map<Object, Object> iArgs) {
    if (className == null) {
      throw new OCommandExecutionException("Cannot execute the command because it has not been parsed yet");
    }

    final ODatabaseDocument database = getDatabase();
    if (ifExists && !database.getMetadata().getSchema().existsClass(className)) {
      return true;
    }
    final OClass cls = database.getMetadata().getSchema().getClass(className);
    if (cls == null) {
      return null;
    }

    final long records = cls.count(true);

    if (records > 0 && !unsafe) {
      // NOT EMPTY, CHECK IF CLASS IS OF VERTEX OR EDGES
      if (cls.isSubClassOf("V")) {
        // FOUND VERTEX CLASS
        throw new OCommandExecutionException("'DROP CLASS' command cannot drop class '" + className
            + "' because it contains Vertices. Use 'DELETE VERTEX' command first to avoid broken edges in a database, or apply the 'UNSAFE' keyword to force it");
      } else if (cls.isSubClassOf("E")) {
        // FOUND EDGE CLASS
        throw new OCommandExecutionException("'DROP CLASS' command cannot drop class '" + className
            + "' because it contains Edges. Use 'DELETE EDGE' command first to avoid broken vertices in a database, or apply the 'UNSAFE' keyword to force it");
      }
    }

    database.getMetadata().getSchema().dropClass(className);

    if (records > 0 && unsafe) {
      // NOT EMPTY, CHECK IF CLASS IS OF VERTEX OR EDGES
      if (cls.isSubClassOf("V")) {
        // FOUND VERTICES
        if (unsafe)
          OLogManager.instance().warn(this,
              "Dropped class '%s' containing %d vertices using UNSAFE mode. Database could contain broken edges", className,
              records);
      } else if (cls.isSubClassOf("E")) {
        // FOUND EDGES
        OLogManager.instance().warn(this,
            "Dropped class '%s' containing %d edges using UNSAFE mode. Database could contain broken vertices", className, records);
      }
    }

    return true;
  }


private void clearConfigurationFiles() throws IOException {
    final Path file = storagePath.resolve(NAME);
    Files.deleteIfExists(file);

    final Path backupFile = storagePath.resolve(BACKUP_NAME);
    Files.deleteIfExists(backupFile);
  }

private void clearConfigurationFiles ( ) throws IOException { final Path file = storagePath . resolve ( NAME ) ; Files . deleteIfExists ( file ) ; final Path backupFile = storagePath . resolve ( BACKUP_NAME ) ; Files . deleteIfExists ( backupFile ) ; }

Remove both backup and primary configuration files on delete

@see #update()


public int getAsByteArrayOffset() {
    if (position >= length)
      return -1;

    final int begin = position;

    final int size = OBinaryProtocol.bytes2int(buffer, position);
    position += OBinaryProtocol.SIZE_INT + size;

    return begin;
  }

public int getAsByteArrayOffset ( ) { if ( position >= length ) return - 1 ; final int begin = position ; final int size = OBinaryProtocol . bytes2int ( buffer , position ) ; position += OBinaryProtocol . SIZE_INT + size ; return begin ; }

Browse the stream but just return the begin of the byte array. This is used to lazy load the information only when needed.

Browse the stream but just return the begin of the byte array . This is used to lazy load the information only when needed .


protected String extract(String tokenType) {
		OAuth2AccessToken accessToken = getToken();
		return String.format("%s %s", tokenType, accessToken.getValue());
	}

protected
String
extract
(
String
tokenType
)
{
OAuth2AccessToken
accessToken
=
getToken
(
)
;
return
String
.
format
(
"%s %s"
,
tokenType
,
accessToken
.
getValue
(
)
)
;
}

Extracts the token extract id the access token exists or returning an empty extract
if there is no one on the context it may occasionally causes Unauthorized response
since the token extract is empty.
@param tokenType type name of token
@return token value from context if it exists otherwise empty String

Extracts the token extract id the access token exists or returning an empty extract if there is no one on the context it may occasionally causes Unauthorized response since the token extract is empty .


protected OAuth2AccessToken acquireAccessToken()
			throws UserRedirectRequiredException {
		AccessTokenRequest tokenRequest = oAuth2ClientContext.getAccessTokenRequest();
		if (tokenRequest == null) {
			throw new AccessTokenRequiredException(
					"Cannot find valid context on request for resource '"
							+ resource.getId() + "'.",
					resource);
		}
		String stateKey = tokenRequest.getStateKey();
		if (stateKey != null) {
			tokenRequest.setPreservedState(
					oAuth2ClientContext.removePreservedState(stateKey));
		}
		OAuth2AccessToken existingToken = oAuth2ClientContext.getAccessToken();
		if (existingToken != null) {
			oAuth2ClientContext.setAccessToken(existingToken);
		}
		OAuth2AccessToken obtainableAccessToken;
		obtainableAccessToken = accessTokenProvider.obtainAccessToken(resource,
				tokenRequest);
		if (obtainableAccessToken == null || obtainableAccessToken.getValue() == null) {
			throw new IllegalStateException(
					" Access token provider returned a null token, which is illegal according to the contract.");
		}
		oAuth2ClientContext.setAccessToken(obtainableAccessToken);
		return obtainableAccessToken;
	}

Try to acquire the token using a access token provider.
@return valid access token
@throws UserRedirectRequiredException in case the user needs to be redirected to an
approval page or login page

Try to acquire the token using a access token provider .


public boolean copyToken() {
		if (context.getAccessToken() == null) {
			Authentication authentication = SecurityContextHolder.getContext()
					.getAuthentication();
			if (authentication != null) {
				Object details = authentication.getDetails();
				if (details instanceof OAuth2AuthenticationDetails) {
					OAuth2AuthenticationDetails holder = (OAuth2AuthenticationDetails) details;
					String token = holder.getTokenValue();
					DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(
							token);
					String tokenType = holder.getTokenType();
					if (tokenType != null) {
						accessToken.setTokenType(tokenType);
					}
					context.setAccessToken(accessToken);
					return true;
				}
			}
		}
		return false;
	}

public boolean copyToken ( ) { if ( context . getAccessToken ( ) == null ) { Authentication authentication = SecurityContextHolder . getContext ( ) . getAuthentication ( ) ; if ( authentication != null ) { Object details = authentication . getDetails ( ) ; if ( details instanceof OAuth2AuthenticationDetails ) { OAuth2AuthenticationDetails holder = ( OAuth2AuthenticationDetails ) details ; String token = holder . getTokenValue ( ) ; DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken ( token ) ; String tokenType = holder . getTokenType ( ) ; if ( tokenType != null ) { accessToken . setTokenType ( tokenType ) ; } context . setAccessToken ( accessToken ) ; return true ; } } } return false ; }

Attempt to copy an access token from the security context into the oauth2 context.
@return true if the token was copied

Attempt to copy an access token from the security context into the oauth2 context .


protected boolean noMoreCharacters() throws IOException {
		if (avail == 0) {
			avail = is.read(buffer);
			if (avail <= 0) {
				avail = 0;
				return true;
			}
			pos = 0;
		}
		return false;
	}

protected boolean noMoreCharacters ( ) throws IOException { if ( avail == 0 ) { avail = is . read ( buffer ) ; if ( avail <= 0 ) { avail = 0 ; return true ; } pos = 0 ; } return false ; }

Checks whether no more bytes will be returned.

<p>This method will refill the internal buffer.

@return true if there are no characters in the internal buffer and
the underlying reader is exhausted.

Checks whether no more bytes will be returned .


public int readLine(final byte[] array, final EnumSet<LineTerminator> terminators) throws IOException {
		return readLine(array, 0, array.length, terminators);
	}

public int readLine ( final byte [ ] array , final EnumSet < LineTerminator > terminators ) throws IOException { return readLine ( array , 0 , array . length , terminators ) ; }

Reads a line into the given byte array.

@param array byte array where the next line will be stored.
@param terminators a set containing the line termination sequences that we want
to consider as valid.
@return the number of bytes actually placed in {@code array}, or -1 at end of file.
@see #readLine(byte[], int, int, EnumSet)

Reads a line into the given byte array .


public int readLine(final byte[] array, final int off, final int len, final EnumSet<LineTerminator> terminators) throws IOException {
		ByteArrays.ensureOffsetLength(array ,off, len);
		if (len == 0) return 0; // 0-length reads always return 0
		if (noMoreCharacters()) return -1;
		int i, k = 0, remaining = len, read = 0; // The number of bytes still to be read
		for(;;) {
			for(i = 0; i < avail && i < remaining && (k = buffer[pos + i]) != '\n' && k != '\r' ; i++);
			System.arraycopy(buffer, pos, array, off + read, i);
			pos += i;
			avail -= i;
			read += i;
			remaining -= i;
			if (remaining == 0) {
				readBytes += read;
				return read; // We did not stop because of a terminator
			}

			if (avail > 0) { // We met a terminator
				if (k == '\n') { // LF first
					pos++;
					avail--;
					if (terminators.contains(LineTerminator.LF)) {
						readBytes += read + 1;
						return read;
					}
					else {
						array[off + read++] = '\n';
						remaining--;
					}
				}
				else if (k == '\r') { // CR first
					pos++;
					avail--;

					if (terminators.contains(LineTerminator.CR_LF)) {
						if (avail > 0) {
							if (buffer[pos] == '\n') { // CR/LF with LF already in the buffer.
								pos ++;
								avail--;
								readBytes += read + 2;
								return read;
							}
						}
						else { // We must search for the LF.
							if (noMoreCharacters()) {
								// Not found a matching LF because of end of file, will return CR in buffer if not a terminator

								if (! terminators.contains(LineTerminator.CR)) {
									array[off + read++] = '\r';
									remaining--;
									readBytes += read;
								}
								else readBytes += read + 1;

								return read;
							}
							if (buffer[0] == '\n') {
								// Found matching LF, won't return terminators in the buffer
								pos++;
								avail--;
								readBytes += read + 2;
								return read;
							}
						}
					}

					if (terminators.contains(LineTerminator.CR)) {
						readBytes += read + 1;
						return read;
					}

					array[off + read++] = '\r';
					remaining--;
				}
			}
			else if (noMoreCharacters()) {
				readBytes += read;
				return read;
			}
		}
	}

Reads a line into the given byte-array fragment.

Reading lines (i.e., characters) out of a byte stream is not always sensible
(methods available to that purpose in old versions of Java have been mercilessly deprecated).
Nonetheless, in several situations, such as when decoding network protocols or headers
known to be ASCII, it is very useful to be able to read a line from a byte stream.

This method will attempt to read the next line into {@code array} starting at {@code off},
reading at most {@code len} bytes. The read, however, will be stopped by the end of file or
when meeting a {@linkplain LineTerminator line terminator}. Of course, for this operation
to be sensible the encoding of the text contained in the stream, if any, must not generate spurious
carriage returns or line feeds. Note that the termination detection uses a maximisation
criterion, so if you specify both {@link LineTerminator#CR} and
{@link LineTerminator#CR_LF} meeting a pair CR/LF will consider the whole pair a terminator.

Terminators are not copied into array or included in the returned count. The
returned integer can be used to check whether the line is complete: if it is smaller than
{@code len}, then more bytes might be available, but note that this method (contrarily
to {@link #read(byte[], int, int)}) can legitimately return zero when {@code len}
is nonzero just because a terminator was found as the first character. Thus, the intended
usage of this method is to call it on a given array, check whether {@code len} bytes
have been read, and if so try again (possibly extending the array) until a number of read bytes
strictly smaller than {@code len} (possibly, -1) is returned.

If you need to guarantee that a full line is read, use the following idiom:

int start = off, len;
while((len = fbis.readLine(array, start, array.length - start, terminators)) == array.length - start) {
start += len;
array = ByteArrays.grow(array, array.length + 1);
}

At the end of the loop, the line will be placed in {@code array} starting at
{@code off} (inclusive) and ending at {@code start + Math.max(len, 0)} (exclusive).

@param array byte array where the next line will be stored.
@param off the first byte to use in {@code array}.
@param len the maximum number of bytes to read.
@param terminators a set containing the line termination sequences that we want
to consider as valid.
@return the number of bytes actually placed in {@code array}, or -1 at end of file.
Note that the returned number will be {@code len} if no line termination sequence
specified in {@code terminators} has been met before scanning {@code len} byte,
and if also we did not meet the end of file.

Reads a line into the given byte - array fragment .


private long skipByReading(final long n) throws IOException {
		long toSkip = n;
		int len;
		while(toSkip > 0) {
			len = is.read(buffer, 0, (int)Math.min(buffer.length, toSkip));
			if (len > 0) toSkip -= len;
			else break;
		}

		return n - toSkip;
	}

private long skipByReading ( final long n ) throws IOException { long toSkip = n ; int len ; while ( toSkip > 0 ) { len = is . read ( buffer , 0 , ( int ) Math . min ( buffer . length , toSkip ) ) ; if ( len > 0 ) toSkip -= len ; else break ; } return n - toSkip ; }

Skips the given amount of bytes by repeated reads.

Warning: this method uses destructively the internal buffer.

@param n the number of bytes to skip.
@return the number of bytes actually skipped.
@see InputStream#skip(long)

Skips the given amount of bytes by repeated reads .


@Override
	public long skip(final long n) throws IOException {
		if (n <= avail) {
			final int m = (int)n;
			pos += m;
			avail -= m;
			readBytes += n;
			return n;
		}

		long toSkip = n - avail, result = 0;
		avail = 0;

		while (toSkip != 0 && (result = is == System.in ? skipByReading(toSkip) : is.skip(toSkip)) < toSkip) {
			if (result == 0) {
				if (is.read() == -1) break;
				toSkip--;
			}
			else toSkip -= result;
		}

		final long t = n - (toSkip - result);
		readBytes += t;
		return t;
	}

@ Override public long skip ( final long n ) throws IOException { if ( n <= avail ) { final int m = ( int ) n ; pos += m ; avail -= m ; readBytes += n ; return n ; } long toSkip = n - avail , result = 0 ; avail = 0 ; while ( toSkip != 0 && ( result = is == System . in ? skipByReading ( toSkip ) : is . skip ( toSkip ) ) < toSkip ) { if ( result == 0 ) { if ( is . read ( ) == - 1 ) break ; toSkip -- ; } else toSkip -= result ; } final long t = n - ( toSkip - result ) ; readBytes += t ; return t ; }

Skips over and discards the given number of bytes of data from this fast buffered input stream.

As explained in the {@linkplain FastBufferedInputStream class documentation}, the semantics
of {@link InputStream#skip(long)} is fatally flawed. This method provides additional semantics as follows:
it will skip the provided number of bytes, unless the end of file has been reached.

Additionally, if the underlying input stream is {@link System#in} this method will use
repeated reads instead of invoking {@link InputStream#skip(long)}.

@param n the number of bytes to skip.
@return the number of bytes actually skipped; it can be smaller than {@code n}
only if the end of file has been reached.
@see InputStream#skip(long)

Skips over and discards the given number of bytes of data from this fast buffered input stream .


public static void ensureOffsetLength(final int arrayLength, final int offset, final int length) {
		if (offset < 0) throw new ArrayIndexOutOfBoundsException("Offset (" + offset + ") is negative");
		if (length < 0) throw new IllegalArgumentException("Length (" + length + ") is negative");
		if (offset + length > arrayLength) throw new ArrayIndexOutOfBoundsException("Last index (" + (offset + length) + ") is greater than array length (" + arrayLength + ")");
	}

public
static
void
ensureOffsetLength
(
final
int
arrayLength
,
final
int
offset
,
final
int
length
)
{
if
(
offset
<
0
)
throw
new
ArrayIndexOutOfBoundsException
(
"Offset ("
+
offset
+
") is negative"
)
;
if
(
length
<
0
)
throw
new
IllegalArgumentException
(
"Length ("
+
length
+
") is negative"
)
;
if
(
offset
+
length
>
arrayLength
)
throw
new
ArrayIndexOutOfBoundsException
(
"Last index ("
+
(
offset
+
length
)
+
") is greater than array length ("
+
arrayLength
+
")"
)
;
}

Ensures that a range given by an offset and a length fits an array of given length.

<p>This method may be used whenever an array range check is needed.

@param arrayLength an array length.
@param offset a start index for the fragment
@param length a length (the number of elements in the fragment).
@throws IllegalArgumentException if {@code length} is negative.
@throws ArrayIndexOutOfBoundsException if {@code offset} is negative or {@code offset}+{@code length} is greater than {@code arrayLength}.

Ensures that a range given by an offset and a length fits an array of given length .


public static void mergeSort(final int from, final int to, final IntComparator c, final Swapper swapper) {
		/*
		 * We retain the same method signature as quickSort. Given only a comparator and swapper we
		 * do not know how to copy and move elements from/to temporary arrays. Hence, in contrast to
		 * the JDK mergesorts this is an "in-place" mergesort, i.e. does not allocate any temporary
		 * arrays. A non-inplace mergesort would perhaps be faster in most cases, but would require
		 * non-intuitive delegate objects...
		 */
		final int length = to - from;

		// Insertion sort on smallest arrays
		if (length < MERGESORT_NO_REC) {
			for (int i = from; i < to; i++) {
				for (int j = i; j > from && (c.compare(j - 1, j) > 0); j--) {
					swapper.swap(j, j - 1);
				}
			}
			return;
		}

		// Recursively sort halves
		int mid = (from + to) >>> 1;
		mergeSort(from, mid, c, swapper);
		mergeSort(mid, to, c, swapper);

		// If list is already sorted, nothing left to do. This is an
		// optimization that results in faster sorts for nearly ordered lists.
		if (c.compare(mid - 1, mid) <= 0) return;

		// Merge sorted halves
		inPlaceMerge(from, mid, to, c, swapper);
	}

Sorts the specified range of elements using the specified swapper and according to the order induced by the specified
comparator using mergesort.

This sort is guaranteed to be stable: equal elements will not be reordered as a result
of the sort. The sorting algorithm is an in-place mergesort that is significantly slower than a
standard mergesort, as its running time is O(<var>n</var> (log <var>n</var>)2), but it does not allocate additional memory; as a result, it can be
used as a generic sorting algorithm.

@param from the index of the first element (inclusive) to be sorted.
@param to the index of the last element (exclusive) to be sorted.
@param c the comparator to determine the order of the generic data (arguments are positions).
@param swapper an object that knows how to swap the elements at any two positions.

Sorts the specified range of elements using the specified swapper and according to the order induced by the specified comparator using mergesort .


protected static void swap(final Swapper swapper, int a, int b, final int n) {
		for (int i = 0; i < n; i++, a++, b++) swapper.swap(a, b);
	}

protected static void swap ( final Swapper swapper , int a , int b , final int n ) { for ( int i = 0 ; i < n ; i ++ , a ++ , b ++ ) swapper . swap ( , b ) ; }

Swaps two sequences of elements using a provided swapper.

@param swapper the swapper.
@param a a position in {@code x}.
@param b another position in {@code x}.
@param n the number of elements to exchange starting at {@code a} and {@code b}.

Swaps two sequences of elements using a provided swapper .


public static void parallelQuickSort(final int from, final int to, final IntComparator comp, final Swapper swapper) {
		final ForkJoinPool pool = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
		pool.invoke(new ForkJoinGenericQuickSort(from, to, comp, swapper));
		pool.shutdown();
	}

public static void parallelQuickSort ( final int from , final int to , final IntComparator comp , final Swapper swapper ) { final ForkJoinPool pool = new ForkJoinPool ( Runtime . getRuntime ( ) . availableProcessors ( ) ) ; pool . invoke ( new ForkJoinGenericQuickSort ( from , to , comp , swapper ) ) ; pool . shutdown ( ) ; }

Sorts the specified range of elements using the specified swapper and according to the order induced by the specified
comparator using a parallel quicksort.

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages
1249−1265, 1993.

This implementation uses a {@link ForkJoinPool} executor service with {@link Runtime#availableProcessors()} parallel threads.

@param from the index of the first element (inclusive) to be sorted.
@param to the index of the last element (exclusive) to be sorted.
@param comp the comparator to determine the order of the generic data.
@param swapper an object that knows how to swap the elements at any two positions.

Sorts the specified range of elements using the specified swapper and according to the order induced by the specified comparator using a parallel quicksort .


public static int murmurHash3(int x) {
		x ^= x >>> 16;
		x *= 0x85ebca6b;
		x ^= x >>> 13;
		x *= 0xc2b2ae35;
		x ^= x >>> 16;
		return x;
	}

public static int murmurHash3 ( int x ) { x ^= x >>> 16 ; x *= 0x85ebca6b ; x ^= x >>> 13 ; x *= 0xc2b2ae35 ; x ^= x >>> 16 ; return x ; }

Avalanches the bits of an integer by applying the finalisation step of MurmurHash3.

This method implements the finalisation step of Austin Appleby's MurmurHash3.
Its purpose is to avalanche the bits of the argument to within 0.25% bias.

@param x an integer.
@return a hash value with good avalanching properties.

Avalanches the bits of an integer by applying the finalisation step of MurmurHash3 .


public static long murmurHash3(long x) {
		x ^= x >>> 33;
		x *= 0xff51afd7ed558ccdL;
		x ^= x >>> 33;
		x *= 0xc4ceb9fe1a85ec53L;
		x ^= x >>> 33;
		return x;
	}

public static long murmurHash3 ( long x ) { x ^= x >>> 33 ; x *= 0xff51afd7ed558ccd L ; x ^= x >>> 33 ; x *= 0xc4ceb9fe1a85ec53 L ; x ^= x >>> 33 ; return x ; }

Avalanches the bits of a long integer by applying the finalisation step of MurmurHash3.

This method implements the finalisation step of Austin Appleby's MurmurHash3.
Its purpose is to avalanche the bits of the argument to within 0.25% bias.

@param x a long integer.
@return a hash value with good avalanching properties.

Avalanches the bits of a long integer by applying the finalisation step of MurmurHash3 .


@Override
	public int write(final ByteBuffer byteBuffer) throws IOException {
		ensureOpen();
		final int remaining = byteBuffer.remaining();

		if (inspectable < buffer.length) {
			// Still some space in the inspectable buffer.
			final int toBuffer = Math.min(buffer.length - inspectable, remaining);
			byteBuffer.get(buffer, inspectable, toBuffer);
			inspectable += toBuffer;
		}

		if (byteBuffer.hasRemaining()) {
			fileChannel.position(writePosition);
			writePosition += fileChannel.write(byteBuffer);
		}

		return remaining;
	}

Appends the content of a specified buffer to the end of the currently represented stream.

@param byteBuffer a byte buffer.
@return the number of bytes appended (i.e., {@link ByteBuffer#remaining() byteBuffer.remaining()}).

Appends the content of a specified buffer to the end of the currently represented stream .


public void truncate(final long size) throws FileNotFoundException, IOException {
		fileChannel.truncate(Math.max(size, writePosition));
	}

public void truncate ( final long size ) throws FileNotFoundException , IOException { fileChannel . truncate ( Math . max ( size , writePosition ) ) ; }

Truncates the overflow file to a given size if possible.

@param size the new size; the final size is the maximum between the current write position (i.e., the length
of the represented stream minus the length of the inspection buffer) and this value.

Truncates the overflow file to a given size if possible .


@Override
	public void position(final long newPosition) throws IOException {
		flush();
		if (repositionableStream != null) repositionableStream.position(newPosition);
		else if (fileChannel != null) fileChannel.position(newPosition);
		else throw new UnsupportedOperationException("position() can only be called if the underlying byte stream implements the RepositionableStream interface or if the getChannel() method of the underlying byte stream exists and returns a FileChannel");
	}

Repositions the stream.

<p>Note that this method performs a {@link #flush()} before changing the underlying stream position.


private final void noFailRefreshEndMetricsReporting(ConsumerRefreshMetrics refreshMetrics) {
        try {
            refreshEndMetricsReporting(refreshMetrics);
        } catch (Exception e) {
            // Metric reporting is not considered critical to consumer refresh. Log exceptions and continue.
            log.log(Level.SEVERE, "Encountered an exception in reporting consumer refresh metrics, ignoring exception and continuing with consumer refresh", e);
        }
    }

Metrics reporting implementation is provided by the extending subclass. If exceptions are not gracefully handled
in the extending subclass then an exception there can fail the consumer refresh, even though metrics reporting
might not be mission critical. This method protects against that scenario by catching all exceptions, logging
that there was an exception, and continuing with the consumer refresh.
@param refreshMetrics Consumer refresh metrics being reported

Metrics reporting implementation is provided by the extending subclass . If exceptions are not gracefully handled in the extending subclass then an exception there can fail the consumer refresh even though metrics reporting might not be mission critical . This method protects against that scenario by catching all exceptions logging that there was an exception and continuing with the consumer refresh .


public void awaitSuccessfulCompletionOfCurrentTasks() throws InterruptedException, ExecutionException {
        for(Future<?> f : futures) {
            f.get();
        }

        futures.clear();
    }

public void awaitSuccessfulCompletionOfCurrentTasks ( ) throws InterruptedException , ExecutionException { for ( Future < ? > f : futures ) { f . get ( ) ; } futures . clear ( ) ; }

Await successful completion of all previously submitted tasks.  Throw exception of the first failed task
if 1 or more tasks failed.

After this call completes, the thread pool will <i>not</i> be shut down and can be reused.

@throws ExecutionException if a computation threw an
exception
@throws InterruptedException if the current thread was interrupted
while waiting

Await successful completion of all previously submitted tasks . Throw exception of the first failed task if 1 or more tasks failed .


public Stream<S> findMatches(Q query) {
        Object[] queryArray = matchFields.stream().map(mf -> mf.extract(query)).toArray();

        HollowHashIndexResult matches = hhi.findMatches(queryArray);
        if (matches == null) {
            return Stream.empty();
        }

        return matches.stream().mapToObj(i -> selectField.extract(api, i));
    }

public Stream < S > findMatches ( Q query ) { Object [ ] queryArray = matchFields . stream ( ) . map ( mf -> mf . extract ( query ) ) . toArray ( ) ; HollowHashIndexResult matches = hhi . findMatches ( queryArray ) ; if ( matches == null ) { return Stream . empty ( ) ; } return matches . stream ( ) . mapToObj ( i -> selectField . extract ( api , i ) ) ; }

Finds matches for a given query.

@param query the query
@return a stream of matching records (may be empty if there are no matches)


private Set<String> findCompactionTargets() {
        List<HollowSchema> schemas = HollowSchemaSorter.dependencyOrderedSchemaList(readEngine.getSchemas());
        Set<String> typesToCompact = new HashSet<String>();

        for(HollowSchema schema : schemas) {
            if(isCompactionCandidate(schema.getName())) {
                if(!candidateIsDependentOnAnyTargetedType(schema.getName(), typesToCompact))
                    typesToCompact.add(schema.getName());
            }
        }

        return typesToCompact;
    }

private Set < String > findCompactionTargets ( ) { List < HollowSchema > schemas = HollowSchemaSorter . dependencyOrderedSchemaList ( readEngine . getSchemas ( ) ) ; Set < String > typesToCompact = new HashSet < String > ( ) ; for ( HollowSchema schema : schemas ) { if ( isCompactionCandidate ( schema . getName ( ) ) ) { if ( ! candidateIsDependentOnAnyTargetedType ( schema . getName ( ) , typesToCompact ) ) typesToCompact . add ( schema . getName ( ) ) ; } } return typesToCompact ; }

Find candidate types for compaction.  No two types in the returned set will have a dependency relationship, either
directly or transitively.

Find candidate types for compaction . No two types in the returned set will have a dependency relationship either directly or transitively .


@Override
    public void cleanSnapshots() {
        File[] files = getFilesByType(HollowProducer.Blob.Type.SNAPSHOT.prefix);

        if(files == null || files.length <= numOfSnapshotsToKeep) {
            return;
        }

        sortByLastModified(files);

        for(int i= numOfSnapshotsToKeep; i < files.length; i++){
            File file = files[i];
            boolean deleted = file.delete();
            if(!deleted) {
                log.warning("Could not delete snapshot " + file.getPath());
            }
        }
    }

@
Override
public
void
cleanSnapshots
(
)
{
File
[
]
files
=
getFilesByType
(
HollowProducer
.
Blob
.
Type
.
SNAPSHOT
.
prefix
)
;
if
(
files
==
||
files
.
length
<=
numOfSnapshotsToKeep
)
{
return
;
}
sortByLastModified
(
files
)
;
for
(
int
i
=
numOfSnapshotsToKeep
;
i
<
files
.
length
;
i
++
)
{
File
file
=
files
[
i
]
;
boolean
deleted
=
file
.
delete
(
)
;
if
(
!
deleted
)
{
log
.
warning
(
"Could not delete snapshot "
+
file
.
getPath
(
)
)
;
}
}
}

Cleans snapshot to keep the last 'n' snapshots. Defaults to 5.

Cleans snapshot to keep the last n snapshots . Defaults to 5 .


public static int fieldHashCode(HollowObjectTypeDataAccess typeAccess, int ordinal, int fieldPosition) {
        HollowObjectSchema schema = typeAccess.getSchema();

        switch(schema.getFieldType(fieldPosition)) {
            case BOOLEAN:
                Boolean bool = typeAccess.readBoolean(ordinal, fieldPosition);
                return booleanHashCode(bool);
            case BYTES:
            case STRING:
                return typeAccess.findVarLengthFieldHashCode(ordinal, fieldPosition);
            case DOUBLE:
                double d = typeAccess.readDouble(ordinal, fieldPosition);
                return doubleHashCode(d);
            case FLOAT:
                float f = typeAccess.readFloat(ordinal, fieldPosition);
                return floatHashCode(f);
            case INT:
                return intHashCode(typeAccess.readInt(ordinal, fieldPosition));
            case LONG:
                long l = typeAccess.readLong(ordinal, fieldPosition);
                return longHashCode(l);
            case REFERENCE:
                return typeAccess.readOrdinal(ordinal, fieldPosition);
        }

        throw new IllegalStateException("I don't know how to hash a " + schema.getFieldType(fieldPosition));
    }

public
static
int
fieldHashCode
(
HollowObjectTypeDataAccess
typeAccess
,
int
ordinal
,
int
fieldPosition
)
{
HollowObjectSchema
schema
=
typeAccess
.
getSchema
(
)
;
switch
(
schema
.
getFieldType
(
fieldPosition
)
)
{
case
BOOLEAN
:
Boolean
bool
=
typeAccess
.
readBoolean
(
ordinal
,
fieldPosition
)
;
return
booleanHashCode
(
bool
)
;
case
BYTES
:
case
STRING
:
return
typeAccess
.
findVarLengthFieldHashCode
(
ordinal
,
fieldPosition
)
;
case
DOUBLE
:
double
d
=
typeAccess
.
readDouble
(
ordinal
,
fieldPosition
)
;
return
doubleHashCode
(
d
)
;
case
FLOAT
:
float
f
=
typeAccess
.
readFloat
(
ordinal
,
fieldPosition
)
;
return
floatHashCode
(
f
)
;
case
INT
:
return
intHashCode
(
typeAccess
.
readInt
(
ordinal
,
fieldPosition
)
)
;
case
LONG
:
long
l
=
typeAccess
.
readLong
(
ordinal
,
fieldPosition
)
;
return
longHashCode
(
l
)
;
case
REFERENCE
:
return
typeAccess
.
readOrdinal
(
ordinal
,
fieldPosition
)
;
}
throw
new
IllegalStateException
(
"I don't know how to hash a "
+
schema
.
getFieldType
(
fieldPosition
)
)
;
}

Hash a field in an OBJECT record.

@param typeAccess the data access
@param ordinal the ordinal
@param fieldPosition the field position
@return the hash code


public static boolean fieldsAreEqual(HollowObjectTypeDataAccess typeAccess1, int ordinal1, int fieldPosition1, HollowObjectTypeDataAccess typeAccess2, int ordinal2, int fieldPosition2) {
        HollowObjectSchema schema1 = typeAccess1.getSchema();

        switch(schema1.getFieldType(fieldPosition1)) {
            case BOOLEAN:
                Boolean bool1 = typeAccess1.readBoolean(ordinal1, fieldPosition1);
                Boolean bool2 = typeAccess2.readBoolean(ordinal2, fieldPosition2);
                return bool1 == bool2;
            case BYTES:
                byte[] data1 = typeAccess1.readBytes(ordinal1, fieldPosition1);
                byte[] data2 = typeAccess2.readBytes(ordinal2, fieldPosition2);
                return Arrays.equals(data1, data2);
            case DOUBLE:
                double d1 = typeAccess1.readDouble(ordinal1, fieldPosition1);
                double d2 = typeAccess2.readDouble(ordinal2, fieldPosition2);
                return Double.compare(d1, d2) == 0;
            case FLOAT:
                float f1 = typeAccess1.readFloat(ordinal1, fieldPosition1);
                float f2 = typeAccess2.readFloat(ordinal2, fieldPosition2);
                return Float.compare(f1, f2) == 0;
            case INT:
                int i1 = typeAccess1.readInt(ordinal1, fieldPosition1);
                int i2 = typeAccess2.readInt(ordinal2, fieldPosition2);
                return i1 == i2;
            case LONG:
                long l1 = typeAccess1.readLong(ordinal1, fieldPosition1);
                long l2 = typeAccess2.readLong(ordinal2, fieldPosition2);
                return l1 == l2;
            case STRING:
                String s1 = typeAccess1.readString(ordinal1, fieldPosition1);
                return typeAccess2.isStringFieldEqual(ordinal2, fieldPosition2, s1);
            case REFERENCE:
                if(typeAccess1 == typeAccess2 && fieldPosition1 == fieldPosition2)
                    return typeAccess1.readOrdinal(ordinal1, fieldPosition1) == typeAccess2.readOrdinal(ordinal2, fieldPosition2);
            default:
        }

        throw new IllegalStateException("I don't know how to test equality for a " + schema1.getFieldType(fieldPosition1));
    }

Determine whether two OBJECT field records are exactly equal.

@param typeAccess1 the first type access
@param ordinal1 the first ordinal
@param fieldPosition1 the first field positiom
@param typeAccess2 the second type access
@param ordinal2 the second ordinal
@param fieldPosition2 the second field position

@return if the two OBJECT field records are exactly equal

Determine whether two OBJECT field records are exactly equal .


public static void removeReferencedOutsideClosure(HollowReadStateEngine stateEngine, Map<String, BitSet> matches) {
        List<HollowSchema> orderedSchemas = HollowSchemaSorter.dependencyOrderedSchemaList(stateEngine);
        Collections.reverse(orderedSchemas);

        for(HollowSchema referencedSchema : orderedSchemas) {
            if(matches.containsKey(referencedSchema.getName())) {
                for(HollowSchema referencerSchema : orderedSchemas) {
                    if(referencerSchema == referencedSchema)
                        break;

                    if(matches.containsKey(referencedSchema.getName()) && matches.get(referencedSchema.getName()).cardinality() > 0)
                        traverseReferencesOutsideClosure(stateEngine, referencerSchema.getName(), referencedSchema.getName(), matches, REMOVE_REFERENCED_OUTSIDE_CLOSURE);
                }
            }
        }
    }

public static void removeReferencedOutsideClosure ( HollowReadStateEngine stateEngine , Map < String , BitSet > matches ) { List < HollowSchema > orderedSchemas = HollowSchemaSorter . dependencyOrderedSchemaList ( stateEngine ) ; Collections . reverse ( orderedSchemas ) ; for ( HollowSchema referencedSchema : orderedSchemas ) { if ( matches . containsKey ( referencedSchema . getName ( ) ) ) { for ( HollowSchema referencerSchema : orderedSchemas ) { if ( referencerSchema == referencedSchema ) break ; if ( matches . containsKey ( referencedSchema . getName ( ) ) && matches . get ( referencedSchema . getName ( ) ) . cardinality ( ) > 0 ) traverseReferencesOutsideClosure ( stateEngine , referencerSchema . getName ( ) , referencedSchema . getName ( ) , matches , REMOVE_REFERENCED_OUTSIDE_CLOSURE ) ; } } } }

Remove any records from the given selection which are referenced by other records not in the selection.
@param stateEngine the state engine
@param matches the matches

Remove any records from the given selection which are referenced by other records not in the selection .


@Override
    public void onAnnouncementComplete(com.netflix.hollow.api.producer.Status status, HollowProducer.ReadState readState, long version, Duration elapsed) {
        boolean isAnnouncementSuccess = false;
        long dataSizeBytes = 0l;

        if (status.getType() == com.netflix.hollow.api.producer.Status.StatusType.SUCCESS) {
            isAnnouncementSuccess = true;
            lastAnnouncementSuccessTimeNanoOptional = OptionalLong.of(System.nanoTime());
        }

        HollowReadStateEngine stateEngine = readState.getStateEngine();
        dataSizeBytes = stateEngine.calcApproxDataSize();

        announcementMetricsBuilder
                .setDataSizeBytes(dataSizeBytes)
                .setIsAnnouncementSuccess(isAnnouncementSuccess)
                .setAnnouncementDurationMillis(elapsed.toMillis());

        lastAnnouncementSuccessTimeNanoOptional.ifPresent(announcementMetricsBuilder::setLastAnnouncementSuccessTimeNano);

        announcementMetricsReporting(announcementMetricsBuilder.build());
    }

@ Override public void onAnnouncementComplete ( com . netflix . hollow . api . producer . Status status , HollowProducer . ReadState readState , long version , Duration elapsed ) { boolean isAnnouncementSuccess = false ; long dataSizeBytes = 0l ; if ( status . getType ( ) == com . netflix . hollow . api . producer . Status . StatusType . SUCCESS ) { isAnnouncementSuccess = true ; lastAnnouncementSuccessTimeNanoOptional = OptionalLong . of ( System . nanoTime ( ) ) ; } HollowReadStateEngine stateEngine = readState . getStateEngine ( ) ; dataSizeBytes = stateEngine . calcApproxDataSize ( ) ; announcementMetricsBuilder . setDataSizeBytes ( dataSizeBytes ) . setIsAnnouncementSuccess ( isAnnouncementSuccess ) . setAnnouncementDurationMillis ( elapsed . toMillis ( ) ) ; lastAnnouncementSuccessTimeNanoOptional . ifPresent ( announcementMetricsBuilder :: setLastAnnouncementSuccessTimeNano ) ; announcementMetricsReporting ( announcementMetricsBuilder . build ( ) ) ; }

Reports announcement-related metrics.
@param status Indicates whether the announcement succeeded of failed
@param readState Hollow data state that is being published, used in this method for computing data size
@param version Version of data that was announced
@param elapsed Announcement start to end duration

Reports announcement - related metrics .


@Override
    public void onCycleComplete(com.netflix.hollow.api.producer.Status status, HollowProducer.ReadState readState, long version, Duration elapsed) {
        boolean isCycleSuccess;
        long cycleEndTimeNano = System.nanoTime();

        if (status.getType() == com.netflix.hollow.api.producer.Status.StatusType.SUCCESS) {
            isCycleSuccess = true;
            consecutiveFailures = 0l;
            lastCycleSuccessTimeNanoOptional = OptionalLong.of(cycleEndTimeNano);
        } else {
            isCycleSuccess = false;
            consecutiveFailures ++;
        }

        cycleMetricsBuilder
                .setConsecutiveFailures(consecutiveFailures)
                .setCycleDurationMillis(elapsed.toMillis())
                .setIsCycleSuccess(isCycleSuccess);

        lastCycleSuccessTimeNanoOptional.ifPresent(cycleMetricsBuilder::setLastCycleSuccessTimeNano);

        cycleMetricsReporting(cycleMetricsBuilder.build());
    }

@ Override public void onCycleComplete ( com . netflix . hollow . api . producer . Status status , HollowProducer . ReadState readState , long version , Duration elapsed ) { boolean isCycleSuccess ; long cycleEndTimeNano = System . nanoTime ( ) ; if ( status . getType ( ) == com . netflix . hollow . api . producer . Status . StatusType . SUCCESS ) { isCycleSuccess = true ; consecutiveFailures = 0l ; lastCycleSuccessTimeNanoOptional = OptionalLong . of ( cycleEndTimeNano ) ; } else { isCycleSuccess = false ; consecutiveFailures ++ ; } cycleMetricsBuilder . setConsecutiveFailures ( consecutiveFailures ) . setCycleDurationMillis ( elapsed . toMillis ( ) ) . setIsCycleSuccess ( isCycleSuccess ) ; lastCycleSuccessTimeNanoOptional . ifPresent ( cycleMetricsBuilder :: setLastCycleSuccessTimeNano ) ; cycleMetricsReporting ( cycleMetricsBuilder . build ( ) ) ; }

On cycle completion this method reports cycle metrics.
@param status Whether the cycle succeeded or failed
@param readState Hollow data state published by cycle, not used here because data size is known from when announcement completed
@param version Version of data that was published in this cycle
@param elapsed Cycle start to end duration

On cycle completion this method reports cycle metrics .


private Map<String, String> readHeaderTags(DataInputStream dis) throws IOException {
        int numHeaderTags = dis.readShort();
        Map<String, String> headerTags = new HashMap<String, String>();
        for (int i = 0; i < numHeaderTags; i++) {
            headerTags.put(dis.readUTF(), dis.readUTF());
        }
        return headerTags;
    }

private Map < String , String > readHeaderTags ( DataInputStream dis ) throws IOException { int numHeaderTags = dis . readShort ( ) ; Map < String , String > headerTags = new HashMap < String , String > ( ) ; for ( int i = 0 ; i < numHeaderTags ; i ++ ) { headerTags . put ( dis . readUTF ( ) , dis . readUTF ( ) ) ; } return headerTags ; }

Map of string header tags reading.

@param dis
@throws IOException


public RecordPrimaryKey extractPrimaryKey(Object o) {
        HollowObjectTypeMapper typeMapper = (HollowObjectTypeMapper) getTypeMapper(o.getClass(), null, null);
        return new RecordPrimaryKey(typeMapper.getTypeName(), typeMapper.extractPrimaryKey(o));
    }

public RecordPrimaryKey extractPrimaryKey ( Object o ) { HollowObjectTypeMapper typeMapper = ( HollowObjectTypeMapper ) getTypeMapper ( o . getClass ( ) , null , null ) ; return new RecordPrimaryKey ( typeMapper . getTypeName ( ) , typeMapper . extractPrimaryKey ( o ) ) ; }

Extracts the primary key from the specified POJO.

@param o the POJO
@return the primary key
@throws IllegalArgumentException if the POJO does not have primary key defined

Extracts the primary key from the specified POJO .


public void clearAll() {
        ThreadSafeBitSetSegments segments = this.segments.get();

        for(int i=0;i<segments.numSegments();i++) {
            AtomicLongArray segment = segments.getSegment(i);

            for(int j=0;j<segment.length();j++) {
                segment.set(j, 0L);
            }
        }
    }

public void clearAll ( ) { ThreadSafeBitSetSegments segments = this . segments . get ( ) ; for ( int i = 0 ; i < segments . numSegments ( ) ; i ++ ) { AtomicLongArray segment = segments . getSegment ( i ) ; for ( int j = 0 ; j < segment . length ( ) ; j ++ ) { segment . set ( j , 0L ) ; } } }


public static void readOrdinals(DataInputStream dis, HollowTypeStateListener[] listeners) throws IOException {
        int numLongs = dis.readInt();

        int currentOrdinal = 0;

        for(int i=0;i<numLongs;i++) {
            long l = dis.readLong();
            notifyPopulatedOrdinals(l, currentOrdinal, listeners);
            currentOrdinal += 64;
        }
    }

public static void readOrdinals ( DataInputStream dis , HollowTypeStateListener [ ] listeners ) throws IOException { int numLongs = dis . readInt ( ) ; int currentOrdinal = 0 ; for ( int i = 0 ; i < numLongs ; i ++ ) { long l = dis . readLong ( ) ; notifyPopulatedOrdinals ( l , currentOrdinal , listeners ) ; currentOrdinal += 64 ; } }

Read populated ordinals as a bit set from a stream, and notify a listener for each populated ordinal.

@param dis the data input stream
@param listeners the type state listeners
@throws IOException if the ordinals cannot be read
@author dkoszewnik

Read populated ordinals as a bit set from a stream and notify a listener for each populated ordinal .


public long size() {
        SparseBitSet current;
        long size;
        do {
            current = sparseBitSetVolatile;
            size = current.estimateBitsUsed();
        } while (current != sparseBitSetVolatile);
        return size;
    }

public long size ( ) { SparseBitSet current ; long size ; do { current = sparseBitSetVolatile ; size = current . estimateBitsUsed ( ) ; } while ( current != sparseBitSetVolatile ) ; return size ; }

Estimate the total number of bits used to represent the integer set.

@return Calculates the total number of bits used by longs in underlying data structure.

Estimate the total number of bits used to represent the integer set .


private static String getFieldValue(HollowDiffViewRow row, boolean useFrom) {
        Field field = useFrom ? row.getFieldPair().getFrom() : row.getFieldPair().getTo();
        if (row.getFieldPair().isLeafNode()) {
          return field.getValue() == null ? "null"
              : field.getValue().toString().replace("|", "&#x2502");
        } else {
            String suffix = field.getValue() == null ? " [null]" : "";
            return "(" + field.getTypeName() + ")" + suffix;
        }
    }

private
static
String
getFieldValue
(
HollowDiffViewRow
row
,
boolean
useFrom
)
{
Field
field
=
useFrom
row
.
getFieldPair
(
)
.
getFrom
(
)
:
row
.
getFieldPair
(
)
.
getTo
(
)
;
if
(
row
.
getFieldPair
(
)
.
isLeafNode
(
)
)
{
return
field
.
getValue
(
)
==
"null"
:
field
.
getValue
(
)
.
toString
(
)
.
replace
(
"|"
,
"&#x2502"
)
;
}
else
{
String
suffix
=
field
.
getValue
(
)
==
" [null]"
:
""
;
return
"("
+
field
.
getTypeName
(
)
+
")"
+
suffix
;
}
}

Returns a String representation of the provided row's field value. If `useFrom` is
true, this will use the `from` value from the pair, otherwise this will use the
`to` value.

Returns a String representation of the provided row s field value . If useFrom is true this will use the from value from the pair otherwise this will use the to value .


public void copy(ByteData src, long srcPos, long destPos, long length) {
        for(long i=0;i<length;i++) {
            set(destPos++, src.get(srcPos++));
        }
    }

public void copy ( ByteData src , long srcPos , long destPos , long length ) { for ( long i = 0 ; i < length ; i ++ ) { set ( destPos ++ , src . get ( srcPos ++ ) ) ; } }

Copy bytes from another ByteData to this array.

@param src the source data
@param srcPos the position to begin copying from the source data
@param destPos the position to begin writing in this array
@param length the length of the data to copy

Copy bytes from another ByteData to this array .


public int copy(long srcPos, byte[] data, int destPos, int length) {
        int segmentSize = 1 << log2OfSegmentSize;
        int remainingBytesInSegment = (int)(segmentSize - (srcPos & bitmask));
        int dataPosition = destPos;

        while(length > 0) {
            byte[] segment = segments[(int)(srcPos >>> log2OfSegmentSize)];

            int bytesToCopyFromSegment = Math.min(remainingBytesInSegment, length);

            System.arraycopy(segment, (int)(srcPos & bitmask), data, dataPosition, bytesToCopyFromSegment);

            dataPosition += bytesToCopyFromSegment;
            srcPos += bytesToCopyFromSegment;
            remainingBytesInSegment = segmentSize - (int)(srcPos & bitmask);
            length -= bytesToCopyFromSegment;
        }

        return dataPosition - destPos;
    }

public int copy ( long srcPos , byte [ ] data , int destPos , int length ) { int segmentSize = 1 << log2OfSegmentSize ; int remainingBytesInSegment = ( int ) ( segmentSize - ( srcPos & bitmask ) ) ; int dataPosition = destPos ; while ( length > 0 ) { byte [ ] segment = segments [ ( int ) ( srcPos >>> log2OfSegmentSize ) ] ; int bytesToCopyFromSegment = Math . min ( remainingBytesInSegment , length ) ; System . arraycopy ( segment , ( int ) ( srcPos & bitmask ) , data , dataPosition , bytesToCopyFromSegment ) ; dataPosition += bytesToCopyFromSegment ; srcPos += bytesToCopyFromSegment ; remainingBytesInSegment = segmentSize - ( int ) ( srcPos & bitmask ) ; length -= bytesToCopyFromSegment ; } return dataPosition - destPos ; }

copies exactly data.length bytes from this SegmentedByteArray into the provided byte array

@param srcPos the position to begin copying from the source data
@param data the source data
@param destPos the position to begin writing in this array
@param length the length of the data to copy
@return the number of bytes copied

copies exactly data . length bytes from this SegmentedByteArray into the provided byte array


public boolean rangeEquals(long rangeStart, SegmentedByteArray compareTo, long cmpStart, int length) {
    	for(int i=0;i<length;i++)
    		if(get(rangeStart + i) != compareTo.get(cmpStart + i))
    			return false;
    	return true;
    }

public boolean rangeEquals ( long rangeStart , SegmentedByteArray compareTo , long cmpStart , int length ) { for ( int i = 0 ; i < length ; i ++ ) if ( get ( rangeStart + i ) != compareTo . get ( cmpStart + i ) ) return false ; return true ; }

checks equality for a specified range of bytes in two arrays

@param rangeStart the start position of the comparison range in this array
@param compareTo the other array to compare
@param cmpStart the start position of the comparison range in the other array
@param length the length of the comparison range
@return


public void orderedCopy(SegmentedByteArray src, long srcPos, long destPos, long length) {
        int segmentLength = 1 << log2OfSegmentSize;
        int currentSegment = (int)(destPos >>> log2OfSegmentSize);
        int segmentStartPos = (int)(destPos & bitmask);
        int remainingBytesInSegment = segmentLength - segmentStartPos;

        while(length > 0) {
            int bytesToCopyFromSegment = (int)Math.min(remainingBytesInSegment, length);
            ensureCapacity(currentSegment);
            int copiedBytes = src.orderedCopy(srcPos, segments[currentSegment], segmentStartPos, bytesToCopyFromSegment);

            srcPos += copiedBytes;
            length -= copiedBytes;
            segmentStartPos = 0;
            remainingBytesInSegment = segmentLength;
            currentSegment++;
        }
    }

public void orderedCopy ( SegmentedByteArray src , long srcPos , long destPos , long length ) { int segmentLength = 1 << log2OfSegmentSize ; int currentSegment = ( int ) ( destPos >>> log2OfSegmentSize ) ; int segmentStartPos = ( int ) ( destPos & bitmask ) ; int remainingBytesInSegment = segmentLength - segmentStartPos ; while ( length > 0 ) { int bytesToCopyFromSegment = ( int ) Math . min ( remainingBytesInSegment , length ) ; ensureCapacity ( currentSegment ) ; int copiedBytes = src . orderedCopy ( srcPos , segments [ currentSegment ] , segmentStartPos , bytesToCopyFromSegment ) ; srcPos += copiedBytes ; length -= copiedBytes ; segmentStartPos = 0 ; remainingBytesInSegment = segmentLength ; currentSegment ++ ; } }

Copies the data from the provided source array into this array, guaranteeing that
if the update is seen by another thread, then all other writes prior to this call
are also visible to that thread.

@param src the source data
@param srcPos the position to begin copying from the source data
@param destPos the position to begin writing in this array
@param length the length of the data to copy

Copies the data from the provided source array into this array guaranteeing that if the update is seen by another thread then all other writes prior to this call are also visible to that thread .


public int orderedCopy(long srcPos, byte[] data, int destPos, int length) {
        int segmentSize = 1 << log2OfSegmentSize;
        int remainingBytesInSegment = (int)(segmentSize - (srcPos & bitmask));
        int dataPosition = destPos;

        while(length > 0) {
            byte[] segment = segments[(int)(srcPos >>> log2OfSegmentSize)];

            int bytesToCopyFromSegment = Math.min(remainingBytesInSegment, length);

            orderedCopy(segment, (int)(srcPos & bitmask), data, dataPosition, bytesToCopyFromSegment);

            dataPosition += bytesToCopyFromSegment;
            srcPos += bytesToCopyFromSegment;
            remainingBytesInSegment = segmentSize - (int)(srcPos & bitmask);
            length -= bytesToCopyFromSegment;
        }

        return dataPosition - destPos;
    }

public int orderedCopy ( long srcPos , byte [ ] data , int destPos , int length ) { int segmentSize = 1 << log2OfSegmentSize ; int remainingBytesInSegment = ( int ) ( segmentSize - ( srcPos & bitmask ) ) ; int dataPosition = destPos ; while ( length > 0 ) { byte [ ] segment = segments [ ( int ) ( srcPos >>> log2OfSegmentSize ) ] ; int bytesToCopyFromSegment = Math . min ( remainingBytesInSegment , length ) ; orderedCopy ( segment , ( int ) ( srcPos & bitmask ) , data , dataPosition , bytesToCopyFromSegment ) ; dataPosition += bytesToCopyFromSegment ; srcPos += bytesToCopyFromSegment ; remainingBytesInSegment = segmentSize - ( int ) ( srcPos & bitmask ) ; length -= bytesToCopyFromSegment ; } return dataPosition - destPos ; }

copies exactly data.length bytes from this SegmentedByteArray into the provided byte array,
guaranteeing that if the update is seen by another thread, then all other writes prior to
this call are also visible to that thread.

@param srcPos the position to begin copying from the source data
@param data the source data
@param destPos the position to begin writing in this array
@param length the length of the data to copy
@return the number of bytes copied

copies exactly data . length bytes from this SegmentedByteArray into the provided byte array guaranteeing that if the update is seen by another thread then all other writes prior to this call are also visible to that thread .


public void readFrom(InputStream is, long length) throws IOException {
        int segmentSize = 1 << log2OfSegmentSize;
        int segment = 0;

        byte scratch[] = new byte[segmentSize];

        while(length > 0) {
            ensureCapacity(segment);
            long bytesToCopy = Math.min(segmentSize, length);
            long bytesCopied = 0;
            while(bytesCopied < bytesToCopy) {
                bytesCopied += is.read(scratch, (int)bytesCopied, (int)(bytesToCopy - bytesCopied));
            }
            orderedCopy(scratch, 0, segments[segment++], 0, (int)bytesCopied);
            length -= bytesCopied;
        }
    }

public void readFrom ( InputStream is , long length ) throws IOException { int segmentSize = 1 << log2OfSegmentSize ; int segment = 0 ; byte scratch [ ] = new byte [ segmentSize ] ; while ( length > 0 ) { ensureCapacity ( segment ) ; long bytesToCopy = Math . min ( segmentSize , length ) ; long bytesCopied = 0 ; while ( bytesCopied < bytesToCopy ) { bytesCopied += is . read ( scratch , ( int ) bytesCopied , ( int ) ( bytesToCopy - bytesCopied ) ) ; } orderedCopy ( scratch , 0 , segments [ segment ++ ] , 0 , ( int ) bytesCopied ) ; length -= bytesCopied ; } }

Copy bytes from the supplied InputStream into this array.

@param is the source data
@param length the length of the data to copy
@throws IOException if the copy could not be performed

Copy bytes from the supplied InputStream into this array .


public void writeTo(OutputStream os, long startPosition, long len) throws IOException {
        int segmentSize = 1 << log2OfSegmentSize;
        int remainingBytesInSegment = segmentSize - (int)(startPosition & bitmask);
        long remainingBytesInCopy = len;

        while(remainingBytesInCopy > 0) {
            long bytesToCopyFromSegment = Math.min(remainingBytesInSegment, remainingBytesInCopy);

            os.write(segments[(int)(startPosition >>> log2OfSegmentSize)], (int)(startPosition & bitmask), (int)bytesToCopyFromSegment);

            startPosition += bytesToCopyFromSegment;
            remainingBytesInSegment = segmentSize - (int)(startPosition & bitmask);
            remainingBytesInCopy -= bytesToCopyFromSegment;
        }
    }

public void writeTo ( OutputStream os , long startPosition , long len ) throws IOException { int segmentSize = 1 << log2OfSegmentSize ; int remainingBytesInSegment = segmentSize - ( int ) ( startPosition & bitmask ) ; long remainingBytesInCopy = len ; while ( remainingBytesInCopy > 0 ) { long bytesToCopyFromSegment = Math . min ( remainingBytesInSegment , remainingBytesInCopy ) ; os . write ( segments [ ( int ) ( startPosition >>> log2OfSegmentSize ) ] , ( int ) ( startPosition & bitmask ) , ( int ) bytesToCopyFromSegment ) ; startPosition += bytesToCopyFromSegment ; remainingBytesInSegment = segmentSize - ( int ) ( startPosition & bitmask ) ; remainingBytesInCopy -= bytesToCopyFromSegment ; } }

Write a portion of this data to an OutputStream.

@param os the output stream to write to
@param startPosition the position to begin copying from this array
@param len the length of the data to copy
@throws IOException if the write to the output stream could not be performed

Write a portion of this data to an OutputStream .


private void ensureCapacity(int segmentIndex) {
        while(segmentIndex >= segments.length) {
            segments = Arrays.copyOf(segments, segments.length * 3 / 2);
        }

        if(segments[segmentIndex] == null) {
            segments[segmentIndex] = memoryRecycler.getByteArray();
        }
    }

private void ensureCapacity ( int segmentIndex ) { while ( segmentIndex >= segments . length ) { segments = Arrays . copyOf ( segments , segments . length * 3 / 2 ) ; } if ( segments [ segmentIndex ] == null ) { segments [ segmentIndex ] = memoryRecycler . getByteArray ( ) ; } }

Ensures that the segment at segmentIndex exists

@param segmentIndex the segment index


public int getPosition(String fieldName) {
        Integer index = nameFieldIndexLookup.get(fieldName);
        if (index == null) {
            return -1;
        }
        return index;
    }

public int getPosition ( String fieldName ) { Integer index = nameFieldIndexLookup . get ( fieldName ) ; if ( index == null ) { return - 1 ; } return index ; }

Returns the position of a field previously added to the map, or -1 if the field has not been added to the map.

The positions of the fields are hashed into the hashedPositionArray by the hashCode of the fieldName.

@param fieldName the field name
@return the position

Returns the position of a field previously added to the map or - 1 if the field has not been added to the map .


private long calculateDedupedSizesAndTotalNumberOfSelectBuckets(MultiLinkedElementArray elementArray, GrowingSegmentedLongArray matchIndexHashAndSizeArray) {
        long totalBuckets = 0;
        long maxSize = 0;
        int[] selectArray = new int[8];

        for(int i=0;i<elementArray.numLists();i++) {
            int listSize = elementArray.listSize(i);
            int setSize = 0;
            int predictedBuckets = HashCodes.hashTableSize(listSize);
            int hashMask = predictedBuckets - 1;
            if(predictedBuckets > selectArray.length)
                selectArray = new int[predictedBuckets];
            for(int j=0;j<predictedBuckets;j++)
                selectArray[j] = -1;

            HollowOrdinalIterator iter = elementArray.iterator(i);
            int selectOrdinal = iter.next();
            while(selectOrdinal != HollowOrdinalIterator.NO_MORE_ORDINALS) {
                int hash = HashCodes.hashInt(selectOrdinal);
                int bucket = hash & hashMask;

                while(true) {
                    if(selectArray[bucket] == selectOrdinal)
                        break;
                    if(selectArray[bucket] == -1) {
                        selectArray[bucket] = selectOrdinal;
                        setSize++;
                        break;
                    }

                    bucket = (bucket+1) & hashMask;
                }

                selectOrdinal = iter.next();
            }

            long matchIndexHashAndSize = matchIndexHashAndSizeArray.get(i);
            matchIndexHashAndSize |= (long)setSize << 32;
            matchIndexHashAndSizeArray.set(i, matchIndexHashAndSize);

            totalBuckets += HashCodes.hashTableSize(setSize);
            if(setSize > maxSize)
                maxSize = setSize;
        }

        return totalBuckets | (long)bitsRequiredToRepresentValue(maxSize) << 56;
    }

Called after initial pass.
Returns the sum total number of select buckets in the low 7 bytes, and the bits required for the max set size in the high 1 byte.

Called after initial pass . Returns the sum total number of select buckets in the low 7 bytes and the bits required for the max set size in the high 1 byte .


protected static boolean hasCollectionsInDataSet(HollowDataset dataset) {
        for(HollowSchema schema : dataset.getSchemas()) {
            if ((schema instanceof HollowListSchema) ||
                    (schema instanceof HollowSetSchema) ||
                    (schema instanceof HollowMapSchema)) {
                return true;
            }
        }
        return false;
    }

protected static boolean hasCollectionsInDataSet ( HollowDataset dataset ) { for ( HollowSchema schema : dataset . getSchemas ( ) ) { if ( ( schema instanceof HollowListSchema ) || ( schema instanceof HollowSetSchema ) || ( schema instanceof HollowMapSchema ) ) { return true ; } } return false ; }

Determines whether DataSet contains any collections schema
@param dataset the data set
@return {@code true} if the data set contains any collections schema


public void generateFiles(File directory) throws IOException {
        if (packageName != null && !packageName.trim().isEmpty()) {
            String packageDir = packageName.replace(".", File.separator);
            if (!directory.getAbsolutePath().endsWith(packageDir)) {
                directory = new File(directory, packageDir);
            }
        }
        directory.mkdirs();

        HollowAPIClassJavaGenerator apiClassGenerator = new HollowAPIClassJavaGenerator(packageName, apiClassname,
                dataset, parameterizeClassNames, config);
        HollowAPIFactoryJavaGenerator apiFactoryGenerator = new HollowAPIFactoryJavaGenerator(packageName,
                apiClassname, dataset, config);

        HollowHashIndexGenerator hashIndexGenerator = new HollowHashIndexGenerator(packageName, apiClassname, dataset, config);

        generateFile(directory, apiClassGenerator);
        generateFile(directory, apiFactoryGenerator);
        generateFile(directory, hashIndexGenerator);

        generateFilesForHollowSchemas(directory);
    }

public void generateFiles ( File directory ) throws IOException { if ( packageName != null && ! packageName . trim ( ) . isEmpty ( ) ) { String packageDir = packageName . replace ( "." , File . separator ) ; if ( ! directory . getAbsolutePath ( ) . endsWith ( packageDir ) ) { directory = new File ( directory , packageDir ) ; } } directory . mkdirs ( ) ; HollowAPIClassJavaGenerator apiClassGenerator = new HollowAPIClassJavaGenerator ( packageName , apiClassname , dataset , parameterizeClassNames , config ) ; HollowAPIFactoryJavaGenerator apiFactoryGenerator = new HollowAPIFactoryJavaGenerator ( packageName , apiClassname , dataset , config ) ; HollowHashIndexGenerator hashIndexGenerator = new HollowHashIndexGenerator ( packageName , apiClassname , dataset , config ) ; generateFile ( directory , apiClassGenerator ) ; generateFile ( directory , apiFactoryGenerator ) ; generateFile ( directory , hashIndexGenerator ) ; generateFilesForHollowSchemas ( directory ) ; }

Generate files under the specified directory

@param directory the directory under which to generate files
@throws IOException if the files cannot be generated
@deprecated construct {@code HollowAPIGenerator} with a {@code destinationPath} then call {@link #generateSourceFiles()}


protected void generateFilesForHollowSchemas(File directory) throws IOException {
        for(HollowSchema schema : dataset.getSchemas()) {
            String type = schema.getName();
            if (config.isUseHollowPrimitiveTypes() && HollowCodeGenerationUtils.isPrimitiveType(type)) continue; // skip if using hollow primitive type

            generateFile(directory, getStaticAPIGenerator(schema));
            generateFile(directory, getHollowObjectGenerator(schema));
            generateFile(directory, getHollowFactoryGenerator(schema));

            if(schema.getSchemaType() == SchemaType.OBJECT) {
                HollowObjectSchema objSchema = (HollowObjectSchema)schema;
                generateFile(directory, new HollowObjectDelegateInterfaceGenerator(packageName, objSchema,
                        ergonomicShortcuts, dataset, config));
                generateFile(directory, new HollowObjectDelegateCachedImplGenerator(packageName, objSchema,
                        ergonomicShortcuts, dataset, config));
                generateFile(directory, new HollowObjectDelegateLookupImplGenerator(packageName, objSchema,
                        ergonomicShortcuts, dataset, config));

                generateFile(directory, new HollowDataAccessorGenerator(packageName, apiClassname, objSchema,
                        dataset, config));
                if (!config.isReservePrimaryKeyIndexForTypeWithPrimaryKey()) {
                    generateFile(directory, new LegacyHollowPrimaryKeyIndexGenerator(packageName, apiClassname,
                            objSchema, dataset, config));
                } else if ((objSchema).getPrimaryKey() != null) {
                    generateFile(directory, new HollowPrimaryKeyIndexGenerator(dataset, packageName, apiClassname,
                            objSchema, config));
                    generateFile(directory, new HollowUniqueKeyIndexGenerator(packageName, apiClassname, objSchema,
                            dataset, config));
                }
            }
        }
    }

Generate files based on dataset schemas under the specified directory

@param directory the directory under which to generate files
@throws IOException if the files cannot be generated
@deprecated construct {@code HollowAPIGenerator} with a {@code destinationPath} then call {@link #generateSourceFilesForHollowSchemas()}


public boolean keyMatches(int ordinal, Object... keys) {
        if(keys.length != fieldPathIndexes.length)
            return false;

        for(int i=0;i<keys.length;i++) {
            if(!keyMatches(keys[i], ordinal, i))
                return false;
        }

        return true;
    }

public boolean keyMatches ( int ordinal , Object ... keys ) { if ( keys . length != fieldPathIndexes . length ) return false ; for ( int i = 0 ; i < keys . length ; i ++ ) { if ( ! keyMatches ( keys [ i ] , ordinal , i ) ) return false ; } return true ; }

Determine whether or not the specified ordinal contains the provided primary key value.

@param ordinal the oridinal
@param keys the primary keys
@return true if the ordinal contains the primary keys

Determine whether or not the specified ordinal contains the provided primary key value .


public Object[] getRecordKey(int ordinal) {
        Object[] results = new Object[fieldPathIndexes.length];

        for (int i = 0; i < fieldPathIndexes.length; i++) {
            results[i] = readValue(ordinal, i);
        }
        return results;
    }

public Object [ ] getRecordKey ( int ordinal ) { Object [ ] results = new Object [ fieldPathIndexes . length ] ; for ( int i = 0 ; i < fieldPathIndexes . length ; i ++ ) { results [ i ] = readValue ( ordinal , i ) ; } return results ; }

Retrieve the primary key value for the specified ordinal.

@param ordinal the oridinal
@return the primary keys

Retrieve the primary key value for the specified ordinal .


public static FieldPath<ObjectFieldSegment> createFieldPathForPrimaryKey(
            HollowDataset dataset, String type, String path) {
        boolean autoExpand = !path.endsWith("!");
        path = autoExpand ? path : path.substring(0, path.length() - 1);

        FieldPath<FieldSegment> fp = createFieldPath(dataset, type, path, autoExpand, false, false);

        // Erasure trick to avoid copying when it is known the list only contains
        // instances of ObjectFieldSegment
        assert fp.segments.stream().allMatch(o -> o instanceof ObjectFieldSegment);
        @SuppressWarnings( {"unchecked", "raw"})
        FieldPath<ObjectFieldSegment> result = (FieldPath<ObjectFieldSegment>) (FieldPath) fp;
        return result;
    }

Creates an object-based field path given a data set and the field path in symbolic form conforming to paths
associated with a primary key.

@param dataset the data set
@param type the type name from which to bind the field path
@param path the symbolic field path
@return the field path
@throws IllegalArgumentException if the symbolic field path is ill-formed and cannot be bound

Creates an object - based field path given a data set and the field path in symbolic form conforming to paths associated with a primary key .


public static FieldPath<FieldSegment> createFieldPathForHashIndex(HollowDataset dataset, String type, String path) {
        return createFieldPath(dataset, type, path, false, false, true);
    }

public static FieldPath < FieldSegment > createFieldPathForHashIndex ( HollowDataset dataset , String type , String path ) { return createFieldPath ( dataset , type , path , false , false , true ) ; }

Creates a field path given a data set and the field path in symbolic form conforming to paths
associated with a hash index.

@param dataset the data set
@param type the type name from which to bind the field path
@param path the symbolic field path
@return the field path
@throws IllegalArgumentException if the symbolic field path is ill-formed and cannot be bound

Creates a field path given a data set and the field path in symbolic form conforming to paths associated with a hash index .


public static FieldPath<FieldSegment> createFieldPathForPrefixIndex(
            HollowDataset dataset, String type, String path, boolean autoExpand) {
        // If autoExpand is false then requireFullPath must be true
        boolean requireFullPath = !autoExpand;
        return createFieldPath(dataset, type, path, autoExpand, requireFullPath, true);
    }

Creates a field path given a data set and the field path in symbolic form conforming to paths
associated with a prefix index.

@param dataset the data set
@param type the type name from which to bind the field path
@param path the symbolic field path
@param autoExpand {@code true} if the field path should be expanded (if needed) to a full path referencing
an object field whose type is a non-reference type, otherwise the field path is not expanded and must be
a full path
@return the field path
@throws IllegalArgumentException if the symbolic field path is ill-formed and cannot be bound

Creates a field path given a data set and the field path in symbolic form conforming to paths associated with a prefix index .


public void put(Object obj, int ordinal) {
        int hashCode = System.identityHashCode(obj);
        int segment = segment(hashCode);
        segments[segment].put(obj, hashCode, ordinal);
    }

public void put ( Object obj , int ordinal ) { int hashCode = System . identityHashCode ( obj ) ; int segment = segment ( hashCode ) ; segments [ segment ] . put ( obj , hashCode , ordinal ) ; }

Associating the obj with an ordinal

@param obj
@param ordinal


private void initialize() {

        String lastRefType = this.fieldPath.getLastRefTypeInPath();

        // get all cardinality to estimate size of array bits needed.
        totalWords = readStateEngine.getTypeState(lastRefType).getPopulatedOrdinals().cardinality();
        averageWordLen = 0;
        double avg = 0;
        HollowObjectTypeReadState objectTypeReadState = (HollowObjectTypeReadState) readStateEngine.getTypeState(lastRefType);
        BitSet keyBitSet = objectTypeReadState.getPopulatedOrdinals();
        int ordinal = keyBitSet.nextSetBit(0);
        while (ordinal != -1) {
            avg += ((double) objectTypeReadState.readString(ordinal, 0).length()) / ((double) objectTypeReadState.maxOrdinal());
            ordinal = keyBitSet.nextSetBit(ordinal + 1);
        }
        averageWordLen = (int) Math.ceil(avg);

        HollowObjectTypeReadState valueState = (HollowObjectTypeReadState) readStateEngine.getTypeDataAccess(type);
        maxOrdinalOfType = valueState.maxOrdinal();

        // initialize the prefix index.
        build();
    }

initialize field positions and field paths.

initialize field positions and field paths .


public boolean contains(String key) {
        if (key == null) throw new IllegalArgumentException("key cannot be null");
        TST current;
        boolean result;
        do {
            current = prefixIndexVolatile;
            result = current.contains(key);
        } while (current != this.prefixIndexVolatile);
        return result;
    }

public
boolean
contains
(
String
key
)
{
if
(
key
==
)
throw
new
IllegalArgumentException
(
"key cannot be null"
)
;
TST
current
;
boolean
result
;
do
{
current
=
prefixIndexVolatile
;
result
=
current
.
contains
(
key
)
;
}
while
(
current
!=
this
.
prefixIndexVolatile
)
;
return
result
;
}

Check if the given key exists in the index.

@param key the key
@return {@code true} if the key exists, otherwise {@code false}

Check if the given key exists in the index .


float getChangePercent(int latestCardinality, int previousCardinality) {
        int diff = Math.abs(latestCardinality - previousCardinality);
        return (100.0f * diff) / previousCardinality;
    }

float getChangePercent ( int latestCardinality , int previousCardinality ) { int diff = Math . abs ( latestCardinality - previousCardinality ) ; return ( 100.0f * diff ) / previousCardinality ; }


public void addField(String type, String objectField) {
        ObjectFilterConfig typeConfig = specifiedFieldConfigs.get(type);
        if(typeConfig == null) {
            typeConfig = new ObjectFilterConfig();
            specifiedFieldConfigs.put(type, typeConfig);
        }
        typeConfig.addField(objectField);
    }

public void addField ( String type , String objectField ) { ObjectFilterConfig typeConfig = specifiedFieldConfigs . get ( type ) ; if ( typeConfig == null ) { typeConfig = new ObjectFilterConfig ( ) ; specifiedFieldConfigs . put ( type , typeConfig ) ; } typeConfig . addField ( objectField ) ; }

Add an individual field from an OBJECT schema.  This field will be either
excluded or included, depending on whether this is an exclude or include filter, respectively.

@param type The OBJECT type from the data model
@param objectField The field in the specified type to either include or exclude.

Add an individual field from an OBJECT schema . This field will be either excluded or included depending on whether this is an exclude or include filter respectively .


public static List<HollowSchema> dependencyOrderedSchemaList(Collection<HollowSchema> schemas) {
        DependencyIndex idx = new DependencyIndex();
        Map<String, HollowSchema> schemaMap = new HashMap<String, HollowSchema>();
        for(HollowSchema schema : schemas) {
            schemaMap.put(schema.getName(), schema);
            idx.indexSchema(schema, schemas);
        }

        List<HollowSchema> orderedSchemas = new ArrayList<HollowSchema>();

        while(idx.hasMoreTypes())
            orderedSchemas.add(schemaMap.get(idx.getNextType()));

        return orderedSchemas;
    }

public static List < HollowSchema > dependencyOrderedSchemaList ( Collection < HollowSchema > schemas ) { DependencyIndex idx = new DependencyIndex ( ) ; Map < String , HollowSchema > schemaMap = new HashMap < String , HollowSchema > ( ) ; for ( HollowSchema schema : schemas ) { schemaMap . put ( schema . getName ( ) , schema ) ; idx . indexSchema ( schema , schemas ) ; } List < HollowSchema > orderedSchemas = new ArrayList < HollowSchema > ( ) ; while ( idx . hasMoreTypes ( ) ) orderedSchemas . add ( schemaMap . get ( idx . getNextType ( ) ) ) ; return orderedSchemas ; }

Dependency types come before dependent types

@param schemas the schema
@return the dependent schema


public void initWithNextMajorVersionDefaults_V3() {
        usePackageGrouping = true;
        useBooleanFieldErgonomics = true;
        reservePrimaryKeyIndexForTypeWithPrimaryKey = true;
        useHollowPrimitiveTypes = true;
        restrictApiToFieldType = true;
        useVerboseToString = true;
    }

Make it easier to automatically use defaults for next major version


public long get(long index) {
        int segmentIndex = (int)(index >> log2OfSegmentSize);

        if(segmentIndex >= segments.length || segments[segmentIndex] == null)
            return 0;

        int longInSegment = (int)(index & bitmask);
        return segments[segmentIndex][longInSegment];
    }

public long get ( long index ) { int segmentIndex = ( int ) ( index >> log2OfSegmentSize ) ; if ( segmentIndex >= segments . length || segments [ segmentIndex ] == null ) return 0 ; int longInSegment = ( int ) ( index & bitmask ) ; return segments [ segmentIndex ] [ longInSegment ] ; }

Get the value of the byte at the specified index.
@param index the index
@return the byte value

Get the value of the byte at the specified index .


public Map<String, BitSet> findMatchingRecords(String fieldName, String fieldValue) {
        Map<String, BitSet> matches = new HashMap<String, BitSet>();

        for(HollowTypeReadState typeState : readEngine.getTypeStates()) {
            augmentMatchingRecords(typeState, fieldName, fieldValue, matches);
        }

        return matches;
    }

public Map < String , BitSet > findMatchingRecords ( String fieldName , String fieldValue ) { Map < String , BitSet > matches = new HashMap < String , BitSet > ( ) ; for ( HollowTypeReadState typeState : readEngine . getTypeStates ( ) ) { augmentMatchingRecords ( typeState , fieldName , fieldValue , matches ) ; } return matches ; }

Match any records which include a field with the provided fieldName and value.

@param fieldName the field name
@param fieldValue the field value as a string that will be parsed as the type of the field to match.
@return the matching records

Match any records which include a field with the provided fieldName and value .


public Map<String, BitSet> findMatchingRecords(String typeName, String fieldName, String fieldValue) {
        Map<String, BitSet> matches = new HashMap<String, BitSet>();

        HollowTypeReadState typeState = readEngine.getTypeState(typeName);
        if(typeState != null)
            augmentMatchingRecords(typeState, fieldName, fieldValue, matches);

        return matches;
    }

public Map < String , BitSet > findMatchingRecords ( String typeName , String fieldName , String fieldValue ) { Map < String , BitSet > matches = new HashMap < String , BitSet > ( ) ; HollowTypeReadState typeState = readEngine . getTypeState ( typeName ) ; if ( typeState != null ) augmentMatchingRecords ( typeState , fieldName , fieldValue , matches ) ; return matches ; }

Match any records of the specified type, which have the specified field set to the specified value.

@param typeName the type name
@param fieldName the field name
@param fieldValue the field value as a string that will be parsed as the type of the field to match.
@return the matching records

Match any records of the specified type which have the specified field set to the specified value .