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 package org.treetank.service.xml.serialize;
29
30 import java.util.Arrays;
31 import java.util.Stack;
32 import java.util.concurrent.Callable;
33
34 import org.treetank.access.NodeReadTrx;
35 import org.treetank.api.INodeReadTrx;
36 import org.treetank.api.ISession;
37 import org.treetank.axis.AbsAxis;
38 import org.treetank.axis.DescendantAxis;
39 import org.treetank.exception.TTException;
40 import org.treetank.exception.TTIOException;
41 import org.treetank.node.IConstants;
42 import org.treetank.node.interfaces.IStructNode;
43
44
45
46
47
48
49
50 abstract class AbsSerializer implements Callable<Void> {
51
52
53 protected final ISession mSession;
54
55
56 protected final Stack<Long> mStack;
57
58
59 protected final long[] mVersions;
60
61
62 protected final long mNodeKey;
63
64
65
66
67
68
69
70
71
72 public AbsSerializer(final ISession paramSession, final long... paramVersions) {
73 this(paramSession, 0, paramVersions);
74 }
75
76
77
78
79
80
81
82
83
84
85
86 public AbsSerializer(final ISession paramSession, final long paramKey, final long... paramVersions) {
87 mStack = new Stack<Long>();
88 mVersions = paramVersions;
89 mSession = paramSession;
90 mNodeKey = paramKey;
91 }
92
93
94
95
96
97
98
99
100 public Void call() throws TTException {
101 emitStartDocument();
102
103 long[] versionsToUse;
104
105
106 if (mVersions.length == 0) {
107 if (mSession.getMostRecentVersion() > 0) {
108 versionsToUse = new long[] {
109 mSession.getMostRecentVersion()
110 };
111 }
112 else {
113 versionsToUse = new long[0];
114 }
115 }
116
117 else {
118
119 Arrays.sort(mVersions);
120 if (mVersions[0] < 0) {
121 versionsToUse = new long[(int)mSession.getMostRecentVersion() - 1];
122
123 for (int i = 0; i < versionsToUse.length; i++) {
124 versionsToUse[i] = i + 1;
125 }
126
127 }
128 else {
129 int index = Arrays.binarySearch(mVersions, 1);
130 versionsToUse = Arrays.copyOfRange(mVersions, index, mVersions.length);
131 }
132 }
133
134 for (int i = 0; i < versionsToUse.length; i++) {
135
136 INodeReadTrx rtx = new NodeReadTrx(mSession.beginBucketRtx(versionsToUse[i]));
137
138 if (versionsToUse == null || mVersions.length > 1) {
139 emitStartManualElement(i);
140 }
141
142 rtx.moveTo(mNodeKey);
143
144 final AbsAxis descAxis = new DescendantAxis(rtx, true);
145
146
147 boolean closeElements = false;
148 long key = rtx.getNode().getDataKey();
149
150
151 while (descAxis.hasNext()) {
152 key = descAxis.next();
153 IStructNode currentStruc = (IStructNode)rtx.getNode();
154
155
156 if (closeElements) {
157 while (!mStack.empty() && mStack.peek() != currentStruc.getLeftSiblingKey()) {
158 rtx.moveTo(mStack.pop());
159 emitEndElement(rtx);
160 rtx.moveTo(key);
161 }
162 if (!mStack.empty()) {
163 rtx.moveTo(mStack.pop());
164 emitEndElement(rtx);
165 }
166 rtx.moveTo(key);
167 closeElements = false;
168 }
169
170 emitStartElement(rtx);
171
172
173 if (currentStruc.getKind() == IConstants.ELEMENT && currentStruc.hasFirstChild()) {
174 mStack.push(rtx.getNode().getDataKey());
175 }
176
177
178
179 if (!currentStruc.hasFirstChild() && !currentStruc.hasRightSibling()) {
180 closeElements = true;
181 }
182
183 }
184
185
186 while (!mStack.empty()) {
187 rtx.moveTo(mStack.pop());
188 emitEndElement(rtx);
189 }
190
191 if (versionsToUse == null || mVersions.length > 1) {
192 emitEndManualElement(i);
193 }
194 }
195 emitEndDocument();
196
197 return null;
198 }
199
200
201 protected abstract void emitStartDocument();
202
203
204
205
206
207
208
209 protected abstract void emitStartElement(final INodeReadTrx pRTX) throws TTIOException;
210
211
212
213
214
215
216
217 protected abstract void emitEndElement(final INodeReadTrx paramRTX);
218
219
220
221
222
223
224
225 protected abstract void emitStartManualElement(final long paramVersion);
226
227
228
229
230
231
232
233 protected abstract void emitEndManualElement(final long paramVersion);
234
235
236 protected abstract void emitEndDocument();
237 }