package org.fenixedu.bennu.core.domain; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.stream.Stream; import org.fenixedu.bennu.core.domain.exceptions.BennuCoreDomainException; import org.fenixedu.commons.StringNormalizer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.CharMatcher; import com.google.common.base.Objects; import com.google.common.base.Strings; /** * User account profile information. This information includes names, email, avatar and preferred locale. * * @author Pedro Santos (pedro.miguel.santos@tecnico.ulisboa.pt) */ public class UserProfile extends UserProfile_Base { private static final Logger logger = LoggerFactory.getLogger(UserProfile.class); protected UserProfile() { super(); setBennu(Bennu.getInstance()); } /** * New unlinked profile. * * @param givenNames person's given names * @param familyNames person's family names * @param displayName person's display name * @param email person's email address for communication * @param preferredLocale locale used to localize all content when the user is logged. */ public UserProfile(String givenNames, String familyNames, String displayName, String email, Locale preferredLocale) { this(); changeName(givenNames, familyNames, displayName); setEmail(email); setPreferredLocale(preferredLocale); } @Override public User getUser() { // FIXME: remove when framework support read-only slots return super.getUser(); } /** * A possibly shorter version of the full name. Used on most places to identify the person. * * @return a String with the display name or null. * @see #getFullName() */ @Override public String getDisplayName() { return super.getDisplayName() != null ? super.getDisplayName() : getFullName(); } /** * The given names of the person. First part of the full name. * * @return a String with the given names or null. * @see #getFamilyNames() * @see #getFullName() */ @Override public String getGivenNames() { // FIXME: remove when framework support read-only slots return super.getGivenNames(); } /** * The family names (surnames) of the person. Last part of the full name. * * @return a String with the family names or null. * @see #getFamilyNames() * @see #getFullName() */ @Override public String getFamilyNames() { // FIXME: remove when framework support read-only slots return super.getFamilyNames(); } /** * The full name of the person, composed of given and family names separated by a space. * * @return a String with the full name or null. * @see #getGivenNames() * @see #getFamilyNames() */ public String getFullName() { StringBuilder builder = new StringBuilder(); if (!Strings.isNullOrEmpty(getGivenNames())) { builder.append(getGivenNames()); } builder.append(" "); if (!Strings.isNullOrEmpty(getFamilyNames())) { builder.append(getFamilyNames()); } return builder.toString().trim(); } /** * Change the name by changing it's parts validating consistency between them. Namely ensures the display name is a subset of * the given and family names together. * * @param given person's given names * @param family person's family names * @param display person's display name */ public void changeName(String given, String family, String display) { setGivenNames(cleanupName(given)); setFamilyNames(cleanupName(family)); setDisplayName(cleanupName(display)); validateNames(super.getDisplayName(), getFullName()); NameIndex.updateNameIndex(this); } /** * User's primary email. * * @return a String with the user's email or null */ @Override public String getEmail() { return super.getEmail(); } /** * Change user's primary email. * * @param email a String with the user's primary email */ @Override public void setEmail(String email) { super.setEmail(email); } /** * The users's preferred locale for internationalized content. If this value is null the system localizes content based on * global defaults. * * @return a Locale instance or null */ @Override public Locale getPreferredLocale() { return super.getPreferredLocale(); } /** * Change the user's preferred locale. * * @param preferredLocale a Locale instance * @see #getPreferredLocale() */ @Override public void setPreferredLocale(Locale preferredLocale) { super.setPreferredLocale(preferredLocale); } /** * Returns this user's avatar URL or a mystery man avatar URL if not present. Avatar URLs can be parameterized with * {@code s=size}, by default size is 100. */ @Override public String getAvatarUrl() { if (super.getAvatarUrl() != null) { return super.getAvatarUrl(); } if (getLocalAvatar() != null) { return getLocalAvatar().url(); } return Avatar.mysteryManUrl(this.getUser()); } /** * Sets the user's base avatar URL. * * @see #getAvatarUrl() */ @Override public void setAvatarUrl(String avatarUrl) { if (getLocalAvatar() != null) { getLocalAvatar().delete(); } super.setAvatarUrl(avatarUrl); } /** * Sets this user's avatar to a locally stored avatar and updates the avatar url accordingly. * * @param localAvatar a Avatar instance with the image * @see #getAvatarUrl() */ @Override public void setLocalAvatar(Avatar localAvatar) { if (Objects.equal(getLocalAvatar(), localAvatar)) { return; } if (getLocalAvatar() != null) { getLocalAvatar().delete(); } super.setLocalAvatar(localAvatar); super.setAvatarUrl(null); } /** * Search all profiles matching the given. * * @param name the query string * @param maxHits limit on the result size * @return all {@link UserProfile}s where the name contains all the terms of the query string */ public static Stream<UserProfile> searchByName(String name, int maxHits) { if (logger.isTraceEnabled()) { long time = System.currentTimeMillis(); Stream<UserProfile> matches = NameIndex.search(name, maxHits); logger.trace("Profile search for '{}' took {}ms", name, System.currentTimeMillis() - time); return matches; } return NameIndex.search(name, maxHits); } private static void validateNames(String displayname, String fullname) { if (displayname == null) { return; } if (fullname == null) { throw BennuCoreDomainException.displayNameNotContainedInFullName(displayname, fullname); } List<String> fullnameParts = Arrays.asList(StringNormalizer.normalizeAndRemoveAccents(fullname).toLowerCase().trim().split("\\s+|-")); List<String> displaynameParts = Arrays.asList(StringNormalizer.normalizeAndRemoveAccents(displayname).toLowerCase().trim().split("\\s+|-")); if (!fullnameParts.containsAll(displaynameParts)) { throw BennuCoreDomainException.displayNameNotContainedInFullName(displayname, fullname); } } private static String cleanupName(String name) { if (name == null) { return null; } return Strings.emptyToNull(CharMatcher.WHITESPACE.trimAndCollapseFrom(name, ' ')); } }