<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>MtasDataCollector.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">MTAS</a> &gt; <a href="index.source.html" class="el_package">mtas.codec.util.collector</a> &gt; <span class="el_source">MtasDataCollector.java</span></div><h1>MtasDataCollector.java</h1><pre class="source lang-java linenums">package mtas.codec.util.collector;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.Map.Entry;

import mtas.codec.util.DataCollector;

/**
 * The Class MtasDataCollector.
 *
 * @param &lt;T1&gt; the generic type
 * @param &lt;T2&gt; the generic type
 */
public abstract class MtasDataCollector&lt;T1 extends Number &amp; Comparable&lt;T1&gt;, T2 extends Number &amp; Comparable&lt;T2&gt;&gt;
    implements Serializable {

  /** The Constant serialVersionUID. */
  private static final long serialVersionUID = 1L;

  /** The Constant SEGMENT_SORT_ASC. */
  public static final String SEGMENT_SORT_ASC = &quot;segment_asc&quot;;

  /** The Constant SEGMENT_SORT_DESC. */
  public static final String SEGMENT_SORT_DESC = &quot;segment_desc&quot;;

  /** The Constant SEGMENT_BOUNDARY_ASC. */
  public static final String SEGMENT_BOUNDARY_ASC = &quot;segment_boundary_asc&quot;;

  /** The Constant SEGMENT_BOUNDARY_DESC. */
  public static final String SEGMENT_BOUNDARY_DESC = &quot;segment_boundary_desc&quot;;

  /** The Constant SEGMENT_KEY. */
  public static final String SEGMENT_KEY = &quot;key&quot;;

  /** The Constant SEGMENT_NEW. */
  public static final String SEGMENT_NEW = &quot;new&quot;;

  /** The Constant SEGMENT_KEY_OR_NEW. */
  public static final String SEGMENT_KEY_OR_NEW = &quot;key_or_new&quot;;

  /** The Constant SEGMENT_POSSIBLE_KEY. */
  public static final String SEGMENT_POSSIBLE_KEY = &quot;possible_key&quot;;

  /** The size. */
  protected int size;

  /** The position. */
  protected int position;

  /** The collector type. */
  // properties collector
  protected String collectorType;

  /** The stats type. */
  protected String statsType;

  /** The data type. */
  protected String dataType;

  /** The stats items. */
  private SortedSet&lt;String&gt; statsItems;

  /** The sort type. */
  protected String sortType;

  /** The sort direction. */
  protected String sortDirection;

  /** The start. */
  protected Integer start;

  /** The number. */
  protected Integer number;

  /** The error number. */
  // error
  protected int[] errorNumber;

  /** The error list. */
  protected HashMap&lt;String, Integer&gt;[] errorList;

  /** The key list. */
  protected String[] keyList;

  /** The source number list. */
  protected int[] sourceNumberList;

  /** The with total. */
  private boolean withTotal;

  /** The segment registration. */
  public transient String segmentRegistration;

  /** The segment key value list. */
  protected transient LinkedHashMap&lt;String, Map&lt;String, T1&gt;&gt; segmentKeyValueList;

  /** The segment recompute key list. */
  public transient Map&lt;String, Set&lt;String&gt;&gt; segmentRecomputeKeyList;

  /** The segment keys. */
  public transient Set&lt;String&gt; segmentKeys;

  /** The segment values boundary. */
  protected transient Map&lt;String, T1&gt; segmentValuesBoundary;

  /** The segment value boundary. */
  protected transient T1 segmentValueBoundary;

  /** The segment value top list last. */
  protected transient Map&lt;String, T1&gt; segmentValueTopListLast;

  /** The segment value top list. */
  protected transient ArrayList&lt;T1&gt; segmentValueTopList;

  /** The segment name. */
  protected transient String segmentName;

  /** The segment number. */
  protected transient int segmentNumber;

  /** The has sub. */
  private boolean hasSub;

  /** The sub collector types. */
  private String[] subCollectorTypes;

  /** The sub data types. */
  private String[] subDataTypes;

  /** The sub stats types. */
  private String[] subStatsTypes;

  /** The sub stats items. */
  private SortedSet&lt;String&gt;[] subStatsItems;

  /** The sub sort types. */
  private String[] subSortTypes;

  /** The sub sort directions. */
  private String[] subSortDirections;

  /** The sub start. */
  private Integer[] subStart;

  /** The sub number. */
  private Integer[] subNumber;

  /** The sub collector list next level. */
<span class="fc" id="L161">  protected MtasDataCollector&lt;?, ?&gt;[] subCollectorListNextLevel = null;</span>

  /** The sub collector next level. */
<span class="fc" id="L164">  protected MtasDataCollector&lt;?, ?&gt; subCollectorNextLevel = null;</span>

  /** The new size. */
  protected transient int newSize;

  /** The new position. */
  protected transient int newPosition;

  /** The new current position. */
  protected transient int newCurrentPosition;

  /** The new current existing. */
  protected transient boolean newCurrentExisting;

  /** The new key list. */
<span class="fc" id="L179">  protected transient String[] newKeyList = null;</span>

  /** The new source number list. */
<span class="fc" id="L182">  protected transient int[] newSourceNumberList = null;</span>

  /** The new error number. */
  protected transient int[] newErrorNumber;

  /** The new error list. */
  protected transient HashMap&lt;String, Integer&gt;[] newErrorList;

  /** The new known key found in segment. */
  public transient Set&lt;String&gt; newKnownKeyFoundInSegment;

  /** The new sub collector types. */
  private transient String[] newSubCollectorTypes;

  /** The new sub data types. */
  private transient String[] newSubDataTypes;

  /** The new sub stats types. */
  private transient String[] newSubStatsTypes;

  /** The new sub stats items. */
  private transient SortedSet&lt;String&gt;[] newSubStatsItems;

  /** The new sub sort types. */
  private transient String[] newSubSortTypes;

  /** The new sub sort directions. */
  private transient String[] newSubSortDirections;

  /** The new sub start. */
  private transient Integer[] newSubStart;

  /** The new sub number. */
  private transient Integer[] newSubNumber;

  /** The new sub collector list next level. */
  // subcollectors next level for adding
<span class="fc" id="L219">  protected transient MtasDataCollector&lt;?, ?&gt;[] newSubCollectorListNextLevel = null;</span>

  /** The new sub collector next level. */
<span class="fc" id="L222">  protected transient MtasDataCollector&lt;?, ?&gt; newSubCollectorNextLevel = null;</span>

  /** The closed. */
<span class="fc" id="L225">  protected transient boolean closed = false;</span>

  /** The result. */
<span class="fc" id="L228">  private transient MtasDataCollectorResult&lt;T1, T2&gt; result = null;</span>

  /**
   * Instantiates a new mtas data collector.
   *
   * @param collectorType the collector type
   * @param dataType the data type
   * @param statsType the stats type
   * @param statsItems the stats items
   * @param sortType the sort type
   * @param sortDirection the sort direction
   * @param start the start
   * @param number the number
   * @param segmentRegistration the segment registration
   * @param boundary the boundary
   * @throws IOException Signals that an I/O exception has occurred.
   */
  @SuppressWarnings(&quot;unchecked&quot;)
  protected MtasDataCollector(String collectorType, String dataType,
      String statsType, SortedSet&lt;String&gt; statsItems, String sortType,
      String sortDirection, Integer start, Integer number,
<span class="fc" id="L249">      String segmentRegistration, String boundary) throws IOException {</span>
    // set properties
<span class="fc" id="L251">    this.closed = false;</span>
<span class="fc" id="L252">    this.collectorType = collectorType; // data or list</span>
<span class="fc" id="L253">    this.dataType = dataType; // long or double</span>
<span class="fc" id="L254">    this.statsType = statsType; // basic, advanced or full</span>
<span class="fc" id="L255">    this.statsItems = statsItems; // sum, n, all, ...</span>
<span class="fc" id="L256">    this.sortType = sortType;</span>
<span class="fc" id="L257">    this.sortDirection = sortDirection;</span>
<span class="fc" id="L258">    this.start = start;</span>
<span class="fc" id="L259">    this.number = number;</span>
<span class="fc" id="L260">    this.segmentRegistration = segmentRegistration;</span>
<span class="fc" id="L261">    this.withTotal = false;</span>
<span class="fc bfc" id="L262" title="All 2 branches covered.">    if (segmentRegistration != null) {</span>
<span class="fc" id="L263">      segmentKeys = new HashSet&lt;&gt;();</span>
<span class="fc" id="L264">      segmentKeyValueList = new LinkedHashMap&lt;&gt;();</span>
<span class="fc" id="L265">      segmentValuesBoundary = new LinkedHashMap&lt;&gt;();</span>
<span class="fc" id="L266">      segmentValueTopListLast = new LinkedHashMap&lt;&gt;();</span>
<span class="pc bpc" id="L267" title="1 of 2 branches missed.">      if (segmentRegistration.equals(SEGMENT_BOUNDARY_ASC)</span>
<span class="pc bpc" id="L268" title="1 of 2 branches missed.">          || segmentRegistration.equals(SEGMENT_BOUNDARY_DESC)) {</span>
<span class="nc bnc" id="L269" title="All 2 branches missed.">        if (boundary != null) {</span>
<span class="nc" id="L270">          segmentValueBoundary = stringToBoundary(boundary);</span>
        } else {
<span class="nc" id="L272">          throw new IOException(&quot;did expect boundary with segmentRegistration &quot;</span>
              + segmentRegistration);
        }
<span class="pc bpc" id="L275" title="1 of 2 branches missed.">      } else if (boundary != null) {</span>
<span class="nc" id="L276">        throw new IOException(&quot;didn't expect boundary with segmentRegistration &quot;</span>
            + segmentRegistration);
      }
    }
    // initialize administration
<span class="fc" id="L281">    keyList = new String[0];</span>
<span class="fc" id="L282">    sourceNumberList = new int[0];</span>
<span class="fc" id="L283">    errorNumber = new int[0];</span>
<span class="fc" id="L284">    errorList = (HashMap&lt;String, Integer&gt;[]) new HashMap&lt;?, ?&gt;[0];</span>
<span class="fc" id="L285">    size = 0;</span>
<span class="fc" id="L286">    position = 0;</span>
    // subCollectors properties
<span class="fc" id="L288">    hasSub = false;</span>
<span class="fc" id="L289">    subCollectorTypes = null;</span>
<span class="fc" id="L290">    subDataTypes = null;</span>
<span class="fc" id="L291">    subStatsTypes = null;</span>
<span class="fc" id="L292">    subStatsItems = null;</span>
<span class="fc" id="L293">    subSortTypes = null;</span>
<span class="fc" id="L294">    subSortDirections = null;</span>
<span class="fc" id="L295">    subStart = null;</span>
<span class="fc" id="L296">    subNumber = null;</span>
<span class="fc" id="L297">    subCollectorListNextLevel = null;</span>
<span class="fc" id="L298">    subCollectorNextLevel = null;</span>
<span class="fc" id="L299">  }</span>

  /**
   * Instantiates a new mtas data collector.
   *
   * @param collectorType the collector type
   * @param dataType the data type
   * @param statsType the stats type
   * @param statsItems the stats items
   * @param sortType the sort type
   * @param sortDirection the sort direction
   * @param start the start
   * @param number the number
   * @param subCollectorTypes the sub collector types
   * @param subDataTypes the sub data types
   * @param subStatsTypes the sub stats types
   * @param subStatsItems the sub stats items
   * @param subSortTypes the sub sort types
   * @param subSortDirections the sub sort directions
   * @param subStart the sub start
   * @param subNumber the sub number
   * @param segmentRegistration the segment registration
   * @param boundary the boundary
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected MtasDataCollector(String collectorType, String dataType,
      String statsType, SortedSet&lt;String&gt; statsItems, String sortType,
      String sortDirection, Integer start, Integer number,
      String[] subCollectorTypes, String[] subDataTypes, String[] subStatsTypes,
      SortedSet&lt;String&gt;[] subStatsItems, String[] subSortTypes,
      String[] subSortDirections, Integer[] subStart, Integer[] subNumber,
      String segmentRegistration, String boundary) throws IOException {
    // initialize
<span class="fc" id="L332">    this(collectorType, dataType, statsType, statsItems, sortType,</span>
        sortDirection, start, number, segmentRegistration, boundary);
    // initialize subCollectors
<span class="pc bpc" id="L335" title="1 of 2 branches missed.">    if (subCollectorTypes != null) {</span>
<span class="nc" id="L336">      hasSub = true;</span>
<span class="nc" id="L337">      this.subCollectorTypes = subCollectorTypes;</span>
<span class="nc" id="L338">      this.subDataTypes = subDataTypes;</span>
<span class="nc" id="L339">      this.subStatsTypes = subStatsTypes;</span>
<span class="nc" id="L340">      this.subStatsItems = subStatsItems;</span>
<span class="nc" id="L341">      this.subSortTypes = subSortTypes;</span>
<span class="nc" id="L342">      this.subSortDirections = subSortDirections;</span>
<span class="nc" id="L343">      this.subStart = subStart;</span>
<span class="nc" id="L344">      this.subNumber = subNumber;</span>
<span class="nc bnc" id="L345" title="All 2 branches missed.">      if (subCollectorTypes.length &gt; 1) {</span>
<span class="nc" id="L346">        newSubCollectorTypes = Arrays.copyOfRange(subCollectorTypes, 1,</span>
            subCollectorTypes.length);
<span class="nc" id="L348">        newSubDataTypes = Arrays.copyOfRange(subDataTypes, 1,</span>
            subStatsTypes.length);
<span class="nc" id="L350">        newSubStatsTypes = Arrays.copyOfRange(subStatsTypes, 1,</span>
            subStatsTypes.length);
<span class="nc" id="L352">        newSubStatsItems = Arrays.copyOfRange(subStatsItems, 1,</span>
            subStatsItems.length);
<span class="nc" id="L354">        newSubSortTypes = Arrays.copyOfRange(subSortTypes, 1,</span>
            subSortTypes.length);
<span class="nc" id="L356">        newSubSortDirections = Arrays.copyOfRange(subSortDirections, 1,</span>
            subSortDirections.length);
<span class="nc" id="L358">        newSubStart = Arrays.copyOfRange(subStart, 1, subStart.length);</span>
<span class="nc" id="L359">        newSubNumber = Arrays.copyOfRange(subNumber, 1, subNumber.length);</span>
      }
<span class="nc" id="L361">      newSubCollectorListNextLevel = new MtasDataCollector[0];</span>
    }
<span class="fc" id="L363">  }</span>

  /**
   * Merge.
   *
   * @param newDataCollector the new data collector
   * @param map the map
   * @param increaseSourceNumber the increase source number
   * @throws IOException Signals that an I/O exception has occurred.
   */
  abstract public void merge(MtasDataCollector&lt;?, ?&gt; newDataCollector,
      Map&lt;MtasDataCollector&lt;?, ?&gt;, MtasDataCollector&lt;?, ?&gt;&gt; map,
      boolean increaseSourceNumber) throws IOException;

  /**
   * Inits the new list.
   *
   * @param maxNumberOfTerms the max number of terms
   * @param segmentName the segment name
   * @param segmentNumber the segment number
   * @param boundary the boundary
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public void initNewList(int maxNumberOfTerms, String segmentName,
      int segmentNumber, String boundary) throws IOException {
<span class="pc bpc" id="L388" title="1 of 2 branches missed.">    if (closed) {</span>
<span class="nc" id="L389">      result = null;</span>
<span class="nc" id="L390">      closed = false;</span>
    }
<span class="fc" id="L392">    initNewListBasic(maxNumberOfTerms);</span>
<span class="fc bfc" id="L393" title="All 2 branches covered.">    if (segmentRegistration != null) {</span>
<span class="fc" id="L394">      this.segmentName = segmentName;</span>
<span class="fc" id="L395">      this.segmentNumber = segmentNumber;</span>
<span class="fc bfc" id="L396" title="All 2 branches covered.">      if (!segmentKeyValueList.containsKey(segmentName)) {</span>
<span class="fc" id="L397">        segmentKeyValueList.put(segmentName, new HashMap&lt;String, T1&gt;());</span>
<span class="pc bpc" id="L398" title="1 of 2 branches missed.">        if (segmentRegistration.equals(SEGMENT_BOUNDARY_ASC)</span>
<span class="pc bpc" id="L399" title="1 of 2 branches missed.">            || segmentRegistration.equals(SEGMENT_BOUNDARY_DESC)) {</span>
<span class="nc bnc" id="L400" title="All 2 branches missed.">          if (boundary != null) {</span>
<span class="nc" id="L401">            segmentValuesBoundary.put(segmentName,</span>
<span class="nc" id="L402">                stringToBoundary(boundary, segmentNumber));</span>
          } else {
<span class="nc" id="L404">            throw new IOException(&quot;expected boundary&quot;);</span>
          }
        } else {
<span class="fc" id="L407">          segmentValuesBoundary.put(segmentName, null);</span>
        }
<span class="fc" id="L409">        segmentValueTopListLast.put(segmentName, null);</span>
      }
<span class="fc" id="L411">      this.segmentValueTopList = new ArrayList&lt;&gt;();</span>
    }
<span class="fc" id="L413">  }</span>

  /**
   * Inits the new list.
   *
   * @param maxNumberOfTerms the max number of terms
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public void initNewList(int maxNumberOfTerms) throws IOException {
<span class="fc bfc" id="L422" title="All 2 branches covered.">    if (closed) {</span>
<span class="fc" id="L423">      result = null;</span>
<span class="fc" id="L424">      closed = false;</span>
    }
<span class="pc bpc" id="L426" title="1 of 2 branches missed.">    if (segmentRegistration != null) {</span>
<span class="nc" id="L427">      throw new IOException(&quot;missing segment name&quot;);</span>
    } else {
<span class="fc" id="L429">      initNewListBasic(maxNumberOfTerms);</span>
    }
<span class="fc" id="L431">  }</span>

  /**
   * Inits the new list basic.
   *
   * @param maxNumberOfTerms the max number of terms
   * @throws IOException Signals that an I/O exception has occurred.
   */
  @SuppressWarnings(&quot;unchecked&quot;)
  private void initNewListBasic(int maxNumberOfTerms) throws IOException {
<span class="pc bpc" id="L441" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="fc" id="L442">      position = 0;</span>
<span class="fc" id="L443">      newPosition = 0;</span>
<span class="fc" id="L444">      newCurrentPosition = 0;</span>
<span class="fc" id="L445">      newSize = maxNumberOfTerms + size;</span>
<span class="fc" id="L446">      newKeyList = new String[newSize];</span>
<span class="fc" id="L447">      newSourceNumberList = new int[newSize];</span>
<span class="fc" id="L448">      newErrorNumber = new int[newSize];</span>
<span class="fc" id="L449">      newErrorList = (HashMap&lt;String, Integer&gt;[]) new HashMap&lt;?, ?&gt;[newSize];</span>
<span class="fc" id="L450">      newKnownKeyFoundInSegment = new HashSet&lt;&gt;();</span>
<span class="pc bpc" id="L451" title="1 of 2 branches missed.">      if (hasSub) {</span>
<span class="nc" id="L452">        newSubCollectorListNextLevel = new MtasDataCollector[newSize];</span>
      }
    } else {
<span class="nc" id="L455">      throw new IOException(&quot;already closed&quot;);</span>
    }
<span class="fc" id="L457">  }</span>

  /**
   * Increase new list size.
   *
   * @throws IOException Signals that an I/O exception has occurred.
   */
  @SuppressWarnings(&quot;unchecked&quot;)
  protected void increaseNewListSize() throws IOException {
<span class="pc bpc" id="L466" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="fc" id="L467">      String[] tmpNewKeyList = newKeyList;</span>
<span class="fc" id="L468">      int[] tmpNewSourceNumberList = newSourceNumberList;</span>
<span class="fc" id="L469">      int[] tmpNewErrorNumber = newErrorNumber;</span>
<span class="fc" id="L470">      HashMap&lt;String, Integer&gt;[] tmpNewErrorList = newErrorList;</span>
<span class="fc" id="L471">      int tmpNewSize = newSize;</span>
<span class="fc" id="L472">      newSize = 2 * newSize;</span>
<span class="fc" id="L473">      newKeyList = new String[newSize];</span>
<span class="fc" id="L474">      newSourceNumberList = new int[newSize];</span>
<span class="fc" id="L475">      newErrorNumber = new int[newSize];</span>
<span class="fc" id="L476">      newErrorList = (HashMap&lt;String, Integer&gt;[]) new HashMap&lt;?, ?&gt;[newSize];</span>
<span class="fc" id="L477">      System.arraycopy(tmpNewKeyList, 0, newKeyList, 0, tmpNewSize);</span>
<span class="fc" id="L478">      System.arraycopy(tmpNewSourceNumberList, 0, newSourceNumberList, 0,</span>
          tmpNewSize);
<span class="fc" id="L480">      System.arraycopy(tmpNewErrorNumber, 0, newErrorNumber, 0, tmpNewSize);</span>
<span class="fc" id="L481">      System.arraycopy(tmpNewErrorList, 0, newErrorList, 0, tmpNewSize);</span>
<span class="pc bpc" id="L482" title="1 of 2 branches missed.">      if (hasSub) {</span>
<span class="nc" id="L483">        MtasDataCollector&lt;?, ?&gt;[] tmpNewSubCollectorListNextLevel = newSubCollectorListNextLevel;</span>
<span class="nc" id="L484">        newSubCollectorListNextLevel = new MtasDataCollector[newSize];</span>
<span class="nc" id="L485">        System.arraycopy(tmpNewSubCollectorListNextLevel, 0,</span>
            newSubCollectorListNextLevel, 0, tmpNewSize);
      }
<span class="fc" id="L488">    } else {</span>
<span class="nc" id="L489">      throw new IOException(&quot;already closed&quot;);</span>
    }
<span class="fc" id="L491">  }</span>

  /**
   * Adds the.
   *
   * @param increaseSourceNumber the increase source number
   * @return the mtas data collector
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected final MtasDataCollector add(boolean increaseSourceNumber)
      throws IOException {
<span class="pc bpc" id="L502" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="pc bpc" id="L503" title="1 of 2 branches missed.">      if (!collectorType.equals(DataCollector.COLLECTOR_TYPE_DATA)) {</span>
<span class="nc" id="L504">        throw new IOException(</span>
            &quot;collector should be &quot; + DataCollector.COLLECTOR_TYPE_DATA);
      } else {
<span class="pc bpc" id="L507" title="1 of 2 branches missed.">        if (newPosition &gt; 0) {</span>
<span class="nc" id="L508">          newCurrentExisting = true;</span>
<span class="fc bfc" id="L509" title="All 2 branches covered.">        } else if (position &lt; getSize()) {</span>
          // copy
<span class="fc" id="L511">          newKeyList[0] = keyList[0];</span>
<span class="fc" id="L512">          newSourceNumberList[0] = sourceNumberList[0];</span>
<span class="fc bfc" id="L513" title="All 2 branches covered.">          if (increaseSourceNumber) {</span>
<span class="fc" id="L514">            newSourceNumberList[0]++;</span>
          }
<span class="fc" id="L516">          newErrorNumber[0] = errorNumber[0];</span>
<span class="fc" id="L517">          newErrorList[0] = errorList[0];</span>
<span class="pc bpc" id="L518" title="1 of 2 branches missed.">          if (hasSub) {</span>
<span class="nc" id="L519">            newSubCollectorNextLevel = subCollectorNextLevel;</span>
          }
<span class="fc" id="L521">          copyToNew(0, 0);</span>
<span class="fc" id="L522">          newPosition = 1;</span>
<span class="fc" id="L523">          position = 1;</span>
<span class="fc" id="L524">          newCurrentExisting = true;</span>
        } else {
          // add key
<span class="fc" id="L527">          newKeyList[0] = DataCollector.COLLECTOR_TYPE_DATA;</span>
<span class="fc" id="L528">          newSourceNumberList[0] = 1;</span>
<span class="fc" id="L529">          newErrorNumber[0] = 0;</span>
<span class="fc" id="L530">          newErrorList[0] = new HashMap&lt;&gt;();</span>
<span class="fc" id="L531">          newPosition = 1;</span>
<span class="fc" id="L532">          newCurrentPosition = newPosition - 1;</span>
<span class="fc" id="L533">          newCurrentExisting = false;</span>
          // ready, only handle sub
<span class="pc bpc" id="L535" title="1 of 2 branches missed.">          if (hasSub) {</span>
<span class="nc" id="L536">            newSubCollectorNextLevel = DataCollector.getCollector(</span>
                subCollectorTypes[0], subDataTypes[0], subStatsTypes[0],
                subStatsItems[0], subSortTypes[0], subSortDirections[0],
                subStart[0], subNumber[0], newSubCollectorTypes,
                newSubDataTypes, newSubStatsTypes, newSubStatsItems,
                newSubSortTypes, newSubSortDirections, newSubStart,
                newSubNumber, segmentRegistration, null);
          } else {
<span class="fc" id="L544">            newSubCollectorNextLevel = null;</span>
          }
        }
<span class="fc" id="L547">        return newSubCollectorNextLevel;</span>
      }
    } else {
<span class="nc" id="L550">      throw new IOException(&quot;already closed&quot;);</span>
    }
  }

  /**
   * Adds the.
   *
   * @param key the key
   * @param increaseSourceNumber the increase source number
   * @return the mtas data collector
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected final MtasDataCollector add(String key,
      boolean increaseSourceNumber) throws IOException {
<span class="pc bpc" id="L564" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="pc bpc" id="L565" title="1 of 2 branches missed.">      if (collectorType.equals(DataCollector.COLLECTOR_TYPE_DATA)) {</span>
<span class="nc" id="L566">        throw new IOException(</span>
            &quot;collector should be &quot; + DataCollector.COLLECTOR_TYPE_LIST);
<span class="pc bpc" id="L568" title="1 of 2 branches missed.">      } else if (key == null) {</span>
<span class="nc" id="L569">        throw new IOException(&quot;key shouldn't be null&quot;);</span>
      } else {
        // check previous added
<span class="fc bfc" id="L572" title="All 2 branches covered.">        if ((newPosition &gt; 0)</span>
<span class="fc bfc" id="L573" title="All 2 branches covered.">            &amp;&amp; newKeyList[(newPosition - 1)].compareTo(key) &gt;= 0) {</span>
<span class="fc" id="L574">          int i = newPosition;</span>
          do {
<span class="fc" id="L576">            i--;</span>
<span class="fc bfc" id="L577" title="All 2 branches covered.">            if (newKeyList[i].equals(key)) {</span>
<span class="fc" id="L578">              newCurrentPosition = i;</span>
<span class="fc" id="L579">              newCurrentExisting = true;</span>
<span class="pc bpc" id="L580" title="1 of 2 branches missed.">              if (subDataTypes != null) {</span>
<span class="nc" id="L581">                return newSubCollectorListNextLevel[newCurrentPosition];</span>
              } else {
<span class="fc" id="L583">                return null;</span>
              }
            }
<span class="fc bfc" id="L586" title="All 4 branches covered.">          } while ((i &gt; 0) &amp;&amp; (newKeyList[i].compareTo(key) &gt; 0));</span>
        }
        // move position in old list
<span class="fc bfc" id="L589" title="All 2 branches covered.">        if (position &lt; getSize()) {</span>
          // just add smaller or equal items
<span class="fc bfc" id="L591" title="All 2 branches covered.">          while (keyList[position].compareTo(key) &lt;= 0) {</span>
<span class="fc bfc" id="L592" title="All 2 branches covered.">            if (newPosition == newSize) {</span>
<span class="fc" id="L593">              increaseNewListSize();</span>
            }
            // copy
<span class="fc" id="L596">            newKeyList[newPosition] = keyList[position];</span>
<span class="fc" id="L597">            newSourceNumberList[newPosition] = sourceNumberList[position];</span>
<span class="fc" id="L598">            newErrorNumber[newPosition] = errorNumber[position];</span>
<span class="fc" id="L599">            newErrorList[newPosition] = errorList[position];</span>
<span class="pc bpc" id="L600" title="1 of 2 branches missed.">            if (hasSub) {</span>
<span class="nc" id="L601">              newSubCollectorListNextLevel[newPosition] = subCollectorListNextLevel[position];</span>
            }
<span class="fc" id="L603">            copyToNew(position, newPosition);</span>
<span class="fc" id="L604">            newPosition++;</span>
<span class="fc" id="L605">            position++;</span>
            // check if added key from list is right key
<span class="fc bfc" id="L607" title="All 2 branches covered.">            if (newKeyList[(newPosition - 1)].equals(key)) {</span>
<span class="fc bfc" id="L608" title="All 2 branches covered.">              if (increaseSourceNumber) {</span>
<span class="fc" id="L609">                newSourceNumberList[(newPosition - 1)]++;</span>
              }
<span class="fc" id="L611">              newCurrentPosition = newPosition - 1;</span>
<span class="fc" id="L612">              newCurrentExisting = true;</span>
              // register known key found again in segment
<span class="fc" id="L614">              newKnownKeyFoundInSegment.add(key);</span>
              // ready
<span class="pc bpc" id="L616" title="1 of 2 branches missed.">              if (hasSub) {</span>
<span class="nc" id="L617">                return newSubCollectorListNextLevel[newCurrentPosition];</span>
              } else {
<span class="fc" id="L619">                return null;</span>
              }
              // stop if position exceeds size
<span class="fc bfc" id="L622" title="All 2 branches covered.">            } else if (position == getSize()) {</span>
<span class="fc" id="L623">              break;</span>
            }
          }
        }
        // check size
<span class="fc bfc" id="L628" title="All 2 branches covered.">        if (newPosition == newSize) {</span>
<span class="fc" id="L629">          increaseNewListSize();</span>
        }
        // add key
<span class="fc" id="L632">        newKeyList[newPosition] = key;</span>
<span class="fc" id="L633">        newSourceNumberList[newPosition] = 1;</span>
<span class="fc" id="L634">        newErrorNumber[newPosition] = 0;</span>
<span class="fc" id="L635">        newErrorList[newPosition] = new HashMap&lt;&gt;();</span>
<span class="fc" id="L636">        newPosition++;</span>
<span class="fc" id="L637">        newCurrentPosition = newPosition - 1;</span>
<span class="fc" id="L638">        newCurrentExisting = false;</span>
        // ready, only handle sub
<span class="pc bpc" id="L640" title="1 of 2 branches missed.">        if (hasSub) {</span>
<span class="nc" id="L641">          newSubCollectorListNextLevel[newCurrentPosition] = DataCollector</span>
<span class="nc" id="L642">              .getCollector(subCollectorTypes[0], subDataTypes[0],</span>
                  subStatsTypes[0], subStatsItems[0], subSortTypes[0],
                  subSortDirections[0], subStart[0], subNumber[0],
                  newSubCollectorTypes, newSubDataTypes, newSubStatsTypes,
                  newSubStatsItems, newSubSortTypes, newSubSortDirections,
                  newSubStart, newSubNumber, segmentRegistration, null);
<span class="nc" id="L648">          return newSubCollectorListNextLevel[newCurrentPosition];</span>
        } else {
<span class="fc" id="L650">          return null;</span>
        }
      }
    } else {
<span class="nc" id="L654">      throw new IOException(&quot;already closed&quot;);</span>
    }
  }

  /**
   * Copy to new.
   *
   * @param position the position
   * @param newPosition the new position
   */
  protected abstract void copyToNew(int position, int newPosition);

  /**
   * Copy from new.
   */
  protected abstract void copyFromNew();

  /**
   * Compare with boundary.
   *
   * @param value the value
   * @param boundary the boundary
   * @return true, if successful
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected abstract boolean compareWithBoundary(T1 value, T1 boundary)
      throws IOException;

  /**
   * Last for computing segment.
   *
   * @param value the value
   * @param boundary the boundary
   * @return the t1
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected abstract T1 lastForComputingSegment(T1 value, T1 boundary)
      throws IOException;

  /**
   * Last for computing segment.
   *
   * @return the t1
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected abstract T1 lastForComputingSegment() throws IOException;

  /**
   * Boundary for segment.
   *
   * @param segmentName the segment name
   * @return the t1
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected abstract T1 boundaryForSegment(String segmentName)
      throws IOException;

  /**
   * Boundary for segment computing.
   *
   * @param segmentName the segment name
   * @return the t1
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected abstract T1 boundaryForSegmentComputing(String segmentName)
      throws IOException;

  /**
   * String to boundary.
   *
   * @param boundary the boundary
   * @param segmentNumber the segment number
   * @return the t1
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected abstract T1 stringToBoundary(String boundary, Integer segmentNumber)
      throws IOException;

  /**
   * String to boundary.
   *
   * @param boundary the boundary
   * @return the t1
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected T1 stringToBoundary(String boundary) throws IOException {
<span class="nc" id="L740">    return stringToBoundary(boundary, null);</span>
  }

  /**
   * Close segment key value registration.
   *
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public void closeSegmentKeyValueRegistration() throws IOException {
<span class="pc bpc" id="L749" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="fc bfc" id="L750" title="All 2 branches covered.">      if (segmentRegistration != null) {</span>
<span class="fc" id="L751">        Map&lt;String, T1&gt; keyValueList = segmentKeyValueList.get(segmentName);</span>
<span class="fc" id="L752">        T1 tmpSegmentValueBoundary = segmentValuesBoundary.get(segmentName);</span>
<span class="fc bfc" id="L753" title="All 2 branches covered.">        for (Entry&lt;String, T1&gt; entry : keyValueList.entrySet()) {</span>
<span class="pc bpc" id="L754" title="1 of 4 branches missed.">          if (tmpSegmentValueBoundary == null || compareWithBoundary(</span>
<span class="fc" id="L755">              entry.getValue(), tmpSegmentValueBoundary)) {</span>
<span class="fc" id="L756">            segmentKeys.add(entry.getKey());</span>
          }
<span class="fc" id="L758">        }</span>
<span class="fc" id="L759">      }</span>
    } else {
<span class="nc" id="L761">      throw new IOException(&quot;already closed&quot;);</span>
    }
<span class="fc" id="L763">  }</span>

  /**
   * Recompute segment keys.
   *
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public void recomputeSegmentKeys() throws IOException {
<span class="pc bpc" id="L771" title="2 of 4 branches missed.">    if (!closed &amp;&amp; segmentRegistration != null) {</span>
<span class="fc bfc" id="L772" title="All 2 branches covered.">      if (segmentRegistration.equals(SEGMENT_SORT_ASC)</span>
<span class="pc bpc" id="L773" title="1 of 2 branches missed.">          || segmentRegistration.equals(SEGMENT_SORT_DESC)</span>
<span class="nc bnc" id="L774" title="All 2 branches missed.">          || segmentRegistration.equals(SEGMENT_BOUNDARY_ASC)</span>
<span class="nc bnc" id="L775" title="All 2 branches missed.">          || segmentRegistration.equals(SEGMENT_BOUNDARY_DESC)) {</span>

<span class="fc bfc" id="L777" title="All 2 branches covered.">        if (segmentRegistration.equals(SEGMENT_SORT_ASC)</span>
<span class="pc bpc" id="L778" title="1 of 2 branches missed.">            || segmentRegistration.equals(SEGMENT_SORT_DESC)) {</span>
<span class="fc" id="L779">          segmentKeys.clear();</span>
          // recompute boundaries
<span class="fc bfc" id="L781" title="All 2 branches covered.">          for (Entry&lt;String, Map&lt;String, T1&gt;&gt; entry : segmentKeyValueList</span>
<span class="fc" id="L782">              .entrySet()) {</span>
<span class="fc" id="L783">            T1 tmpSegmentValueBoundary = boundaryForSegment(entry.getKey());</span>
<span class="fc" id="L784">            segmentValuesBoundary.put(entry.getKey(), tmpSegmentValueBoundary);</span>
<span class="fc" id="L785">          }</span>
          // compute adjusted boundaries and compute keys
<span class="fc bfc" id="L787" title="All 2 branches covered.">          for (Entry&lt;String, Map&lt;String, T1&gt;&gt; entry : segmentKeyValueList</span>
<span class="fc" id="L788">              .entrySet()) {</span>
<span class="fc" id="L789">            this.segmentName = entry.getKey();</span>
<span class="fc" id="L790">            Map&lt;String, T1&gt; keyValueList = entry.getValue();</span>
<span class="fc" id="L791">            T1 tmpSegmentValueBoundaryForComputing = boundaryForSegmentComputing(</span>
<span class="fc" id="L792">                entry.getKey());</span>
<span class="fc bfc" id="L793" title="All 2 branches covered.">            for (Entry&lt;String, T1&gt; subEntry : keyValueList.entrySet()) {</span>
<span class="pc bpc" id="L794" title="1 of 2 branches missed.">              if (tmpSegmentValueBoundaryForComputing == null</span>
<span class="fc bfc" id="L795" title="All 2 branches covered.">                  || compareWithBoundary(subEntry.getValue(),</span>
                      tmpSegmentValueBoundaryForComputing)) {
<span class="fc bfc" id="L797" title="All 2 branches covered.">                if (!segmentKeys.contains(subEntry.getKey())) {</span>
<span class="fc" id="L798">                  segmentKeys.add(subEntry.getKey());</span>
                }
              }
<span class="fc" id="L801">            }</span>
<span class="fc" id="L802">          }</span>
        }

        Map&lt;String, T1&gt; keyValueList;
        Set&lt;String&gt; recomputeKeyList;
<span class="fc" id="L807">        segmentRecomputeKeyList = new LinkedHashMap&lt;&gt;();</span>
<span class="fc bfc" id="L808" title="All 2 branches covered.">        for (String key : segmentKeys) {</span>
<span class="fc bfc" id="L809" title="All 2 branches covered.">          for (Entry&lt;String, Map&lt;String, T1&gt;&gt; entry : segmentKeyValueList</span>
<span class="fc" id="L810">              .entrySet()) {</span>
<span class="fc" id="L811">            keyValueList = entry.getValue();</span>
<span class="fc bfc" id="L812" title="All 2 branches covered.">            if (!keyValueList.containsKey(key)) {</span>
<span class="fc bfc" id="L813" title="All 2 branches covered.">              if (!segmentRecomputeKeyList.containsKey(entry.getKey())) {</span>
<span class="fc" id="L814">                recomputeKeyList = new HashSet&lt;&gt;();</span>
<span class="fc" id="L815">                segmentRecomputeKeyList.put(entry.getKey(), recomputeKeyList);</span>
              } else {
<span class="fc" id="L817">                recomputeKeyList = segmentRecomputeKeyList.get(entry.getKey());</span>
              }
<span class="fc" id="L819">              recomputeKeyList.add(key);</span>
            }
<span class="fc" id="L821">          }</span>
<span class="fc" id="L822">        }</span>
<span class="fc" id="L823">        this.segmentName = null;</span>
      } else {
<span class="nc" id="L825">        throw new IOException(</span>
            &quot;not for segmentRegistration &quot; + segmentRegistration);
      }
    } else {
<span class="nc" id="L829">      throw new IOException(&quot;already closed or no segmentRegistration (&quot;</span>
          + segmentRegistration + &quot;)&quot;);
    }
<span class="fc" id="L832">  }</span>

  /**
   * Reduce to keys.
   *
   * @param keys the keys
   */
  public abstract void reduceToKeys(Set&lt;String&gt; keys);

  /**
   * Reduce to segment keys.
   */
  public void reduceToSegmentKeys() {
<span class="nc bnc" id="L845" title="All 2 branches missed.">    if (segmentRegistration != null) {</span>
<span class="nc" id="L846">      reduceToKeys(segmentKeys);</span>
    }
<span class="nc" id="L848">  }</span>

  /**
   * Check existence necessary keys.
   *
   * @return true, if successful
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public boolean checkExistenceNecessaryKeys() throws IOException {
<span class="pc bpc" id="L857" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="pc bpc" id="L858" title="1 of 2 branches missed.">      if (segmentRegistration != null) {</span>
<span class="fc bfc" id="L859" title="All 2 branches covered.">        return segmentRecomputeKeyList.size() == 0;</span>
      } else {
<span class="nc" id="L861">        return true;</span>
      }
    } else {
<span class="nc" id="L864">      throw new IOException(&quot;already closed&quot;);</span>
    }
  }

  /**
   * Validate segment boundary.
   *
   * @param o the o
   * @return true, if successful
   * @throws IOException Signals that an I/O exception has occurred.
   */
  abstract public boolean validateSegmentBoundary(Object o) throws IOException;

  /**
   * Validate with segment boundary.
   *
   * @param value the value
   * @return true, if successful
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected boolean validateWithSegmentBoundary(T1 value) throws IOException {
<span class="pc bpc" id="L885" title="1 of 4 branches missed.">    if (!closed &amp;&amp; segmentRegistration != null) {</span>
<span class="fc" id="L886">      T1 tmpSegmentValueBoundary = segmentValuesBoundary.get(segmentName);</span>
<span class="pc bpc" id="L887" title="1 of 2 branches missed.">      if (tmpSegmentValueBoundary == null</span>
<span class="fc bfc" id="L888" title="All 2 branches covered.">          || compareWithBoundary(value, tmpSegmentValueBoundary)) {</span>
<span class="fc" id="L889">        return true;</span>
      }
    }
<span class="fc" id="L892">    return false;</span>
  }

  /**
   * Validate segment value.
   *
   * @param value the value
   * @param maximumNumber the maximum number
   * @param segmentNumber the segment number
   * @return the string
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public String validateSegmentValue(T1 value, int maximumNumber,
      int segmentNumber) throws IOException {
<span class="pc bpc" id="L906" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="pc bpc" id="L907" title="1 of 2 branches missed.">      if (segmentRegistration != null) {</span>
<span class="pc bpc" id="L908" title="1 of 2 branches missed.">        if (maximumNumber &gt; 0) {</span>
<span class="fc" id="L909">          T1 tmpSegmentValueBoundary = segmentValuesBoundary.get(segmentName);</span>
<span class="fc bfc" id="L910" title="All 2 branches covered.">          if (segmentValueTopList.size() &lt; maximumNumber</span>
<span class="fc bfc" id="L911" title="All 2 branches covered.">              || compareWithBoundary(value, tmpSegmentValueBoundary)) {</span>
<span class="fc" id="L912">            return SEGMENT_KEY_OR_NEW;</span>
<span class="fc bfc" id="L913" title="All 2 branches covered.">          } else if (segmentKeys.size() &gt; newKnownKeyFoundInSegment.size()) {</span>
<span class="fc" id="L914">            return SEGMENT_POSSIBLE_KEY;</span>
          } else {
<span class="fc" id="L916">            return null;</span>
          }
        } else {
<span class="nc" id="L919">          return null;</span>
        }
      } else {
<span class="nc" id="L922">        return null;</span>
      }
    } else {
<span class="nc" id="L925">      throw new IOException(&quot;already closed&quot;);</span>
    }
  }

  /**
   * Validate segment value.
   *
   * @param key the key
   * @param value the value
   * @param maximumNumber the maximum number
   * @param segmentNumber the segment number
   * @param test the test
   * @return the string
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public String validateSegmentValue(String key, T1 value, int maximumNumber,
      int segmentNumber, boolean test) throws IOException {
<span class="pc bpc" id="L942" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="pc bpc" id="L943" title="1 of 2 branches missed.">      if (segmentRegistration != null) {</span>
<span class="pc bpc" id="L944" title="1 of 2 branches missed.">        if (maximumNumber &gt; 0) {</span>
<span class="fc" id="L945">          T1 tmpSegmentValueMaxListMin = segmentValueTopListLast</span>
<span class="fc" id="L946">              .get(segmentName);</span>
<span class="fc" id="L947">          T1 tmpSegmentValueBoundary = segmentValuesBoundary.get(segmentName);</span>
<span class="fc bfc" id="L948" title="All 2 branches covered.">          if (segmentValueTopList.size() &lt; maximumNumber) {</span>
<span class="pc bpc" id="L949" title="1 of 2 branches missed.">            if (!test) {</span>
<span class="fc" id="L950">              segmentKeyValueList.get(segmentName).put(key, value);</span>
<span class="fc" id="L951">              segmentValueTopList.add(value);</span>
<span class="fc bfc" id="L952" title="All 2 branches covered.">              segmentValueTopListLast.put(segmentName,</span>
                  (tmpSegmentValueMaxListMin == null) ? value
<span class="fc" id="L954">                      : lastForComputingSegment(tmpSegmentValueMaxListMin,</span>
                          value));
<span class="fc bfc" id="L956" title="All 2 branches covered.">              if (segmentValueTopList.size() == maximumNumber) {</span>
<span class="fc" id="L957">                tmpSegmentValueMaxListMin = segmentValueTopListLast</span>
<span class="fc" id="L958">                    .get(segmentName);</span>
<span class="fc" id="L959">                segmentValueTopListLast.put(segmentName,</span>
                    tmpSegmentValueMaxListMin);
<span class="fc" id="L961">                segmentValuesBoundary.put(segmentName,</span>
<span class="fc" id="L962">                    boundaryForSegmentComputing(segmentName));</span>
              }
            }
<span class="fc bfc" id="L965" title="All 2 branches covered.">            return segmentKeys.contains(key) ? SEGMENT_KEY : SEGMENT_NEW;</span>
<span class="fc bfc" id="L966" title="All 2 branches covered.">          } else if (compareWithBoundary(value, tmpSegmentValueBoundary)) {</span>
            // System.out.println(key+&quot; &quot;+value+&quot; &quot;+tmpSegmentValueBoundary);
<span class="pc bpc" id="L968" title="1 of 2 branches missed.">            if (!test) {</span>
<span class="fc" id="L969">              segmentKeyValueList.get(segmentName).put(key, value);</span>
<span class="fc bfc" id="L970" title="All 2 branches covered.">              if (compareWithBoundary(value, tmpSegmentValueMaxListMin)) {</span>
<span class="fc" id="L971">                segmentValueTopList.add(value);</span>
<span class="fc" id="L972">                segmentValueTopList.remove(tmpSegmentValueMaxListMin);</span>
<span class="fc" id="L973">                tmpSegmentValueMaxListMin = lastForComputingSegment();</span>
<span class="fc" id="L974">                segmentValueTopListLast.put(segmentName,</span>
                    tmpSegmentValueMaxListMin);
<span class="fc" id="L976">                segmentValuesBoundary.put(segmentName,</span>
<span class="fc" id="L977">                    boundaryForSegmentComputing(segmentName));</span>
              }
            }
<span class="fc bfc" id="L980" title="All 2 branches covered.">            return segmentKeys.contains(key) ? SEGMENT_KEY : SEGMENT_NEW;</span>
<span class="fc bfc" id="L981" title="All 2 branches covered.">          } else if (segmentKeys.contains(key)) {</span>
<span class="fc bfc" id="L982" title="All 2 branches covered.">            if (!test) {</span>
<span class="fc" id="L983">              segmentKeyValueList.get(segmentName).put(key, value);</span>
            }
<span class="fc" id="L985">            return SEGMENT_KEY;</span>
          } else {
<span class="fc" id="L987">            return null;</span>
          }
        } else {
<span class="nc" id="L990">          return null;</span>
        }
      } else {
<span class="nc" id="L993">        return null;</span>
      }
    } else {
<span class="nc" id="L996">      throw new IOException(&quot;already closed&quot;);</span>
    }
  }

  /**
   * Sets the error.
   *
   * @param newPosition the new position
   * @param errorNumberItem the error number item
   * @param errorListItem the error list item
   * @param currentExisting the current existing
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected final void setError(int newPosition, int errorNumberItem,
      HashMap&lt;String, Integer&gt; errorListItem, boolean currentExisting)
      throws IOException {
<span class="pc bpc" id="L1012" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="fc bfc" id="L1013" title="All 2 branches covered.">      if (currentExisting) {</span>
<span class="fc" id="L1014">        newErrorNumber[newPosition] += errorNumberItem;</span>
<span class="fc" id="L1015">        HashMap&lt;String, Integer&gt; item = newErrorList[newPosition];</span>
<span class="pc bpc" id="L1016" title="1 of 2 branches missed.">        for (Entry&lt;String, Integer&gt; entry : errorListItem.entrySet()) {</span>
<span class="nc bnc" id="L1017" title="All 2 branches missed.">          if (item.containsKey(entry.getKey())) {</span>
<span class="nc" id="L1018">            item.put(entry.getKey(),</span>
<span class="nc" id="L1019">                item.get(entry.getKey()) + entry.getValue());</span>
          } else {
<span class="nc" id="L1021">            item.put(entry.getKey(), entry.getValue());</span>
          }
<span class="nc" id="L1023">        }</span>
<span class="fc" id="L1024">      } else {</span>
<span class="fc" id="L1025">        newErrorNumber[newPosition] = errorNumberItem;</span>
<span class="fc" id="L1026">        newErrorList[newPosition] = errorListItem;</span>
      }
    } else {
<span class="nc" id="L1029">      throw new IOException(&quot;already closed&quot;);</span>
    }
<span class="fc" id="L1031">  }</span>

  /**
   * Sorted and unique.
   *
   * @param keyList the key list
   * @param size the size
   * @return true, if successful
   * @throws IOException Signals that an I/O exception has occurred.
   */
  private boolean sortedAndUnique(String[] keyList, int size)
      throws IOException {
<span class="pc bpc" id="L1043" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="fc bfc" id="L1044" title="All 2 branches covered.">      for (int i = 1; i &lt; size; i++) {</span>
<span class="fc bfc" id="L1045" title="All 2 branches covered.">        if (keyList[(i - 1)].compareTo(keyList[i]) &gt;= 0) {</span>
<span class="fc" id="L1046">          return false;</span>
        }
      }
<span class="fc" id="L1049">      return true;</span>
    } else {
<span class="nc" id="L1051">      throw new IOException(&quot;already closed&quot;);</span>
    }
  }

  /**
   * Compute sort and unique mapping.
   *
   * @param keyList the key list
   * @param size the size
   * @return the int[][]
   * @throws IOException Signals that an I/O exception has occurred.
   */
  private int[][] computeSortAndUniqueMapping(String[] keyList, int size)
      throws IOException {
<span class="pc bpc" id="L1065" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="pc bpc" id="L1066" title="1 of 2 branches missed.">      if (size &gt; 0) {</span>
<span class="fc" id="L1067">        SortedMap&lt;String, int[]&gt; sortedMap = new TreeMap&lt;&gt;();</span>
<span class="fc bfc" id="L1068" title="All 2 branches covered.">        for (int i = 0; i &lt; size; i++) {</span>
<span class="fc bfc" id="L1069" title="All 2 branches covered.">          if (sortedMap.containsKey(keyList[i])) {</span>
<span class="fc" id="L1070">            int[] previousList = sortedMap.get(keyList[i]);</span>
<span class="fc" id="L1071">            int[] newList = new int[previousList.length + 1];</span>
<span class="fc" id="L1072">            System.arraycopy(previousList, 0, newList, 0, previousList.length);</span>
<span class="fc" id="L1073">            newList[previousList.length] = i;</span>
<span class="fc" id="L1074">            sortedMap.put(keyList[i], newList);</span>
<span class="fc" id="L1075">          } else {</span>
<span class="fc" id="L1076">            sortedMap.put(keyList[i], new int[] { i });</span>
          }
        }
<span class="fc" id="L1079">        Collection&lt;int[]&gt; values = sortedMap.values();</span>
<span class="fc" id="L1080">        int[][] result = new int[sortedMap.size()][];</span>
<span class="fc" id="L1081">        return values.toArray(result);</span>
      } else {
<span class="nc" id="L1083">        return null;</span>
      }
    } else {
<span class="nc" id="L1086">      throw new IOException(&quot;already closed&quot;);</span>
    }
  }

  /**
   * Remap data.
   *
   * @param mapping the mapping
   * @throws IOException Signals that an I/O exception has occurred.
   */
  protected void remapData(int[][] mapping) throws IOException {
<span class="pc bpc" id="L1097" title="1 of 2 branches missed.">    if (!closed) {</span>
      // remap and merge keys
<span class="fc" id="L1099">      String[] newKeyList = new String[mapping.length];</span>
      // process mapping for functions?
<span class="fc" id="L1101">      HashMap&lt;MtasDataCollector&lt;?, ?&gt;, MtasDataCollector&lt;?, ?&gt;&gt; map = new HashMap&lt;&gt;();</span>
<span class="fc" id="L1102">      int[] newSourceNumberList = new int[mapping.length];</span>
<span class="fc" id="L1103">      int[] newErrorNumber = new int[mapping.length];</span>
      @SuppressWarnings(&quot;unchecked&quot;)
<span class="fc" id="L1105">      HashMap&lt;String, Integer&gt;[] newErrorList = (HashMap&lt;String, Integer&gt;[]) new HashMap&lt;?, ?&gt;[mapping.length];</span>
<span class="fc bfc" id="L1106" title="All 2 branches covered.">      for (int i = 0; i &lt; mapping.length; i++) {</span>
<span class="fc" id="L1107">        newKeyList[i] = keyList[mapping[i][0]];</span>
<span class="fc" id="L1108">        newSourceNumberList[i] = sourceNumberList[mapping[i][0]];</span>
<span class="fc bfc" id="L1109" title="All 2 branches covered.">        for (int j = 0; j &lt; mapping[i].length; j++) {</span>
<span class="fc bfc" id="L1110" title="All 2 branches covered.">          if (j == 0) {</span>
<span class="fc" id="L1111">            newErrorNumber[i] = errorNumber[mapping[i][j]];</span>
<span class="fc" id="L1112">            newErrorList[i] = errorList[mapping[i][j]];</span>
          } else {
<span class="fc" id="L1114">            newErrorNumber[i] += errorNumber[mapping[i][j]];</span>
<span class="pc bpc" id="L1115" title="1 of 2 branches missed.">            for (Entry&lt;String, Integer&gt; entry : errorList[mapping[i][j]]</span>
<span class="fc" id="L1116">                .entrySet()) {</span>
<span class="nc bnc" id="L1117" title="All 2 branches missed.">              if (newErrorList[i].containsKey(entry.getKey())) {</span>
<span class="nc" id="L1118">                newErrorList[i].put(entry.getKey(),</span>
<span class="nc" id="L1119">                    newErrorList[i].get(entry.getKey()) + entry.getValue());</span>
              } else {
<span class="nc" id="L1121">                newErrorList[i].put(entry.getKey(), entry.getValue());</span>
              }
<span class="nc" id="L1123">            }</span>
          }
        }
      }
<span class="pc bpc" id="L1127" title="1 of 2 branches missed.">      if (hasSub) {</span>
<span class="nc" id="L1128">        newSubCollectorListNextLevel = new MtasDataCollector&lt;?, ?&gt;[mapping.length];</span>
<span class="nc bnc" id="L1129" title="All 2 branches missed.">        for (int i = 0; i &lt; mapping.length; i++) {</span>
<span class="nc bnc" id="L1130" title="All 2 branches missed.">          for (int j = 0; j &lt; mapping[i].length; j++) {</span>
<span class="nc bnc" id="L1131" title="All 4 branches missed.">            if (j == 0 || newSubCollectorListNextLevel[i] == null) {</span>
<span class="nc" id="L1132">              newSubCollectorListNextLevel[i] = subCollectorListNextLevel[mapping[i][j]];</span>
            } else {
<span class="nc" id="L1134">              newSubCollectorListNextLevel[i]</span>
<span class="nc" id="L1135">                  .merge(subCollectorListNextLevel[mapping[i][j]], map, false);</span>
            }
          }
        }
<span class="nc" id="L1139">        subCollectorListNextLevel = newSubCollectorListNextLevel;</span>
      }
<span class="fc" id="L1141">      keyList = newKeyList;</span>
<span class="fc" id="L1142">      sourceNumberList = newSourceNumberList;</span>
<span class="fc" id="L1143">      errorNumber = newErrorNumber;</span>
<span class="fc" id="L1144">      errorList = newErrorList;</span>
<span class="fc" id="L1145">      size = keyList.length;</span>
<span class="fc" id="L1146">      position = 0;</span>
<span class="fc" id="L1147">    } else {</span>
<span class="nc" id="L1148">      throw new IOException(&quot;already closed&quot;);</span>
    }
<span class="fc" id="L1150">  }</span>

  /**
   * Close new list.
   *
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public void closeNewList() throws IOException {
<span class="fc bfc" id="L1158" title="All 2 branches covered.">    if (!closed) {</span>
<span class="fc bfc" id="L1159" title="All 2 branches covered.">      if (segmentRegistration != null) {</span>
<span class="fc" id="L1160">        this.segmentName = null;</span>
      }
<span class="fc bfc" id="L1162" title="All 2 branches covered.">      if (newSize &gt; 0) {</span>
        // add remaining old
<span class="fc bfc" id="L1164" title="All 2 branches covered.">        while (position &lt; getSize()) {</span>
<span class="pc bpc" id="L1165" title="1 of 2 branches missed.">          if (newPosition == newSize) {</span>
<span class="nc" id="L1166">            increaseNewListSize();</span>
          }
<span class="fc" id="L1168">          newKeyList[newPosition] = keyList[position];</span>
<span class="fc" id="L1169">          newSourceNumberList[newPosition] = sourceNumberList[position];</span>
<span class="fc" id="L1170">          newErrorNumber[newPosition] = errorNumber[position];</span>
<span class="fc" id="L1171">          newErrorList[newPosition] = errorList[position];</span>
<span class="pc bpc" id="L1172" title="1 of 2 branches missed.">          if (hasSub) {</span>
<span class="nc" id="L1173">            newSubCollectorListNextLevel[newPosition] = subCollectorListNextLevel[position];</span>
          }
<span class="fc" id="L1175">          copyToNew(position, newPosition);</span>
<span class="fc" id="L1176">          position++;</span>
<span class="fc" id="L1177">          newPosition++;</span>
        }
        // copy
<span class="fc" id="L1180">        keyList = newKeyList;</span>
<span class="fc" id="L1181">        sourceNumberList = newSourceNumberList;</span>
<span class="fc" id="L1182">        errorNumber = newErrorNumber;</span>
<span class="fc" id="L1183">        errorList = newErrorList;</span>
<span class="fc" id="L1184">        subCollectorListNextLevel = newSubCollectorListNextLevel;</span>
<span class="fc" id="L1185">        copyFromNew();</span>
<span class="fc" id="L1186">        size = newPosition;</span>
        // sort and merge
<span class="fc bfc" id="L1188" title="All 2 branches covered.">        if (!sortedAndUnique(keyList, getSize())) {</span>
<span class="fc" id="L1189">          remapData(computeSortAndUniqueMapping(keyList, getSize()));</span>
        }
      }
<span class="fc" id="L1192">      position = 0;</span>
<span class="fc" id="L1193">      newSize = 0;</span>
<span class="fc" id="L1194">      newPosition = 0;</span>
<span class="fc" id="L1195">      newCurrentPosition = 0;</span>
    }
<span class="fc" id="L1197">  }</span>

  /**
   * Gets the item.
   *
   * @param i the i
   * @return the item
   */
  abstract protected MtasDataItem&lt;T1, T2&gt; getItem(int i);

  /**
   * Checks for sub.
   *
   * @return true, if successful
   */
  protected boolean hasSub() {
<span class="fc" id="L1213">    return hasSub;</span>
  }

  /**
   * Error.
   *
   * @param error the error
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public abstract void error(String error) throws IOException;

  /**
   * Error.
   *
   * @param key the key
   * @param error the error
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public abstract void error(String key, String error) throws IOException;

  /**
   * Adds the.
   *
   * @param valueSum the value sum
   * @param valueN the value N
   * @return the mtas data collector
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public abstract MtasDataCollector add(long valueSum, long valueN)
      throws IOException;

  /**
   * Adds the.
   *
   * @param values the values
   * @param number the number
   * @return the mtas data collector
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public abstract MtasDataCollector add(long[] values, int number)
      throws IOException;

  /**
   * Adds the.
   *
   * @param valueSum the value sum
   * @param valueN the value N
   * @return the mtas data collector
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public abstract MtasDataCollector add(double valueSum, long valueN)
      throws IOException;

  /**
   * Adds the.
   *
   * @param values the values
   * @param number the number
   * @return the mtas data collector
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public abstract MtasDataCollector add(double[] values, int number)
      throws IOException;

  /**
   * Adds the.
   *
   * @param key the key
   * @param valueSum the value sum
   * @param valueN the value N
   * @return the mtas data collector
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public abstract MtasDataCollector add(String key, long valueSum, long valueN)
      throws IOException;

  /**
   * Adds the.
   *
   * @param key the key
   * @param values the values
   * @param number the number
   * @return the mtas data collector
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public abstract MtasDataCollector add(String key, long[] values, int number)
      throws IOException;

  /**
   * Adds the.
   *
   * @param key the key
   * @param valueSum the value sum
   * @param valueN the value N
   * @return the mtas data collector
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public abstract MtasDataCollector add(String key, double valueSum,
      long valueN) throws IOException;

  /**
   * Adds the.
   *
   * @param key the key
   * @param values the values
   * @param number the number
   * @return the mtas data collector
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public abstract MtasDataCollector add(String key, double[] values, int number)
      throws IOException;

  /*
   * (non-Javadoc)
   * 
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
<span class="nc" id="L1332">    StringBuilder text = new StringBuilder();</span>
<span class="nc" id="L1333">    text.append(this.getClass().getSimpleName() + &quot;-&quot; + this.hashCode() + &quot;\n&quot;);</span>
<span class="nc" id="L1334">    text.append(&quot;\t=== &quot; + collectorType + &quot; - &quot; + statsType + &quot; &quot; + statsItems</span>
        + &quot; &quot; + hasSub + &quot; ===\n&quot;);
<span class="nc" id="L1336">    text.append(&quot;\tclosed: &quot; + closed + &quot;\n&quot;);</span>
<span class="nc" id="L1337">    text.append(&quot;\tkeylist: &quot; + Arrays.asList(keyList) + &quot;\n&quot;);</span>
<span class="nc bnc" id="L1338" title="All 2 branches missed.">    text.append(&quot;\tsegmentKeys: &quot;</span>
<span class="nc" id="L1339">        + (segmentKeys != null ? segmentKeys.contains(&quot;1&quot;) : &quot;null&quot;) + &quot;\n&quot;);</span>
<span class="nc" id="L1340">    return text.toString().trim();</span>
  }

  /**
   * Gets the result.
   *
   * @return the result
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public MtasDataCollectorResult&lt;T1, T2&gt; getResult() throws IOException {
<span class="fc bfc" id="L1350" title="All 2 branches covered.">    if (!closed) {</span>
<span class="fc" id="L1351">      close();</span>
    }
<span class="fc" id="L1353">    return result;</span>
  }

  /**
   * Gets the key list.
   *
   * @return the key list
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public Set&lt;String&gt; getKeyList() throws IOException {
<span class="nc bnc" id="L1363" title="All 2 branches missed.">    if (!closed) {</span>
<span class="nc" id="L1364">      close();</span>
    }
<span class="nc" id="L1366">    return new HashSet&lt;&gt;(Arrays.asList(keyList));</span>
  }

  /**
   * Gets the stats items.
   *
   * @return the stats items
   */
  public SortedSet&lt;String&gt; getStatsItems() {
<span class="fc" id="L1375">    return statsItems;</span>
  }

  /**
   * Close.
   *
   * @throws IOException Signals that an I/O exception has occurred.
   */
  @SuppressWarnings({ &quot;rawtypes&quot;, &quot;unchecked&quot; })
  public void close() throws IOException {
<span class="pc bpc" id="L1385" title="1 of 2 branches missed.">    if (!closed) {</span>
<span class="fc" id="L1386">      closeNewList();</span>
<span class="fc bfc" id="L1387" title="All 2 branches covered.">      if (collectorType.equals(DataCollector.COLLECTOR_TYPE_LIST)) {</span>
        // compute initial basic list
<span class="fc" id="L1389">        TreeMap&lt;String, MtasDataItem&lt;T1, T2&gt;&gt; basicList = new TreeMap&lt;&gt;();</span>
<span class="fc bfc" id="L1390" title="All 2 branches covered.">        for (int i = 0; i &lt; getSize(); i++) {</span>
<span class="fc" id="L1391">          MtasDataItem&lt;T1, T2&gt; newItem = getItem(i);</span>
<span class="pc bpc" id="L1392" title="1 of 2 branches missed.">          if (basicList.containsKey(keyList[i])) {</span>
<span class="nc" id="L1393">            newItem.add(basicList.get(keyList[i]));</span>
          }
<span class="fc" id="L1395">          basicList.put(keyList[i], newItem);</span>
        }
        // create result based on basic list
<span class="fc" id="L1398">        result = new MtasDataCollectorResult&lt;&gt;(collectorType, sortType,</span>
            sortDirection, basicList, start, number);
        // reduce
<span class="fc bfc" id="L1401" title="All 2 branches covered.">        if (segmentRegistration != null) {</span>
<span class="fc bfc" id="L1402" title="All 2 branches covered.">          if (segmentRegistration.equals(SEGMENT_SORT_ASC)</span>
<span class="pc bpc" id="L1403" title="1 of 2 branches missed.">              || segmentRegistration.equals(SEGMENT_SORT_DESC)) {</span>
<span class="fc" id="L1404">            reduceToKeys(result.getComparatorList().keySet());</span>
<span class="nc bnc" id="L1405" title="All 2 branches missed.">          } else if (segmentRegistration.equals(SEGMENT_BOUNDARY_ASC)</span>
<span class="nc bnc" id="L1406" title="All 2 branches missed.">              || segmentRegistration.equals(SEGMENT_BOUNDARY_DESC)) {</span>
<span class="nc" id="L1407">            Map&lt;String, MtasDataItemNumberComparator&gt; comparatorList = result</span>
<span class="nc" id="L1408">                .getComparatorList();</span>
<span class="nc" id="L1409">            HashSet&lt;String&gt; filteredKeySet = new HashSet&lt;&gt;();</span>
<span class="nc bnc" id="L1410" title="All 2 branches missed.">            if (segmentRegistration.equals(SEGMENT_BOUNDARY_ASC)) {</span>
<span class="nc bnc" id="L1411" title="All 2 branches missed.">              for (Entry&lt;String, MtasDataItemNumberComparator&gt; entry : comparatorList</span>
<span class="nc" id="L1412">                  .entrySet()) {</span>
<span class="nc bnc" id="L1413" title="All 2 branches missed.">                if (entry.getValue().compareTo(segmentValueBoundary) &lt; 0) {</span>
<span class="nc" id="L1414">                  filteredKeySet.add(entry.getKey());</span>
                }
<span class="nc" id="L1416">              }</span>
            } else {
<span class="nc bnc" id="L1418" title="All 2 branches missed.">              for (Entry&lt;String, MtasDataItemNumberComparator&gt; entry : comparatorList</span>
<span class="nc" id="L1419">                  .entrySet()) {</span>
<span class="nc bnc" id="L1420" title="All 2 branches missed.">                if (entry.getValue().compareTo(segmentValueBoundary) &gt; 0) {</span>
<span class="nc" id="L1421">                  filteredKeySet.add(entry.getKey());</span>
                }
<span class="nc" id="L1423">              }</span>
            }
<span class="nc" id="L1425">            reduceToKeys(filteredKeySet);</span>
<span class="nc" id="L1426">            basicList.keySet().retainAll(filteredKeySet);</span>
<span class="nc" id="L1427">            result = new MtasDataCollectorResult&lt;&gt;(collectorType, sortType,</span>
                sortDirection, basicList, start, number);
          }
        }
<span class="pc bpc" id="L1431" title="1 of 2 branches missed.">      } else if (collectorType.equals(DataCollector.COLLECTOR_TYPE_DATA)) {</span>
<span class="fc bfc" id="L1432" title="All 2 branches covered.">        if (getSize() &gt; 0) {</span>
<span class="fc" id="L1433">          result = new MtasDataCollectorResult&lt;&gt;(collectorType, getItem(0));</span>
        } else {
<span class="fc" id="L1435">          result = new MtasDataCollectorResult&lt;&gt;(collectorType, sortType,</span>
              sortDirection);
        }
      } else {
<span class="nc" id="L1439">        throw new IOException(&quot;type &quot; + collectorType + &quot; not supported&quot;);</span>
      }
<span class="fc" id="L1441">      closed = true;</span>
    }
<span class="fc" id="L1443">  }</span>

  /**
   * Gets the collector type.
   *
   * @return the collector type
   */
  public String getCollectorType() {
<span class="fc" id="L1451">    return collectorType;</span>
  }

  /**
   * Gets the stats type.
   *
   * @return the stats type
   */
  public String getStatsType() {
<span class="fc" id="L1460">    return statsType;</span>
  }

  /**
   * Gets the data type.
   *
   * @return the data type
   */
  public String getDataType() {
<span class="fc" id="L1469">    return dataType;</span>
  }

  /**
   * Gets the size.
   *
   * @return the size
   */
  public int getSize() {
<span class="fc" id="L1478">    return size;</span>
  }

  /**
   * With total.
   *
   * @return true, if successful
   */
  public boolean withTotal() {
<span class="fc" id="L1487">    return withTotal;</span>
  }

  /**
   * Sets the with total.
   *
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public void setWithTotal() throws IOException {
<span class="pc bpc" id="L1496" title="1 of 2 branches missed.">    if (collectorType.equals(DataCollector.COLLECTOR_TYPE_LIST)) {</span>
<span class="pc bpc" id="L1497" title="1 of 2 branches missed.">      if (segmentName != null) {</span>
<span class="nc" id="L1498">        throw new IOException(&quot;can't get total with segmentRegistration&quot;);</span>
      } else {
<span class="fc" id="L1500">        withTotal = true;</span>
      }
    } else {
<span class="nc" id="L1503">      throw new IOException(</span>
          &quot;can't get total for dataCollector of type &quot; + collectorType);
    }
<span class="fc" id="L1506">  }</span>

}
</pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.7.9.201702052155</span></div></body></html>