Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 9b26a57d0facb92943a4e5806f464c73eae5bcb6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*******************************************************************************
 * Copyright (c) 2012 Florian Thienel and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 * 		Florian Thienel - initial API and implementation
 *******************************************************************************/
package org.eclipse.vex.core.internal.dom;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.eclipse.vex.core.dom.ContentRange;
import org.eclipse.vex.core.dom.IContent;
import org.eclipse.vex.core.dom.INode;
import org.eclipse.vex.core.dom.IParent;

/**
 * This class creates a deep copy of a single Node or the child nodes of a Parent within a given Range. The copy is made
 * instantly when the constructor of DeepCopy is called.
 * <p>
 * DeepCopy means a full copy of all nodes, their children down to the leaf level and the associated content.
 * 
 * @author Florian Thienel
 */
public class DeepCopy {

	private final IContent content;
	private final List<Node> nodes;

	/**
	 * Creates a deep copy of the given node.
	 * 
	 * @param node
	 *            the node to copy
	 */
	public DeepCopy(final INode node) {
		final int delta;
		if (node.isAssociated()) {
			final ContentRange range = node.getRange();
			delta = -range.getStartOffset();
			content = node.getContent().getContent(range);
		} else {
			delta = 0;
			content = null;
		}
		nodes = new ArrayList<Node>();

		copyNodes(Collections.singletonList(node), delta);
	}

	/**
	 * Creates a deep copy of the child nodes of the given parent within the given range.
	 * 
	 * @param parent
	 *            the parent
	 * @param range
	 *            the range to copy
	 */
	public DeepCopy(final IParent parent, final ContentRange range) {
		final int delta;
		if (parent.isAssociated()) {
			delta = -range.getStartOffset();
			content = parent.getContent().getContent(range);
		} else {
			delta = 0;
			content = null;
		}
		nodes = new ArrayList<Node>();

		copyNodes(parent.children().in(range), delta);
	}

	private void copyNodes(final Iterable<? extends INode> sourceNodes, final int delta) {
		final DeepCopyVisitor deepCopyVisitor = new DeepCopyVisitor(nodes, content, delta);
		for (final INode sourceNode : sourceNodes) {
			sourceNode.accept(deepCopyVisitor);
		}
	}

	/**
	 * @return the copied nodes on the root level.
	 */
	public List<Node> getNodes() {
		return nodes;
	}

	/**
	 * @return the copied content.
	 */
	public IContent getContent() {
		return content;
	}

}

Back to the top