Complex Node Hierarchies

Complex Node Hierarchies

When you're using the Nodes API, things can become a bit tricky, especially when you want to visualize different Node types on the same level within a hierarchy.

As an example, let's imagine our domain model represents music bands, e.g., 'Oasis', etc. Here's a very simple node hierarchy that simply lists the names of the bands, i.e., each Node below visualizes an underlying Band object that is defined by a name:

After you've done the above, you want to show the members of the band. So, now the Band object is defined by a name and a list of Members:

However, let's say each Band has a list of Members, as well as one Manager. Here things start getting a bit tricky. The ChildFactory class has a 'createNodesForKey' method that returns multiple Nodes, so your inclination would be to use that, something like this:

@Override
protected Node[] createNodesForKey(Band key) {
    int size = key.getMembers().size() + 1;
    Node[] nodes = new Node[size];
    for (int i = 0; i < key.getMembers().size(); i++) {
        try {
            nodes[i] = new MemberNode(key.getMembers().get(i));
        } catch (IntrospectionException ex) {
            Exceptions.printStackTrace(ex);
        }
    }
    try {
        nodes[size-1] = new ManagerNode(key.getManager());
    } catch (IntrospectionException ex) {
        Exceptions.printStackTrace(ex);
    }
    return nodes;
}

What the above gets you is a structure like this:

However, you're more likely to want the structure below instead, i.e., a container Node for all the Members, together with a leaf Node for the Manager, of which there will always be one:

To achieve the above, I learned this approach from Sven Reimers during JCrete:

public class MusicBandContainerChildFactory extends 
    ChildFactory<MusicBandContainerChildFactory.Container> {
    
    private final Band band;

    public enum Container {
        MEMBERS, MANAGER
    }
    
    public MusicBandContainerChildFactory(Band band) {
        this.band = band;
    }

    @Override
    protected boolean createKeys(List<Container> list) {
        list.add(Container.MEMBERS);
        list.add(Container.MANAGER);
        return true;
    }
    
    @Override
    protected Node createNodeForKey(Container key) {
        switch (key) {
            case MEMBERS: {
                try {
                    return new MemberContainerNode(key);
                } catch (IntrospectionException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
            case MANAGER: {
                try {
                    return new ManagerNode(key);
                } catch (IntrospectionException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        }
        return null;
    }
    
    private class ManagerNode extends BeanNode {
        public ManagerNode(Container key) throws IntrospectionException {
            super(key);
            setDisplayName("Manager: "+band.getManager().getName());
        }
    }
    
    private class MemberContainerNode extends BeanNode {
        public MemberContainerNode(Container key) throws IntrospectionException {
            super(key, Children.create(new BandMemberChildFactory(band), true));
            setDisplayName("Members");
        }
    }
    
    private class BandMemberChildFactory extends ChildFactory<Member> {
        private final Band bean;
        public BandMemberChildFactory(Band bean) {
            this.bean = bean;
        }
        @Override
        protected boolean createKeys(List<Member> list) {
            list.addAll(bean.getMembers());
            return true;
        }
        @Override
        protected Node createNodeForKey(Member key) {
            BandMemberNode node = null;
            try {
                node = new BandMemberNode(key);
            } catch (IntrospectionException ex) {
                Exceptions.printStackTrace(ex);
            }
            return node;
        }
    }

    private class BandMemberNode extends BeanNode<Member> {
        public BandMemberNode(Member bean) throws IntrospectionException {
            super(bean, Children.LEAF);
            setDisplayName(bean.getName());
        }
    }
    
}

Thanks, Sven!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 缩小层次结构(contraction hierarchies)是一种用于优化图形搜索的算法。它通过将原始图形逐渐缩小,从而构建了一个图形层次结构。这个结构可以使搜索速度更快,因为它可以避免在搜索中重复计算一些相同的路径。此外,缩小层次结构还可以优化大量的图形问题,如最短路径问题和旅行商问题。 ### 回答2: 收缩层次(Contraction Hierarchies)是一种在路网图中进行高效路径搜索的常见方法。它的核心思想是通过将路网中的一些节点逐层合并,从而减少搜索空间,加速最短路径搜索和其他路径查询。 在收缩层次中,一开始,所有原始节点都被视为未缩小的。然后,每步都会将一些节点收缩成“超级节点”,并且当两个超级节点合并时,它们的邻居就合并成了新的邻居。这个过程会一直持续,直到最终只剩下一个超级节点。 在这个过程中,每个超级节点都会预处理它到其他超级节点的最短路径。这样,在进行路径查询时,可以快速地遍历超级节点,并且只需要搜索预处理的最短路径即可。由于节点的数量已经大大减少,所以搜索速度也得到了显著的提高。 收缩层次算法是一个有效的高速路径搜索方法,被广泛应用于计算机网络、地理信息系统、路线规划等领域。因为它能够处理大规模的路网图,并能够在较短的时间内完成路径查询,是一种非常有用的算法。 ### 回答3: 合并层次法(contraction hierarchies)是一种用于快速路线查询的算法,它可以在有向无环图上进行高效的路径计算。该算法通过先处理图,将一些节点“缩”起来形成超级节点(即合并节点),并记录路径中需要经过这些超级节点的最短路,从而减少了实际查询时需要计算的节点数,大大提高了查询效率。 在此算法中,合法的“缩点”必须满足“不会影响最短路径”的条件。因此,合并的节点是相邻节点之间的边数较短的节点。例如,当我们从起点到终点的路径时,会经过许多中间节点。而经过这些节点的最短路,通常只与这些节点的相邻节点相关。那么,我们可以将这些相邻节点及他们的边合并为超级节点,从而减少需要计算的节点数量。 此算法中的缩点过程是有序的,从而保证每个节点的合法和无干扰。在处理完某些节点后,该节点不再用于后续处理。合法的缩点可以减少很多计算量,而不合法的节点就不进行缩点。 总之,合并层次法是一种可靠且有效的路线查询算法,它可以大大提高查询效率,并在许多重要的应用程序中得到了广泛的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值