@Nullable
      @Override
      public SwitchOnStringCandidate recognize(@NotNull SwitchStatement firstSwitch,
                                               @NotNull InvocationExprent switchSelector) {
        if (switchSelector.getInstance() == null || switchSelector.getInstance().type != Exprent.EXPRENT_VAR) return null;
        if (!switchSelector.isInstanceCall(ClassNameConstants.JAVA_LANG_STRING, "hashCode", 0)) return null;

        Set<Object> realCaseValueHashCodes = findRealCaseValuesHashCodes(firstSwitch);
        VarExprent firstSwitchSelectorQualifier = (VarExprent)switchSelector.getInstance();
        VarExprent tmpVarAssignTo = null;
        SwitchStatement secondSwitch = null;
        Map<Integer, String> mappedCaseLabelValues = new HashMap<>();
        for (Statement statement : firstSwitch.getCaseStatements()) {
          if (statement.type != StatementType.IF) {
            Statement defaultStatement = firstSwitch.getDefaultEdge().getDestination();
            if (defaultStatement != statement) return null;
            continue;
          }
          IfStatement ifStatement = (IfStatement)statement;
          String caseLabelValue = findRealCaseValue(ifStatement, firstSwitchSelectorQualifier);
          if (caseLabelValue == null) return null;
          if (!realCaseValueHashCodes.remove(caseLabelValue.hashCode())) return null;
          if (ifStatement.getIfstat() == null) return null;
          List<Exprent> ifStatementExprents = ifStatement.getIfstat().getExprents();
          if (ifStatementExprents == null || ifStatementExprents.size() != 1) return null;
          if (ifStatementExprents.get(0).type != Exprent.EXPRENT_ASSIGNMENT) return null;
          AssignmentExprent assignment = (AssignmentExprent)ifStatementExprents.get(0);
          if (assignment.getLeft().type != Exprent.EXPRENT_VAR || assignment.getRight().type != Exprent.EXPRENT_CONST) return null;
          // tmp variable should be the same for all assignments
          if (tmpVarAssignTo != null && !tmpVarAssignTo.equals(assignment.getLeft())) return null;
          tmpVarAssignTo = (VarExprent)assignment.getLeft();
          Object valueAssignedToTmpVar = ((ConstExprent)assignment.getRight()).getValue();
          if (!(valueAssignedToTmpVar instanceof Integer)) return null;
          mappedCaseLabelValues.put((Integer)valueAssignedToTmpVar, caseLabelValue);

          if (ifStatement.getLabelEdges().size() != 1) return null;
          Statement edgeDestination = ifStatement.getLabelEdges().iterator().next().getDestination();
          if (edgeDestination.type == StatementType.SEQUENCE) {
            edgeDestination = edgeDestination.getFirst();
          }
          if (edgeDestination.type != StatementType.SWITCH) return null;
          // the switch should be the same for all case labels
          if (secondSwitch != null && secondSwitch != edgeDestination) return null;
          secondSwitch = (SwitchStatement)edgeDestination;
        }
        if (secondSwitch == null || !realCaseValueHashCodes.isEmpty()) return null;

        Exprent siblingSwitchExprent = secondSwitch.getHeadExprent();
        if (siblingSwitchExprent == null) return null;
        if (siblingSwitchExprent.type != Exprent.EXPRENT_SWITCH) return null;
        if (!tmpVarAssignTo.equals(((SwitchExprent)siblingSwitchExprent).getValue())) return null;

        Exprent secondSwitchSelector = secondSwitch.getHeadExprent();
        if (secondSwitchSelector == null || secondSwitchSelector.type != Exprent.EXPRENT_SWITCH) return null;
        Statement firstStatementInFirstSwitch = firstSwitch.getFirst();
        if (firstStatementInFirstSwitch.type != StatementType.BASIC_BLOCK) return null;
        Statement firstStatementInSecondSwitch = secondSwitch.getFirst();
        if (firstStatementInSecondSwitch.type != StatementType.BASIC_BLOCK) return null;
        List<Exprent> firstSwitchExprents = firstStatementInFirstSwitch.getExprents();
        if (firstSwitchExprents == null || firstStatementInSecondSwitch.getExprents() == null) return null;

        return new SwitchOnStringCandidate.JavacSwitchCandidate(firstSwitch, firstSwitchSelectorQualifier, tmpVarAssignTo, secondSwitch,
                                                                mappedCaseLabelValues,
                                                                firstSwitchExprents,
                                                                secondSwitchSelector,
                                                                firstStatementInSecondSwitch);
      }
@Nullable
      @Override
      public SwitchOnStringCandidate recognize(@NotNull SwitchStatement firstSwitch,
                                               @NotNull InvocationExprent switchSelector)