// Path: streamflyer-experimental/src/main/java/com/github/rwitzel/streamflyer/experimental/range2/MatchResultShifted.java
// public class MatchResultShifted implements MatchResult {
// 
//     private MatchResult delegate;
// 
//     private StringBuilder input;
// 
//     private int shift;
// 
//     /**
//      * 
//      * @param delegate
//      *            the original match result
//      * @param input
//      *            the input where some character before the match have been inserted or removed
//      * @param shift
//      *            the number of characters that are inserted or removed. If the characters are removed, the shift must
//      *            be negative number.
//      */
//     public MatchResultShifted(MatchResult delegate, StringBuilder input, int shift) {
//         super();
//         this.delegate = delegate;
//         this.input = input;
//         this.shift = shift;
//     }
// 
//     @Override
//     public int start() {
//         int result = delegate.start();
//         if (result == -1) {
//             return result;
//         } else {
//             return result + shift;
//         }
//     }
// 
//     @Override
//     public int start(int group) {
//         int result = delegate.start(group);
//         if (result == -1) {
//             return result;
//         } else {
//             return result + shift;
//         }
//     }
// 
//     @Override
//     public int end() {
//         int result = delegate.end();
//         if (result == -1) {
//             return result;
//         } else {
//             return result + shift;
//         }
//     }
// 
//     @Override
//     public int end(int group) {
//         int result = delegate.end(group);
//         if (result == -1) {
//             return result;
//         } else {
//             return result + shift;
//         }
//     }
// 
//     @Override
//     public String group() {
//         int start = start();
//         int end = end();
//         if (start == -1 || end == -1) {
//             return null;
//         } else {
//             return input.substring(start, end);
//         }
//     }
// 
//     @Override
//     public String group(int group) {
//         int start = start(group);
//         int end = end(group);
//         if (start == -1 || end == -1) {
//             return null;
//         } else {
//             return input.substring(start, end);
//         }
//     }
// 
//     @Override
//     public int groupCount() {
//         return delegate.groupCount();
//     }
// 
//     /*
//      * (non-Javadoc)
//      * 
//      * @see java.lang.Object#toString()
//      */
//     @Override
//     public String toString() {
//         return "MatchResultShifted [group=" + group() + ", start=" + start() + ", end=" + end() + "]";
//     }
// 
// }


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.Test;
import com.github.rwitzel.streamflyer.experimental.range2.MatchResultShifted;

            assertEquals("1xx2yy5aa6bb", matcher.group());
            fail("StringIndexOutOfBoundsException expected");
        } catch (StringIndexOutOfBoundsException e) {

        }

        {
            // offset = 0 -> "1xx2yy5aa6bb" will be the match result
            MatchResult result = new MatchResultShifted(matcher, input, -10);
            assertGroups(result, -10);
        }

    }

    private void assertGroups(MatchResult result, int shift) {
        assertGroup(-1, "1xx2yy5aa6bb", 15 + shift, 27 + shift, result);
        assertGroup(0, "1xx2yy5aa6bb", 15 + shift, 27 + shift, result);
        assertGroup(1, "1xx2yy5aa6bb", 15 + shift, 27 + shift, result);
        assertGroup(2, "2yy5aa", 18 + shift, 24 + shift, result);
        assertGroup(3, "5aa", 21 + shift, 24 + shift, result);
        assertGroup(4, null, -1, -1, result);
        assertGroup(5, "5aa", 21 + shift, 24 + shift, result);
        assertGroup(6, "6bb", 24 + shift, 27 + shift, result);
        assertEquals(6, result.groupCount());
    }

    private void assertGroup(int groupIndex, String group, int start, int end, MatchResult matchResult) {
        if (groupIndex >= 0) {
            assertEquals(group, matchResult.group(groupIndex));
            assertEquals(start, matchResult.start(groupIndex));

// Path: streamflyer-experimental/src/main/java/com/github/rwitzel/streamflyer/experimental/range2/MatchResultShifted.java
// public class MatchResultShifted implements MatchResult {
// 
//     private MatchResult delegate;
// 
//     private StringBuilder input;
// 
//     private int shift;
// 
//     /**
//      * 
//      * @param delegate
//      *            the original match result
//      * @param input
//      *            the input where some character before the match have been inserted or removed
//      * @param shift
//      *            the number of characters that are inserted or removed. If the characters are removed, the shift must
//      *            be negative number.
//      */
//     public MatchResultShifted(MatchResult delegate, StringBuilder input, int shift) {
//         super();
//         this.delegate = delegate;
//         this.input = input;
//         this.shift = shift;
//     }
// 
//     @Override
//     public int start() {
//         int result = delegate.start();
//         if (result == -1) {
//             return result;
//         } else {
//             return result + shift;
//         }
//     }
// 
//     @Override
//     public int start(int group) {
//         int result = delegate.start(group);
//         if (result == -1) {
//             return result;
//         } else {
//             return result + shift;
//         }
//     }
// 
//     @Override
//     public int end() {
//         int result = delegate.end();
//         if (result == -1) {
//             return result;
//         } else {
//             return result + shift;
//         }
//     }
// 
//     @Override
//     public int end(int group) {
//         int result = delegate.end(group);
//         if (result == -1) {
//             return result;
//         } else {
//             return result + shift;
//         }
//     }
// 
//     @Override
//     public String group() {
//         int start = start();
//         int end = end();
//         if (start == -1 || end == -1) {
//             return null;
//         } else {
//             return input.substring(start, end);
//         }
//     }
// 
//     @Override
//     public String group(int group) {
//         int start = start(group);
//         int end = end(group);
//         if (start == -1 || end == -1) {
//             return null;
//         } else {
//             return input.substring(start, end);
//         }
//     }
// 
//     @Override
//     public int groupCount() {
//         return delegate.groupCount();
//     }
// 
//     /*
//      * (non-Javadoc)
//      * 
//      * @see java.lang.Object#toString()
//      */
//     @Override
//     public String toString() {
//         return "MatchResultShifted [group=" + group() + ", start=" + start() + ", end=" + end() + "]";
//     }
// 
// }


// Path: streamflyer-experimental/src/test/java/com/github/rwitzel/streamflyer/experimental/range2/MatchResultShiftedTest.java
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.Test;
import com.github.rwitzel.streamflyer.experimental.range2.MatchResultShifted;

            assertEquals("1xx2yy5aa6bb", matcher.group());
            fail("StringIndexOutOfBoundsException expected");
        } catch (StringIndexOutOfBoundsException e) {

        }

        {
            // offset = 0 -> "1xx2yy5aa6bb" will be the match result
            MatchResult result = new MatchResultShifted(matcher, input, -10);
            assertGroups(result, -10);
        }

    }

    private void assertGroups(MatchResult result, int shift) {
        assertGroup(-1, "1xx2yy5aa6bb", 15 + shift, 27 + shift, result);
        assertGroup(0, "1xx2yy5aa6bb", 15 + shift, 27 + shift, result);
        assertGroup(1, "1xx2yy5aa6bb", 15 + shift, 27 + shift, result);
        assertGroup(2, "2yy5aa", 18 + shift, 24 + shift, result);
        assertGroup(3, "5aa", 21 + shift, 24 + shift, result);
        assertGroup(4, null, -1, -1, result);
        assertGroup(5, "5aa", 21 + shift, 24 + shift, result);
        assertGroup(6, "6bb", 24 + shift, 27 + shift, result);
        assertEquals(6, result.groupCount());
    }

    private void assertGroup(int groupIndex, String group, int start, int end, MatchResult matchResult) {
        if (groupIndex >= 0) {
            assertEquals(group, matchResult.group(groupIndex));
            assertEquals(start, matchResult.start(groupIndex));

            assertEquals(end, matchResult.end(groupIndex));
