1 | package eu.clarin.cmdi.virtualcollectionregistry.service.impl; |
---|
2 | |
---|
3 | import eu.clarin.cmdi.virtualcollectionregistry.service.VirtualCollectionCMDIWriter; |
---|
4 | import eu.clarin.cmdi.virtualcollectionregistry.service.VirtualCollectionMarshaller; |
---|
5 | import eu.clarin.cmdi.virtualcollectionregistry.VirtualCollectionRegistryException; |
---|
6 | |
---|
7 | import java.io.IOException; |
---|
8 | import java.io.InputStream; |
---|
9 | import java.io.OutputStream; |
---|
10 | import java.net.URL; |
---|
11 | import java.text.DateFormat; |
---|
12 | import java.text.ParseException; |
---|
13 | import java.text.SimpleDateFormat; |
---|
14 | import java.util.Collections; |
---|
15 | import java.util.Map; |
---|
16 | |
---|
17 | import javax.xml.stream.XMLInputFactory; |
---|
18 | import javax.xml.stream.XMLOutputFactory; |
---|
19 | import javax.xml.stream.XMLStreamConstants; |
---|
20 | import javax.xml.stream.XMLStreamException; |
---|
21 | import javax.xml.stream.XMLStreamReader; |
---|
22 | import javax.xml.stream.XMLStreamWriter; |
---|
23 | |
---|
24 | import org.codehaus.jettison.mapped.MappedXMLInputFactory; |
---|
25 | import org.codehaus.jettison.mapped.MappedXMLOutputFactory; |
---|
26 | import org.codehaus.stax2.XMLInputFactory2; |
---|
27 | import org.codehaus.stax2.XMLOutputFactory2; |
---|
28 | import org.codehaus.stax2.XMLStreamReader2; |
---|
29 | import org.codehaus.stax2.XMLStreamWriter2; |
---|
30 | import org.codehaus.stax2.validation.XMLValidationSchema; |
---|
31 | import org.codehaus.stax2.validation.XMLValidationSchemaFactory; |
---|
32 | import org.slf4j.Logger; |
---|
33 | import org.slf4j.LoggerFactory; |
---|
34 | |
---|
35 | import eu.clarin.cmdi.virtualcollectionregistry.model.Creator; |
---|
36 | import eu.clarin.cmdi.virtualcollectionregistry.model.GeneratedBy; |
---|
37 | import eu.clarin.cmdi.virtualcollectionregistry.model.GeneratedByQuery; |
---|
38 | import eu.clarin.cmdi.virtualcollectionregistry.model.Resource; |
---|
39 | import eu.clarin.cmdi.virtualcollectionregistry.model.VirtualCollection; |
---|
40 | import eu.clarin.cmdi.virtualcollectionregistry.model.VirtualCollectionList; |
---|
41 | |
---|
42 | import org.springframework.beans.factory.annotation.Autowired; |
---|
43 | import org.springframework.stereotype.Service; |
---|
44 | |
---|
45 | @Service |
---|
46 | public class VirtualCollectionMarshallerImpl implements VirtualCollectionMarshaller { |
---|
47 | |
---|
48 | private static final String ENCODING = "UTF-8"; |
---|
49 | private static final String VERSION = "1.0"; |
---|
50 | private static final Logger logger = |
---|
51 | LoggerFactory.getLogger(VirtualCollectionMarshallerImpl.class); |
---|
52 | private final DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); |
---|
53 | private final XMLValidationSchema schema; |
---|
54 | private final XMLInputFactory2 xmlReaderFactory; |
---|
55 | private final XMLOutputFactory2 xmlWriterFactory; |
---|
56 | private final MappedXMLInputFactory jsonReaderFactory; |
---|
57 | private final MappedXMLOutputFactory jsonWriterFactory; |
---|
58 | |
---|
59 | @Autowired |
---|
60 | private VirtualCollectionCMDIWriter cmdiWriter; |
---|
61 | |
---|
62 | VirtualCollectionMarshallerImpl() throws VirtualCollectionRegistryException { |
---|
63 | logger.debug("initializing schemas for marshaller ..."); |
---|
64 | try { |
---|
65 | XMLValidationSchemaFactory sf = XMLValidationSchemaFactory |
---|
66 | .newInstance(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA); |
---|
67 | URL url = VirtualCollectionMarshallerImpl.class |
---|
68 | .getClassLoader() |
---|
69 | .getResource("META-INF/VirtualCollection.xsd"); |
---|
70 | if (url == null) { |
---|
71 | throw new NullPointerException("schema not found!"); |
---|
72 | } |
---|
73 | schema = sf.createSchema(url); |
---|
74 | |
---|
75 | // XML factories |
---|
76 | xmlReaderFactory = |
---|
77 | (XMLInputFactory2) XMLInputFactory.newInstance(); |
---|
78 | xmlReaderFactory.configureForSpeed(); |
---|
79 | xmlReaderFactory |
---|
80 | .setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.TRUE); |
---|
81 | xmlReaderFactory |
---|
82 | .setProperty(XMLInputFactory2.P_INTERN_NAMES, Boolean.TRUE); |
---|
83 | xmlReaderFactory |
---|
84 | .setProperty(XMLInputFactory2.P_INTERN_NS_URIS, Boolean.TRUE); |
---|
85 | xmlWriterFactory = |
---|
86 | (XMLOutputFactory2) XMLOutputFactory.newInstance(); |
---|
87 | xmlWriterFactory.configureForSpeed(); |
---|
88 | |
---|
89 | // JSON factories |
---|
90 | final Map<String, String> mapping = Collections.emptyMap(); |
---|
91 | jsonReaderFactory = new MappedXMLInputFactory(mapping); |
---|
92 | jsonWriterFactory = new MappedXMLOutputFactory(mapping); |
---|
93 | } catch (Exception e) { |
---|
94 | logger.error("error initializing marshaller", e); |
---|
95 | throw new VirtualCollectionRegistryException( |
---|
96 | "error initializing marshaller", e); |
---|
97 | } |
---|
98 | } |
---|
99 | |
---|
100 | @Override |
---|
101 | public void marshal(OutputStream out, Format format, VirtualCollection vc) |
---|
102 | throws IOException { |
---|
103 | if (vc == null) { |
---|
104 | throw new NullPointerException("vc == null"); |
---|
105 | } |
---|
106 | XMLStreamWriter writer = null; |
---|
107 | try { |
---|
108 | writer = createWriter(out, format, true); |
---|
109 | writer.writeStartDocument(ENCODING, VERSION); |
---|
110 | writeVirtualCollection(writer, vc); |
---|
111 | writer.writeEndDocument(); |
---|
112 | } catch (XMLStreamException e) { |
---|
113 | logger.error("error marshalling virtual collection", e); |
---|
114 | throw new IOException("error marshalling virtual collection", e); |
---|
115 | } finally { |
---|
116 | try { |
---|
117 | if (writer != null) { |
---|
118 | writer.close(); |
---|
119 | } |
---|
120 | } catch (XMLStreamException e) { |
---|
121 | /* IGNORE */ |
---|
122 | } |
---|
123 | } |
---|
124 | } |
---|
125 | |
---|
126 | @Override |
---|
127 | public void marshal(OutputStream out, Format format, |
---|
128 | VirtualCollectionList vcs) throws IOException { |
---|
129 | if (vcs == null) { |
---|
130 | throw new NullPointerException("vcs == null"); |
---|
131 | } |
---|
132 | XMLStreamWriter writer = null; |
---|
133 | try { |
---|
134 | writer = createWriter(out, format, true); |
---|
135 | writer.writeStartDocument(ENCODING, VERSION); |
---|
136 | writer.writeStartElement("VirtualCollections"); |
---|
137 | writer.writeAttribute("totalCount", |
---|
138 | Integer.toString(vcs.getTotalCount())); |
---|
139 | writer.writeAttribute("offset", |
---|
140 | Integer.toString(vcs.getOffset())); |
---|
141 | writer.writeAttribute("result", |
---|
142 | (vcs.isPartialList() ? "partial" : "full")); |
---|
143 | for (VirtualCollection vc : vcs.getItems()) { |
---|
144 | writeVirtualCollection(writer, vc); |
---|
145 | } |
---|
146 | writer.writeEndElement(); // "VirtualCollections" element |
---|
147 | writer.writeEndDocument(); |
---|
148 | } catch (XMLStreamException e) { |
---|
149 | logger.error("error marshalling virtual collections", e); |
---|
150 | throw new IOException("error marshalling virtual collections", e); |
---|
151 | } finally { |
---|
152 | try { |
---|
153 | if (writer != null) { |
---|
154 | writer.close(); |
---|
155 | } |
---|
156 | } catch (XMLStreamException e) { |
---|
157 | /* IGNORE */ |
---|
158 | } |
---|
159 | } |
---|
160 | } |
---|
161 | |
---|
162 | @Override |
---|
163 | public VirtualCollection unmarshal(InputStream in, Format format, |
---|
164 | String encoding) throws IOException { |
---|
165 | XMLStreamReader reader = null; |
---|
166 | try { |
---|
167 | reader = createReader(in, format, encoding); |
---|
168 | return readVirtualCollection(reader); |
---|
169 | } catch (XMLStreamException e) { |
---|
170 | logger.error("error unmarshalling virtual collection", e); |
---|
171 | throw new IOException("error unmarshalling virtual collection", e); |
---|
172 | } finally { |
---|
173 | try { |
---|
174 | if (reader != null) { |
---|
175 | reader.close(); |
---|
176 | } |
---|
177 | } catch (XMLStreamException e) { |
---|
178 | /* IGNORE */ |
---|
179 | } |
---|
180 | } |
---|
181 | } |
---|
182 | |
---|
183 | @Override |
---|
184 | public void marshalAsCMDI(OutputStream out, Format format, |
---|
185 | VirtualCollection vc) throws IOException { |
---|
186 | if (vc == null) { |
---|
187 | throw new NullPointerException("vc == null"); |
---|
188 | } |
---|
189 | |
---|
190 | XMLStreamWriter writer = null; |
---|
191 | try { |
---|
192 | writer = createWriter(out, format, false); |
---|
193 | writer.writeStartDocument(ENCODING, VERSION); |
---|
194 | cmdiWriter.writeCMDI(writer, vc); |
---|
195 | writer.writeEndDocument(); |
---|
196 | } catch (XMLStreamException e) { |
---|
197 | logger.error("error marshalling clarin virtual collections", e); |
---|
198 | throw new IOException( |
---|
199 | "error marshalling clarin virtual collections", e); |
---|
200 | } finally { |
---|
201 | try { |
---|
202 | if (writer != null) { |
---|
203 | writer.close(); |
---|
204 | } |
---|
205 | } catch (XMLStreamException e) { |
---|
206 | /* IGNORE */ |
---|
207 | } |
---|
208 | } |
---|
209 | } |
---|
210 | |
---|
211 | private void writeVirtualCollection(XMLStreamWriter writer, |
---|
212 | VirtualCollection vc) throws XMLStreamException { |
---|
213 | writer.writeStartElement("VirtualCollection"); |
---|
214 | if (vc.getId() != null) { |
---|
215 | writer.writeAttribute("id", Long.toString(vc.getId())); |
---|
216 | } |
---|
217 | if (vc.getPersistentIdentifier() != null) { |
---|
218 | writer.writeAttribute("persistentId", |
---|
219 | vc.getPersistentIdentifier().getIdentifier()); |
---|
220 | } |
---|
221 | writer.writeAttribute("state", getStateRepresentation(vc.getState())); |
---|
222 | |
---|
223 | writer.writeStartElement("Type"); |
---|
224 | switch (vc.getType()) { |
---|
225 | case EXTENSIONAL: |
---|
226 | writer.writeCharacters("extensional"); |
---|
227 | break; |
---|
228 | case INTENSIONAL: |
---|
229 | writer.writeCharacters("intensional"); |
---|
230 | break; |
---|
231 | } // switch |
---|
232 | writer.writeEndElement(); // "Type" element |
---|
233 | |
---|
234 | writer.writeStartElement("Name"); |
---|
235 | writer.writeCharacters(vc.getName()); |
---|
236 | writer.writeEndElement(); // "Name" element |
---|
237 | |
---|
238 | if (vc.getDescription() != null) { |
---|
239 | writer.writeStartElement("Description"); |
---|
240 | writer.writeCharacters(vc.getDescription()); |
---|
241 | writer.writeEndElement(); // "Description" element |
---|
242 | } |
---|
243 | |
---|
244 | if (vc.getCreationDate() != null) { |
---|
245 | writer.writeStartElement("CreationDate"); |
---|
246 | // XXX: threading vs. performance |
---|
247 | synchronized (df) { |
---|
248 | writer.writeCharacters(df.format(vc.getCreationDate())); |
---|
249 | } // synchronized (df) |
---|
250 | writer.writeEndElement(); // "CreationDate" element |
---|
251 | } |
---|
252 | |
---|
253 | if ((vc.getCreators() != null) && !vc.getCreators().isEmpty()) { |
---|
254 | writer.writeStartElement("Creators"); |
---|
255 | for (Creator creator : vc.getCreators()) { |
---|
256 | writeCreator(writer, creator); |
---|
257 | } |
---|
258 | writer.writeEndElement(); // "Creators" element |
---|
259 | } // Creators |
---|
260 | |
---|
261 | if (vc.getPurpose() != null) { |
---|
262 | writer.writeStartElement("Purpose"); |
---|
263 | switch (vc.getPurpose()) { |
---|
264 | case RESEARCH: |
---|
265 | writer.writeCharacters("research"); |
---|
266 | break; |
---|
267 | case REFERENCE: |
---|
268 | writer.writeCharacters("reference"); |
---|
269 | break; |
---|
270 | case SAMPLE: |
---|
271 | writer.writeCharacters("sample"); |
---|
272 | break; |
---|
273 | case FUTURE_USE: |
---|
274 | writer.writeCharacters("future-use"); |
---|
275 | break; |
---|
276 | } // switch |
---|
277 | writer.writeEndElement(); // "Purpose" element |
---|
278 | } |
---|
279 | |
---|
280 | if (vc.getReproducibility() != null) { |
---|
281 | writer.writeStartElement("Reproducibility"); |
---|
282 | switch (vc.getReproducibility()) { |
---|
283 | case INTENDED: |
---|
284 | writer.writeCharacters("intended"); |
---|
285 | break; |
---|
286 | case FLUCTUATING: |
---|
287 | writer.writeCharacters("fluctuating"); |
---|
288 | break; |
---|
289 | case UNTENDED: |
---|
290 | writer.writeCharacters("untended"); |
---|
291 | break; |
---|
292 | } // switch |
---|
293 | writer.writeEndElement(); // "Reproducibility" element |
---|
294 | } |
---|
295 | |
---|
296 | if (vc.getReproducibilityNotice() != null) { |
---|
297 | writer.writeStartElement("ReproducibilityNotice"); |
---|
298 | writer.writeCharacters(vc.getReproducibilityNotice()); |
---|
299 | writer.writeEndElement(); // "ReproducibilityNotice" element |
---|
300 | } |
---|
301 | |
---|
302 | if ((vc.getKeywords() != null) && !vc.getKeywords().isEmpty()) { |
---|
303 | writer.writeStartElement("Keywords"); |
---|
304 | |
---|
305 | for (final String keyword : vc.getKeywords()) { |
---|
306 | writer.writeStartElement("Keyword"); |
---|
307 | writer.writeCharacters(keyword); |
---|
308 | writer.writeEndElement(); // "Keyword" element |
---|
309 | } |
---|
310 | |
---|
311 | writer.writeEndElement(); // "Keywords" element |
---|
312 | } // Keywords |
---|
313 | |
---|
314 | if ((vc.getResources() != null) && !vc.getResources().isEmpty()) { |
---|
315 | writer.writeStartElement("Resources"); |
---|
316 | |
---|
317 | for (final Resource resource : vc.getResources()) { |
---|
318 | writeResource(writer, resource); |
---|
319 | } |
---|
320 | |
---|
321 | writer.writeEndElement(); // "Resources" element |
---|
322 | } // Resources |
---|
323 | |
---|
324 | if (vc.getGeneratedBy() != null) { |
---|
325 | final GeneratedBy generatedBy = vc.getGeneratedBy(); |
---|
326 | writer.writeStartElement("GeneratedBy"); |
---|
327 | |
---|
328 | writer.writeStartElement("Description"); |
---|
329 | writer.writeCharacters(generatedBy.getDescription()); |
---|
330 | writer.writeEndElement(); // "Description" element |
---|
331 | |
---|
332 | if (generatedBy.getURI() != null) { |
---|
333 | writer.writeStartElement("URI"); |
---|
334 | writer.writeCharacters(generatedBy.getURI()); |
---|
335 | writer.writeEndElement(); // "URI" element |
---|
336 | } |
---|
337 | |
---|
338 | if (generatedBy.getQuery() != null) { |
---|
339 | GeneratedByQuery query = generatedBy.getQuery(); |
---|
340 | writer.writeStartElement("Query"); |
---|
341 | writer.writeAttribute("profile", query.getProfile()); |
---|
342 | writer.writeCData(query.getValue()); |
---|
343 | writer.writeEndElement(); // "Query" element |
---|
344 | } |
---|
345 | |
---|
346 | writer.writeEndElement(); // "GeneratedBy" element |
---|
347 | } |
---|
348 | |
---|
349 | writer.writeEndElement(); // "VirtualCollection" element |
---|
350 | } |
---|
351 | |
---|
352 | private String getStateRepresentation(final VirtualCollection.State state) { |
---|
353 | String s = null; |
---|
354 | switch (state) { |
---|
355 | case PRIVATE: |
---|
356 | s = "private"; |
---|
357 | break; |
---|
358 | case PUBLIC_PENDING: |
---|
359 | s = "public-pending"; |
---|
360 | break; |
---|
361 | case PUBLIC: |
---|
362 | s = "public"; |
---|
363 | break; |
---|
364 | case DELETED: |
---|
365 | s = "deleted"; |
---|
366 | break; |
---|
367 | case DEAD: |
---|
368 | s = "dead"; |
---|
369 | break; |
---|
370 | } |
---|
371 | return s; |
---|
372 | } |
---|
373 | |
---|
374 | private void writeCreator(XMLStreamWriter writer, Creator creator) throws XMLStreamException { |
---|
375 | writer.writeStartElement("Creator"); |
---|
376 | |
---|
377 | writer.writeStartElement("Person"); |
---|
378 | writer.writeCharacters(creator.getPerson()); |
---|
379 | writer.writeEndElement(); // "Person" element |
---|
380 | |
---|
381 | if (creator.getAddress() != null) { |
---|
382 | writer.writeStartElement("Address"); |
---|
383 | writer.writeCharacters(creator.getAddress()); |
---|
384 | writer.writeEndElement(); // "Address" element |
---|
385 | } |
---|
386 | |
---|
387 | if (creator.getEMail() != null) { |
---|
388 | writer.writeStartElement("Email"); |
---|
389 | writer.writeCharacters(creator.getEMail()); |
---|
390 | writer.writeEndElement(); // "Email" element |
---|
391 | } |
---|
392 | |
---|
393 | if (creator.getOrganisation() != null) { |
---|
394 | writer.writeStartElement("Organisation"); |
---|
395 | writer.writeCharacters(creator.getOrganisation()); |
---|
396 | writer.writeEndElement(); // "Organisation" element |
---|
397 | } |
---|
398 | |
---|
399 | if (creator.getTelephone() != null) { |
---|
400 | writer.writeStartElement("Telephone"); |
---|
401 | writer.writeCharacters(creator.getTelephone()); |
---|
402 | writer.writeEndElement(); // "Telephone" element |
---|
403 | } |
---|
404 | |
---|
405 | if (creator.getWebsite() != null) { |
---|
406 | writer.writeStartElement("Website"); |
---|
407 | writer.writeCharacters(creator.getWebsite()); |
---|
408 | writer.writeEndElement(); // "Website" element |
---|
409 | } |
---|
410 | |
---|
411 | if (creator.getRole() != null) { |
---|
412 | writer.writeStartElement("Role"); |
---|
413 | writer.writeCharacters(creator.getRole()); |
---|
414 | writer.writeEndElement(); // "Role" element |
---|
415 | } |
---|
416 | |
---|
417 | writer.writeEndElement(); // "Creator" element |
---|
418 | } |
---|
419 | |
---|
420 | private void writeResource(XMLStreamWriter writer, final Resource resource) throws XMLStreamException { |
---|
421 | writer.writeStartElement("Resource"); |
---|
422 | |
---|
423 | writer.writeStartElement("ResourceType"); |
---|
424 | switch (resource.getType()) { |
---|
425 | case METADATA: |
---|
426 | writer.writeCharacters("Metadata"); |
---|
427 | break; |
---|
428 | case RESOURCE: |
---|
429 | writer.writeCharacters("Resource"); |
---|
430 | break; |
---|
431 | } // switch |
---|
432 | writer.writeEndElement(); // "ResourceType" element |
---|
433 | |
---|
434 | writer.writeStartElement("ResourceRef"); |
---|
435 | writer.writeCharacters(resource.getRef()); |
---|
436 | writer.writeEndElement(); // "ResourceRef" element |
---|
437 | |
---|
438 | if(resource.getLabel() != null) { |
---|
439 | writer.writeStartElement("Label"); |
---|
440 | writer.writeCharacters(resource.getLabel()); |
---|
441 | writer.writeEndElement(); // "Label" element |
---|
442 | } |
---|
443 | |
---|
444 | if(resource.getDescription() != null) { |
---|
445 | writer.writeStartElement("Description"); |
---|
446 | writer.writeCharacters(resource.getDescription()); |
---|
447 | writer.writeEndElement(); |
---|
448 | } |
---|
449 | |
---|
450 | writer.writeEndElement(); // "Resource" element |
---|
451 | } |
---|
452 | |
---|
453 | private VirtualCollection readVirtualCollection( |
---|
454 | XMLStreamReader reader) throws XMLStreamException { |
---|
455 | readStart(reader, "VirtualCollection", true, false); |
---|
456 | |
---|
457 | VirtualCollection vc = new VirtualCollection(); |
---|
458 | String s = reader.getAttributeValue(null, "state"); |
---|
459 | if ((s != null) && !s.isEmpty()) { |
---|
460 | if ("private".equals(s)) { |
---|
461 | vc.setState(VirtualCollection.State.PRIVATE); |
---|
462 | } else if ("public-pending".equals(s)) { |
---|
463 | vc.setState(VirtualCollection.State.PUBLIC_PENDING); |
---|
464 | } else if ("public".equals(s)) { |
---|
465 | vc.setState(VirtualCollection.State.PUBLIC); |
---|
466 | } else if ("deleted".equals(s)) { |
---|
467 | vc.setState(VirtualCollection.State.DELETED); |
---|
468 | } else if ("dead".equals(s)) { |
---|
469 | vc.setState(VirtualCollection.State.DEAD); |
---|
470 | } else { |
---|
471 | throw new XMLStreamException("invalid value for attribute " + |
---|
472 | "'state' on element 'VirtualCollecion', expected one " + |
---|
473 | "of 'private', 'public-pending', 'public', " + |
---|
474 | "'deleted' or 'dead'"); |
---|
475 | } |
---|
476 | } |
---|
477 | reader.next(); |
---|
478 | readStart(reader, "Type", true, true); |
---|
479 | s = readString(reader, true); |
---|
480 | if ("extensional".equals(s)) { |
---|
481 | vc.setType(VirtualCollection.Type.EXTENSIONAL); |
---|
482 | } else if ("intensional".equals(s)) { |
---|
483 | vc.setType(VirtualCollection.Type.INTENSIONAL); |
---|
484 | } else { |
---|
485 | throw new XMLStreamException("invalid value for element 'Type', " + |
---|
486 | "expected either 'extensional' or 'intensional'"); |
---|
487 | } |
---|
488 | readStart(reader, "Name", true, true); |
---|
489 | vc.setName(readString(reader, false)); |
---|
490 | if (readStart(reader, "Description", false, true)) { |
---|
491 | vc.setDescription(readString(reader, false)); |
---|
492 | } |
---|
493 | if (readStart(reader, "CreationDate", false, true)) { |
---|
494 | try { |
---|
495 | // XXX: threading vs. performance |
---|
496 | synchronized (df) { |
---|
497 | vc.setCreationDate(df.parse(readString(reader, false))); |
---|
498 | } // synchronized df |
---|
499 | } catch (ParseException e) { |
---|
500 | throw new XMLStreamException("invalid date format", e); |
---|
501 | } |
---|
502 | } |
---|
503 | if (readStart(reader, "Creators", false, true)) { |
---|
504 | readStart(reader, "Creator", true, true); |
---|
505 | do { |
---|
506 | readStart(reader, "Person", true, true); |
---|
507 | Creator creator = new Creator(readString(reader, false)); |
---|
508 | if (readStart(reader, "Address", false, true)) { |
---|
509 | creator.setAddress(readString(reader, false)); |
---|
510 | } |
---|
511 | if (readStart(reader, "Email", false, true)) { |
---|
512 | creator.setEMail(readString(reader, false)); |
---|
513 | } |
---|
514 | if (readStart(reader, "Organisation", false, true)) { |
---|
515 | creator.setOrganisation(readString(reader, false)); |
---|
516 | } |
---|
517 | if (readStart(reader, "Telephone", false, true)) { |
---|
518 | creator.setTelephone(readString(reader, false)); |
---|
519 | } |
---|
520 | if (readStart(reader, "Website", false, true)) { |
---|
521 | creator.setWebsite(readString(reader, false)); |
---|
522 | } |
---|
523 | if (readStart(reader, "Role", false, true)) { |
---|
524 | creator.setRole(readString(reader, false)); |
---|
525 | } |
---|
526 | vc.getCreators().add(creator); |
---|
527 | } while (readStart(reader, "Creator", false, true)); |
---|
528 | } |
---|
529 | if (readStart(reader, "Purpose", false, true)) { |
---|
530 | s = readString(reader, true); |
---|
531 | if ("research".equals(s)) { |
---|
532 | vc.setPurpose(VirtualCollection.Purpose.RESEARCH); |
---|
533 | } else if ("reference".equals(s)) { |
---|
534 | vc.setPurpose(VirtualCollection.Purpose.REFERENCE); |
---|
535 | } else if ("sample".equals(s)) { |
---|
536 | vc.setPurpose(VirtualCollection.Purpose.SAMPLE); |
---|
537 | } else if ("future-use".equals(s)) { |
---|
538 | vc.setPurpose(VirtualCollection.Purpose.FUTURE_USE); |
---|
539 | } else { |
---|
540 | throw new XMLStreamException("invalid value for element " + |
---|
541 | "'Purpose', expected one of 'research', 'reference'," + |
---|
542 | " 'sample' or 'future-use'"); |
---|
543 | } |
---|
544 | } |
---|
545 | if (readStart(reader, "Reproducibility", false, true)) { |
---|
546 | s = readString(reader, true); |
---|
547 | if ("intended".equals(s)) { |
---|
548 | vc.setReproducibility(VirtualCollection |
---|
549 | .Reproducibility.INTENDED); |
---|
550 | } else if ("fluctuating".equals(s)) { |
---|
551 | vc.setReproducibility(VirtualCollection |
---|
552 | .Reproducibility.FLUCTUATING); |
---|
553 | } else if ("untended".endsWith(s)) { |
---|
554 | vc.setReproducibility(VirtualCollection |
---|
555 | .Reproducibility.UNTENDED); |
---|
556 | } else { |
---|
557 | throw new XMLStreamException("invalid value for element " + |
---|
558 | "'Reproducibility', expected one of 'intended', "+ |
---|
559 | "'fluctuating' or 'fluctuating'"); |
---|
560 | } |
---|
561 | } |
---|
562 | if (readStart(reader, "ReproducibilityNotice", false, true)) { |
---|
563 | vc.setReproducibilityNotice(readString(reader, false)); |
---|
564 | } |
---|
565 | if (readStart(reader, "Keywords", false, true)) { |
---|
566 | readStart(reader, "Keyword", true, true); |
---|
567 | do { |
---|
568 | vc.getKeywords().add(readString(reader, false)); |
---|
569 | } while (readStart(reader, "Keyword", false, true)); |
---|
570 | } |
---|
571 | if (readStart(reader, "Resources", false, true)) { |
---|
572 | readStart(reader, "Resource", true, true); |
---|
573 | do { |
---|
574 | readStart(reader, "ResourceType", true, true); |
---|
575 | Resource.Type r_type; |
---|
576 | s = readString(reader, true); |
---|
577 | if ("Metadata".equals(s)) { |
---|
578 | r_type = Resource.Type.METADATA; |
---|
579 | } else if ("Resource".equals(s)) { |
---|
580 | r_type = Resource.Type.RESOURCE; |
---|
581 | } else { |
---|
582 | throw new XMLStreamException("invalid value for element " + |
---|
583 | "'ResourceType', expected either 'Metadata' " + |
---|
584 | "or 'Resource'"); |
---|
585 | } |
---|
586 | readStart(reader, "ResourceRef", true, true); |
---|
587 | final Resource resource = new Resource(r_type, readString(reader, false)); |
---|
588 | |
---|
589 | if(readStart(reader, "Label", false, true)){ |
---|
590 | resource.setLabel(readString(reader, false)); |
---|
591 | } |
---|
592 | |
---|
593 | if(readStart(reader, "Description", false, true)){ |
---|
594 | resource.setDescription(readString(reader, false)); |
---|
595 | } |
---|
596 | |
---|
597 | vc.getResources().add(resource); |
---|
598 | |
---|
599 | } while (readStart(reader, "Resource", false, true)); |
---|
600 | } |
---|
601 | if (readStart(reader, "GeneratedBy", false, true)) { |
---|
602 | readStart(reader, "Description", true, true); |
---|
603 | GeneratedBy generatedBy = |
---|
604 | new GeneratedBy(readString(reader, false)); |
---|
605 | if (readStart(reader, "URI", false, true)) { |
---|
606 | generatedBy.setURI(readString(reader, false)); |
---|
607 | } |
---|
608 | if (readStart(reader, "Query", false, false)) { |
---|
609 | s = reader.getAttributeValue(null, "profile"); |
---|
610 | if ((s == null) || s.isEmpty()) { |
---|
611 | throw new XMLStreamException("missing or empty " + |
---|
612 | "attribute 'profile' on element 'Query'"); |
---|
613 | } |
---|
614 | reader.next(); |
---|
615 | final GeneratedByQuery query = |
---|
616 | new GeneratedByQuery(s, readString(reader, false)); |
---|
617 | generatedBy.setQuery(query); |
---|
618 | } |
---|
619 | vc.setGeneratedBy(generatedBy); |
---|
620 | } |
---|
621 | // skip to end of virtual collection |
---|
622 | for (int t = reader.getEventType(); |
---|
623 | reader.hasNext(); |
---|
624 | t = reader.next()) { |
---|
625 | if ((t == XMLStreamConstants.END_ELEMENT) && |
---|
626 | "VirtualCollection".equals(reader.getLocalName())) { |
---|
627 | break; |
---|
628 | } |
---|
629 | } |
---|
630 | return vc; |
---|
631 | } |
---|
632 | |
---|
633 | private XMLStreamWriter createWriter(OutputStream out, Format format, |
---|
634 | boolean validate) throws XMLStreamException { |
---|
635 | if (out == null) { |
---|
636 | throw new NullPointerException("out == null"); |
---|
637 | } |
---|
638 | if (format == null) { |
---|
639 | throw new NullPointerException("format == null"); |
---|
640 | } |
---|
641 | |
---|
642 | switch (format) { |
---|
643 | case XML: |
---|
644 | XMLStreamWriter writer = |
---|
645 | xmlWriterFactory.createXMLStreamWriter(out, ENCODING); |
---|
646 | if (validate) { |
---|
647 | ((XMLStreamWriter2) writer).validateAgainst(schema); |
---|
648 | } |
---|
649 | return writer; |
---|
650 | case JSON: |
---|
651 | return jsonWriterFactory.createXMLStreamWriter(out, ENCODING); |
---|
652 | default: |
---|
653 | // should never happen |
---|
654 | throw new IllegalArgumentException("unsupported input format"); |
---|
655 | } // switch |
---|
656 | } |
---|
657 | |
---|
658 | private XMLStreamReader createReader(InputStream in, Format format, |
---|
659 | String encoding) throws XMLStreamException { |
---|
660 | if (in == null) { |
---|
661 | throw new NullPointerException("in == null"); |
---|
662 | } |
---|
663 | if (format == null) { |
---|
664 | throw new NullPointerException("format == null"); |
---|
665 | } |
---|
666 | if (encoding == null) { |
---|
667 | throw new NullPointerException("encoding == null"); |
---|
668 | } |
---|
669 | |
---|
670 | switch (format) { |
---|
671 | case XML: |
---|
672 | XMLStreamReader reader = |
---|
673 | xmlReaderFactory.createXMLStreamReader(in, encoding); |
---|
674 | ((XMLStreamReader2) reader).validateAgainst(schema); |
---|
675 | return reader; |
---|
676 | case JSON: |
---|
677 | // FIXME: json + schema validation? |
---|
678 | return jsonReaderFactory.createXMLStreamReader(in, encoding); |
---|
679 | default: |
---|
680 | // should never happen |
---|
681 | throw new IllegalArgumentException("unsupported input format"); |
---|
682 | } // switch |
---|
683 | } |
---|
684 | |
---|
685 | private static boolean readStart(XMLStreamReader reader, String element, |
---|
686 | boolean required, boolean advance) throws XMLStreamException { |
---|
687 | for (int type = reader.getEventType(); |
---|
688 | reader.hasNext(); |
---|
689 | type = reader.next()) { |
---|
690 | if (type == XMLStreamConstants.START_ELEMENT) { |
---|
691 | if (element.equals(reader.getLocalName())) { |
---|
692 | if (advance) { |
---|
693 | reader.next(); // advance to next tag |
---|
694 | } |
---|
695 | return true; |
---|
696 | } |
---|
697 | break; |
---|
698 | } |
---|
699 | } // for |
---|
700 | if (required) { |
---|
701 | throw new XMLStreamException("expected element '" + element + |
---|
702 | "' at this position"); |
---|
703 | } |
---|
704 | return false; |
---|
705 | } |
---|
706 | |
---|
707 | private static String readString(XMLStreamReader reader, boolean intern) |
---|
708 | throws XMLStreamException { |
---|
709 | int type = reader.getEventType(); |
---|
710 | while (type == XMLStreamConstants.SPACE) { |
---|
711 | type = reader.next(); |
---|
712 | } |
---|
713 | switch (type) { |
---|
714 | case XMLStreamConstants.CHARACTERS: |
---|
715 | /* FALL-TROUGH */ |
---|
716 | case XMLStreamConstants.CDATA: |
---|
717 | if (!reader.hasNext()) { |
---|
718 | throw new XMLStreamException("unexpected end of stream"); |
---|
719 | } |
---|
720 | String s = reader.getText(); |
---|
721 | if (s != null) { |
---|
722 | s = s.trim(); |
---|
723 | if (intern) { |
---|
724 | s = s.intern(); |
---|
725 | } |
---|
726 | } |
---|
727 | if (s == null || s.isEmpty()) { |
---|
728 | throw new XMLStreamException("expected character content " + |
---|
729 | "at this position", reader.getLocation()); |
---|
730 | } |
---|
731 | reader.next(); |
---|
732 | return s; |
---|
733 | default: |
---|
734 | throw new XMLStreamException("expected character content " + |
---|
735 | "at this position", reader.getLocation()); |
---|
736 | } // switch |
---|
737 | } |
---|
738 | |
---|
739 | } // class VirtualCollectionRegistryMarshaller |
---|