net.frontlinesms.plugins.reminders.RemindersDialogHandler.java Source code

Java tutorial

Introduction

Here is the source code for net.frontlinesms.plugins.reminders.RemindersDialogHandler.java

Source

/*
 * FrontlineSMS <http://www.frontlinesms.com>
 * Copyright 2007, 2008 kiwanja
 * 
 * This file is part of FrontlineSMS.
 * 
 * FrontlineSMS is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * 
 * FrontlineSMS is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with FrontlineSMS. If not, see <http://www.gnu.org/licenses/>.
 */
package net.frontlinesms.plugins.reminders;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;

import net.frontlinesms.FrontlineSMS;
import net.frontlinesms.FrontlineUtils;
import net.frontlinesms.data.domain.Contact;
import net.frontlinesms.data.domain.EmailAccount;
import net.frontlinesms.data.events.DatabaseEntityNotification;
import net.frontlinesms.data.repository.ContactDao;
import net.frontlinesms.data.repository.EmailAccountDao;
import net.frontlinesms.events.EventObserver;
import net.frontlinesms.events.FrontlineEventNotification;
import net.frontlinesms.plugins.reminders.data.domain.OnceReminder;
import net.frontlinesms.plugins.reminders.data.domain.Reminder;
import net.frontlinesms.plugins.reminders.data.domain.Reminder.Type;
import net.frontlinesms.plugins.reminders.data.repository.ReminderDao;
import net.frontlinesms.ui.ThinletUiEventHandler;
import net.frontlinesms.ui.UiGeneratorController;
import net.frontlinesms.ui.events.TabChangedNotification;
import net.frontlinesms.ui.handler.ComponentPagingHandler;
import net.frontlinesms.ui.handler.PagedComponentItemProvider;
import net.frontlinesms.ui.handler.PagedListDetails;
import net.frontlinesms.ui.i18n.InternationalisationUtils;

/*
 * RemindersDialogHandler
 * @author Dale Zak
 * 
 * see {@link "http://www.frontlinesms.net"} for more details. 
 * copyright owned by Kiwanja.net
 */
public class RemindersDialogHandler implements ThinletUiEventHandler, PagedComponentItemProvider, EventObserver {

    private static Logger LOG = FrontlineUtils.getLogger(RemindersDialogHandler.class);

    private static final String DIALOG_XML = "/ui/plugins/reminders/remindersForm.xml";

    /**
     * FrontlineSMS
     */
    private FrontlineSMS frontlineController;

    /**
     * UiGeneratorController
     */
    private UiGeneratorController ui;

    /**
     * ApplicationContext
     */
    private ApplicationContext applicationContext;

    private final ReminderDao reminderDao;
    private final ContactDao contactDao;
    private final EmailAccountDao emailAccountDao;

    private Object dialogReminders;
    private ComponentPagingHandler pagerRecipients;
    private Object tableRecipients;
    private Reminder selectedReminder;
    private RemindersCallback remindersCallback;

    private Object comboEmailAccount;

    private Object panelRecipients;
    private Object comboOccurrence;

    private Object comboHourStart;
    private Object comboHourEnd;

    private Object comboMinuteStart;
    private Object comboMinuteEnd;

    private Object comboAmPmStart;
    private Object comboAmPmEnd;

    private Object textDateStart;
    private Object textDateEnd;

    private Object checkboxEmail;
    private Object checkboxMessage;

    private Object buttonDateEnd;

    private Object textMessage;
    private Object textSubject;

    /**
     * RemindersDialogHandler
     * @param ui UiGeneratorController
     * @param applicationContext ApplicationContext
     * @param callback RemindersCallback
     */
    public RemindersDialogHandler(UiGeneratorController ui, ApplicationContext applicationContext,
            RemindersCallback callback) {
        this.ui = ui;
        this.applicationContext = applicationContext;
        this.remindersCallback = callback;
        this.reminderDao = (ReminderDao) this.applicationContext.getBean("reminderDao");
        this.contactDao = this.ui.getFrontlineController().getContactDao();
        this.emailAccountDao = this.ui.getFrontlineController().getEmailAccountFactory();

        this.dialogReminders = this.ui.loadComponentFromFile(DIALOG_XML, this);
        this.panelRecipients = this.ui.find(this.dialogReminders, "panelRecipients");

        this.tableRecipients = this.ui.find(this.dialogReminders, "tableRecipients");
        this.pagerRecipients = new ComponentPagingHandler(this.ui, this, this.tableRecipients);

        this.ui.add(this.panelRecipients, this.pagerRecipients.getPanel());
        this.ui.add(this.dialogReminders);

        this.pagerRecipients.setCurrentPage(0);
        this.pagerRecipients.refresh();

        this.comboEmailAccount = this.ui.find(this.dialogReminders, "comboEmailAccount");
        this.comboOccurrence = this.ui.find(this.dialogReminders, "comboOccurrence");

        this.comboHourStart = this.ui.find(this.dialogReminders, "comboHourStart");
        this.comboHourEnd = this.ui.find(this.dialogReminders, "comboHourEnd");

        this.comboMinuteStart = this.ui.find(this.dialogReminders, "comboMinuteStart");
        this.comboMinuteEnd = this.ui.find(this.dialogReminders, "comboMinuteEnd");

        this.comboAmPmStart = this.ui.find(this.dialogReminders, "comboAmPmStart");
        this.comboAmPmEnd = this.ui.find(this.dialogReminders, "comboAmPmEnd");

        this.textDateStart = this.ui.find(this.dialogReminders, "textDateStart");
        this.textDateEnd = this.ui.find(this.dialogReminders, "textDateEnd");
        this.buttonDateEnd = this.ui.find(this.dialogReminders, "buttonDateEnd");

        this.checkboxEmail = this.ui.find(this.dialogReminders, "checkboxEmail");
        this.checkboxMessage = this.ui.find(this.dialogReminders, "checkboxMessage");

        this.textSubject = this.ui.find(this.dialogReminders, "textSubject");
        this.textMessage = this.ui.find(this.dialogReminders, "textMessage");
    }

    /**
     * Initialize dialog
     * @param reminder Reminder
     */
    public void init(Reminder reminder) {
        this.selectedReminder = reminder;
        loadEmailAccounts();
        this.ui.removeAll(this.comboOccurrence);
        for (Reminder reminderClass : RemindersFactory.getReminderClasses()) {
            Object comboBoxChoice = this.ui.createComboboxChoice(reminderClass.getOccurrenceLabel(),
                    reminderClass.getOccurrence());
            this.ui.add(this.comboOccurrence, comboBoxChoice);
        }
        this.ui.removeAll(this.comboHourStart);
        this.ui.removeAll(this.comboHourEnd);
        for (int hour = 1; hour <= 12; hour++) {
            this.ui.add(this.comboHourStart, this.ui.createComboboxChoice(Integer.toString(hour), hour));
            this.ui.add(this.comboHourEnd, this.ui.createComboboxChoice(Integer.toString(hour), hour));
        }
        this.ui.removeAll(this.comboMinuteStart);
        this.ui.removeAll(this.comboMinuteEnd);
        for (int minute = 0; minute < 60; minute++) {
            this.ui.add(this.comboMinuteStart, this.ui.createComboboxChoice(String.format("%02d", minute), minute));
            this.ui.add(this.comboMinuteEnd, this.ui.createComboboxChoice(String.format("%02d", minute), minute));
        }
        this.ui.removeAll(this.comboAmPmStart);
        this.ui.removeAll(this.comboAmPmEnd);
        for (String amPm : new String[] { "AM", "PM" }) {
            this.ui.add(this.comboAmPmStart, this.ui.createComboboxChoice(amPm, amPm));
            this.ui.add(this.comboAmPmEnd, this.ui.createComboboxChoice(amPm, amPm));
        }
        if (reminder != null) {
            this.ui.setAttachedObject(this.dialogReminders, reminder);
            this.ui.setEnabled(this.comboOccurrence, false);
            for (int index = 0; index < this.ui.getCount(this.comboOccurrence); index++) {
                Object comboOccurrenceItem = this.ui.getItem(this.comboOccurrence, index);
                String comboOccurrenceItemOccurrence = this.ui.getAttachedObject(comboOccurrenceItem).toString();
                if (reminder.getOccurrence().equalsIgnoreCase(comboOccurrenceItemOccurrence)) {
                    this.ui.setSelectedIndex(this.comboOccurrence, index);
                    break;
                }
            }
            occurrenceChanged(this.dialogReminders, this.comboOccurrence);
            setDateFields(reminder.getStartCalendar(), this.textDateStart, this.comboHourStart,
                    this.comboMinuteStart, this.comboAmPmStart);
            setDateFields(reminder.getEndCalendar(), this.textDateEnd, this.comboHourEnd, this.comboMinuteEnd,
                    this.comboAmPmEnd);
            this.ui.setSelected(this.checkboxEmail, reminder.getType() == Reminder.Type.EMAIL);
            this.ui.setSelected(this.checkboxMessage, reminder.getType() == Reminder.Type.MESSAGE);
            this.ui.setText(this.textSubject, reminder.getSubject());
            this.ui.setText(this.textMessage, reminder.getContent());
            this.ui.setText(this.dialogReminders,
                    InternationalisationUtils.getI18NString(RemindersConstants.EDIT_REMINDER));
            this.ui.setIcon(this.dialogReminders, "/icons/reminders_edit.png");
        } else {
            Calendar now = Calendar.getInstance();
            setDateFields(now, this.textDateStart, this.comboHourStart, this.comboMinuteStart, this.comboAmPmStart);
            setDateFields(now, this.textDateEnd, this.comboHourEnd, this.comboMinuteEnd, this.comboAmPmEnd);
            this.ui.setSelected(this.checkboxEmail, true);
            this.ui.setSelected(this.checkboxMessage, false);
            this.ui.setText(this.textSubject, "");
            this.ui.setText(this.textMessage, "");
            this.ui.setEnabled(this.comboOccurrence, true);
            for (int index = 0; index < this.ui.getCount(this.comboOccurrence); index++) {
                Object comboOccurrenceItem = this.ui.getItem(this.comboOccurrence, index);
                if (OnceReminder.isSatisfiedBy(this.ui.getAttachedObject(comboOccurrenceItem).toString())) {
                    this.ui.setSelectedIndex(this.comboOccurrence, index);
                    break;
                }
            }
            this.ui.setText(this.dialogReminders,
                    InternationalisationUtils.getI18NString(RemindersConstants.CREATE_REMINDER));
            this.ui.setIcon(this.dialogReminders, "/icons/reminders_add.png");
        }
    }

    /**
     * Set Front
     * @param frontlineController FrontlineSMS
     */
    public void setFrontline(FrontlineSMS frontlineController) {
        this.frontlineController = frontlineController;
        this.frontlineController.getEventBus().registerObserver(this);
    }

    /**
     * Handle Frontline notification
     * @param notification
     */
    public void notify(FrontlineEventNotification notification) {
        if (notification instanceof DatabaseEntityNotification<?>) {
            Object entity = ((DatabaseEntityNotification<?>) notification).getDatabaseEntity();
            if (entity instanceof Contact) {
                this.pagerRecipients.setCurrentPage(0);
                this.pagerRecipients.refresh();
            }
        } else if (notification instanceof TabChangedNotification) {
            loadEmailAccounts();
        } else if (notification instanceof DatabaseEntityNotification<?>) {
            Object entity = ((DatabaseEntityNotification<?>) notification).getDatabaseEntity();
            if (entity instanceof EmailAccount && !((EmailAccount) entity).isForReceiving()) {
                loadEmailAccounts();
            }
        }
    }

    /**
     * Save reminder
     * @param dialog
     * @param table
     */
    public void saveReminder(Object dialog, Object table) {
        LOG.debug("saveReminder");
        try {
            Type type = this.ui.isSelected(this.checkboxEmail) ? Type.EMAIL : Type.MESSAGE;
            StringBuilder recipients = new StringBuilder();
            for (Object selected : this.ui.getSelectedItems(table)) {
                Contact contact = this.ui.getAttachedObject(selected, Contact.class);
                if (recipients.length() > 0) {
                    recipients.append(Reminder.RECIPIENT_SEPARATOR);
                }
                recipients.append(contact.getName());
            }
            Object occurrenceItem = this.ui.getSelectedItem(this.comboOccurrence);
            String occurrence = this.ui.getAttachedObject(occurrenceItem).toString();

            long startDate = getLongFromDateFields(this.textDateStart, this.comboHourStart, this.comboMinuteStart,
                    this.comboAmPmStart);
            long endDate = getLongFromDateFields(this.textDateEnd, this.comboHourEnd, this.comboMinuteEnd,
                    this.comboAmPmEnd);
            if (OnceReminder.isSatisfiedBy(occurrence)) {
                endDate = startDate;
            }
            String subject = (type == Reminder.Type.EMAIL) ? this.ui.getText(this.textSubject) : "";
            String message = this.ui.getText(this.textMessage);
            EmailAccount emailAccount = getEmailAccount();
            if (type == Type.EMAIL && this.emailAccountDao.getAllEmailAccounts().size() == 0) {
                this.ui.alert(InternationalisationUtils.getI18NString(RemindersConstants.MISSING_EMAIL_ACCOUNT));
            } else if (startDate == 0) {
                this.ui.alert(InternationalisationUtils.getI18NString(RemindersConstants.MISSING_START_DATE));
            } else if (OnceReminder.isSatisfiedBy(occurrence) == false && endDate == 0) {
                this.ui.alert(InternationalisationUtils.getI18NString(RemindersConstants.MISSING_END_DATE));
            } else if (OnceReminder.isSatisfiedBy(occurrence) == false && startDate > endDate) {
                this.ui.alert(InternationalisationUtils.getI18NString(RemindersConstants.MISSING_DATE_RANGE));
            } else if (recipients.length() == 0) {
                this.ui.alert(InternationalisationUtils.getI18NString(RemindersConstants.MISSING_RECIPIENT));
            } else if (type == Type.EMAIL && subject.isEmpty()) {
                this.ui.alert(InternationalisationUtils.getI18NString(RemindersConstants.MISSING_SUBJECT));
            } else if (message.isEmpty()) {
                this.ui.alert(InternationalisationUtils.getI18NString(RemindersConstants.MISSING_MESSAGE));
            } else if (type == Type.EMAIL && emailAccount == null) {
                this.ui.alert(InternationalisationUtils.getI18NString(RemindersConstants.MISSING_EMAIL_ACCOUNT));
            } else {
                Reminder reminder = this.ui.getAttachedObject(dialog, Reminder.class);
                if (reminder != null) {
                    reminder.stopReminder();
                }
                if (reminder != null) {
                    reminder.setStartDate(startDate);
                    reminder.setEndDate(endDate);
                    reminder.setType(type);
                    reminder.setRecipients(recipients.toString());
                    reminder.setSubject(subject);
                    reminder.setContent(message);
                    reminder.setStatus(Reminder.Status.PENDING);
                    reminder.setEmailAccount(type == Type.EMAIL ? emailAccount : null);
                    this.reminderDao.updateReminder(reminder);
                    if (type == Reminder.Type.EMAIL) {
                        this.ui.setStatus(
                                InternationalisationUtils.getI18NString(RemindersConstants.EMAIL_REMINDER_UPDATED));
                    } else {
                        this.ui.setStatus(
                                InternationalisationUtils.getI18NString(RemindersConstants.SMS_REMINDER_UPDATED));
                    }
                } else {
                    reminder = RemindersFactory.createReminder(startDate, endDate, type, recipients.toString(),
                            subject, message, occurrence);
                    reminder.setStatus(Reminder.Status.PENDING);
                    reminder.setEmailAccount(type == Type.EMAIL ? emailAccount : null);
                    this.reminderDao.saveReminder(reminder);
                    if (type == Reminder.Type.EMAIL) {
                        this.ui.setStatus(
                                InternationalisationUtils.getI18NString(RemindersConstants.EMAIL_REMINDER_CREATED));
                    } else {
                        this.ui.setStatus(
                                InternationalisationUtils.getI18NString(RemindersConstants.SMS_REMINDER_CREATED));
                    }
                }
                reminder.scheduleReminder();
                this.ui.remove(dialog);
            }
        } catch (Exception ex) {
            LOG.debug(ex);
            this.ui.alert(ex.getMessage());
        }
        if (remindersCallback != null) {
            remindersCallback.refreshReminders(null);
        }
    }

    /**
     * Remove dialog
     * @param dialog
     */
    public void removeDialog(Object dialog) {
        this.ui.removeDialog(dialog);
    }

    /**
     * Reminder type changed
     * @param checkbox
     * @param textSubject
     * @param textMessage
     */
    public void typeChanged(Object checkbox, Object textSubject, Object textMessage, Object comboboxAccount) {
        LOG.debug("typeChanged");
        if (checkbox == this.checkboxEmail) {
            this.ui.setEnabled(textSubject, true);
            this.ui.setEditable(textSubject, true);
            this.ui.setEnabled(comboboxAccount, true);
        } else if (checkbox == this.checkboxMessage) {
            this.ui.setEnabled(textSubject, false);
            this.ui.setEditable(textSubject, false);
            this.ui.setText(textSubject, "");
            this.ui.setEnabled(comboboxAccount, false);
        }
    }

    /**
     * Occurrence type changed
     * @param dialogReminderForm
     * @param occurrence
     */
    public void occurrenceChanged(Object dialogReminderForm, Object occurrence) {
        LOG.debug("occurrenceChanged");
        if (this.ui.getSelectedIndex(occurrence) == 0) {
            this.ui.setEnabled(this.comboHourEnd, false);
            this.ui.setEnabled(this.comboMinuteEnd, false);
            this.ui.setEnabled(this.comboAmPmEnd, false);
            this.ui.setEnabled(this.buttonDateEnd, false);
            this.ui.setEnabled(this.textDateEnd, false);
            this.ui.setSelectedIndex(this.comboHourEnd, -1);
            this.ui.setSelectedIndex(this.comboMinuteEnd, -1);
            this.ui.setSelectedIndex(this.comboAmPmEnd, -1);
        } else {
            this.ui.setEnabled(this.comboHourEnd, true);
            this.ui.setEnabled(this.comboMinuteEnd, true);
            this.ui.setEnabled(this.comboAmPmEnd, true);
            this.ui.setEnabled(this.textDateEnd, true);
            this.ui.setEnabled(this.buttonDateEnd, true);
        }
    }

    /**
     * Show date selector
     * @param textField
     */
    public void showDateSelecter(Object textField) {
        LOG.debug("showDateSelecter");
        this.ui.showDateSelecter(textField);
    }

    /**
     * Populate table
     */
    public PagedListDetails getListDetails(Object list, int startIndex, int limit) {
        LOG.debug("getListDetails:" + this.ui.getName(list));
        List<Contact> contacts = this.contactDao.getAllContacts(startIndex, limit);
        Object[] listItems = toThinletContacts(contacts, this.selectedReminder);
        return new PagedListDetails(listItems.length, listItems);
    }

    /**
     * Load email accounts
     */
    private void loadEmailAccounts() {
        int index = 0;
        EmailAccount selectedEmailAccount = selectedReminder != null ? selectedReminder.getEmailAccount() : null;
        this.ui.removeAll(this.comboEmailAccount);
        for (EmailAccount emailAccount : this.emailAccountDao.getSendingEmailAccounts()) {
            String comboBoxText = String.format("%s : %s : %s : %s", emailAccount.getAccountName(),
                    emailAccount.getAccountServer(), emailAccount.getProtocol(),
                    emailAccount.getAccountServerPort());
            Object comboBoxItem = this.ui.createComboboxChoice(comboBoxText, emailAccount);
            this.ui.add(this.comboEmailAccount, comboBoxItem);
            if (selectedEmailAccount != null && emailAccount.equals(selectedEmailAccount)) {
                this.ui.setSelectedIndex(this.comboEmailAccount, index);
            }
            index++;
        }
    }

    /**
     * Get email account
     */
    private EmailAccount getEmailAccount() {
        Object selectedItem = this.ui.getSelectedItem(this.comboEmailAccount);
        if (selectedItem != null) {
            return (EmailAccount) this.ui.getAttachedObject(selectedItem);
        }
        return null;
    }

    /**
     * Convert contacts to table rows
     * @param contacts collection of Contacts
     * @param reminder Reminder
     * @return collection of table rows
     */
    private Object[] toThinletContacts(List<Contact> contacts, Reminder reminder) {
        Object[] components = new Object[contacts.size()];
        for (int i = 0; i < components.length; i++) {
            Contact contact = contacts.get(i);
            components[i] = getContactRow(contact, reminder);
        }
        return components;
    }

    /**
     * Get contact table row
     * @param contact Contact
     * @param reminder Reminder
     * @return table row
     */
    private Object getContactRow(Contact contact, Reminder reminder) {
        Object row = this.ui.createTableRow(contact);
        this.ui.add(row, this.ui.createTableCell(contact.getDisplayName()));
        this.ui.add(row, this.ui.createTableCell(contact.getPhoneNumber()));
        this.ui.add(row, this.ui.createTableCell(contact.getEmailAddress()));
        if (reminder != null) {
            for (String contactName : reminder.getRecipientsArray()) {
                if (contactName.equals(contact.getName())) {
                    this.ui.setSelected(row, true);
                }
            }
        }
        return row;
    }

    /**
     * Set date fields
     * @param calendar
     * @param textDate
     * @param comboHour
     * @param comboMinute
     * @param comboAmPm
     */
    private void setDateFields(Calendar calendar, Object textDate, Object comboHour, Object comboMinute,
            Object comboAmPm) {
        this.ui.setText(textDate, getDateStringFromCalendar(calendar));
        if (calendar.get(Calendar.HOUR_OF_DAY) == 0) {
            this.ui.setSelectedIndex(comboHour, 11);
        } else if (calendar.get(Calendar.HOUR_OF_DAY) == 12) {
            this.ui.setSelectedIndex(comboHour, 11);
        } else if (calendar.get(Calendar.HOUR_OF_DAY) < 12) {
            this.ui.setSelectedIndex(comboHour, calendar.get(Calendar.HOUR_OF_DAY) - 1);
        } else if (calendar.get(Calendar.HOUR_OF_DAY) > 12) {
            this.ui.setSelectedIndex(comboHour, calendar.get(Calendar.HOUR_OF_DAY) - 13);
        } else {
            this.ui.setSelectedIndex(comboHour, 0);
        }
        this.ui.setSelectedIndex(comboMinute, calendar.get(Calendar.MINUTE));
        this.ui.setSelectedIndex(comboAmPm, calendar.get(Calendar.AM_PM));
    }

    /**
     * Get time ticks from date fields
     * @param textDate
     * @param comboHour
     * @param comboMinute
     * @param comboAmPm
     * @return time ticks
     */
    private long getLongFromDateFields(Object textDate, Object comboHour, Object comboMinute, Object comboAmPm) {
        try {
            String date = this.ui.getText(textDate);
            int hour = this.ui.getSelectedIndex(comboHour) + 1;
            int minute = this.ui.getSelectedIndex(comboMinute);
            boolean isAM = this.ui.getSelectedIndex(comboAmPm) == 0;
            DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
            Date dateTime = dateFormat.parse(date);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(dateTime);
            if (isAM && hour == 12) {
                calendar.set(Calendar.HOUR_OF_DAY, 0);
            } else if (isAM && hour < 12) {
                calendar.set(Calendar.HOUR_OF_DAY, hour);
            } else if (!isAM && hour == 12) {
                calendar.set(Calendar.HOUR_OF_DAY, 12);
            } else if (!isAM) {
                calendar.set(Calendar.HOUR_OF_DAY, hour + 12);
            }
            calendar.set(Calendar.MINUTE, minute);
            return calendar.getTimeInMillis();
        } catch (ParseException e) {
            return 0;
        }
    }

    /**
     * Get date string from Calendar object
     * @param calendar Calendar
     * @return date string
     */
    private String getDateStringFromCalendar(Calendar calendar) {
        return String.format("%02d/%02d/%d", calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.MONTH) + 1,
                calendar.get(Calendar.YEAR));
    }
}