/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.kernel;
// Identity class.
import java.math.BigDecimal;
import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.kernel.permissions.PermissionDescriptor;
import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.DataAssociation;
import com.arsdigita.persistence.DataAssociationCursor;
import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.DataOperation;
import com.arsdigita.persistence.DataQuery;
import com.arsdigita.persistence.Filter;
import com.arsdigita.persistence.OID;
import com.arsdigita.persistence.PersistenceException;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.persistence.metadata.ObjectType;
/**
* Represents a user.
*
* @author Phong Nguyen
* @version $Id: User.java 1586 2007-05-31 13:05:10Z chrisgilbert23 $
**/
public class User extends Party {
private PersonName m_name;
private boolean m_external;
/** An attribute name for the underlying data object. */
public static final String BANNED = "banned";
/**
* Every instance of group must encapsulate a data object whose
* object type is either this base type or a subtype of this base type.
*/
public static final String BASE_DATA_OBJECT_TYPE =
"com.arsdigita.kernel.User";
@Override
protected String getBaseDataObjectType() {
return BASE_DATA_OBJECT_TYPE;
}
/**
* Retrieves a user with the given ID. Use this method instead of
* new User(BigDecimal). This method uses the domain
* object factory to produce the appropriate user class for the
* data object of type User.BASE_DATA_OBJECT_TYPE
* identified by ID.
*
* @param id the ID for the
* DataObject to retrieve
*
* @return the user with the specified ID.
*
* @see Party#Party(OID)
* @see #BASE_DATA_OBJECT_TYPE
* @see com.arsdigita.persistence.DataObject
* @see com.arsdigita.persistence.OID
**/
public static User retrieve(BigDecimal id) throws DataObjectNotFoundException {
return retrieve(new OID(BASE_DATA_OBJECT_TYPE, id));
}
/**
* Retrieves a user with the given OID. Use this method instead of
* the new User(OID) method. This method uses the domain object
* factory to produce the appropriate user class.
*
* @param oid the OID for the retrieved User
* DataObject
*
* @return the user with the specified OID.
*
* @exception DataObjectNotFoundException when
* no user could be retrieved with the given OID.
*
* @see Party#Party(OID)
* @see com.arsdigita.persistence.DataObject
* @see com.arsdigita.persistence.OID
* @see DomainObjectFactory#newInstance(OID)
**/
public static User retrieve(OID oid) throws DataObjectNotFoundException {
User user = (User) DomainObjectFactory.newInstance(oid);
if (user == null) {
throw new
DataObjectNotFoundException("Domain object factory " +
"produced null user for OID " +
oid);
}
return user;
}
/**
* Returns a user for the given data object. Use this method instead
* of the new User(DataObject) method. This method uses the domain
* object factory to produce the appropriate user class.
*
* @param userData the user DataObject
*
* @return the user for the given data object.
**/
public static User retrieve(DataObject userData) {
User user = (User) DomainObjectFactory.newInstance(userData);
if (user == null) {
throw new RuntimeException("Domain object factory produced " +
"null user for data object " +
userData);
}
return user;
}
/**
* Retrieves all users.
*
* @return a collection of all users.
*/
public static UserCollection retrieveAll() {
return new UserCollection( SessionManager.getSession()
.retrieve(BASE_DATA_OBJECT_TYPE) );
}
/**
* @deprecated Use {@link #retrieve(DataObject)}
*/
public User(DataObject userData) {
super(userData);
}
/**
* Default constructor. The contained DataObject is
* initialized with a new DataObject with an
* ObjectType of "User".
*
* An external user is not granted admin permission on their
* user object (so they cannot edit their attributes)
*
* @see Party#Party(String)
* @see com.arsdigita.persistence.DataObject
* @see com.arsdigita.persistence.metadata.ObjectType
**/
public User(boolean external) {
this(BASE_DATA_OBJECT_TYPE);
m_external = external;
}
public User() {
this(false);
}
/**
* Convenience constructor
* @param givenName User's first name
* @param familyName User's last name
* @param email User's email address
* @param external Whether attributes are retrieved from an external source
* An external user is not granted admin permission on their
* user object (so they cannot edit their attributes)
*
**/
public User(String givenName, String familyName, String email, boolean external) {
this(BASE_DATA_OBJECT_TYPE);
getPersonName().setGivenName(givenName);
getPersonName().setFamilyName(familyName);
setPrimaryEmail(new EmailAddress(email));
m_external = external;
}
public User(String givenName, String familyName, String email) {
this(givenName, familyName, email, false);
}
/**
* Constructor in which the contained DataObject is
* initialized with a new DataObject with an
* ObjectType specified by the string
* typeName.
*
* @param typeName the name of the ObjectType of the
* contained DataObject
*
* @see Party#Party(ObjectType)
* @see com.arsdigita.persistence.DataObject
* @see com.arsdigita.persistence.metadata.ObjectType
**/
public User(String typeName) {
super(typeName);
}
/**
* Constructor in which the contained DataObject is
* initialized with a new DataObject with an
* ObjectType specified by type.
*
* @param type the ObjectType of the contained
* DataObject
*
* @see Party#Party(ObjectType)
* @see com.arsdigita.persistence.DataObject
* @see com.arsdigita.persistence.metadata.ObjectType
**/
public User(ObjectType type) throws DataObjectNotFoundException {
super(type);
}
/**
* Constructor. The contained DataObject is retrieved
* from the persistent storage mechanism with an OID
* specified by oid.
*
* @param oid the OID for the retrieved
* DataObject
*
* @deprecated Use {@link #retrieve(OID)} instead. This constructor will
* eventually be made protected.
*
* @see #retrieve(OID)
* @see Party#Party(OID)
* @see com.arsdigita.persistence.DataObject
* @see com.arsdigita.persistence.OID
**/
public User(OID oid) throws DataObjectNotFoundException {
super(oid);
}
/**
* Constructor. The contained DataObject is retrieved
* from the persistent storage mechanism with an OID
* specified by id and User.BASE_DATA_OBJECT_TYPE.
*
* @param id the id for the retrieved
* DataObject
*
* @deprecated Use {@link #retrieve(BigDecimal)} instead.
* This constructor will eventually be made protected.
*
* @see #retrieve(BigDecimal)
* @see Party#Party(OID)
* @see #BASE_DATA_OBJECT_TYPE
* @see com.arsdigita.persistence.DataObject
* @see com.arsdigita.persistence.OID
**/
public User(BigDecimal id) throws DataObjectNotFoundException {
this(new OID(BASE_DATA_OBJECT_TYPE, id));
}
/**
* Called from base class (DomainObject) constructors.
*/
protected void initialize() {
super.initialize();
if (isNew()) {
m_name = new PersonName();
setAssociation("name", m_name);
set(BANNED, new Boolean(false));
}
}
/**
* Returns the screen name for this user.
*
* @return the screen name for the user.
**/
public String getScreenName() {
return (String) get("screenName");
}
/**
* Sets the screen name for this user.
*
* @param screenName the screen name to set for this user
**/
public void setScreenName(String screenName) {
set("screenName", screenName);
}
/**
* Returns the name of this user as a PersonName object.
*
* @return the name of this user as a PersonName object.
*
* @see PersonName
**/
public PersonName getPersonName() {
if (m_name == null) {
DataObject nameData = (DataObject) get("name");
m_name = new PersonName(nameData);
}
return m_name;
}
/**
* Returns the name of this user.
*
* @return the name of this user.
**/
public String getName() {
return getPersonName().toString();
}
/**
* Marks the specified emailAddress as this user's
* primary email address. If this party does not already
* have the specified emailAddress as an email address, it
* will be added using the addEmailAddress() method.
*
* @param emailAddress the email address to set as primary
*
* @pre emailAddress != null
*
* @see Party#addEmailAddress
* @see EmailAddress
**/
public void setPrimaryEmail(EmailAddress emailAddress) {
if (emailAddress == null) {
throw new IllegalArgumentException("User's primary email cannot be null");
}
super.setPrimaryEmail(emailAddress);
}
/**
*
* Returns all groups that the user is a direct or indirect member of.
* For example, if the user is in groups A and B, and group A is a
* subgroup of group C, this method returns groups A, B, and C.
*
* @return the groups that this user is a direct or indirect member of.
*
**/
public GroupCollection getAllGroups() {
DataAssociationCursor assoc =
((DataAssociation) get("allGroups")).cursor();
return new GroupCollection(assoc);
}
/**
*
* Returns the groups that this user is a direct member of.
*
* @return the groups that user is a direct member of.
**/
public GroupCollection getGroups() {
DataAssociationCursor assoc =
((DataAssociation) get("groups")).cursor();
return new GroupCollection(assoc);
}
/**
* Persists any changes made to this object.
*
* @see com.arsdigita.persistence.DataObject#save()
**/
protected void beforeSave() throws PersistenceException {
super.beforeSave();
// If the domain object is new or the primary email has been changed,
// validate it.
if ((isNew() || isPropertyModified("primaryEmail")) && Kernel.getConfig().emailIsPrimaryIdentifier()) {
validatePrimaryEmail();
}
if ((isNew() || isPropertyModified("primaryEmail") || isPropertyModified("screenName"))
&& !Kernel.getConfig().emailIsPrimaryIdentifier()) {
if (getPrimaryEmail() == null) {
throw new RuntimeException("Primary email must be specified");
}
validateScreenName();
}
}
protected void afterSave() {
super.afterSave();
// users have admin permissions on themselves (needed to change
// email, for instance).
if (!m_external) {
PermissionDescriptor perm = new PermissionDescriptor(PrivilegeDescriptor.ADMIN, this, this);
PermissionService.grantPermission(perm);
}
}
/**
* Deletes this user. The EmailAddress service may retain
* persistent data about the email addresses that belonged to this
* user (for example, bouncing status).
*
* @see com.arsdigita.persistence.DataObject#delete()
**/
public void delete() throws PersistenceException {
clearUserFromGroups();
super.delete();
}
public void clearUserFromGroups() throws PersistenceException {
DataOperation op = getDataOperation("com.arsdigita.kernel.ClearUserFromGroups");
op.setParameter("memberID", getID());
op.execute();
}
protected void validatePrimaryEmail() {
EmailAddress email = getPrimaryEmail();
if (email == null) {
throw new RuntimeException("Primary email must be specified");
}
// Verify uniqueness of email
DataQuery query = SessionManager.getSession().retrieveQuery("com.arsdigita.kernel.UserPrimaryEmail");
Filter f = query.addFilter("primaryEmailAddress=:email " + "and userID != :userID");
f.set("email", email.getEmailAddress());
f.set("userID", getID());
if (query.size() > 0) {
throw new RuntimeException("Primary email must be unique among users");
}
}
protected void validateScreenName() {
String sn = getScreenName();
if (sn == null) {
throw new RuntimeException("Screen Name must be specified");
}
// Verify uniqueness of screen name
DataQuery query = SessionManager.getSession().retrieveQuery("com.arsdigita.kernel.UserPrimaryEmail");
Filter f = query.addFilter("lowerScreenName=:sn " + "and userID != :userID");
f.set("sn", sn.toLowerCase());
f.set("userID", getID());
if (query.size() > 0) {
throw new RuntimeException("Screen Name must be unique among users");
}
}
private DataOperation getDataOperation(String name) {
return SessionManager.getSession().retrieveDataOperation(name);
}
/**
* Getter for the banned property, which is persisted to the database
*/
public boolean isBanned() {
return ((Boolean) get(BANNED)).booleanValue();
}
/**
* Setter for the banned property, which is persisted to the database
*/
public void setBanned(boolean b) {
set(BANNED, new Boolean(b));
}
}