package fr.openwide.core.jpa.security.business.person.model;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.MappedSuperclass;
import javax.persistence.OrderBy;
import org.bindgen.Bindable;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.SortComparator;
import org.hibernate.annotations.Type;
import org.hibernate.search.annotations.Analyzer;
import org.hibernate.search.annotations.DocumentId;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Fields;
import org.hibernate.search.annotations.SortableField;
import org.springframework.security.acls.model.Permission;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Sets;
import com.querydsl.core.annotations.PropertyType;
import com.querydsl.core.annotations.QueryType;
import fr.openwide.core.commons.util.collections.CollectionUtils;
import fr.openwide.core.jpa.business.generic.model.GenericEntity;
import fr.openwide.core.jpa.search.util.HibernateSearchAnalyzer;
import fr.openwide.core.jpa.security.business.authority.model.Authority;
import fr.openwide.core.jpa.security.business.person.util.AbstractUserComparator;
@MappedSuperclass
@Bindable
public abstract class GenericUserGroup<G extends GenericUserGroup<G, P>, P extends GenericUser<P, G>>
extends GenericEntity<Long, G>
implements IUserGroup {
private static final long serialVersionUID = 2156717229285615454L;
public static final String NAME_SORT = "nameSort";
@Id
@DocumentId
@GeneratedValue
private Long id;
@Fields({
@Field(analyzer = @Analyzer(definition = HibernateSearchAnalyzer.TEXT)),
@Field(name = NAME_SORT, analyzer = @Analyzer(definition = HibernateSearchAnalyzer.TEXT_SORT))
})
@SortableField(forField = NAME_SORT)
private String name;
/**
* This field is here just to generate bindings (qGenericUserGroup).
* <p>It should not be accessed, since:
* <ol>
* <li>it is not kept up to date when adding a user to a group</li>
* <li>loading it or keeping it up to date may lead to performance issues when groups contain many users (> 10k).
* </ol>
*/
@JsonIgnore
@ManyToMany(mappedBy = "groups")
@SortComparator(AbstractUserComparator.class)
private Set<P> persons = Sets.newTreeSet(AbstractUserComparator.get()); // NOSONAR
@JsonIgnore
@ManyToMany
@Cascade({CascadeType.SAVE_UPDATE})
@OrderBy("name")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<Authority> authorities = new LinkedHashSet<Authority>();
@Type(type = "fr.openwide.core.jpa.hibernate.usertype.StringClobType")
private String description;
@Column(nullable = false)
private boolean locked = false;
public GenericUserGroup() {
}
public GenericUserGroup(String name) {
this.name = name;
}
protected abstract G thisAsConcreteType();
@Override
public Long getId() {
return id;
}
@Override
public void setId(Long id) {
this.id = id;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String getDisplayName() {
return this.getName();
}
@Override
public Set<Authority> getAuthorities() {
return Collections.unmodifiableSet(authorities);
}
public void setAuthorities(Set<Authority> authorities) {
CollectionUtils.replaceAll(this.authorities, authorities);
}
public void addAuthority(Authority authority) {
this.authorities.add(authority);
}
public void removeAuthority(Authority authority) {
this.authorities.remove(authority);
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
@Override
@QueryType(PropertyType.NONE)
public Set<? extends Permission> getPermissions() {
return Sets.newHashSetWithExpectedSize(0);
}
@Override
public int compareTo(G group) {
if(this == group) {
return 0;
}
return DEFAULT_STRING_COLLATOR.compare(this.getName(), group.getName());
}
@Override
public String getNameForToString() {
return getName();
}
}