package com.constellio.model.services.users;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.jdom2.Document;
import com.constellio.data.dao.managers.config.ConfigManager;
import com.constellio.data.dao.managers.config.DocumentAlteration;
import com.constellio.data.dao.managers.config.events.ConfigUpdatedEventListener;
import com.constellio.model.entities.security.global.GlobalGroup;
import com.constellio.model.entities.security.global.GlobalGroupStatus;
import com.constellio.model.entities.security.global.XmlGlobalGroup;
import com.constellio.model.services.users.GlobalGroupsManagerRuntimeException.GlobalGroupsManagerRuntimeException_InvalidParent;
import com.constellio.model.services.users.GlobalGroupsManagerRuntimeException.GlobalGroupsManagerRuntimeException_ParentNotFound;
public class XmlGlobalGroupsManager implements GlobalGroupsManager, ConfigUpdatedEventListener {
public static final String CONFIG_FILE = "/globalGroups.xml";
private final ConfigManager configManager;
Map<String, GlobalGroup> cache = new HashMap<>();
Map<String, List<String>> cacheRelation = new HashMap<>();
public XmlGlobalGroupsManager(ConfigManager configManager) {
this.configManager = configManager;
}
@Override
public void initialize() {
registerListener(configManager);
}
@Override
public GlobalGroup create(String code, String name, List<String> collections, String parent, GlobalGroupStatus status, boolean locallyCreated) {
return new XmlGlobalGroup(code, name, collections, parent, status, locallyCreated);
}
@Override
public GlobalGroup create(String code, String parent, GlobalGroupStatus status, boolean locallyCreated) {
return create(code, code, Collections.<String>emptyList(), parent, status, locallyCreated);
}
@Override
public void addUpdate(GlobalGroup globalGroup) {
if (globalGroup.getParent() != null) {
if (getGlobalGroupWithCode(globalGroup.getParent()) == null) {
throw new GlobalGroupsManagerRuntimeException_ParentNotFound();
} else if (globalGroup.getParent().equals(globalGroup.getCode()) || isInHierarchy(globalGroup.getCode(),
globalGroup.getParent())) {
throw new GlobalGroupsManagerRuntimeException_InvalidParent(globalGroup.getParent());
}
}
configManager.updateXML(CONFIG_FILE, newAddUpdateGlobalGroupsDocumentAlteration(globalGroup));
}
@Override
public void logicallyRemoveGroup(GlobalGroup globalGroup) {
configManager.updateXML(CONFIG_FILE, newRemoveGlobalGroupDocumentAlteration(getHierarchy(globalGroup.getCode())));
}
@Override
public GlobalGroup getGlobalGroupWithCode(String code) {
return cache.get(code);
}
@Override
public GlobalGroup getActiveGlobalGroupWithCode(String code) {
GlobalGroup group = getGlobalGroupWithCode(code);
if (group == null || group.getStatus() != GlobalGroupStatus.ACTIVE) {
return null;
} else {
return group;
}
}
@Override
public List<GlobalGroup> getActiveGroups() {
List<GlobalGroup> activeGlobalGroups = new ArrayList<>();
for (GlobalGroup globalGroup : getAllGroups()) {
if (globalGroup.getStatus() == GlobalGroupStatus.ACTIVE) {
activeGlobalGroups.add(globalGroup);
}
}
return Collections.unmodifiableList(activeGlobalGroups);
}
@Override
public List<GlobalGroup> getAllGroups() {
List<GlobalGroup> globalGroups = new ArrayList<>(cache.values());
return Collections.unmodifiableList(globalGroups);
}
@Override
public void activateGlobalGroupHierarchy(GlobalGroup globalGroup) {
for (GlobalGroup group : getHierarchy(globalGroup.getCode())) {
group = group.withStatus(GlobalGroupStatus.ACTIVE);
addUpdate(group);
}
}
boolean isInHierarchy(String hierarchyCode, String code) {
if (getChildrenOf(hierarchyCode).contains(code)) {
return true;
} else {
for (String child : getChildrenOf(hierarchyCode)) {
return isInHierarchy(child, code);
}
return false;
}
}
@Override
public List<GlobalGroup> getHierarchy(String hierarchyCode) {
List<GlobalGroup> hierarchy = new ArrayList<>();
List<String> hierarchyCodes = new ArrayList<>();
getHierarchy(hierarchyCode, hierarchyCodes);
for (String code : hierarchyCodes) {
GlobalGroup group = getGlobalGroupWithCode(code);
if (group != null) {
hierarchy.add(getGlobalGroupWithCode(code));
}
}
return hierarchy;
}
List<String> getHierarchy(String hierarchyCode, List<String> hierarchyCodes) {
hierarchyCodes.add(hierarchyCode);
for (String child : getChildrenOf(hierarchyCode)) {
hierarchyCodes.add(child);
hierarchyCodes = getHierarchy(child, hierarchyCodes);
}
return hierarchyCodes;
}
List<String> getChildrenOf(String code) {
List<String> result = new ArrayList<>();
if (cacheRelation.containsKey(code)) {
result = cacheRelation.get(code);
}
return result;
}
@Override
public void onConfigUpdated(String configPath) {
load();
}
private void load() {
Document document = configManager.getXML(CONFIG_FILE).getDocument();
GlobalGroupsReader reader = newGlobalGroupsReader(document);
cache = Collections.unmodifiableMap(reader.readAll());
loadCacheRelations();
}
private void loadCacheRelations() {
cacheRelation = new HashMap<>();
List children;
for (Entry<String, GlobalGroup> globalGroupEntry : cache.entrySet()) {
if (globalGroupEntry.getValue().getParent() != null) {
String parent = globalGroupEntry.getValue().getParent();
children = cacheRelation.get(parent);
if (children == null) {
children = new ArrayList();
}
children.add(globalGroupEntry.getKey());
cacheRelation.put(parent, children);
}
}
}
DocumentAlteration newAddUpdateGlobalGroupsDocumentAlteration(final GlobalGroup globalGroup) {
return new DocumentAlteration() {
@Override
public void alter(Document document) {
newGlobalGroupsWriter(document).addUpdate(globalGroup);
}
};
}
DocumentAlteration newRemoveGlobalGroupDocumentAlteration(final List<GlobalGroup> globalGroupCodes) {
return new DocumentAlteration() {
@Override
public void alter(Document document) {
newGlobalGroupsWriter(document).logicallyRemove(globalGroupCodes);
}
};
}
DocumentAlteration newRemoveCollectionDocumentAlteration(final String collection) {
return new DocumentAlteration() {
@Override
public void alter(Document document) {
newGlobalGroupsWriter(document).removeCollection(collection);
}
};
}
void registerListener(ConfigManager configManager) {
if (!configManager.exist(CONFIG_FILE)) {
createEmptyGlobalGroupsConfig();
}
load();
configManager.registerListener(CONFIG_FILE, this);
}
void createEmptyGlobalGroupsConfig() {
Document document = new Document();
GlobalGroupsWriter writer = newGlobalGroupsWriter(document);
writer.createEmptyGlobalGroups();
configManager.add(CONFIG_FILE, document);
}
GlobalGroupsWriter newGlobalGroupsWriter(Document document) {
return new GlobalGroupsWriter(document);
}
GlobalGroupsReader newGlobalGroupsReader(Document document) {
return new GlobalGroupsReader(document);
}
@Override
public void close() {
}
@Override
public void removeCollection(String collection) {
configManager.updateXML(CONFIG_FILE, newRemoveCollectionDocumentAlteration(collection));
}
}