/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/
package org.olat.course.nodes.projectbroker.service;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.olat.basesecurity.ManagerFactory;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.id.Identity;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.coordinate.SyncerCallback;
import org.olat.core.util.event.MultiUserEvent;
import org.olat.course.CourseFactory;
import org.olat.course.ICourse;
import org.olat.course.groupsandrights.CourseGroupManager;
import org.olat.course.nodes.CourseNode;
import org.olat.course.nodes.ProjectBrokerCourseNode;
import org.olat.course.nodes.projectbroker.datamodel.Project;
import org.olat.course.properties.CoursePropertyManager;
import org.olat.group.BusinessGroup;
import org.olat.group.BusinessGroupImpl;
import org.olat.group.BusinessGroupManagerImpl;
import org.olat.group.context.BGContext;
import org.olat.group.context.BGContextManagerImpl;
import org.olat.group.ui.BGConfigFlags;
import org.olat.group.ui.edit.BusinessGroupModifiedEvent;
import org.olat.properties.Property;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryManager;
import org.olat.resource.OLATResource;
import org.olat.resource.OLATResourceManager;
import org.olat.testutils.codepoints.server.Codepoint;
/**
*
* @author guretzki
*/
public class ProjectGroupManagerImpl implements ProjectGroupManager {
private OLog log = Tracing.createLoggerFor(this.getClass());
//////////////////////
// ACCOUNT MANAGEMENT
//////////////////////
public BusinessGroup getAccountManagerGroupFor(CoursePropertyManager cpm, CourseNode courseNode, ICourse course, String groupName, String groupDescription, Identity identity) {
Long groupKey = null;
BusinessGroup accountManagerGroup = null;
Property accountManagerGroupProperty = cpm.findCourseNodeProperty(courseNode, null, null, ProjectBrokerCourseNode.CONF_ACCOUNTMANAGER_GROUP_KEY);
// Check if forum-property exist
if (accountManagerGroupProperty != null) {
groupKey = accountManagerGroupProperty.getLongValue();
log.debug("accountManagerGroupProperty=" + accountManagerGroupProperty + " groupKey=" + groupKey);
}
log.debug("groupKey=" + groupKey);
if (groupKey != null) {
accountManagerGroup = BusinessGroupManagerImpl.getInstance().loadBusinessGroup(groupKey, false);
log.debug("load businessgroup=" + accountManagerGroup);
if (accountManagerGroup != null) {
return accountManagerGroup;
} else {
if (accountManagerGroupProperty != null) {
cpm.deleteProperty(accountManagerGroupProperty);
}
groupKey = null;
log.warn("ProjectBroker: Account-manager does no longer exist, create a new one");
}
}
if (groupKey == null) {
log.debug("No group for project-broker exist => create a new one");
BGContext context = createGroupContext(course);
accountManagerGroup = BusinessGroupManagerImpl.getInstance().createAndPersistBusinessGroup(BusinessGroup.TYPE_LEARNINGROUP, identity, groupName, groupDescription, null, null, false, false, context);
int i = 2;
while (accountManagerGroup == null) {
// group with this name exist already, try another name
accountManagerGroup = BusinessGroupManagerImpl.getInstance().createAndPersistBusinessGroup(BusinessGroup.TYPE_LEARNINGROUP, identity, groupName + " #" + i, groupDescription, null, null, false, false, context);
i++;
}
log.debug("createAndPersistBusinessGroup businessgroup=" + accountManagerGroup);
saveAccountManagerGroupKey(accountManagerGroup.getKey(), cpm, courseNode);
log.debug("created account-manager default businessgroup=" + accountManagerGroup);
}
return accountManagerGroup;
}
public void saveAccountManagerGroupKey(Long accountManagerGroupKey, CoursePropertyManager cpm, CourseNode courseNode) {
Property accountManagerGroupKeyProperty = cpm.createCourseNodePropertyInstance(courseNode, null, null, ProjectBrokerCourseNode.CONF_ACCOUNTMANAGER_GROUP_KEY, null, accountManagerGroupKey, null, null);
cpm.saveProperty(accountManagerGroupKeyProperty);
log.debug("saveAccountManagerGroupKey accountManagerGroupKey=" + accountManagerGroupKey);
}
public boolean isAccountManager(Identity identity, CoursePropertyManager cpm, CourseNode courseNode) {
Property accountManagerGroupProperty = cpm.findCourseNodeProperty(courseNode, null, null, ProjectBrokerCourseNode.CONF_ACCOUNTMANAGER_GROUP_KEY);
if (accountManagerGroupProperty != null) {
Long groupKey = accountManagerGroupProperty.getLongValue();
BusinessGroup accountManagerGroup = BusinessGroupManagerImpl.getInstance().loadBusinessGroup(groupKey, false);
if (accountManagerGroup != null) {
return isAccountManager(identity, accountManagerGroup);
}
}
return false;
}
public void deleteAccountManagerGroup( CoursePropertyManager cpm, CourseNode courseNode) {
log.debug("deleteAccountManagerGroup start...");
Property accountManagerGroupProperty = cpm.findCourseNodeProperty(courseNode, null, null, ProjectBrokerCourseNode.CONF_ACCOUNTMANAGER_GROUP_KEY);
if (accountManagerGroupProperty != null) {
Long groupKey = accountManagerGroupProperty.getLongValue();
if (groupKey != null) {
BusinessGroup accountManagerGroup = BusinessGroupManagerImpl.getInstance().loadBusinessGroup(groupKey, false);
if (accountManagerGroup != null) {
BusinessGroupManagerImpl.getInstance().deleteBusinessGroup(accountManagerGroup);
log.audit("ProjectBroker: Deleted accountManagerGroup=" + accountManagerGroup);
} else {
log.debug("deleteAccountManagerGroup: accountManagerGroup=" + accountManagerGroup + " has already been deleted");
}
}
cpm.deleteProperty(accountManagerGroupProperty);
log.debug("deleteAccountManagerGroup: deleted accountManagerGroupProperty=" + accountManagerGroupProperty );
} else {
log.debug("deleteAccountManagerGroup: found no accountManagerGroup-key");
}
}
public void updateAccountManagerGroupName(String groupName, String groupDescription, BusinessGroup accountManagerGroup) {
BusinessGroup reloadedBusinessGroup = (BusinessGroup)DBFactory.getInstance().loadObject(BusinessGroupImpl.class, accountManagerGroup.getKey());
reloadedBusinessGroup.setName(groupName);
reloadedBusinessGroup.setDescription(groupDescription);
BusinessGroupManagerImpl.getInstance().updateBusinessGroup(reloadedBusinessGroup);
}
////////////////////////////
// PROJECT GROUP MANAGEMENT
////////////////////////////
public BusinessGroup createProjectGroupFor(Long projectBrokerId, Identity identity, String groupName, String groupDescription, Long courseId) {
List<Project> projects = ProjectBrokerManagerFactory.getProjectBrokerManager().getProjectListBy(projectBrokerId);
BGContext context = createGroupContext(CourseFactory.loadCourse(courseId));
// TODO: groupNbr no longer used => remove for 6.4
int groupNbr = projects.size() + 1;
log.debug("createProjectGroupFor groupName=" + groupName);
BusinessGroup projectGroup = BusinessGroupManagerImpl.getInstance().createAndPersistBusinessGroup(BusinessGroup.TYPE_LEARNINGROUP, identity, groupName, groupDescription, null, null, false, false, context);
// projectGroup could be null when a group with name already exists
int counter = 2;
while (projectGroup == null) {
// name alreday exist try another one
String newGroupName = groupName + " #" + counter ;
projectGroup = BusinessGroupManagerImpl.getInstance().createAndPersistBusinessGroup(BusinessGroup.TYPE_LEARNINGROUP, identity, newGroupName, groupDescription, null, null, false, false, context);
counter++;
}
log.debug("Created a new projectGroup=" + projectGroup);
return projectGroup;
}
public void deleteProjectGroupFor(Project project) {
BusinessGroupManagerImpl.getInstance().deleteBusinessGroup(project.getProjectGroup());
}
public void updateProjectGroupFor(Project project) {
BusinessGroupManagerImpl.getInstance().updateBusinessGroup(project.getProjectGroup());
}
public List<Identity> addCandidates(final List<Identity> addIdentities, final Project project) {
Codepoint.codepoint(ProjectBrokerManagerImpl.class, "beforeDoInSync");
List<Identity> addedIdentities = CoordinatorManager.getCoordinator().getSyncer().doInSync(project.getProjectGroup(), new SyncerCallback<List<Identity>>(){
public List<Identity> execute() {
List<Identity> addedIdentities = new ArrayList<Identity>();
for (Identity identity : addIdentities) {
if (!ManagerFactory.getManager().isIdentityInSecurityGroup(identity, project.getCandidateGroup()) ) {
ManagerFactory.getManager().addIdentityToSecurityGroup(identity, project.getCandidateGroup());
addedIdentities.add(identity);
log.audit("ProjectBroker: Add user as candidate, identity=" + identity);
}
// fireEvents ?
}
return addedIdentities;
}
});// end of doInSync
Codepoint.codepoint(ProjectBrokerManagerImpl.class, "afterDoInSync");
return addedIdentities;
}
public void removeCandidates(final List<Identity> addIdentities, final Project project) {
Codepoint.codepoint(ProjectBrokerManagerImpl.class, "beforeDoInSync");
Boolean result = CoordinatorManager.getCoordinator().getSyncer().doInSync(project.getProjectGroup(), new SyncerCallback<Boolean>(){
public Boolean execute() {
for (Identity identity : addIdentities) {
ManagerFactory.getManager().removeIdentityFromSecurityGroup(identity, project.getCandidateGroup());
log.audit("ProjectBroker: Remove user as candidate, identity=" + identity);
// fireEvents ?
}
return Boolean.TRUE;
}
});// end of doInSync
Codepoint.codepoint(ProjectBrokerManagerImpl.class, "afterDoInSync");
}
public boolean acceptCandidates(final List<Identity> identities, final Project project, final Identity actionIdentity, final boolean autoSignOut, final boolean isAcceptSelectionManually) {
Codepoint.codepoint(ProjectBrokerManagerImpl.class, "beforeDoInSync");
Boolean result = CoordinatorManager.getCoordinator().getSyncer().doInSync(project.getProjectGroup(), new SyncerCallback<Boolean>(){
public Boolean execute() {
for (Identity identity : identities ) {
ManagerFactory.getManager().removeIdentityFromSecurityGroup(identity, project.getCandidateGroup());
BGConfigFlags flags = BGConfigFlags.createRightGroupDefaultFlags();
BusinessGroupManagerImpl.getInstance().addParticipantAndFireEvent(actionIdentity, identity, project.getProjectGroup(), flags, false);
log.audit("ProjectBroker: Accept candidate, identity=" + identity);
// fireEvents ?
}
return Boolean.TRUE;
}
});// end of doInSync
if (autoSignOut && result.booleanValue()) {
ProjectBrokerManagerFactory.getProjectBrokerManager().signOutFormAllCandidateList(identities, project.getProjectBroker().getKey());
}
if (isAcceptSelectionManually && (project.getMaxMembers() != Project.MAX_MEMBERS_UNLIMITED)
&& project.getSelectedPlaces() >= project.getMaxMembers()) {
ProjectBrokerManagerFactory.getProjectBrokerManager().setProjectState(project, Project.STATE_ASSIGNED);
log.info("ProjectBroker: Accept candidate, change project-state=" + Project.STATE_ASSIGNED);
}
Codepoint.codepoint(ProjectBrokerManagerImpl.class, "afterDoInSync");
return result.booleanValue();
}
@Override
public void sendGroupChangeEvent(Project project, Long courseResourceableId, Identity identity) {
ICourse course = CourseFactory.loadCourse(courseResourceableId);
RepositoryEntry ores = RepositoryManager.getInstance().lookupRepositoryEntry(course, true);
MultiUserEvent modifiedEvent = new BusinessGroupModifiedEvent(BusinessGroupModifiedEvent.IDENTITY_ADDED_EVENT, project.getProjectGroup(), identity);
CoordinatorManager.getCoordinator().getEventBus().fireEventToListenersOf(modifiedEvent, ores);
}
///////////////////
// PRIVATE METHODS
///////////////////
private BGContext createGroupContext(ICourse course) {
List<BGContext> groupContexts = course.getCourseEnvironment().getCourseGroupManager().getLearningGroupContexts();
log.debug("createGroupContext groupContexts.size=" + groupContexts.size());
for (Iterator<BGContext> iterator = groupContexts.iterator(); iterator.hasNext();) {
BGContext iterContext = iterator.next();
log.debug("createGroupContext loop iterContext=" + iterContext);
if (iterContext.isDefaultContext()) {
log.debug("createGroupContext default groupContexts=" + iterContext);
return iterContext;
}
}
// found no default context
String defaultContextName = CourseGroupManager.DEFAULT_NAME_LC_PREFIX + course.getCourseTitle();
if (groupContexts.size() == 0) {
log.debug("no group context exists, create a new default defaultContextName=" + defaultContextName);
} else {
log.debug("Found no default group context, create a new default defaultContextName=" + defaultContextName);
}
// no context exists => create a new default context
OLATResource courseResource = OLATResourceManager.getInstance().findOrPersistResourceable(course);
BGContext context = BGContextManagerImpl.getInstance().createAndAddBGContextToResource(defaultContextName, courseResource, BusinessGroup.TYPE_LEARNINGROUP, null, true);
return context;
}
private boolean isAccountManager(Identity identity, BusinessGroup businessGroup) {
if ( (businessGroup == null) || (businessGroup.getPartipiciantGroup() == null) ) {
return false;
}
return ManagerFactory.getManager().isIdentityInSecurityGroup(identity, businessGroup.getPartipiciantGroup())
|| ManagerFactory.getManager().isIdentityInSecurityGroup(identity, businessGroup.getOwnerGroup());
}
}