Skip to content

Commit

Permalink
DAC-76 Delegated Access Performance Improvements when retrieving nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
Bryan Holladay committed Apr 15, 2015
1 parent 730e657 commit 2e4a5c3
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,14 @@ public interface ProjectLogic {
* @param id
* @return
*/
public HierarchyNodeSerialized getNode(String id);
public HierarchyNodeSerialized getCachedNode(String id);

/**
* returns a map of HierarchyNodes
* @param ids
* @return
*/
public Map<String, HierarchyNodeSerialized> getCachedNodes(String[] ids);

/**
* This returns the entire tree plus any permissions set for a user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ public void init() {
public HierarchyNodeSerialized getNode(String id){
return new HierarchyNodeSerialized(hierarchyService.getNodeById(id));
}

public Map<String, HierarchyNodeSerialized> getNodes(String[] ids){
Map<String, HierarchyNodeSerialized> returnNodes = new HashMap<String, HierarchyNodeSerialized>();
Map<String, HierarchyNode> nodes = hierarchyService.getNodesByIds(ids);
for(Entry<String, HierarchyNode> entry : nodes.entrySet()){
returnNodes.put(entry.getKey(), new HierarchyNodeSerialized(entry.getValue()));
}
return returnNodes;
}


/**
Expand Down Expand Up @@ -1267,20 +1276,23 @@ private List<List> getTreeListForUser(String userId, boolean addDirectChildren,
List<List> currentLevel = l1;

for(HierarchyNodeSerialized node : nodes){
for(String parentId : getOrderedParentsList(node)){
HierarchyNodeSerialized parentNode = getCachedNode(parentId);

if(!hasNode(parentNode, currentLevel)){
List newNode = new ArrayList();
newNode.add(parentNode);
newNode.add(new ArrayList());
currentLevel.add(newNode);
}
currentLevel = getChildrenForNode(parentNode.id, currentLevel);
if(addDirectChildren){
for(List nodeList : getDirectChildren(parentNode)){
if(!hasNode((HierarchyNodeSerialized) nodeList.get(0), currentLevel)){
currentLevel.add(nodeList);
List<String> parents = getOrderedParentsList(node);
Map<String, HierarchyNodeSerialized> cachedNodes = getCachedNodes(parents.toArray(new String[parents.size()]));
for(String parentId : parents){
HierarchyNodeSerialized parentNode = cachedNodes.get(parentId);
if(parentNode != null){
if(!hasNode(parentNode, currentLevel)){
List newNode = new ArrayList();
newNode.add(parentNode);
newNode.add(new ArrayList());
currentLevel.add(newNode);
}
currentLevel = getChildrenForNode(parentNode.id, currentLevel);
if(addDirectChildren){
for(List nodeList : getDirectChildren(parentNode)){
if(!hasNode((HierarchyNodeSerialized) nodeList.get(0), currentLevel)){
currentLevel.add(nodeList);
}
}
}
}
Expand Down Expand Up @@ -1320,7 +1332,7 @@ private List<List> getTreeListForUser(String userId, boolean addDirectChildren,
* @param id
* @return
*/
private HierarchyNodeSerialized getCachedNode(String id){
public HierarchyNodeSerialized getCachedNode(String id){
Object el = nodeCache.get(id);
HierarchyNodeSerialized node = null;
if(el == null){
Expand All @@ -1335,6 +1347,30 @@ private HierarchyNodeSerialized getCachedNode(String id){
}
return node;
}

public Map<String, HierarchyNodeSerialized> getCachedNodes(String[] ids){
Map<String, HierarchyNodeSerialized> returnNodes = new HashMap<String, HierarchyNodeSerialized>();
Set<String> lookupNodes = new HashSet<String>();
for(String id : ids){
Object el = nodeCache.get(id);
HierarchyNodeSerialized node = null;
if(el == null){
//look these up in bulk:
lookupNodes.add(id);
}else if(el instanceof HierarchyNodeSerialized){
returnNodes.put(id, (HierarchyNodeSerialized) el);
}
}
//now that we only have non cached ids, look them up in bulk:
Map<String, HierarchyNodeSerialized> lookupMap = getNodes(lookupNodes.toArray(new String[lookupNodes.size()]));
//store nodes in cache and add to return set
for(Entry<String, HierarchyNodeSerialized> entry : lookupMap.entrySet()){
returnNodes.put(entry.getKey(), entry.getValue());
nodeCache.put(entry.getKey(), entry.getValue());
}

return returnNodes;
}

/**
* returns the children for this node
Expand Down Expand Up @@ -1364,11 +1400,14 @@ private List<List> getDirectChildren(HierarchyNodeSerialized parent){

if(parent != null){
Set<String> parentChildren = parent.directChildNodeIds;
Map<String, HierarchyNodeSerialized> childreNodes = getCachedNodes(parentChildren.toArray(new String[parentChildren.size()]));
for(String childId : parentChildren){
List child = new ArrayList();
child.add(getCachedNode(childId));
child.add(new ArrayList());
returnList.add(child);
if(childreNodes.containsKey(childId)){
List child = new ArrayList();
child.add(childreNodes.get(childId));
child.add(new ArrayList());
returnList.add(child);
}
}
}
return returnList;
Expand All @@ -1383,20 +1422,23 @@ private List<List> getDirectChildren(HierarchyNodeSerialized parent){
*/
private List<List> getCascadingChildren(HierarchyNodeSerialized parent, List<List> children){
Set<String> parentChildren = parent.directChildNodeIds;
Map<String, HierarchyNodeSerialized> childreNodes = getCachedNodes(parentChildren.toArray(new String[parentChildren.size()]));
for(String childId : parentChildren){
HierarchyNodeSerialized childNode = getCachedNode(childId);
if(childreNodes.containsKey(childId)){
HierarchyNodeSerialized childNode = childreNodes.get(childId);

List childMap = getChildrenForNode(childNode.id, children);
if(childMap == null){
childMap = new ArrayList();
}
List childMap = getChildrenForNode(childNode.id, children);
if(childMap == null){
childMap = new ArrayList();
}

childMap = getCascadingChildren(childNode, childMap);
if(!hasNode(childNode, children)){
List childList = new ArrayList();
childList.add(childNode);
childList.add(childMap);
children.add(childList);
childMap = getCascadingChildren(childNode, childMap);
if(!hasNode(childNode, children)){
List childList = new ArrayList();
childList.add(childNode);
childList.add(childMap);
children.add(childList);
}
}
}

Expand Down Expand Up @@ -1562,7 +1604,7 @@ private boolean doesChildExist(String childNodeId, DefaultMutableTreeNode parent
}

public NodeModel getNodeModel(String nodeId, String userId){
HierarchyNodeSerialized node = getNode(nodeId);
HierarchyNodeSerialized node = getCachedNode(nodeId);
NodeModel parentNodeModel = null;
if(node.directParentNodeIds != null && node.directParentNodeIds.size() > 0){
//grad the last parent in the Set (this is the closest parent)
Expand Down Expand Up @@ -1974,26 +2016,29 @@ private String getFirstAccessParent(Set<String> parentIds, Map<String, Set<Strin
//so by starting at the bottom we have a better chance of using less cylces
Collections.reverse(accessParents);

Map<String, HierarchyNodeSerialized> cachedNodes = getCachedNodes(accessParents.toArray(new String[accessParents.size()]));
for(String parent: accessParents){
HierarchyNodeSerialized pNode = getCachedNode(parent);
boolean foundAccessChild = false;
for(String child : pNode.childNodeIds){
for(String childCheck: accessParents){
if(childCheck.equals(child)){
//there is a parent with access permissions at a lower level,
//skip this parent and go to the next one
foundAccessChild = true;
HierarchyNodeSerialized pNode = cachedNodes.get(parent);
if(pNode != null){
boolean foundAccessChild = false;
for(String child : pNode.childNodeIds){
for(String childCheck: accessParents){
if(childCheck.equals(child)){
//there is a parent with access permissions at a lower level,
//skip this parent and go to the next one
foundAccessChild = true;
break;
}
}
if(foundAccessChild){
break;
}
}
if(foundAccessChild){
if(!foundAccessChild){
accessParent = parent;
break;
}
}
if(!foundAccessChild){
accessParent = parent;
break;
}
}
}

Expand Down Expand Up @@ -2493,8 +2538,11 @@ public Set<HierarchyNodeSerialized> getDirectNodes(String nodeId){
HierarchyNodeSerialized node = getCachedNode(nodeId);
Set<HierarchyNodeSerialized> returnSet = new HashSet<HierarchyNodeSerialized>();
if(node != null && node.directChildNodeIds != null){
Map<String, HierarchyNodeSerialized> cachedNodes = getCachedNodes(node.directChildNodeIds.toArray(new String[node.directChildNodeIds.size()]));
for(String id : node.directChildNodeIds){
returnSet.add(getCachedNode(id));
if(cachedNodes.containsKey(id)){
returnSet.add(cachedNodes.get(id));
}
}
}
return returnSet;
Expand Down Expand Up @@ -2590,9 +2638,13 @@ public List<AccessSearchResult> getAccessForUser(User user){

private List<String> getHierarchyForNode(HierarchyNodeSerialized node){
List<String> returnList = new ArrayList<String>();
for(String parentId : getOrderedParentsList(node)){
HierarchyNodeSerialized parentNode = getCachedNode(parentId);
returnList.add(parentNode.description);
List<String> parentList = getOrderedParentsList(node);
Map<String, HierarchyNodeSerialized> cachedNodes = getCachedNodes(parentList.toArray(new String[parentList.size()]));
for(String parentId : parentList){
HierarchyNodeSerialized parentNode = cachedNodes.get(parentId);
if(parentNode != null){
returnList.add(parentNode.description);
}
}
returnList.add(node.description);
return returnList;
Expand Down

0 comments on commit 2e4a5c3

Please sign in to comment.