/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.core.security.group;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.builder.HashCodeBuilder;
import com.enonic.cms.core.security.user.UserEntity;
import com.enonic.cms.core.security.userstore.UserStoreEntity;
import com.enonic.cms.core.security.userstore.UserStoreKey;
public class GroupEntity
implements Serializable
{
private GroupKey key;
private String name;
private String description;
private Integer deleted;
private Integer restricted;
private String syncValue;
private Integer type;
private Set<UserEntity> user = new HashSet<UserEntity>();
private UserStoreEntity userStore;
private Set<GroupEntity> memberships = new LinkedHashSet<GroupEntity>();
private Set<GroupEntity> members = new LinkedHashSet<GroupEntity>();
private transient QualifiedGroupname qualifiedName;
private transient Set<GroupEntity> allMemberships;
private transient List<GroupKey> allMembershipsGroupKeys;
public GroupKey getGroupKey()
{
return key;
}
public String getName()
{
return name;
}
public String getDescription()
{
return description;
}
public boolean isDeleted()
{
return deleted != 0;
}
public boolean isRestricted()
{
return restricted != 0;
}
public String getSyncValue()
{
return syncValue;
}
public GroupType getType()
{
return GroupType.get( type );
}
public UserEntity getUser()
{
if ( user.size() == 1 )
{
return user.iterator().next();
}
else if ( user.size() > 1 )
{
throw new IllegalStateException( "Unexpected number of users with relation to this group: " + user.size() );
}
else
{
return null;
}
}
public UserStoreEntity getUserStore()
{
return userStore;
}
public UserStoreKey getUserStoreKey()
{
return userStore != null ? userStore.getKey() : null;
}
public Set<GroupEntity> getMemberships( boolean includeDeleted )
{
if ( includeDeleted )
{
return memberships;
}
Set<GroupEntity> notDeletedMemberships = new LinkedHashSet<GroupEntity>();
for ( GroupEntity membership : memberships )
{
if ( !membership.isDeleted() )
{
notDeletedMemberships.add( membership );
}
}
return notDeletedMemberships;
}
public Set<GroupEntity> getMembers( boolean includeDeleted )
{
if ( includeDeleted )
{
return members;
}
Set<GroupEntity> notDeletedMembers = new LinkedHashSet<GroupEntity>();
for ( GroupEntity member : members )
{
if ( !member.isDeleted() )
{
notDeletedMembers.add( member );
}
}
return notDeletedMembers;
}
public void setKey( GroupKey value )
{
this.key = value;
}
@Deprecated
public void setKey( String value )
{
this.key = new GroupKey( value );
}
public void setName( String value )
{
this.name = value;
// invalidate
qualifiedName = null;
}
public void setDescription( String value )
{
this.description = value;
}
public void setDeleted( int value )
{
this.deleted = value;
}
public void setDeleted( boolean value )
{
this.deleted = value ? 1 : 0;
}
public void setRestricted( int value )
{
this.restricted = value;
}
public void setRestricted( boolean value )
{
this.restricted = value ? 1 : 0;
}
public void setSyncValue( String value )
{
this.syncValue = value;
}
public void setType( GroupType value )
{
this.type = value.toInteger();
}
public void setUser( UserEntity value )
{
if ( value != null )
{
user.clear();
user.add( value );
}
}
public void setUserStore( UserStoreEntity value )
{
this.userStore = value;
// invalidate
qualifiedName = null;
}
public void setMemberships( Set<GroupEntity> value )
{
this.memberships = value;
}
public void setMembers( Set<GroupEntity> value )
{
this.members = value;
}
public QualifiedGroupname getQualifiedName()
{
if ( qualifiedName == null )
{
if ( isGlobal() )
{
qualifiedName = new QualifiedGroupname( true, null, getName() );
}
else
{
qualifiedName = new QualifiedGroupname( false, getUserStore().getName(), getName() );
}
}
return qualifiedName;
}
public boolean isGlobal()
{
return getType().isGlobal();
}
/**
* @return All memberships group keys including memberships thru other memberships (note that the groups are not
* duplicated).
*/
public List<GroupKey> getAllMembershipsGroupKeys()
{
if ( allMembershipsGroupKeys == null )
{
allMembershipsGroupKeys = new ArrayList<GroupKey>();
for ( GroupEntity group : getAllMemberships() )
{
allMembershipsGroupKeys.add( group.getGroupKey() );
}
}
return allMembershipsGroupKeys;
}
/**
* @return The set of all memberships including memberships thru other memberships (note that the groups are not
* duplicated).
*/
public Set<GroupEntity> getAllMemberships()
{
if ( allMemberships == null )
{
allMemberships = new HashSet<GroupEntity>();
this.doAddAllMemberships( allMemberships );
}
return allMemberships;
}
private void doAddAllMemberships( Set<GroupEntity> allMemberships )
{
for ( GroupEntity membership : getMemberships( false ) )
{
boolean alreadyAdded = allMemberships.contains( membership );
if ( !alreadyAdded )
{
allMemberships.add( membership );
membership.doAddAllMemberships( allMemberships );
}
}
}
public boolean isOfType( final GroupType groupType, boolean recursively )
{
if ( groupType.equals( getType() ) )
{
return true;
}
if ( recursively )
{
GroupMembershipSearcher searcher = new GroupMembershipSearcher()
{
public boolean isGroupFound( GroupEntity traversedGroup )
{
return groupType.equals( traversedGroup.getType() );
}
};
return searcher.startSearch( this );
}
else
{
for ( GroupEntity currGroup : getMemberships( false ) )
{
if ( groupType.equals( currGroup.getType() ) )
{
return true;
}
}
}
return false;
}
public boolean isUserstoreAdmin( final UserStoreEntity userStore )
{
if ( isOfType( GroupType.USERSTORE_ADMINS, false ) )
{
UserStoreEntity currUserStore = getUserStore();
if ( currUserStore != null && currUserStore.equals( userStore ) )
{
return true;
}
}
GroupMembershipSearcher searcher = new GroupMembershipSearcher()
{
public boolean isGroupFound( GroupEntity traversedGroup )
{
if ( GroupType.USERSTORE_ADMINS.equals( traversedGroup.getType() ) )
{
UserStoreEntity currUserStore = traversedGroup.getUserStore();
if ( currUserStore != null && currUserStore.equals( userStore ) )
{
return true;
}
}
return false;
}
};
return searcher.startSearch( this );
}
public boolean isAdministrator()
{
return isOfType( GroupType.ADMINS, true );
}
public boolean isContributor()
{
return isOfType( GroupType.CONTRIBUTORS, true );
}
public boolean isExpertContributor()
{
return isOfType( GroupType.EXPERT_CONTRIBUTORS, true );
}
public boolean isDeveloper()
{
return isOfType( GroupType.DEVELOPERS, true );
}
public boolean isMemberOf( final GroupEntity group, boolean recursively )
{
if ( recursively )
{
GroupMembershipSearcher searcher = new GroupMembershipSearcher()
{
public boolean isGroupFound( GroupEntity traversedGroup )
{
return group.equals( traversedGroup );
}
};
return searcher.startSearch( this );
}
else
{
for ( GroupEntity currGroup : getMemberships( false ) )
{
if ( currGroup.equals( group ) )
{
return true;
}
}
}
return false;
}
public boolean hasMember( GroupEntity group )
{
final Collection<GroupEntity> members = this.getMembers( false );
for ( GroupEntity currGroup : members )
{
if ( group.equals( currGroup ) )
{
return true;
}
}
return false;
}
public GroupEntity addMembership( GroupEntity group )
{
this.memberships.add( group );
group.members.add( this );
return this;
}
public void removeMembership( GroupEntity group )
{
this.memberships.remove( group );
group.members.remove( this );
}
public boolean equals( Object o )
{
if ( this == o )
{
return true;
}
// this breaks the Java equals protocol but is necessary when using potentially proxified object
if ( !( o instanceof GroupEntity ) )
{
return false;
}
GroupEntity that = (GroupEntity) o;
return getGroupKey().equals( that.getGroupKey() );
}
public int hashCode()
{
final int initialNonZeroOddNumber = 133;
final int multiplierNonZeroOddNumber = 77;
return new HashCodeBuilder( initialNonZeroOddNumber, multiplierNonZeroOddNumber ).append( key ).toHashCode();
}
public String toString()
{
StringBuffer s = new StringBuffer();
s.append( "key = " ).append( getGroupKey() ).append( ", name = '" ).append( getName() ).append( "'" );
return s.toString();
}
public boolean isAnonymous()
{
return getType().equals( GroupType.ANONYMOUS );
}
public boolean isBuiltIn()
{
return getType().isBuiltIn();
}
public void removeAllMembers()
{
members.clear();
}
public boolean hasMembership( GroupEntity group )
{
return memberships.contains( group );
}
public Set<GroupEntity> getAllMembersRecursively()
{
return getAllMembersRecursively( null );
}
public Set<GroupEntity> getAllMembersRecursively( final Set<GroupType> groupTypeFilter )
{
Set<GroupEntity> allMembers = new LinkedHashSet<GroupEntity>();
return getAllMembersRecursively( this, allMembers, groupTypeFilter );
}
private Set<GroupEntity> getAllMembersRecursively( final GroupEntity root, final Set<GroupEntity> allMembers,
final Set<GroupType> groupTypeFilter )
{
if ( allMembers.contains( root ) )
{
return allMembers;
}
final boolean checkGroupFilter = groupTypeFilter != null ? true : false;
Iterator<GroupEntity> membersIterator = getMembers( false ).iterator();
while ( membersIterator.hasNext() )
{
GroupEntity member = membersIterator.next();
if ( allMembers.contains( member ) || member.equals( root ) )
{
continue;
}
if ( checkGroupFilter && !groupTypeFilter.contains( member.getType() ) )
{
allMembers.addAll( member.getAllMembersRecursively( root, allMembers, groupTypeFilter ) );
}
else
{
allMembers.add( member );
allMembers.addAll( member.getAllMembersRecursively( root, allMembers, groupTypeFilter ) );
}
}
return allMembers;
}
public boolean isInUserStore()
{
return getType().equals( GroupType.USER ) || getType().equals( GroupType.USERSTORE_GROUP ) ||
getType().equals( GroupType.USERSTORE_ADMINS ) ||
getType().equals( GroupType.AUTHENTICATED_USERS );
}
}