package org.fenixedu.bennu.core.groups;
import java.util.Optional;
import java.util.stream.Stream;
import org.fenixedu.bennu.core.domain.User;
import org.fenixedu.bennu.core.domain.exceptions.BennuCoreDomainException;
import org.fenixedu.bennu.core.domain.groups.PersistentDynamicGroup;
import org.fenixedu.commons.i18n.LocalizedString;
import org.joda.time.DateTime;
/**
* Named link to a group.
*
* @author Pedro Santos (pedro.miguel.santos@tecnico.ulisboa.pt)
* @see Group
*/
public final class DynamicGroup extends Group {
private static final long serialVersionUID = -8544141315269000405L;
/**
* This instance must be defined here to prevent cyclical initialization issues (i.e., trying to create a new DynamicGroup
* before the Group class is fully initialized).
*/
static final DynamicGroup MANAGERS = DynamicGroup.get("managers");
private final String name;
DynamicGroup(String name) {
super();
this.name = validateName(name);
}
private String validateName(String name) {
if (!GroupParser.isValidIdentifier(name)) {
throw BennuCoreDomainException.invalidGroupIdentifier(name);
}
return name;
}
public static DynamicGroup get(String name) {
return new DynamicGroup(name);
}
public boolean isDefined() {
return PersistentDynamicGroup.getInstance(name).isPresent();
}
@Override
public PersistentDynamicGroup toPersistentGroup() {
return PersistentDynamicGroup.getInstance(name).orElseGet(
() -> PersistentDynamicGroup.set(name, Group.nobody().toPersistentGroup()));
}
@Override
public String getPresentationName() {
return PersistentDynamicGroup.getInstance(name).map(PersistentDynamicGroup::getCustomPresentationName)
.map(LocalizedString::getContent).orElseGet(() -> name + ": (" + underlyingGroup().getPresentationName() + ")");
}
@Override
public String getExpression() {
return "#" + name;
}
@Override
public Stream<User> getMembers() {
return underlyingGroup().getMembers();
}
@Override
public Stream<User> getMembers(DateTime when) {
return underlyingGroup(when).getMembers(when);
}
@Override
public boolean isMember(User user) {
return underlyingGroup().isMember(user);
}
@Override
public boolean isMember(User user, DateTime when) {
return underlyingGroup(when).isMember(user, when);
}
public Group underlyingGroup() {
Optional<PersistentDynamicGroup> persistent = PersistentDynamicGroup.getInstance(name);
if (persistent.isPresent()) {
return persistent.get().getGroup().toGroup();
}
return Group.nobody();
}
public Group underlyingGroup(DateTime when) {
Optional<PersistentDynamicGroup> persistent = PersistentDynamicGroup.getInstance(name);
if (persistent.isPresent()) {
return persistent.get().getGroup(when).toGroup();
}
return Group.nobody();
}
public String getName() {
return name;
}
@Override
public boolean equals(Object object) {
if (object instanceof DynamicGroup) {
return name.equals(((DynamicGroup) object).name);
}
return false;
}
@Override
public int hashCode() {
return name.hashCode();
}
/**
* Returns a {@link Mutator} that allows access to operations that will change the state
* of this dynamic group.
*
* @return
* A {@link Mutator} for this Dynamic Group.
*/
public DynamicGroup.Mutator mutator() {
return new Mutator();
}
/**
* A {@link Mutator} allows access to operations that change the state of the Dynamic Group.
*
* All the methods in this class behave like the ones in {@link Group}, only instead of returning
* a new group, change the underlying one with the same semantics.
*
*/
public class Mutator {
/**
* Changes the underlying group for this Dynamic Group.
*
* @param group
* The new underlying group
* @return
* This Dynamic Group, with the new underlying group.
*/
public DynamicGroup changeGroup(Group group) {
PersistentDynamicGroup.set(name, group.toPersistentGroup());
return DynamicGroup.this;
}
/**
* Changes the name for this Dynamic Group.
*
* @param name
* The new name.
* @return
* A new Dynamic Group, with a new name.
*/
public DynamicGroup rename(String name) {
Optional<PersistentDynamicGroup> persistent = PersistentDynamicGroup.getInstance(name);
if (persistent.isPresent()) {
persistent.get().rename(name);
}
return new DynamicGroup(name);
}
/**
* Sets a custom presentation name for this dynamic group.
*
* @param presentationName
* The new presentation name for this Dynamic Group.
* @return
* This Dynamic Group, with the new presentation name.
*/
public DynamicGroup setPresentationName(LocalizedString presentationName) {
toPersistentGroup().changePresentationName(presentationName);
return DynamicGroup.this;
}
public DynamicGroup and(Group group) {
return changeGroup(underlyingGroup().and(group));
}
public DynamicGroup or(Group group) {
return changeGroup(underlyingGroup().or(group));
}
public DynamicGroup minus(Group group) {
return changeGroup(underlyingGroup().minus(group));
}
public DynamicGroup not() {
return changeGroup(underlyingGroup().not());
}
public DynamicGroup grant(User user) {
return changeGroup(underlyingGroup().grant(user));
}
public DynamicGroup revoke(User user) {
return changeGroup(underlyingGroup().revoke(user));
}
}
}