/*
* Copyright (c) 2009-2011 Lockheed Martin Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eurekastreams.server.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PostPersist;
import javax.persistence.PostUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.eurekastreams.commons.model.DomainEntity;
import org.eurekastreams.commons.search.analysis.HtmlStemmerAnalyzer;
import org.eurekastreams.commons.search.analysis.TextStemmerAnalyzer;
import org.eurekastreams.server.domain.stream.Stream;
import org.eurekastreams.server.domain.stream.StreamScope;
import org.eurekastreams.server.search.bridge.BackgroundStringBridge;
import org.eurekastreams.server.search.bridge.EducationListStringBridge;
import org.eurekastreams.server.search.bridge.JobsListStringBridge;
import org.eurekastreams.server.search.bridge.OrgIdHierarchyFieldBridge;
import org.eurekastreams.server.search.bridge.OrganizationToShortNameFieldBridge;
import org.eurekastreams.server.search.modelview.OrganizationModelView;
import org.eurekastreams.server.search.modelview.PersonModelView;
import org.hibernate.annotations.Formula;
import org.hibernate.annotations.IndexColumn;
import org.hibernate.search.annotations.Analyzer;
import org.hibernate.search.annotations.DateBridge;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.FieldBridge;
import org.hibernate.search.annotations.Fields;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.Resolution;
import org.hibernate.search.annotations.Store;
import org.hibernate.validator.Digits;
import org.hibernate.validator.Email;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotEmpty;
/**
* Represents a person using the system, owning a start page.
*/
@Entity
@Indexed
public class Person extends DomainEntity implements Serializable, AvatarEntity, Followable, OrganizationChild,
HasEmail, Bannerable
{
/**
* Serial version uid.
*/
private static final long serialVersionUID = -2941774908815671062L;
/**
* used for validation.
*/
@Transient
public static final int MAX_FIRST_NAME_LENGTH = 50;
/**
* Used for validation.
*/
@Transient
public static final int MAX_LAST_NAME_LENGTH = 50;
/**
* used for validation.
*/
@Transient
public static final int MAX_TITLE_LENGTH = 150;
/**
* Used for validation.
*/
@Transient
public static final int MAX_JOB_DESCRIPTION_LENGTH = 250;
/**
* Used for validation.
*/
@Transient
public static final int MAX_PHONE_NUMBER_LENGTH = 250;
/**
* The number of tabs each person is limited to ont he start page.
*/
@Transient
public static final int TAB_LIMIT = 6;
/**
* Message to return when limit is reached.
*/
@Transient
public static final String TAB_LIMIT_MESSAGE = "Start page tabs are limited to " + TAB_LIMIT + ".";
/**
* Used for validation.
*/
@Transient
public static final String PHONE_NUMBER_MESSAGE = "Phone numbers can be no more than " + MAX_PHONE_NUMBER_LENGTH
+ " characters.";
/**
* Used for validation.
*/
@Transient
public static final String FAX_NUMBER_MESSAGE = "Fax number can be no more than " + MAX_PHONE_NUMBER_LENGTH
+ " characters.";
/**
* Used for validation.
*/
@Transient
public static final String JOB_DESCRIPTION_MESSAGE = "Job Description supports up to " + MAX_JOB_DESCRIPTION_LENGTH
+ " characters.";
/**
* Used for validation.
*/
@Transient
public static final String TITLE_MESSAGE = "Title supports up to " + MAX_TITLE_LENGTH + " characters.";
/**
* Used for validation.
*/
@Transient
public static final String FIRST_NAME_MESSAGE = "First name must be between 1 and " + MAX_FIRST_NAME_LENGTH
+ " characters.";
/**
* Used for validation.
*/
@Transient
public static final String MIDDLE_NAME_MESSAGE = "Middle name must be between 1 and " + MAX_LAST_NAME_LENGTH
+ " characters.";
/**
* Used for validation.
*/
@Transient
public static final String COMPANY_NAME_MESSAGE = "Company name must be between 1 and " + MAX_LAST_NAME_LENGTH
+ " characters.";
/**
* Used for validation.
*/
@Transient
public static final String LAST_NAME_MESSAGE = "Last name must be between 1 and " + MAX_LAST_NAME_LENGTH
+ " characters.";
/**
* Used for validation.
*/
@Transient
public static final String EMAIL_MESSAGE = "Please enter a properly formatted email address.";
/**
* Used for validation.
*/
@Transient
private static final int MAX_OVERVIEW_LENGTH = 10000;
/**
* Used for validation.
*/
@Transient
public static final String OVERVIEW_MESSAGE = "Overview can be no more than " + MAX_OVERVIEW_LENGTH
+ " characters.";
/**
* Transient 'isPublic' field used only for searching - helps speed up certain queries that contain
* permission-scoped entities.
*/
@Transient
@Field(name = "isPublic", index = Index.UN_TOKENIZED, store = Store.NO)
@SuppressWarnings("unused")
private final boolean publicGroup = true;
/**
* Transient field used only for displaying a banner on profile pages. This is needed so that a common strategy can
* be used across groups, orgs, and people to display banners. When profiles support DTO's, this can be moved there.
*/
@Transient
private String bannerId = null;
/**
* Transient field used only for displaying a banner on profile pages. This is needed so that a common strategy can
* be used across groups, orgs, and people to display banners. When profiles support DTO's, this can be moved there.
*/
@Transient
private Long bannerEntityId = null;
/**
* List of Streams for this person.
*/
@IndexColumn(name = "streamIndex", base = 0)
// Don't cascade on delete
@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
@JoinTable(name = "Person_Stream",
// join columns
joinColumns = { @JoinColumn(table = "Person", name = "personId") },
// inverse join columns
inverseJoinColumns = { @JoinColumn(table = "Stream", name = "streamId") },
// unique constraints
uniqueConstraints = { @UniqueConstraint(columnNames = { "personId", "streamId" }) })
private List<Stream> streams;
// ///////////////////////////////////////////////////////////////////
// ATTRIBUTES
// ///////////////////////////////////////////////////////////////////
/**
* The date the user was added into the system, defaults to the current time, indexed into search engine. Note, for
* the date to be sortable, it needs to be either Index.UN_TOKENIZED or Index.NO_NORMS.
*/
@Column(nullable = false)
@Field(name = "dateAdded", index = Index.UN_TOKENIZED, store = Store.NO)
@Temporal(TemporalType.TIMESTAMP)
@DateBridge(resolution = Resolution.SECOND)
private Date dateAdded = new Date();
/**
* The unique (case-insensitive) account id for this Person.
*/
@Column(nullable = false, unique = true)
@Field(name = "accountId", index = Index.UN_TOKENIZED, store = Store.NO)
private String accountId;
/**
* The first name of this Person.
*/
@Basic(optional = false)
@Length(min = 1, max = MAX_FIRST_NAME_LENGTH, message = FIRST_NAME_MESSAGE)
private String firstName;
/**
* The middle name of this Person.
*/
@Length(min = 1, max = MAX_FIRST_NAME_LENGTH, message = MIDDLE_NAME_MESSAGE)
private String middleName;
/**
* The last name of this Person.
*/
@Basic(optional = false)
@Length(min = 1, max = MAX_FIRST_NAME_LENGTH, message = LAST_NAME_MESSAGE)
@Field(name = "lastName", index = Index.TOKENIZED,
// search is using text stemmer, so we need to index searchable fields with it
analyzer = @Analyzer(impl = TextStemmerAnalyzer.class), store = Store.NO)
private String lastName;
/**
* The preferred name of this Person.
*/
@Basic(optional = false)
@Field(name = "preferredName", index = Index.TOKENIZED, store = Store.NO,
// analyzer
analyzer = @Analyzer(impl = TextStemmerAnalyzer.class))
private String preferredName;
/**
* Email for person.
*/
@Basic(optional = false)
@NotEmpty
@Email(message = EMAIL_MESSAGE)
private String email;
/**
* Work phone number.
*/
@Length(max = MAX_PHONE_NUMBER_LENGTH, message = PHONE_NUMBER_MESSAGE)
private String workPhone;
/**
* Home phone number.
*/
@Basic(optional = true)
@Length(max = MAX_PHONE_NUMBER_LENGTH, message = PHONE_NUMBER_MESSAGE)
private String cellPhone;
/**
* Fax number.
*/
@Basic(optional = true)
@Length(max = MAX_PHONE_NUMBER_LENGTH, message = FAX_NUMBER_MESSAGE)
private String fax;
/**
* Profile title for person.
*/
@Length(max = MAX_TITLE_LENGTH, message = TITLE_MESSAGE)
@Field(name = "title", index = Index.TOKENIZED,
//
analyzer = @Analyzer(impl = TextStemmerAnalyzer.class), store = Store.NO)
private String title;
/**
* Parent organization.
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parentOrganizationId")
@Fields(value = {
// "parentOrganizationShortName"
@Field(name = "parentOrganizationShortName", index = Index.UN_TOKENIZED, store = Store.NO,
// field bridge
bridge = @FieldBridge(impl = OrganizationToShortNameFieldBridge.class)),
// "parentOrganizationShortNameHierarchy" - a space-separated list of all short names up the tree
@Field(name = "parentOrganizationIdHierarchy", index = Index.TOKENIZED, store = Store.NO,
// WhitespaceAnalyzer to split on spaces, not lowercase, and not use stop words - necessary to mention
// since we're tokenizing
analyzer = @Analyzer(impl = WhitespaceAnalyzer.class),
// field bridge
bridge = @FieldBridge(impl = OrgIdHierarchyFieldBridge.class)) })
private Organization parentOrganization;
/**
* The organizations a person is related to.
*/
@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST })
@JoinTable(name = "Person_RelatedOrganization",
// join columns
joinColumns = { @JoinColumn(table = "Person", name = "personId") },
// inverse join columns
inverseJoinColumns = { @JoinColumn(table = "Organization", name = "organizationId") },
// unique constraints
uniqueConstraints = { @UniqueConstraint(columnNames = { "personId", "organizationId" }) })
private List<Organization> relatedOrganizations = new ArrayList<Organization>();
/**
* Job description for person.
*/
@Basic(optional = true)
@Length(max = MAX_JOB_DESCRIPTION_LENGTH, message = JOB_DESCRIPTION_MESSAGE)
@Field(name = "description", index = Index.TOKENIZED,
// search is using text stemmer, so we need to index searchable fields with it
analyzer = @Analyzer(impl = TextStemmerAnalyzer.class), store = Store.NO)
private String jobDescription;
/**
* Profile biography for person.
*/
@Basic(optional = true)
@Field(name = "biography", index = Index.TOKENIZED, store = Store.NO,
// html-stemmer analyzer will be used for indexing and, text-stemmer for searching
analyzer = @Analyzer(impl = HtmlStemmerAnalyzer.class))
@Lob
private String biography;
/**
* Profile overview for person. This is a short version of the biography.
*/
@Basic(optional = true)
@Length(max = MAX_OVERVIEW_LENGTH, message = OVERVIEW_MESSAGE)
@Field(name = "overview", index = Index.TOKENIZED, store = Store.NO,
// html-stemmer analyzer will be used for indexing and, text-stemmer for searching
analyzer = @Analyzer(impl = HtmlStemmerAnalyzer.class))
private String overview;
/**
* Background information - not managed through Person, here for search indexing.
*/
@OneToOne(mappedBy = "person", fetch = FetchType.LAZY)
@Field(name = "background", bridge = @FieldBridge(impl = BackgroundStringBridge.class), index = Index.TOKENIZED,
// line break
store = Store.NO, analyzer = @Analyzer(impl = TextStemmerAnalyzer.class))
private Background background;
/**
* Job history - not managed through Person, here for search indexing.
*/
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "personId")
@Field(name = "jobs", bridge = @FieldBridge(impl = JobsListStringBridge.class), index = Index.TOKENIZED,
// line break
store = Store.NO, analyzer = @Analyzer(impl = TextStemmerAnalyzer.class))
private List<Job> jobs;
/**
* School Enrollments - not managed through Person, here for search indexing.
*/
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "personId")
@Field(name = "education", bridge = @FieldBridge(impl = EducationListStringBridge.class), index = Index.TOKENIZED,
// line break
store = Store.NO, analyzer = @Analyzer(impl = TextStemmerAnalyzer.class))
private List<Enrollment> schoolEnrollments;
/**
* A ; delimited list of video ids a person has optedOut of seeing.
*/
@Basic
private String optOutVideoIds = "";
/**
* Used for validation.
*/
@Transient
public static final int LOCATION_LENGTH = 5;
/**
* Used for validation.
*/
@Transient
public static final String LOCATION_MESSAGE = "Please use a 5-digit zip code";
/**
* Profile location for person.
*
* @Digits integerDigits tells you *up to* how many digits it can have so we include a minimum length here to make
* sure there are exactly 10.
*/
@Digits(integerDigits = LOCATION_LENGTH, message = LOCATION_MESSAGE)
@Length(min = LOCATION_LENGTH, message = LOCATION_MESSAGE)
@Field(name = "location", index = Index.UN_TOKENIZED, store = Store.NO)
private String location;
/**
* Open social ID.
*/
@Basic
private String openSocialId;
/**
*
*/
@Basic
private Integer avatarCropX;
/**
*
*/
@Basic
private Integer avatarCropY;
/**
*
*/
@Basic
private Integer avatarCropSize;
/**
* The date the user last accepted the terms of service.
*/
@Basic(optional = true)
private Date lastAcceptedTermsOfService = null;
/**
* Count of people following this user.
*/
@Basic(optional = false)
@Field(name = "followersCount", index = Index.UN_TOKENIZED, store = Store.NO)
private int followersCount = 0;
/**
* The number of updates for this person.
*/
@Basic(optional = false)
@Field(name = "updatesCount", index = Index.UN_TOKENIZED, store = Store.NO)
private int updatesCount = 0;
/**
* Count of people this user is following.
*/
@Basic(optional = false)
private int followingCount = 0;
/**
* Count of groups this user is following.
*/
@Basic(optional = false)
private int groupsCount = 0;
/**
* avatar id image for this user.
*/
@Basic
private String avatarId;
/**
* Whether the entity allows comments on their post.
*/
@Basic(optional = false)
@Field(name = "isCommentable", index = Index.UN_TOKENIZED, store = Store.NO)
private boolean commentable = true;
/**
* Whether the entity allows people to post to their stream.
*/
@Basic(optional = false)
@Field(name = "isStreamPostable", index = Index.UN_TOKENIZED, store = Store.NO)
private boolean streamPostable = true;
/**
* Only used for query reference, don't load this.
*/
@SuppressWarnings("unused")
@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
@JoinTable(name = "Follower",
// join columns
joinColumns = { @JoinColumn(table = "Person", name = "followingId") },
// inverse join columns
inverseJoinColumns = { @JoinColumn(table = "Person", name = "followerId") })
private List<Person> followers;
/**
* List of people this user is following.
*/
@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
@JoinTable(name = "Follower",
// join columns
joinColumns = { @JoinColumn(table = "Person", name = "followerId") },
// inverse join columns
inverseJoinColumns = { @JoinColumn(table = "Person", name = "followingId") })
private List<Person> following;
/**
* List of groups this user is following.
*/
@SuppressWarnings("unused")
@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
@JoinTable(name = "GroupFollower",
// join columns
joinColumns = { @JoinColumn(table = "Person", name = "followerId") },
// inverse join columns
inverseJoinColumns = { @JoinColumn(table = "DomainGroup", name = "followingId") })
private List<DomainGroup> followingGroup;
/**
* Start page TabGroup.
*/
@OneToOne(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
@JoinColumn(name = "startTabGroupId", nullable = false)
private TabGroup startTabGroup = new TabGroup();
/**
* The application data for this person.
*/
@SuppressWarnings("unused")
@OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
@JoinColumn(name = "personId")
private List<AppData> appData;
/**
* This field will maintain a link to the corresponding theme for this person.
*/
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "themeId")
private Theme theme;
/**
* Stream scope representing this person.
*/
@OneToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST })
@JoinColumn(name = "streamScopeId")
private StreamScope streamScope;
/**
* StreamView hidden line index for user.
*/
@Basic(optional = false)
private Integer streamViewHiddenLineIndex = 0;
/**
* GroupStream hidden line index for user.
*/
@Basic(optional = false)
private Integer groupStreamHiddenLineIndex = 0;
/**
* Flag indicating if user's account is locked.
*/
@Basic(optional = false)
private boolean accountLocked = false;
/**
* Public constructor for ORM and ResourcePersistenceStrategy.
*/
public Person()
{
}
/**
* Gets the user's name in the standard format for display.
*
* @return Displayed name.
*/
public String getDisplayName()
{
if (displayName == null || displayName.isEmpty())
{
displayName = preferredName + " " + lastName;
}
return displayName;
}
/**
* Set the display name - for de/serialization only.
*
* @param inDisplayName
* the display name to set
*/
@SuppressWarnings("unused")
private void setDisplayName(final String inDisplayName)
{
displayName = inDisplayName;
}
/**
* Allows for getting displayName in a property projection.
*/
@Formula("preferredName || ' ' || lastName")
private String displayName;
/**
* Get the parent org id w/o loading the org.
*/
@Formula("parentOrganizationId")
private Long parentOrgId;
/**
* Optional map of additional properties.
*/
@Basic(optional = true)
private HashMap<String, String> additionalProperties;
/**
* Company name.
*/
@Length(min = 1, max = MAX_FIRST_NAME_LENGTH, message = COMPANY_NAME_MESSAGE)
private String companyName;
/**
* TODO: This is a patch until we stop sending entities over the line
*
* Construct a person from a person model view.
*
* @param personModelView
* the person model view.
*/
public Person(final PersonModelView personModelView)
{
this.setId(personModelView.getEntityId());
avatarId = personModelView.getAvatarId();
setAccountId(personModelView.getAccountId());
openSocialId = personModelView.getOpenSocialId();
this.setOptOutVideos(personModelView.getOptOutVideos());
displayName = personModelView.getDisplayName();
followersCount = personModelView.getFollowersCount();
title = personModelView.getTitle();
email = personModelView.getEmail();
dateAdded = personModelView.getDateAdded();
parentOrganization = new Organization(personModelView.getParentOrganizationName(), personModelView
.getParentOrganizationShortName());
additionalProperties = personModelView.getAdditionalProperties();
lastName = personModelView.getLastName();
preferredName = personModelView.getPreferredName();
}
/**
* Public constructor for API.
*
* @param inAccountId
* unique key for person - lower-cased for uniqueness
* @param inFirstName
* person's first name
* @param inMiddleName
* person's middle name
* @param inLastName
* person's last name
* @param inPreferredName
* name the user prefers to be called
*/
public Person(final String inAccountId, final String inFirstName, final String inMiddleName,
final String inLastName, final String inPreferredName)
{
setAccountId(inAccountId);
firstName = inFirstName;
middleName = inMiddleName;
lastName = inLastName;
preferredName = (inPreferredName == null || inPreferredName.trim().length() == 0) ? inFirstName
: inPreferredName;
displayName = preferredName + " " + lastName;
}
/**
* Get the person's unique key.
*
* @return the unique case-insensitive account id of this Person.
*/
public String getAccountId()
{
return accountId;
}
/**
* Gets the opensocial ID.
*
* @return the open social id.
*/
public String getOpenSocialId()
{
return openSocialId;
}
/**
* Sets the open social id.
*
* @param inOpenSocialId
* the open social id.
*/
public void setOpenSocialId(final String inOpenSocialId)
{
openSocialId = inOpenSocialId;
}
/**
* Returns list of tabs of correct TabGroupType or empty list if none exist.
*
* @param tabGroupType
* The tab type enum value.
* @return list of tabs of correct TabGroupType.
*/
public List<Tab> getTabs(final TabGroupType tabGroupType)
{
switch (tabGroupType)
{
case START:
return startTabGroup != null ? startTabGroup.getTabs() : new ArrayList<Tab>();
default:
return new ArrayList<Tab>();
}
}
/**
* Adds the given tab to the specified tab group type.
*
* @param newTab
* The new tab.
* @param tabGroupType
* The new tab type.
*/
public void addTab(final Tab newTab, final TabGroupType tabGroupType)
{
switch (tabGroupType)
{
case START:
startTabGroup.addTab(newTab);
break;
default:
}
}
/**
* @return the startTabGroup
*/
public TabGroup getStartTabGroup()
{
return startTabGroup;
}
/**
* @param inStartTabGroup
* the startTabGroup to set
*/
public void setStartTabGroup(final TabGroup inStartTabGroup)
{
startTabGroup = inStartTabGroup;
}
/**
* Set the Person's individual theme.
*
* @param inTheme
* the new theme.
*/
public void setTheme(final Theme inTheme)
{
theme = inTheme;
}
/**
* Get the Person's individual theme.
*
* @return the theme
*/
public Theme getTheme()
{
return theme;
}
/**
* Set the Person's biography.
*
* @param inBiography
* the biography.
*/
public void setBiography(final String inBiography)
{
biography = inBiography;
}
/**
* Get the Person's biography.
*
* @return the biography.
*/
public String getBiography()
{
return biography;
}
/**
* Get the person's first name.
*
* @return the first name
*/
public String getFirstName()
{
return firstName;
}
/**
* Get the person's middle name.
*
* @return the middle name
*/
public String getMiddleName()
{
return middleName;
}
/**
* Get the person's last name.
*
* @return the last name
*/
public String getLastName()
{
return lastName;
}
/**
* Get the name the user prefers to be called.
*
* Method is non-final to facilitate mocking.
*
* @return the name the user prefers to be called
*/
public String getPreferredName()
{
return preferredName;
}
/**
* Getter for person's email address.
*
* @return person's email address.
*/
@Override
public String getEmail()
{
return email;
}
/**
* Setter for person's email address.
*
* Hibernate validation on this object requires the attribute to be not null and to be a valid email address.
* (name@domain.com, etc).
*
* @param inEmail
* person's email address.
*/
public void setEmail(final String inEmail)
{
email = inEmail;
}
/**
* @return the workPhone
*/
public String getWorkPhone()
{
return workPhone;
}
/**
* Setter for work phone number.
*
* @param phoneNumber
* The phone number.
*/
public void setWorkPhone(final String phoneNumber)
{
workPhone = phoneNumber;
}
/**
* @return the cellPhone
*/
public String getCellPhone()
{
return cellPhone;
}
/**
* Setter for cell phone number.
*
* @param phoneNumber
* The phone number.
*/
public void setCellPhone(final String phoneNumber)
{
cellPhone = phoneNumber;
}
/**
* @return optout video ids.
*/
@SuppressWarnings("unused")
private String getOptOutVideoIds()
{
return optOutVideoIds;
}
/**
* private methods.
*
* @param inOptOutVideoIds
* the String of opt videos to set.
*/
@SuppressWarnings("unused")
private void setOptOutVideoIds(final String inOptOutVideoIds)
{
optOutVideoIds = inOptOutVideoIds;
}
/**
* NOTE: this method abstracts the way the db stores this data. This returns a copy of the set. Adding to this copy
* will not save to the entity. You must use the set method to modify these values.
*
* @return a COPY of the set of videos a person has opted out of.
*/
@SuppressWarnings("unchecked")
public HashSet<Long> getOptOutVideos()
{
HashSet<Long> videoIdSet = new HashSet();
if (optOutVideoIds != null && !(optOutVideoIds.isEmpty()))
{
String[] videoIdsArray = optOutVideoIds.split(";");
for (String vidId : videoIdsArray)
{
// if it tokenized the ending ; then don't set a blank long.
if (!vidId.isEmpty())
{
videoIdSet.add(Long.valueOf(vidId.trim()));
}
}
}
return videoIdSet;
}
/**
* set the set of videos a person has opted out of.
*
* @param inOptOutVideos
* the set of videos.
*
*/
public void setOptOutVideos(final HashSet<Long> inOptOutVideos)
{
// this tmp variable is being used in case there is a exception then we won't loss data.
String tmpOptOutVideoIds = "";
for (Long vidId : inOptOutVideos)
{
tmpOptOutVideoIds = tmpOptOutVideoIds + vidId + ";";
}
optOutVideoIds = tmpOptOutVideoIds;
}
/**
* @return the fax
*/
public String getFax()
{
return fax;
}
/**
* Setter for fax number.
*
* @param faxNumber
* The phone number.
*/
public void setFax(final String faxNumber)
{
fax = faxNumber;
}
/**
* Getter for job description.
*
* @return job description.
*/
public String getJobDescription()
{
return jobDescription;
}
/**
* Setter for job description.
*
* @param inJobDescription
* person's job description.
*/
public void setJobDescription(final String inJobDescription)
{
jobDescription = inJobDescription;
}
/**
* Getter for person's title.
*
* @return person's title.
*/
public String getTitle()
{
return title;
}
/**
* Setter for person's title.
*
* @param inTitle
* person's title.
*/
public void setTitle(final String inTitle)
{
title = inTitle;
}
/**
* Getter for person's location.
*
* @return person's location.
*/
public String getLocation()
{
return location;
}
/**
* Setter for person's location.
*
* @param inLocation
* person's location.
*/
public void setLocation(final String inLocation)
{
location = inLocation;
}
/**
* @return the followersCount
*/
@Override
public int getFollowersCount()
{
return followersCount;
}
/**
* Private setter for followers count.
*
* @param inFollowersCount
* The count.
*/
@SuppressWarnings("unused")
private void setFollowersCount(final int inFollowersCount)
{
followersCount = inFollowersCount;
}
/**
* @return the followingCount
*/
public int getFollowingCount()
{
return followingCount;
}
/**
* Private setter for followingCount.
*
* @param inFollowingCount
* The count.
*/
@SuppressWarnings("unused")
private void setFollowingCount(final int inFollowingCount)
{
followingCount = inFollowingCount;
}
/**
* @return following
*/
public List<Person> getFollowing()
{
return following;
}
/**
* Get avatar x coord.
*
* @return avatar x coord.
*/
@Override
public Integer getAvatarCropX()
{
return avatarCropX;
}
/**
* Set avatar x coord.
*
* @param value
* x coord.
*/
@Override
public void setAvatarCropX(final Integer value)
{
avatarCropX = value;
}
/**
* Get avatar y coord.
*
* @return avatar y coord.
*/
@Override
public Integer getAvatarCropY()
{
return avatarCropY;
}
/**
* Set avatar y coord.
*
* @param value
* y coord.
*/
@Override
public void setAvatarCropY(final Integer value)
{
avatarCropY = value;
}
/**
* Get avatar crop size.
*
* @return avatar crop size.
*/
@Override
public Integer getAvatarCropSize()
{
return avatarCropSize;
}
/**
* Set avatar crop size.
*
* @param value
* crop size.
*/
@Override
public void setAvatarCropSize(final Integer value)
{
avatarCropSize = value;
}
/**
* @return the avatar Id
*/
@Override
public String getAvatarId()
{
return avatarId;
}
/**
* @param inAvatarId
* the avatar to set
*/
@Override
public void setAvatarId(final String inAvatarId)
{
avatarId = inAvatarId;
}
/**
* Adding private setter to make serialization work.
*
* Hibernate validation on this object requires the first name to be not null, and of length greater than 1 and less
* than MAX_FIRST_NAME_LENGTH
*
* @param inFirstName
* the firstName to set
*/
@SuppressWarnings("unused")
private void setFirstName(final String inFirstName)
{
firstName = inFirstName;
}
/**
* Adding private setter to make serialization work.
*
* @param inMiddleName
* the middleName to set
*/
@SuppressWarnings("unused")
private void setMiddleName(final String inMiddleName)
{
middleName = inMiddleName;
}
/**
* Set the person's last name.
*
* Hibernate validation on this object requires the last name to be not null, and of length greater than 1 and less
* than MAX_LAST_NAME_LENGTH
*
* @param inLastName
* the lastName to set
*/
public void setLastName(final String inLastName)
{
lastName = inLastName;
}
/**
* Set the person's preferred name.
*
* @param inPreferredName
* the preferredName to set
*/
public void setPreferredName(final String inPreferredName)
{
preferredName = inPreferredName;
// reset the display name
displayName = null;
}
/**
* Set the person's unique key, needed for serialization.
*
* @param inAccountId
* the account ID.
*/
private void setAccountId(final String inAccountId)
{
accountId = inAccountId == null ? null : inAccountId.toLowerCase();
}
/**
* @return the parentOrganization
*/
@Override
public Organization getParentOrganization()
{
return parentOrganization;
}
/**
* Returns list of organizations this person is related to.
*
* @return list of organizations this person is related to.
*/
public List<Organization> getRelatedOrganizations()
{
return relatedOrganizations;
}
/**
* Set a list of organizations to be related to this person.
*
* @param inOrganizations
* A list of organizations this person is related to.
*/
public void setRelatedOrganizations(final List<Organization> inOrganizations)
{
relatedOrganizations = inOrganizations;
}
/**
* Add the organization as a relation to this person.
*
* @param inOrganization
* The organization to add as a relation to this person.
*/
public void addRelatedOrganization(final Organization inOrganization)
{
relatedOrganizations.add(inOrganization);
}
/**
* @param inOrganization
* the parentOrganization to set
*/
@Override
public void setParentOrganization(final Organization inOrganization)
{
parentOrganization = inOrganization;
}
/**
* Returns properties of person, this is NOT an all inclusive list, this is used by create and update functionality.
*
* @param includeOrganization
* Flag to include organization in properties or not.
* @return properties of person.
*/
public HashMap<String, Serializable> getProperties(final Boolean includeOrganization)
{
HashMap<String, Serializable> personData = new HashMap<String, Serializable>();
addNonNullProperty("accountId", getAccountId(), personData);
addNonNullProperty("firstName", getFirstName(), personData);
addNonNullProperty("middleName", getMiddleName(), personData);
addNonNullProperty("lastName", getLastName(), personData);
addNonNullProperty("preferredName", getPreferredName(), personData);
addNonNullProperty("email", getEmail(), personData);
addNonNullProperty("workPhone", getWorkPhone(), personData);
addNonNullProperty("fax", getFax(), personData);
addNonNullProperty("cellPhone", getCellPhone(), personData);
addNonNullProperty("jobDescription", getJobDescription(), personData);
addNonNullProperty("title", getTitle(), personData);
addNonNullProperty("location", getLocation(), personData);
addNonNullProperty("accountLocked", isAccountLocked(), personData);
addNonNullProperty("companyName", getCompanyName(), personData);
if (getAdditionalProperties() != null)
{
personData.put("additionalProperties", getAdditionalProperties());
}
if (includeOrganization)
{
addNonNullProperty("organization", getParentOrganization(), personData);
}
return personData;
}
/**
* Adds key/value pairs to a map if non-null.
*
* @param key
* Key to use.
* @param value
* Value to use.
* @param map
* Map to use.
*/
private void addNonNullProperty(final String key, final Serializable value, final Map<String, Serializable> map)
{
// if null or empty string, return instantly.
if (value == null || (value instanceof String && ((String) value).length() == 0))
{
return;
}
map.put(key, value);
}
/**
* @return the overview
*/
public String getOverview()
{
return overview;
}
/**
* @param inOverview
* the overview to set
*/
public void setOverview(final String inOverview)
{
overview = inOverview;
}
/**
* @param inGroupCount
* the groupCount to set
*/
public void setGroupCount(final int inGroupCount)
{
groupsCount = inGroupCount;
}
/**
* @return the groupCount
*/
public int getGroupCount()
{
return groupsCount;
}
/**
* Override equality to be based on the person's id.
*
* @param rhs
* target object
* @return true if equal, false otherwise.
*/
@Override
public boolean equals(final Object rhs)
{
return (rhs instanceof Person && this.getId() == ((Person) rhs).getId() && accountId.equals(((Person) rhs)
.getAccountId()));
}
/**
* set the id - useful for unit testing.
*
* @param newId
* the new id
*/
@Override
protected void setId(final long newId)
{
super.setId(newId);
}
/**
* HashCode override.
*
* @see java.lang.Object#hashCode()
* @return hashcode for object.
*/
@Override
public int hashCode()
{
// NOTE: unable to use HashCodeBuilder here due to GWT limitation.
int hashCode = 0;
hashCode ^= (new Long(getId())).hashCode();
hashCode ^= null != accountId ? accountId.hashCode() : "".hashCode();
return hashCode;
}
/**
* Set the date the user was added to the system.
*
* @param inDateAdded
* the dateAdded to set
*/
protected void setDateAdded(final Date inDateAdded)
{
dateAdded = inDateAdded;
}
/**
* Get the date the person was added to the system.
*
* @return the dateAdded
*/
public Date getDateAdded()
{
return dateAdded;
}
/**
* Get the number of updates for this person.
*
* @return the updatesCount
*/
public int getUpdatesCount()
{
return updatesCount;
}
/**
* Set the number of updates for this person.
*
* @param inUpdatesCount
* the updatesCount to set
*/
protected void setUpdatesCount(final int inUpdatesCount)
{
updatesCount = inUpdatesCount;
}
/**
* Get the Person's jobs.
*
* @return the jobs for a person.
*/
public List<Job> getJobs()
{
return jobs;
}
/**
* Get the Person's background.
*
* @return the Person's background.
*/
public Background getBackground()
{
return background;
}
/**
* Setter for serialization.
*
* @param inBackground
* the background to set
*/
@SuppressWarnings("unused")
private void setBackground(final Background inBackground)
{
background = inBackground;
}
/**
* Get the Person's school enrollments.
*
* @return the Person's school enrollments.
*/
public List<Enrollment> getSchoolEnrollments()
{
return schoolEnrollments;
}
/**
* @return if the profile is set to allow post comments.
*/
public boolean isCommentable()
{
return commentable;
}
/**
* @param inCommentable
* if the profile is set to allow post comments.
*/
public void setCommentable(final boolean inCommentable)
{
commentable = inCommentable;
}
/**
* @return if the profile is set to allow wall post.
*/
public boolean isStreamPostable()
{
return streamPostable;
}
/**
* @param inStreamPostable
* set the steam postable property.
*/
public void setStreamPostable(final boolean inStreamPostable)
{
streamPostable = inStreamPostable;
}
/**
* @return the streamViewHiddenLineIndex
*/
public Integer getStreamViewHiddenLineIndex()
{
return streamViewHiddenLineIndex;
}
/**
* @param inStreamViewHiddenLineIndex
* the streamViewHiddenLineIndex to set
*/
public void setStreamViewHiddenLineIndex(final Integer inStreamViewHiddenLineIndex)
{
streamViewHiddenLineIndex = inStreamViewHiddenLineIndex;
}
/**
* @return the groupStreamHiddenLineIndex
*/
public Integer getGroupStreamHiddenLineIndex()
{
return groupStreamHiddenLineIndex;
}
/**
* @param inGroupStreamHiddenLineIndex
* the groupStreamHiddenLineIndex to set
*/
public void setGroupStreamHiddenLineIndex(final Integer inGroupStreamHiddenLineIndex)
{
groupStreamHiddenLineIndex = inGroupStreamHiddenLineIndex;
}
// ----------------------------------------------------
// ------------------ CACHE UPDATING ------------------
/**
* Call-back after a Person entity has been updated. This tells the static cacheUpdater if set.
*/
@SuppressWarnings("unused")
@PostUpdate
private void onPostUpdate()
{
if (entityCacheUpdater != null)
{
entityCacheUpdater.onPostUpdate(this);
}
}
/**
* Call-back after the entity has been persisted. This tells the static cacheUpdater if set.
*/
@SuppressWarnings("unused")
@PostPersist
private void onPostPersist()
{
if (entityCacheUpdater != null)
{
entityCacheUpdater.onPostPersist(this);
}
}
/**
* The entity cache updater.
*/
private static transient EntityCacheUpdater<Person> entityCacheUpdater;
/**
* Setter for the static PersonUpdater.
*
* @param inEntityCacheUpdater
* the PersonUpdater to set
*/
public static void setEntityCacheUpdater(final EntityCacheUpdater<Person> inEntityCacheUpdater)
{
entityCacheUpdater = inEntityCacheUpdater;
}
// ---------------- END CACHE UPDATING ----------------
// ----------------------------------------------------
/**
* @param inLastAcceptedTermsOfService
* the lastAcceptedTermsOfService to set
*/
public void setLastAcceptedTermsOfService(final Date inLastAcceptedTermsOfService)
{
lastAcceptedTermsOfService = inLastAcceptedTermsOfService;
}
/**
* @return the lastAcceptedTermsOfService
*/
public Date getLastAcceptedTermsOfService()
{
return lastAcceptedTermsOfService;
}
/**
* @return the streamScope
*/
public StreamScope getStreamScope()
{
return streamScope;
}
/**
* @param inStreamScope
* the streamScope to set
*/
public void setStreamScope(final StreamScope inStreamScope)
{
streamScope = inStreamScope;
}
/**
* @return if the account is locked.
*/
public boolean isAccountLocked()
{
return accountLocked;
}
/**
* @param inAccountLocked
* if the account is locked.
*/
public void setAccountLocked(final boolean inAccountLocked)
{
accountLocked = inAccountLocked;
}
/**
* Get the unique id for as implemented for Followable.
*
* @return uniqueId of the person - accountid.
*/
@Override
public String getUniqueId()
{
return getAccountId();
}
/**
* Get the parent org id without loading the parent organization.
*
* @return the parent org id without loading the parent organization
*/
@Override
public Long getParentOrgId()
{
return parentOrgId;
}
/**
* Set the parent org id.
*
* @param inParentOrgId
* the parent org id
*/
protected void setParentOrgId(final Long inParentOrgId)
{
parentOrgId = inParentOrgId;
}
/**
* {@inheritDoc}.
*/
@Override
public String getBannerId()
{
return bannerId;
}
/**
* {@inheritDoc}.
*/
@Override
public void setBannerId(final String inBannerId)
{
bannerId = inBannerId;
}
/**
* {@inheritDoc}.
*/
@Override
public Long getBannerEntityId()
{
return bannerEntityId;
}
/**
* {@inheritDoc}.
*/
@Override
public void setBannerEntityId(final Long inBannerEntityId)
{
bannerEntityId = inBannerEntityId;
}
/**
* {@inheritDoc}
*/
@Override
public String getParentOrganizationName()
{
return parentOrganization.getName();
}
/**
* {@inheritDoc}
*/
@Override
public String getParentOrganizationShortName()
{
return parentOrganization.getShortName();
}
/**
* Get the streams.
*
* @return the streams
*/
public List<Stream> getStreams()
{
return streams;
}
/**
* Set the streams.
*
* @param inStreams
* the streams to set
*/
public void setStreams(final List<Stream> inStreams)
{
streams = inStreams;
}
/**
* The additionalProperties setter.
*
* @param inAdditionalProperties
* the properties hashmap to set
*/
public void setAdditionalProperties(final HashMap<String, String> inAdditionalProperties)
{
additionalProperties = inAdditionalProperties;
}
/**
* The additionalProperties getter.
*
* @return additionalProperties hashmap.
*/
public HashMap<String, String> getAdditionalProperties()
{
return additionalProperties;
}
/**
* TODO: This is a patch until we stop sending entities over the line
*
* Creates a PersonModelView from the person.
*
* @return PersonModelView.
*/
public PersonModelView toPersonModelView()
{
PersonModelView p = new PersonModelView();
p.setEntityId(getId());
p.setAvatarId(avatarId);
p.setAccountId(accountId);
p.setOpenSocialId(openSocialId);
p.setOptOutVideos(getOptOutVideos());
p.setDisplayName(getDisplayName());
p.setFollowersCount(followersCount);
p.setFollowingCount(followingCount);
p.setGroupsCount(groupsCount);
p.setTitle(title);
p.setEmail(email);
p.setDateAdded(dateAdded);
p.setParentOrganizationId(parentOrganization.getId());
p.setParentOrganizationName(parentOrganization.getName());
p.setParentOrganizationShortName(parentOrganization.getShortName());
p.setAdditionalProperties(getAdditionalProperties());
p.setLastName(lastName);
p.setPreferredName(preferredName);
p.setJobDescription(getJobDescription());
p.setCompanyName(getCompanyName());
if (relatedOrganizations != null)
{
List<OrganizationModelView> relatedOrgMvs = new ArrayList<OrganizationModelView>();
for (Organization o : relatedOrganizations)
{
OrganizationModelView orgMv = new OrganizationModelView();
orgMv.setEntityId(o.getId());
orgMv.setShortName(o.getShortName());
orgMv.setName(o.getName());
relatedOrgMvs.add(orgMv);
}
p.setRelatedOrganizations(relatedOrgMvs);
}
p.setAvatarCropSize(avatarCropSize);
p.setAvatarCropX(avatarCropX);
p.setAvatarCropY(avatarCropY);
p.setCellPhone(cellPhone);
p.setWorkPhone(workPhone);
p.setFax(fax);
p.setBannerId(bannerId);
if (background != null)
{
List<String> interests = new ArrayList<String>();
for (BackgroundItem item : background.getBackgroundItems(BackgroundItemType.SKILL))
{
interests.add(item.getName());
}
p.setInterests(interests);
}
p.setBiography(biography);
return p;
}
/**
* Get the company name.
*
* @return the company name.
*/
public String getCompanyName()
{
return companyName;
}
/**
* Set the company name.
*
* @param inCompanyName
* the company name.
*/
public void setCompanyName(final String inCompanyName)
{
companyName = inCompanyName;
}
}