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