org.projectforge.address.AddressDao.java Source code

Java tutorial

Introduction

Here is the source code for org.projectforge.address.AddressDao.java

Source

/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
//         www.projectforge.org
//
// Copyright (C) 2001-2013 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition 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 General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.address;

import java.io.PrintWriter;
import java.io.Writer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.projectforge.access.AccessType;
import org.projectforge.access.OperationType;
import org.projectforge.common.DateHelper;
import org.projectforge.common.DateHolder;
import org.projectforge.common.NumberHelper;
import org.projectforge.core.BaseDao;
import org.projectforge.core.BaseSearchFilter;
import org.projectforge.core.Configuration;
import org.projectforge.core.ConfigurationParam;
import org.projectforge.core.QueryFilter;
import org.projectforge.task.TaskDO;
import org.projectforge.task.TaskDao;
import org.projectforge.user.PFUserDO;

/**
 * 
 * @author Kai Reinhard (k.reinhard@micromata.de)
 * 
 */
public class AddressDao extends BaseDao<AddressDO> {
    private static final DateFormat V_CARD_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(AddressDao.class);

    private Configuration configuration;

    private TaskDao taskDao;

    public void setConfiguration(final Configuration configuration) {
        this.configuration = configuration;
    }

    public void setTaskDao(final TaskDao taskDao) {
        this.taskDao = taskDao;
    }

    private PersonalAddressDao personalAddressDao;

    public void setPersonalAddressDao(final PersonalAddressDao personalAddressDao) {
        this.personalAddressDao = personalAddressDao;
    }

    public AddressDao() {
        super(AddressDO.class);
    }

    /**
     * Addresses will be assigned to a default task.
     */
    public Integer getDefaultTaskId() {
        return configuration.getTaskIdValue(ConfigurationParam.DEFAULT_TASK_ID_4_ADDRESSES);
    }

    public List<Locale> getUsedCommunicationLanguages() {
        @SuppressWarnings("unchecked")
        final List<Locale> list = getHibernateTemplate().find(
                "select distinct a.communicationLanguage from AddressDO a where deleted=false and a.communicationLanguage is not null order by a.communicationLanguage");
        return list;
    }

    /**
     * Get the newest address entries (by time of creation).
     * @return
     * @see #getNewestMax()
     */
    public List<AddressDO> getNewest(final BaseSearchFilter filter) {
        final QueryFilter queryFilter = new QueryFilter();
        queryFilter.addOrder(Order.desc("created"));
        if (filter.getMaxRows() > 0) {
            queryFilter.setMaxResults(filter.getMaxRows());
        }
        return getList(queryFilter);
    }

    @Override
    public List<AddressDO> getList(final BaseSearchFilter filter) {
        final AddressFilter myFilter;
        if (filter instanceof AddressFilter) {
            myFilter = (AddressFilter) filter;
        } else {
            myFilter = new AddressFilter(filter);
        }
        final QueryFilter queryFilter = new QueryFilter(myFilter);
        if (StringUtils.isBlank(myFilter.getSearchString()) == true) {
            if (myFilter.isDeleted() == false) {
                if (myFilter.isNewest() == true) {
                    return getNewest(myFilter);
                }
                if (myFilter.isMyFavorites() == true) {
                    // Show only favorites.
                    return personalAddressDao.getMyAddresses();
                }
            }
        } else {
            if (StringUtils.isNumeric(filter.getSearchString()) == true) {
                myFilter.setSearchString("*" + myFilter.getSearchString() + "*");
            }
        }
        if ("filter".equals(myFilter.getListType()) == true) {
            // Proceed contact status:
            // Use filter only for non deleted entries:
            if (myFilter.isActive() == true || myFilter.isNonActive() == true || myFilter.isUninteresting() == true
                    || myFilter.isDeparted() == true || myFilter.isPersonaIngrata() == true) {
                final Collection<ContactStatus> col = new ArrayList<ContactStatus>();
                if (myFilter.isActive() == true) {
                    col.add(ContactStatus.ACTIVE);
                }
                if (myFilter.isNonActive() == true) {
                    col.add(ContactStatus.NON_ACTIVE);
                }
                if (myFilter.isUninteresting() == true) {
                    col.add(ContactStatus.UNINTERESTING);
                }
                if (myFilter.isDeparted() == true) {
                    col.add(ContactStatus.DEPARTED);
                }
                if (myFilter.isPersonaIngrata() == true) {
                    col.add(ContactStatus.PERSONA_INGRATA);
                }
                queryFilter.add(Restrictions.in("contactStatus", col));
            }

            // Proceed address status:
            // Use filter only for non deleted books:
            if (myFilter.isUptodate() == true || myFilter.isOutdated() == true || myFilter.isLeaved() == true) {
                final Collection<AddressStatus> col = new ArrayList<AddressStatus>();
                if (myFilter.isUptodate() == true) {
                    col.add(AddressStatus.UPTODATE);
                }
                if (myFilter.isOutdated() == true) {
                    col.add(AddressStatus.OUTDATED);
                }
                if (myFilter.isLeaved() == true) {
                    col.add(AddressStatus.LEAVED);
                }
                queryFilter.add(Restrictions.in("addressStatus", col));
            }
        }
        queryFilter.addOrder(Order.asc("name"));
        return getList(queryFilter);
    }

    /**
     * @param address
     * @param taskId If null, then task will be set to null;
     * @see BaseDao#getOrLoad(Integer)
     */
    public void setTask(final AddressDO address, final Integer taskId) {
        final TaskDO task = taskDao.getOrLoad(taskId);
        address.setTask(task);
    }

    /**
     * return Always true, no generic select access needed for address objects.
     * @see org.projectforge.core.BaseDao#hasSelectAccess()
     */
    @Override
    public boolean hasSelectAccess(final PFUserDO user, final boolean throwException) {
        return true;
    }

    private void beforeUpdateOrSave(final AddressDO address) {
        if (address != null && address.getTaskId() == null) {
            setTask(address, getDefaultTaskId());
        }
    }

    /**
     * @see org.projectforge.core.BaseDao#hasAccess(Object, OperationType)
     */
    @Override
    public boolean hasAccess(final PFUserDO user, final AddressDO obj, final AddressDO oldObj,
            final OperationType operationType, final boolean throwException) {
        beforeUpdateOrSave(obj);
        return accessChecker.hasPermission(user, obj.getTaskId(), AccessType.TASKS, operationType, throwException);
    }

    /**
     * @see org.projectforge.core.BaseDao#hasUpdateAccess(Object, Object)
     */
    @Override
    public boolean hasUpdateAccess(final PFUserDO user, final AddressDO obj, final AddressDO dbObj,
            final boolean throwException) {
        Validate.notNull(dbObj);
        Validate.notNull(obj);
        beforeUpdateOrSave(obj);
        Validate.notNull(dbObj.getTaskId());
        Validate.notNull(obj.getTaskId());
        if (accessChecker.hasPermission(user, obj.getTaskId(), AccessType.TASKS, OperationType.UPDATE,
                throwException) == false) {
            return false;
        }
        if (dbObj.getTaskId().equals(obj.getTaskId()) == false) {
            // User moves the object to another task:
            if (accessChecker.hasPermission(user, obj.getTaskId(), AccessType.TASKS, OperationType.INSERT,
                    throwException) == false) {
                // Inserting of object under new task not allowed.
                return false;
            }
            if (accessChecker.hasPermission(user, dbObj.getTaskId(), AccessType.TASKS, OperationType.DELETE,
                    throwException) == false) {
                // Deleting of object under old task not allowed.
                return false;
            }
        }
        return true;
    }

    /**
     * Get the birthdays of address entries.
     * @param fromDate Search for birthdays from given date (ignoring the year).
     * @param toDate Search for birthdays until given date (ignoring the year).
     * @param max Maximum number of result entries.
     * @param all If false, only the birthdays of favorites will be returned.
     * @return The entries are ordered by date of year and name.
     */
    public Set<BirthdayAddress> getBirthdays(final Date fromDate, final Date toDate, final int max,
            final boolean all) {
        final QueryFilter filter = new QueryFilter();
        filter.add(Restrictions.isNotNull("birthday"));
        final List<AddressDO> list = getList(filter);
        // Uses not Collections.sort because every comparison needs Calendar.getDayOfYear().
        final Set<BirthdayAddress> set = new TreeSet<BirthdayAddress>();
        final Set<Integer> favorites = getFavorites();
        final DateHolder from = new DateHolder(fromDate);
        final DateHolder to = new DateHolder(toDate);
        DateHolder dh;
        final int fromMonth = from.getMonth();
        final int fromDayOfMonth = from.getDayOfMonth();
        final int toMonth = to.getMonth();
        final int toDayOfMonth = to.getDayOfMonth();
        for (final AddressDO address : list) {
            if (all == false && favorites.contains(address.getId()) == false) {
                // Address is not a favorite address, so ignore it.
                continue;
            }
            dh = new DateHolder(address.getBirthday());
            final int month = dh.getMonth();
            final int dayOfMonth = dh.getDayOfMonth();
            if (DateHelper.dateOfYearBetween(month, dayOfMonth, fromMonth, fromDayOfMonth, toMonth,
                    toDayOfMonth) == false) {
                continue;
            }
            final BirthdayAddress ba = new BirthdayAddress(address);
            if (favorites.contains(address.getId()) == true) {
                ba.setFavorite(true);
            }
            set.add(ba);
        }
        return set;
    }

    public List<PersonalAddressDO> getFavoriteVCards() {
        final List<PersonalAddressDO> list = personalAddressDao.getList();
        final List<PersonalAddressDO> result = new ArrayList<PersonalAddressDO>();
        if (CollectionUtils.isNotEmpty(list) == true) {
            for (final PersonalAddressDO entry : list) {
                if (entry.isFavoriteCard() == true) {
                    result.add(entry);
                }
            }
        }
        return result;
    }

    public Set<Integer> getFavorites() {
        final List<PersonalAddressDO> list = personalAddressDao.getList();
        final Set<Integer> result = new HashSet<Integer>();
        if (CollectionUtils.isNotEmpty(list) == true) {
            for (final PersonalAddressDO entry : list) {
                if (entry.isFavoriteCard() == true) {
                    result.add(entry.getAddressId());
                }
            }
        }
        return result;
    }

    public void exportFavoriteVCards(final Writer out, final List<PersonalAddressDO> favorites) {
        log.info("Exporting personal AddressBook.");
        final PrintWriter pw = new PrintWriter(out);
        for (final PersonalAddressDO entry : favorites) {
            if (entry.isFavoriteCard() == false) {
                // Entry is not marks as vCard-Entry.
                continue;
            }
            final AddressDO addressDO = entry.getAddress();
            exportVCard(pw, addressDO);
        }
        pw.flush();
    }

    /**
     * Exports a single vcard for the given addressDO
     * @param pw
     * @param addressDO
     * @return
     */
    public void exportVCard(final PrintWriter pw, final AddressDO addressDO) {
        if (log.isDebugEnabled() == true) {
            log.debug("Exporting vCard for addressDo : " + addressDO != null ? addressDO.getId() : null);
        }
        pw.println("BEGIN:VCARD");
        pw.println("VERSION:3.0");
        pw.print("N:");
        out(pw, addressDO.getName());
        pw.print(';');
        out(pw, addressDO.getFirstName());
        pw.print(";;");
        out(pw, addressDO.getTitle());
        pw.println(";");
        print(pw, "FN:", getFullName(addressDO));
        if (isGiven(addressDO.getOrganization()) == true || isGiven(addressDO.getDivision()) == true) {
            pw.print("ORG:");
            out(pw, addressDO.getOrganization());
            pw.print(';');
            if (isGiven(addressDO.getDivision()) == true) {
                out(pw, addressDO.getDivision());
            }
            pw.println();
        }
        print(pw, "TITLE:", addressDO.getPositionText());
        print(pw, "EMAIL;type=INTERNET;type=WORK;type=pref:", addressDO.getEmail());
        print(pw, "EMAIL;type=INTERNET;type=HOME;type=pref:", addressDO.getPrivateEmail());
        print(pw, "TEL;type=WORK;type=pref:", addressDO.getBusinessPhone());
        print(pw, "TEL;TYPE=CELL:", addressDO.getMobilePhone());
        print(pw, "TEL;type=WORK;type=FAX:", addressDO.getFax());
        print(pw, "TEL;TYPE=HOME:", addressDO.getPrivatePhone());
        print(pw, "TEL;TYPE=HOME;type=CELL:", addressDO.getPrivateMobilePhone());

        if (isGiven(addressDO.getAddressText()) == true || isGiven(addressDO.getCity()) == true
                || isGiven(addressDO.getZipCode()) == true) {
            pw.print("ADR;TYPE=WORK:;;");
            out(pw, addressDO.getAddressText());
            pw.print(';');
            out(pw, addressDO.getCity());
            pw.print(";;");
            out(pw, addressDO.getZipCode());
            pw.print(';');
            out(pw, addressDO.getCountry());
            pw.println();
        }
        if (isGiven(addressDO.getPrivateAddressText()) == true || isGiven(addressDO.getPrivateCity()) == true
                || isGiven(addressDO.getPrivateZipCode()) == true) {
            pw.print("ADR;TYPE=HOME:;;");
            out(pw, addressDO.getPrivateAddressText());
            pw.print(';');
            out(pw, addressDO.getPrivateCity());
            pw.print(";;");
            out(pw, addressDO.getPrivateZipCode());
            pw.print(";");
            pw.println();
        }
        print(pw, "URL;type=pref:", addressDO.getWebsite());
        if (addressDO.getBirthday() != null) {
            print(pw, "BDAY;value=date:", V_CARD_DATE_FORMAT.format(addressDO.getBirthday()));
        }
        if (isGiven(addressDO.getComment()) == true) {
            print(pw, "NOTE:", addressDO.getComment() + "\\nCLASS: WORK");
        } else {
            print(pw, "NOTE:", "CLASS: WORK");
        }
        // pw.println("TZ:+00:00");
        pw.println("CATEGORIES:ProjectForge");
        pw.print("UID:U");
        pw.println(addressDO.getId());
        pw.println("END:VCARD");
        pw.println();
        // Unused: addressDO.getState();
    }

    /**
     * Used by vCard export for field 'FN' (full name). Concatenates first name, last name and title.
     * @return
     */
    public String getFullName(final AddressDO a) {
        final StringBuffer buf = new StringBuffer();
        boolean space = false;
        if (isGiven(a.getName()) == true) {
            buf.append(a.getName());
            space = true;
        }
        if (isGiven(a.getFirstName()) == true) {
            if (space == true) {
                buf.append(' ');
            } else {
                space = true;
            }
            buf.append(a.getFirstName());
        }
        if (isGiven(a.getTitle()) == true) {
            if (space == true) {
                buf.append(' ');
            } else {
                space = true;
            }
            buf.append(a.getTitle());
        }
        return buf.toString();
    }

    public List<PersonalAddressDO> getFavoritePhoneEntries() {
        final List<PersonalAddressDO> list = personalAddressDao.getList();
        final List<PersonalAddressDO> result = new ArrayList<PersonalAddressDO>();
        if (CollectionUtils.isNotEmpty(list) == true) {
            for (final PersonalAddressDO entry : list) {
                if (entry.isFavoriteBusinessPhone() == true || entry.isFavoriteFax() == true
                        || entry.isFavoriteMobilePhone() == true || entry.isFavoritePrivatePhone() == true) {
                    result.add(entry);
                }
            }
        }
        return result;
    }

    /**
     * Throws UserException, if for example the phone list is empty.
     */
    public void exportFavoritePhoneList(final Writer out, final List<PersonalAddressDO> favorites) {
        log.info("Exporting phone list");
        final PrintWriter pw = new PrintWriter(out);
        pw.println("\"Name\",\"Phone number\"");
        for (final PersonalAddressDO entry : favorites) {
            final AddressDO address = entry.getAddress();
            String number = address.getBusinessPhone();
            if (entry.isFavoriteBusinessPhone() == true && StringUtils.isNotBlank(number)) {
                appendPhoneEntry(pw, address, "", number);
            }
            number = address.getFax();
            if (entry.isFavoriteFax() == true && StringUtils.isNotBlank(number)) {
                appendPhoneEntry(pw, address, "fax", number);
            }
            number = address.getMobilePhone();
            if (entry.isFavoriteMobilePhone() == true && StringUtils.isNotBlank(number)) {
                appendPhoneEntry(pw, address, "mobil", number);
            }
            number = address.getPrivateMobilePhone();
            if (entry.isFavoritePrivateMobilePhone() == true && StringUtils.isNotBlank(number)) {
                final String str = StringUtils.isNotBlank(address.getMobilePhone()) == true ? "mobil privat"
                        : "mobil";
                appendPhoneEntry(pw, address, str, number);
            }
            number = address.getPrivatePhone();
            if (entry.isFavoritePrivatePhone() == true && StringUtils.isNotBlank(number)) {
                appendPhoneEntry(pw, address, "privat", number);
            }
        }
        pw.flush();
    }

    private void print(final PrintWriter pw, final String key, final String value) {
        if (isGiven(value) == false) {
            return;
        }
        pw.print(key);
        out(pw, value);
        pw.println();
    }

    /**
     * Simply calls StringUtils.defaultString(String) and replaces: "\r" -> "", "\n" -> "\\n", "," -> "\\,", ":" -> "\\:" and print the
     * resulted string into given PrintWriter (without newline).
     * @param str
     * @see StringUtils#defaultString(String)
     */
    private void out(final PrintWriter pw, final String str) {
        final String s = StringUtils.defaultString(str);
        boolean cr = false;
        for (int i = 0; i < s.length(); i++) {
            final char ch = s.charAt(i);
            if (ch == ':') {
                pw.print("\\:");
            } else if (ch == ',') {
                pw.print("\\,");
            } else if (ch == ';') {
                pw.print("\\;");
            } else if (ch == '\r') {
                pw.print("\\n");
                cr = true;
                continue;
            } else if (ch == '\n') {
                if (cr == false) {
                    // Print only \n if not already done by previous \r.
                    pw.print("\\n");
                }
            } else {
                pw.print(ch);
            }
            cr = false;
        }
    }

    /**
     * Simply call StringUtils.isNotBlank(String)
     * @param str
     * @return
     * @see StringUtils#isNotBlank(String)
     */
    private boolean isGiven(final String str) {
        return StringUtils.isNotBlank(str);
    }

    private void appendPhoneEntry(final PrintWriter pw, final AddressDO address, final String suffix,
            final String number) {
        if (isGiven(number) == false) {
            // Do nothing, number is empty.
            return;
        }
        final String no = NumberHelper.extractPhonenumber(number,
                configuration.getStringValue(ConfigurationParam.DEFAULT_COUNTRY_PHONE_PREFIX));
        final String name = address.getName();
        pw.print("\"");
        if (StringUtils.isNotEmpty(name)) {
            pw.print(name);
        }
        final String firstName = address.getFirstName();
        if (StringUtils.isNotBlank(firstName)) {
            if (StringUtils.isNotBlank(name)) {
                pw.print(", ");
            }
            pw.print(firstName);
        }
        if (StringUtils.isNotEmpty(suffix)) {
            pw.print(' ');
            pw.print(suffix);
        }
        pw.print("\",\"");
        pw.println(no + "\"");
    }

    @Override
    public AddressDO newInstance() {
        return new AddressDO();
    }

    /**
     * @see org.projectforge.core.BaseDao#useOwnCriteriaCacheRegion()
     */
    @Override
    protected boolean useOwnCriteriaCacheRegion() {
        return true;
    }
}