@Override
  public Object visit(ASTElseClause node, Object data) {
    LOGGER.entering(CLASS_NAME, "visit(ASTElseClause)");
    // (npath of if + npath of else (or 1) + bool_comp of if) * npath of
    // next

    int complexity = 0;

    List<PLSQLNode> statementChildren = new ArrayList<PLSQLNode>();
    for (int i = 0; i < node.jjtGetNumChildren(); i++) {
      if (node.jjtGetChild(i).getClass() == ASTStatement.class) {
        statementChildren.add((PLSQLNode) node.jjtGetChild(i));
      }
    }
    if (LOGGER.isLoggable(Level.FINEST)) {
      LOGGER.finest(
          statementChildren.size()
              + " statementChildren found for ELSE clause statement "
              + node.getBeginLine()
              + ", column "
              + node.getBeginColumn());
    }

    for (PLSQLNode element : statementChildren) {
      complexity += (Integer) element.jjtAccept(this, data);
    }

    LOGGER.exiting(CLASS_NAME, "visit(ASTElseClause)", complexity);
    return Integer.valueOf(complexity);
  }
  @Override
  public Object visit(ASTIfStatement node, Object data) {
    LOGGER.entering(CLASS_NAME, "visit(ASTIfStatement)");
    // (npath of if + npath of else (or 1) + bool_comp of if) * npath of
    // next

    int boolCompIf = sumExpressionComplexity(node.getFirstChildOfType(ASTExpression.class));

    int complexity = 0;

    List<PLSQLNode> statementChildren = new ArrayList<PLSQLNode>();
    for (int i = 0; i < node.jjtGetNumChildren(); i++) {
      if (node.jjtGetChild(i).getClass() == ASTStatement.class
          || node.jjtGetChild(i).getClass() == ASTElsifClause.class
          || node.jjtGetChild(i).getClass() == ASTElseClause.class) {
        statementChildren.add((PLSQLNode) node.jjtGetChild(i));
      }
    }
    if (LOGGER.isLoggable(Level.FINEST)) {
      LOGGER.finest(
          statementChildren.size()
              + " statementChildren found for IF statement "
              + node.getBeginLine()
              + ", column "
              + node.getBeginColumn());
    }

    /*
     * SRT if (statementChildren.isEmpty() || statementChildren.size() == 1
     * && ( null != node.getFirstChildOfType(ASTElseClause.class) )
     * //.hasElse() || statementChildren.size() != 1 && ( null ==
     * node.getFirstChildOfType(ASTElseClause.class) ) // !node.hasElse() )
     * { throw new
     * IllegalStateException("If node has wrong number of children"); }
     */

    /*
     * @TODO Any explicit Elsif clause(s) and Else clause are included in
     * the list of statements // add path for not taking if if (null ==
     * node.getFirstChildOfType(ASTElsifClause.class) ) //
     * !node.hasElse()!node.hasElse()) { complexity++; }
     *
     * if (null == node.getFirstChildOfType(ASTElseClause.class) ) //
     * !node.hasElse()!node.hasElse()) { complexity++; }
     */

    for (PLSQLNode element : statementChildren) {
      complexity += (Integer) element.jjtAccept(this, data);
    }

    LOGGER.exiting(CLASS_NAME, "visit(ASTIfStatement)", boolCompIf + complexity);
    return Integer.valueOf(boolCompIf + complexity);
  }
  private int complexityMultipleOf(PLSQLNode node, int npathStart, Object data) {
    LOGGER.entering(CLASS_NAME, "complexityMultipleOf(SimpleNode)");

    int npath = npathStart;
    PLSQLNode n;

    for (int i = 0; i < node.jjtGetNumChildren(); i++) {
      n = (PLSQLNode) node.jjtGetChild(i);
      npath *= (Integer) n.jjtAccept(this, data);
    }

    LOGGER.exiting(CLASS_NAME, "complexityMultipleOf(SimpleNode)", npath);
    return npath;
  }
  @Override
  public Object visit(ASTCaseStatement node, Object data) {
    LOGGER.entering(CLASS_NAME, "visit(ASTCaseStatement)");
    // bool_comp of switch + sum(npath(case_range))

    int boolCompSwitch = sumExpressionComplexity(node.getFirstChildOfType(ASTExpression.class));

    int npath = 0;
    int caseRange = 0;
    for (int i = 0; i < node.jjtGetNumChildren(); i++) {
      PLSQLNode n = (PLSQLNode) node.jjtGetChild(i);

      // Fall-through labels count as 1 for complexity
      Integer complexity = (Integer) n.jjtAccept(this, data);
      caseRange *= complexity;
    }
    // add in npath of last label
    npath += caseRange;
    LOGGER.exiting(CLASS_NAME, "visit(ASTCaseStatement)", (boolCompSwitch + npath));
    return Integer.valueOf(boolCompSwitch + npath);
  }