private void populateSpanEvent(final Node node, final SpanCallTree spanCallTree, final List<Align> alignList) {
        if (CollectionUtils.isEmpty(alignList)) {
            return;
        }

        // cursor tree
        SpanCallTree tree = spanCallTree;
        for (Align align : alignList) {
            try {
                if (!node.isCorrupted()) {
                    tree.add(align);
                }
            } catch (CorruptedSpanCallTreeNodeException e) {
                logger.warn("Corrupted span event {}", e.getMessage(), e);
                node.setCorrupted(true);
                traceState.progress();

                final long startTimeMillis = align.getStartTime();
                final SpanBo spanBo = node.getSpanBo();
                final SpanCallTree corruptedCallTree = metaSpanCallTreeFactory.corrupted(e.getTitle(), spanBo.getParentSpanId(), spanBo.getSpanId(), startTimeMillis);
                tree.add(corruptedCallTree);
                // replace cursor tree.
                tree = corruptedCallTree;
            }
            // link
            final long nextSpanId = align.getSpanEventBo().getNextSpanId();
            if (nextSpanId != -1) {
                // add linked call tree
                final LinkedCallTree linkedCallTree = new LinkedCallTree(new SpanAlign(new SpanBo()));
                tree.add(linkedCallTree);
                final Link link = Link.newLink(align, linkedCallTree);
                this.linkList.add(link);
            }

            // async
            final int nextAsyncId = align.getSpanEventBo().getNextAsyncId();
            final SpanAsyncEventMap asyncSpanEventMap = node.getAsyncSpanEventMap();

            for (List<Align> asyncAlignList : asyncSpanEventMap.getAsyncAlign(nextAsyncId)) {
                populateAsyncSpanEvent(node, tree, asyncAlignList);
            }
        }
    }
@author netspider
@author emeroad
@author jaehong.kim
web/src/main/java/com/navercorp/pinpoint/web/calltree/span/SpanAligner.java