public boolean readNextProtoBytes(BytesWritable writable) throws IOException {
    byte[] blob = readNextProtoBytes();
    if (blob != null) {
      writable.set(blob, 0, blob.length);
      return true;
    }
    return false;
  }

public boolean readNextProtoBytes ( BytesWritable writable ) throws IOException { byte [ ] blob = readNextProtoBytes ( ) ; if ( blob != null ) { writable . set ( blob , 0 , blob . length ) ; return true ; } return false ; }

returns true if bytes for next object are written to writable, false
other wise.

returns true if bytes for next object are written to writable false other wise .


public static TaskAttemptContext newTaskAttemptContext(
                            Configuration conf, TaskAttemptID taskAttemptId) {
    return (TaskAttemptContext)
        newInstance(TASK_CONTEXT_CONSTRUCTOR, conf, taskAttemptId);
  }

public static TaskAttemptContext newTaskAttemptContext ( Configuration conf , TaskAttemptID taskAttemptId ) { return ( TaskAttemptContext ) newInstance ( TASK_CONTEXT_CONSTRUCTOR , conf , taskAttemptId ) ; }

Creates TaskAttempContext from a JobConf and jobId using the correct
constructor for based on Hadoop version.

Creates TaskAttempContext from a JobConf and jobId using the correct constructor for based on Hadoop version .


public static MapContext newMapContext(Configuration conf,
                                         TaskAttemptID taskAttemptID,
                                         RecordReader recordReader,
                                         RecordWriter recordWriter,
                                         OutputCommitter outputCommitter,
                                         StatusReporter statusReporter,
                                         InputSplit inputSplit) {
    return (MapContext) newInstance(MAP_CONTEXT_CONSTRUCTOR,
        conf, taskAttemptID, recordReader, recordWriter, outputCommitter,
        statusReporter, inputSplit);
  }

public static MapContext newMapContext ( Configuration conf , TaskAttemptID taskAttemptID , RecordReader recordReader , RecordWriter recordWriter , OutputCommitter outputCommitter , StatusReporter statusReporter , InputSplit inputSplit ) { return ( MapContext ) newInstance ( MAP_CONTEXT_CONSTRUCTOR , conf , taskAttemptID , recordReader , recordWriter , outputCommitter , statusReporter , inputSplit ) ; }

Instantiates MapContext under Hadoop 1 and MapContextImpl under Hadoop 2.

Instantiates MapContext under Hadoop 1 and MapContextImpl under Hadoop 2 .


public static <M extends TBase<?, ?>> ThriftWritable<M> newInstance(Class<M> tClass) {
    return new ThriftWritable<M>(new TypeRef<M>(tClass){});
  }

public static < M extends TBase < ? , ? > > ThriftWritable < M > newInstance ( Class < M > tClass ) { return new ThriftWritable < M > ( new TypeRef < M > ( tClass ) { } ) ; }

Returns a ThriftWritable for a given Thrift class.

Returns a ThriftWritable for a given Thrift class .


@SuppressWarnings("unchecked")
  public T newInstance()
      throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    if (constructor_ == null) {
      constructor_ = getRawClass().getConstructor();
    }

    return (T)constructor_.newInstance();
  }

@ SuppressWarnings ( "unchecked" ) public T newInstance ( ) throws NoSuchMethodException , IllegalAccessException , InvocationTargetException , InstantiationException { if ( constructor_ == null ) { constructor_ = getRawClass ( ) . getConstructor ( ) ; } return ( T ) constructor_ . newInstance ( ) ; }

Use the typeRef's parameter to create a new instance of the TypeRef's template parameter.
@return a new instance of type T
@throws NoSuchMethodException
@throws IllegalAccessException
@throws InvocationTargetException
@throws InstantiationException

Use the typeRef s parameter to create a new instance of the TypeRef s template parameter .


public T safeNewInstance() {
    try {
      return newInstance();
    } catch (NoSuchMethodException e) {
      throw new IllegalArgumentException(e);
    } catch (IllegalAccessException e) {
      throw new IllegalArgumentException(e);
    } catch (InvocationTargetException e) {
      throw new IllegalArgumentException(e);
    } catch (InstantiationException e) {
      throw new IllegalArgumentException(e);
    }
  }

public T safeNewInstance ( ) { try { return newInstance ( ) ; } catch ( NoSuchMethodException e ) { throw new IllegalArgumentException ( e ) ; } catch ( IllegalAccessException e ) { throw new IllegalArgumentException ( e ) ; } catch ( InvocationTargetException e ) { throw new IllegalArgumentException ( e ) ; } catch ( InstantiationException e ) { throw new IllegalArgumentException ( e ) ; } }

The cheap, ugly version of the above, for when you don't want to catch 900 exceptions at
the calling site.
@return a new instance of type T.

The cheap ugly version of the above for when you don t want to catch 900 exceptions at the calling site .


public Message.Builder getBuilder(Class<? extends TBase<?, ?>> thriftClass) {
    return messageBuilderMap.get(protoMessageType(thriftClass)).clone();
  }

public Message . Builder getBuilder ( Class < ? extends TBase < ? , ? > > thriftClass ) { return messageBuilderMap . get ( protoMessageType ( thriftClass ) ) . clone ( ) ; }

For the given thriftClass, return a Protobufs builder to build a similar protobuf class.
@param thriftClass The thrift class for which the builder is desired.
@return a protobuf message builder

For the given thriftClass return a Protobufs builder to build a similar protobuf class .


private Message.Builder mapEntryProtoBuilder(TStructDescriptor descriptor, Field field) {
    return messageBuilderMap.get(mapProtoMessageType(descriptor, field)).clone();
  }

private Message . Builder mapEntryProtoBuilder ( TStructDescriptor descriptor , Field field ) { return messageBuilderMap . get ( mapProtoMessageType ( descriptor , field ) ) . clone ( ) ; }

Return Protobufs builder for a Map field


private DescriptorProtos.DescriptorProto.Builder mapDescriptorProtoBuilder(
    Field field, String typeName) throws DescriptorValidationException {
    DescriptorProtos.DescriptorProto.Builder mapBuilder =
      DescriptorProtos.DescriptorProto.newBuilder().setName(typeName);

    Field keyField = field.getMapKeyField();
    Field valueField = field.getMapValueField();

    DescriptorProtos.FieldDescriptorProto.Builder keyBuilder = mapKeyProtoBuilder();
    DescriptorProtos.FieldDescriptorProto.Builder valueBuilder = mapValueProtoBuilder();

    setBuilderTypeFromField(keyField, keyBuilder);
    setBuilderTypeFromField(valueField, valueBuilder);

    mapBuilder.addField(keyBuilder.build());
    mapBuilder.addField(valueBuilder.build());

    return mapBuilder;
  }

private DescriptorProtos . DescriptorProto . Builder mapDescriptorProtoBuilder ( Field field , String typeName ) throws DescriptorValidationException { DescriptorProtos . DescriptorProto . Builder mapBuilder = DescriptorProtos . DescriptorProto . newBuilder ( ) . setName ( typeName ) ; Field keyField = field . getMapKeyField ( ) ; Field valueField = field . getMapValueField ( ) ; DescriptorProtos . FieldDescriptorProto . Builder keyBuilder = mapKeyProtoBuilder ( ) ; DescriptorProtos . FieldDescriptorProto . Builder valueBuilder = mapValueProtoBuilder ( ) ; setBuilderTypeFromField ( keyField , keyBuilder ) ; setBuilderTypeFromField ( valueField , valueBuilder ) ; mapBuilder . addField ( keyBuilder . build ( ) ) ; mapBuilder . addField ( valueBuilder . build ( ) ) ; return mapBuilder ; }

Generate a DescriptorProto.Builder for the Message type that will be used
to represent the entries of the input Map field.

@param field a Map Field (field.isMap() == true)
@param typeName name of new message type

Generate a DescriptorProto . Builder for the Message type that will be used to represent the entries of the input Map field .


private String resolveMessageTypeName(TStructDescriptor descriptor)
    throws DescriptorValidationException {
    String typeName = protoMessageType(descriptor.getThriftClass());

    // Anytime we have a new message typeName, we make sure that we have a builder for it.
    // If not, we create one.
    DescriptorProtos.DescriptorProto.Builder builder = descriptorBuilderMap.get(typeName);
    if (builder == null) {
      builder = DescriptorProtos.DescriptorProto.newBuilder();
      builder.setName(typeName);
      descriptorBuilderMap.put(typeName, builder);
      doSchemaMapping(builder, descriptor);
    }

    return typeName;
  }

For a TStructDescriptor, resolves the typeName and optionally converts and memoizes it's
schema.

For a TStructDescriptor resolves the typeName and optionally converts and memoizes it s schema .


@SuppressWarnings("unchecked")
  public Message convert(T thriftObj) {
    return doConvert((TBase<?, ?>)
                     Preconditions.checkNotNull(thriftObj, "Can not convert a null object"));
  }

@
SuppressWarnings
(
"unchecked"
)
public
Message
convert
(
T
thriftObj
)
{
return
doConvert
(
(
TBase
<
,
>
)
Preconditions
.
checkNotNull
(
thriftObj
,
"Can not convert a null object"
)
)
;
}

Convert a thrift object to a protobuf message.
@param thriftObj thrift object
@return protobuf protobuf message

Convert a thrift object to a protobuf message .


@SuppressWarnings("unchecked")
  public <F extends TFieldIdEnum> Message doConvert(TBase<?, F> thriftObj) {
    if (thriftObj == null) { return null; }

    Class<TBase<?, F>> clazz = (Class<TBase<?, F>>) thriftObj.getClass();
    checkState(clazz);

    Message.Builder builder = getBuilder(clazz);

    TStructDescriptor fieldDesc = TStructDescriptor.getInstance(clazz);
    int fieldId = 0;
    for (Field tField : fieldDesc.getFields()) {
      // don't want to carry over default values from unset fields
      if (!thriftObj.isSet((F) tField.getFieldIdEnum())
          || (!supportNestedObjects && hasNestedObject(tField))) {
        fieldId++;
        continue;
      }

      // recurse into the object if it's a struct, otherwise just add the field
      if (supportNestedObjects && tField.getType() == TType.STRUCT) {
        TBase<?, ?> fieldValue = (TBase<?, ?>) fieldDesc.getFieldValue(fieldId++, thriftObj);
        Message message = doConvert(fieldValue);
        if (message != null) {
          FieldDescriptor protoFieldDesc = builder.getDescriptorForType().findFieldByName(
              tField.getName());
          builder.setField(protoFieldDesc, message);
        }
      } else {
        fieldId = convertField(thriftObj, builder, fieldDesc, fieldId, tField);
      }
    }
    return builder.build();
  }

conver TBase object to Message object
@param thriftObj


private Message buildMapEntryMessage(Message.Builder mapBuilder, Field field,
                                       Object mapKey, Object mapValue) {
    FieldDescriptor keyFieldDescriptor =
      mapBuilder.getDescriptorForType().findFieldByName(MAP_KEY_FIELD_NAME);
    FieldDescriptor valueFieldDescriptor =
      mapBuilder.getDescriptorForType().findFieldByName(MAP_VALUE_FIELD_NAME);

    boolean isKeyStruct = field.getMapKeyField().isStruct();
    boolean isValueStruct = field.getMapValueField().isStruct();

    Object convertedKey;
    if (isKeyStruct) {
      convertedKey = doConvert((TBase<?, ?>) mapKey);
    } else {
      convertedKey = sanitizeRawValue(mapKey, field.getMapKeyField());
    }

    Object convertedValue;
    if (isValueStruct) {
      convertedValue = doConvert((TBase<?, ?>) mapValue);
    } else {
      convertedValue = sanitizeRawValue(mapValue, field.getMapValueField());
    }

    mapBuilder.setField(keyFieldDescriptor, convertedKey);
    mapBuilder.setField(valueFieldDescriptor, convertedValue);

    return mapBuilder.build();
  }

private Message buildMapEntryMessage ( Message . Builder mapBuilder , Field field , Object mapKey , Object mapValue ) { FieldDescriptor keyFieldDescriptor = mapBuilder . getDescriptorForType ( ) . findFieldByName ( MAP_KEY_FIELD_NAME ) ; FieldDescriptor valueFieldDescriptor = mapBuilder . getDescriptorForType ( ) . findFieldByName ( MAP_VALUE_FIELD_NAME ) ; boolean isKeyStruct = field . getMapKeyField ( ) . isStruct ( ) ; boolean isValueStruct = field . getMapValueField ( ) . isStruct ( ) ; Object convertedKey ; if ( isKeyStruct ) { convertedKey = doConvert ( ( TBase < ? , ? > ) mapKey ) ; } else { convertedKey = sanitizeRawValue ( mapKey , field . getMapKeyField ( ) ) ; } Object convertedValue ; if ( isValueStruct ) { convertedValue = doConvert ( ( TBase < ? , ? > ) mapValue ) ; } else { convertedValue = sanitizeRawValue ( mapValue , field . getMapValueField ( ) ) ; } mapBuilder . setField ( keyFieldDescriptor , convertedKey ) ; mapBuilder . setField ( valueFieldDescriptor , convertedValue ) ; return mapBuilder . build ( ) ; }

Builds a Message that contains the key value pair of a Map entry


private String mapProtoMessageType(TStructDescriptor descriptor, Field field) {
    return String.format("%s_%s", protoMessageType(descriptor.getThriftClass()), field.getName());
  }

private String mapProtoMessageType ( TStructDescriptor descriptor , Field field ) { return String . format ( "%s_%s" , protoMessageType ( descriptor . getThriftClass ( ) ) , field . getName ( ) ) ; }

name the proto message used for Map types after the thrift class name of the enclosing
struct and the field name


public static void walkPath(Path path,
                              FileSystem fs,
                              PathFilter filter,
                              PathVisitor visitor) throws IOException {

    FileStatus fileStatus = fs.getFileStatus(path);

    if (filter.accept(path)) {
      visitor.visit(fileStatus);
    }

    if (fileStatus.isDir()) {
      FileStatus[] children = fs.listStatus(path);
      for (FileStatus childStatus : children) {
        walkPath(childStatus.getPath(), fs, filter, visitor);
      }
    }
  }

public static void walkPath ( Path path , FileSystem fs , PathFilter filter , PathVisitor visitor ) throws IOException { FileStatus fileStatus = fs . getFileStatus ( path ) ; if ( filter . accept ( path ) ) { visitor . visit ( fileStatus ) ; } if ( fileStatus . isDir ( ) ) { FileStatus [ ] children = fs . listStatus ( path ) ; for ( FileStatus childStatus : children ) { walkPath ( childStatus . getPath ( ) , fs , filter , visitor ) ; } } }

Recursively walk a path applying visitor to each path accepted by
filter

@param path root path to begin walking, will be visited if
it passes the filter and directory flag
@param fs FileSystem for this path
@param filter filter to determine which paths to accept
@param visitor visitor to apply to each accepted path
@throws IOException


public static void collectPaths(Path path,
                                  FileSystem fs,
                                  PathFilter filter,
                                  final List<Path> accumulator) throws IOException {

    walkPath(path, fs, filter, new PathVisitor() {
      @Override
      public void visit(FileStatus fileStatus) {
        accumulator.add(fileStatus.getPath());
      }
    });
  }

public static void collectPaths ( Path path , FileSystem fs , PathFilter filter , final List < Path > accumulator ) throws IOException { walkPath ( path , fs , filter , new PathVisitor ( ) { @ Override public void visit ( FileStatus fileStatus ) { accumulator . add ( fileStatus . getPath ( ) ) ; } } ) ; }

Recursively walk a path, adding paths that are accepted by filter to accumulator

@param path root path to begin walking, will be added to accumulator
@param fs FileSystem for this path
@param filter filter to determine which paths to accept
@param accumulator all paths accepted will be added to accumulator
@throws IOException

Recursively walk a path adding paths that are accepted by filter to accumulator


public static long getDirectorySize(Path path, FileSystem fs, PathFilter filter)
      throws IOException {
    PathSizeVisitor visitor = new PathSizeVisitor();
    PathFilter composite = new PathFilters.CompositePathFilter(
      PathFilters.newExcludeDirectoriesFilter(fs.getConf()),
      filter);
    walkPath(path, fs, composite, visitor);
    return visitor.getSize();
  }

public static long getDirectorySize ( Path path , FileSystem fs , PathFilter filter ) throws IOException { PathSizeVisitor visitor = new PathSizeVisitor ( ) ; PathFilter composite = new PathFilters . CompositePathFilter ( PathFilters . newExcludeDirectoriesFilter ( fs . getConf ( ) ) , filter ) ; walkPath ( path , fs , composite , visitor ) ; return visitor . getSize ( ) ; }

Calculates the total size of all the contents of a directory that are accepted
by filter. All subdirectories will be searched recursively and paths in subdirectories
that are accepted by filter will also be counted.

Does not include the size of directories themselves
(which are 0 in HDFS but may not be 0 on local file systems)

To get the size of a directory without filtering, use
{@link #getDirectorySize(Path, FileSystem)} which is much more efficient.

@param path path to recursively walk
@param fs FileSystem for this path
@param filter path filter for which paths size's to include in the total
NOTE: you do *not* need to filter out directories, this will be done for you
@return size of the directory in bytes
@throws IOException

Calculates the total size of all the contents of a directory that are accepted by filter . All subdirectories will be searched recursively and paths in subdirectories that are accepted by filter will also be counted .


public static void setColumnNumber(Configuration conf, int columnNum) {
    assert columnNum > 0;
    conf.setInt(RCFile.COLUMN_NUMBER_CONF_STR, columnNum);
  }

public static void setColumnNumber ( Configuration conf , int columnNum ) { assert columnNum > 0 ; conf . setInt ( RCFile . COLUMN_NUMBER_CONF_STR , columnNum ) ; }

set number of columns into the given configuration.

@param conf
configuration instance which need to set the column number
@param columnNum
column number for RCFile's Writer

set number of columns into the given configuration .


private static void updateJobConfForLocalSettings(JobConf conf) {
    String localSetCompressionEnabled = conf.get(COMPRESS_ENABLE);
    if(localSetCompressionEnabled != null) {
      conf.set(MR_COMPRESS_ENABLE, localSetCompressionEnabled);
    }

    String localSetCompressionType = conf.get(COMPRESS_TYPE);
    if(localSetCompressionType != null) {
      conf.set(MR_COMPRESS_TYPE, localSetCompressionType);
    }

    String localSetCompressionCodec = conf.get(COMPRESS_CODEC);
    if(localSetCompressionCodec != null) {
      conf.set(MR_COMPRESS_CODEC, localSetCompressionCodec);
    }
  }

private static void updateJobConfForLocalSettings ( JobConf conf ) { String localSetCompressionEnabled = conf . get ( COMPRESS_ENABLE ) ; if ( localSetCompressionEnabled != null ) { conf . set ( MR_COMPRESS_ENABLE , localSetCompressionEnabled ) ; } String localSetCompressionType = conf . get ( COMPRESS_TYPE ) ; if ( localSetCompressionType != null ) { conf . set ( MR_COMPRESS_TYPE , localSetCompressionType ) ; } String localSetCompressionCodec = conf . get ( COMPRESS_CODEC ) ; if ( localSetCompressionCodec != null ) { conf . set ( MR_COMPRESS_CODEC , localSetCompressionCodec ) ; } }

We can allow overriding the compression settings for just this scheme here


public static Method parseMethodFor(Class<Message> klass) {
    try {
      return klass.getMethod("parseDelimitedFrom", new Class[] {InputStream.class });
    } catch (SecurityException e) {
      throw new RuntimeException(e);
    } catch (NoSuchMethodException e) {
      throw new RuntimeException(e);
    }
  }

public static Method parseMethodFor ( Class < Message > klass ) { try { return klass . getMethod ( "parseDelimitedFrom" , new Class [ ] { InputStream . class } ) ; } catch ( SecurityException e ) { throw new RuntimeException ( e ) ; } catch ( NoSuchMethodException e ) { throw new RuntimeException ( e ) ; } }

Parse the method for a message
@param klass the class containing the message
@return the parsed method


public static Message parseMessage(Method parseMethod, InputStream in) {
    try {
      return (Message) parseMethod.invoke(null, in);
    } catch (IllegalArgumentException e) {
      throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      throw new RuntimeException(e);
    }
  }

public static Message parseMessage ( Method parseMethod , InputStream in ) { try { return ( Message ) parseMethod . invoke ( null , in ) ; } catch ( IllegalArgumentException e ) { throw new RuntimeException ( e ) ; } catch ( IllegalAccessException e ) { throw new RuntimeException ( e ) ; } catch ( InvocationTargetException e ) { throw new RuntimeException ( e ) ; } }

Parse the message in a given InputStream using scpecified Method
@param parseMethod the method used for parsing
@param in the input stream
@return the parsed message


public static Message parseMessage(Class<Message> klass, InputStream in) {
    Method parseMethod = parseMethodFor(klass);
    return parseMessage(parseMethod, in);
  }

public static Message parseMessage ( Class < Message > klass , InputStream in ) { Method parseMethod = parseMethodFor ( klass ) ; return parseMessage ( parseMethod , in ) ; }

Parse the message in a given Message container
@param klass the class containing the message
@param in the input stream
@return the parsed Message


@Override
  @SuppressWarnings("unchecked")
  public void putNext(Tuple tuple) throws IOException {
    json.clear();
    if (tuple != null && tuple.size() >= 1) {
      Map<String, Object> map = (Map<String, Object>) tuple.get(0);
      if (keysToKeep_ == null) {
        json.putAll(map);
      } else {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
          if (keysToKeep_.contains(entry.getKey())) {
            json.put(entry.getKey(), entry.getValue());
          }
        }
      }
    }
    try {
      writer.write(null, new Text(json.toString()));
    } catch (InterruptedException e) {
      // Under what circumstances does this happen?
      throw new IOException(e);
    }
  }

The first element is expected to be a map, or null. Anything else causes an error.
@param tuple the tuple to write.

The first element is expected to be a map or null . Anything else causes an error .


public static <M extends Message>
  void setClassConf(Class<M> protoClass, Configuration jobConf) {
    Protobufs.setClassConf(jobConf,
                           LzoProtobufB64LineOutputFormat.class,
                           protoClass);
  }

public static < M extends Message > void setClassConf ( Class < M > protoClass , Configuration jobConf ) { Protobufs . setClassConf ( jobConf , LzoProtobufB64LineOutputFormat . class , protoClass ) ; }

Sets an internal configuration in jobConf so that remote Tasks
instantiate appropriate object for this generic class based on protoClass


private void setTypeRef(Configuration conf) {
    String className = conf.get(CLASS_CONF_KEY);

    if (className == null) {
      throw new RuntimeException(CLASS_CONF_KEY + " is not set");
    }

    Class<?> clazz = null;
    try {
      clazz = conf.getClassByName(className);
    } catch (ClassNotFoundException e) {
      throw new RuntimeException("failed to instantiate class '" + className + "'", e);
    }

    typeRef = new TypeRef<M>(clazz){};
  }

private
void
setTypeRef
(
Configuration
conf
)
{
String
className
=
conf
.
get
(
CLASS_CONF_KEY
)
;
if
(
className
==
)
{
throw
new
RuntimeException
(
CLASS_CONF_KEY
+
" is not set"
)
;
}
Class
<
>
clazz
=
;
try
{
clazz
=
conf
.
getClassByName
(
className
)
;
}
catch
(
ClassNotFoundException
e
)
{
throw
new
RuntimeException
(
"failed to instantiate class '"
+
className
+
"'"
,
e
)
;
}
typeRef
=
new
TypeRef
<
M
>
(
clazz
)
{
}
;
}


protected void checkContainerSize(int size) throws TProtocolException {
    if (size < 0) {
      throw new TProtocolException("Negative container size: " + size);
    }

    if (checkReadLength_ && (readLength_ - size) < 0) {
      throw new TProtocolException("Remaining message length is " + readLength_
              + " but container size in underlying TTransport is set to at least: " + size);
    }
  }

Check if the container size is valid.

NOTE: This assumes that the elements are one byte each. So this does not
catch all cases, but does increase the chances of handling malformed
lengths when the number of remaining bytes in the underlying Transport is
clearly less than the container size that the Transport provides.


public void setPattern(byte[] pattern) {
    pattern_ = Arrays.copyOf(pattern, pattern.length);
    borders_ = new int[pattern_.length + 1];
    preProcess();
  }

public void setPattern ( byte [ ] pattern ) { pattern_ = Arrays . copyOf ( pattern , pattern . length ) ; borders_ = new int [ pattern_ . length + 1 ] ; preProcess ( ) ; }

Sets a new pattern for this StreamSearcher to use.
@param pattern
the pattern the StreamSearcher will look for in future calls to search(...)

Sets a new pattern for this StreamSearcher to use .


public static String underscore(String word) {
    String firstPattern = "([A-Z]+)([A-Z][a-z])";
    String secondPattern = "([a-z\\d])([A-Z])";
    String replacementPattern = "$1_$2";
    // Replace package separator with slash.
    word = word.replaceAll("\\.", "/");
    // Replace $ with two underscores for inner classes.
    word = word.replaceAll("\\$", "__");
    // Replace capital letter with _ plus lowercase letter.
    word = word.replaceAll(firstPattern, replacementPattern);
    word = word.replaceAll(secondPattern, replacementPattern);
    word = word.replace('-', '_');
    word = word.toLowerCase();
    return word;
  }

Underscore the given word.
@param word The word
@return The underscored version of the word


public static String ordinalize(int n) {
    int mod100 = n % 100;
    if (mod100 == 11 || mod100 == 12 || mod100 == 13) {
      return String.valueOf(n) + "th";
    }
    switch (n % 10) {
      case 1:
        return String.valueOf(n) + "st";
      case 2:
        return String.valueOf(n) + "nd";
      case 3:
        return String.valueOf(n) + "rd";
      default:
        return String.valueOf(n) + "th";
    }
  }

public static String ordinalize ( int n ) { int mod100 = n % 100 ; if ( mod100 == 11 || mod100 == 12 || mod100 == 13 ) { return String . valueOf ( n ) + "th" ; } switch ( n % 10 ) { case 1 : return String . valueOf ( n ) + "st" ; case 2 : return String . valueOf ( n ) + "nd" ; case 3 : return String . valueOf ( n ) + "rd" ; default : return String . valueOf ( n ) + "th" ; } }

Return the ordinal for the given number.
@param n The number
@return The ordinal String

Return the ordinal for the given number .


public static <M extends Message> ProtobufWritable<M> newInstance(Class<M> tClass) {
    return new ProtobufWritable<M>(new TypeRef<M>(tClass){});
  }

public static < M extends Message > ProtobufWritable < M > newInstance ( Class < M > tClass ) { return new ProtobufWritable < M > ( new TypeRef < M > ( tClass ) { } ) ; }

Returns a ProtobufWritable for a given Protobuf class.

Returns a ProtobufWritable for a given Protobuf class .


public static LzoW3CLogInputFormat newInstance(final String fieldDefinitionFile) {
    return new LzoW3CLogInputFormat() {
      @Override
      public RecordReader<LongWritable, MapWritable> createRecordReader(InputSplit split,
          TaskAttemptContext context) throws IOException, InterruptedException {
        RecordReader<LongWritable, MapWritable> reader = new LzoW3CLogRecordReader() {
          @Override
          protected String getFieldDefinitionFile() {
            return fieldDefinitionFile;
          }
        };
        reader.initialize(split, context);
        return reader;
      }
    };
  }

public static LzoW3CLogInputFormat newInstance ( final String fieldDefinitionFile ) { return new LzoW3CLogInputFormat ( ) { @ Override public RecordReader < LongWritable , MapWritable > createRecordReader ( InputSplit split , TaskAttemptContext context ) throws IOException , InterruptedException { RecordReader < LongWritable , MapWritable > reader = new LzoW3CLogRecordReader ( ) { @ Override protected String getFieldDefinitionFile ( ) { return fieldDefinitionFile ; } } ; reader . initialize ( split , context ) ; return reader ; } } ; }

Use this method to create valid instances of LzoW3CLogInputFormat
@param fieldDefinitionFile path to file in HDFS that contains the CRC hash to column mappings.
@return


public static void setOutputFormat(Class<?> realOutputFormatClass, Configuration conf) {
    conf.setClass("mapred.output.format.class", DeprecatedOutputFormatWrapper.class, org.apache.hadoop.mapred.OutputFormat.class);
    HadoopUtils.setClassConf(conf, CLASS_CONF_KEY, realOutputFormatClass);
  }

public static void setOutputFormat ( Class < ? > realOutputFormatClass , Configuration conf ) { conf . setClass ( "mapred.output.format.class" , DeprecatedOutputFormatWrapper . class , org . apache . hadoop . mapred . OutputFormat . class ) ; HadoopUtils . setClassConf ( conf , CLASS_CONF_KEY , realOutputFormatClass ) ; }

For cases where we need to set hadoop1 output format in a hadoop2 Configuration object.

For cases where we need to set hadoop1 output format in a hadoop2 Configuration object .


public boolean match(String word) {
    int flags = ignoreCase_ ? Pattern.CASE_INSENSITIVE : 0;
    return Pattern.compile(pattern_, flags).matcher(word).find();
  }

public boolean match ( String word ) { int flags = ignoreCase_ ? Pattern . CASE_INSENSITIVE : 0 ; return Pattern . compile ( pattern_ , flags ) . matcher ( word ) . find ( ) ; }

Does the given word match?
@param word The word
@return True if it matches the inflection pattern


public String replace(String word) {
    int flags = ignoreCase_ ? Pattern.CASE_INSENSITIVE : 0;
    return Pattern.compile(pattern_, flags).matcher(word).replaceAll(replacement_);
  }

public String replace ( String word ) { int flags = ignoreCase_ ? Pattern . CASE_INSENSITIVE : 0 ; return Pattern . compile ( pattern_ , flags ) . matcher ( word ) . replaceAll ( replacement_ ) ; }

Replace the word with its pattern.
@param word The word
@return The result


public static String pluralize(String word) {
    if (isUncountable(word)) {
      return word;
    } else {
      for (Inflection inflection : plurals_) {
        if (inflection.match(word)) {
          return inflection.replace(word);
        }
      }
      return word;
    }
  }

public static String pluralize ( String word ) { if ( isUncountable ( word ) ) { return word ; } else { for ( Inflection inflection : plurals_ ) { if ( inflection . match ( word ) ) { return inflection . replace ( word ) ; } } return word ; } }

Return the pluralized version of a word.
@param word The word
@return The pluralized word

Return the pluralized version of a word .


public static boolean isUncountable(String word) {
    for (String w : uncountables_) {
      if (w.equalsIgnoreCase(word)) {
        return true;
      }
    }
    return false;
  }

public static boolean isUncountable ( String word ) { for ( String w : uncountables_ ) { if ( w . equalsIgnoreCase ( word ) ) { return true ; } } return false ; }

Return true if the word is uncountable.
@param word The word
@return True if it is uncountable

Return true if the word is uncountable .


protected DataOutputStream getOutputStream(TaskAttemptContext job)
                  throws IOException, InterruptedException {

    return LzoUtils.getIndexedLzoOutputStream(
                      HadoopCompat.getConfiguration(job),
                      getDefaultWorkFile(job, LzopCodec.DEFAULT_LZO_EXTENSION));
  }

protected DataOutputStream getOutputStream ( TaskAttemptContext job ) throws IOException , InterruptedException { return LzoUtils . getIndexedLzoOutputStream ( HadoopCompat . getConfiguration ( job ) , getDefaultWorkFile ( job , LzopCodec . DEFAULT_LZO_EXTENSION ) ) ; }

Helper method to create lzo output file needed to create RecordWriter


private static <W extends Writable> void verifyWritableClass(Class<W> writableClass,
      boolean isKeyClass, WritableConverter<W> writableConverter) {
    Preconditions.checkNotNull(writableClass, "%s Writable class is undefined;"
        + " WritableConverter of type '%s' does not define default Writable type,"
        + " and no type was specified by user", isKeyClass ? "Key" : "Value", writableConverter
        .getClass().getName());
  }

Tests validity of Writable class, ensures consistent error message for both key and value
tests.

@param writableClass class being tested.
@param isKeyClass {@code true} if testing keyClass, {@code false} otherwise.
@param writableConverter associated WritableConverter instance.

Tests validity of Writable class ensures consistent error message for both key and value tests .


public static <M extends TBase<?, ?>> ThriftConverter<M> newInstance(Class<M> tClass) {
    return new ThriftConverter<M>(new TypeRef<M>(tClass){});
  }

public static < M extends TBase < ? , ? > > ThriftConverter < M > newInstance ( Class < M > tClass ) { return new ThriftConverter < M > ( new TypeRef < M > ( tClass ) { } ) ; }

Returns a ThriftConverter for a given Thrift class.

Returns a ThriftConverter for a given Thrift class .


public static Class<?> getClass(String className) {
    try {
      return PigContext.resolveClassName(className);
    } catch (IOException e) {
      throw new RuntimeException("Could not instantiate " + className, e);
    }
  }

public
static
Class
<
>
getClass
(
String
className
)
{
try
{
return
PigContext
.
resolveClassName
(
className
)
;
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
"Could not instantiate "
+
className
,
e
)
;
}
}

Returns class using Pig s class loader .


public static<T extends TBase<?,?>> TypeRef<T> getThriftTypeRef(String thriftClassName) {
    return ThriftUtils.getTypeRef(getClass(thriftClassName));
  }

public static < T extends TBase < ? , ? > > TypeRef < T > getThriftTypeRef ( String thriftClassName ) { return ThriftUtils . getTypeRef ( getClass ( thriftClassName ) ) ; }

Returns TypeRef using Pig class loader .


public static ArrayList<Integer> findColumnsToRead(
                                         Configuration      conf,
                                         List<Integer>      currFieldIds,
                                         ColumnarMetadata   storedInfo)
                                         throws IOException {

    ArrayList<Integer> columnsToRead = Lists.newArrayList();

    // first find the required fields
    ArrayList<Integer> requiredFieldIds = Lists.newArrayList();
    String reqFieldStr = conf.get(RCFileUtil.REQUIRED_FIELD_INDICES_CONF, "");

    int numKnownFields = currFieldIds.size();

    if (reqFieldStr == null || reqFieldStr.equals("")) {
      for(int i=0; i<numKnownFields; i++) {
        requiredFieldIds.add(currFieldIds.get(i));
      }
    } else {
      for (String str : reqFieldStr.split(",")) {
        int idx = Integer.valueOf(str);
        if (idx < 0 || idx >= numKnownFields) {
          throw new IOException("idx " + idx + " is out of range for known fields");
        }
        requiredFieldIds.add(currFieldIds.get(idx));
      }
    }

    List<Integer> storedFieldIds = storedInfo.getFieldIdList();

    for(int i=0; i < storedFieldIds.size(); i++) {
      int sid = storedFieldIds.get(i);
      if (sid > 0 && requiredFieldIds.contains(sid)) {
        columnsToRead.add(i);
      }
    }

    // unknown fields : the required fields that are not listed in storedFieldIds
    String unknownFields = "";
    for(int rid : requiredFieldIds) {
      if (!storedFieldIds.contains(rid)) {
        unknownFields += " " + rid;
      }
    }

    if (unknownFields.length() > 0) {
      int last = storedFieldIds.size() - 1;
      LOG.info("unknown fields among required fileds :" + unknownFields);
      if (storedFieldIds.get(last) != -1) { // not expected
        throw new IOException("No unknowns column in in input");
      }
      columnsToRead.add(last);
    }

    LOG.info(String.format(
        "reading %d%s out of %d stored columns for %d required columns",
        columnsToRead.size(),
        (unknownFields.length() > 0 ? " (including unknowns column)" : ""),
        storedInfo.getFieldIdList().size(),
        requiredFieldIds.size()));

    return columnsToRead;
  }

Returns list of columns that need to be read from the RCFile.
These columns are the intersection of currently required columns and
columns stored in the file.
If any required column does not exist in the file, we need to read
the "unknown fields" column, which is usually the last last one.

Returns list of columns that need to be read from the RCFile . These columns are the intersection of currently required columns and columns stored in the file . If any required column does not exist in the file we need to read the unknown fields column which is usually the last last one .


public static <M extends TBase<?, ?>>
  void setClassConf(Class<M> thriftClass, Configuration jobConf) {
    ThriftUtils.setClassConf(jobConf,
                             LzoThriftB64LineOutputFormat.class,
                             thriftClass);
  }

public static < M extends TBase < ? , ? > > void setClassConf ( Class < M > thriftClass , Configuration jobConf ) { ThriftUtils . setClassConf ( jobConf , LzoThriftB64LineOutputFormat . class , thriftClass ) ; }

Sets an internal configuration in jobConf so that remote Tasks
instantiate appropriate object for this generic class based on thriftClass


private String executeHttpRequest(HttpUriRequest request) {
        try {

            // Attempt to do execute request
            HttpResponse response = httpClient.execute(request);

            // Return response if successful
            if (response != null) {
                return EntityUtils.toString(response.getEntity(), "UTF-8");
            }

        } catch (UnsupportedEncodingException uee) {
            LOGGER.warn("Unsupported Encoding Exception thrown in request", uee);
        } catch (ClientProtocolException cpe) {
            LOGGER.warn("Client Protocol Exception thrown in request", cpe);
        } catch (IOException ioe) {
            LOGGER.warn("I/O Exception thrown in request", ioe);
        }

        return null;

    }

Execute the given HTTP request.

@param request HTTP request

@return Result, <i>null</i> if failed


private void addAuthorization(HttpRequest request, RedditToken rToken) {
        request.addHeader("Authorization", rToken.getTokenType() + " " + rToken.getAccessToken());
    }

private
void
addAuthorization
(
HttpRequest
request
,
RedditToken
rToken
)
{
request
.
addHeader
(
"Authorization"
,
rToken
.
getTokenType
(
)
+
" "
+
rToken
.
getAccessToken
(
)
)
;
}

Add authorization to the HTTP request.

@param request HTTP request
@param rToken Reddit token (generally of the "bearer" type)


public void validate(Object response) throws RedditParseException {

        // Check for null
        if (response == null) {
            throw new RedditParseException();
        }

        // Check it is a JSON response
        if (!(response instanceof JSONObject)) {
            throw new RedditParseException("not a JSON response");
        }

        // Cast to JSON object
        JSONObject jsonResponse = ((JSONObject) response);

        // Check for error
        if (jsonResponse.get("error") != null) {
            throw new RedditParseException(JsonUtils.safeJsonToInteger(jsonResponse.get("error")));
        }

        // Check that data exists
        if (jsonResponse.get("data") == null && jsonResponse.get("json") == null) {
            throw new RedditParseException("data is missing from listing");
        }

    }

public
void
validate
(
Object
response
)
throws
RedditParseException
{
// Check for null
if
(
response
==
)
{
throw
new
RedditParseException
(
)
;
}
// Check it is a JSON response
if
(
!
(
response
instanceof
JSONObject
)
)
{
throw
new
RedditParseException
(
"not a JSON response"
)
;
}
// Cast to JSON object
JSONObject
jsonResponse
=
(
(
JSONObject
)
response
)
;
// Check for error
if
(
jsonResponse
.
get
(
"error"
)
!=
)
{
throw
new
RedditParseException
(
JsonUtils
.
safeJsonToInteger
(
jsonResponse
.
get
(
"error"
)
)
)
;
}
// Check that data exists
if
(
jsonResponse
.
get
(
"data"
)
==
&&
jsonResponse
.
get
(
"json"
)
==
)
{
throw
new
RedditParseException
(
"data is missing from listing"
)
;
}
}

Validate that it is indeed the starting of a listing of reddit things.

@param response Object returned by JSON parser

@throws RedditRequestException If the response is not valid listing of reddit things

Validate that it is indeed the starting of a listing of reddit things .


private Thing parseThing(Kind kind, JSONObject data) {

        // For a comment
        if (kind == Kind.COMMENT) {
            return new Comment(data);

        // For a submission
        } else if (kind == Kind.LINK) {
            return new Submission(data);

        // For a subreddit
        } else if (kind == Kind.SUBREDDIT) {
            return new Subreddit(data);

        // For a more
        } else if (kind == Kind.MORE) {
            return new More(data);

        // In all other cases (null, or of a different type)
        } else {
            return null;
        }

    }

Parse the data into a thing if possible.

@param kind Kind of data
@param data Data for the thing
@return The thing generated from the data, if failed <i>null</i>

Parse the data into a thing if possible .


public List<MixedListingElement> parse(String jsonText) throws RedditParseException {

        // Parse to a list of things
        List<Thing> things = this.parseGeneric(jsonText);

        // List of comment and submission mixed elements
        List<MixedListingElement> mixedElements = new LinkedList<MixedListingElement>();

        // Iterate over things
        for (Thing t : things) {

            if (t instanceof Comment) {
                mixedElements.add((Comment) t);
            } else if (t instanceof Submission) {
                mixedElements.add((Submission) t);
            } else {
                LOGGER.warn("Encountered an unexpected reddit thing (" + t.getKind().value() + "), skipping it.");
            }

        }

        // Return result
        return mixedElements;

    }

Parse JSON received from reddit into a list of submissions and comments.
This parser expects the JSON to be of a listing of submissions and comments.

@param jsonText JSON Text
@return Parsed list of submissions

@throws ParseException

Parse JSON received from reddit into a list of submissions and comments . This parser expects the JSON to be of a listing of submissions and comments .


public static String formatCommaSeparatedList(List<String> list) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            if (i != 0) {
                builder.append(",");
            }
            builder.append(list.get(i));
        }
        return builder.toString();
    }

public static String formatCommaSeparatedList ( List < String > list ) { StringBuilder builder = new StringBuilder ( ) ; for ( int i = 0 ; i < list . size ( ) ; i ++ ) { if ( i != 0 ) { builder . append ( "," ) ; } builder . append ( list . get ( i ) ) ; } return builder . toString ( ) ; }

Format a comma separated list of the given list.

@param list List of strings

@return Comma-separated list string (e.g. "a,b,c,d")

Format a comma separated list of the given list .


private void waitIfNeeded() {

        // Calculate elapsed milliseconds
        long elapsed = System.currentTimeMillis() - lastReqTime;

        // If enough time has elapsed, no need to wait
        if (elapsed >= interval) {
            return;
        }

        // If not enough time was elapsed, wait the remainder
        long toWait = interval - elapsed;
        try {
            Thread.sleep(toWait);
        } catch (InterruptedException ie) {
            LOGGER.warn("Interrupted Exception thrown while politely waiting for remainder of interval", ie);
        }

    }


private void addBasicAuthentication(OAuthClientRequest request, RedditApp app) {
        String authString = app.getClientID() + ":" + app.getClientSecret();
        String authStringEnc = DatatypeConverter.printBase64Binary(authString.getBytes());
        request.addHeader(HEADER_AUTHORIZATION, "Basic " + authStringEnc);
    }

private
void
addBasicAuthentication
(
OAuthClientRequest
request
,
RedditApp
app
)
{
String
authString
=
app
.
getClientID
(
)
+
":"
+
app
.
getClientSecret
(
)
;
String
authStringEnc
=
DatatypeConverter
.
printBase64Binary
(
authString
.
getBytes
(
)
)
;
request
.
addHeader
(
HEADER_AUTHORIZATION
,
"Basic "
+
authStringEnc
)
;
}

Add the basic authentication protocol to the OAuth request using
the credentials of the Reddit application provided.

@param request OAuth request
@param app Reddit application

Add the basic authentication protocol to the OAuth request using the credentials of the Reddit application provided .


public void refresh(OAuthJSONAccessTokenResponse token) {
        this.accessToken = token.getAccessToken();
        this.expiration = currentTimeSeconds() + token.getExpiresIn();
        this.expirationSpan = token.getExpiresIn();
        this.scopes = new RedditTokenCompleteScope(token.getScope());
        this.tokenType = token.getParam(PARAM_TOKEN_TYPE);
    }

public void refresh ( OAuthJSONAccessTokenResponse token ) { this . accessToken = token . getAccessToken ( ) ; this . expiration = currentTimeSeconds ( ) + token . getExpiresIn ( ) ; this . expirationSpan = token . getExpiresIn ( ) ; this . scopes = new RedditTokenCompleteScope ( token . getScope ( ) ) ; this . tokenType = token . getParam ( PARAM_TOKEN_TYPE ) ; }

Refresh this reddit token with data received from the new token.

@param token Token received from a refresh request to reddit

Refresh this reddit token with data received from the new token .


public static String printCommentTree(List<CommentTreeElement> cs) {
        StringBuilder builder = new StringBuilder();
        for (CommentTreeElement c : cs) {
            builder.append(printCommentTree(c, 0));
        }
        return builder.toString();
    }

public static String printCommentTree ( List < CommentTreeElement > cs ) { StringBuilder builder = new StringBuilder ( ) ; for ( CommentTreeElement c : cs ) { builder . append ( printCommentTree ( c , 0 ) ) ; } return builder . toString ( ) ; }

Get printable version of the given comment tree.

@param cs     List of comment tree elements

@return Printable comment tree

Get printable version of the given comment tree .


public static Integer safeJsonToInteger(Object obj) {
        Integer intValue = null;

        try {
            String str = safeJsonToString(obj);
            intValue = str != null ? Integer.parseInt(str) : null;
        } catch (NumberFormatException e) {
            LOGGER.warn("Safe JSON conversion to Integer failed", e);
        }

        return intValue;
    }

Safely converts an object into an integer

@param obj The object to convert.
@return an Integer representing the integer value of the Object (null if the object cannot be converted to an Integer)


public static Double safeJsonToDouble(Object obj) {
        Double doubleValue = null;

        try {
            String str = safeJsonToString(obj);
            doubleValue = str != null ? Double.parseDouble(str) : null;
        } catch (NumberFormatException e) {
            LOGGER.warn("Safe JSON conversion to Double failed", e);
        }

        return doubleValue;
    }

public
static
Double
safeJsonToDouble
(
Object
obj
)
{
Double
doubleValue
=
;
try
{
String
str
=
safeJsonToString
(
obj
)
;
doubleValue
=
str
!=
Double
.
parseDouble
(
str
)
:
;
}
catch
(
NumberFormatException
e
)
{
LOGGER
.
warn
(
"Safe JSON conversion to Double failed"
,
e
)
;
}
return
doubleValue
;
}

Safely converts an object into an double

@param obj The object to convert.
@return a Double representing the double value of the Object (null if the object cannot be converted to Double)


public static Boolean safeJsonToBoolean(Object obj) {
        String str = safeJsonToString(obj);
        Boolean booleanValue = str != null ? Boolean.parseBoolean(str) : null;
        return booleanValue;
    }

public static Boolean safeJsonToBoolean ( Object obj ) { String str = safeJsonToString ( obj ) ; Boolean booleanValue = str != null ? Boolean . parseBoolean ( str ) : null ; return booleanValue ; }

Safely converts an object into an boolean

@param obj The object to convert.
@return a Boolean representing the boolean value of the Object (null only if the object was also null)


public static Long safeJsonToLong(Object obj) {
        Long longValue = null;

        try {
            String str = safeJsonToString(obj);
            longValue = str != null ? Long.parseLong(str) : null;
        } catch (NumberFormatException e) {
            LOGGER.warn("Safe JSON conversion to Long failed", e);
        }

        return longValue;
    }

public
static
Long
safeJsonToLong
(
Object
obj
)
{
Long
longValue
=
;
try
{
String
str
=
safeJsonToString
(
obj
)
;
longValue
=
str
!=
Long
.
parseLong
(
str
)
:
;
}
catch
(
NumberFormatException
e
)
{
LOGGER
.
warn
(
"Safe JSON conversion to Long failed"
,
e
)
;
}
return
longValue
;
}

Safely converts an object into an long

@param obj The object to convert.
@return a Long representing the long value of the Object (null if the object cannot be converted to Long)


protected List<CommentTreeElement> parseRecursive(JSONObject main) throws RedditParseException {

        List<CommentTreeElement> commentTree = new ArrayList<CommentTreeElement>();

        // Iterate over the comment tree results
        JSONArray array = (JSONArray) ((JSONObject) main.get("data")).get("children");
        for (Object element : array) {

            // Get the element
            JSONObject data = (JSONObject) element;

            // Make sure it is of the correct kind
            String kind = safeJsonToString(data.get("kind"));

            // If it is a comment
            if (kind != null && kind.equals(Kind.COMMENT.value())) {

                // Create comment
                Comment comment = new Comment( (JSONObject) data.get("data") );

                // Retrieve replies
                Object replies = ((JSONObject) data.get("data")).get("replies");

                // If it is an JSON object
                if (replies instanceof JSONObject) {
                    comment.setReplies(parseRecursive( (JSONObject) replies ));

                // If there are no replies, end with an empty one
                } else {
                    comment.setReplies(new ArrayList<CommentTreeElement>());
                }

                // Add comment to the tree
                commentTree.add(comment);
            }

            // If it is a more
            if (kind != null && kind.equals(Kind.MORE.value())) {

                // Add to comment tree
                commentTree.add(new More((JSONObject) data.get("data")));

            }

        }

        return commentTree;

    }

Parse a JSON object consisting of comments and add them
to the already existing list of comments. This does NOT create
a new comment list.

@param comments     List of comments
@param object    JSON Object

Parse a JSON object consisting of comments and add them to the already existing list of comments . This does NOT create a new comment list .


public List<Subreddit> parse(String jsonText) throws RedditParseException {

        // Parse to a list of things
        List<Thing> things = this.parseGeneric(jsonText);

        // List of comment and submission mixed elements
        List<Subreddit> subreddits = new LinkedList<Subreddit>();

        // Iterate over things
        for (Thing t : things) {

            if (t instanceof Subreddit) {
                subreddits.add((Subreddit) t);
            } else {
                LOGGER.warn("Encountered an unexpected reddit thing (" + t.getKind().value() + "), skipping it.");
            }

        }

        // Return resulting comments list
        return subreddits;

    }

Parse JSON received from reddit into a list of subreddits.
This parser expects the JSON to be of a listing of subreddits.

@param jsonText JSON Text
@return Parsed list of subreddits

@throws ParseException

Parse JSON received from reddit into a list of subreddits . This parser expects the JSON to be of a listing of subreddits .


public static String signature(String endpoint, Map<String, String> params, String clientSecret) throws InstagramException {
        SecretKeySpec keySpec = new SecretKeySpec(clientSecret.getBytes(UTF_8), HMAC_SHA256);

        // ensure we iterate through the keys in sorted order
        List<String> values = new ArrayList<String>(params.size());
        for (String key : MapUtils.getSortedKeys(params)) {
            values.add(String.format("%s=%s", key, params.get(key)));
        }

        // the sig string to sign in the form "endpoint|key1=value1|key2=value2|...."
        String sig = String.format("%s|%s", endpoint, StringUtils.join(values, '|'));

        try {
            Mac mac = Mac.getInstance(HMAC_SHA256);
            mac.init(keySpec);
            byte[] result = mac.doFinal(sig.getBytes(UTF_8));
            return Hex.encodeHexString(result);
        } catch (NoSuchAlgorithmException e) {
            throw new InstagramException("Invalid algorithm name!", e);
        } catch (InvalidKeyException e) {
            throw new InstagramException("Invalid key: " + clientSecret, e);
        }
    }

signature returns the HmacSHA256 encoded signature used for signed Instagram requests
@param endpoint The endpoint
@param params   The query parameters
@param clientSecret The client application secret
@return encoded signature String
@throws InstagramException


public static Map<String, String> sort(Map<String, String> map) {
        Preconditions.checkNotNull(map, "Cannot sort a null object.");

        Map<String, String> sorted = new LinkedHashMap<String, String>();

        for (String key : getSortedKeys(map)) {
            sorted.put(key, map.get(key));
        }

        return sorted;
    }

public
static
Map
<
String
,
String
>
sort
(
Map
<
String
,
String
>
map
)
{
Preconditions
.
checkNotNull
(
map
,
"Cannot sort a null object."
)
;
Map
<
String
,
String
>
sorted
=
new
LinkedHashMap
<
String
,
String
>
(
)
;
for
(
String
key
:
getSortedKeys
(
map
)
)
{
sorted
.
put
(
key
,
map
.
get
(
key
)
)
;
}
return
sorted
;
}

Sorts a Map

@param map unsorted map
@return sorted map


public OembedInformation getOembedInformation(String url) throws InstagramException {
        String apiMethod = String.format(Methods.OEMBED_INFORMATION, url);
        return createInstagramObject(Verbs.GET, OembedInformation.class, apiMethod, null);
    }

public OembedInformation getOembedInformation ( String url ) throws InstagramException { String apiMethod = String . format ( Methods . OEMBED_INFORMATION , url ) ; return createInstagramObject ( Verbs . GET , OembedInformation . class , apiMethod , null ) ; }

Returns information about the media associated with that link.

@param url A short link, like http://instagr.am/p/BUG/.
@return OembedInformation object
@throws org.jinstagram.exceptions.InstagramException if any error occurs.

Returns information about the media associated with that link .


private static <T> T createInstagramObject(Verbs verbs, Class<T> clazz, String methodName, Map<String, String> params)
            throws InstagramException {
        Response response;
        try {
            response = getApiResponse(verbs, methodName, params);
        } catch (IOException e) {
            throw new InstagramException("IOException while retrieving data", e);
        }

        if (response.getCode() >= 200 && response.getCode() < 300) {
            return createObjectFromResponse(clazz, response.getBody());
        }

        throw handleInstagramError(response);
    }

private
static
<
T
>
T
createInstagramObject
(
Verbs
verbs
,
Class
<
T
>
clazz
,
String
methodName
,
Map
<
String
,
String
>
params
)
throws
InstagramException
{
Response
response
;
try
{
response
=
getApiResponse
(
verbs
,
methodName
,
params
)
;
}
catch
(
IOException
e
)
{
throw
new
InstagramException
(
"IOException while retrieving data"
,
e
)
;
}
if
(
response
.
getCode
(
)
>=
200
&&
response
.
getCode
(
)
<
300
)
{
return
createObjectFromResponse
(
clazz
,
response
.
getBody
(
)
)
;
}
throw
handleInstagramError
(
response
)
;
}

Create an Instagram object based on class-name and response.

@param verbs HTTP State
@param clazz
@param methodName
@param params
@return
@throws InstagramException

Create an Instagram object based on class - name and response .


private static <T> T createObjectFromResponse(Class<T> clazz, final String response) throws InstagramException {
        Gson gson = new Gson();
        T object;

        try {
            object = gson.fromJson(response, clazz);
        } catch (Exception e) {
            throw new InstagramException("Error parsing json to object type " + clazz.getName(), e);
        }

        return object;
    }

private
static
<
T
>
T
createObjectFromResponse
(
Class
<
T
>
clazz
,
final
String
response
)
throws
InstagramException
{
Gson
gson
=
new
Gson
(
)
;
T
object
;
try
{
object
=
gson
.
fromJson
(
response
,
clazz
)
;
}
catch
(
Exception
e
)
{
throw
new
InstagramException
(
"Error parsing json to object type "
+
clazz
.
getName
(
)
,
e
)
;
}
return
object
;
}

Creates an object from the JSON response and the class which the object would be mapped to.

@param clazz a class instance
@param response a JSON feed
@return a object of type <T>
@throws InstagramException if any error occurs.

Creates an object from the JSON response and the class which the object would be mapped to .


public static void checkBothNotNull(Object object1, Object object2, String errorMsg) {
		check(!(object1 == null && object2 == null), errorMsg);
	}

public static void checkBothNotNull ( Object object1 , Object object2 , String errorMsg ) { check ( ! ( object1 == null && object2 == null ) , errorMsg ) ; }

Checks that at least one of object1 or object2 is not null

@param object1 any object
@param object2 any object
@param errorMsg error message
@throws IllegalArgumentException if both object1 and object2 are null


public static void checkEmptyString(String string, String errorMsg) {
		check(StringUtils.isNotBlank(string), errorMsg);
	}

public static void checkEmptyString ( String string , String errorMsg ) { check ( StringUtils . isNotBlank ( string ) , errorMsg ) ; }

Checks that a string is not null or empty
@param string   any string
@param errorMsg error message
@throws IllegalArgumentException if the string is null or empty


public static void checkValidUrl(String url, String errorMsg) {
		checkEmptyString(url, errorMsg);
		check(isUrl(url), errorMsg);
	}

public static void checkValidUrl ( String url , String errorMsg ) { checkEmptyString ( url , errorMsg ) ; check ( isUrl ( url ) , errorMsg ) ; }

Checks that a URL is valid

@param url      any string
@param errorMsg error message


public static void checkValidOAuthCallback(String url, String errorMsg) {
		checkEmptyString(url, errorMsg);

		if (url.toLowerCase().compareToIgnoreCase(OAuthConstants.OUT_OF_BAND) != 0) {
			check(isUrl(url), errorMsg);
		}
	}

public static void checkValidOAuthCallback ( String url , String errorMsg ) { checkEmptyString ( url , errorMsg ) ; if ( url . toLowerCase ( ) . compareToIgnoreCase ( OAuthConstants . OUT_OF_BAND ) != 0 ) { check ( isUrl ( url ) , errorMsg ) ; } }

Checks that a URL is a valid OAuth callback

@param url      any string
@param errorMsg error message


@Deprecated
	public InstagramClient getSignedHeaderInstagram(Token accessToken, String ipAddress) {
		return new Instagram(accessToken.getToken(), config.getApiSecret(), ipAddress);
	}

@ Deprecated public InstagramClient getSignedHeaderInstagram ( Token accessToken , String ipAddress ) { return new Instagram ( accessToken . getToken ( ) , config . getApiSecret ( ) , ipAddress ) ; }

Return an Instagram object with enforced signed header


public static void configureConnectionSettings(final Request request, final InstagramConfig config) {
        request.setConnectTimeout(config.getConnectionTimeoutMills(), TimeUnit.MILLISECONDS);
        request.setReadTimeout(config.getReadTimeoutMills(), TimeUnit.MILLISECONDS);

        // #51 Connection Keep Alive
        request.setConnectionKeepAlive(config.isConnectionKeepAlive());
    }

public
static
void
configureConnectionSettings
(
final
Request
request
,
final
InstagramConfig
config
)
{
request
.
setConnectTimeout
(
config
.
getConnectionTimeoutMills
(
)
,
TimeUnit
.
MILLISECONDS
)
;
request
.
setReadTimeout
(
config
.
getReadTimeoutMills
(
)
,
TimeUnit
.
MILLISECONDS
)
;
// #51 Connection Keep Alive
request
.
setConnectionKeepAlive
(
config
.
isConnectionKeepAlive
(
)
)
;
}

Configure the request with the connection settings of config
@param request OAuthRequest object
@param config InstagramConfig object


public String getBodyContents() {
		try {
			return new String(getByteBodyContents(), getCharset());
		} catch (UnsupportedEncodingException uee) {
			throw new OAuthException("Unsupported Charset: " + charset, uee);
		}
	}

public
String
getBodyContents
(
)
{
try
{
return
new
String
(
getByteBodyContents
(
)
,
getCharset
(
)
)
;
}
catch
(
UnsupportedEncodingException
uee
)
{
throw
new
OAuthException
(
"Unsupported Charset: "
+
charset
,
uee
)
;
}
}

Returns the body of the request

@return form encoded string
@throws OAuthException if the charset chosen is not supported


public static void prettyPrintJSONResponse(Logger logger, String jsonString) {
        if(logger.isDebugEnabled()) {
            // it can fail...on 404 it usually not a json
            String s;
            try {
                final JsonElement element = new JsonParser().parse(jsonString);
                s = new GsonBuilder().setPrettyPrinting().create().toJson(element);
            } catch(Exception e) {
                s = jsonString;
            }

            logger.debug("Received JSON response from Instagram - " + s);
        }
    }

Pretty print the JSON response in the logs

@param logger     the logger instance
@param jsonString the json String which is to be pretty printed.


public InstagramSubscription callback(String callback) {
		Preconditions.checkValidUrl(callback, "Invalid Callback Url");

		this.params.put(Constants.CALLBACK_URL, callback);

		return this;
	}

public
InstagramSubscription
callback
(
String
callback
)
{
Preconditions
.
checkValidUrl
(
callback
,
"Invalid Callback Url"
)
;
this
.
params
.
put
(
Constants
.
CALLBACK_URL
,
callback
)
;
return
this
;
}

Configures the callback url

@param callback The callback for your application
@return the {@link InstagramSubscription} instance for method chaining


public InstagramSubscription clientId(String clientId) {
		Preconditions.checkEmptyString(clientId, "Invalid 'clientId' key");

		this.params.put(Constants.CLIENT_ID, clientId);

		return this;
	}

public
InstagramSubscription
clientId
(
String
clientId
)
{
Preconditions
.
checkEmptyString
(
clientId
,
"Invalid 'clientId' key"
)
;
this
.
params
.
put
(
Constants
.
CLIENT_ID
,
clientId
)
;
return
this
;
}

Configures the clientId

@param clientId The clientId for your application
@return the {@link InstagramSubscription} instance for method chaining


public InstagramSubscription clientSecret(String clientSecret) {
		Preconditions.checkEmptyString(clientSecret, "Invalid 'clientSecret' key");

		this.params.put(Constants.CLIENT_SECRET, clientSecret);

		return this;
	}

public
InstagramSubscription
clientSecret
(
String
clientSecret
)
{
Preconditions
.
checkEmptyString
(
clientSecret
,
"Invalid 'clientSecret' key"
)
;
this
.
params
.
put
(
Constants
.
CLIENT_SECRET
,
clientSecret
)
;
return
this
;
}

Configure the clientSecret
@param clientSecret The clientSecret for your application
@return the {@link InstagramSubscription} instance for method chaining


public InstagramSubscription object(SubscriptionType type) {

		this.params.put(Constants.SUBSCRIPTION_TYPE, type.toString());

		return this;
	}

public InstagramSubscription object ( SubscriptionType type ) { this . params . put ( Constants . SUBSCRIPTION_TYPE , type . toString ( ) ) ; return this ; }

Configure the subscription type
@param type The subscription type for your usage
@return the {@link InstagramSubscription} instance for method chaining


public InstagramSubscription verifyToken(String verifyToken) {
		Preconditions.checkEmptyString(verifyToken, "Invalid 'verifyToken' key");

		this.params.put(Constants.VERIFY_TOKEN, verifyToken);

		return this;
	}

public
InstagramSubscription
verifyToken
(
String
verifyToken
)
{
Preconditions
.
checkEmptyString
(
verifyToken
,
"Invalid 'verifyToken' key"
)
;
this
.
params
.
put
(
Constants
.
VERIFY_TOKEN
,
verifyToken
)
;
return
this
;
}

Configure the verifyToken for the subscription

@param verifyToken The token for the subscription
@return the {@link InstagramSubscription} instance for method chaining


public InstagramSubscription aspect(String aspect) {
		Preconditions.checkEmptyString(aspect, "Invalid 'aspect' key");

		this.params.put(Constants.ASPECT, aspect);

		return this;
	}

public
InstagramSubscription
aspect
(
String
aspect
)
{
Preconditions
.
checkEmptyString
(
aspect
,
"Invalid 'aspect' key"
)
;
this
.
params
.
put
(
Constants
.
ASPECT
,
aspect
)
;
return
this
;
}

Configure the aspect for the subscription

@param aspect The aspect of the subscription
@return the {@link InstagramSubscription} instance for method chaining


public InstagramSubscription latitute(String latitude){
		Preconditions.checkValidLatLong(latitude, "Invalid 'lat' key");

		this.params.put(Constants.LATITUDE, latitude);

		return this;
	}

public
InstagramSubscription
latitute
(
String
latitude
)
{
Preconditions
.
checkValidLatLong
(
latitude
,
"Invalid 'lat' key"
)
;
this
.
params
.
put
(
Constants
.
LATITUDE
,
latitude
)
;
return
this
;
}

Configure the latitude for geography subscription
@param latitude The latitude for geography subscription
@return the {@link InstagramSubscription} instance for method chaining


public InstagramSubscription longitude(String longitude){
		Preconditions.checkValidLatLong(longitude, "Invalid 'lng' key");

		this.params.put(Constants.LONGITUDE, longitude);

		return this;
	}

public
InstagramSubscription
longitude
(
String
longitude
)
{
Preconditions
.
checkValidLatLong
(
longitude
,
"Invalid 'lng' key"
)
;
this
.
params
.
put
(
Constants
.
LONGITUDE
,
longitude
)
;
return
this
;
}

Configure the longitude for geography subscription
@param longitude The longitude for geography subscription
@return the {@link InstagramSubscription} instance for method chaining


public InstagramSubscription radius(String radius){
		Preconditions.checkValidRadius(radius, "Invalid 'radius' key");

		this.params.put(Constants.RADIUS, radius);

		return this;
	}

public
InstagramSubscription
radius
(
String
radius
)
{
Preconditions
.
checkValidRadius
(
radius
,
"Invalid 'radius' key"
)
;
this
.
params
.
put
(
Constants
.
RADIUS
,
radius
)
;
return
this
;
}

Configure the radius for geography subscription
@param radius The radius for geography subscription in metre
@return the {@link InstagramSubscription} instance for method chaining


public SubscriptionResponse deleteSubscription(String id) throws InstagramException {
        final OAuthRequest request = prepareOAuthRequest(Verbs.DELETE);
        request.addQuerystringParameter("id", id);

        try {
            final Response response = request.send();
            return getSubscriptionResponse(response.getBody());
        } catch (IOException e) {
            throw new InstagramException("Failed to delete subscription with id ["+id+"]", e);
        }
    }

Deletes a subscription with the specified identifier.

@param id the id of the subscription to remove

Deletes a subscription with the specified identifier .


public SubscriptionResponse deleteAllSubscription() throws InstagramException {
        final OAuthRequest request = prepareOAuthRequest(Verbs.DELETE);
		request.addQuerystringParameter(Constants.SUBSCRIPTION_TYPE, "all");

        try {
            final Response response = request.send();
            return getSubscriptionResponse(response.getBody());
        } catch (IOException e) {
            throw new InstagramException("Failed to delete all subscriptions", e);
        }
	}

public
SubscriptionResponse
deleteAllSubscription
(
)
throws
InstagramException
{
final
OAuthRequest
request
=
prepareOAuthRequest
(
Verbs
.
DELETE
)
;
request
.
addQuerystringParameter
(
Constants
.
SUBSCRIPTION_TYPE
,
"all"
)
;
try
{
final
Response
response
=
request
.
send
(
)
;
return
getSubscriptionResponse
(
response
.
getBody
(
)
)
;
}
catch
(
IOException
e
)
{
throw
new
InstagramException
(
"Failed to delete all subscriptions"
,
e
)
;
}
}

Deletes all the known subscription.

@return the response of this request, holding mainly the code


public SubscriptionsListResponse getSubscriptionList() throws InstagramException {
		final OAuthRequest request = prepareOAuthRequest(Verbs.GET);

        try {
            final Response response = request.send();
            return getSubscriptionsListResponse(response.getBody());
        } catch (IOException e) {
            throw new InstagramException("Failed to get subscription list", e);
        }
	}

public
SubscriptionsListResponse
getSubscriptionList
(
)
throws
InstagramException
{
final
OAuthRequest
request
=
prepareOAuthRequest
(
Verbs
.
GET
)
;
try
{
final
Response
response
=
request
.
send
(
)
;
return
getSubscriptionsListResponse
(
response
.
getBody
(
)
)
;
}
catch
(
IOException
e
)
{
throw
new
InstagramException
(
"Failed to get subscription list"
,
e
)
;
}
}

Returns the currently active subscription.

@return the active subscription

Returns the currently active subscription .


public static String formURLEncodeMap(Map<String, String> map) {
        Preconditions.checkNotNull(map, "Cannot url-encode a null object");

        return (map.size() <= 0) ? EMPTY_STRING : doFormUrlEncode(map);
    }

public
static
String
formURLEncodeMap
(
Map
<
String
,
String
>
map
)
{
Preconditions
.
checkNotNull
(
map
,
"Cannot url-encode a null object"
)
;
return
(
map
.
size
(
)
<=
0
)
EMPTY_STRING
:
doFormUrlEncode
(
map
)
;
}

Turns a map into a form-urlencoded string

@param map any map
@return form-url-encoded string

Turns a map into a form - urlencoded string


public static String percentEncode(String string) {
        String encoded = formURLEncode(string);

        for (EncodingRule rule : ENCODING_RULES) {
            encoded = rule.apply(encoded);
        }

        return encoded;
    }

public static String percentEncode ( String string ) { String encoded = formURLEncode ( string ) ; for ( EncodingRule rule : ENCODING_RULES ) { encoded = rule . apply ( encoded ) ; } return encoded ; }

Percent encodes a string

@param string plain string
@return percent encoded string


public static String appendParametersToQueryString(String url, Map<String, String> params) {
        Preconditions.checkNotNull(url, "Cannot append to null URL");

        String queryString = URLUtils.formURLEncodeMap(params);

        if (queryString.equals(EMPTY_STRING)) {
            return url;
        } else {
            url += (url.indexOf(QUERY_STRING_SEPARATOR) != -1) ? PARAM_SEPARATOR : QUERY_STRING_SEPARATOR;
            url += queryString;

            return url;
        }
    }

public
static
String
appendParametersToQueryString
(
String
url
,
Map
<
String
,
String
>
params
)
{
Preconditions
.
checkNotNull
(
url
,
"Cannot append to null URL"
)
;
String
queryString
=
URLUtils
.
formURLEncodeMap
(
params
)
;
if
(
queryString
.
equals
(
EMPTY_STRING
)
)
{
return
url
;
}
else
{
url
+=
(
url
.
indexOf
(
QUERY_STRING_SEPARATOR
)
!=
1
)
PARAM_SEPARATOR
:
QUERY_STRING_SEPARATOR
;
url
+=
queryString
;
return
url
;
}
}

Append given parameters to the query string of the url

@param url the url to append parameters to
@param params any map
@return new url with parameters on query string


public static String concatSortedPercentEncodedParams(Map<String, String> params) {
        StringBuilder result = new StringBuilder();

        for (Map.Entry<String, String> entry : params.entrySet()) {
            result.append(entry.getKey()).append(PAIR_SEPARATOR);
            result.append(entry.getValue()).append(PARAM_SEPARATOR);
        }

        return result.toString().substring(0, result.length() - 1);
    }

public static String concatSortedPercentEncodedParams ( Map < String , String > params ) { StringBuilder result = new StringBuilder ( ) ; for ( Map . Entry < String , String > entry : params . entrySet ( ) ) { result . append ( entry . getKey ( ) ) . append ( PAIR_SEPARATOR ) ; result . append ( entry . getValue ( ) ) . append ( PARAM_SEPARATOR ) ; } return result . toString ( ) . substring ( 0 , result . length ( ) - 1 ) ; }

Concats a key-value map into a querystring-like String

@param params key-value map
@return querystring-like String

Concats a key - value map into a querystring - like String


public static Map<String, String> queryStringToMap(String queryString) {
        Map<String, String> result = new HashMap<String, String>();

        if ((queryString != null) && (queryString.length() > 0)) {
            for (String param : queryString.split(PARAM_SEPARATOR)) {
                String pair[] = param.split(PAIR_SEPARATOR);
                String key = formURLDecode(pair[0]);
                String value = (pair.length > 1) ? formURLDecode(pair[1]) : EMPTY_STRING;

                result.put(key, value);
            }
        }

        return result;
    }

public static Map < String , String > queryStringToMap ( String queryString ) { Map < String , String > result = new HashMap < String , String > ( ) ; if ( ( queryString != null ) && ( queryString . length ( ) > 0 ) ) { for ( String param : queryString . split ( PARAM_SEPARATOR ) ) { String pair [ ] = param . split ( PAIR_SEPARATOR ) ; String key = formURLDecode ( pair [ 0 ] ) ; String value = ( pair . length > 1 ) ? formURLDecode ( pair [ 1 ] ) : EMPTY_STRING ; result . put ( key , value ) ; } } return result ; }

Parses and form-urldecodes a querystring-like string into a map

@param queryString querystring-like String
@return a map with the form-urldecoded parameters

Parses and form - urldecodes a querystring - like string into a map


public void throwException() throws InstagramException {
        if (errorMeta != null) {
            String msg = errorMeta.getErrorType() + ": " + errorMeta.getErrorMessage();
            switch (errorMeta.getCode()) {
                case 400:
                    throw new InstagramBadRequestException(errorMeta.getErrorType(), msg, this.headers);
                case 429:
                    throw new InstagramRateLimitException(errorMeta.getErrorType(), msg, this.headers);
                default:
                    throw new InstagramException(errorMeta.getErrorType(), msg, this.headers);
            }
        } else {
            throw new InstagramException("No metadata found in response", this.headers);
        }
    }

public
void
throwException
(
)
throws
InstagramException
{
if
(
errorMeta
!=
)
{
String
msg
=
errorMeta
.
getErrorType
(
)
+
": "
+
errorMeta
.
getErrorMessage
(
)
;
switch
(
errorMeta
.
getCode
(
)
)
{
case
400
:
throw
new
InstagramBadRequestException
(
errorMeta
.
getErrorType
(
)
,
msg
,
this
.
headers
)
;
case
429
:
throw
new
InstagramRateLimitException
(
errorMeta
.
getErrorType
(
)
,
msg
,
this
.
headers
)
;
default
:
throw
new
InstagramException
(
errorMeta
.
getErrorType
(
)
,
msg
,
this
.
headers
)
;
}
}
else
{
throw
new
InstagramException
(
"No metadata found in response"
,
this
.
headers
)
;
}
}

Throw instagram exception to the client

@throws InstagramException


public void addTrade(Decimal tradeVolume, Decimal tradePrice) {
        if (openPrice == null) {
            openPrice = tradePrice;
        }
        closePrice = tradePrice;

        if (maxPrice == null) {
            maxPrice = tradePrice;
        } else {
            maxPrice = maxPrice.isLessThan(tradePrice) ? tradePrice : maxPrice;
        }
        if (minPrice == null) {
            minPrice = tradePrice;
        } else {
            minPrice = minPrice.isGreaterThan(tradePrice) ? tradePrice : minPrice;
        }
        volume = volume.plus(tradeVolume);
        amount = amount.plus(tradeVolume.multipliedBy(tradePrice));
        trades++;
    }

public void addTrade ( Decimal tradeVolume , Decimal tradePrice ) { if ( openPrice == null ) { openPrice = tradePrice ; } closePrice = tradePrice ; if ( maxPrice == null ) { maxPrice = tradePrice ; } else { maxPrice = maxPrice . isLessThan ( tradePrice ) ? tradePrice : maxPrice ; } if ( minPrice == null ) { minPrice = tradePrice ; } else { minPrice = minPrice . isGreaterThan ( tradePrice ) ? tradePrice : minPrice ; } volume = volume . plus ( tradeVolume ) ; amount = amount . plus ( tradeVolume . multipliedBy ( tradePrice ) ) ; trades ++ ; }

Adds a trade at the end of tick period.
@param tradeVolume the traded volume
@param tradePrice the price

Adds a trade at the end of tick period .


private void increaseLengthTo(int index, int maxLength) {
        if (highestResultIndex > -1) {
            int newResultsCount = Math.min(index-highestResultIndex, maxLength);
            if (newResultsCount == maxLength) {
                results.clear();
                results.addAll(Collections.<T> nCopies(maxLength, null));
            } else if (newResultsCount > 0) {
                results.addAll(Collections.<T> nCopies(newResultsCount, null));
                removeExceedingResults(maxLength);
            }
        } else {
            // First use of cache
            assert results.isEmpty() : "Cache results list should be empty";
            results.addAll(Collections.<T> nCopies(Math.min(index+1, maxLength), null));
        }
    }

private
void
increaseLengthTo
(
int
index
,
int
maxLength
)
{
if
(
highestResultIndex
>
1
)
{
int
newResultsCount
=
Math
.
min
(
index
highestResultIndex
,
maxLength
)
;
if
(
newResultsCount
==
maxLength
)
{
results
.
clear
(
)
;
results
.
addAll
(
Collections
.
<
T
>
nCopies
(
maxLength
,
)
)
;
}
else
if
(
newResultsCount
>
0
)
{
results
.
addAll
(
Collections
.
<
T
>
nCopies
(
newResultsCount
,
)
)
;
removeExceedingResults
(
maxLength
)
;
}
}
else
{
// First use of cache
assert
results
.
isEmpty
(
)
:
"Cache results list should be empty"
;
results
.
addAll
(
Collections
.
<
T
>
nCopies
(
Math
.
min
(
index
+
1
,
maxLength
)
,
)
)
;
}
}

Increases the size of cached results buffer.
@param index the index to increase length to
@param maxLength the maximum length of the results buffer

Increases the size of cached results buffer .


private Decimal calculateMaximumDrawdown(TimeSeries series, CashFlow cashFlow) {
        Decimal maximumDrawdown = Decimal.ZERO;
        Decimal maxPeak = Decimal.ZERO;
        if (!series.isEmpty()) {
        	// The series is not empty
	        for (int i = series.getBeginIndex(); i <= series.getEndIndex(); i++) {
	            Decimal value = cashFlow.getValue(i);
	            if (value.isGreaterThan(maxPeak)) {
	                maxPeak = value;
	            }

	            Decimal drawdown = maxPeak.minus(value).dividedBy(maxPeak);
	            if (drawdown.isGreaterThan(maximumDrawdown)) {
	                maximumDrawdown = drawdown;
	            }
	        }
        }
        return maximumDrawdown;
    }

private
Decimal
calculateMaximumDrawdown
(
TimeSeries
series
,
CashFlow
cashFlow
)
{
Decimal
maximumDrawdown
=
Decimal
.
ZERO
;
Decimal
maxPeak
=
Decimal
.
ZERO
;
if
(
!
series
.
isEmpty
(
)
)
{
// The series is not empty
for
(
int
i
=
series
.
getBeginIndex
(
)
;
i
<=
series
.
getEndIndex
(
)
;
i
++
)
{
Decimal
value
=
cashFlow
.
getValue
(
i
)
;
if
(
value
.
isGreaterThan
(
maxPeak
)
)
{
maxPeak
=
value
;
}
Decimal
drawdown
=
maxPeak
.
minus
(
value
)
.
dividedBy
(
maxPeak
)
;
if
(
drawdown
.
isGreaterThan
(
maximumDrawdown
)
)
{
maximumDrawdown
=
drawdown
;
}
}
}
return
maximumDrawdown
;
}

Calculates the maximum drawdown from a cash flow over a series.
@param series the time series
@param cashFlow the cash flow
@return the maximum drawdown from a cash flow over a series

Calculates the maximum drawdown from a cash flow over a series .


public static List<Integer> getSplitBeginIndexes(TimeSeries series, Duration splitDuration) {
        ArrayList<Integer> beginIndexes = new ArrayList<>();

        int beginIndex = series.getBeginIndex();
        int endIndex = series.getEndIndex();

        // Adding the first begin index
        beginIndexes.add(beginIndex);

        // Building the first interval before next split
        ZonedDateTime beginInterval = series.getFirstTick().getEndTime();
        ZonedDateTime endInterval = beginInterval.plus(splitDuration);

        for (int i = beginIndex; i <= endIndex; i++) {
            // For each tick...
            ZonedDateTime tickTime = series.getTick(i).getEndTime();
            if (tickTime.isBefore(beginInterval) || !tickTime.isBefore(endInterval)) {
                // Tick out of the interval
                if (!endInterval.isAfter(tickTime)) {
                    // Tick after the interval
                    // --> Adding a new begin index
                    beginIndexes.add(i);
                }

                // Building the new interval before next split
                beginInterval = endInterval.isBefore(tickTime) ? tickTime : endInterval;
                endInterval = beginInterval.plus(splitDuration);
            }
        }
        return beginIndexes;
    }

Builds a list of split indexes from splitDuration.
@param series the time series to get split begin indexes of
@param splitDuration the duration between 2 splits
@return a list of begin indexes after split

Builds a list of split indexes from splitDuration .


private void calculateRegressionLine(int startIndex, int endIndex) {
        // First pass: compute xBar and yBar
        Decimal sumX = Decimal.ZERO;
        Decimal sumY = Decimal.ZERO;
        for (int i = startIndex; i <= endIndex; i++) {
            sumX = sumX.plus(Decimal.valueOf(i));
            sumY = sumY.plus(indicator.getValue(i));
        }
        Decimal nbObservations = Decimal.valueOf(endIndex - startIndex + 1);
        Decimal xBar = sumX.dividedBy(nbObservations);
        Decimal yBar = sumY.dividedBy(nbObservations);

        // Second pass: compute slope and intercept
        Decimal xxBar = Decimal.ZERO;
        Decimal xyBar = Decimal.ZERO;
        for (int i = startIndex; i <= endIndex; i++) {
            Decimal dX = Decimal.valueOf(i).minus(xBar);
            Decimal dY = indicator.getValue(i).minus(yBar);
            xxBar = xxBar.plus(dX.multipliedBy(dX));
            xyBar = xyBar.plus(dX.multipliedBy(dY));
        }

        slope = xyBar.dividedBy(xxBar);
        intercept = yBar.minus(slope.multipliedBy(xBar));
    }

Calculates the regression line.
@param startIndex the start index (inclusive) in the time series
@param endIndex the end index (inclusive) in the time series


public Order operate(int index, Decimal price, Decimal amount) {
        Order order = null;
        if (isNew()) {
            order = new Order(index, startingType, price, amount);
            entry = order;
        } else if (isOpened()) {
            if (index < entry.getIndex()) {
                throw new IllegalStateException("The index i is less than the entryOrder index");
            }
            order = new Order(index, startingType.complementType(), price, amount);
            exit = order;
        }
        return order;
    }

Operates the trade at the index-th position
@param index the tick index
@param price the price
@param amount the amount
@return the order

Operates the trade at the index - th position


private static org.jfree.data.time.TimeSeries buildChartTimeSeries(TimeSeries tickSeries, Indicator<Decimal> indicator, String name) {
        org.jfree.data.time.TimeSeries chartTimeSeries = new org.jfree.data.time.TimeSeries(name);
        for (int i = 0; i < tickSeries.getTickCount(); i++) {
            Tick tick = tickSeries.getTick(i);
            chartTimeSeries.add(new Minute(Date.from(tick.getEndTime().toInstant())), indicator.getValue(i).toDouble());
        }
        return chartTimeSeries;
    }

private static org . jfree . data . time . TimeSeries buildChartTimeSeries ( TimeSeries tickSeries , Indicator < Decimal > indicator , String name ) { org . jfree . data . time . TimeSeries chartTimeSeries = new org . jfree . data . time . TimeSeries ( name ) ; for ( int i = 0 ; i < tickSeries . getTickCount ( ) ; i ++ ) { Tick tick = tickSeries . getTick ( i ) ; chartTimeSeries . add ( new Minute ( Date . from ( tick . getEndTime ( ) . toInstant ( ) ) ) , indicator . getValue ( i ) . toDouble ( ) ) ; } return chartTimeSeries ; }

Builds a JFreeChart time series from a Ta4j time series and an indicator.
@param tickSeries the ta4j time series
@param indicator the indicator
@param name the name of the chart time series
@return the JFreeChart time series

Builds a JFreeChart time series from a Ta4j time series and an indicator .


private static Decimal randDecimal(Decimal min, Decimal max) {
        Decimal randomDecimal = null;
        if (min != null && max != null && min.isLessThan(max)) {
            randomDecimal = max.minus(min).multipliedBy(Decimal.valueOf(Math.random())).plus(min);
        }
        return randomDecimal;
    }

private static Decimal randDecimal ( Decimal min , Decimal max ) { Decimal randomDecimal = null ; if ( min != null && max != null && min . isLessThan ( max ) ) { randomDecimal = max . minus ( min ) . multipliedBy ( Decimal . valueOf ( Math . random ( ) ) ) . plus ( min ) ; } return randomDecimal ; }

Generates a random decimal number between min and max.
@param min the minimum bound
@param max the maximum bound
@return a random decimal number between min and max

Generates a random decimal number between min and max .


private static Tick generateRandomTick() {
        final Decimal maxRange = Decimal.valueOf("0.03"); // 3.0%
        Decimal openPrice = LAST_TICK_CLOSE_PRICE;
        Decimal minPrice = openPrice.minus(openPrice.multipliedBy(maxRange.multipliedBy(Decimal.valueOf(Math.random()))));
        Decimal maxPrice = openPrice.plus(openPrice.multipliedBy(maxRange.multipliedBy(Decimal.valueOf(Math.random()))));
        Decimal closePrice = randDecimal(minPrice, maxPrice);
        LAST_TICK_CLOSE_PRICE = closePrice;
        return new BaseTick(ZonedDateTime.now(), openPrice, maxPrice, minPrice, closePrice, Decimal.ONE);
    }

private
static
Tick
generateRandomTick
(
)
{
final
Decimal
maxRange
=
Decimal
.
valueOf
(
"0.03"
)
;
// 3.0%
Decimal
openPrice
=
LAST_TICK_CLOSE_PRICE
;
Decimal
minPrice
=
openPrice
.
minus
(
openPrice
.
multipliedBy
(
maxRange
.
multipliedBy
(
Decimal
.
valueOf
(
Math
.
random
(
)
)
)
)
)
;
Decimal
maxPrice
=
openPrice
.
plus
(
openPrice
.
multipliedBy
(
maxRange
.
multipliedBy
(
Decimal
.
valueOf
(
Math
.
random
(
)
)
)
)
)
;
Decimal
closePrice
=
randDecimal
(
minPrice
,
maxPrice
)
;
LAST_TICK_CLOSE_PRICE
=
closePrice
;
return
new
BaseTick
(
ZonedDateTime
.
now
(
)
,
openPrice
,
maxPrice
,
minPrice
,
closePrice
,
Decimal
.
ONE
)
;
}

Generates a random tick.
@return a random tick


private void incrementAcceleration() {
        if (acceleration.isGreaterThanOrEqual(ACCELERATION_THRESHOLD)) {
            acceleration = MAX_ACCELERATION;
        } else {
            acceleration = acceleration.plus(ACCELERATION_INCREMENT);
        }
    }

private void incrementAcceleration ( ) { if ( acceleration . isGreaterThanOrEqual ( ACCELERATION_THRESHOLD ) ) { acceleration = MAX_ACCELERATION ; } else { acceleration = acceleration . plus ( ACCELERATION_INCREMENT ) ; } }


private Decimal calculateSar(int index) {
        Decimal previousSar = getValue(index - 1);
        return extremePoint.multipliedBy(acceleration)
                .plus(Decimal.ONE.minus(acceleration).multipliedBy(previousSar));
    }

private Decimal calculateSar ( int index ) { Decimal previousSar = getValue ( index - 1 ) ; return extremePoint . multipliedBy ( acceleration ) . plus ( Decimal . ONE . minus ( acceleration ) . multipliedBy ( previousSar ) ) ; }

Calculates the SAR.
@param index the tick index
@return the SAR


private void calculate(Trade trade) {
        final int entryIndex = trade.getEntry().getIndex();
        int begin = entryIndex + 1;
        if (begin > values.size()) {
            Decimal lastValue = values.get(values.size() - 1);
            values.addAll(Collections.nCopies(begin - values.size(), lastValue));
        }
        int end = trade.getExit().getIndex();
        for (int i = Math.max(begin, 1); i <= end; i++) {
            Decimal ratio;
            if (trade.getEntry().isBuy()) {
                ratio = timeSeries.getTick(i).getClosePrice().dividedBy(timeSeries.getTick(entryIndex).getClosePrice());
            } else {
                ratio = timeSeries.getTick(entryIndex).getClosePrice().dividedBy(timeSeries.getTick(i).getClosePrice());
            }
            values.add(values.get(entryIndex).multipliedBy(ratio));
        }
    }

private void calculate ( Trade trade ) { final int entryIndex = trade . getEntry ( ) . getIndex ( ) ; int begin = entryIndex + 1 ; if ( begin > values . size ( ) ) { Decimal lastValue = values . get ( values . size ( ) - 1 ) ; values . addAll ( Collections . nCopies ( begin - values . size ( ) , lastValue ) ) ; } int end = trade . getExit ( ) . getIndex ( ) ; for ( int i = Math . max ( begin , 1 ) ; i <= end ; i ++ ) { Decimal ratio ; if ( trade . getEntry ( ) . isBuy ( ) ) { ratio = timeSeries . getTick ( i ) . getClosePrice ( ) . dividedBy ( timeSeries . getTick ( entryIndex ) . getClosePrice ( ) ) ; } else { ratio = timeSeries . getTick ( entryIndex ) . getClosePrice ( ) . dividedBy ( timeSeries . getTick ( i ) . getClosePrice ( ) ) ; } values . add ( values . get ( entryIndex ) . multipliedBy ( ratio ) ) ; } }

Calculates the cash flow for a single trade.
@param trade a single trade

Calculates the cash flow for a single trade .


private void fillToTheEnd() {
        if (timeSeries.getEndIndex() >= values.size()) {
            Decimal lastValue = values.get(values.size() - 1);
            values.addAll(Collections.nCopies(timeSeries.getEndIndex() - values.size() + 1, lastValue));
        }
    }

private void fillToTheEnd ( ) { if ( timeSeries . getEndIndex ( ) >= values . size ( ) ) { Decimal lastValue = values . get ( values . size ( ) - 1 ) ; values . addAll ( Collections . nCopies ( timeSeries . getEndIndex ( ) - values . size ( ) + 1 , lastValue ) ) ; } }

Fills with last value till the end of the series.

Fills with last value till the end of the series .


private static void loadLoggerConfiguration() {
        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        context.reset();

        JoranConfigurator configurator = new JoranConfigurator();
        configurator.setContext(context);
        try {
            configurator.doConfigure(LOGBACK_CONF_FILE);
        } catch (JoranException je) {
            Logger.getLogger(StrategyExecutionLogging.class.getName()).log(Level.SEVERE, "Unable to load Logback configuration", je);
        }
    }

private
static
void
loadLoggerConfiguration
(
)
{
LoggerContext
context
=
(
LoggerContext
)
LoggerFactory
.
getILoggerFactory
(
)
;
context
.
reset
(
)
;
JoranConfigurator
configurator
=
new
JoranConfigurator
(
)
;
configurator
.
setContext
(
context
)
;
try
{
configurator
.
doConfigure
(
LOGBACK_CONF_FILE
)
;
}
catch
(
JoranException
je
)
{
Logger
.
getLogger
(
StrategyExecutionLogging
.
class
.
getName
(
)
)
.
log
(
Level
.
SEVERE
,
"Unable to load Logback configuration"
,
je
)
;
}
}

Loads the Logback configuration from a resource file.
Only here to avoid polluting other examples with logs. Could be replaced by a simple logback.xml file in the resource folder.

Loads the Logback configuration from a resource file . Only here to avoid polluting other examples with logs . Could be replaced by a simple logback . xml file in the resource folder .


private static OHLCDataset createOHLCDataset(TimeSeries series) {
        final int nbTicks = series.getTickCount();

        Date[] dates = new Date[nbTicks];
        double[] opens = new double[nbTicks];
        double[] highs = new double[nbTicks];
        double[] lows = new double[nbTicks];
        double[] closes = new double[nbTicks];
        double[] volumes = new double[nbTicks];

        for (int i = 0; i < nbTicks; i++) {
            Tick tick = series.getTick(i);
            dates[i] = new Date(tick.getEndTime().toEpochSecond() * 1000);
            opens[i] = tick.getOpenPrice().toDouble();
            highs[i] = tick.getMaxPrice().toDouble();
            lows[i] = tick.getMinPrice().toDouble();
            closes[i] = tick.getClosePrice().toDouble();
            volumes[i] = tick.getVolume().toDouble();
        }

        OHLCDataset dataset = new DefaultHighLowDataset("btc", dates, highs, lows, opens, closes, volumes);

        return dataset;
    }

private static OHLCDataset createOHLCDataset ( TimeSeries series ) { final int nbTicks = series . getTickCount ( ) ; Date [ ] dates = new Date [ nbTicks ] ; double [ ] opens = new double [ nbTicks ] ; double [ ] highs = new double [ nbTicks ] ; double [ ] lows = new double [ nbTicks ] ; double [ ] closes = new double [ nbTicks ] ; double [ ] volumes = new double [ nbTicks ] ; for ( int i = 0 ; i < nbTicks ; i ++ ) { Tick tick = series . getTick ( i ) ; dates [ i ] = new Date ( tick . getEndTime ( ) . toEpochSecond ( ) * 1000 ) ; opens [ i ] = tick . getOpenPrice ( ) . toDouble ( ) ; highs [ i ] = tick . getMaxPrice ( ) . toDouble ( ) ; lows [ i ] = tick . getMinPrice ( ) . toDouble ( ) ; closes [ i ] = tick . getClosePrice ( ) . toDouble ( ) ; volumes [ i ] = tick . getVolume ( ) . toDouble ( ) ; } OHLCDataset dataset = new DefaultHighLowDataset ( "btc" , dates , highs , lows , opens , closes , volumes ) ; return dataset ; }

Builds a JFreeChart OHLC dataset from a ta4j time series.
@param series a time series
@return an Open-High-Low-Close dataset

Builds a JFreeChart OHLC dataset from a ta4j time series .


private static TimeSeriesCollection createAdditionalDataset(TimeSeries series) {
        ClosePriceIndicator indicator = new ClosePriceIndicator(series);
        TimeSeriesCollection dataset = new TimeSeriesCollection();
        org.jfree.data.time.TimeSeries chartTimeSeries = new org.jfree.data.time.TimeSeries("Btc price");
        for (int i = 0; i < series.getTickCount(); i++) {
            Tick tick = series.getTick(i);
            chartTimeSeries.add(new Second(new Date(tick.getEndTime().toEpochSecond() * 1000)), indicator.getValue(i).toDouble());
        }
        dataset.addSeries(chartTimeSeries);
        return dataset;
    }

private
static
TimeSeriesCollection
createAdditionalDataset
(
TimeSeries
series
)
{
ClosePriceIndicator
indicator
=
new
ClosePriceIndicator
(
series
)
;
TimeSeriesCollection
dataset
=
new
TimeSeriesCollection
(
)
;
org
.
jfree
.
data
.
time
.
TimeSeries
chartTimeSeries
=
new
org
.
jfree
.
data
.
time
.
TimeSeries
(
"Btc price"
)
;
for
(
int
i
=
0
;
i
<
series
.
getTickCount
(
)
;
i
++
)
{
Tick
tick
=
series
.
getTick
(
i
)
;
chartTimeSeries
.
add
(
new
Second
(
new
Date
(
tick
.
getEndTime
(
)
.
toEpochSecond
(
)
*
1000
)
)
,
indicator
.
getValue
(
i
)
.
toDouble
(
)
)
;
}
dataset
.
addSeries
(
chartTimeSeries
)
;
return
dataset
;
}

Builds an additional JFreeChart dataset from a ta4j time series.
@param series a time series
@return an additional dataset

Builds an additional JFreeChart dataset from a ta4j time series .


private static void addCashFlowAxis(XYPlot plot, TimeSeriesCollection dataset) {
        final NumberAxis cashAxis = new NumberAxis("Cash Flow Ratio");
        cashAxis.setAutoRangeIncludesZero(false);
        plot.setRangeAxis(1, cashAxis);
        plot.setDataset(1, dataset);
        plot.mapDatasetToRangeAxis(1, 1);
        final StandardXYItemRenderer cashFlowRenderer = new StandardXYItemRenderer();
        cashFlowRenderer.setSeriesPaint(0, Color.blue);
        plot.setRenderer(1, cashFlowRenderer);
    }

private
static
void
addCashFlowAxis
(
XYPlot
plot
,
TimeSeriesCollection
dataset
)
{
final
NumberAxis
cashAxis
=
new
NumberAxis
(
"Cash Flow Ratio"
)
;
cashAxis
.
setAutoRangeIncludesZero
(
false
)
;
plot
.
setRangeAxis
(
1
,
cashAxis
)
;
plot
.
setDataset
(
1
,
dataset
)
;
plot
.
mapDatasetToRangeAxis
(
1
,
1
)
;
final
StandardXYItemRenderer
cashFlowRenderer
=
new
StandardXYItemRenderer
(
)
;
cashFlowRenderer
.
setSeriesPaint
(
0
,
Color
.
blue
)
;
plot
.
setRenderer
(
1
,
cashFlowRenderer
)
;
}

Adds the cash flow axis to the plot.
@param plot the plot
@param dataset the cash flow dataset


private static void displayChart(JFreeChart chart) {
        // Chart panel
        ChartPanel panel = new ChartPanel(chart);
        panel.setFillZoomRectangle(true);
        panel.setMouseWheelEnabled(true);
        panel.setPreferredSize(new Dimension(1024, 400));
        // Application frame
        ApplicationFrame frame = new ApplicationFrame("Ta4j example - Cash flow to chart");
        frame.setContentPane(panel);
        frame.pack();
        RefineryUtilities.centerFrameOnScreen(frame);
        frame.setVisible(true);
    }

private
static
void
displayChart
(
JFreeChart
chart
)
{
// Chart panel
ChartPanel
panel
=
new
ChartPanel
(
chart
)
;
panel
.
setFillZoomRectangle
(
true
)
;
panel
.
setMouseWheelEnabled
(
true
)
;
panel
.
setPreferredSize
(
new
Dimension
(
1024
,
400
)
)
;
// Application frame
ApplicationFrame
frame
=
new
ApplicationFrame
(
"Ta4j example - Cash flow to chart"
)
;
frame
.
setContentPane
(
panel
)
;
frame
.
pack
(
)
;
RefineryUtilities
.
centerFrameOnScreen
(
frame
)
;
frame
.
setVisible
(
true
)
;
}

Displays a chart in a frame.
@param chart the chart to be displayed


private void removeExceedingTicks() {
        int tickCount = ticks.size();
        if (tickCount > maximumTickCount) {
            // Removing old ticks
            int nbTicksToRemove = tickCount - maximumTickCount;
            for (int i = 0; i < nbTicksToRemove; i++) {
                ticks.remove(0);
            }
            // Updating removed ticks count
            removedTicksCount += nbTicksToRemove;
        }
    }

private
void
removeExceedingTicks
(
)
{
int
tickCount
=
ticks
.
size
(
)
;
if
(
tickCount
>
maximumTickCount
)
{
// Removing old ticks
int
nbTicksToRemove
=
tickCount
maximumTickCount
;
for
(
int
i
=
0
;
i
<
nbTicksToRemove
;
i
++
)
{
ticks
.
remove
(
0
)
;
}
// Updating removed ticks count
removedTicksCount
+=
nbTicksToRemove
;
}
}

Removes the N first ticks which exceed the maximum tick count.

Removes the N first ticks which exceed the maximum tick count .