class JTableSwitchStmt extends AbstractSwitchStmt implements TableSwitchStmt {

  protected int lowIndex;
  protected int highIndex;

  public JTableSwitchStmt(Value key, int lowIndex, int highIndex, List<? extends Unit> targets, Unit defaultTarget) {
    this(Jimple.v().newImmediateBox(key), lowIndex, highIndex, getTargetBoxesArray(targets, Jimple.v()::newStmtBox),
        Jimple.v().newStmtBox(defaultTarget));
  }

  public JTableSwitchStmt(Value key, int lowIndex, int highIndex, List<? extends UnitBox> targets, UnitBox defaultTarget) {
    this(Jimple.v().newImmediateBox(key), lowIndex, highIndex, targets.toArray(new UnitBox[targets.size()]), defaultTarget);
  }

  protected JTableSwitchStmt(ValueBox keyBox, int lowIndex, int highIndex, UnitBox[] targetBoxes, UnitBox defaultTargetBox) {
    super(keyBox, defaultTargetBox, targetBoxes);

    if (lowIndex > highIndex) {
      throw new RuntimeException(
          "Error creating tableswitch: lowIndex(" + lowIndex + ") can't be greater than highIndex(" + highIndex + ").");
    }

    this.lowIndex = lowIndex;
    this.highIndex = highIndex;
  }

  @Override
  public Object clone() {
    return new JTableSwitchStmt(Jimple.cloneIfNecessary(getKey()), lowIndex, highIndex, getTargets(), getDefaultTarget());
  }

  @Override
  public String toString() {
    final char endOfLine = ' ';
    StringBuilder buf = new StringBuilder(Jimple.TABLESWITCH + "(");

    buf.append(keyBox.getValue().toString()).append(')').append(endOfLine);
    buf.append('{').append(endOfLine);

    // In this for-loop, we cannot use "<=" since 'i' would wrap around.
    // The case for "i == highIndex" is handled separately after the loop.
    final int low = lowIndex, high = highIndex;
    for (int i = low; i < high; i++) {
      buf.append("    " + Jimple.CASE + " ").append(i).append(": " + Jimple.GOTO + " ");
      Unit target = getTarget(i - low);
      buf.append(target == this ? "self" : target).append(';').append(endOfLine);
    }
    {
      buf.append("    " + Jimple.CASE + " ").append(high).append(": " + Jimple.GOTO + " ");
      Unit target = getTarget(high - low);
      buf.append(target == this ? "self" : target).append(';').append(endOfLine);
    }
    {
      Unit target = getDefaultTarget();
      buf.append("    " + Jimple.DEFAULT + ": " + Jimple.GOTO + " ");
      buf.append(target == this ? "self" : target).append(';').append(endOfLine);
    }
    buf.append('}');

    return buf.toString();
  }

  @Override
  public void toString(UnitPrinter up) {
    up.literal(Jimple.TABLESWITCH);
    up.literal("(");
    keyBox.toString(up);
    up.literal(")");
    up.newline();
    up.literal("{");
    up.newline();
    // In this for-loop, we cannot use "<=" since 'i' would wrap around.
    // The case for "i == highIndex" is handled separately after the loop.
    final int high = highIndex;
    for (int i = lowIndex; i < high; i++) {
      printCaseTarget(up, i);
    }
    printCaseTarget(up, high);
    up.literal("    " + Jimple.DEFAULT + ": " + Jimple.GOTO + " ");
    defaultTargetBox.toString(up);
    up.literal(";");
    up.newline();
    up.literal("}");
  }

  private void printCaseTarget(UnitPrinter up, int targetIndex) {
    up.literal("    " + Jimple.CASE + " ");
    up.literal(Integer.toString(targetIndex));
    up.literal(": " + Jimple.GOTO + " ");
    targetBoxes[targetIndex - lowIndex].toString(up);
    up.literal(";");
    up.newline();
  }

  @Override
  public void setLowIndex(int lowIndex) {
    this.lowIndex = lowIndex;
  }

  @Override
  public void setHighIndex(int highIndex) {
    this.highIndex = highIndex;
  }

  @Override
  public int getLowIndex() {
    return lowIndex;
  }

  @Override
  public int getHighIndex() {
    return highIndex;
  }

  @Override
  public void apply(Switch sw) {
    ((StmtSwitch) sw).caseTableSwitchStmt(this);
  }

  @Override
  public void convertToBaf(JimpleToBafContext context, List<Unit> out) {<FILL_FUNCTION_BODY>}

  @Override
  public Unit getTargetForValue(int value) {

    final int high = highIndex;
    int tgtIdx = 0;
    // In this for-loop, we cannot use "<=" since 'i' would wrap around.
    // The case for "i == highIndex" is handled separately after the loop.
    for (int i = lowIndex; i < high; i++) {
      if (value == i) {
        return getTarget(tgtIdx);
      }
      tgtIdx++;
    }
    if (high == value) {
      return getTarget(tgtIdx);
    }
    return getDefaultTarget();
  }
}

    ((ConvertToBaf) getKey()).convertToBaf(context, out);

    final Baf vaf = Baf.v();
    final List<Unit> targets = getTargets();
    List<PlaceholderInst> targetPlaceholders = new ArrayList<PlaceholderInst>(targets.size());
    for (Unit target : targets) {
      targetPlaceholders.add(vaf.newPlaceholderInst(target));
    }

    Unit u = vaf.newTableSwitchInst(vaf.newPlaceholderInst(getDefaultTarget()), lowIndex, highIndex, targetPlaceholders);
    u.addAllTagsOf(this);
    out.add(u);
  
<methods>public final boolean branches() ,public final boolean fallsThrough() ,public final soot.Unit getDefaultTarget() ,public final soot.UnitBox getDefaultTargetBox() ,public final soot.Value getKey() ,public final soot.ValueBox getKeyBox() ,public final soot.Unit getTarget(int) ,public final soot.UnitBox getTargetBox(int) ,public final int getTargetCount() ,public final List<soot.Unit> getTargets() ,public final List<soot.UnitBox> getUnitBoxes() ,public final List<soot.ValueBox> getUseBoxes() ,public final void setDefaultTarget(soot.Unit) ,public final void setKey(soot.Value) ,public final void setTarget(int, soot.Unit) ,public final void setTargets(List<? extends soot.Unit>) ,public final void setTargets(soot.Unit[]) <variables>protected final non-sealed soot.UnitBox defaultTargetBox,protected final non-sealed soot.ValueBox keyBox,protected final non-sealed List<soot.UnitBox> stmtBoxes,protected final non-sealed soot.UnitBox[] targetBoxes