Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/controller/LogEventController.java =================================================================== diff -u -r8e2e72a36d57288787cf76af6484e25c82b385c1 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/controller/LogEventController.java (.../LogEventController.java) (revision 8e2e72a36d57288787cf76af6484e25c82b385c1) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/controller/LogEventController.java (.../LogEventController.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -62,7 +62,7 @@ @Autowired private ILogEventService logEventService; - + @Autowired @Qualifier("adminMessageService") private MessageService messageService; @@ -121,11 +121,12 @@ int sorting = ILogEventService.SORT_BY_DATE_DESC; if (isSortDate != null) { - sorting = isSortDate.equals(1) ? ILogEventService.SORT_BY_DATE_DESC : ILogEventService.SORT_BY_DATE_ASC; + sorting = isSortDate.equals(1) ? ILogEventService.SORT_BY_DATE_DESC : ILogEventService.SORT_BY_DATE_ASC; } else if (isSortUser != null) { - sorting = isSortUser.equals(1) ? ILogEventService.SORT_BY_USER_DESC : ILogEventService.SORT_BY_USER_ASC; + sorting = isSortUser.equals(1) ? ILogEventService.SORT_BY_USER_DESC : ILogEventService.SORT_BY_USER_ASC; } else if (isSortTarget != null) { - sorting = isSortTarget.equals(1) ? ILogEventService.SORT_BY_TARGET_DESC : ILogEventService.SORT_BY_TARGET_ASC; + sorting = isSortTarget.equals(1) ? ILogEventService.SORT_BY_TARGET_DESC + : ILogEventService.SORT_BY_TARGET_ASC; } Long dateParameter = WebUtil.readLongParam(request, "startDate", true); @@ -161,8 +162,10 @@ LogEvent event = (LogEvent) eventDetails[0]; ObjectNode responseRow = JsonNodeFactory.instance.objectNode(); - responseRow.put("dateOccurred", event.getOccurredDateTime() != null ? - DateUtil.convertToStringForJSON(event.getOccurredDateTime(), request.getLocale()) : ""); + responseRow.put("dateOccurred", + event.getOccurredDateTime() != null + ? DateUtil.convertToStringForJSON(event.getOccurredDateTime(), request.getLocale()) + : ""); responseRow.put("typeId", event.getLogEventTypeId()); responseRow.put("description", event.getDescription()); if (event.getLessonId() != null) { @@ -174,13 +177,15 @@ User user = event.getUser(); if (user != null) { - responseRow.put("userPortraitId", user.getPortraitUuid()); + responseRow.put("userPortraitId", + user.getPortraitUuid() == null ? null : user.getPortraitUuid().toString()); responseRow.put("userId", user.getUserId()); responseRow.put("userName", user.getLogin()); } User targetUser = event.getTargetUser(); if (targetUser != null) { - responseRow.put("targetUserPortraitId", targetUser.getPortraitUuid()); + responseRow.put("targetUserPortraitId", + targetUser.getPortraitUuid() == null ? null : targetUser.getPortraitUuid().toString()); responseRow.put("targetUserId", targetUser.getUserId()); responseRow.put("targetUserName", targetUser.getLogin()); } Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/controller/UserController.java =================================================================== diff -u -r1ef1213820fe7ff7c6f4a9238b3f489a25012c63 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/controller/UserController.java (.../UserController.java) (revision 1ef1213820fe7ff7c6f4a9238b3f489a25012c63) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/controller/UserController.java (.../UserController.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -173,7 +173,7 @@ userSelectedTheme = themeService.getDefaultTheme().getThemeId(); } userForm.setUserTheme(userSelectedTheme); - userForm.setInitialPortraitId(user.getPortraitUuid()); + userForm.setInitialPortraitId(user.getPortraitUuid() == null ? null : user.getPortraitUuid().toString()); //property available for modification only to sysadmins userForm.setTwoFactorAuthenticationEnabled(user.isTwoFactorAuthenticationEnabled()); Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/UserForm.java =================================================================== diff -u -r550e1b37b507779064955267ef47e9085f791357 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/UserForm.java (.../UserForm.java) (revision 550e1b37b507779064955267ef47e9085f791357) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/UserForm.java (.../UserForm.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -53,7 +53,7 @@ private Long userTheme; private boolean twoFactorAuthenticationEnabled = false; // - private Long initialPortraitId = null; + private String initialPortraitId = null; public Integer getOrgId() { return orgId; @@ -279,11 +279,11 @@ this.twoFactorAuthenticationEnabled = twoFactorAuthenticationEnabled; } - public Long getInitialPortraitId() { + public String getInitialPortraitId() { return initialPortraitId; } - public void setInitialPortraitId(Long initialPortraitId) { + public void setInitialPortraitId(String initialPortraitId) { this.initialPortraitId = initialPortraitId; } Index: lams_central/src/java/org/lamsfoundation/lams/web/PortraitActionForm.java =================================================================== diff -u -r792f30e164500b758d9eeac2dcf19853be4dfd9f -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_central/src/java/org/lamsfoundation/lams/web/PortraitActionForm.java (.../PortraitActionForm.java) (revision 792f30e164500b758d9eeac2dcf19853be4dfd9f) +++ lams_central/src/java/org/lamsfoundation/lams/web/PortraitActionForm.java (.../PortraitActionForm.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -30,14 +30,14 @@ */ public class PortraitActionForm { - private Long portraitUuid; + private String portraitUuid; private MultipartFile file; - public Long getPortraitUuid() { + public String getPortraitUuid() { return portraitUuid; } - public void setPortraitUuid(Long uuid) { + public void setPortraitUuid(String uuid) { this.portraitUuid = uuid; } Index: lams_central/src/java/org/lamsfoundation/lams/web/PortraitController.java =================================================================== diff -u -r40de3afab4e8d589660daffb6efd6e568e87f8fa -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_central/src/java/org/lamsfoundation/lams/web/PortraitController.java (.../PortraitController.java) (revision 40de3afab4e8d589660daffb6efd6e568e87f8fa) +++ lams_central/src/java/org/lamsfoundation/lams/web/PortraitController.java (.../PortraitController.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -23,6 +23,8 @@ package org.lamsfoundation.lams.web; +import java.util.UUID; + import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; @@ -42,11 +44,12 @@ private IUserManagementService userManagementService; @RequestMapping("/portrait") - public String execute(@ModelAttribute("PortraitActionForm") PortraitActionForm portraitForm, HttpServletRequest request) { - Long portraitUuid = userManagementService.getUserByLogin(request.getRemoteUser()).getPortraitUuid(); + public String execute(@ModelAttribute("PortraitActionForm") PortraitActionForm portraitForm, + HttpServletRequest request) { + UUID portraitUuid = userManagementService.getUserByLogin(request.getRemoteUser()).getPortraitUuid(); log.debug("using portraitUuid=" + portraitUuid); // if no portrait has been uploaded, set the uuid to 0 - portraitForm.setPortraitUuid(portraitUuid == null ? 0 : portraitUuid); + portraitForm.setPortraitUuid(portraitUuid == null ? "0" : portraitUuid.toString()); return "profile/portrait"; } } Index: lams_central/src/java/org/lamsfoundation/lams/web/PortraitSaveController.java =================================================================== diff -u -r40de3afab4e8d589660daffb6efd6e568e87f8fa -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_central/src/java/org/lamsfoundation/lams/web/PortraitSaveController.java (.../PortraitSaveController.java) (revision 40de3afab4e8d589660daffb6efd6e568e87f8fa) +++ lams_central/src/java/org/lamsfoundation/lams/web/PortraitSaveController.java (.../PortraitSaveController.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -25,6 +25,7 @@ import java.io.IOException; import java.io.InputStream; +import java.util.UUID; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -67,7 +68,7 @@ public class PortraitSaveController { private static Logger log = Logger.getLogger(PortraitSaveController.class); private static final String PORTRAIT_DELETE_AUDIT_KEY = "audit.delete.portrait"; - + @Autowired private IUserManagementService userManagementService; @Autowired @@ -126,10 +127,10 @@ // upload to the content repository originalFileNode = centralToolContentHandler.uploadFile(is, fileNameWithoutExt + "_original.jpg", - "image/jpeg"); + "image/jpeg", true); is.close(); - log.debug("saved file with uuid: " + originalFileNode.getUuid() + " and version: " - + originalFileNode.getVersion()); + log.debug("saved file with uuid: " + originalFileNode.getUuid() + " and portrait uuid " + + originalFileNode.getPortraitUuid() + " and version: " + originalFileNode.getVersion()); //resize to the large size is = ResizePictureUtil.resize(file.getInputStream(), CommonConstants.PORTRAIT_LARGEST_DIMENSION_LARGE); @@ -158,7 +159,7 @@ if (user.getPortraitUuid() != null) { centralToolContentHandler.deleteFile(user.getPortraitUuid()); } - user.setPortraitUuid(originalFileNode.getUuid()); + user.setPortraitUuid(UUID.fromString(originalFileNode.getPortraitUuid())); userManagementService.saveUser(user); return "forward:/index.do?redirect=portrait"; Index: lams_central/src/java/org/lamsfoundation/lams/web/tag/PortraitTag.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_central/src/java/org/lamsfoundation/lams/web/tag/PortraitTag.java (.../PortraitTag.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_central/src/java/org/lamsfoundation/lams/web/tag/PortraitTag.java (.../PortraitTag.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -48,18 +48,18 @@ private static final String CSS_ROUND = " portrait-round"; private static final String PORTRAIT_VERSION_SUFFIX = " portrait-color-"; - + private static final String STYLE_SMALL = "small"; - private static final String CSS_SMALL[] = {"portrait-sm", "&version=4"}; + private static final String CSS_SMALL[] = { "portrait-sm", "&version=4" }; private static final String CSS_GENERIC_SMALL = "portrait-generic-sm"; private static final String STYLE_MEDIUM = "medium"; - private static final String CSS_MEDIUM[] = {"portrait-md", "&version=3"}; + private static final String CSS_MEDIUM[] = { "portrait-md", "&version=3" }; private static final String CSS_GENERIC_MEDIUM = "portrait-generic-md"; private static final String STYLE_LARGE = "large"; - private static final String CSS_LARGE[] = {"portrait-lg", "&version=2"};; + private static final String CSS_LARGE[] = { "portrait-lg", "&version=2" };; private static final String CSS_GENERIC_LARGE = "portrait-generic-lg"; private static final String STYLE_XLARGE = "xlarge"; - private static final String CSS_XLARGE[] = {"portrait-xl", "&version=1"}; + private static final String CSS_XLARGE[] = { "portrait-xl", "&version=1" }; private static final String CSS_GENERIC_XLARGE = "portrait-generic-xl"; /* Attributes */ @@ -94,7 +94,7 @@ Integer userIdInt = Integer.decode(userId); User user = (User) getUserManagementService().findById(User.class, userIdInt); boolean isHover = (hover != null ? Boolean.valueOf(hover) : false); - if ( isHover ) { + if (isHover) { code = buildHoverUrl(user); } else { code = buildDivUrl(user); @@ -120,7 +120,7 @@ } private String buildDivUrl(User user) { - Long portraitId = user != null ? user.getPortraitUuid() : null; + String portraitId = user == null || user.getPortraitUuid() == null ? null : user.getPortraitUuid().toString(); if (portraitId != null) { boolean isRound = (round != null ? Boolean.valueOf(round) : true); String[] sizes = getSizeClass(); @@ -142,22 +142,23 @@ } private String buildHoverUrl(User user) { - Long portraitId = user != null ? user.getPortraitUuid() : null; + String portraitId = user == null || user.getPortraitUuid() == null ? null : user.getPortraitUuid().toString(); String linkText = getBodyContent() != null ? getBodyContent().getString() : null; if (portraitId != null) { String fullName = user.getFullName(); - if ( linkText == null || linkText.length() == 0) + if (linkText == null || linkText.length() == 0) { linkText = fullName; + } return new StringBuilder( "") - .append(linkText).append("").toString(); + .append("\" data-fullname=\"").append(fullName).append("\">").append(linkText) + .append("").toString(); } else { return linkText != null ? linkText : ""; } } - + private IUserManagementService getUserManagementService() { if (userManagementService == null) { WebApplicationContext ctx = WebApplicationContextUtils @@ -170,33 +171,39 @@ private HashMap getPortraitCache() { HashMap cache = (HashMap) pageContext.getAttribute("portraitCache"); if (cache == null) { - cache = new HashMap(); + cache = new HashMap<>(); pageContext.setAttribute("portraitCache", cache); } return cache; } /* Get String[size css class, version id] based on size attribute */ - private String[] getSizeClass() { + private String[] getSizeClass() { if (size != null) { - if (size.equalsIgnoreCase(STYLE_MEDIUM)) + if (size.equalsIgnoreCase(STYLE_MEDIUM)) { return CSS_MEDIUM; - if (size.equalsIgnoreCase(STYLE_LARGE)) + } + if (size.equalsIgnoreCase(STYLE_LARGE)) { return CSS_LARGE; - if (size.equalsIgnoreCase(STYLE_XLARGE)) + } + if (size.equalsIgnoreCase(STYLE_XLARGE)) { return CSS_XLARGE; + } } return CSS_SMALL; } private String getGenericSizeClass() { if (size != null) { - if (size.equalsIgnoreCase(STYLE_MEDIUM)) + if (size.equalsIgnoreCase(STYLE_MEDIUM)) { return CSS_GENERIC_MEDIUM; - if (size.equalsIgnoreCase(STYLE_LARGE)) + } + if (size.equalsIgnoreCase(STYLE_LARGE)) { return CSS_GENERIC_LARGE; - if (size.equalsIgnoreCase(STYLE_XLARGE)) + } + if (size.equalsIgnoreCase(STYLE_XLARGE)) { return CSS_GENERIC_XLARGE; + } } return CSS_GENERIC_SMALL; } Index: lams_common/src/java/org/lamsfoundation/lams/contentrepository/NodeKey.java =================================================================== diff -u -r46fe95e04d6fbe8fec9e41f054a711e23c1e064c -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_common/src/java/org/lamsfoundation/lams/contentrepository/NodeKey.java (.../NodeKey.java) (revision 46fe95e04d6fbe8fec9e41f054a711e23c1e064c) +++ lams_common/src/java/org/lamsfoundation/lams/contentrepository/NodeKey.java (.../NodeKey.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -21,7 +21,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.contentrepository; import org.apache.commons.lang.builder.EqualsBuilder; @@ -38,13 +37,15 @@ private Long uuid = null; private Long version = null; + private String portraitUuid; /** - * + * */ - public NodeKey(Long uuid, Long version) { + public NodeKey(Long uuid, Long version, String portraitUuid) { this.uuid = uuid; this.version = version; + this.portraitUuid = portraitUuid; } /** @@ -61,9 +62,14 @@ return version; } + public String getPortraitUuid() { + return portraitUuid; + } + @Override public String toString() { - return new ToStringBuilder(this).append("uuid", uuid).append("version", version).toString(); + return new ToStringBuilder(this).append("uuid", uuid).append("version", version) + .append("portraitUuid", portraitUuid).toString(); } @Override Index: lams_common/src/java/org/lamsfoundation/lams/contentrepository/client/IToolContentHandler.java =================================================================== diff -u -r9d017688cf84d7a7c26203a3b0e13a5301b9c756 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_common/src/java/org/lamsfoundation/lams/contentrepository/client/IToolContentHandler.java (.../IToolContentHandler.java) (revision 9d017688cf84d7a7c26203a3b0e13a5301b9c756) +++ lams_common/src/java/org/lamsfoundation/lams/contentrepository/client/IToolContentHandler.java (.../IToolContentHandler.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -21,11 +21,11 @@ * **************************************************************** */ - package org.lamsfoundation.lams.contentrepository.client; import java.io.IOException; import java.io.InputStream; +import java.util.UUID; import org.lamsfoundation.lams.contentrepository.NodeKey; import org.lamsfoundation.lams.contentrepository.exception.FileException; @@ -65,13 +65,16 @@ public NodeKey uploadFile(InputStream stream, String fileName, String mimeType) throws RepositoryCheckedException, InvalidParameterException, RepositoryCheckedException; + public NodeKey uploadFile(InputStream stream, String fileName, String mimeType, boolean generatePortraitUuid) + throws RepositoryCheckedException, InvalidParameterException, RepositoryCheckedException; + /** * Update an existing file in the repository. This will create a new version of this file (its version number will * be equal to the current one incremented by 1). * * @param uuid * unique id of the updated file. Mandatory - * + * * @param stream * Input filestream. Mandatory. * @param fileName @@ -91,7 +94,7 @@ /** * Save a directory of files in the content repository. - * + * * @param ticket * ticket issued on login. Identifies tool and workspace - mandatory * @param dirPath @@ -111,7 +114,7 @@ /** * Delete a file node. If the node does not exist, then nothing happens (ie ItemNotFoundException is NOT thrown). - * + * * @param uuid * id of the file node. Mandatory * @throws InvalidParameterException @@ -122,8 +125,13 @@ public void deleteFile(Long uuid) throws InvalidParameterException, RepositoryCheckedException; /** + * Delete a file node using portrait UUID + */ + public void deleteFile(UUID portraitUuid) throws InvalidParameterException, RepositoryCheckedException; + + /** * Get the file, as an inputstream. - * + * * @param uuid * id of the file node. Mandatory * @throws FileException Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20200204.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20200204.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20200204.sql (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -0,0 +1,23 @@ +SET AUTOCOMMIT = 0; +set FOREIGN_KEY_CHECKS = 0; + +-- LDEV-4962 Use complex UUIDs for user portraits + +ALTER TABLE lams_cr_node ADD COLUMN portrait_uuid BINARY(16) AFTER node_id, + ADD UNIQUE INDEX IDX_portrait_uuid (portrait_uuid); + +UPDATE lams_cr_node AS n JOIN lams_user AS u ON n.node_id = u.portrait_uuid +SET n.portrait_uuid = UUID_TO_BIN(UUID()); + +ALTER TABLE lams_user ADD COLUMN temp BINARY(16) AFTER portrait_uuid; + +UPDATE lams_cr_node AS n JOIN lams_user AS u ON n.node_id = u.portrait_uuid +SET u.temp = n.portrait_uuid; + +ALTER TABLE lams_user DROP COLUMN portrait_uuid; +ALTER TABLE lams_user RENAME COLUMN temp TO portrait_uuid; + +COMMIT; +SET AUTOCOMMIT = 1; +set FOREIGN_KEY_CHECKS = 1; + Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java =================================================================== diff -u -r1ee503e3d0e0228ea8a45025fddf15d9623c0377 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java (.../User.java) (revision 1ee503e3d0e0228ea8a45025fddf15d9623c0377) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java (.../User.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -30,6 +30,7 @@ import java.util.LinkedHashSet; import java.util.Set; import java.util.TimeZone; +import java.util.UUID; import javax.persistence.CascadeType; import javax.persistence.Column; @@ -162,7 +163,7 @@ private AuthenticationMethod authenticationMethod; @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) - private Set userOrganisations = new HashSet(); + private Set userOrganisations = new HashSet<>(); @Column(name = "last_visited_organisation_id") private Integer lastVisitedOrganisationId; @@ -173,16 +174,16 @@ @OneToMany(mappedBy = "user") @LazyCollection(LazyCollectionOption.EXTRA) - private Set learnerProgresses = new HashSet(); + private Set learnerProgresses = new HashSet<>(); @OneToMany(mappedBy = "user") - private Set learningDesigns = new HashSet(); + private Set learningDesigns = new HashSet<>(); @OneToMany(mappedBy = "user") - private Set lessons = new HashSet(); + private Set lessons = new HashSet<>(); @Column(name = "portrait_uuid") - private Long portraitUuid; + private UUID portraitUuid; @Column(name = "change_password") private Boolean changePassword; @@ -194,7 +195,7 @@ @JoinTable(name = "lams_planner_recent_learning_designs", joinColumns = @JoinColumn(name = "user_id")) @Column(name = "learning_design_id") @OrderBy("learning_design_id") - private Set recentlyModifiedLearningDesigns = new LinkedHashSet(); + private Set recentlyModifiedLearningDesigns = new LinkedHashSet<>(); @Column(name = "modified_date") private Date modifiedDate; @@ -522,7 +523,7 @@ return new UserDTO(userId, firstName, lastName, login, languageIsoCode, countryIsoCode, direction, email, theme != null ? new ThemeDTO(theme) : null, timeZone, authenticationMethod.getAuthenticationMethodId(), fckLanguageMapping, (firstLogin == null || firstLogin ? true : false), // assume no firstLogin value means they haven't logged in - lastVisitedOrganisationId, portraitUuid); + lastVisitedOrganisationId, portraitUuid == null ? null : portraitUuid.toString()); } public UserBasicDTO getUserBasicDTO() { @@ -590,11 +591,11 @@ this.locale = locale; } - public Long getPortraitUuid() { + public UUID getPortraitUuid() { return portraitUuid; } - public void setPortraitUuid(Long portraitUuid) { + public void setPortraitUuid(UUID portraitUuid) { this.portraitUuid = portraitUuid; } Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/dao/hibernate/UserDAO.java =================================================================== diff -u -r62aaf160878735888d077bf28fac3c1989bb8fbd -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/dao/hibernate/UserDAO.java (.../UserDAO.java) (revision 62aaf160878735888d077bf28fac3c1989bb8fbd) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/dao/hibernate/UserDAO.java (.../UserDAO.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.UUID; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; @@ -82,17 +83,16 @@ List list = query.list(); //group by userId as long as it returns all completed visitLogs for each user - List userDtos = new ArrayList(); + List userDtos = new ArrayList<>(); for (Object[] element : list) { Integer userId = ((Number) element[0]).intValue(); String login = (String) element[1]; String firstName = (String) element[2]; String lastName = (String) element[3]; String email = (String) element[4]; - Long portraitUuid = element[5] != null ? ((Number) element[5]).longValue() : null; - + byte[] portraitUuid = (byte[]) element[5]; UserDTO userDto = new UserDTO(userId, firstName, lastName, login, null, null, null, email, null, null, null, - null, false, null, portraitUuid); + null, false, null, portraitUuid == null ? null : UUID.nameUUIDFromBytes(portraitUuid).toString()); userDtos.add(userDto); } Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/dto/UserDTO.java =================================================================== diff -u -r62aaf160878735888d077bf28fac3c1989bb8fbd -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/dto/UserDTO.java (.../UserDTO.java) (revision 62aaf160878735888d077bf28fac3c1989bb8fbd) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/dto/UserDTO.java (.../UserDTO.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -50,12 +50,12 @@ private Integer authenticationMethodId; private Boolean firstLogin; private Integer lastVisitedOrganisationId; - private Long portraitUuid; + private String portraitUuid; public UserDTO(Integer userID, String firstName, String lastName, String login, String localeLanguage, String localeCountry, String direction, String email, ThemeDTO htmlTheme, TimeZone timezone, Integer authenticationMethodId, String fckLanguageMapping, Boolean firstLogin, - Integer lastVisitedOrganisationId, Long portraitUuid) { + Integer lastVisitedOrganisationId, String portraitUuid) { this.userID = userID; this.firstName = firstName; this.lastName = lastName; @@ -183,11 +183,11 @@ return lastVisitedOrganisationId; } - public Long getPortraitUuid() { + public String getPortraitUuid() { return portraitUuid; } - public void setPortraitUuid(Long portraitUuid) { + public void setPortraitUuid(String portraitUuid) { this.portraitUuid = portraitUuid; } } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java =================================================================== diff -u -rebb598b9d631fa479aef19110dc7b8c2cce0575b -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision ebb598b9d631fa479aef19110dc7b8c2cce0575b) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -39,6 +39,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.Vector; import java.util.stream.Collectors; @@ -306,7 +307,7 @@ } return true; } - + @Override public Organisation getOrganisationById(Integer organisationId) { return (Organisation) findById(Organisation.class, organisationId); @@ -371,7 +372,7 @@ properties.put("organisation.parentOrganisation.organisationId", parentOrgId); return baseDAO.findByProperties(UserOrganisation.class, properties); } - + @Override public UserOrganisationCollapsed getUserOrganisationCollapsed(Integer userId, Integer orgId) { Map properties = new HashMap<>(); @@ -380,9 +381,10 @@ List results = baseDAO.findByProperties(UserOrganisationCollapsed.class, properties); return results.isEmpty() ? null : (UserOrganisationCollapsed) results.get(0); } - + @Override - public List getChildOrganisationsCollapsedByUser(Integer parentOrganisationId, Integer userId) { + public List getChildOrganisationsCollapsedByUser(Integer parentOrganisationId, + Integer userId) { return organisationDAO.getChildOrganisationsCollapsedByUser(parentOrganisationId, userId); } @@ -1128,7 +1130,7 @@ FileInputStream is = new FileInputStream(portraitFile); String fileNameWithoutExt = login; NodeKey originalFileNode = centralToolContentHandler.uploadFile(is, - fileNameWithoutExt + "_original.jpg", "image/jpeg"); + fileNameWithoutExt + "_original.jpg", "image/jpeg", true); is.close(); log.debug("Saved original portrait with uuid: " + originalFileNode.getUuid() + " and version: " + originalFileNode.getVersion()); @@ -1175,7 +1177,7 @@ if (user.getPortraitUuid() != null) { centralToolContentHandler.deleteFile(user.getPortraitUuid()); } - user.setPortraitUuid(originalFileNode.getUuid()); + user.setPortraitUuid(UUID.fromString(originalFileNode.getPortraitUuid())); saveUser(user); log.info("Uploaded portrait for user " + userId + " with login \"" + login + "\""); Index: lams_common/src/java/org/lamsfoundation/lams/util/WebUtil.java =================================================================== diff -u -r40de3afab4e8d589660daffb6efd6e568e87f8fa -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_common/src/java/org/lamsfoundation/lams/util/WebUtil.java (.../WebUtil.java) (revision 40de3afab4e8d589660daffb6efd6e568e87f8fa) +++ lams_common/src/java/org/lamsfoundation/lams/util/WebUtil.java (.../WebUtil.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -9,19 +9,14 @@ import java.util.HashMap; import java.util.Map.Entry; -import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; -import org.lamsfoundation.lams.learning.service.ILearnerService; -import org.lamsfoundation.lams.learningdesign.dto.ActivityPositionDTO; import org.lamsfoundation.lams.tool.ToolAccessMode; import org.lamsfoundation.lams.tool.exception.ToolException; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.web.util.AttributeNames; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.context.support.WebApplicationContextUtils; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -481,7 +476,8 @@ * @throws ToolException * @throws IOException */ - public static InputStream getResponseInputStreamFromExternalServer(String urlStr, HashMap params) throws IOException { + public static InputStream getResponseInputStreamFromExternalServer(String urlStr, HashMap params) + throws IOException { if (!urlStr.contains("?")) { urlStr += "?"; } @@ -537,7 +533,7 @@ userJSON.put("firstName", user.getFirstName()); userJSON.put("lastName", user.getLastName()); userJSON.put("login", user.getLogin()); - userJSON.put("portraitId", user.getPortraitUuid()); + userJSON.put("portraitId", user.getPortraitUuid() == null ? null : user.getPortraitUuid().toString()); return userJSON; } Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/CrNode.java =================================================================== diff -u -r1ee503e3d0e0228ea8a45025fddf15d9623c0377 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/CrNode.java (.../CrNode.java) (revision 1ee503e3d0e0228ea8a45025fddf15d9623c0377) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/CrNode.java (.../CrNode.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -21,7 +21,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.contentrepository; import java.io.Serializable; @@ -31,6 +30,7 @@ import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; +import java.util.UUID; import javax.persistence.CascadeType; import javax.persistence.Column; @@ -57,6 +57,9 @@ @GeneratedValue(strategy = GenerationType.IDENTITY) private Long nodeId; + @Column(name = "portrait_uuid") + private UUID portraitUuid; + @Column private String path; @@ -69,18 +72,15 @@ @Column(name = "next_version_id") private Long nextVersionId; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "workspace_id") + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "workspace_id") private org.lamsfoundation.lams.contentrepository.CrWorkspace crWorkspace; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "parent_nv_id") + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "parent_nv_id") private org.lamsfoundation.lams.contentrepository.CrNodeVersion parentNodeVersion; - @OneToMany(mappedBy = "node", - cascade = CascadeType.ALL, - orphanRemoval = true, - fetch = FetchType.EAGER) + @OneToMany(mappedBy = "node", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) private Set crNodeVersions; /** default constructor - used by Hibernate */ @@ -133,6 +133,14 @@ this.nodeId = nodeId; } + public UUID getPortraitUuid() { + return portraitUuid; + } + + public void setPortraitUuid(UUID portraitUuid) { + this.portraitUuid = portraitUuid; + } + public String getPath() { return this.path; } @@ -192,7 +200,7 @@ /** Add a version to this node */ public void addCrNodeVersion(CrNodeVersion version) { if (getCrNodeVersions() == null) { - Set set = new HashSet(); + Set set = new HashSet<>(); set.add(version); setCrNodeVersions(set); } else { @@ -264,12 +272,12 @@ * Get the history for this node. Quite intensive operation * as it has to build all the data structures. Can't cache * it as can't tell easily when the versions are changed. - * + * * @return SortedSet of IVersionDetail objects, ordered by version */ public SortedSet getVersionHistory() { - SortedSet history = new TreeSet(); + SortedSet history = new TreeSet<>(); Set versions = getCrNodeVersions(); if (versions != null) { @@ -285,7 +293,7 @@ /** * Indicates whether this node is of the specified node type. - * + * * @param nodeTypeName * the name of a node type. * @return true if this node is of the specified node type Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/IVersionedNode.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/IVersionedNode.java (.../IVersionedNode.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/IVersionedNode.java (.../IVersionedNode.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -21,7 +21,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.contentrepository; import java.io.InputStream; @@ -62,14 +61,14 @@ /** * Returns an Set of all child nodes of node. Returns an empty * set if no nodes found. - * + * * @return Set of nodes. */ public Set getChildNodes(); /** * Does this node have a parent node? - * + * * @return boolean */ public boolean hasParentNode(); @@ -120,6 +119,8 @@ */ public Long getUUID(); + public String getPortraitUuid(); + /** * Indicates whether a property exists for this name * Returns true if a property exists and false otherwise. @@ -211,23 +212,23 @@ /** * Get the date/time of when this node was created. - * + * * @return date/time stamp of creation */ public Date getCreatedDateTime(); /** * Get the file, as an inputstream. It is the responsibility * of the caller to close the stream. - * + * * If the node is a package node, it will get the input stream * of the first file. */ public InputStream getFile() throws FileException; /** * Get the user_id of the user who created this node. - * + * * @return userId */ public Integer getUserId(); Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/Download.java =================================================================== diff -u -r1e26200cec472e799b29f548270b1a67027e9167 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/Download.java (.../Download.java) (revision 1e26200cec472e799b29f548270b1a67027e9167) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/Download.java (.../Download.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -138,8 +138,6 @@ private void handleCall(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, RepositoryCheckedException { - long start = System.currentTimeMillis(); - ITicket ticket = null; String toolContentHandlerName = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_HANDLER_NAME); if (StringUtils.isBlank(toolContentHandlerName)) { @@ -152,18 +150,15 @@ throw new RepositoryCheckedException("Unable to get ticket - getTicket(false) returned null"); } - Long uuid = Download.getLong(request.getParameter(Download.UUID_NAME)); + String uuid = request.getParameter(Download.UUID_NAME); Long version = null; boolean saveFile = Download.getBoolean(request.getParameter(Download.PREFER_DOWNLOAD)); - String callId = null; - if (uuid != null) { version = Download.getLong(request.getParameter(Download.VERSION_NAME)); - - IVersionedNode node = getFileItem(ticket, uuid, version, null); - + IVersionedNode node = uuid.contains("-") ? getRepositoryService().getFileItem(ticket, uuid, version) + : getRepositoryService().getFileItem(ticket, Long.valueOf(uuid), version); // update versionId in case it was null and we got the latest version... version = node.getVersion(); @@ -200,12 +195,10 @@ // using the /download// format - must be a file node! String pathString = request.getPathInfo(); String[] strings = deriveIdFile(pathString); - uuid = Download.getLong(strings[0]); + uuid = strings[0]; version = Download.getLong(strings[1]); String relPathString = strings[2]; - callId = "download " + Math.random() + " " + uuid; - if (uuid == null) { throw new RepositoryCheckedException("UUID value is missing. " + Download.expectedFormat); } @@ -218,7 +211,8 @@ throw new RepositoryCheckedException("Filename is missing. " + Download.expectedFormat); } - IVersionedNode node = getFileItem(ticket, uuid, version, relPathString); + IVersionedNode node = uuid.contains("-") ? getRepositoryService().getFileItem(ticket, uuid, version) + : getRepositoryService().getFileItem(ticket, Long.valueOf(uuid), version); if (!node.isNodeType(NodeType.FILENODE)) { throw new RepositoryCheckedException( "Unexpected type of node " + node.getNodeType() + " Expected File node. Data is " + node); @@ -229,29 +223,6 @@ } /** - * The call getFileItem was throwing a runtime hibernate/jdbc error when being thrash tested, and I couldn't work - * out the context, so I've wrapped the call here so it can be debugged. - */ - private IVersionedNode getFileItem(ITicket ticket, Long uuid, Long version, String relPathString) - throws RepositoryCheckedException { - try { - IVersionedNode node = null; - if (relPathString != null) { - // get file in package - node = getRepositoryService().getFileItem(ticket, uuid, version, relPathString); - } else { - // get node - node = getRepositoryService().getFileItem(ticket, uuid, version); - } - return node; - } catch (RuntimeException e) { - Download.log.error("Exception thrown calling repository.getFileItem(," + uuid + "," + version + "," - + relPathString + "). " + e.getMessage(), e); - throw e; - } - } - - /** * @param response * @param aNode * @throws IOException Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/ToolContentHandler.java =================================================================== diff -u -r62aaf160878735888d077bf28fac3c1989bb8fbd -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/ToolContentHandler.java (.../ToolContentHandler.java) (revision 62aaf160878735888d077bf28fac3c1989bb8fbd) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/ToolContentHandler.java (.../ToolContentHandler.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -21,11 +21,11 @@ * **************************************************************** */ - package org.lamsfoundation.lams.contentrepository.client; import java.io.IOException; import java.io.InputStream; +import java.util.UUID; import org.apache.log4j.Logger; import org.lamsfoundation.lams.contentrepository.ICredentials; @@ -64,7 +64,7 @@ * Content Repository's applicationContext.xml. The name must be unique to this project. * * For example: - * + * *
  * 	<bean id="blahToolContentHandler" class="your class name here">
  * 		<property name="repositoryService"> <ref bean="repositoryService"/</property>
@@ -84,7 +84,7 @@
  * 
  • IVersionedNode getFileNode(Long uuid)
    * Gets the file node from the repository. To get the file stream, do getFileNode().getFile() * For example:
    - * + * *
      * NodeKey nodeKey = handler.uploadFile(istream, fileName, fileMimeType);
    * Long uuid = nodeKey.getUuid();
    @@ -111,7 +111,7 @@ private IRepositoryService repositoryService; private ITicket ticket; - + private String repositoryWorkspaceName; private String repositoryUser; private String repositoryId; @@ -125,7 +125,7 @@ } return repositoryWorkspaceName; } - + public void setRepositoryWorkspaceName(String repositoryWorkspaceName) { this.repositoryWorkspaceName = repositoryWorkspaceName; } @@ -135,9 +135,9 @@ log.error( "Accessing ToolContentHandler bean, but repositoryUser has not been defined. Please define this property in ApplicationContext.xml"); } - return repositoryUser; + return repositoryUser; } - + public void setRepositoryUser(String repositoryUser) { this.repositoryUser = repositoryUser; } @@ -147,9 +147,9 @@ log.error( "Accessing ToolContentHandler bean, but repositoryWorkspaceName has not been defined. Please define this property in ApplicationContext.xml"); } - return repositoryId.toCharArray(); + return repositoryId.toCharArray(); } - + public void setRepositoryId(String repositoryId) { this.repositoryId = repositoryId; } @@ -162,7 +162,7 @@ // make sure workspace exists - sometimes it does not get created when creating a ticket cred = new SimpleCredentials(getRepositoryUser(), getRepositoryId()); doLogin = !repositoryService.workspaceExists(cred, getRepositoryWorkspaceName()); - } + } if (doLogin) { if (cred == null) { cred = new SimpleCredentials(getRepositoryUser(), getRepositoryId()); @@ -173,16 +173,18 @@ } @Override - public NodeKey uploadFile(InputStream stream, String fileName, String mimeType) + public NodeKey uploadFile(InputStream stream, String fileName, String mimeType, boolean generatePortraitUuid) throws RepositoryCheckedException, InvalidParameterException, RepositoryCheckedException { NodeKey nodeKey = null; try { try { - nodeKey = repositoryService.addFileItem(getTicket(false), stream, fileName, mimeType, null); + nodeKey = repositoryService.addFileItem(getTicket(false), stream, fileName, mimeType, null, + generatePortraitUuid); } catch (AccessDeniedException e) { log.warn("Unable to access repository to add file " + fileName + "AccessDeniedException: " + e.getMessage() + " Retrying login."); - nodeKey = repositoryService.addFileItem(getTicket(true), stream, fileName, mimeType, null); + nodeKey = repositoryService.addFileItem(getTicket(true), stream, fileName, mimeType, null, + generatePortraitUuid); } } catch (RepositoryCheckedException e2) { @@ -193,8 +195,14 @@ return nodeKey; } - + @Override + public NodeKey uploadFile(InputStream stream, String fileName, String mimeType) + throws RepositoryCheckedException, InvalidParameterException, RepositoryCheckedException { + return uploadFile(stream, fileName, mimeType, false); + } + + @Override public NodeKey updateFile(Long uuid, InputStream stream, String fileName, String mimeType) throws RepositoryCheckedException, InvalidParameterException, RepositoryCheckedException { NodeKey nodeKey = null; @@ -229,7 +237,7 @@ /** * Save a directory of files in the content repository. - * + * * @param ticket * ticket issued on login. Identifies tool and workspace - mandatory * @param dirPath @@ -354,6 +362,25 @@ } @Override + public void deleteFile(UUID portraitUuid) throws InvalidParameterException, RepositoryCheckedException { + try { + try { + repositoryService.deleteNode(getTicket(false), portraitUuid); + } catch (AccessDeniedException e) { + log.warn("Unable to access repository to delete file id" + portraitUuid + "AccessDeniedException: " + + e.getMessage() + " Retrying login."); + repositoryService.deleteNode(getTicket(true), portraitUuid); + } + } catch (ItemNotFoundException e1) { + // didn't exist so don't need to delete. Ignore problem. + } catch (RepositoryCheckedException e2) { + log.error("Unable delete file id" + portraitUuid + "Repository Exception: " + e2.getMessage() + + " Retry not possible."); + throw e2; + } + } + + @Override public InputStream getFileInputStream(Long uuid) throws ItemNotFoundException, FileException, RepositoryCheckedException { try { @@ -387,7 +414,7 @@ * out.flush(); * return file; * } - * + * * protected byte[] getBytes(File file) throws FileNotFoundException, Exception { * byte[] byteArray = new byte[(int) file.length()]; * FileInputStream stream = new FileInputStream(file); Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/INodeFactory.java =================================================================== diff -u -rea80430beb4497f12c92db2580341f21750a5a43 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/INodeFactory.java (.../INodeFactory.java) (revision ea80430beb4497f12c92db2580341f21750a5a43) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/INodeFactory.java (.../INodeFactory.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -21,10 +21,10 @@ * **************************************************************** */ - package org.lamsfoundation.lams.contentrepository.service; import java.io.InputStream; +import java.util.UUID; import org.lamsfoundation.lams.contentrepository.CrNode; import org.lamsfoundation.lams.contentrepository.CrWorkspace; @@ -43,7 +43,7 @@ /** * Create a new file node (which is assumed to be a newly created Spring * bean) with relPath and node type. - * + * * @param relPath * The path of the new Node that is to be created, * the last item of this path will be the name of the new Node. @@ -54,12 +54,13 @@ */ public abstract SimpleVersionedNode createFileNode(CrWorkspace workspace, SimpleVersionedNode parentNode, String relPath, InputStream istream, String filename, String mimeType, String versionDescription, - Integer userId) throws org.lamsfoundation.lams.contentrepository.exception.InvalidParameterException; + Integer userId, boolean generatePortraitUuid) + throws org.lamsfoundation.lams.contentrepository.exception.InvalidParameterException; /** * Create a new package node (which is assumed to be a newly created Spring * bean) with the default file and node type. Package node cannot have a parent node. - * + * * @param initialPath * The path of the default content. * @throws org.lamsfoundation.lams.contentrepository.exception.InvalidParameterException @@ -74,7 +75,7 @@ /** * Create a new data node (which is assumed to be a newly created Spring * bean). This node may have a parent node. - * + * * @throws org.lamsfoundation.lams.contentrepository.exception.InvalidParameterException * if the file parameters are invalid * @throws RepositoryRuntimeException @@ -87,7 +88,7 @@ /** * Build a SimpleVersionedNode, given a CrNode from the database. If versionId == null * then gets the latest version. - * + * * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#getNode(String relPath) */ public abstract SimpleVersionedNode getNode(CrNode databaseNode, Long versionId); @@ -97,17 +98,20 @@ * Creates the CrNode and CrNodeVersion objects. * Equivalent of createFileNode/createPackageNode for existing nodes * Checks that the workspace found in the database is the expected workspace. - * + * * If this node object is returned to a web app, then the * crNode and crNodeVersion objects will be disconnected * from the session, as the session will have been ended * with the Spring transaction. - * + * * If versionId is null, then gets the latest version */ public abstract SimpleVersionedNode getNode(Long workspaceId, Long uuid, Long versionId) throws ItemNotFoundException; + public abstract SimpleVersionedNode getNode(Long workspaceId, UUID portraitUuid, Long versionId) + throws ItemNotFoundException; + /** * Build a SimpleVersionedNode, reading the data from the database. * Creates a new (empty) version ready for updating. @@ -118,9 +122,9 @@ * crNode and crNodeVersion objects will be disconnected * from the session, as the session will have been ended * with the Spring transaction. - * + * * @throws ItemNotFoundException - * + * * @throws RepositoryRuntimeException * if an internal error occurs. * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#createNewVersion(java.lang.String, @@ -132,11 +136,11 @@ /** * Copy the supplied node/version to a new node. Does not copy the history * of the node. Copies any child nodes of the current version. All files are duplicated. - * + * * This method only works as we know that we have two levels of nodes - the * childNodes can't have their own childNodes. If this is no longer the case, * this method and SimpleVersionedNode.save() will need to be changed. - * + * * @throws FileException * will occur if there is a problem reading a file from the repository * @throws InvalidParameterException Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/IRepositoryService.java =================================================================== diff -u -rea80430beb4497f12c92db2580341f21750a5a43 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/IRepositoryService.java (.../IRepositoryService.java) (revision ea80430beb4497f12c92db2580341f21750a5a43) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/IRepositoryService.java (.../IRepositoryService.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -28,6 +28,7 @@ import java.util.List; import java.util.SortedMap; import java.util.SortedSet; +import java.util.UUID; import org.lamsfoundation.lams.contentrepository.CrWorkspace; import org.lamsfoundation.lams.contentrepository.ICredentials; @@ -170,7 +171,8 @@ * if any internal errors have occured */ public abstract NodeKey addFileItem(ITicket ticket, InputStream istream, String filename, String mimeType, - String versionDescription) throws FileException, AccessDeniedException, InvalidParameterException; + String versionDescription, boolean generatePortraitUuid) + throws FileException, AccessDeniedException, InvalidParameterException; /** * Add a new package of files to the repository. If startFile @@ -329,6 +331,9 @@ public abstract IVersionedNode getFileItem(ITicket ticket, Long uuid, Long version) throws AccessDeniedException, ItemNotFoundException, FileException; + IVersionedNode getFileItem(ITicket ticket, String portraitUuid, Long version) + throws AccessDeniedException, ItemNotFoundException, FileException; + /** * Get an item from the repository based on the UUID and relative * path. Only used to get the content from a package. The @@ -441,6 +446,9 @@ public String[] deleteNode(ITicket ticket, Long uuid) throws AccessDeniedException, InvalidParameterException, ItemNotFoundException; + public String[] deleteNode(ITicket ticket, UUID portraitUuid) + throws AccessDeniedException, InvalidParameterException, ItemNotFoundException; + /** * Finish using this ticket. No more updates may be used with this ticket * after logout(). Allows any resources to be freed. Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/NodeFactory.java =================================================================== diff -u -rea80430beb4497f12c92db2580341f21750a5a43 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/NodeFactory.java (.../NodeFactory.java) (revision ea80430beb4497f12c92db2580341f21750a5a43) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/NodeFactory.java (.../NodeFactory.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -21,13 +21,14 @@ * **************************************************************** */ - package org.lamsfoundation.lams.contentrepository.service; import java.io.InputStream; import java.util.Date; import java.util.Iterator; +import java.util.List; import java.util.Set; +import java.util.UUID; import org.apache.log4j.Logger; import org.lamsfoundation.lams.contentrepository.CrNode; @@ -68,26 +69,27 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#createFileNode(org.lamsfoundation.lams. * contentrepository.CrWorkspace, org.lamsfoundation.lams.contentrepository.service.SimpleVersionedNode, * java.lang.String, java.io.InputStream, java.lang.String, java.lang.String, java.lang.String) */ @Override public SimpleVersionedNode createFileNode(CrWorkspace workspace, SimpleVersionedNode parentNode, String relPath, - InputStream istream, String filename, String mimeType, String versionDescription, Integer userId) + InputStream istream, String filename, String mimeType, String versionDescription, Integer userId, + boolean generatePortraitUuid) throws org.lamsfoundation.lams.contentrepository.exception.InvalidParameterException { SimpleVersionedNode initialNodeVersion = createBasicNode(NodeType.FILENODE, workspace, parentNode, relPath, - versionDescription, userId); + versionDescription, userId, generatePortraitUuid); initialNodeVersion.setFile(istream, filename, mimeType); return initialNodeVersion; } /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#createPackageNode(org.lamsfoundation.lams. * contentrepository.CrWorkspace, java.lang.String, java.lang.String) */ @@ -96,15 +98,15 @@ Integer userId) throws org.lamsfoundation.lams.contentrepository.exception.InvalidParameterException { SimpleVersionedNode initialNodeVersion = createBasicNode(NodeType.PACKAGENODE, workspace, null, null, - versionDescription, userId); + versionDescription, userId, false); initialNodeVersion.setProperty(PropertyName.INITIALPATH, initialPath); return initialNodeVersion; } /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#createDataNode(org.lamsfoundation.lams. * contentrepository.CrWorkspace, org.lamsfoundation.lams.contentrepository.service.SimpleVersionedNode, * java.lang.String) @@ -115,21 +117,24 @@ throws org.lamsfoundation.lams.contentrepository.exception.InvalidParameterException { SimpleVersionedNode initialNodeVersion = createBasicNode(NodeType.DATANODE, workspace, parentNode, null, - versionDescription, userId); + versionDescription, userId, false); return initialNodeVersion; } /** Create the core part of a node */ private SimpleVersionedNode createBasicNode(String nodeType, CrWorkspace workspace, SimpleVersionedNode parentNode, - String relPath, String versionDescription, Integer userId) { + String relPath, String versionDescription, Integer userId, boolean generatePortraitUuid) { SimpleVersionedNode initialNodeVersion = beanFactory.getBean("node", SimpleVersionedNode.class); Date createdDate = new Date(System.currentTimeMillis()); CrNodeVersion parentNodeVersion = parentNode != null ? parentNode.getNodeVersion() : null; CrNode node = new CrNode(relPath, nodeType, createdDate, userId, workspace, parentNodeVersion, versionDescription); + if (generatePortraitUuid) { + node.setPortraitUuid(UUID.randomUUID()); + } CrNodeVersion nodeVersion = node.getNodeVersion(null); initialNodeVersion.setNode(node); @@ -144,7 +149,7 @@ /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.service.INodeFactory#getNode(org.lamsfoundation.lams.contentrepository. * CrNode, java.lang.Long) @@ -159,7 +164,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#getNode(java.lang.Long, java.lang.Long, * java.lang.Long) */ @@ -192,9 +197,39 @@ return getNode(node, versionId); } + @Override + public SimpleVersionedNode getNode(Long workspaceId, UUID portraitUuid, Long versionId) + throws ItemNotFoundException { + + if (portraitUuid == null) { + throw new ItemNotFoundException("UUID is null, unable to find node."); + } + + if (workspaceId == null) { + throw new ItemNotFoundException("Workspace Id is null, unable to find node."); + } + + CrNode node = null; + List result = nodeDAO.findByProperty(CrNode.class, "portraitUuid", portraitUuid); + node = result.isEmpty() ? null : result.get(0); + if (node == null) { + + throw new ItemNotFoundException("Node " + portraitUuid + " not found."); + + } else if (!workspaceId.equals(node.getCrWorkspace().getWorkspaceId())) { + + log.error("Security warning. User of workspace " + workspaceId + " is trying to access node " + portraitUuid + + " which is in workspace " + node.getCrWorkspace().getWorkspaceId() + + " Request for node will be rejected."); + throw new ItemNotFoundException("Node " + portraitUuid + " does not exist in workspace " + workspaceId); + } + + return getNode(node, versionId); + } + /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#getNode(java.lang.Long, java.lang.Long, * java.lang.Long, java.lang.String) */ @@ -220,7 +255,7 @@ /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.service.INodeFactory#copy(org.lamsfoundation.lams.contentrepository. * service.SimpleVersionedNode) @@ -235,7 +270,7 @@ /** * Private method to handle the recursive copy. The parent node is needed to set up the * node -> parent link in the CrNode object. - * + * * @param originalNode * @param parentNode * @return new Node @@ -268,7 +303,7 @@ } } - // copy any attached file. don't actually copy the file - set up + // copy any attached file. don't actually copy the file - set up // and input stream and the file will be copied when the node is saved. // this is likely to recopy the Filename and Mimetype properties. if (originalNode.isNodeType(NodeType.FILENODE)) { @@ -300,7 +335,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#getNodeDAO() */ @Override @@ -310,7 +345,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#setNodeDAO(org.lamsfoundation.lams. * contentrepository.dao.INodeDAO) */ @@ -322,7 +357,7 @@ /* **** Method for BeanFactoryAware interface *****************/ /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.service.INodeFactory#setBeanFactory(org.springframework.beans.factory. * BeanFactory) Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/SimpleRepository.java =================================================================== diff -u -rea80430beb4497f12c92db2580341f21750a5a43 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/SimpleRepository.java (.../SimpleRepository.java) (revision ea80430beb4497f12c92db2580341f21750a5a43) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/SimpleRepository.java (.../SimpleRepository.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -21,7 +21,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.contentrepository.service; import java.io.FileNotFoundException; @@ -37,6 +36,7 @@ import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; +import java.util.UUID; import javax.servlet.http.HttpSession; @@ -87,7 +87,7 @@ * run separately and without suitable AOP support then * each transaction method must check that the credential is okay * or that the ticket is a known ticket (isTicketOkay() method). - * + * * This class also depends on the transactions defined in the * application context for the hibernate sessions to work properly. * If the method isn't transactioned, then there won't be a proper @@ -134,10 +134,10 @@ } return user.getUserID(); } - throw new AccessDeniedException( - "Cannot get user details for content repository. No session found - user not logged in or the webservice call has not set up the session details."); + throw new AccessDeniedException( + "Cannot get user details for content repository. No session found - user not logged in or the webservice call has not set up the session details."); - } + } /** * @param workspaceId @@ -155,7 +155,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IRepository#login(org.lamsfoundation.lams.contentrepository. * ICredentials, java.lang.String) */ @@ -182,7 +182,7 @@ } // okay, we should now be able to create a ticket - // make ticket, create new credentials without the password + // make ticket, create new credentials without the password ITicket ticket = new SimpleTicket(workspace.getWorkspaceId()); ticketIdSet.add(ticket.getTicketId()); return ticket; @@ -191,7 +191,7 @@ /** * Add a workspace, giving the credentials as the user of this workspace. * It does not clear the password in the credentials - * + * * @param credentials * this user/password must already exist in the repository. Password will be checked. * @param workspaceName @@ -266,7 +266,7 @@ * The password must be at least 6 chars. * Possibly this should only be available to an internal management tool * *** Security Risk - I'm converting the password to a string... *** - * + * * @throws LoginException * if the oldCredential fails login test (e.g. wrong password) * @throws RepositoryCheckedException @@ -304,9 +304,9 @@ /** * Checks that a password meets our password criteria. This could be implemented * as a Strategy, but that's overkill! - * + * * Checks that the password is six or more characters. - * + * * @param password * @throws RepositoryCheckedException * if @@ -404,7 +404,7 @@ /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.IRepository#logout(org.lamsfoundation.lams.contentrepository.ITicket) */ @@ -426,19 +426,20 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IRepository#addFileItem(org.lamsfoundation.lams.contentrepository. * ITicket, java.io.InputStream, java.lang.String, java.lang.String, java.lang.String) */ @Override public NodeKey addFileItem(ITicket ticket, InputStream istream, String filename, String mimeType, - String versionDescription) throws FileException, AccessDeniedException, InvalidParameterException { + String versionDescription, boolean generatePortraitUUid) + throws FileException, AccessDeniedException, InvalidParameterException { try { CrWorkspace workspace = getWorkspace(ticket.getWorkspaceId()); Integer userId = getCurrentUserId(); SimpleVersionedNode initialNodeVersion = nodeFactory.createFileNode(workspace, null, null, istream, - filename, mimeType, versionDescription, userId); + filename, mimeType, versionDescription, userId, generatePortraitUUid); initialNodeVersion.save(); return initialNodeVersion.getNodeKey(); } catch (ValidationException e) { @@ -452,7 +453,7 @@ /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.IRepository#addPackageItem(org.lamsfoundation.lams.contentrepository. * ITicket, java.lang.String, java.lang.String, java.lang.String) @@ -486,7 +487,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IRepository#getFileItem(org.lamsfoundation.lams.contentrepository. * ITicket, java.lang.Long, java.lang.Long) */ @@ -497,9 +498,15 @@ return nodeFactory.getNode(ticket.getWorkspaceId(), uuid, version); } + @Override + public IVersionedNode getFileItem(ITicket ticket, String portraitUuid, Long version) + throws AccessDeniedException, ItemNotFoundException, FileException { + return nodeFactory.getNode(ticket.getWorkspaceId(), UUID.fromString(portraitUuid), version); + } + /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IRepository#getFileItem(org.lamsfoundation.lams.contentrepository. * ITicket, java.lang.Long, java.lang.Long, java.lang.String) */ @@ -530,7 +537,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IRepository#getFileItem(org.lamsfoundation.lams.contentrepository. * ITicket, java.lang.Long, java.lang.Long, java.lang.String) */ @@ -556,7 +563,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IRepository#getNodeList(org.lamsfoundation.lams.contentrepository. * ITicket) */ @@ -582,7 +589,7 @@ /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.IRepository#getVersionHistory(org.lamsfoundation.lams.contentrepository * .ITicket, java.lang.Long) @@ -596,7 +603,7 @@ /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.IRepository#updateFileItem(org.lamsfoundation.lams.contentrepository. * ITicket, java.lang.Long, java.lang.String, java.io.InputStream, java.lang.String, java.lang.String) @@ -627,7 +634,7 @@ /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.IRepository#updatePackageItem(org.lamsfoundation.lams.contentrepository * .ITicket, java.lang.Long, java.lang.String, java.lang.String, java.lang.String) @@ -690,7 +697,7 @@ /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.IRepository#copyNodeVersion(org.lamsfoundation.lams.contentrepository. * ITicket, java.lang.Long, java.lang.Long) @@ -723,7 +730,7 @@ /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.IRepository#saveFile(org.lamsfoundation.lams.contentrepository.ITicket, * java.lang.Long, java.lang.String, java.lang.String, java.lang.String) @@ -804,7 +811,7 @@ /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.IRepository#updatePackageItem(org.lamsfoundation.lams.contentrepository * .ITicket, java.lang.Long, java.lang.String, java.lang.String, java.lang.String) @@ -828,9 +835,28 @@ } + @Override + public String[] deleteNode(ITicket ticket, UUID portraitUuid) + throws AccessDeniedException, InvalidParameterException, ItemNotFoundException { + + if (portraitUuid == null) { + throw new InvalidParameterException("UUID is required for deleteItem."); + } + + // get the first version of the node and delete from there. + SimpleVersionedNode latestNodeVersion = nodeFactory.getNode(ticket.getWorkspaceId(), portraitUuid, new Long(1)); + if (latestNodeVersion.hasParentNode()) { + throw new InvalidParameterException("You cannot delete a node that is in a package (ie has a parent). " + + "Please delete the parent. Node UUID " + portraitUuid); + } + List problemPaths = latestNodeVersion.deleteNode(); + return problemPaths != null ? (String[]) problemPaths.toArray(new String[problemPaths.size()]) : new String[0]; + + } + /* * (non-Javadoc) - * + * * @see * org.lamsfoundation.lams.contentrepository.IRepository#updatePackageItem(org.lamsfoundation.lams.contentrepository * .ITicket, java.lang.Long, java.lang.String, java.lang.String, java.lang.String) @@ -850,10 +876,12 @@ } + @Override public boolean workspaceExists(ICredentials credentials, Long workspaceId) { return workspaceDAO.find(CrWorkspace.class, workspaceId) != null; } + @Override public boolean workspaceExists(ICredentials credentials, String workspaceName) { return workspaceDAO.findByName(workspaceName) != null; } Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/SimpleVersionedNode.java =================================================================== diff -u -rea80430beb4497f12c92db2580341f21750a5a43 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/SimpleVersionedNode.java (.../SimpleVersionedNode.java) (revision ea80430beb4497f12c92db2580341f21750a5a43) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/SimpleVersionedNode.java (.../SimpleVersionedNode.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -21,7 +21,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.contentrepository.service; import java.io.File; @@ -143,12 +142,12 @@ @Override public NodeKey getNodeKey() { - return new NodeKey(getUUID(), getVersion()); + return new NodeKey(getUUID(), getVersion(), getPortraitUuid()); } /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#setProperty(java.lang.String, java.lang.String, * int) */ @@ -160,7 +159,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#setProperty(java.lang.String, java.lang.String) */ @Override @@ -171,7 +170,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#setProperty(java.lang.String, boolean) */ @Override @@ -182,7 +181,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#setProperty(java.lang.String, double) */ @Override @@ -193,7 +192,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#setProperty(java.lang.String, long) */ @Override @@ -204,7 +203,7 @@ /* * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#setProperty(java.lang.String, java.util.Calendar) */ @Override @@ -242,6 +241,12 @@ return node.getNodeId(); } + @Override + public String getPortraitUuid() { + nodeObjectInitilised("Unable to get portrait UUID"); + return node.getPortraitUuid() == null ? null : node.getPortraitUuid().toString(); + } + /** * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#hasProperty(java.lang.String) */ @@ -271,7 +276,7 @@ /** * (non-Javadoc) - * + * * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#isNodeType(java.lang.String) */ @Override @@ -284,7 +289,7 @@ * Get the history for this node. Quite intensive operation * as it has to build all the data structures. Can't be easily * cached. - * + * * @return SortedSet of IVersionDetail objects, ordered by version */ @Override @@ -380,7 +385,7 @@ * of the caller to close the stream. Note: this should only be * called once the node is saved - do not call it directly after * setting the file stream - * + * * If the node is a package node, it will get the input stream * of the first file. */ @@ -416,7 +421,7 @@ /** * Set the file, passed in as an inputstream. The stream will be closed * when the file is saved. Only nodes of type FILENODE can have a file! - * + * * @param iStream * mandatory * @param filename @@ -478,7 +483,7 @@ * we could just be doing a setProperty save, in which case the file * will already exist. *
  • Package nodes must not have a file, must have a INITIALPATH property - * + * * @throws ValidationException * if problems exist. */ @@ -541,19 +546,19 @@ * Save the changes to this node. This method must be called when saving a file * or package node for the first time - it does both the database and the file * saves. - * + * * If it is a file node, then it writes out the db changes and then saves * the file. - * + * * If is is a package node, then it writes out the db changes for all the nodes, * then saves all the file. Why do it this way - we want to do all the file * changes at the end as they cannot be rolled back if there is a db error. - * + * * This method only works as we know that we have two levels of nodes - the * childNodes can't have their own childNodes. If this is no longer the case, * this method and copy() will need to be changed. - * * + * * TODO This needs a lot of testing */ protected Long save() throws ValidationException, FileException { @@ -615,7 +620,8 @@ : element.getFilePath(); } else { failedDeleted = failedDeleted != null - ? failedDeleted + File.pathSeparator + element.getFilePath() : element.getFilePath(); + ? failedDeleted + File.pathSeparator + element.getFilePath() + : element.getFilePath(); } } String msg = "Result of rolling back file changes:"; @@ -667,7 +673,7 @@ /** * Write the file out (if one exists). Sets the private attribute filePath. - * + * * @return the path to which the file was written */ private void writeFile() throws FileException { @@ -695,7 +701,7 @@ /** * Another case for the factory? - * + * * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#getNode(String relPath) */ @Override @@ -719,7 +725,7 @@ /** * If no nodes are found, returns an empty set. - * + * * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#getChildNodes() */ @Override @@ -782,13 +788,13 @@ /** * Delete all versions of this node, returning the number of nodes * deleted. If it is a package node, all child nodes will be deleted. - * + * * @see org.lamsfoundation.lams.contentrepository.IVersionedNodeAdmin#deleteNode() */ @Override public List deleteNode() { - // first make a list of all the versions to delete. + // first make a list of all the versions to delete. // don't iterate over the set, deleting as we go so that // we can't run into any issues trying to access something // that is deleted or belongs to an iterator. @@ -822,7 +828,7 @@ // doing file system changes if the db would fail later. deleteVersionFromDB(nodeKeysDeleted); - // now delete the files. If it fails due to the file not being found, then + // now delete the files. If it fails due to the file not being found, then // that's fine. ArrayList failedList = new ArrayList(); Iterator iter = nodeKeysDeleted.iterator(); @@ -890,7 +896,7 @@ /** * Process files in the package. Create a List of file nodes but do not persist * the nodes. - * + * * @param dirPath: * the directory from which to get files. Mandatory. * @param packageNode: @@ -985,7 +991,7 @@ // no need to the new node as a child node, as createFileNode will do it. FileInputStream istream = new FileInputStream(file); nodeFactory.createFileNode(workspace, this, relPath, istream, filename, null, versionDescription, - userId); + userId, false); } } @@ -1009,11 +1015,11 @@ /** * Copy the supplied node/version to a new node. Does not copy the history * of the node. Copies any child nodes of the current version. All files are duplicated. - * + * * This method only works as we know that we have two levels of nodes - the * childNodes can't have their own childNodes. If this is no longer the case, * this method and SimpleVersionedNode.save() will need to be changed. - * + * * @throws FileException * will occur if there is a problem reading a file from the repository * @throws InvalidParameterException Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBUserGridRowDTO.java =================================================================== diff -u -rfd2cfad55c7c517931f69334ce644d509ec28140 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBUserGridRowDTO.java (.../GBUserGridRowDTO.java) (revision fd2cfad55c7c517931f69334ce644d509ec28140) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBUserGridRowDTO.java (.../GBUserGridRowDTO.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -41,7 +41,7 @@ private String lastName; private String login; private String currentActivity; - private Long portraitId; + private String portraitId; private boolean hasArchivedMarks; @@ -54,12 +54,12 @@ this.firstName = user.getFirstName(); this.lastName = user.getLastName(); this.login = user.getLogin(); - this.setPortraitId(user.getPortraitUuid()); + this.setPortraitId(user.getPortraitUuid() == null ? null : user.getPortraitUuid().toString()); } @Override public ArrayList toStringArray(GBGridView view) { - ArrayList ret = new ArrayList(); + ArrayList ret = new ArrayList<>(); ret.add(id.toString()); @@ -150,11 +150,11 @@ this.currentActivity = currentActivity; } - public Long getPortraitId() { + public String getPortraitId() { return portraitId; } - public void setPortraitId(Long portraitId) { + public void setPortraitId(String portraitId) { this.portraitId = portraitId; } Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dao/hibernate/AssessmentUserDAOHibernate.java =================================================================== diff -u -rdcdc1487609bd4f00afaa93c09272d84ab0cd325 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dao/hibernate/AssessmentUserDAOHibernate.java (.../AssessmentUserDAOHibernate.java) (revision dcdc1487609bd4f00afaa93c09272d84ab0cd325) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dao/hibernate/AssessmentUserDAOHibernate.java (.../AssessmentUserDAOHibernate.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.UUID; import org.hibernate.query.NativeQuery; import org.hibernate.query.Query; @@ -50,12 +51,12 @@ private static final String FIND_MARK_STATS_FOR_SESSION = "SELECT MIN(grade) min_grade, AVG(grade) avg_grade, MAX(grade) max_grade FROM tl_laasse10_assessment_result " + " WHERE finish_date IS NOT NULL AND latest = 1 AND session_id = :sessionId"; - private static final String LOAD_MARKS_FOR_LEADERS = "SELECT r.grade FROM tl_laasse10_assessment_result r " + private static final String LOAD_MARKS_FOR_LEADERS = "SELECT r.grade FROM tl_laasse10_assessment_result r " + " JOIN tl_laasse10_session s ON r.session_id = s.session_id AND r.user_uid = s.group_leader_uid " + " JOIN tl_laasse10_assessment a ON s.assessment_uid = a.uid " + " WHERE r.finish_date IS NOT NULL AND r.latest = 1 AND a.content_id = :toolContentId"; private static final String FIND_MARK_STATS_FOR_LEADERS = "SELECT MIN(grade) min_grade, AVG(grade) avg_grade, MAX(grade) max_grade, COUNT(grade) num_complete " - + " FROM tl_laasse10_assessment_result r " + + " FROM tl_laasse10_assessment_result r " + " JOIN tl_laasse10_session s ON r.session_id = s.session_id AND r.user_uid = s.group_leader_uid " + " JOIN tl_laasse10_assessment a ON s.assessment_uid = a.uid " + " WHERE r.finish_date IS NOT NULL AND r.latest = 1 AND a.content_id = :toolContentId"; @@ -104,10 +105,10 @@ private static String LOAD_USERS_ORDERED_BY_SESSION_SELECT = "SELECT DISTINCT user.user_id, user.last_name, user.first_name, user.login_name, result.grade "; private static String LOAD_USERS_ORDERED_BY_SESSION_FROM = " FROM tl_laasse10_user user "; private static String LOAD_USERS_ORDERED_BY_SESSION_JOIN = " INNER JOIN tl_laasse10_session session" - + " ON user.session_uid=session.uid LEFT OUTER JOIN tl_laasse10_assessment_result result " - + " ON result.user_uid = user.uid AND result.finish_date IS NOT NULL" - + " AND result.latest = 1 WHERE session.session_id = :sessionId " - + " AND (CONCAT(user.last_name, ' ', user.first_name) LIKE CONCAT('%', :searchString, '%')) "; + + " ON user.session_uid=session.uid LEFT OUTER JOIN tl_laasse10_assessment_result result " + + " ON result.user_uid = user.uid AND result.finish_date IS NOT NULL" + + " AND result.latest = 1 WHERE session.session_id = :sessionId " + + " AND (CONCAT(user.last_name, ' ', user.first_name) LIKE CONCAT('%', :searchString, '%')) "; private static String LOAD_USERS_ORDERED_ORDER_BY_NAME = "ORDER BY (CONCAT(user.last_name, ' ', user.first_name)) "; private static String LOAD_USERS_ORDERED_ORDER_BY_TOTAL = "ORDER BY result.grade "; @@ -116,18 +117,17 @@ public List getPagedUsersBySession(Long sessionId, int page, int size, String sortBy, String sortOrder, String searchString, IUserManagementService userManagementService) { String[] portraitStrings = userManagementService.getPortraitSQL("user.user_id"); - - StringBuilder bldr = new StringBuilder(LOAD_USERS_ORDERED_BY_SESSION_SELECT) - .append(portraitStrings[0]) - .append(LOAD_USERS_ORDERED_BY_SESSION_FROM) - .append(portraitStrings[1]) + + StringBuilder bldr = new StringBuilder(LOAD_USERS_ORDERED_BY_SESSION_SELECT).append(portraitStrings[0]) + .append(LOAD_USERS_ORDERED_BY_SESSION_FROM).append(portraitStrings[1]) .append(LOAD_USERS_ORDERED_BY_SESSION_JOIN); - if ( "total".equalsIgnoreCase(sortBy) ) + if ("total".equalsIgnoreCase(sortBy)) { bldr.append(LOAD_USERS_ORDERED_ORDER_BY_TOTAL); - else + } else { bldr.append(LOAD_USERS_ORDERED_ORDER_BY_NAME); + } bldr.append(sortOrder); - + NativeQuery query = getSession().createNativeQuery(bldr.toString()); query.setParameter("sessionId", sessionId); // support for custom search from a toolbar @@ -137,7 +137,7 @@ query.setMaxResults(size); List list = query.list(); - ArrayList userDtos = new ArrayList(); + ArrayList userDtos = new ArrayList<>(); if (list != null && list.size() > 0) { for (Object[] element : list) { @@ -146,15 +146,15 @@ String lastName = (String) element[2]; String login = (String) element[3]; float grade = element[4] == null ? 0 : ((Number) element[4]).floatValue(); - Long portraitId = element[5] == null ? null : ((Number) element[5]).longValue(); + byte[] portraitId = (byte[]) element[5]; AssessmentUserDTO userDto = new AssessmentUserDTO(); userDto.setUserId(userId); userDto.setFirstName(firstName); userDto.setLastName(lastName); userDto.setLogin(login); userDto.setGrade(grade); - userDto.setPortraitId(portraitId); + userDto.setPortraitId(portraitId == null ? null : UUID.nameUUIDFromBytes(portraitId).toString()); userDtos.add(userDto); } @@ -183,7 +183,7 @@ return ((Number) list.get(0)).intValue(); } } - + @Override public int getCountUsersByContentId(Long contentId) { final String LOAD_USERS_ORDERED_BY_NAME = "SELECT COUNT(*) FROM " + AssessmentUser.class.getName() + " user" @@ -198,8 +198,7 @@ @Override public Object[] getStatsMarksBySession(Long sessionId) { Query query = getSession().createNativeQuery(FIND_MARK_STATS_FOR_SESSION) - .addScalar("min_grade", FloatType.INSTANCE) - .addScalar("avg_grade", FloatType.INSTANCE) + .addScalar("min_grade", FloatType.INSTANCE).addScalar("avg_grade", FloatType.INSTANCE) .addScalar("max_grade", FloatType.INSTANCE); query.setParameter("sessionId", sessionId); List list = query.list(); @@ -214,10 +213,8 @@ @Override public Object[] getStatsMarksForLeaders(Long toolContentId) { NativeQuery query = getSession().createNativeQuery(FIND_MARK_STATS_FOR_LEADERS) - .addScalar("min_grade", FloatType.INSTANCE) - .addScalar("avg_grade", FloatType.INSTANCE) - .addScalar("max_grade", FloatType.INSTANCE) - .addScalar("num_complete", IntegerType.INSTANCE); + .addScalar("min_grade", FloatType.INSTANCE).addScalar("avg_grade", FloatType.INSTANCE) + .addScalar("max_grade", FloatType.INSTANCE).addScalar("num_complete", IntegerType.INSTANCE); query.setParameter("toolContentId", toolContentId); List list = query.list(); if ((list == null) || (list.size() == 0)) { @@ -230,34 +227,34 @@ private static String LOAD_USERS_ORDERED_BY_SESSION_QUESTION_SELECT = "SELECT DISTINCT question_result.uid, user.last_name, user.first_name, user.login_name, question_result.mark"; private static String LOAD_USERS_ORDERED_BY_SESSION_QUESTION_FROM = " FROM tl_laasse10_user user"; private static String LOAD_USERS_ORDERED_BY_SESSION_QUESTION_JOIN = " INNER JOIN tl_laasse10_session session" - + " ON user.session_uid=session.uid" + + + " ON user.session_uid=session.uid" + - " LEFT OUTER JOIN tl_laasse10_assessment_result result " + " ON result.user_uid = user.uid" - + " AND result.finish_date IS NOT NULL" + " AND result.latest = 1" + + " LEFT OUTER JOIN tl_laasse10_assessment_result result " + " ON result.user_uid = user.uid" + + " AND result.finish_date IS NOT NULL" + " AND result.latest = 1" + - " INNER JOIN tl_laasse10_question_result question_result " + " ON result.uid=question_result.result_uid" - + " AND question_result.assessment_question_uid = :questionUid" + + " INNER JOIN tl_laasse10_question_result question_result " + " ON result.uid=question_result.result_uid" + + " AND question_result.assessment_question_uid = :questionUid" + - " WHERE session.session_id = :sessionId " - + " AND (CONCAT(user.last_name, ' ', user.first_name) LIKE CONCAT('%', :searchString, '%')) "; + " WHERE session.session_id = :sessionId " + + " AND (CONCAT(user.last_name, ' ', user.first_name) LIKE CONCAT('%', :searchString, '%')) "; private static String LOAD_USERS_ORDERED_ORDER_BY_RESULT = "ORDER BY question_result.mark "; @SuppressWarnings("unchecked") @Override public List getPagedUsersBySessionAndQuestion(Long sessionId, Long questionUid, int page, - int size, String sortBy, String sortOrder, String searchString, IUserManagementService userManagementService) { + int size, String sortBy, String sortOrder, String searchString, + IUserManagementService userManagementService) { String[] portraitStrings = userManagementService.getPortraitSQL("user.user_id"); - StringBuilder bldr = new StringBuilder(LOAD_USERS_ORDERED_BY_SESSION_QUESTION_SELECT) - .append(portraitStrings[0]) - .append(LOAD_USERS_ORDERED_BY_SESSION_QUESTION_FROM) - .append(portraitStrings[1]) + StringBuilder bldr = new StringBuilder(LOAD_USERS_ORDERED_BY_SESSION_QUESTION_SELECT).append(portraitStrings[0]) + .append(LOAD_USERS_ORDERED_BY_SESSION_QUESTION_FROM).append(portraitStrings[1]) .append(LOAD_USERS_ORDERED_BY_SESSION_QUESTION_JOIN); - if ( "grade".equalsIgnoreCase(sortBy) ) + if ("grade".equalsIgnoreCase(sortBy)) { bldr.append(LOAD_USERS_ORDERED_ORDER_BY_RESULT); - else + } else { bldr.append(LOAD_USERS_ORDERED_ORDER_BY_NAME); + } bldr.append(sortOrder); NativeQuery query = getSession().createNativeQuery(bldr.toString()); @@ -270,7 +267,7 @@ query.setMaxResults(size); List list = query.list(); - ArrayList userDtos = new ArrayList(); + ArrayList userDtos = new ArrayList<>(); if (list != null && list.size() > 0) { for (Object[] element : list) { @@ -279,16 +276,15 @@ String lastName = (String) element[2]; String login = (String) element[3]; float grade = element[4] == null ? 0 : ((Number) element[4]).floatValue(); - Long portraitId = element[5] == null ? null : ((Number) element[5]).longValue(); + byte[] portraitId = (byte[]) element[5]; AssessmentUserDTO userDto = new AssessmentUserDTO(); userDto.setQuestionResultUid(questionResultUid); - ; userDto.setFirstName(firstName); userDto.setLastName(lastName); userDto.setLogin(login); userDto.setGrade(grade); - userDto.setPortraitId(portraitId); + userDto.setPortraitId(portraitId == null ? null : UUID.nameUUIDFromBytes(portraitId).toString()); userDtos.add(userDto); } Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dto/AssessmentUserDTO.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dto/AssessmentUserDTO.java (.../AssessmentUserDTO.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dto/AssessmentUserDTO.java (.../AssessmentUserDTO.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -20,7 +20,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.tool.assessment.dto; public class AssessmentUserDTO { @@ -31,7 +30,7 @@ private float grade; private Long questionResultUid; - private Long portraitId; + private String portraitId; public String getFirstName() { return firstName; @@ -81,11 +80,11 @@ this.questionResultUid = questionResultUid; } - public Long getPortraitId() { + public String getPortraitId() { return portraitId; } - public void setPortraitId(Long portraitId) { + public void setPortraitId(String portraitId) { this.portraitId = portraitId; } Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java =================================================================== diff -u -r746369b4989a3ccae7c71d6a07bbb79ab4f47689 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision 746369b4989a3ccae7c71d6a07bbb79ab4f47689) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -358,10 +358,10 @@ } @Override - public Long getPortraitId(Long userId) { + public String getPortraitId(Long userId) { if (userId != null) { User user = (User) userManagementService.findById(User.class, userId.intValue()); - return user != null ? user.getPortraitUuid() : null; + return user == null || user.getPortraitUuid() == null ? null : user.getPortraitUuid().toString(); } return null; } @@ -418,7 +418,7 @@ @Override public void saveOrUpdateAssessment(Assessment assessment) { //update questions' hashes in case questions' titles or descriptions got changed - for (AssessmentQuestion question : (Set) assessment.getQuestions()) { + for (AssessmentQuestion question : assessment.getQuestions()) { String newHash = question.getQuestion() == null ? null : HashUtil.sha1(question.getQuestion()); question.setQuestionHash(newHash); } @@ -569,8 +569,7 @@ return questionResult; } - - + @Override public void storeSingleMarkHedgingQuestion(Assessment assessment, Long userId, List> pagedQuestions, Long singleMarkHedgingQuestionUid) @@ -592,10 +591,10 @@ } } } - + AssessmentQuestionResult questionResult = storeUserAnswer(result, questionDto); questionResult.setFinishDate(new Date()); - + float mark = 0; for (OptionDTO optionDto : questionDto.getOptionDtos()) { if (optionDto.isCorrect()) { @@ -608,7 +607,7 @@ questionResult.setMark(mark); questionResult.setMaxMark((float) questionDto.getGrade()); assessmentResultDao.saveObject(questionResult); - + //for displaying purposes calculate mark and set it to questionDto questionDto.setMark(mark); } @@ -716,10 +715,10 @@ if (assessment.isEnableConfidenceLevels()) { questionResult.setConfidenceLevel(questionDto.getConfidenceLevel()); } - + return questionResult; } - + /** * * @return grade that user scored by answering that question @@ -870,21 +869,21 @@ } } } - + //total mark can't be more than maxMark if (mark > maxMark) { mark = maxMark; - // in case options have negative grades (<0), their total mark can't be less than -maxMark + // in case options have negative grades (<0), their total mark can't be less than -maxMark } else if (mark < -maxMark) { mark = -maxMark; } // calculate penalty if (mark > 0) { // calculate number of wrong answers - int numberWrongAnswers = assessmentQuestionResultDao.getNumberWrongAnswersDoneBefore(assessmentUid, - userId, questionDto.getUid()); + int numberWrongAnswers = assessmentQuestionResultDao.getNumberWrongAnswersDoneBefore(assessmentUid, userId, + questionDto.getUid()); // calculate penalty itself float penalty = questionDto.getPenaltyFactor() * numberWrongAnswers; @@ -903,7 +902,7 @@ questionResult.setMark(mark); questionResult.setMaxMark(maxMark); } - + @Override public void loadupLastAttempt(Long assessmentUid, Long userId, List> pagedQuestionDtos) { //get the latest result (it can be unfinished one) @@ -938,7 +937,7 @@ } } } - + /** * Loads up all information from questionResult into questionDto. */ @@ -1078,7 +1077,7 @@ public int getAssessmentResultCount(Long assessmentUid, Long userId) { return assessmentResultDao.getAssessmentResultCount(assessmentUid, userId); } - + @Override public boolean isAssessmentAttempted(Long assessmentUid) { return assessmentResultDao.isAssessmentAttempted(assessmentUid); @@ -1163,7 +1162,7 @@ //finish non-leader sessionUser.setSessionFinished(true); assessmentUserDao.saveObject(user); - + //copy answers from leader to non-leaders copyAnswersFromLeader(sessionUser, session.getGroupLeader()); }); @@ -1307,7 +1306,7 @@ //otherwise show only questions from the question list } else { - for (QuestionReference reference : (Set) assessment.getQuestionReferences()) { + for (QuestionReference reference : assessment.getQuestionReferences()) { questions.add(reference.getQuestion()); } } @@ -1388,7 +1387,7 @@ sessionIdToUsersMap.put(sessionId, users); } - for (AssessmentQuestion question : (Set) assessment.getQuestions()) { + for (AssessmentQuestion question : assessment.getQuestions()) { Long questionUid = question.getUid(); QuestionSummary questionSummary = new QuestionSummary(); questionSummary.setQuestion(question); @@ -1447,9 +1446,8 @@ } @Override - public List exportSummary(Assessment assessment, List sessionDtos, - boolean showUserNames) { - List sheets = new LinkedList(); + public List exportSummary(Assessment assessment, List sessionDtos, boolean showUserNames) { + List sheets = new LinkedList<>(); // -------------- First tab: Summary ---------------------------------------------------- if (showUserNames) { @@ -1519,16 +1517,16 @@ ExcelRow minMaxRow = summarySheet.initRow(); minMaxRow.addCell(getMessage("label.number.learners"), true); minMaxRow.addCell(totalNumEntries); - + minMaxRow = summarySheet.initRow(); minMaxRow.addCell(getMessage("label.lowest.mark"), true); minMaxRow.addCell((double) minGrade); - + minMaxRow = summarySheet.initRow(); minMaxRow.addCell(getMessage("label.highest.mark"), true); minMaxRow.addCell((double) maxGrade); summarySheet.addEmptyRow(); - + ExcelRow binSummaryRow = summarySheet.initRow(); binSummaryRow.addCell(getMessage("label.authoring.basic.list.header.mark"), true, ExcelCell.BORDER_STYLE_BOTTOM_THIN); @@ -1587,10 +1585,9 @@ ExcelCell.BORDER_STYLE_BOTTOM_THIN); questionTitleRow.addCell(getMessage("label.authoring.basic.penalty.factor"), true, ExcelCell.BORDER_STYLE_BOTTOM_THIN); - questionTitleRow.addCell(getMessage("label.monitoring.question.summary.default.mark"), - true, ExcelCell.BORDER_STYLE_BOTTOM_THIN); - questionTitleRow.addCell(getMessage("label.export.user.id"), true, + questionTitleRow.addCell(getMessage("label.monitoring.question.summary.default.mark"), true, ExcelCell.BORDER_STYLE_BOTTOM_THIN); + questionTitleRow.addCell(getMessage("label.export.user.id"), true, ExcelCell.BORDER_STYLE_BOTTOM_THIN); if (showUserNames) { questionTitleRow.addCell(getMessage("label.monitoring.user.summary.user.name"), true, ExcelCell.BORDER_STYLE_BOTTOM_THIN); @@ -1601,17 +1598,15 @@ ExcelCell.BORDER_STYLE_BOTTOM_THIN); questionTitleRow.addCell(getMessage("label.authoring.basic.option.answer"), true, ExcelCell.BORDER_STYLE_BOTTOM_THIN); - questionTitleRow.addCell(getMessage("label.export.time.taken"), true, - ExcelCell.BORDER_STYLE_BOTTOM_THIN); - questionTitleRow.addCell(getMessage("label.export.mark"), true, - ExcelCell.BORDER_STYLE_BOTTOM_THIN); + questionTitleRow.addCell(getMessage("label.export.time.taken"), true, ExcelCell.BORDER_STYLE_BOTTOM_THIN); + questionTitleRow.addCell(getMessage("label.export.mark"), true, ExcelCell.BORDER_STYLE_BOTTOM_THIN); int questionNumber = 1; for (AssessmentQuestion question : questions) { ExcelRow questionTitle = questionSummarySheet.initRow(); - questionTitle.addCell( - getMessage("label.monitoring.question.summary.question") + " " + questionNumber++, true); + questionTitle.addCell(getMessage("label.monitoring.question.summary.question") + " " + questionNumber++, + true); // set up the summary table data for the top of the question area. boolean doSummaryTable = question.getType() == AssessmentConstants.QUESTION_TYPE_MULTIPLE_CHOICE @@ -1636,24 +1631,19 @@ Set options = question.getOptions(); // question row title ExcelRow hedgeQuestionTitleRow = new ExcelRow(); - hedgeQuestionTitleRow.addCell( - getMessage("label.monitoring.question.summary.question"), true); - hedgeQuestionTitleRow.addCell(getMessage("label.authoring.basic.list.header.type"), - true); - hedgeQuestionTitleRow.addCell(getMessage("label.authoring.basic.penalty.factor"), - true); - hedgeQuestionTitleRow.addCell( - getMessage("label.monitoring.question.summary.default.mark"), true); + hedgeQuestionTitleRow.addCell(getMessage("label.monitoring.question.summary.question"), true); + hedgeQuestionTitleRow.addCell(getMessage("label.authoring.basic.list.header.type"), true); + hedgeQuestionTitleRow.addCell(getMessage("label.authoring.basic.penalty.factor"), true); + hedgeQuestionTitleRow.addCell(getMessage("label.monitoring.question.summary.default.mark"), true); hedgeQuestionTitleRow.addCell(getMessage("label.export.user.id"), true); if (showUserNames) { - hedgeQuestionTitleRow.addCell( - getMessage("label.monitoring.user.summary.user.name"), true); + hedgeQuestionTitleRow.addCell(getMessage("label.monitoring.user.summary.user.name"), true); } hedgeQuestionTitleRow.addCell(getMessage("label.export.date.attempted"), true); hedgeQuestionTitleRow.addCell(getMessage("label.export.time.attempted"), true); for (AssessmentQuestionOption option : options) { - ExcelCell cell = hedgeQuestionTitleRow.addCell( - option.getOptionString().replaceAll("\\<.*?\\>", ""), true); + ExcelCell cell = hedgeQuestionTitleRow + .addCell(option.getOptionString().replaceAll("\\<.*?\\>", ""), true); if (option.isCorrect()) { cell.setColor(IndexedColors.GREEN); } @@ -1679,8 +1669,7 @@ userResultRow.addCell(questionResult.getAssessmentQuestion().getTitle()); userResultRow.addCell( getQuestionTypeLanguageLabel(questionResult.getAssessmentQuestion().getType())); - userResultRow.addCell( - Float.valueOf(questionResult.getAssessmentQuestion().getPenaltyFactor())); + userResultRow.addCell(Float.valueOf(questionResult.getAssessmentQuestion().getPenaltyFactor())); Float maxMark = (questionResult.getMaxMark() == null) ? 0 : Float.valueOf(questionResult.getMaxMark()); userResultRow.addCell(maxMark); @@ -1690,7 +1679,7 @@ } else { userResultRow.addCell(questionResult.getUser().getUserId()); } - + //date and time ExcelCell dateCell = userResultRow.addCell(questionResult.getFinishDate()); dateCell.setDataFormat(ExcelCell.CELL_FORMAT_DATE); @@ -1860,20 +1849,17 @@ if (showUserNames) { ExcelRow userTitleRow = userSummarySheet.initRow(); userTitleRow.addCell(getMessage("label.export.user.id"), true); - userTitleRow.addCell(getMessage("label.monitoring.user.summary.user.name"), - true); + userTitleRow.addCell(getMessage("label.monitoring.user.summary.user.name"), true); userTitleRow.addCell(getMessage("label.export.date.attempted"), true); - userTitleRow.addCell(getMessage("label.monitoring.question.summary.question"), - true); + userTitleRow.addCell(getMessage("label.monitoring.question.summary.question"), true); userTitleRow.addCell(getMessage("label.authoring.basic.option.answer"), true); userTitleRow.addCell(getMessage("label.export.mark"), true); } else { ExcelRow userTitleRow = userSummarySheet.initRow(); userTitleRow.addCell(getMessage("label.export.user.id"), true); userTitleRow.addCell(getMessage("label.export.date.attempted"), true); - userTitleRow.addCell(getMessage("label.monitoring.question.summary.question"), - true); + userTitleRow.addCell(getMessage("label.monitoring.question.summary.question"), true); userTitleRow.addCell(getMessage("label.authoring.basic.option.answer"), true); userTitleRow.addCell(getMessage("label.export.mark"), true); } @@ -1912,8 +1898,8 @@ return sheets; } - private ExcelRow startSummaryTable(AssessmentQuestion question, Map summaryOfAnswers, - Long trueKey, Long falseKey) { + private ExcelRow startSummaryTable(AssessmentQuestion question, Map summaryOfAnswers, Long trueKey, + Long falseKey) { ExcelRow summaryTableRow; int i = 0; if (question.getType() == AssessmentConstants.QUESTION_TYPE_MULTIPLE_CHOICE @@ -2018,16 +2004,16 @@ optionCell.setColor(IndexedColors.GREEN); } } - + } else { Double correctPercentage = total == 0 || summaryOfAnswers.get(trueKey) == null ? 0 : (double) summaryOfAnswers.get(trueKey) / total; ExcelCell correctCell = summaryTableRow.addPercentageCell(correctPercentage); - + Double wrongPercentage = total == 0 || summaryOfAnswers.get(falseKey) == null ? 0 : (double) summaryOfAnswers.get(falseKey) / total; ExcelCell wrongCell = summaryTableRow.addPercentageCell(wrongPercentage); - + if (question.getCorrectAnswer()) { correctCell.setColor(IndexedColors.GREEN); } else { @@ -2037,7 +2023,7 @@ Double summaryNAPercentage = total == 0 ? 0 : (double) summaryNACount / total; summaryTableRow.addPercentageCell(summaryNAPercentage); - + return summaryTableRow; } @@ -2131,7 +2117,7 @@ // create list of modified questions List modifiedQuestions = new ArrayList<>(); for (AssessmentQuestion oldQuestion : oldQuestions) { - + if (AssessmentConstants.QUESTION_TYPE_ESSAY == oldQuestion.getType() || AssessmentConstants.QUESTION_TYPE_MATCHING_PAIRS == oldQuestion.getType()) { continue; @@ -2143,7 +2129,7 @@ boolean isQuestionModified = false; // title or question is different - do nothing. Also question grade can't be changed - + //AssessmentConstants.QUESTION_TYPE_TRUE_FALSE if (oldQuestion.getCorrectAnswer() != newQuestion.getCorrectAnswer()) { isQuestionModified = true; @@ -2222,7 +2208,7 @@ float assessmentMark = assessmentResult.getGrade(); int assessmentMaxMark = assessmentResult.getMaximumGrade(); Set questionResults = assessmentResult.getQuestionResults(); - + // [+] if the question is modified for (AssessmentQuestionResult questionResult : questionResults) { AssessmentQuestion question = questionResult.getAssessmentQuestion(); @@ -2238,18 +2224,18 @@ loadupQuestionResultIntoQuestionDto(questionDto, questionResult); calculateAnswerMark(assessmentUid, user.getUserId(), questionResult, questionDto); assessmentQuestionResultDao.saveObject(questionResult); - + float newQuestionAnswerMark = questionResult.getMark(); assessmentMark += newQuestionAnswerMark - oldQuestionAnswerMark; break; } } } - + // [+] if the question reference mark is modified - for (AssessmentQuestionResult questionResult:questionResults) { + for (AssessmentQuestionResult questionResult : questionResults) { Long questionUid = questionResult.getAssessmentQuestion().getUid(); - + for (QuestionReference modifiedReference : modifiedReferences.keySet()) { if (!modifiedReference.isRandomQuestion() && questionUid.equals(modifiedReference.getQuestion().getUid())) { @@ -2356,7 +2342,7 @@ public void auditLogStartEditingActivityInMonitor(long toolContentID) { toolService.auditLogStartEditingActivityInMonitor(toolContentID); } - + @Override public boolean isLastActivity(Long toolSessionId) { return toolService.isLastActivity(toolSessionId); @@ -2572,8 +2558,7 @@ // reset it to new toolContentId toolContentObj.setContentId(toolContentId); - AssessmentUser user = assessmentUserDao.getUserCreatedAssessment(newUserUid.longValue(), - toolContentId); + AssessmentUser user = assessmentUserDao.getUserCreatedAssessment(newUserUid.longValue(), toolContentId); if (user == null) { user = new AssessmentUser(); UserDTO sysUser = ((User) userManagementService.findById(User.class, newUserUid)).getUserDTO(); @@ -2756,7 +2741,7 @@ @Override public List getConfidenceLevels(Long toolSessionId) { - List confidenceLevelDtos = new ArrayList(); + List confidenceLevelDtos = new ArrayList<>(); if (toolSessionId == null) { return confidenceLevelDtos; } @@ -2777,7 +2762,7 @@ for (AssessmentQuestionResult questionResult : assessmentResult.getQuestionResults()) { AssessmentQuestion question = questionResult.getAssessmentQuestion(); - List answers = new LinkedList(); + List answers = new LinkedList<>(); if (question.getType() == AssessmentConstants.QUESTION_TYPE_MULTIPLE_CHOICE) { @@ -2842,16 +2827,16 @@ return; } Assessment assessment = session.getAssessment(); - + AssessmentUser assessmentUser = getUserByIDAndSession(userId, toolSessionId); // create user if he hasn't accessed this activity yet if (assessmentUser == null) { assessmentUser = new AssessmentUser(user.getUserDTO(), session); createUser(assessmentUser); - + setAttemptStarted(assessment, assessmentUser, toolSessionId); } - + //finalize the latest result, if it's still active AssessmentResult lastAssessmentResult = getLastAssessmentResult(assessment.getUid(), userId); if (lastAssessmentResult != null && lastAssessmentResult.getFinishDate() == null) { @@ -2872,7 +2857,7 @@ //copy answers from leader to non-leaders copyAnswersFromLeader(sessionUser, groupLeader); }); - + } else { assessmentUser.setSessionFinished(true); assessmentUserDao.saveObject(user); @@ -3171,7 +3156,7 @@ @Override public void notifyLearnersOnAnswerDisclose(long toolContentId) { List sessions = assessmentSessionDao.getByContentId(toolContentId); - Set userIds = new HashSet(); + Set userIds = new HashSet<>(); for (AssessmentSession session : sessions) { for (AssessmentUser user : session.getAssessmentUsers()) { userIds.add(user.getUserId().intValue()); Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/IAssessmentService.java =================================================================== diff -u -r20aa6cbca9fc96d341080e6ad39f82593443f792 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/IAssessmentService.java (.../IAssessmentService.java) (revision 20aa6cbca9fc96d341080e6ad39f82593443f792) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/IAssessmentService.java (.../IAssessmentService.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -24,7 +24,6 @@ package org.lamsfoundation.lams.tool.assessment.service; import java.lang.reflect.InvocationTargetException; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -47,7 +46,6 @@ import org.lamsfoundation.lams.tool.assessment.model.AssessmentUser; import org.lamsfoundation.lams.tool.assessment.model.QuestionReference; import org.lamsfoundation.lams.tool.service.ICommonToolService; -import org.lamsfoundation.lams.util.excel.ExcelCell; import org.lamsfoundation.lams.util.excel.ExcelSheet; /** @@ -230,7 +228,7 @@ * @param assessmentResult */ void setAttemptStarted(Assessment assessment, AssessmentUser assessmentUser, Long toolSessionId); - + void storeSingleMarkHedgingQuestion(Assessment assessment, Long userId, List> pagedQuestions, Long singleMarkHedgingQuestionUid) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException; @@ -248,7 +246,7 @@ */ boolean storeUserAnswers(Assessment assessment, Long userId, List> pagedQuestions, boolean isAutosave) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException; - + void loadupLastAttempt(Long assessmentUid, Long userId, List> pagedQuestionDtos); /** @@ -353,7 +351,7 @@ * @return */ int getAssessmentResultCount(Long assessmentUid, Long userId); - + /** * Checks whether anyone has attempted this assessment. */ @@ -447,8 +445,7 @@ * @param showUserNames * @return */ - List exportSummary(Assessment assessment, List sessionDtos, - boolean showUserNames); + List exportSummary(Assessment assessment, List sessionDtos, boolean showUserNames); /** * Gets the basic statistics for the grades for the Leaders when an Assessment is done using @@ -521,7 +518,7 @@ void releaseFromCache(Object object); - Long getPortraitId(Long userId); + String getPortraitId(Long userId); AssessmentQuestion getAssessmentQuestionByUid(Long questionUid); Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/MonitoringController.java =================================================================== diff -u -rbac8a1d9f2b37ca6e26f275886b9e6603a6c0fb7 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/MonitoringController.java (.../MonitoringController.java) (revision bac8a1d9f2b37ca6e26f275886b9e6603a6c0fb7) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/MonitoringController.java (.../MonitoringController.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -290,7 +290,7 @@ if (groupLeader != null) { float assessmentResult = service.getLastTotalScoreByUser(assessment.getUid(), groupLeader.getUserId()); - Long portraitId = service.getPortraitId(groupLeader.getUserId()); + String portraitId = service.getPortraitId(groupLeader.getUserId()); AssessmentUserDTO userDto = new AssessmentUserDTO(); userDto.setUserId(groupLeader.getUserId()); Index: lams_tool_chat/src/java/org/lamsfoundation/lams/tool/chat/web/controller/LearningWebsocketServer.java =================================================================== diff -u -ra8bbaa43c079c2a25d1a81c234114e6103b046a5 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_tool_chat/src/java/org/lamsfoundation/lams/tool/chat/web/controller/LearningWebsocketServer.java (.../LearningWebsocketServer.java) (revision a8bbaa43c079c2a25d1a81c234114e6103b046a5) +++ lams_tool_chat/src/java/org/lamsfoundation/lams/tool/chat/web/controller/LearningWebsocketServer.java (.../LearningWebsocketServer.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -57,10 +57,10 @@ private String userName; private String nickName; private Long lamsUserId; - private Long portraitId; + private String portraitId; private String hash; - private Websocket(Session session, String nickName, Long lamsUserId, Long portraitId) { + private Websocket(Session session, String nickName, Long lamsUserId, String portraitId) { this.session = session; this.userName = session.getUserPrincipal().getName(); this.nickName = nickName; @@ -186,7 +186,7 @@ private long lastDBCheckTime = 0; // Learners who are currently active - private final TreeMap activeUsers = new TreeMap<>(); + private final TreeMap activeUsers = new TreeMap<>(); private Roster(Long toolSessionId) { this.toolSessionId = toolSessionId; @@ -199,11 +199,12 @@ * @throws JsonProcessingException */ private ArrayNode getRosterJSON() throws JsonProcessingException, IOException { - TreeMap localActiveUsers = new TreeMap<>(); + TreeMap localActiveUsers = new TreeMap<>(); Set sessionWebsockets = LearningWebsocketServer.websockets.get(toolSessionId); // find out who is active locally for (Websocket websocket : sessionWebsockets) { - localActiveUsers.put(websocket.nickName, new Long[] { websocket.lamsUserId, websocket.portraitId }); + localActiveUsers.put(websocket.nickName, + new String[] { websocket.lamsUserId.toString(), websocket.portraitId }); } // is it time to sync with the DB yet? @@ -218,7 +219,7 @@ // refresh current collection activeUsers.clear(); for (ChatUser activeUser : storedActiveUsers) { - activeUsers.put(activeUser.getNickname(), new Long[] { activeUser.getUserId(), + activeUsers.put(activeUser.getNickname(), new String[] { activeUser.getUserId().toString(), LearningWebsocketServer.getPortraitId(activeUser.getUserId()) }); } @@ -229,8 +230,8 @@ } ArrayNode rosterJSON = JsonNodeFactory.instance.arrayNode(); - for (Map.Entry entry : activeUsers.entrySet()) { - Long[] ids = entry.getValue(); + for (Map.Entry entry : activeUsers.entrySet()) { + String[] ids = entry.getValue(); ObjectNode userJSON = JsonNodeFactory.instance.objectNode().put("nickName", entry.getKey()) .put("lamsUserId", ids[0]).put("portraitId", ids[1]); rosterJSON.add(userJSON); @@ -412,12 +413,12 @@ return messagesJSON; } - private static Long getPortraitId(Long userId) { + private static String getPortraitId(Long userId) { if (userId != null) { User user = (User) LearningWebsocketServer.getUserManagementService().findById(User.class, userId.intValue()); - if (user != null) { - return user.getPortraitUuid(); + if (user != null && user.getPortraitUuid() != null) { + return user.getPortraitUuid().toString(); } } return null; Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/IMcService.java =================================================================== diff -u -r6ec43132d9df310eebff50fac6fca9f095757bd7 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/IMcService.java (.../IMcService.java) (revision 6ec43132d9df310eebff50fac6fca9f095757bd7) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/IMcService.java (.../IMcService.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -83,7 +83,7 @@ McQueUsr getMcUserBySession(final Long queUsrId, final Long mcSessionUid) throws McApplicationException; - Long getPortraitId(Long userId); + String getPortraitId(Long userId); void saveUserAttempt(McQueUsr user, List answerDtos); @@ -240,15 +240,15 @@ /** * Gets the basic statistics for the grades for the Leaders when an Assessment is done using * Group Leaders. So the averages, etc are for the whole Assessment, not for a Group. - * + * * @param contentId * @return */ LeaderResultsDTO getLeaderResultsDTOForLeaders(Long contentId); /** * Prepares data for the marks summary graph on the statistics page - * + * * @param assessment * @param sessionDtos * @return @@ -258,7 +258,7 @@ /** * Prepares data for the marks summary graph on the statistics page, using the grades for the Leaders * when an Assessment is done using Group Leaders. So the grades are for the whole Assessment, not for a Group. - * + * * @param assessment * @param sessionDtos * @return Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/McService.java =================================================================== diff -u -r26d1f2a5b30574d0aef6b6eaf98b2d02ba72b5a2 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/McService.java (.../McService.java) (revision 26d1f2a5b30574d0aef6b6eaf98b2d02ba72b5a2) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/McService.java (.../McService.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -384,10 +384,10 @@ } @Override - public Long getPortraitId(Long userId) { + public String getPortraitId(Long userId) { if (userId != null) { User user = (User) userManagementService.findById(User.class, userId.intValue()); - return user != null ? user.getPortraitUuid() : null; + return user == null || user.getPortraitUuid() == null ? null : user.getPortraitUuid().toString(); } return null; } Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/controller/MonitoringController.java =================================================================== diff -u -r0e335c2bff2e2b295994a308ec675a0d343071e8 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/controller/MonitoringController.java (.../MonitoringController.java) (revision 0e335c2bff2e2b295994a308ec675a0d343071e8) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/controller/MonitoringController.java (.../MonitoringController.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -328,7 +328,7 @@ } mcContent.setSubmissionDeadline(tzSubmissionDeadline); mcService.updateMc(mcContent); - + return formattedDate; } @@ -414,14 +414,14 @@ if (groupLeader != null) { Integer totalMark = groupLeader.getLastAttemptTotalMark(); - Long portraitId = mcService.getPortraitId(groupLeader.getQueUsrId()); + String portraitId = mcService.getPortraitId(groupLeader.getQueUsrId()); McUserMarkDTO userDto = new McUserMarkDTO(); userDto.setQueUsrId(groupLeader.getUid().toString()); userDto.setUserId(groupLeader.getQueUsrId().toString()); userDto.setFullName(groupLeader.getFullname()); userDto.setTotalMark(totalMark != null ? totalMark.longValue() : null); - userDto.setPortraitId(portraitId == null ? null : portraitId.toString()); + userDto.setPortraitId(portraitId); userDtos.add(userDto); countVisitLogs = 1; Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieUser.java =================================================================== diff -u -r1ee503e3d0e0228ea8a45025fddf15d9623c0377 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieUser.java (.../ScratchieUser.java) (revision 1ee503e3d0e0228ea8a45025fddf15d9623c0377) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieUser.java (.../ScratchieUser.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -76,7 +76,7 @@ //******************** DTO ********************** @Transient - private Long portraitId; + private String portraitId; public ScratchieUser() { } @@ -191,11 +191,11 @@ this.sessionFinished = sessionFinished; } - public Long getPortraitId() { + public String getPortraitId() { return portraitId; } - public void setPortraitId(Long portraitId) { + public void setPortraitId(String portraitId) { this.portraitId = portraitId; } Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java =================================================================== diff -u -rf5e59b4320e8fdfb492b6432ca965c2381918d91 -r7a2a590146e0899d86b5b810547ba2d4ca83aa18 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision f5e59b4320e8fdfb492b6432ca965c2381918d91) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision 7a2a590146e0899d86b5b810547ba2d4ca83aa18) @@ -701,7 +701,8 @@ // include only leaders in case isUserGroupLeader is ON, include all otherwise if (isIncludeOnlyLeaders && isUserGroupLeader) { User systemUser = (User) userManagementService.findById(User.class, user.getUserId().intValue()); - user.setPortraitId(systemUser.getPortraitUuid()); + user.setPortraitId( + systemUser.getPortraitUuid() == null ? null : systemUser.getPortraitUuid().toString()); usersToShow.add(user); } else if (!isIncludeOnlyLeaders) { usersToShow.add(user);