1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.smartics.maven.issues.cache;
17
18 import java.io.Closeable;
19 import java.lang.reflect.Constructor;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import javax.xml.namespace.QName;
24 import javax.xml.stream.XMLStreamConstants;
25 import javax.xml.stream.XMLStreamException;
26 import javax.xml.stream.XMLStreamReader;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.eclipse.mylyn.tasks.core.TaskRepository;
31 import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
32 import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper;
33 import org.eclipse.mylyn.tasks.core.data.TaskAttributeMetaData;
34 import org.eclipse.mylyn.tasks.core.data.TaskData;
35
36
37
38
39
40
41
42 public class XmlTaskReader implements Closeable
43 {
44
45
46
47
48
49
50
51
52
53 private final Log log = LogFactory.getLog(XmlTaskReader.class);
54
55
56
57
58 protected final XMLStreamReader xmlReader;
59
60
61
62
63
64
65
66
67
68
69
70
71 public XmlTaskReader(final XMLStreamReader xmlReader)
72 throws NullPointerException
73 {
74 if (xmlReader == null)
75 {
76 throw new NullPointerException("XML reader must not be 'null'.");
77 }
78 this.xmlReader = xmlReader;
79 }
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 public TaskData readTask() throws XMLStreamException
100 {
101 if (xmlReader.hasNext())
102 {
103 xmlReader.nextTag();
104 final QName qNameRoot = xmlReader.getName();
105 final String giRoot = qNameRoot.getLocalPart();
106 if (!TaskInfoKey.TASK_DATA.equals(giRoot))
107 {
108 throw new XMLStreamException("Expected '" + TaskInfoKey.TASK_DATA
109 + "' but encountered '" + giRoot + "'.");
110 }
111
112 return readTaskData(giRoot);
113 }
114 return null;
115 }
116
117
118
119
120
121
122
123
124 private TaskData readTaskData(final String giRoot) throws XMLStreamException
125 {
126 final TaskData taskData = createTaskData();
127
128 if (xmlReader.hasNext())
129 {
130 xmlReader.nextTag();
131 final QName qName = xmlReader.getName();
132 final String gi = qName.getLocalPart();
133 if (TaskInfoKey.ATTRIBUTE.equals(gi))
134 {
135 provideAttribute(taskData.getRoot());
136 }
137 else
138 {
139 if (log.isDebugEnabled())
140 {
141 log.debug(createUnrecognizedElementMessage(giRoot, gi));
142 }
143 }
144 }
145 return taskData;
146 }
147
148
149
150
151
152
153
154
155
156
157
158 private static String createUnrecognizedElementMessage(
159 final String parentElementGi, final String nestedElementGi)
160 {
161 return "Unrecognized tag within '" + parentElementGi + "': "
162 + nestedElementGi;
163 }
164
165
166
167
168
169
170
171
172
173 public TaskData createTaskData() throws XMLStreamException
174 {
175 final Map<String, String> properties = readElementAttributes();
176 final TaskData taskData = createTaskData(properties);
177 return taskData;
178 }
179
180
181
182
183
184
185
186 private Map<String, String> readElementAttributes() throws XMLStreamException
187 {
188 final int attributeCount = xmlReader.getAttributeCount();
189 final Map<String, String> attributes = new HashMap<String, String>();
190 for (int i = 0; i < attributeCount; i++)
191 {
192 final String name = xmlReader.getAttributeLocalName(i);
193 final String value = xmlReader.getAttributeValue(i);
194 attributes.put(name, value);
195 }
196 return attributes;
197 }
198
199
200
201
202
203
204
205
206
207 private TaskData createTaskData(final Map<String, String> properties)
208 throws XMLStreamException
209 {
210 try
211 {
212 final Constructor<TaskData> constructor =
213 TaskData.class.getConstructor(TaskAttributeMapper.class,
214 String.class, String.class, String.class);
215 final String taskId = properties.get(TaskInfoKey.TASK_ID);
216 final String repositoryUrl = properties.get(TaskInfoKey.REPOSITORY_URL);
217 final String connectorKind = properties.get(TaskInfoKey.CONNECTOR_KIND);
218
219 final TaskRepository taskRepository =
220 new TaskRepository(connectorKind, repositoryUrl);
221 final TaskAttributeMapper mapper =
222 new TaskAttributeMapper(taskRepository);
223
224 final TaskData taskData =
225 constructor.newInstance(mapper, connectorKind, repositoryUrl, taskId);
226 final String version = properties.get(TaskInfoKey.VERSION);
227 if (version != null)
228 {
229 taskData.setVersion(version);
230 }
231 return taskData;
232 }
233 catch (final Exception e)
234 {
235 throw new XMLStreamException("Cannot create task data with properties: "
236 + properties, e);
237 }
238 }
239
240
241
242
243
244
245
246
247 private void provideAttribute(final TaskAttribute attribute)
248 throws XMLStreamException
249 {
250 while (xmlReader.hasNext())
251 {
252 xmlReader.nextTag();
253 final QName qName = xmlReader.getName();
254 final String gi = qName.getLocalPart();
255 if (TaskInfoKey.ATTRIBUTE.equals(gi))
256 {
257 return;
258 }
259 else
260 {
261 readNextInformation(attribute, gi);
262 }
263 }
264 }
265
266
267
268
269
270
271
272
273
274 private void readNextInformation(final TaskAttribute attribute,
275 final String gi) throws XMLStreamException
276 {
277 if (TaskInfoKey.ATTRIBUTES.equals(gi))
278 {
279 provideAttributes(attribute);
280 }
281 else if (TaskInfoKey.OPTIONS.equals(gi))
282 {
283 provideOptions(attribute);
284 }
285 else if (TaskInfoKey.META_DATA.equals(gi))
286 {
287 provideMetaData(attribute);
288 }
289 else if (TaskInfoKey.VALUES.equals(gi))
290 {
291 provideValues(attribute);
292 }
293 else
294 {
295 if (log.isDebugEnabled())
296 {
297 log.debug(createUnrecognizedElementMessage(TaskInfoKey.ATTRIBUTE, gi));
298 }
299 }
300 }
301
302
303
304
305
306
307
308 private void provideMetaData(final TaskAttribute attribute)
309 throws XMLStreamException
310 {
311 final TaskAttributeMetaData metaData = attribute.getMetaData();
312 while (xmlReader.hasNext())
313 {
314 xmlReader.nextTag();
315 final QName qName = xmlReader.getName();
316 final String gi = qName.getLocalPart();
317 if (TaskInfoKey.META_DATA.equals(gi))
318 {
319 return;
320 }
321 else if (xmlReader.getEventType() == XMLStreamConstants.END_ELEMENT)
322 {
323 continue;
324 }
325 else
326 {
327 if (TaskInfoKey.ENTRY.equals(gi))
328 {
329 final String key = readSimpleElement(TaskInfoKey.KEY);
330 final String value = readSimpleElement(TaskInfoKey.VALUE);
331 metaData.putValue(key, value);
332 xmlReader.nextTag();
333 }
334 else
335 {
336 if (log.isDebugEnabled())
337 {
338 log.debug(createUnrecognizedElementMessage(TaskInfoKey.META_DATA,
339 gi));
340 }
341 }
342 }
343 }
344 }
345
346
347
348
349
350
351
352
353 private String readSimpleElement(final String expectedGi)
354 throws XMLStreamException
355 {
356 xmlReader.nextTag();
357 final QName qName = xmlReader.getName();
358 final String gi = qName.getLocalPart();
359 if (expectedGi.equals(gi))
360 {
361 xmlReader.next();
362 final String value = readCharacters();
363 return value;
364 }
365 else
366 {
367 throw new XMLStreamException("Expected '" + expectedGi + "' but found '"
368 + gi + "'.");
369 }
370 }
371
372
373
374
375
376
377
378 private void provideOptions(final TaskAttribute attribute)
379 throws XMLStreamException
380 {
381 while (xmlReader.hasNext())
382 {
383 xmlReader.nextTag();
384 final QName qName = xmlReader.getName();
385 final String gi = qName.getLocalPart();
386 if (TaskInfoKey.OPTIONS.equals(gi))
387 {
388 return;
389 }
390 else if (xmlReader.getEventType() == XMLStreamConstants.END_ELEMENT)
391 {
392 continue;
393 }
394 else
395 {
396 if (TaskInfoKey.ENTRY.equals(gi))
397 {
398 final String key = readSimpleElement(TaskInfoKey.KEY);
399 final String value = readSimpleElement(TaskInfoKey.VALUE);
400 attribute.putOption(key, value);
401 xmlReader.nextTag();
402 }
403 else
404 {
405 if (log.isDebugEnabled())
406 {
407 log.debug(createUnrecognizedElementMessage(TaskInfoKey.OPTIONS, gi));
408 }
409 }
410 }
411 }
412 }
413
414
415
416
417
418
419
420
421 private void provideValues(final TaskAttribute attribute)
422 throws XMLStreamException
423 {
424 xmlReader.nextTag();
425 while (xmlReader.hasNext())
426 {
427 final QName qName = xmlReader.getName();
428 final String gi = qName.getLocalPart();
429 if (TaskInfoKey.VALUES.equals(gi))
430 {
431 return;
432 }
433 else if (xmlReader.getEventType() == XMLStreamConstants.END_ELEMENT)
434 {
435 xmlReader.nextTag();
436 continue;
437 }
438 else if (TaskInfoKey.VALUE.equals(gi))
439 {
440 xmlReader.next();
441 final String value = readCharacters();
442 attribute.addValue(value);
443 }
444 }
445 }
446
447
448
449
450
451
452
453
454
455 private String readCharacters() throws XMLStreamException
456 {
457 final StringBuilder buffer = new StringBuilder();
458 while (xmlReader.getEventType() == XMLStreamConstants.CHARACTERS)
459 {
460 buffer.append(xmlReader.getText());
461 xmlReader.next();
462 }
463 return buffer.toString();
464 }
465
466
467
468
469
470
471
472 private void provideAttributes(final TaskAttribute attribute)
473 throws XMLStreamException
474 {
475 while (xmlReader.hasNext())
476 {
477 xmlReader.nextTag();
478 final QName qName = xmlReader.getName();
479 final String gi = qName.getLocalPart();
480 if (TaskInfoKey.ATTRIBUTES.equals(gi))
481 {
482 return;
483 }
484 else
485 {
486 final String attributeId = getAttribute(TaskInfoKey.ATTRIBUTE_ID);
487 final TaskAttribute subAttribute =
488 new TaskAttribute(attribute, attributeId);
489 provideAttribute(subAttribute);
490 }
491 }
492
493 }
494
495
496
497
498
499
500
501
502
503
504 private String getAttribute(final String name) throws XMLStreamException
505 {
506 final Map<String, String> attributes = readElementAttributes();
507 return attributes.get(name);
508 }
509
510
511
512
513
514
515
516
517
518 public void close()
519 {
520 try
521 {
522 this.xmlReader.close();
523 }
524 catch (final XMLStreamException e)
525 {
526 if (log.isErrorEnabled())
527 {
528 log.error("Cannot close XML stream of task reader.");
529 }
530 }
531 }
532
533
534
535 }