/**
* 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.
* <hr>
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* This file has been modified by the OpenOLAT community. Changes are licensed
* under the Apache 2.0 license as the original file.
* <p>
*/
package org.olat.course.nodes.en;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.olat.basesecurity.BaseSecurity;
import org.olat.basesecurity.GroupRoles;
import org.olat.core.commons.persistence.DB;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.control.WindowBackOffice;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.closablewrapper.CalloutSettings;
import org.olat.core.gui.control.generic.dtabs.DTabs;
import org.olat.core.gui.control.info.WindowControlInfo;
import org.olat.core.gui.translator.Translator;
import org.olat.core.id.Identity;
import org.olat.core.id.IdentityEnvironment;
import org.olat.core.id.Roles;
import org.olat.core.id.context.BusinessControl;
import org.olat.core.id.context.ContextEntry;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.logging.activity.OlatResourceableType;
import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
import org.olat.core.logging.activity.ThreadLocalUserActivityLoggerInstaller;
import org.olat.core.util.SessionInfo;
import org.olat.core.util.UserSession;
import org.olat.core.util.Util;
import org.olat.course.CourseFactory;
import org.olat.course.CourseModule;
import org.olat.course.groupsandrights.CourseGroupManager;
import org.olat.course.nodes.ENCourseNode;
import org.olat.course.properties.CoursePropertyManager;
import org.olat.course.run.environment.CourseEnvironment;
import org.olat.course.run.userview.UserCourseEnvironment;
import org.olat.course.run.userview.UserCourseEnvironmentImpl;
import org.olat.group.BusinessGroup;
import org.olat.group.BusinessGroupService;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryService;
import org.olat.resource.OLATResource;
import org.olat.resource.OLATResourceManager;
import org.olat.test.JunitTestHelper;
import org.olat.test.OlatTestCase;
import org.olat.util.logging.activity.LoggingResourceable;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Description: <BR/>
* Test the enrollment
* <P/> Initial Date: Jul 28, 2004
*
* @author patrick
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
public class EnrollmentManagerConcurrentTest extends OlatTestCase implements WindowControl {
//
private static OLog log = Tracing.createLoggerFor(EnrollmentManagerConcurrentTest.class);
/*
* ::Test Setup::
*/
private static Identity id1;
// For WaitingGroup tests
private static Identity wg1, wg2,wg3;
private static Roles wg1Roles, wg2Roles, wg3Roles;
// For WaitingGroup tests
private static Translator testTranslator = null;
private static BusinessGroup bgWithWaitingList = null;
@Autowired
private RepositoryService repositoryService;
@Autowired
private OLATResourceManager resourceManager;
@Autowired
private BusinessGroupService businessGroupService;
@Autowired
private EnrollmentManager enrollmentManager;
@Autowired
private BaseSecurity securityManager;
@Autowired
private DB dbInstance;
/**
* @see junit.framework.TestCase#setUp()
*/
@Before public void setup() throws Exception {
// Identities
id1 = JunitTestHelper.createAndPersistIdentityAsUser("id1");
DBFactory.getInstance().closeSession();
// create business-group with waiting-list
String bgWithWaitingListName = "Group with WaitingList";
String bgWithWaitingListDesc = "some short description for Group with WaitingList";
Boolean enableWaitinglist = new Boolean(true);
Boolean enableAutoCloseRanks = new Boolean(true);
RepositoryEntry resource = JunitTestHelper.createAndPersistRepositoryEntry();
log.info("testAddToWaitingListAndFireEvent: resource=" + resource);
bgWithWaitingList = businessGroupService.createBusinessGroup(id1, bgWithWaitingListName,
bgWithWaitingListDesc, -1, -1, enableWaitinglist, enableAutoCloseRanks, resource);
bgWithWaitingList.setMaxParticipants(new Integer(2));
log.info("TEST bgWithWaitingList=" + bgWithWaitingList);
log.info("TEST bgWithWaitingList.getMaxParticipants()=" + bgWithWaitingList.getMaxParticipants() );
log.info("TEST bgWithWaitingList.getWaitingListEnabled()=" + bgWithWaitingList.getWaitingListEnabled() );
// create mock objects
testTranslator = Util.createPackageTranslator(EnrollmentManagerConcurrentTest.class, new Locale("de"));
// Identities
wg1 = JunitTestHelper.createAndPersistIdentityAsUser("wg1");
wg1Roles = securityManager.getRoles(wg1);
wg2 = JunitTestHelper.createAndPersistIdentityAsUser("wg2");
wg2Roles = securityManager.getRoles(wg2);
wg3 = JunitTestHelper.createAndPersistIdentityAsUser("wg3");
wg3Roles = securityManager.getRoles(wg3);
DBFactory.getInstance().closeSession();
}
// Test for WaitingList
///////////////////////
/**
* Enroll 3 identities (group with max-size=2 and waiting-list).
* Cancel enrollment. Check size after each step.
*/
@Test
public void testEnroll() throws Exception {
log.info("testEnroll: start...");
ENCourseNode enNode = new ENCourseNode();
OLATResource resource = resourceManager.createOLATResourceInstance(CourseModule.class);
RepositoryEntry addedEntry = repositoryService.create("Ayanami", "-", "Enrollment test course 1", "A JUnit course", resource);
CourseEnvironment cenv = CourseFactory.createCourse(addedEntry, "Test", "Test", "learningObjectives").getCourseEnvironment();
// 1. enroll wg1 user
IdentityEnvironment ienv = new IdentityEnvironment();
ienv.setIdentity(wg1);
UserCourseEnvironment userCourseEnv = new UserCourseEnvironmentImpl(ienv, cenv);
CoursePropertyManager coursePropertyManager = userCourseEnv.getCourseEnvironment().getCoursePropertyManager();
log.info("enrollmentManager=" + enrollmentManager);
log.info("bgWithWaitingList=" + bgWithWaitingList);
assertTrue("bgWithWaitingList is null",bgWithWaitingList != null);
log.info("userCourseEnv=" + userCourseEnv);
log.info("userCourseEnv.getCourseEnvironment()=" + userCourseEnv.getCourseEnvironment());
enrollmentManager.doEnroll(wg1, wg1Roles, bgWithWaitingList, enNode, coursePropertyManager,this /*WindowControl mock*/,testTranslator,
new ArrayList<Long>()/*enrollableGroupNames*/, new ArrayList<Long>()/*enrollableAreaNames*/, userCourseEnv.getCourseEnvironment().getCourseGroupManager());
assertTrue("Enrollment failed, user='wg1'", businessGroupService.isIdentityInBusinessGroup(wg1,bgWithWaitingList));
int participantsCounter = businessGroupService.countMembers(bgWithWaitingList, GroupRoles.participant.name());
assertTrue("Wrong number of participants," + participantsCounter , participantsCounter == 1);
// 2. enroll wg2 user
ienv = new IdentityEnvironment();
ienv.setIdentity(wg2);
userCourseEnv = new UserCourseEnvironmentImpl(ienv, cenv);
coursePropertyManager = userCourseEnv.getCourseEnvironment().getCoursePropertyManager();
enrollmentManager.doEnroll(wg2, wg2Roles, bgWithWaitingList, enNode, coursePropertyManager,this /*WindowControl mock*/,testTranslator,
new ArrayList<Long>()/*enrollableGroupNames*/, new ArrayList<Long>()/*enrollableAreaNames*/, userCourseEnv.getCourseEnvironment().getCourseGroupManager());
assertTrue("Enrollment failed, user='wg2'", businessGroupService.isIdentityInBusinessGroup(wg2,bgWithWaitingList));
assertTrue("Enrollment failed, user='wg1'", businessGroupService.isIdentityInBusinessGroup(wg1,bgWithWaitingList));
participantsCounter = businessGroupService.countMembers(bgWithWaitingList, GroupRoles.participant.name());
assertTrue("Wrong number of participants," + participantsCounter , participantsCounter == 2);
// 3. enroll wg3 user => list is full => waiting-list
ienv = new IdentityEnvironment();
ienv.setIdentity(wg3);
userCourseEnv = new UserCourseEnvironmentImpl(ienv, cenv);
coursePropertyManager = userCourseEnv.getCourseEnvironment().getCoursePropertyManager();
enrollmentManager.doEnroll(wg3, wg3Roles, bgWithWaitingList, enNode, coursePropertyManager,this /*WindowControl mock*/,testTranslator,
new ArrayList<Long>()/*enrollableGroupNames*/, new ArrayList<Long>()/*enrollableAreaNames*/, userCourseEnv.getCourseEnvironment().getCourseGroupManager());
assertFalse("Wrong enrollment, user='wg3' is in PartipiciantGroup, must be on waiting-list", businessGroupService.isIdentityInBusinessGroup(wg3,bgWithWaitingList));
assertFalse("Wrong enrollment, user='wg3' is in PartipiciantGroup, must be on waiting-list", businessGroupService.hasRoles(wg3, bgWithWaitingList, GroupRoles.participant.name()));
assertTrue("Wrong enrollment, user='wg3' must be on waiting-list", businessGroupService.hasRoles(wg3, bgWithWaitingList, GroupRoles.waiting.name()));
assertTrue("Enrollment failed, user='wg2'", businessGroupService.isIdentityInBusinessGroup(wg2,bgWithWaitingList));
assertTrue("Enrollment failed, user='wg1'", businessGroupService.isIdentityInBusinessGroup(wg1,bgWithWaitingList));
participantsCounter = businessGroupService.countMembers(bgWithWaitingList, GroupRoles.participant.name());
assertTrue("Wrong number of participants," + participantsCounter , participantsCounter == 2);
int waitingListCounter = businessGroupService.countMembers(bgWithWaitingList, GroupRoles.waiting.name());
assertTrue("Wrong number of waiting-list, must be 1, is " + waitingListCounter , waitingListCounter == 1);
// cancel enrollment for wg2 => transfer wg3 from waiting-list to participants
ienv = new IdentityEnvironment();
ienv.setIdentity(wg2);
userCourseEnv = new UserCourseEnvironmentImpl(ienv, cenv);
coursePropertyManager = userCourseEnv.getCourseEnvironment().getCoursePropertyManager();
enrollmentManager.doCancelEnrollment(wg2,bgWithWaitingList, enNode, coursePropertyManager,this /*WindowControl mock*/,testTranslator);
assertFalse("Cancel enrollment failed, user='wg2' is still participants.", businessGroupService.isIdentityInBusinessGroup(wg2,bgWithWaitingList));
assertTrue("Enrollment failed, user='wg3'", businessGroupService.isIdentityInBusinessGroup(wg3,bgWithWaitingList));
assertTrue("Enrollment failed, user='wg1'", businessGroupService.isIdentityInBusinessGroup(wg1,bgWithWaitingList));
participantsCounter = businessGroupService.countMembers(bgWithWaitingList, GroupRoles.participant.name());
assertTrue("Wrong number of participants, must be 2, is " + participantsCounter , participantsCounter == 2);
waitingListCounter = businessGroupService.countMembers(bgWithWaitingList, GroupRoles.waiting.name());
assertTrue("Wrong number of waiting-list, must be 0, is " + waitingListCounter , waitingListCounter == 0);
// cancel enrollment for wg1
ienv = new IdentityEnvironment();
ienv.setIdentity(wg1);
userCourseEnv = new UserCourseEnvironmentImpl(ienv, cenv);
coursePropertyManager = userCourseEnv.getCourseEnvironment().getCoursePropertyManager();
enrollmentManager.doCancelEnrollment(wg1,bgWithWaitingList, enNode, coursePropertyManager,this /*WindowControl mock*/,testTranslator);
assertFalse("Cancel enrollment failed, user='wg2' is still participants.", businessGroupService.isIdentityInBusinessGroup(wg2,bgWithWaitingList));
assertFalse("Cancel enrollment failed, user='wg1' is still participants.", businessGroupService.isIdentityInBusinessGroup(wg1,bgWithWaitingList));
assertTrue("Enrollment failed, user='wg3'", businessGroupService.isIdentityInBusinessGroup(wg3,bgWithWaitingList));
participantsCounter = businessGroupService.countMembers(bgWithWaitingList, GroupRoles.participant.name());
assertTrue("Wrong number of participants, must be 1, is " + participantsCounter , participantsCounter == 1);
waitingListCounter = businessGroupService.countMembers(bgWithWaitingList, GroupRoles.waiting.name());
assertTrue("Wrong number of waiting-list, must be 0, is " + waitingListCounter , waitingListCounter == 0);
// cancel enrollment for wg3
ienv = new IdentityEnvironment();
ienv.setIdentity(wg3);
userCourseEnv = new UserCourseEnvironmentImpl(ienv, cenv);
coursePropertyManager = userCourseEnv.getCourseEnvironment().getCoursePropertyManager();
enrollmentManager.doCancelEnrollment(wg3,bgWithWaitingList, enNode, coursePropertyManager,this /*WindowControl mock*/,testTranslator);
assertFalse("Cancel enrollment failed, user='wg3' is still participants.", businessGroupService.isIdentityInBusinessGroup(wg3,bgWithWaitingList));
assertFalse("Cancel enrollment failed, user='wg2' is still participants.", businessGroupService.isIdentityInBusinessGroup(wg2,bgWithWaitingList));
assertFalse("Cancel enrollment failed, user='wg1' is still participants.", businessGroupService.isIdentityInBusinessGroup(wg1,bgWithWaitingList));
participantsCounter = businessGroupService.countMembers(bgWithWaitingList, GroupRoles.participant.name());
assertTrue("Wrong number of participants, must be 0, is " + participantsCounter , participantsCounter == 0);
waitingListCounter = businessGroupService.countMembers(bgWithWaitingList, GroupRoles.waiting.name());
assertTrue("Wrong number of waiting-list, must be 0, is " + waitingListCounter , waitingListCounter == 0);
log.info("testEnroll: done...");
}
@Test
public void testConcurrentEnrollmentWithWaitingList() {
int NUM_OF_USERS = 30;
List<Identity> ids = new ArrayList<Identity>(NUM_OF_USERS);
for(int i=0; i<NUM_OF_USERS; i++) {
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("enroll-a-" + i + "-" + UUID.randomUUID().toString());
ids.add(id);
}
ENCourseNode enNode = new ENCourseNode();
Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("enroller");
RepositoryEntry addedEntry = JunitTestHelper.deployBasicCourse(author);
CourseEnvironment cenv = CourseFactory.createCourse(addedEntry, "Test-Enroll", "Test", "Test enrollment with concurrent users").getCourseEnvironment();
BusinessGroup group = businessGroupService.createBusinessGroup(id1, "Enrollment", "Enroll", new Integer(1), new Integer(10), true, false, null);
Assert.assertNotNull(group);
dbInstance.commitAndCloseSession();
final CountDownLatch doneSignal = new CountDownLatch(ids.size());
EnrollThread[] threads = new EnrollThread[NUM_OF_USERS];
int t = 0;
for(Identity id:ids) {
threads[t++] = new EnrollThread(id, addedEntry, group, enNode, cenv, doneSignal);
}
for(EnrollThread thread:threads) {
thread.start();
}
try {
boolean interrupt = doneSignal.await(360, TimeUnit.SECONDS);
assertTrue("Test takes too long (more than 10s)", interrupt);
} catch (InterruptedException e) {
fail("" + e.getMessage());
}
dbInstance.commitAndCloseSession();
List<Identity> enrolledIds = businessGroupService.getMembers(group, GroupRoles.participant.name());
Assert.assertNotNull(enrolledIds);
Assert.assertEquals(10, enrolledIds.size());
List<Identity> waitingIds = businessGroupService.getMembers(group, GroupRoles.waiting.name());
Assert.assertNotNull(waitingIds);
Assert.assertEquals(ids.size() - 10, waitingIds.size());
}
@Test @Ignore
public void testConcurrentEnrollmentWithWaitingList_big() {
List<Identity> ids = new ArrayList<Identity>(100);
for(int i=0; i<100; i++) {
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("enroll-a-" + i + "-" + UUID.randomUUID().toString());
ids.add(id);
}
Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("enroller");
RepositoryEntry addedEntry = JunitTestHelper.deployBasicCourse(author);
ENCourseNode enNode1 = new ENCourseNode();
ENCourseNode enNode2 = new ENCourseNode();
ENCourseNode enNode3 = new ENCourseNode();
ENCourseNode enNode4 = new ENCourseNode();
ENCourseNode enNode5 = new ENCourseNode();
CourseEnvironment cenv = CourseFactory.loadCourse(addedEntry).getCourseEnvironment();
BusinessGroup group1 = businessGroupService.createBusinessGroup(author, "Enrollment 1", "Enroll 1", new Integer(1), new Integer(8), true, true, addedEntry);
BusinessGroup group2 = businessGroupService.createBusinessGroup(author, "Enrollment 2", "Enroll 2", new Integer(1), new Integer(10), true, true, addedEntry);
BusinessGroup group3 = businessGroupService.createBusinessGroup(author, "Enrollment 3", "Enroll 3", new Integer(1), new Integer(4), true, true, addedEntry);
BusinessGroup group4 = businessGroupService.createBusinessGroup(author, "Enrollment 4", "Enroll 4", new Integer(1), new Integer(10), true, true, addedEntry);
BusinessGroup group5 = businessGroupService.createBusinessGroup(author, "Enrollment 5", "Enroll 5", new Integer(1), new Integer(9), true, true, addedEntry);
dbInstance.commitAndCloseSession();
EnrollThread[] threads = new EnrollThread[100];
final CountDownLatch doneSignal = new CountDownLatch(ids.size());
int t = 0;
for(int i=0; i<30; i++) {
threads[t++] = new EnrollThread(ids.get(i), addedEntry, group1, enNode1, cenv, doneSignal);
}
for(int i=30; i<50; i++) {
threads[t++] = new EnrollThread(ids.get(i), addedEntry, group2, enNode2, cenv, doneSignal);
}
for(int i=50; i<70; i++) {
threads[t++] = new EnrollThread(ids.get(i), addedEntry, group3, enNode3, cenv, doneSignal);
}
for(int i=70; i<90; i++) {
threads[t++] = new EnrollThread(ids.get(i), addedEntry, group4, enNode4, cenv, doneSignal);
}
for(int i=90; i<100; i++) {
threads[t++] = new EnrollThread(ids.get(i), addedEntry, group5, enNode5, cenv, doneSignal);
}
for(EnrollThread thread:threads) {
thread.start();
}
try {
boolean interrupt = doneSignal.await(360, TimeUnit.SECONDS);
assertTrue("Test takes too long (more than 10s)", interrupt);
} catch (InterruptedException e) {
fail("" + e.getMessage());
}
dbInstance.commitAndCloseSession();
List<Identity> enrolled_1_Ids = businessGroupService.getMembers(group1, GroupRoles.participant.name());
Assert.assertEquals(8, enrolled_1_Ids.size());
List<Identity> enrolled_2_Ids = businessGroupService.getMembers(group2, GroupRoles.participant.name());
Assert.assertEquals(10, enrolled_2_Ids.size());
List<Identity> enrolled_3_Ids = businessGroupService.getMembers(group3, GroupRoles.participant.name());
Assert.assertEquals(4, enrolled_3_Ids.size());
List<Identity> enrolled_4_Ids = businessGroupService.getMembers(group4, GroupRoles.participant.name());
Assert.assertEquals(10, enrolled_4_Ids.size());
List<Identity> enrolled_5_Ids = businessGroupService.getMembers(group5, GroupRoles.participant.name());
Assert.assertEquals(9, enrolled_5_Ids.size());
}
private class EnrollThread extends Thread {
private final ENCourseNode enNode;
private final Identity identity;
private final CourseEnvironment cenv;
private final BusinessGroup group;
private final RepositoryEntry courseEntry;
private final CountDownLatch doneSignal;
public EnrollThread(Identity identity, RepositoryEntry courseEntry, BusinessGroup group,
ENCourseNode enNode, CourseEnvironment cenv, CountDownLatch doneSignal) {
this.enNode = enNode;
this.group = group;
this.courseEntry = courseEntry;
this.identity = identity;
this.cenv = cenv;
this.doneSignal = doneSignal;
}
@Override
public void run() {
try {
UserSession session = new UserSession();
session.setIdentity(identity);
session.setSessionInfo(new SessionInfo(identity.getKey(), identity.getName()));
ThreadLocalUserActivityLoggerInstaller.initUserActivityLogger(session);
IdentityEnvironment ienv = new IdentityEnvironment();
ienv.setIdentity(identity);
UserCourseEnvironment userCourseEnv = new UserCourseEnvironmentImpl(ienv, cenv);
CoursePropertyManager coursePropertyManager = userCourseEnv.getCourseEnvironment().getCoursePropertyManager();
CourseGroupManager courseGroupManager = userCourseEnv.getCourseEnvironment().getCourseGroupManager();
ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrap(courseEntry.getOlatResource(), OlatResourceableType.course));
ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrap(enNode));
ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrap(group));
sleep(Math.round(new Random().nextDouble() * 100l));
enrollmentManager.doEnroll(identity, JunitTestHelper.getUserRoles(), group, enNode, coursePropertyManager, EnrollmentManagerConcurrentTest.this /*WindowControl mock*/, testTranslator,
new ArrayList<Long>()/*enrollableGroupNames*/, new ArrayList<Long>()/*enrollableAreaNames*/, courseGroupManager);
DBFactory.getInstance().commit();
} catch (Exception e) {
log.error("", e);
} finally {
ThreadLocalUserActivityLoggerInstaller.resetUserActivityLogger();
DBFactory.getInstance().commitAndCloseSession();
doneSignal.countDown();
}
}
}
// Implements interface WindowControl
/////////////////////////////////////
public void pushToMainArea(Component comp){}
public void pushAsModalDialog(Component comp){}
@Override
public void pushAsCallout(Component comp, String targetId, CalloutSettings settings){}
public void pop(){}
public void setInfo(String string){}
public void setError(String string){}
public void setWarning(String string){}
public DTabs getDTabs(){return null;}
public WindowControlInfo getWindowControlInfo(){return null;}
public void makeFlat(){}
public BusinessControl getBusinessControl() {
BusinessControl control = new BusinessControl() {
@Override
public String getAsString() {
return null;
}
@Override
public List<ContextEntry> getEntries() {
return Collections.<ContextEntry>emptyList();
}
@Override
public List<ContextEntry> getEntriesDownTheControls() {
return Collections.<ContextEntry>emptyList();
}
@Override
public ContextEntry popLauncherContextEntry() {
return null;
}
@Override
public ContextEntry getCurrentContextEntry() {
return null;
}
@Override
public void setCurrentContextEntry(ContextEntry cw) {
//
}
@Override
public void dropLauncherEntries() {
//
}
@Override
public boolean hasContextEntry() {
return false;
}
};
return control;
}
public WindowBackOffice getWindowBackOffice() {
return null;
};
}