package com.criteo.biggraphite.graphiteindex;

import java.util.function.BiConsumer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.IntPoint;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.StoredField;

public class MetricPath
{
    public static final char ELEMENT_SEPARATOR = '.';

    public static final String FIELD_PATH = "path";
    public static final String FIELD_LENGTH = "length";
    public static final String FIELD_PART_PREFIX = "p";
    public static final String FIELD_OFFSET = "offset";

    public static Document toDocument(String path)
    {
        Document doc = new Document();

        int length = iterateOnElements(
            path,
            (element, depth) -> doc.add(
                new StringField(
                    FIELD_PART_PREFIX + depth,
                    element,
                    Field.Store.NO
                )
            )
        );

        doc.add(new StringField(FIELD_PATH, path, Field.Store.YES));
        doc.add(new IntPoint(FIELD_LENGTH, length));

        return doc;
    }

    public static Document toDocument(String path, long offset)
    {
        Document doc = toDocument(path);
        doc.add(new StoredField(FIELD_OFFSET, offset));

        return doc;
    }

    public static String getPathFromDocument(Document doc)
    {
        return doc.getField(FIELD_PATH).stringValue();
    }

    public static long getOffsetFromDocument(Document doc)
    {
        return doc.getField(FIELD_OFFSET).numericValue().longValue();
    }

    public static int iterateOnElements(String path, BiConsumer<String, Integer> f)
    {
        int depth = 0;
        int start = 0;
        int end = path.indexOf(ELEMENT_SEPARATOR, start);
        do {
            if (end == -1) {
                end = path.length();
            }

            f.accept(path.substring(start, end), depth);

            depth += 1;
            start = end + 1;
            end = path.indexOf(ELEMENT_SEPARATOR, start);
        } while (start < path.length());

        return depth;
    }
}

@@ -345,16 +345,48 @@
 edField;
+%0Aimport java.util.regex.Pattern;
 %0A%0Apublic
@@ -433,36 +433,130 @@
 nal 
-char ELEMENT_SEPARATOR = '.'
+String ELEMENT_SEPARATOR = %22.%22;%0A    public static final String ELEMENT_SEPARATOR_REGEXP = Pattern.quote(ELEMENT_SEPARATOR)
 ;%0A%0A 
@@ -1875,69 +1875,33 @@
     
-int depth = 0;%0A        int start = 0;%0A        int end
+String%5B%5D elements
  = path.
 inde
@@ -1888,39 +1888,37 @@
 elements = path.
-indexOf
+split
 (ELEMENT_SEPARAT
@@ -1911,39 +1911,39 @@
 LEMENT_SEPARATOR
-, start
+_REGEXP
 );%0A        do %7B%0A
@@ -1941,303 +1941,99 @@
     
-do %7B%0A            if (end == -1) %7B%0A                end = path.length();%0A            %7D%0A%0A            f.accept(path.substring(start, end), depth);%0A%0A            depth += 1;%0A            start = end + 1;%0A            end = path.indexOf(ELEMENT_SEPARATOR, start);%0A        %7D while (start %3C path.length());
+for (int i = 0; i %3C elements.length; i++) %7B%0A            f.accept(elements%5Bi%5D, i);%0A        %7D
 %0A%0A  
@@ -2045,19 +2045,29 @@
  return 
-dep
+elements.leng
 th;%0A    

Use String::split instead of custom code