package org.japura.gui.model;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
import org.japura.gui.event.DateEvent;
import org.japura.gui.event.DateListener;
import org.japura.util.date.DateMask;
import org.japura.util.date.DateSeparator;
import org.japura.util.date.DateUtil;
/**
*
* <P>
* Copyright (C) 2011-2013 Carlos Eduardo Leite de Andrade
* <P>
* This library 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.
* <P>
* This program 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.
* <P>
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <A
* HREF="www.gnu.org/licenses/">www.gnu.org/licenses/</A>
* <P>
* For more information, contact: <A HREF="www.japura.org">www.japura.org</A>
* <P>
*
* @author Carlos Eduardo Leite de Andrade
*/
public class DateDocument extends PlainDocument{
private static final long serialVersionUID = 1L;
private DateSeparator separator;
private DateMask mask;
private Locale locale;
private DateUtil dateUtil;
private String regex;
private boolean autoCompleteEnabled = true;
private Date oldDate;
private boolean oldDateSetted;
public DateDocument() {
this(null, null);
}
public DateDocument(Locale locale, DateSeparator separator) {
if (separator == null) {
this.separator = DateSeparator.SLASH;
} else {
this.separator = separator;
}
this.mask = DateMask.getMask(locale);
this.regex = buildRegex();
setLocale(locale);
this.dateUtil = DateUtil.getInstance();
}
public Locale getLocale() {
return locale;
}
private void setLocale(Locale locale) {
if (locale == null) {
locale = Locale.getDefault();
}
this.locale = locale;
mask = DateMask.getMask(locale);
}
public DateSeparator getSeparator() {
return separator;
}
public boolean isAutoCompleteEnabled() {
return autoCompleteEnabled;
}
public void setAutoCompleteEnabled(boolean enabled) {
this.autoCompleteEnabled = enabled;
}
private String buildRegex() {
String year = "([0-9]{1,4})?";
String dayOrMonth = "([0-9]{1,2})?";
String sep = "(\\" + getSeparator().getSeparator() + ")?";
String regex = "";
if (mask == DateMask.MMDDYYYY || mask == DateMask.DDMMYYYY) {
regex = dayOrMonth + sep + dayOrMonth + sep + year;
} else if (mask == DateMask.YYYYMMDD || mask == DateMask.YYYYDDMM) {
regex = year + sep + dayOrMonth + sep + dayOrMonth;
}
return regex;
}
public boolean isValid() {
if (getLength() > 0) {
if (getDate() != null) {
return true;
}
return false;
}
return true;
}
private GregorianCalendar getGregorianCalendar() {
Date date = getDate();
if (date != null) {
GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(date.getTime());
return gc;
}
return null;
}
public Integer getDay() {
GregorianCalendar gc = getGregorianCalendar();
if (gc != null) {
return gc.get(GregorianCalendar.DAY_OF_MONTH);
}
return null;
}
public Integer getMonth() {
GregorianCalendar gc = getGregorianCalendar();
if (gc != null) {
return gc.get(GregorianCalendar.MONTH) + 1;
}
return null;
}
public Integer getYear() {
GregorianCalendar gc = getGregorianCalendar();
if (gc != null) {
return gc.get(GregorianCalendar.YEAR);
}
return null;
}
public Date getDate() {
try {
String text = getText(0, getLength());
Date date = dateUtil.toDate(locale, getSeparator(), text);
if (date != null) {
return date;
}
} catch (BadLocationException e) {
e.printStackTrace();
}
return null;
}
public void setDate(int day, int month, int year) {
try {
replace(0, getLength(),
DateUtil.toString(mask, getSeparator(), day, month, year), null);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
public void clear() {
try {
remove(0, getLength());
} catch (BadLocationException e) {
e.printStackTrace();
}
}
public void setDate(long time) {
try {
replace(0, getLength(), dateUtil.toString(locale, getSeparator(), time),
null);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
public void setToCurrentDate() {
setDate(System.currentTimeMillis());
}
private String buildCompletedText(String text, String newStr) {
String regex1 = "";
String regex2 = "";
String complt1 = "";
String complt2 = "";
String sep = "\\" + separator.getSeparator();
if (mask == DateMask.DDMMYYYY || mask == DateMask.MMDDYYYY) {
regex1 = "[0-9]{2}";
regex2 = "[0-9]{2}" + sep + "[0-9]{2}";
complt1 = "[0-9]{1,2}(" + sep + "([0-9]{1,4})?)?";
complt2 = "[0-9]{1,4}";
} else if (mask == DateMask.YYYYMMDD || mask == DateMask.YYYYDDMM) {
regex1 = "[0-9]{4}";
complt1 = "[0-9]{1,2}(" + sep + "([0-9]{1,2})?)?";
regex2 = "[0-9]{4}" + sep + "[0-9]{2}";
complt2 = "[0-9]{1,2}";
}
if ((text.matches(regex1) && newStr.matches(complt1))
|| text.matches(regex2) && newStr.matches(complt2)) {
return separator.getSeparator() + newStr;
}
return newStr;
}
public DateMask getMask() {
return mask;
}
@Override
public void remove(int offs, int len) throws BadLocationException {
oldDate = getDate();
super.remove(offs, len);
if (getCurrentWriter() == null) {
fireListeners(oldDate, getDate());
} else {
oldDateSetted = true;
}
}
@Override
public void insertString(int offs, String str, AttributeSet a)
throws BadLocationException {
String newText = null;
if (getLength() > 0) {
String text = getText(0, getLength());
if (isAutoCompleteEnabled() && offs == getLength()) {
str = buildCompletedText(text, str);
}
newText =
text.substring(0, offs) + str + text.substring(offs, getLength());
} else {
if (isAutoCompleteEnabled() && offs == getLength()) {
str = buildCompletedText("", str);
}
newText = str;
}
if (newText.matches(regex)) {
if (oldDateSetted == false) {
oldDate = getDate();
}
super.insertString(offs, str, a);
fireListeners(oldDate, getDate());
}
}
protected void fireListeners(Date oldDate, Date newDate) {
DateEvent event = new DateEvent(this, newDate, oldDate);
DateListener[] listeners = listenerList.getListeners(DateListener.class);
for (DateListener listener : listeners) {
listener.dateChanged(event);
}
oldDate = null;
oldDateSetted = false;
}
public void addDateListener(DateListener listener) {
listenerList.add(DateListener.class, listener);
}
public void removeDateListener(DateListener listener) {
listenerList.remove(DateListener.class, listener);
}
}