package com.spun.util.parser; import java.util.Arrays; /***********************************************************************/ public class SteppingIterator { public static final int[] DEFAULT_STEPPING = {1}; private int offset = 0; private int[] stepping = DEFAULT_STEPPING; private int actualSize = 0; /***********************************************************************/ public SteppingIterator(int offset, int[] stepping, int actualSize) { this.offset = offset; this.stepping = stepping; this.actualSize = actualSize; assertSteppingValid(stepping); } /***********************************************************************/ private void assertSteppingValid(int[] stepping) { if (stepping == null || stepping.length == 0 || stepping[0] == 0) { throw new NullPointerException( "Stepping cannot be null or zero in " + Arrays.toString(stepping)); } for (int i = stepping.length - 1; i > 0; i--) { if (stepping[i - 1] % stepping[i] != 0) { String string = String.format("Invalid stepping parameters - %s is not divisible by %s in parameters %s", stepping[i - 1], stepping[i], Arrays.toString(stepping)); throw new Error(string); } } } /***********************************************************************/ public boolean isLast(int currentPlace, int forSteppingLevel) { if (forSteppingLevel == -1 || stepping[forSteppingLevel] == 1) { return (currentPlace + 1) == getSize(true, true); } else { return (((currentPlace + 1) % stepping[forSteppingLevel]) == 0); } } /************************************************************************/ public boolean isFirst(int index, int forSteppingLevel) { return (getStepPositionForRound(forSteppingLevel, 0, index) == 0); } /************************************************************************/ public int getSize(boolean includeOffset, boolean includeStepping) { int size = actualSize; size += includeOffset ? offset : 0; if (includeStepping && (size % stepping[0]) != 0) { size += (stepping[0] - (size % stepping[0])); } return size; } /***********************************************************************/ /** * @return the index of the current Step. **/ public static int getStepCountForRound(int forSteppingLevel, int onIndex, int stepping[], int indexBase) { if (forSteppingLevel == -1 || stepping[forSteppingLevel] == 1) { return indexBase; } else { return ((onIndex / stepping[forSteppingLevel]) + indexBase); } } /***********************************************************************/ public int getStepCountForRound(int forSteppingLevel, int currentPlace, int indexBase) { return getStepCountForRound(forSteppingLevel, currentPlace, this.stepping, indexBase); } /***********************************************************************/ public int getTotalStepCountForRound(int forSteppingLevel, int indexBase) { return getStepCountForRound(forSteppingLevel, getSize(true, true) - 1, stepping, indexBase); } /***********************************************************************/ public int getStepPositionForRound(int forSteppingLevel, int indexBase, int currentIndex) { if (forSteppingLevel == -1 || stepping[forSteppingLevel] == 1) { return currentIndex + indexBase; } else { return ((currentIndex % stepping[forSteppingLevel]) + indexBase); } } /***********************************************************************/ public int getActualPosition(int position) { position = position - this.offset; return (position < 0 || this.actualSize <= position) ? -1 : position; } /************************************************************************/ /************************************************************************/ }