/////////////////////////////////////////////////////////////////////////////
//
// 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.plugins.teamcal;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.projectforge.common.StringHelper;
import org.projectforge.continuousdb.UpdateEntry;
import org.projectforge.core.CronSetup;
import org.projectforge.database.xstream.XStreamSavingConverter;
import org.projectforge.plugins.core.AbstractPlugin;
import org.projectforge.plugins.teamcal.admin.TeamCalDO;
import org.projectforge.plugins.teamcal.admin.TeamCalDao;
import org.projectforge.plugins.teamcal.admin.TeamCalEditPage;
import org.projectforge.plugins.teamcal.admin.TeamCalListPage;
import org.projectforge.plugins.teamcal.admin.TeamCalRight;
import org.projectforge.plugins.teamcal.event.TeamEventAttachmentDO;
import org.projectforge.plugins.teamcal.event.TeamEventAttendeeDO;
import org.projectforge.plugins.teamcal.event.TeamEventDO;
import org.projectforge.plugins.teamcal.event.TeamEventDao;
import org.projectforge.plugins.teamcal.event.TeamEventEditPage;
import org.projectforge.plugins.teamcal.event.TeamEventListPage;
import org.projectforge.plugins.teamcal.event.TeamEventRight;
import org.projectforge.plugins.teamcal.externalsubscription.TeamCalSubscriptionJob;
import org.projectforge.plugins.teamcal.externalsubscription.TeamEventExternalSubscriptionCache;
import org.projectforge.plugins.teamcal.integration.TeamCalCalendarFeedHook;
import org.projectforge.plugins.teamcal.integration.TeamCalCalendarFilter;
import org.projectforge.plugins.teamcal.integration.TeamCalCalendarPage;
import org.projectforge.plugins.teamcal.integration.TeamcalTimesheetPluginComponentHook;
import org.projectforge.plugins.teamcal.integration.TemplateCalendarProperties;
import org.projectforge.plugins.teamcal.integration.TemplateEntry;
import org.projectforge.plugins.teamcal.rest.TeamCalDaoRest;
import org.projectforge.plugins.teamcal.rest.TeamEventDaoRest;
import org.projectforge.registry.DaoRegistry;
import org.projectforge.registry.Registry;
import org.projectforge.registry.RegistryEntry;
import org.projectforge.user.GroupDO;
import org.projectforge.user.PFUserDO;
import org.projectforge.user.UserXmlPreferencesDO;
import org.projectforge.web.MenuItemDef;
import org.projectforge.web.MenuItemDefId;
import org.projectforge.web.MenuItemRegistry;
import org.projectforge.web.calendar.CalendarFeed;
import org.projectforge.web.rest.RestCallRegistry;
import org.projectforge.web.timesheet.TimesheetEditPage;
import org.projectforge.web.wicket.WicketApplication;
/**
* @author Kai Reinhard (k.reinhard@micromata.de)
* @author M. Lauterbach (m.lauterbach@micromata.de)
*/
public class TeamCalPlugin extends AbstractPlugin
{
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(TeamCalPlugin.class);
public static final String ID = "teamCal";
public static final String RESOURCE_BUNDLE_NAME = TeamCalPlugin.class.getPackage().getName() + ".TeamCalI18nResources";
// The order of the entities is important for xml dump and imports as well as for test cases (order for deleting objects at the end of
// each test).
// The entities are inserted in ascending order and deleted in descending order.
private static final Class< ? >[] PERSISTENT_ENTITIES = new Class< ? >[] { TeamCalDO.class, TeamEventDO.class, TeamEventAttendeeDO.class,
TeamEventAttachmentDO.class};
/**
* This dao should be defined in pluginContext.xml (as resources) for proper initialization.
*/
private TeamCalDao teamCalDao;
private TeamEventDao teamEventDao;
@Override
public Class< ? >[] getPersistentEntities()
{
return PERSISTENT_ENTITIES;
}
/**
* @see org.projectforge.plugins.core.AbstractPlugin#initialize()
*/
@SuppressWarnings("unchecked")
@Override
protected void initialize()
{
// DatabaseUpdateDao is needed by the updater:
TeamCalPluginUpdates.dao = getDatabaseUpdateDao();
final RegistryEntry entry = new RegistryEntry(ID, TeamCalDao.class, teamCalDao, "plugins.teamcal");
final RegistryEntry eventEntry = new RegistryEntry("teamEvent", TeamEventDao.class, teamEventDao, "plugins.teamcal.event");
eventEntry.setNestedDOClasses(TeamEventAttendeeDO.class, TeamEventAttachmentDO.class);
// The CalendarDao is automatically available by the scripting engine!
register(entry);
register(eventEntry);
// Register the web part:
registerWeb(ID, TeamCalListPage.class, TeamCalEditPage.class);
registerWeb(ID, TeamCalListPage.class, TeamCalEditPage.class, DaoRegistry.ADDRESS, false); // At second position (after Address entry)
// for SearchPage.
registerWeb("teamEvent", TeamEventListPage.class, TeamEventEditPage.class, ID, false); // At position after entry.
addMountPage("teamCalendar", TeamCalCalendarPage.class);
// Register the menu entry as sub menu entry of the misc menu:
final MenuItemDef parentMenu = getMenuItemDef(MenuItemDefId.COMMON);
// registerMenuItem(new MenuItemDef(parentMenu, ID, 7, "plugins.teamcal.menu", TeamCalCalendarPage.class));
registerMenuItem(new MenuItemDef(parentMenu, ID + "List", 11, "plugins.teamcal.title.list", TeamCalListPage.class));
final MenuItemDef menuItemDef = MenuItemRegistry.instance().get(MenuItemDefId.CALENDAR);
menuItemDef.setPageClass(TeamCalCalendarPage.class);
WicketApplication.setDefaultPage(TeamCalCalendarPage.class);
// .setMobileMenu(ToDoMobileListPage.class, 10));
// Define the access management:
registerRight(new TeamCalRight());
registerRight(new TeamEventRight());
// All the i18n stuff:
addResourceBundle(RESOURCE_BUNDLE_NAME);
CalendarFeed.registerFeedHook(new TeamCalCalendarFeedHook());
TimesheetEditPage.addPluginHook(new TeamcalTimesheetPluginComponentHook());
RestCallRegistry.getInstance().register(TeamCalDaoRest.class).register(TeamEventDaoRest.class);
TeamCalSubscriptionJob.setTeamCalDao(teamCalDao);
}
/**
* @param teamCalDao the calendarDao to set
* @return this for chaining.
*/
public void setTeamCalDao(final TeamCalDao teamCalDao)
{
this.teamCalDao = teamCalDao;
}
public void setTeamEventDao(final TeamEventDao teamEventDao)
{
this.teamEventDao = teamEventDao;
}
/**
* @see org.projectforge.plugins.core.AbstractPlugin#getInitializationUpdateEntry()
*/
@Override
public UpdateEntry getInitializationUpdateEntry()
{
return TeamCalPluginUpdates.getInitializationUpdateEntry();
}
/**
* @see org.projectforge.plugins.core.AbstractPlugin#getUpdateEntries()
*/
@Override
public List<UpdateEntry> getUpdateEntries()
{
return TeamCalPluginUpdates.getUpdateEntries();
}
/**
* Migrates the calendar ids of the filter templates and user/group id's of calendar access strings.
* @see org.projectforge.plugins.core.AbstractPlugin#onBeforeRestore(org.projectforge.database.xstream.XStreamSavingConverter,
* java.lang.Object)
*/
@Override
public void onBeforeRestore(final XStreamSavingConverter xstreamSavingConverter, final Object obj)
{
if (obj instanceof UserXmlPreferencesDO) {
final UserXmlPreferencesDO userPrefs = (UserXmlPreferencesDO) obj;
if (TeamCalCalendarPage.USERPREF_KEY.equals(userPrefs.getKey()) == false) {
return;
}
if (userXmlPreferencesDao == null) {
// Only for testcases.
userXmlPreferencesDao = Registry.instance().getUserXmlPreferencesDao();
}
final Object userPrefsObj = userXmlPreferencesDao.deserialize(userPrefs, true);
if (userPrefsObj == null || userPrefsObj instanceof TeamCalCalendarFilter == false) {
return;
}
final TeamCalCalendarFilter filter = (TeamCalCalendarFilter) userPrefsObj;
final List<TemplateEntry> templates = filter.getTemplateEntries();
if (templates == null) {
// Nothing to do.
return;
}
for (final TemplateEntry template : templates) {
final Set<TemplateCalendarProperties> calendarPropertiesSet = template.getCalendarProperties();
if (calendarPropertiesSet != null && calendarPropertiesSet.size() > 0) {
for (final TemplateCalendarProperties props : calendarPropertiesSet) {
final Integer newCalendarId = xstreamSavingConverter.getNewIdAsInteger(TeamCalDO.class, props.getCalId());
if (newCalendarId == null) {
continue;
}
props.setCalId(newCalendarId);
}
}
final Integer calendarId = template.getDefaultCalendarId();
if (calendarId != null) {
template.setDefaultCalendarId(xstreamSavingConverter.getNewIdAsInteger(TeamCalDO.class, calendarId));
}
final Integer timesheetUserId = template.getTimesheetUserId();
if (timesheetUserId != null) {
template.setTimesheetUserId(xstreamSavingConverter.getNewIdAsInteger(PFUserDO.class, timesheetUserId));
}
}
userXmlPreferencesDao.serialize(userPrefs, filter);
return;
} else if (obj instanceof TeamCalDO) {
log.info("Migrating " + obj);
final TeamCalDO cal = (TeamCalDO) obj;
cal.setFullAccessUserIds(updateIds(xstreamSavingConverter, PFUserDO.class, cal.getFullAccessUserIds()));
cal.setReadonlyAccessUserIds(updateIds(xstreamSavingConverter, PFUserDO.class, cal.getReadonlyAccessUserIds()));
cal.setMinimalAccessUserIds(updateIds(xstreamSavingConverter, PFUserDO.class, cal.getMinimalAccessUserIds()));
cal.setFullAccessGroupIds(updateIds(xstreamSavingConverter, GroupDO.class, cal.getFullAccessGroupIds()));
cal.setReadonlyAccessGroupIds(updateIds(xstreamSavingConverter, GroupDO.class, cal.getReadonlyAccessGroupIds()));
cal.setMinimalAccessGroupIds(updateIds(xstreamSavingConverter, GroupDO.class, cal.getMinimalAccessGroupIds()));
}
}
private String updateIds(final XStreamSavingConverter xstreamSavingConverter, final Class< ? > entityClass, final String oldIdsString)
{
if (StringUtils.isBlank(oldIdsString) == true) {
return oldIdsString;
}
final int[] oldIds = StringHelper.splitToInts(oldIdsString, ",", false);
if (oldIds == null || oldIds.length == 0) {
return "";
}
final StringBuffer buf = new StringBuffer();
String delimiter = "";
for (final int oldId : oldIds) {
final Integer newId = xstreamSavingConverter.getNewIdAsInteger(entityClass, oldId);
if (newId == null) {
// Can' be restored :-(
continue;
}
buf.append(delimiter).append(newId);
delimiter = ",";
}
return buf.toString();
}
@Override
public void registerCronJob(final CronSetup cronSetup)
{
cronSetup.registerCronJob("teamCalAboJob", TeamCalSubscriptionJob.class, "0 */5 * * * ?");
// do initial cache installation in a separated thread
final Thread t = new Thread() {
@Override
public void run()
{
TeamEventExternalSubscriptionCache.instance().updateCache(teamCalDao);
}
};
t.start();
}
}