/**
* Copyright (c) 2008-2012 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.sakaiproject.profile2.logic;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.Setter;
import org.apache.log4j.Logger;
import org.sakaiproject.profile2.model.Person;
import org.sakaiproject.profile2.util.Messages;
import org.sakaiproject.profile2.util.ProfileConstants;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SitePage;
import org.sakaiproject.site.api.ToolConfiguration;
import org.sakaiproject.tool.api.Tool;
import org.sakaiproject.user.api.User;
import org.springframework.util.CollectionUtils;
/**
* Implementation of ProfileWorksiteLogic API
*
* @author d.b.robinson@lancaster.ac.uk
*/
public class ProfileWorksiteLogicImpl implements ProfileWorksiteLogic {
private static final Logger log = Logger.getLogger(ProfileWorksiteLogicImpl.class);
/**
* Profile2 creates <code>project</code> type worksites.
*/
private static final String SITE_TYPE_PROJECT = "project";
/**
* Connections invited to worksites are initially given the
* <code>access</code> role.
*/
private static final String ROLE_ACCESS = "access";
/**
* Users who create worksites are initially given the <code>maintain</code>
* role.
*/
private static final String ROLE_MAINTAIN = "maintain";
/**
* The id of the worksite home page.
*/
private static final String TOOL_ID_HOME = "home";
/**
* The id of the iframe tool.
*/
private static final String TOOL_ID_IFRAME = "sakai.iframe";
/**
* The id of the synoptic calendar tool.
*/
private static final String TOOL_ID_SUMMARY_CALENDAR = "sakai.summary.calendar";
/**
* The id of the synoptic announcements tool.
*/
private static final String TOOL_ID_SYNOPTIC_ANNOUNCEMENT = "sakai.synoptic.announcement";
/**
* The id of the synoptic chat tool.
*/
private static final String TOOL_ID_SYNOPTIC_CHAT = "sakai.synoptic.chat";
/**
* The id of the synoptic discussions tool.
*/
private static final String TOOL_ID_SYNOPTIC_DISCUSSION = "sakai.synoptic.discussion";
/**
* The id of the synoptic message center tool.
*/
private static final String TOOL_ID_SYNOPTIC_MESSAGECENTER = "sakai.synoptic.messagecenter";
/**
* Map of synoptic tool and the related tool ids.
*/
private final static Map<String, List<String>> SYNOPTIC_TOOL_ID_MAP;
static
{
SYNOPTIC_TOOL_ID_MAP = new HashMap<String, List<String>>();
SYNOPTIC_TOOL_ID_MAP.put(TOOL_ID_SUMMARY_CALENDAR, new ArrayList<String>(Arrays.asList("sakai.schedule")));
SYNOPTIC_TOOL_ID_MAP.put(TOOL_ID_SYNOPTIC_ANNOUNCEMENT, new ArrayList<String>(Arrays.asList("sakai.announcements")));
SYNOPTIC_TOOL_ID_MAP.put(TOOL_ID_SYNOPTIC_CHAT, new ArrayList<String>(Arrays.asList("sakai.chat")));
SYNOPTIC_TOOL_ID_MAP.put(TOOL_ID_SYNOPTIC_DISCUSSION, new ArrayList<String>(Arrays.asList("sakai.discussion")));
SYNOPTIC_TOOL_ID_MAP.put(TOOL_ID_SYNOPTIC_MESSAGECENTER, new ArrayList<String>(Arrays.asList("sakai.messages", "sakai.forums", "sakai.messagecenter")));
}
/**
* Map of tools and the related synoptic tool ids.
*/
private final static Map<String, String> TOOLS_WITH_SYNOPTIC_ID_MAP;
static
{
TOOLS_WITH_SYNOPTIC_ID_MAP = new HashMap<String, String>();
TOOLS_WITH_SYNOPTIC_ID_MAP.put("sakai.schedule", TOOL_ID_SUMMARY_CALENDAR);
TOOLS_WITH_SYNOPTIC_ID_MAP.put("sakai.announcements", TOOL_ID_SYNOPTIC_ANNOUNCEMENT);
TOOLS_WITH_SYNOPTIC_ID_MAP.put("sakai.chat", TOOL_ID_SYNOPTIC_CHAT);
TOOLS_WITH_SYNOPTIC_ID_MAP.put("sakai.discussion", TOOL_ID_SYNOPTIC_DISCUSSION);
TOOLS_WITH_SYNOPTIC_ID_MAP.put("sakai.messages", TOOL_ID_SYNOPTIC_MESSAGECENTER);
TOOLS_WITH_SYNOPTIC_ID_MAP.put("sakai.forums", TOOL_ID_SYNOPTIC_MESSAGECENTER);
TOOLS_WITH_SYNOPTIC_ID_MAP.put("sakai.messagecenter", TOOL_ID_SYNOPTIC_MESSAGECENTER);
}
/**
* The tool to place on the home page.
*/
private static final String HOME_TOOL = "sakai.iframe.site";
/**
* The tool used to modify the worksite after creation.
*/
private static final String SITEINFO_TOOL = "sakai.siteinfo";
/**
* The tool used to unjoin worksites.
*/
private static final String MEMBERSHIP_TOOL = "sakai.membership";
/**
* Worksite setup tools.
*/
private static final String WORKSITE_SETUP_TOOLS = "wsetup.home.toolids";
/**
* {@inheritDoc}
*/
public boolean createWorksite(final String siteTitle, final String ownerId,
final Collection<Person> members, boolean notifyByEmail) {
// double-check permission
if (false == sakaiProxy.isUserAllowedAddSite(ownerId)) {
log .warn("user " + ownerId + " tried to create worksite without site.add");
return false;
}
// ensure site id is unique
String siteId = sakaiProxy.createUuid();
while (true == sakaiProxy.checkForSite(siteId)) {
siteId = sakaiProxy.createUuid();
}
final Site site = sakaiProxy.addSite(siteId, SITE_TYPE_PROJECT);
if (null == site) {
log.warn("unable to create new worksite from Profile2");
return false;
} else {
// set initial site maintainer to Profile2 user creating worksite
User owner = sakaiProxy.getUserById(ownerId);
if (null != owner) {
// false == provided
site.addMember(ownerId, site.getMaintainRole(), true, false);
} else {
log.warn("unknown user " + ownerId + " tried to create worksite");
return false;
}
addSiteMembers(members, site);
addTitleAndDescription(siteTitle, ownerId, site);
addHomePageAndTools(site);
site.setPublished(true);
if (false == sakaiProxy.saveSite(site)) {
log.warn("unable to save new worksite from Profile2");
return false;
}
emailSiteMembers(siteTitle, ownerId, members, notifyByEmail, site);
return true;
}
}
private void addHomePageAndTools(final Site site) {
// we will always have a home page
SitePage homePage = site.addPage();
homePage.getPropertiesEdit().addProperty(
SitePage.IS_HOME_PAGE, Boolean.TRUE.toString());
Tool homeTool = sakaiProxy.getTool(HOME_TOOL);
ToolConfiguration homeToolConfig = homePage.addTool();
homeToolConfig.setTool(TOOL_ID_HOME, homeTool);
homeToolConfig.setTitle(homeTool.getTitle());
// normally brings in sakai.siteinfo
List<String> toolIds = sakaiProxy.getToolsRequired(SITE_TYPE_PROJECT);
int synopticToolIndex = addRequiredToolsForWorksite(site, homePage, toolIds);
// for synoptic tools
if (synopticToolIndex > 0) {
homePage.setLayout(SitePage.LAYOUT_DOUBLE_COL);
}
addRequiredHomeTools(homePage, toolIds, synopticToolIndex);
}
private int addRequiredToolsForWorksite(final Site site,
SitePage homePage, List<String> toolIds) {
int synopticToolIndex = 0;
for (String toolId : toolIds) {
if (isToolToIgnore(toolId)) {
continue;
} else if (isToolWithSynopticTool(toolId)) {
// add tool
SitePage toolPage = site.addPage();
toolPage.addTool(toolId);
// add corresponding synoptic tool if not already added
if (false == isToolAlreadyAdded(homePage, TOOLS_WITH_SYNOPTIC_ID_MAP.get(toolId))) {
ToolConfiguration toolConfig = homePage.addTool(TOOLS_WITH_SYNOPTIC_ID_MAP.get(toolId));
if (null != toolConfig) {
toolConfig.setLayoutHints(synopticToolIndex + ",1");
for (int i = 0; i < synopticToolIndex; i++) {
toolConfig.moveUp();
}
synopticToolIndex++;
}
}
} else if (null != sakaiProxy.getTool(toolId)) {
SitePage toolPage = site.addPage();
toolPage.addTool(toolId);
}
}
return synopticToolIndex;
}
private void addRequiredHomeTools(SitePage homePage, List<String> toolIds,
int synopticToolIndex) {
// home tools specified in sakai.properties or default set of home tools
List<String> homeToolIds = getHomeToolIds();
for (String homeToolId : homeToolIds) {
if (isToolToIgnore(homeToolId)) {
continue;
} else {
// check for corresponding tool
if (SYNOPTIC_TOOL_ID_MAP.get(homeToolId) != null &&
CollectionUtils.containsAny(SYNOPTIC_TOOL_ID_MAP.get(homeToolId), toolIds)) {
// check it hasn't been added already
if (false == isToolAlreadyAdded(homePage, homeToolId)) {
ToolConfiguration toolConfig = homePage.addTool(homeToolId);
if (null != toolConfig) {
toolConfig.setLayoutHints(synopticToolIndex + ",1");
for (int i = 0; i < synopticToolIndex; i++) {
toolConfig.moveUp();
}
synopticToolIndex++;
}
}
}
}
}
}
private List<String> getHomeToolIds() {
List<String> homeToolIds;
if (null != sakaiProxy.getServerConfigurationParameter(WORKSITE_SETUP_TOOLS + "." + SITE_TYPE_PROJECT, null)) {
homeToolIds = new ArrayList<String>(Arrays.asList(
sakaiProxy.getServerConfigurationParameter(WORKSITE_SETUP_TOOLS + "." + SITE_TYPE_PROJECT, null)));
} else if (null != sakaiProxy.getServerConfigurationParameter(WORKSITE_SETUP_TOOLS, null)) {
homeToolIds = new ArrayList<String>(Arrays.asList(
sakaiProxy.getServerConfigurationParameter(WORKSITE_SETUP_TOOLS, null)));
} else {
homeToolIds = new ArrayList<String>();
}
return homeToolIds;
}
private void addTitleAndDescription(final String siteTitle,
final String ownerId, final Site site) {
// finishing setting up site
site.setTitle(siteTitle);
// add description for editing the worksite
site.setDescription(Messages.getString("worksite.help",
new Object[] { sakaiProxy.getTool(SITEINFO_TOOL).getTitle(),
sakaiProxy.getTool(MEMBERSHIP_TOOL).getTitle(),
sakaiProxy.getUserDisplayName(ownerId),
sakaiProxy.getUserEmail(ownerId),
siteTitle}));
}
private void addSiteMembers(final Collection<Person> members,
final Site site) {
// user could create worksite without any connections (that's okay)
if (null != members) {
for (Person member : members) {
User user = sakaiProxy.getUserById(member.getUuid());
if (null != user) {
// false == provided
site.addMember(member.getUuid(), ROLE_ACCESS, true, false);
} else {
log .warn("attempt to add unknown user " + member.getUuid() + " to worksite");
}
}
}
}
private boolean isToolAlreadyAdded(SitePage homePage, String homeToolId) {
for (ToolConfiguration tool : homePage.getTools()) {
if (tool.getToolId().equals(homeToolId)) {
return true;
}
}
return false;
}
private boolean isToolWithSynopticTool(String toolId) {
return TOOLS_WITH_SYNOPTIC_ID_MAP.containsKey(toolId);
}
private boolean isToolToIgnore(String toolId) {
return toolId.equals(TOOL_ID_IFRAME) || toolId.equals(HOME_TOOL);
}
private void emailSiteMembers(final String siteTitle, final String ownerId,
final Collection<Person> members, boolean notifyByEmail,
final Site site) {
if (true == notifyByEmail) {
Thread thread = new Thread() {
public void run() {
emailSiteMembers(siteTitle, site.getUrl(), ownerId, members);
}
};
thread.start();
}
}
private void emailSiteMembers(String siteTitle, String siteUrl, String ownerId,
Collection<Person> members) {
for (Person member : members) {
if (true == member.getPreferences().isWorksiteNewEmailEnabled()) {
emailSiteMember(siteTitle, siteUrl, ownerId, member);
}
}
}
private void emailSiteMember(String siteTitle, String siteUrl, String ownerId, Person member) {
// create the map of replacement values for this email template
Map<String, String> replacementValues = new HashMap<String, String>();
replacementValues.put("senderDisplayName", sakaiProxy.getUserDisplayName(ownerId));
replacementValues.put("worksiteTitle", siteTitle);
replacementValues.put("worksiteLink", siteUrl);
replacementValues.put("localSakaiName", sakaiProxy.getServiceName());
replacementValues.put("localSakaiUrl", sakaiProxy.getPortalUrl());
replacementValues.put("toolName", sakaiProxy.getCurrentToolTitle());
sakaiProxy.sendEmail(member.getUuid(),
ProfileConstants.EMAIL_TEMPLATE_KEY_WORKSITE_NEW, replacementValues);
}
@Setter
private SakaiProxy sakaiProxy;
}