Преобразуй perl в java
public int loadBillSchedule(Date startDate, int months) {
    int workFailed = 0;
    int totalDeletesBS = 0;
    int totalDeletesBSC = 0;
    int totalInsertsBS = 0;
    int totalInsertsBSC = 0;

    try {
        // Get default months and start date
        Pair<Integer, Date> defaultParams = getDefaultMonthsStartDate(months, startDate);
        months = defaultParams.getKey();
        startDate = defaultParams.getValue();

        // Get pre-bill offset days
        Pair<String, Integer> prebillParams = rba.getRBAPARAMS("BillingPreBillOffsetDays");
        int prebillOffset = prebillParams.getValue();

        // Get billing schedule override defaults
        Pair<String, Integer> schDefaultsParams = rba.getRBAPARAMS("BillingScheduleOverrideDefaults");
        String schDefaults = schDefaultsParams.getKey();

        // Get customer categories
        Pair<String, Integer> custCategoriesParams = rba.getRBAPARAMS("CustomerCategories");
        String custCategories = custCategoriesParams.getKey();

        // Get billing threshold check defaults
        Pair<String, Integer> thresholdsParams = rba.getRBAPARAMS("BillingThresholdCheckDefaults");
        String thresholds = thresholdsParams.getKey();

        // Parse billing schedule defaults
        HashMap<String, Integer> billDays = new HashMap<>();
        for (String item : schDefaults.split("\\|")) {
            String[] parts = item.split(",");
            int billDay = Integer.parseInt(parts[0]);
            int schDay = Integer.parseInt(parts[1]);
            if (billDay < 1 || billDay > 28) {
                rba.logError("Invalid bill day of " + billDay + " with schedule day of " + schDay);
                return 1;
            }
            if (schDay < 1 || schDay > 28) {
                rba.logError("Invalid schedule day of " + schDay + " with bill day of " + billDay);
                return 1;
            }
            if (billDay > schDay && schDay > 4) {
                rba.logError("Invalid combination of schedule day of " + schDay + " with bill day of " + billDay);
                return 1;
            }
            if (billDay > schDay && billDay < 25) {
                rba.logError("Invalid combination of schedule day of " + schDay + " with bill day of " + billDay);
                return 1;
            }
            // set bogey that schedule_dat can't be more than 5 days later than NBD day
            if (billDay < schDay && billDay + 5 < schDay) {
                rba.logError("Invalid combination of schedule day of " + schDay + " with bill day of " + billDay);
                return 1;
            }
            billDays.put(String.format("%02d", billDay), schDay);
        }

        // Parse customer categories
        HashMap<String, String> categories = new HashMap<>();
        for (String item : custCategories.split("\\|")) {
            String[] parts = item.split(",");
            String id = parts[0];
            String category = parts[1];
            categories.put(id, category);
        }

        // Parse billing threshold check defaults
        HashMap<String, Integer> thresholdPercent = new HashMap<>();
        HashMap<String, Integer> thresholdQuantity = new HashMap<>();
        for (String item : thresholds.split("\\|")) {
            String[] parts = item.split(",");
            String id = parts[0];
            int percent = Integer.parseInt(parts[1]);
            int quantity = Integer.parseInt(parts[2]);
            thresholdPercent.put(id, percent);
            thresholdQuantity.put(id, quantity);
        }

        // Check pre-bill offset days
        if (prebillOffset < 1 || prebillOffset > 9 || prebillOffset == 0) {
            rba.logError("Invalid BillingPreBillOffsetDays setting of " + prebillOffset + " - must be 1 to 9 days");
            return 1;
        }

        // Check category and threshold details
        for (String key : categories.keySet()) {
            if (!thresholdPercent.containsKey(key)) {
                rba.logError("Can't find BillingThresholdCheckDefaults details for id " + key + " category " + categories.get(key));
                return 1;
            }
        }

        for (String key : thresholdPercent.keySet()) {
            if (!categories.containsKey(key)) {
                rba.logError("Can't find CustomerCategories details for id " + key);
                return 1;
            }
        }

        // Prepare statements for database operations
        PreparedStatement deleteBS = rba.db.prepareStatement("delete fromBILL_SCHEDULE where BS_MONTH=? and BS_YEAR=?");
        PreparedStatement deleteBSC = rba.db.prepareStatement("delete from BILL_SCHEDULE_CUSTOMERS where BS_MONTH=? and BS_YEAR=?");
        PreparedStatement insertBS = rba.db.prepareStatement("insert into BILL_SCHEDULE (BS_MONTH, BS_YEAR, BS_DAY, BS_SCH_DAY, BS_PREBILL_OFFSET) values (?, ?, ?, ?, ?)");
        PreparedStatement insertBSC = rba.db.prepareStatement("insert into BILL_SCHEDULE_CUSTOMERS (BS_MONTH, BS_YEAR, CUST_ID, BILL_THRESHOLD_PERCENT, BILL_THRESHOLD_QUANTITY) values (?, ?, ?, ?, ?)");

        // Loop through each month and insert/update the bill schedule
        Calendar cal = Calendar.getInstance();
        cal.setTime(startDate);
        for (int i = 0; i < months; i++) {
            int month = cal.get(Calendar.MONTH) + 1;
            int year = cal.get(Calendar.YEAR);
            int daysInMonth = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
            int prebillDay = daysInMonth - prebillOffset;

            // Delete any existing records for this month/year
            deleteBS.setInt(1, month);
            deleteBS.setInt(2, year);
            totalDeletesBS += deleteBS.executeUpdate();

            deleteBSC.setInt(1, month);
            deleteBSC.setInt(2, year);
            totalDeletesBSC += deleteBSC.executeUpdate();

            // Insert new bill schedule for this month/year
            for (int day = 1; day <= daysInMonth; day++) {
                String billDayStr = String.format("%02d", day);
                int schDay = billDays.getOrDefault(billDayStr, day);
                insertBS.setInt(1, month);
                insertBS.setInt(2, year);
                insertBS.setInt(3, day);
                insertBS.setInt(4, schDay);
                insertBS.setInt(5, prebillDay);
                totalInsertsBS += insertBS.executeUpdate();
            }

            // Insert new bill schedule customers for this month/year
            for (Map.Entry<String, String> entry : categories.entrySet()) {
                String custId = entry.getKey();
                String category = entry.getValue();
                int thresholdPct = thresholdPercent.get(custId);
                int thresholdQty = thresholdQuantity.get(custId);
                insertBSC.setInt(1, month);
                insertBSC.setInt(2, year);
                insertBSC.setString(3, custId);
                insertBSC.setInt(4, thresholdPct);
                insertBSC.setInt(5, thresholdQty);
                totalInsertsBSC += insertBSC.executeUpdate();
            }

            // Move to next month
            cal.add(Calendar.MONTH, 1);
        }

    } catch (Exception e) {
        rba.logError("Error loading bill schedule: " + e.getMessage());
        workFailed = 1;
    }

    rba.logInfo(String.format("Bill schedule loaded: %d deletes from BILL_SCHEDULE, %d deletes from BILL_SCHEDULE_CUSTOMERS, %d inserts into BILL_SCHEDULE, %d inserts into BILL_SCHEDULE_CUSTOMERS", totalDeletesBS, totalDeletesBSC, totalInsertsBS, totalInsertsBSC));

    return workFailed;
}