Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
pl.edu.icm.unity.webadmin.groupbrowser.GroupsTree Maven / Gradle / Ivy
/*
* Copyright (c) 2013 ICM Uniwersytet Warszawski All rights reserved.
* See LICENCE.txt file for licensing information.
*/
package pl.edu.icm.unity.webadmin.groupbrowser;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.vaadin.data.TreeData;
import com.vaadin.data.provider.TreeDataProvider;
import com.vaadin.event.ExpandEvent;
import com.vaadin.event.ExpandEvent.ExpandListener;
import com.vaadin.shared.ui.Orientation;
import com.vaadin.shared.ui.dnd.DropEffect;
import com.vaadin.shared.ui.grid.DropMode;
import com.vaadin.ui.TreeGrid;
import com.vaadin.ui.components.grid.GridDragSource;
import com.vaadin.ui.components.grid.SingleSelectionModel;
import com.vaadin.ui.components.grid.TreeGridDropTarget;
import com.vaadin.ui.renderers.HtmlRenderer;
import io.imunity.webadmin.directoryBrowser.GroupChangedEvent;
import io.imunity.webadmin.groupbrowser.GroupAttributesClassesDialog;
import io.imunity.webadmin.groupbrowser.GroupDelegationEditConfigDialog;
import io.imunity.webadmin.groupbrowser.GroupEditDialog;
import io.imunity.webadmin.groupbrowser.TreeNode;
import io.imunity.webadmin.idcreate.EntityCreationHandler;
import io.imunity.webadmin.reg.forms.EnquiryFormEditor;
import io.imunity.webadmin.reg.forms.RegistrationFormEditor;
import io.imunity.webadmin.utils.GroupManagementHelper;
import pl.edu.icm.unity.MessageSource;
import pl.edu.icm.unity.engine.api.AttributeClassManagement;
import pl.edu.icm.unity.engine.api.AttributeTypeManagement;
import pl.edu.icm.unity.engine.api.EnquiryManagement;
import pl.edu.icm.unity.engine.api.EntityManagement;
import pl.edu.icm.unity.engine.api.GroupsManagement;
import pl.edu.icm.unity.engine.api.RegistrationsManagement;
import pl.edu.icm.unity.engine.api.authn.InvocationContext;
import pl.edu.icm.unity.engine.api.authn.LoginSession;
import pl.edu.icm.unity.engine.api.bulk.BulkGroupQueryService;
import pl.edu.icm.unity.engine.api.bulk.GroupStructuralData;
import pl.edu.icm.unity.engine.api.utils.GroupDelegationConfigGenerator;
import pl.edu.icm.unity.exceptions.AuthorizationException;
import pl.edu.icm.unity.exceptions.EngineException;
import pl.edu.icm.unity.types.basic.EntityParam;
import pl.edu.icm.unity.types.basic.Group;
import pl.edu.icm.unity.types.basic.GroupContents;
import pl.edu.icm.unity.types.basic.Identity;
import pl.edu.icm.unity.webadmin.identities.IdentitiesGrid;
import pl.edu.icm.unity.webui.WebSession;
import pl.edu.icm.unity.webui.bus.EventsBus;
import pl.edu.icm.unity.webui.common.ConfirmWithOptionDialog;
import pl.edu.icm.unity.webui.common.DnDGridUtils;
import pl.edu.icm.unity.webui.common.EntityWithLabel;
import pl.edu.icm.unity.webui.common.GridContextMenuSupport;
import pl.edu.icm.unity.webui.common.HamburgerMenu;
import pl.edu.icm.unity.webui.common.Images;
import pl.edu.icm.unity.webui.common.NotificationPopup;
import pl.edu.icm.unity.webui.common.SingleActionHandler;
import pl.edu.icm.unity.webui.common.Styles;
import pl.edu.icm.unity.webui.common.Toolbar;
/**
* Tree with groups obtained dynamically from the engine.
*
* @author K. Benedyczak
*/
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class GroupsTree extends TreeGrid
{
private GroupsManagement groupsMan;
private EntityManagement identitiesMan;
private MessageSource msg;
private EventsBus bus;
private AttributeClassManagement acMan;
private TreeData treeData;
private GridContextMenuSupport contextMenuSupp;
private EntityCreationHandler entityCreationDialogHandler;
private Toolbar toolbar;
private BulkGroupQueryService bulkQueryService;
private RegistrationsManagement registrationMan;
private EnquiryManagement enquiryMan;
private AttributeTypeManagement attrTypeMan;
private ObjectFactory regFormEditorFactory;
private ObjectFactory enquiryFormEditorFactory;
private GroupDelegationConfigGenerator delConfigUtils;
@Autowired
public GroupsTree(GroupsManagement groupsMan, EntityManagement identitiesMan,
MessageSource msg, AttributeClassManagement acMan,
EntityCreationHandler entityCreationDialogHandler,
GroupManagementHelper groupManagementHelper,
BulkGroupQueryService bulkQueryService,
RegistrationsManagement registrationMan,
EnquiryManagement enquiryMan,
AttributeTypeManagement attrTypeMan, ObjectFactory regFormEditorFactory,
ObjectFactory enquiryFormEditorFactory,
GroupDelegationConfigGenerator delConfigGenerator)
{
this.groupsMan = groupsMan;
this.identitiesMan = identitiesMan;
this.msg = msg;
this.acMan = acMan;
this.entityCreationDialogHandler = entityCreationDialogHandler;
this.bulkQueryService = bulkQueryService;
this.registrationMan = registrationMan;
this.enquiryMan = enquiryMan;
this.attrTypeMan = attrTypeMan;
this.regFormEditorFactory = regFormEditorFactory;
this.enquiryFormEditorFactory = enquiryFormEditorFactory;
this.delConfigUtils = delConfigGenerator;
contextMenuSupp = new GridContextMenuSupport<>(this);
addExpandListener(new GroupExpandListener());
addSelectionListener(e -> {
final TreeNode node = getSelection();
bus.fireEvent(new GroupChangedEvent(node == null ? null : node.getPath()));
});
SingleSelectionModel singleSelect = (SingleSelectionModel) getSelectionModel();
singleSelect.setDeselectAllowed(false);
toolbar = new Toolbar<>(Orientation.HORIZONTAL);
addSelectionListener(toolbar.getSelectionListener());
HamburgerMenu hamburgerMenu = new HamburgerMenu<>();
addSelectionListener(hamburgerMenu.getSelectionListener());
SingleActionHandler refreshAction = getRefreshAction();
addActionHandler(refreshAction);
SingleActionHandler expandAllAction = getExpandAllAction();
addActionHandler(expandAllAction);
SingleActionHandler collapseAllAction = getCollapseAllAction();
addActionHandler(collapseAllAction);
SingleActionHandler addAction = getAddAction();
addActionHandler(addAction);
SingleActionHandler editAction = getEditAction();
addActionHandler(editAction);
SingleActionHandler editACAction = getEditACsAction();
addActionHandler(editACAction);
SingleActionHandler editDelegationConfigAction = getEditDelegationConfigAction();
addActionHandler(editDelegationConfigAction);
SingleActionHandler deleteAction = getDeleteAction();
addActionHandler(deleteAction);
SingleActionHandler addEntityAction = getAddEntityAction();
addActionHandler(addEntityAction);
toolbar.addActionHandler(addAction);
toolbar.addActionHandler(deleteAction);
hamburgerMenu.addActionHandler(refreshAction);
hamburgerMenu.addActionHandler(expandAllAction);
hamburgerMenu.addActionHandler(collapseAllAction);
hamburgerMenu.addActionHandler(editAction);
hamburgerMenu.addActionHandler(editACAction);
hamburgerMenu.addActionHandler(editDelegationConfigAction);
hamburgerMenu.addActionHandler(addEntityAction);
toolbar.addHamburger(hamburgerMenu);
this.bus = WebSession.getCurrent().getEventBus();
treeData = new TreeData<>();
setDataProvider(new GroupsDataProvider(treeData));
addColumn(n -> n.getIcon() + " " + n.toString(), new HtmlRenderer());
setHeaderVisible(false);
setPrimaryStyleName(Styles.vGroupBrowser.toString());
setRowHeight(34);
setSizeFull();
setupDragNDrop(groupManagementHelper);
try
{
setupRoot();
} catch (EngineException e)
{
// this will show error node
TreeNode parent = new TreeNode(msg, new Group("/"),
Images.folder_open_o.getHtml());
treeData.addItems(null, parent);
getDataProvider().refreshAll();
expand(parent);
}
}
@SuppressWarnings("unchecked")
private void setupDragNDrop(GroupManagementHelper groupManagementHelper)
{
TreeGridDropTarget dropTarget = new TreeGridDropTarget<>(this,
DropMode.ON_TOP);
dropTarget.setDropEffect(DropEffect.MOVE);
dropTarget.setDropCriteriaScript(DnDGridUtils
.getTypedCriteriaScript(IdentitiesGrid.ENTITY_DND_TYPE));
dropTarget.addGridDropListener(e -> {
e.getDragSourceExtension().ifPresent(source -> {
if (source instanceof GridDragSource
&& e.getDropTargetRow().isPresent()
&& source.getDragData() != null)
{
Set dragData = (Set) source
.getDragData();
groupManagementHelper.bulkAddToGroup(
e.getDropTargetRow().get().getPath(),
dragData, true);
}
});
});
}
private void addActionHandler(SingleActionHandler actionHandler)
{
contextMenuSupp.addActionHandler(actionHandler);
}
public List> getActionHandlers()
{
return contextMenuSupp.getActionHandlers();
}
public Toolbar getToolbar()
{
return toolbar;
}
/**
* We can have two cases: either we can read '/' or not. In the latter
* case we take groups where the logged user is the member, and we put
* all of them as root groups.
*
* @throws EngineException
*/
private void setupRoot() throws EngineException
{
try
{
GroupContents contents = groupsMan.getContents("/",
GroupContents.GROUPS | GroupContents.METADATA);
TreeNode parent = new TreeNode(msg, contents.getGroup(),
Images.folder_open_o.getHtml());
treeData.clear();
treeData.addItem(null, parent);
getDataProvider().refreshAll();
expand(parent);
} catch (AuthorizationException e)
{
setupAccessibleRoots();
}
}
private void setupAccessibleRoots() throws EngineException
{
LoginSession ae = InvocationContext.getCurrent().getLoginSession();
Collection groups = identitiesMan
.getGroups(new EntityParam(ae.getEntityId())).keySet();
List accessibleGroups = new ArrayList<>(groups.size());
for (String groupM : groups)
{
try
{
groupsMan.getContents(groupM, GroupContents.GROUPS);
} catch (AuthorizationException e2)
{
continue;
}
accessibleGroups.add(groupM);
}
treeData.clear();
for (int i = 0; i < accessibleGroups.size(); i++)
{
Group groupG = new Group(accessibleGroups.get(i));
boolean parentFound = false;
for (int j = 0; j < accessibleGroups.size(); j++)
{
if (i == j)
continue;
if (groupG.isChild(new Group(accessibleGroups.get(j))))
{
parentFound = true;
break;
}
}
if (!parentFound)
{
try
{
GroupContents contents = groupsMan.getContents(
accessibleGroups.get(i),
GroupContents.METADATA);
TreeNode parent = new TreeNode(msg, contents.getGroup(),
Images.folder_open_o.getHtml());
treeData.addItem(null, parent);
} catch (AuthorizationException e2)
{
continue;
}
}
getDataProvider().refreshAll();
}
}
public void refresh()
{
for (TreeNode rootItem : treeData.getRootItems())
refreshNode(rootItem);
}
private void refreshNode(TreeNode node)
{
if (node == null)
{
refresh();
return;
}
node.setContentsFetched(false);
getDataProvider().refreshAll();
collapse(node);
expand(node);
}
private void removeGroup(TreeNode parent, String path, boolean recursive)
{
try
{
groupsMan.removeGroup(path, recursive);
refreshNode(parent);
select(parent);
} catch (Exception e)
{
NotificationPopup.showError(msg,
msg.getMessage("GroupsTree.removeGroupError"), e);
}
}
private void createGroup(Group toBeCreated)
{
try
{
groupsMan.addGroup(toBeCreated);
} catch (Exception e)
{
NotificationPopup.showError(msg, msg.getMessage("GroupsTree.addGroupError"),
e);
}
}
private void updateGroup(String path, Group group)
{
try
{
groupsMan.updateGroup(path, group, "manual update", "");
} catch (Exception e)
{
NotificationPopup.showError(msg,
msg.getMessage("GroupsTree.updateGroupError"), e);
}
}
private SingleActionHandler getAddAction()
{
return SingleActionHandler.builder(TreeNode.class)
.withCaption(msg.getMessage("add"))
.withIcon(Images.add.getResource()).withHandler(this::showAddDialog)
.build();
}
private void showAddDialog(Collection target)
{
final TreeNode node = target.iterator().next();
new GroupEditDialog(msg, new Group(node.getPath()), false, g -> {
createGroup(g);
refreshNode(node);
}).show();
}
private SingleActionHandler getEditACsAction()
{
return SingleActionHandler.builder(TreeNode.class)
.withCaption(msg.getMessage("GroupDetails.editACAction"))
.withIcon(Images.attributes.getResource())
.withHandler(this::showEditACsDialog).build();
}
private void showEditACsDialog(Collection target)
{
final TreeNode node = target.iterator().next();
GroupAttributesClassesDialog dialog = new GroupAttributesClassesDialog(msg,
node.getPath(), acMan, groupsMan,
g -> bus.fireEvent(new GroupChangedEvent(node.getPath())));
dialog.show();
}
private Group resolveGroup(TreeNode node)
{
Group group = null;
try
{
group = groupsMan.getContents(node.getPath(), GroupContents.METADATA)
.getGroup();
} catch (Exception e)
{
NotificationPopup.showError(msg,
msg.getMessage("GroupsTree.resolveGroupError"), e);
}
return group;
}
private SingleActionHandler getEditAction()
{
return SingleActionHandler.builder4Edit(msg, TreeNode.class)
.withHandler(this::showEditDialog).build();
}
private void showEditDialog(Collection target)
{
TreeNode node = target.iterator().next();
Group group = resolveGroup(node);
if (group == null)
return;
new GroupEditDialog(msg, group, true, g -> {
updateGroup(node.getPath(), g);
refreshNode(node.getParentNode());
if (node.equals(getSelection()))
bus.fireEvent(new GroupChangedEvent(node.getPath()));
}).show();
}
private SingleActionHandler getEditDelegationConfigAction()
{
return SingleActionHandler.builder(TreeNode.class)
.withCaption(msg.getMessage("GroupsTree.editDelegationConfigAction"))
.withIcon(Images.forward.getResource())
.withHandler(this::showEditDelegationCondigDialog).build();
}
private void showEditDelegationCondigDialog(Collection target)
{
TreeNode node = target.iterator().next();
Group group = resolveGroup(node);
if (group == null)
return;
new GroupDelegationEditConfigDialog(msg, registrationMan, enquiryMan, attrTypeMan, regFormEditorFactory,
enquiryFormEditorFactory, bus, delConfigUtils, group, delConfig -> {
group.setDelegationConfiguration(delConfig);
updateGroup(node.getPath(), group);
}).show();
}
private TreeNode getSelection()
{
try
{
return getSelectedItems().iterator().next();
} catch (Exception e)
{
return null;
}
}
private SingleActionHandler getAddEntityAction()
{
return SingleActionHandler.builder(TreeNode.class)
.withCaption(msg.getMessage("GroupsTree.addEntityAction"))
.withIcon(Images.addEntity.getResource())
.withHandler(this::showAddEntityDialog).build();
}
private void showAddEntityDialog(Collection target)
{
final TreeNode node = target.iterator().next();
entityCreationDialogHandler.showAddEntityDialog(() -> node.getPath(),
i -> onCreatedIdentity(node, i));
}
private void onCreatedIdentity(TreeNode node, Identity newIdentity)
{
if (node.equals(getSelection()))
bus.fireEvent(new GroupChangedEvent(node.getPath()));
}
private SingleActionHandler getRefreshAction()
{
return SingleActionHandler.builder4Refresh(msg, TreeNode.class)
.withHandler(selection -> selection.forEach(this::refreshNode))
.build();
}
private SingleActionHandler getDeleteAction()
{
return SingleActionHandler.builder4Delete(msg, TreeNode.class)
.withHandler(this::deleteHandler).build();
}
private void deleteHandler(Collection items)
{
final TreeNode node = items.iterator().next();
new ConfirmWithOptionDialog(msg,
msg.getMessage("GroupRemovalDialog.confirmDelete", node.getPath()),
msg.getMessage("GroupRemovalDialog.recursive"),
r -> removeGroup(node.getParentNode(), node.getPath(), r)
).show();
}
private SingleActionHandler getExpandAllAction()
{
return SingleActionHandler.builder(TreeNode.class)
.withCaption(msg.getMessage("GroupsTree.expandGroupAction"))
.withIcon(Images.expand.getResource())
.withHandler(this::expandItemsRecursively).build();
}
private void expandItemsRecursively(Collection items)
{
for (TreeNode node : items)
{
expand(node);
for (TreeNode child : treeData.getChildren(node))
expandItemsRecursively(Arrays.asList(child));
}
}
private SingleActionHandler getCollapseAllAction()
{
return SingleActionHandler.builder(TreeNode.class)
.withCaption(msg.getMessage("GroupsTree.collapseGroupAction"))
.withIcon(Images.collapse.getResource())
.withHandler(this::collapseItemsRecursively).build();
}
private void collapseItemsRecursively(Collection items)
{
for (TreeNode node : items)
{
collapse(node);
for (TreeNode child : treeData.getChildren(node))
collapseItemsRecursively(Arrays.asList(child));
}
}
private class GroupExpandListener implements ExpandListener
{
private void removeAllChildren(TreeNode item)
{
// warning - a live collection is returned
Collection children = treeData.getChildren(item);
if (children != null)
{
Set copied = new HashSet<>(children.size());
copied.addAll(children);
for (TreeNode child : copied)
{
collapse(child);
treeData.removeItem(child);
}
}
}
@Override
public void itemExpand(ExpandEvent event)
{
TreeNode expandedNode = event.getExpandedItem();
if (expandedNode.isContentsFetched())
return;
// in case of refresh
removeAllChildren(expandedNode);
GroupStructuralData bulkData;
try
{
bulkData = bulkQueryService
.getBulkStructuralData(expandedNode.getPath());
} catch (Exception e)
{
expandedNode.setIcon(Images.noAuthzGrp.getHtml());
expandedNode.setContentsFetched(true);
expand(expandedNode);
return;
}
Map groupAndSubgroups = bulkQueryService
.getGroupAndSubgroups(bulkData);
expandedNode.setIcon(Images.folder_open_o.getHtml());
GroupContents contents = groupAndSubgroups.get(expandedNode.getPath());
expandedNode.setGroupMetadata(contents.getGroup());
List subgroups = contents.getSubGroups();
Collections.sort(subgroups);
for (String subgroup : subgroups)
{
GroupContents contents2 = groupAndSubgroups.get(subgroup);
TreeNode node = new TreeNode(msg, contents2.getGroup(),
Images.folder_open_o.getHtml(), expandedNode);
treeData.addItem(node.getParentNode(), node);
}
expandedNode.setContentsFetched(true);
getDataProvider().refreshAll();
// we expand empty node before, we have to expand one
// more time to reload
expand(expandedNode);
}
}
private class GroupsDataProvider extends TreeDataProvider
{
public GroupsDataProvider(TreeData treeData)
{
super(treeData);
}
@Override
public boolean hasChildren(TreeNode item)
{
if (!item.isContentsFetched())
return true;
return super.hasChildren(item);
}
}
}