///////////////////////////////////////////////////////////////////////////// // // Project ProjectForge Community Edition // www.projectforge.org // // Copyright (C) 2001-2014 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.user; import java.io.Serializable; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.util.List; 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.AccessException; import org.projectforge.access.OperationType; import org.projectforge.common.NumberHelper; import org.projectforge.common.StringHelper; import org.projectforge.core.BaseDO; import org.projectforge.core.BaseDao; import org.projectforge.core.BaseSearchFilter; import org.projectforge.core.DefaultBaseDO; import org.projectforge.core.QueryFilter; import org.projectforge.core.UserPrefParameter; import org.projectforge.database.HibernateUtils; import org.projectforge.fibu.KundeDO; import org.projectforge.fibu.KundeDao; import org.projectforge.fibu.ProjektDO; import org.projectforge.fibu.ProjektDao; import org.projectforge.fibu.kost.Kost2DO; import org.projectforge.fibu.kost.Kost2Dao; import org.projectforge.task.TaskDO; import org.projectforge.task.TaskDao; /** * * @author Kai Reinhard (k.reinhard@micromata.de) * */ public class UserPrefDao extends BaseDao<UserPrefDO> { private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(UserPrefDao.class); private static final String[] ADDITIONAL_SEARCH_FIELDS = new String[] { "user.username", "user.firstname", "user.lastname"}; private Kost2Dao kost2Dao; private KundeDao kundeDao; private ProjektDao projektDao; private TaskDao taskDao; private UserDao userDao; @Override protected String[] getAdditionalSearchFields() { return ADDITIONAL_SEARCH_FIELDS; } public UserPrefDao() { super(UserPrefDO.class); } /** * Gets all names of entries of the given area for the current logged in user * @param area * @return */ public String[] getPrefNames(final UserPrefArea area) { final PFUserDO user = PFUserContext.getUser(); @SuppressWarnings("unchecked") final List<Object> list = getSession().createQuery("select name from UserPrefDO t where user_fk=? and areaString = ? order by name") .setInteger(0, user.getId()).setParameter(1, area.getId()).list(); final String[] result = new String[list.size()]; int i = 0; for (final Object oa : list) { result[i++] = (String) oa; } return result; } /** * Does (another) entry for the given user with the given area and name already exists? * @param id of the current data object (null for new objects). * @param user * @param area * @param name * @return */ @SuppressWarnings("unchecked") public boolean doesParameterNameAlreadyExist(final Integer id, final PFUserDO user, final UserPrefArea area, final String name) { Validate.notNull(user); Validate.notNull(area); Validate.notNull(name); final List<UserPrefDO> list; if (id != null) { list = getHibernateTemplate().find("from UserPrefDO u where pk <> ? and u.user.id = ? and areaString = ? and name = ?", new Object[] { id, user.getId(), area.getId(), name}); } else { list = getHibernateTemplate().find("from UserPrefDO u where u.user.id = ? and areaString = ? and name = ?", new Object[] { user.getId(), area.getId(), name}); } if (CollectionUtils.isNotEmpty(list) == true) { return true; } return false; } @Override public List<UserPrefDO> getList(final BaseSearchFilter filter) { final UserPrefFilter myFilter = (UserPrefFilter) filter; final QueryFilter queryFilter = new QueryFilter(filter); if (myFilter.getArea() != null) { queryFilter.add(Restrictions.eq("areaString", myFilter.getArea().getId())); } queryFilter.addOrder(Order.asc("areaString")); queryFilter.addOrder(Order.asc("name")); final List<UserPrefDO> list = getList(queryFilter); return list; } public UserPrefDO getUserPref(final UserPrefArea area, final String name) { final PFUserDO user = PFUserContext.getUser(); @SuppressWarnings("unchecked") final List<UserPrefDO> list = getHibernateTemplate().find("from UserPrefDO u where u.user.id = ? and u.areaString = ? and u.name = ?", new Object[] { user.getId(), area.getId(), name}); if (list == null || list.size() != 1) { return null; } return list.get(0); } public List<UserPrefDO> getUserPrefs(final UserPrefArea area) { final PFUserDO user = PFUserContext.getUser(); @SuppressWarnings("unchecked") final List<UserPrefDO> list = getHibernateTemplate().find("from UserPrefDO u where u.user.id = ? and u.areaString = ?", new Object[] { user.getId(), area.getId()}); return selectUnique(list); } /** * Adds the object fields as parameters to the given userPref. Fields without the annotation UserPrefParameter will be ignored. * @param userPref * @param obj * @see #fillFromUserPrefParameters(UserPrefDO, Object) */ public void addUserPrefParameters(final UserPrefDO userPref, final Object obj) { addUserPrefParameters(userPref, obj.getClass(), obj); } /** * Adds the fields of the bean type represented by the given area as parameters to the given userPref. Fields without the annotation * UserPrefParameter will be ignored. * @param userPref * @param area * @see #fillFromUserPrefParameters(UserPrefDO, Object) */ public void addUserPrefParameters(final UserPrefDO userPref, final UserPrefArea area) { addUserPrefParameters(userPref, area.getBeanType(), null); } private void addUserPrefParameters(final UserPrefDO userPref, final Class< ? > beanType, final Object obj) { Validate.notNull(userPref); Validate.notNull(beanType); final Field[] fields = beanType.getDeclaredFields(); AccessibleObject.setAccessible(fields, true); int no = 0; for (final Field field : fields) { if (field.isAnnotationPresent(UserPrefParameter.class) == true) { final UserPrefEntryDO userPrefEntry = new UserPrefEntryDO(); userPrefEntry.setParameter(field.getName()); if (obj != null) { Object value = null; try { value = field.get(obj); userPrefEntry.setValue(convertParameterValueToString(value)); } catch (final IllegalAccessException ex) { log.error(ex.getMessage(), ex); } userPrefEntry.valueAsObject = value; } evaluateAnnotation(userPrefEntry, beanType, field); if (userPrefEntry.orderString == null) { userPrefEntry.orderString = "ZZZ" + StringHelper.format2DigitNumber(no++); } userPref.addUserPrefEntry(userPrefEntry); } } } private void evaluateAnnotations(final UserPrefDO userPref, final Class< ? > beanType) { if (userPref.getUserPrefEntries() == null) { return; } final Field[] fields = beanType.getDeclaredFields(); int no = 0; for (final Field field : fields) { if (field.isAnnotationPresent(UserPrefParameter.class) == true) { UserPrefEntryDO userPrefEntry = null; for (final UserPrefEntryDO entry : userPref.getUserPrefEntries()) { if (field.getName().equals(entry.getParameter()) == true) { userPrefEntry = entry; break; } } if (userPrefEntry == null) { userPrefEntry = new UserPrefEntryDO(); evaluateAnnotation(userPrefEntry, beanType, field); userPref.addUserPrefEntry(userPrefEntry); } else { evaluateAnnotation(userPrefEntry, beanType, field); } if (StringUtils.isBlank(userPrefEntry.orderString) == true) { userPrefEntry.orderString = "ZZZ" + StringHelper.format2DigitNumber(no++); } userPrefEntry.setParameter(field.getName()); } } } private void evaluateAnnotation(final UserPrefEntryDO userPrefEntry, final Class< ? > beanType, final Field field) { final UserPrefParameter ann = field.getAnnotation(UserPrefParameter.class); userPrefEntry.i18nKey = ann.i18nKey(); userPrefEntry.tooltipI18nKey = ann.tooltipI18nKey(); userPrefEntry.dependsOn = StringUtils.isNotBlank(ann.dependsOn()) ? ann.dependsOn() : null; userPrefEntry.required = ann.required(); userPrefEntry.multiline = ann.multiline(); userPrefEntry.orderString = StringUtils.isNotBlank(ann.orderString()) ? ann.orderString() : null; if (String.class.isAssignableFrom(field.getType()) == true) { userPrefEntry.maxLength = HibernateUtils.getPropertyLength(beanType, field.getName()); } userPrefEntry.type = field.getType(); } /** * Fill object fields from the parameters of the given userPref. * @param userPref * @param obj * @see #addUserPrefParameters(UserPrefDO, Object) */ public void fillFromUserPrefParameters(final UserPrefDO userPref, final Object obj) { fillFromUserPrefParameters(userPref, obj, false); } /** * Fill object fields from the parameters of the given userPref. * @param userPref * @param obj * @param preserveExistingValues If true then existing value will not be overwritten by the user pref object. Default is false. * @see #addUserPrefParameters(UserPrefDO, Object) */ public void fillFromUserPrefParameters(final UserPrefDO userPref, final Object obj, final boolean preserveExistingValues) { Validate.notNull(userPref); Validate.notNull(obj); final Field[] fields = obj.getClass().getDeclaredFields(); AccessibleObject.setAccessible(fields, true); if (userPref.getUserPrefEntries() != null) { for (final UserPrefEntryDO entry : userPref.getUserPrefEntries()) { Field field = null; for (final Field f : fields) { if (f.getName().equals(entry.getParameter()) == true) { field = f; break; } } if (field == null) { log.error("Declared field '" + entry.getParameter() + "' not found for " + obj.getClass() + ". Ignoring parameter."); } else { final Object value = getParameterValue(field.getType(), entry.getValue()); try { if (preserveExistingValues == true) { final Object oldValue = field.get(obj); if (oldValue != null) { if (oldValue instanceof String) { if (((String) oldValue).length() > 0) { // Preserve existing value: continue; } } else { // Preserve existing value: continue; } } } field.set(obj, value); } catch (final IllegalArgumentException ex) { log.error(ex.getMessage() + " While setting declared field '" + entry.getParameter() + "' of " + obj.getClass() + ". Ignoring parameter.", ex); } catch (final IllegalAccessException ex) { log.error(ex.getMessage() + " While setting declared field '" + entry.getParameter() + "' of " + obj.getClass() + ". Ignoring parameter.", ex); } } } } } public void setValueObject(final UserPrefEntryDO userPrefEntry, final Object value) { userPrefEntry.setValue(convertParameterValueToString(value)); updateParameterValueObject(userPrefEntry); } /** * @param value * @return * @see #getParameterValue(String) */ public String convertParameterValueToString(final Object value) { if (value == null) { return null; } if (value instanceof BaseDO< ? >) { return String.valueOf(((BaseDO< ? >) value).getId()); } return String.valueOf(value); } /** * Sets the value object by converting it from the value string. The type of the userPrefEntry must be given. * @param userPrefEntry */ public void updateParameterValueObject(final UserPrefEntryDO userPrefEntry) { userPrefEntry.valueAsObject = getParameterValue(userPrefEntry.getType(), userPrefEntry.getValue()); } /** * @param value * @return * @see #convertParameterValueToString(Object) */ @SuppressWarnings("unchecked") public Object getParameterValue(final Class< ? > type, final String str) { if (str == null) { return null; } if (type.isAssignableFrom(String.class) == true) { return str; } else if (type.isAssignableFrom(Integer.class) == true) { return Integer.valueOf(str); } else if (DefaultBaseDO.class.isAssignableFrom(type) == true) { final Integer id = NumberHelper.parseInteger(str); if (id != null) { if (PFUserDO.class.isAssignableFrom(type) == true) { return userDao.getOrLoad(id); } else if (TaskDO.class.isAssignableFrom(type) == true) { return taskDao.getOrLoad(id); } else if (Kost2DO.class.isAssignableFrom(type) == true) { return kost2Dao.getOrLoad(id); } else if (ProjektDO.class.isAssignableFrom(type) == true) { return projektDao.getOrLoad(id); } else { log.warn("getParameterValue: Type '" + type + "' not supported. May-be it does not work."); return getHibernateTemplate().load(type, id); } } else { return null; } } else if (KundeDO.class.isAssignableFrom(type) == true) { final Integer id = NumberHelper.parseInteger(str); if (id != null) { return kundeDao.getOrLoad(id); } else { return null; } } else if (type.isEnum() == true) { return Enum.valueOf((Class<Enum>) type, str); } log.error("UserPrefDao does not yet support parameters from type: " + type); return null; } @Override public UserPrefDO internalGetById(final Serializable id) { final UserPrefDO userPref = super.internalGetById(id); if (userPref == null) { return null; } if (userPref.getArea() != null) { evaluateAnnotations(userPref, userPref.getArea().getBeanType()); } return userPref; } /** * @return Always true, no generic select access needed for user pref objects. * @see org.projectforge.core.BaseDao#hasSelectAccess() */ @Override public boolean hasSelectAccess(final PFUserDO user, final boolean throwException) { return true; } /** * @see org.projectforge.core.BaseDao#hasAccess(Object, OperationType) */ @Override public boolean hasAccess(final PFUserDO user, final UserPrefDO obj, final UserPrefDO oldObj, final OperationType operationType, final boolean throwException) { if (accessChecker.userEquals(user, obj.getUser()) == true) { return true; } if (throwException == true) { throw new AccessException("userPref.error.userIsNotOwner"); } else { return false; } } @Override public UserPrefDO newInstance() { return new UserPrefDO(); } public void setKost2Dao(final Kost2Dao kost2Dao) { this.kost2Dao = kost2Dao; } public void setKundeDao(final KundeDao kundeDao) { this.kundeDao = kundeDao; } public void setProjektDao(final ProjektDao projektDao) { this.projektDao = projektDao; } public void setTaskDao(final TaskDao taskDao) { this.taskDao = taskDao; } public void setUserDao(final UserDao userDao) { this.userDao = userDao; } }