/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/lessonbuilder/trunk/tool/src/java/org/sakaiproject/lessonbuildertool/tool/entityproviders/LessonbuilderEntityProvider.java $ * $Id: LessonbuilderEntityProvider.java $ *********************************************************************************** * * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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.lessonbuildertool.tool.entityproviders; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.Getter; import lombok.Setter; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.entitybroker.EntityReference; import org.sakaiproject.entitybroker.EntityView; import org.sakaiproject.entity.cover.EntityManager; import org.sakaiproject.entitybroker.entityprovider.annotations.EntityCustomAction; import org.sakaiproject.entitybroker.entityprovider.EntityProvider; import org.sakaiproject.entitybroker.entityprovider.capabilities.ActionsExecutable; import org.sakaiproject.entitybroker.entityprovider.capabilities.AutoRegisterEntityProvider; import org.sakaiproject.entitybroker.entityprovider.capabilities.Describeable; import org.sakaiproject.entitybroker.entityprovider.capabilities.Outputable; import org.sakaiproject.entitybroker.entityprovider.capabilities.Resolvable; import org.sakaiproject.entitybroker.entityprovider.capabilities.Sampleable; import org.sakaiproject.entitybroker.entityprovider.extension.Formats; import org.sakaiproject.entitybroker.exception.EntityNotFoundException; import org.sakaiproject.entitybroker.util.AbstractEntityProvider; import org.sakaiproject.entitybroker.DeveloperHelperService; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.exception.PermissionException; import org.sakaiproject.authz.api.SecurityService; import org.sakaiproject.site.api.Site; import org.sakaiproject.site.api.SiteService; import org.sakaiproject.site.api.SiteService.SortType; import org.sakaiproject.site.api.ToolConfiguration; import org.sakaiproject.tool.api.Session; import org.sakaiproject.tool.api.SessionManager; import org.sakaiproject.tool.api.ToolManager; import org.sakaiproject.tool.api.ToolSession; import org.sakaiproject.tool.api.ActiveTool; import org.sakaiproject.component.cover.ServerConfigurationService; import org.sakaiproject.thread_local.cover.ThreadLocalManager; import org.sakaiproject.tool.cover.ActiveToolManager; import org.sakaiproject.tool.api.Placement; import org.sakaiproject.lessonbuildertool.model.SimplePageToolDao; import org.sakaiproject.lessonbuildertool.SimplePage; import org.sakaiproject.lessonbuildertool.SimplePageItem; import org.sakaiproject.lessonbuildertool.SimplePageQuestionAnswer; import org.sakaiproject.lessonbuildertool.service.LessonsAccess; import org.sakaiproject.lessonbuildertool.tool.beans.SimplePageBean; /** * @author fsaez * */ public class LessonsEntityProvider extends AbstractEntityProvider implements EntityProvider, AutoRegisterEntityProvider, Outputable, Describeable, Sampleable, Resolvable, ActionsExecutable { public final static String ENTITY_PREFIX = "lessons"; public final static String TOOL_COMMON_ID = "sakai.lessonbuildertool"; public static final String REFERENCE_ROOT = "/lessons"; // from ToolComponent, which is part of kernel-impl, so we can't get to it. /** Key in the ThreadLocalManager for binding our current placement. */ protected final static String CURRENT_PLACEMENT = "sakai:ToolComponent:current.placement"; /** Key in the ThreadLocalManager for binding our current tool. */ protected final static String CURRENT_TOOL = "sakai:ToolComponent:current.tool"; private static final Log log = LogFactory.getLog(LessonsEntityProvider.class); @Override public String getEntityPrefix() { return ENTITY_PREFIX; } @Override public Object getSampleEntity() { return null; } /* * security model. Need the following * * setToolSession - creates a tool session and sets current site in ThreadLocal. * needed because some tools for which we do group checks use this info * in their services. (in fact Lessons code current does, though that could be fixed.) * checkReadPermission in site * isItemAccessible * These are combined by checkItemPermissions, but in loops it is probaby better to * do checkReadPermission once and checkItemPermission for the items * In a loop it's also best to do an explicitly creation of a SimplePageBean and * pass it to each call to checkItemPermission * checkUpdatePermission in site * if user has update you don't need to check for read or item permission */ @Override public Object getEntity(EntityReference ref) { if (!ServerConfigurationService.getBoolean("lessonbuilder.keitai", true)) return null; //get user uuid String id = ref.getId(); if(StringUtils.isBlank(id)) { throw new EntityNotFoundException("Invalid lesson.", ref.getId()); } DecoratedItem ret = null; SimplePageItem item = simplePageToolDao.findItem(Long.valueOf(id)); if(item == null) throw new EntityNotFoundException("Id not found", id); SimplePage page = null; if (item.getType() == SimplePageItem.PAGE) page = simplePageToolDao.getPage(Long.parseLong(item.getSakaiId())); else page = simplePageToolDao.getPage(item.getPageId()); if(page != null) { String siteId = page.getSiteId(); Site site = null; try { site = siteService.getSiteVisit(siteId); } catch (IdUnusedException e) { throw new EntityNotFoundException("Invalid siteId: " + siteId, siteId); } catch (PermissionException e) { throw new EntityNotFoundException("No access to site: " + siteId, siteId); } //check if given site contains the lessonbuilder tool //checkTool(site); setToolSession(site); //check if current user has permission to access to the lessonbuilder tool // checks tool read and item perm if (!checkUpdatePermission(siteId)) checkItemPermission(siteId, item.getId()); if (item.getType() == SimplePageItem.PAGE) { String baseURL = developerHelperService.getEntityURL(REFERENCE_ROOT, EntityView.VIEW_LIST, null); // /direct/lessons baseURL = baseURL + "/lesson/"; ret = new DecoratedPageItem(item.getId(), item.getName(), item.getType(), siteId, site.getTitle(), baseURL + item.getId()); } else ret = new DecoratedItem(item.getId(), item.getName(), item.getType(), siteId, site.getTitle()); } else throw new EntityNotFoundException("Invalid id", id); return ret; } /** * site * example: /direct/lessons/site/SITEID.xml */ @EntityCustomAction(action="site",viewKey=EntityView.VIEW_LIST) public List<?> getLessonsInSite(EntityView view, Map<String, Object> params) { if (!ServerConfigurationService.getBoolean("lessonbuilder.keitai", true)) return null; String siteId = view.getPathSegment(2); if (siteId == null || "".equals(siteId)) { // format of the view should be in a standard message reference throw new IllegalArgumentException("Must include siteId in the path ("+view+"): e.g. /direct/lessons/site/{siteId}"); } Site site = null; try { site = siteService.getSiteVisit(siteId); } catch (IdUnusedException e) { throw new EntityNotFoundException("Invalid siteId: " + siteId, siteId); } catch (PermissionException e) { throw new EntityNotFoundException("No access to site: " + siteId, siteId); } //check if given site contains the lessonbuilder tool //checkTool(site); setToolSession(site); //check if current user has permission to access to the lessonbuilder tool checkReadPermission(siteId); List<DecoratedSiteItem> ret = new ArrayList<DecoratedSiteItem>(); List<SimplePageItem> list = simplePageToolDao.findItemsInSite(siteId); // best to do this once so each call to isItemAccessible doesn't have to SimplePageBean simplePageBean = null; String currentUserId = sessionManager.getCurrentSessionUserId(); String baseURL = developerHelperService.getEntityURL(REFERENCE_ROOT, EntityView.VIEW_LIST, null); // /direct/lessons baseURL = baseURL + "/lesson/"; boolean hasUpdatePermission = checkUpdatePermission(siteId); for(SimplePageItem item : list) { simplePageBean = makeSimplePageBean(simplePageBean, siteId, item); if (hasUpdatePermission || lessonsAccess.isItemAccessible(item.getId(), siteId, currentUserId, simplePageBean)) ret.add(new DecoratedSiteItem(item.getId(), item.getName(), baseURL + item.getId())); } return ret; } /** * user * example: /direct/lessons/user.xml */ @EntityCustomAction(action="user",viewKey=EntityView.VIEW_LIST) public List<?> getLessonsForUser(EntityView view, Map<String, Object> params) { if (!ServerConfigurationService.getBoolean("lessonbuilder.keitai", true)) return null; List<DecoratedUserItem> ret = new ArrayList<DecoratedUserItem>(); String currentUserId = sessionManager.getCurrentSessionUserId(); String baseURL = developerHelperService.getEntityURL(REFERENCE_ROOT, EntityView.VIEW_LIST, null); // /direct/lessons baseURL = baseURL + "/lesson/"; //first of all, we get a list with all sites that the user can access List<Site> siteList = getUserSites(); for(Site s : siteList) { SimplePageBean simplePageBean = null; try { //check if given site contains the lessonbuilder tool //checkTool(s); setToolSession(s); //check if current user has permission to access to the lessonbuilder tool checkReadPermission(s.getId()); List<SimplePageItem> list = simplePageToolDao.findItemsInSite(s.getId()); boolean hasUpdatePermission = checkUpdatePermission(s.getId()); for(SimplePageItem item : list) { simplePageBean = makeSimplePageBean(simplePageBean, s.getId(), item); if (hasUpdatePermission || lessonsAccess.isItemAccessible(item.getId(), s.getId(), currentUserId, simplePageBean)) ret.add(new DecoratedUserItem(item.getId(), item.getName(), s.getId(), s.getTitle(), baseURL + item.getId())); } }catch(EntityNotFoundException e) { //if there is no lessonbuilder tool in that site, just skip it }catch(SecurityException e) { //if current user can not access to the lessonbuilder tool on that site, just skip it } } return ret; } /** * lesson * example: /direct/lessons/lesson/LESSONID.xml */ @EntityCustomAction(action="lesson",viewKey=EntityView.VIEW_LIST) public Object getLesson(EntityView view, Map<String, Object> params) { if (!ServerConfigurationService.getBoolean("lessonbuilder.keitai", true)) return null; String id = view.getPathSegment(2); if (id == null || "".equals(id)) { // format of the view should be in a standard message reference throw new IllegalArgumentException("Must include lessonId in the path ("+view+"): e.g. /direct/lessons/lesson/{lessonId}"); } boolean simpleType = false; boolean fullTree = true; if(params != null) { try { if(params.get("type") != null) simpleType = "simple".equals(params.get("type")); } catch(Exception e){} try { if(params.get("fullTree") != null) fullTree = Boolean.valueOf((String)params.get("fullTree")); } catch(Exception e){} } List ret = new ArrayList(); //get item by id SimplePageItem item = simplePageToolDao.findItem(Long.parseLong(id)); if(item == null) throw new EntityNotFoundException("Id not found", id); SimplePage page = null; if (item.getType() == SimplePageItem.PAGE) page = simplePageToolDao.getPage(Long.parseLong(item.getSakaiId())); else page = simplePageToolDao.getPage(item.getPageId()); if(page != null) { String siteId = page.getSiteId(); Site site = null; try { site = siteService.getSiteVisit(siteId); } catch (IdUnusedException e) { throw new EntityNotFoundException("Invalid siteId: " + siteId, siteId); } catch (PermissionException e) { throw new EntityNotFoundException("No access to site: " + siteId, siteId); } //check if given site contains the lessonbuilder tool //checkTool(site); setToolSession(site); //check if current user has permission to access to the lessonbuilder tool //checks tool read and item permission boolean hasUpdatePermission = checkUpdatePermission(siteId); if (!hasUpdatePermission) checkItemPermission(siteId, item.getId()); // remove after testing // hasUpdatePermission = false; String currentUserId = sessionManager.getCurrentSessionUserId(); //if required item is not a page or we just want a single item if (item.getType() != SimplePageItem.PAGE || !fullTree) { if(simpleType) ret.add(new DecoratedItem(item.getId(), item.getName(), item.getType(), site.getId(), site.getTitle())); else addItem(item, ret, hasUpdatePermission); return ret.get(0); } // build map of all pages, so we can check if any is repeated Map<Long,SimplePage> pageMap = new HashMap<Long,SimplePage>(); // all pages List<SimplePage> pages = simplePageToolDao.getSitePages(siteId); for (SimplePage p: pages) pageMap.put(p.getPageId(), p); if(simpleType) findAllSimplePages(item, ret, pageMap, hasUpdatePermission, site, currentUserId); else findAllPages(item, ret, pageMap, hasUpdatePermission, siteId, currentUserId); } else { throw new EntityNotFoundException("Given id does not pertain to any page", id); } if (ret != null && ret.size() > 0) return ret.get(0); return ret; } @Override public String[] getHandledOutputFormats() { return new String[] {Formats.XML, Formats.JSON}; } // -------------------------------------------------------------------------------- // OUTPUT OBJECTS // -------------------------------------------------------------------------------- //for getEntity and action=lesson & type=simple @NoArgsConstructor @AllArgsConstructor @Data public class DecoratedItem { private long id; private String lessonTitle; private int type; private String siteId; private String siteTitle; } @NoArgsConstructor @AllArgsConstructor @Data public class DecoratedPageItem extends DecoratedItem { private String contentsURL; public DecoratedPageItem(long id, String title, int type, String siteId, String siteTitle, String contentsURL) { super(id, title, type, siteId, siteTitle); this.contentsURL = contentsURL; } } // for action=site @NoArgsConstructor @AllArgsConstructor @Data public class DecoratedSiteItem { private long id; private String lessonTitle; private String contentsURL; } //for action=user @NoArgsConstructor @AllArgsConstructor @Data public class DecoratedUserItem { private long id; private String lessonTitle; private String siteId; private String siteTitle; private String contentsURL; } // simplified version of SimplePageItem (base object) for action=lesson & type!=simple(default) /** * LessonBase: is a wrapper of SimplePageItem, so we can show only the attributes we want. This class is the base from which all other classes extend. * Any attribute shared by all kinds of "items", should be placed here. Attributes are called as SimplePageItem to avoid misunderstandings */ @NoArgsConstructor @AllArgsConstructor @Data public class LessonBase { private long id; private String name; private int type; private long pageId; private boolean prerequisite; private boolean required; public LessonBase(SimplePageItem item) { if(item != null) { this.id = item.getId(); this.name = item.getName(); this.type = item.getType(); this.pageId = item.getPageId(); this.prerequisite = item.isPrerequisite(); this.required = item.isRequired(); } } } //(based on LessonBase) for most cases @NoArgsConstructor @AllArgsConstructor @Data public class DecoratedLesson extends LessonBase{ private String sakaiId; private String html; private String url; public DecoratedLesson(SimplePageItem item) { super(item); if(item != null) { this.sakaiId = item.getSakaiId(); this.html = item.getHtml(); this.url = item.getURL(); } } } @NoArgsConstructor @AllArgsConstructor @Data public class DecoratedLessonPage extends DecoratedLesson { private String contentsURL; private List<LessonBase> contentsList; public void setContentsList(List<LessonBase> list) { contentsList = list; } public DecoratedLessonPage(SimplePageItem item) { super(item); String baseURL = developerHelperService.getEntityURL(REFERENCE_ROOT, EntityView.VIEW_LIST, null); // /direct/lessons baseURL = baseURL + "/lesson/"; this.contentsURL = baseURL + item.getId(); this.contentsList = null; } } //for question items (base) @NoArgsConstructor @Data public class DecoratedQuiz extends LessonBase { private String questionText; private String questionCorrectText; private String questionIncorrectText; private String questionType; private String questionGraded; public DecoratedQuiz(SimplePageItem item) { super(item); } public DecoratedQuiz(SimplePageItem item, String questionText, String questionCorrectText, String questionIncorrectText, String questionType, String questionGraded) { super(item); this.questionText = questionText; this.questionCorrectText = questionCorrectText; this.questionIncorrectText = questionIncorrectText; this.questionType = questionType; this.questionGraded = questionGraded; } } //for multiple choice questions @NoArgsConstructor @Data public class DecoratedMultipleChoiceQuestion extends DecoratedQuiz { private String questionShowPoll; private List<DecoratedAnswerItem> answersList; public DecoratedMultipleChoiceQuestion(SimplePageItem item) { super(item); answersList = new ArrayList<DecoratedAnswerItem>(); } public DecoratedMultipleChoiceQuestion(SimplePageItem item, String questionText, String questionCorrectText, String questionIncorrectText, String questionGraded) { super(item, questionText, questionCorrectText, questionIncorrectText, "multipleChoice", questionGraded); answersList = new ArrayList<DecoratedAnswerItem>(); } public DecoratedMultipleChoiceQuestion(SimplePageItem item, String questionText, String questionCorrectText, String questionIncorrectText, String questionGraded, String questionShowPoll) { super(item, questionText, questionCorrectText, questionIncorrectText, "multipleChoice", questionGraded); this.questionShowPoll = questionShowPoll; answersList = new ArrayList<DecoratedAnswerItem>(); } public void addAnswer(DecoratedAnswerItem answer) { answersList.add(answer); } } //for shortanswer questions @NoArgsConstructor @Data public class DecoratedShortAnswerQuestion extends DecoratedQuiz { private String questionAnswer; public DecoratedShortAnswerQuestion(SimplePageItem item) { super(item); } public DecoratedShortAnswerQuestion(SimplePageItem item, String questionText, String questionCorrectText, String questionIncorrectText, String questionGraded) { super(item, questionText, questionCorrectText, questionIncorrectText, "shortanswer", questionGraded); } public DecoratedShortAnswerQuestion(SimplePageItem item, String questionText, String questionCorrectText, String questionIncorrectText, String questionGraded, String questionAnswer) { super(item, questionText, questionCorrectText, questionIncorrectText, "shortanswer", questionGraded); this.questionAnswer = questionAnswer; } } //answers for multiple choice questions @NoArgsConstructor @AllArgsConstructor @Data public class DecoratedAnswerItem { private long id; private String text; private Boolean correct; } // -------------------------------------------------------------------------------- // PRIVATE METHODS // -------------------------------------------------------------------------------- private void checkTool(Site site) { if(site != null) { //check user can access the tool, it might be hidden Collection col = site.getTools(TOOL_COMMON_ID); if(col == null || col.isEmpty()) throw new EntityNotFoundException("No tool "+TOOL_COMMON_ID+" in site: " + site.getId(), site.getId()); for(Object o : col) { ToolConfiguration toolConfig = (ToolConfiguration)o; if(!toolManager.isVisible(site, toolConfig)) throw new EntityNotFoundException("No access to tool in site: " + site.getId(), site.getId()); } } else throw new EntityNotFoundException("Invalid site", "-null-"); } // Some of the tools (e.g. Formums) require a valid session in order to do permission // checking. So if we don't already have a session with the right site, set one up. private void setToolSession(Site site) { Placement p = toolManager.getCurrentPlacement(); if (p == null || !site.getId().equals(p.getContext())) { ToolConfiguration siteTool = site.getToolForCommonId(TOOL_COMMON_ID); ActiveTool tool = ActiveToolManager.getActiveTool(siteTool.getToolId()); Session ses = sessionManager.getCurrentSession(); ToolSession toolSession = ses.getToolSession(siteTool.getId()); sessionManager.setCurrentToolSession(toolSession); ThreadLocalManager.set(CURRENT_PLACEMENT, siteTool); ThreadLocalManager.set(CURRENT_TOOL, tool); } } private void checkReadPermission(String siteId) { checkReadPermission(siteId, sessionManager.getCurrentSessionUserId()); } private void checkItemPermission(String siteId, long itemId) { String currentUserId = sessionManager.getCurrentSessionUserId(); checkReadPermission(siteId, currentUserId); if (!lessonsAccess.isItemAccessible(itemId, siteId, currentUserId, null)) { throw new SecurityException("User "+currentUserId+" does not have permission to read lessons on site " + siteId); } } private void checkReadPermission(String siteId, String userId) { if(!securityService.unlock(userId, SimplePage.PERMISSION_LESSONBUILDER_READ, siteService.siteReference(siteId))) { throw new SecurityException("User "+userId+" does not have permission to read lessons on site " + siteId); } } private boolean checkUpdatePermission(String siteId) { return checkUpdatePermission(siteId, sessionManager.getCurrentSessionUserId()); } private boolean checkUpdatePermission(String siteId, String userId) { return securityService.unlock(userId, SimplePage.PERMISSION_LESSONBUILDER_UPDATE, siteService.siteReference(siteId)); } private SimplePage getPage(SimplePageBean simplePageBean, Long pageId) { // use cached version if we have the bean if (simplePageBean != null) return simplePageBean.getPage(pageId); else return simplePageToolDao.getPage(pageId); } private SimplePageBean makeSimplePageBean(SimplePageBean simplePageBean,String siteId, SimplePageItem item) { SimplePage page = null; if (item.getType() == SimplePageItem.PAGE) page = getPage(simplePageBean, Long.parseLong(item.getSakaiId())); else page = getPage(simplePageBean, item.getPageId()); if (simplePageBean == null) simplePageBean = lessonsAccess.makeSimplePageBean(null, siteId, page); else { // reuse current bean simplePageBean.setCurrentPage(page); simplePageBean.setCurrentPageId(page.getPageId()); } return simplePageBean; } private synchronized List<Site> getUserSites() { List<Site> siteList = new ArrayList<Site>(); try { siteList = siteService.getSites(org.sakaiproject.site.api.SiteService.SelectionType.ACCESS, null, null, null, SortType.TITLE_ASC, null); }catch(Exception e){ log.warn("getUserSites -> "+e); } return siteList; } // caller has done checkItemPermissions for the page. We have to check it // for all items on the page. Since caller has checked site read we // only have to check isItemAccessible. /** * findAllPages : explores lessonbuilder tree from a base pageItem and fills a list of LessonBase items * * @param pageItem * @param entries * @param pageMap * @param hasUpdatePermission */ private void findAllPages(SimplePageItem pageItem, List<LessonBase> entries, Map<Long,SimplePage> pageMap, boolean hasUpdatePermission, String siteId, String currentUserId) { Long pageId = Long.valueOf(pageItem.getSakaiId()); // already done if page is null if (pageMap.get(pageId) == null) return; // say done pageMap.remove(pageId); LessonBase lessonPage = addItem(pageItem, entries, hasUpdatePermission); // now recursively do subpages List<SimplePageItem> items = simplePageToolDao.findItemsOnPage(pageId); if (items != null && items.size() > 0) { if (lessonPage instanceof DecoratedLessonPage) { entries = new ArrayList<LessonBase>(); ((DecoratedLessonPage)lessonPage).setContentsList(entries); } SimplePageBean simplePageBean = null; // subpages done in place for (SimplePageItem item: items) { simplePageBean = makeSimplePageBean(simplePageBean, siteId, item); // skip if don't have permission if (!hasUpdatePermission && !lessonsAccess.isItemAccessible(item.getId(), siteId, currentUserId, simplePageBean)) continue; if (item.getType() == SimplePageItem.PAGE) findAllPages(item, entries, pageMap, hasUpdatePermission, siteId, currentUserId ); else addItem(item, entries, hasUpdatePermission); } } } // caller has done checkItemPermissions for the page. We have to check it // for all items on the page. Since caller has checked site read we // only have to check isItemAccessible. /** * findAllPages : explores lessonbuilder tree from a base pageItem and fills a list of DecoratedItem items * * @param pageItem * @param entries * @param pageMap * @param site */ private void findAllSimplePages(SimplePageItem pageItem, List<DecoratedItem> entries, Map<Long,SimplePage> pageMap, boolean hasUpdatePermission, Site site, String currentUserId) { Long pageId = Long.valueOf(pageItem.getSakaiId()); // already done if page is null if (pageMap.get(pageId) == null) return; // say done pageMap.remove(pageId); entries.add(new DecoratedItem(pageItem.getId(), pageItem.getName(), pageItem.getType(), site.getId(), site.getTitle())); // now recursively do subpages List<SimplePageItem> items = simplePageToolDao.findItemsOnPage(pageId); SimplePageBean simplePageBean = null; // subpages done in place for (SimplePageItem item: items) { simplePageBean = makeSimplePageBean(simplePageBean, site.getId(), item); // skip if don't have permission if (!hasUpdatePermission && !lessonsAccess.isItemAccessible(item.getId(), site.getId(), currentUserId, simplePageBean)) continue; if (item.getType() == SimplePageItem.PAGE) findAllSimplePages(item, entries, pageMap, hasUpdatePermission, site, currentUserId); else entries.add(new DecoratedItem(item.getId(), item.getName(), item.getType(), site.getId(), site.getTitle())); } } /** * addItem : creates a new LessonBase item based on the given SimplePageItem item and adds it to the given list * depending of SimplePageItem's type, the new LessonBase object could be one of the following: * - QUESTION -> DecoratedQuiz (DecoratedMultipleChoiceQuestion or DecoratedShortAnswerQuestion) * - OTHERS -> DecoratedLesson * * @param item * @param list * @param hasUpdatePermission */ private LessonBase addItem(SimplePageItem item, List<LessonBase> list, boolean hasUpdatePermission) { if(list == null) list = new ArrayList<LessonBase>(); if(item != null) { LessonBase lesson = null; //check type switch(item.getType()) { case SimplePageItem.QUESTION: if("multipleChoice".equals(item.getAttribute("questionType"))) { lesson = new DecoratedMultipleChoiceQuestion(item, item.getAttribute("questionText"), item.getAttribute("questionCorrectText"), item.getAttribute("questionIncorrectText"), item.getAttribute("questionGraded"), item.getAttribute("questionShowPoll")); List<SimplePageQuestionAnswer> answers = simplePageToolDao.findAnswerChoices(item); for(SimplePageQuestionAnswer a : answers) { DecoratedAnswerItem answer = new DecoratedAnswerItem(); answer.setId(a.getId()); answer.setText(a.getText()); //only show correct value if has permissions if(hasUpdatePermission) answer.setCorrect(a.isCorrect()); ((DecoratedMultipleChoiceQuestion)lesson).addAnswer(answer); } } else if("shortanswer".equals(item.getAttribute("questionType"))) { lesson = new DecoratedShortAnswerQuestion(item, item.getAttribute("questionText"), item.getAttribute("questionCorrectText"), item.getAttribute("questionIncorrectText"), item.getAttribute("questionGraded"), item.getAttribute("questionAnswer")); } break; case SimplePageItem.PAGE: lesson = new DecoratedLessonPage(item); break; default: lesson = new DecoratedLesson(item); break; } list.add(lesson); return lesson; } return null; } @Setter private SecurityService securityService; @Setter private SessionManager sessionManager; @Setter private SiteService siteService; @Setter private ToolManager toolManager; @Setter private SimplePageToolDao simplePageToolDao; @Setter private LessonsAccess lessonsAccess; @Setter private DeveloperHelperService developerHelperService; }