source: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUExplainRecordDataParser.java @ 7281

Last change on this file since 7281 was 7281, checked in by Oliver Schonefeld, 2 years ago
  • cleanup
  • Property svn:eol-style set to native
File size: 31.0 KB
Line 
1/**
2 * This software is copyright (c) 2012-2022 by
3 *  - Leibniz-Institut fuer Deutsche Sprache (http://www.ids-mannheim.de)
4 * This is free software. You can redistribute it
5 * and/or modify it under the terms described in
6 * the GNU General Public License v3 of which you
7 * should have received a copy. Otherwise you can download
8 * it from
9 *
10 *   http://www.gnu.org/licenses/gpl-3.0.txt
11 *
12 * @copyright Leibniz-Institut fuer Deutsche Sprache (http://www.ids-mannheim.de)
13 *
14 * @license http://www.gnu.org/licenses/gpl-3.0.txt
15 *  GNU General Public License v3
16 */
17package eu.clarin.sru.client;
18
19import java.util.ArrayList;
20import java.util.HashMap;
21import java.util.HashSet;
22import java.util.List;
23import java.util.Map;
24import java.util.Set;
25
26import javax.xml.namespace.QName;
27import javax.xml.stream.XMLStreamException;
28import javax.xml.stream.XMLStreamReader;
29
30import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
33import eu.clarin.sru.client.SRUExplainRecordData.ConfigInfo;
34import eu.clarin.sru.client.SRUExplainRecordData.DatabaseInfo;
35import eu.clarin.sru.client.SRUExplainRecordData.IndexInfo;
36import eu.clarin.sru.client.SRUExplainRecordData.LocalizedString;
37import eu.clarin.sru.client.SRUExplainRecordData.Schema;
38import eu.clarin.sru.client.SRUExplainRecordData.ServerInfo;
39
40
41/**
42 * This class implements a (partial) record data parser for SRU explain record
43 * data conforming to the ZeeRex schema.
44 *
45 * @see <a href="http://zeerex.z3950.org/dtd/">ZeeRex DTD</a>
46 */
47class SRUExplainRecordDataParser {
48    private static final String ZEEREX_NS       =
49            SRUExplainRecordData.RECORD_SCHEMA;
50    private static final String ZEEREX_NS_QUIRK =
51            "http://explain.z3950.org/dtd/2.1/";
52    private static final String VERSION_1_1     = "1.1";
53    private static final String VERSION_1_2     = "1.2";
54    private static final String VERSION_2       = "2";
55    private static final String VERSION_2_0     = "2.0";
56    private static final String TRANSPORT_HTTP  = "http";
57    private static final String TRANSPORT_HTTPS = "https";
58    private static final String STRING_TRUE     = "true";
59    private static final String PRIMARY_FALSE   = "false";
60    private static final Logger logger =
61            LoggerFactory.getLogger(SRUExplainRecordDataParser.class);
62
63
64    public SRURecordData parse(XMLStreamReader reader, SRUVersion version,
65            boolean strict, String recordSchema) throws XMLStreamException,
66            SRUClientException {
67        // sanity check, if we are dealing with the expected record schema
68        if (!(ZEEREX_NS.equals(recordSchema) ||
69                ZEEREX_NS_QUIRK.equals(recordSchema))) {
70            throw new SRUClientException("record schema '" + recordSchema +
71                    "' not supported in explain response record data");
72        }
73
74        logger.debug("parsing explain record data (version={}, schema={})",
75                version, recordSchema);
76
77        // explain
78        if (XmlStreamReaderUtils.peekStart(reader, ZEEREX_NS, "explain")) {
79            return parseExplain(reader, version, strict, ZEEREX_NS);
80        } else if (XmlStreamReaderUtils.peekStart(reader,
81                ZEEREX_NS_QUIRK, "explain")) {
82            if (strict) {
83                logger.warn("namespace '{}' is not defined by ZeeRex, " +
84                        "enabling quirks mode (consider using namespace '{}'" +
85                        " which is defined)", ZEEREX_NS_QUIRK, ZEEREX_NS);
86            } else {
87                logger.info("namespace '{}' is not defined by ZeeRex, " +
88                        "enabling quirks mode (consider using namespace '{}'" +
89                        " which is defined)", ZEEREX_NS_QUIRK, ZEEREX_NS);
90            }
91            return parseExplain(reader, version, strict, ZEEREX_NS_QUIRK);
92        } else {
93            throw new XMLStreamException("expected start tag for element '" +
94                    new QName(ZEEREX_NS, "explain") + " at this position",
95                    reader.getLocation());
96        }
97    }
98
99
100    private static SRURecordData parseExplain(XMLStreamReader reader,
101            SRUVersion version, boolean strict, String ns)
102            throws XMLStreamException, SRUClientException {
103
104        // explain
105        XmlStreamReaderUtils.readStart(reader, ns, "explain", true);
106
107        /*
108         * explain (serverInfo, databaseInfo?, metaInfo?, indexInfo?,
109         *     (recordInfo|schemaInfo)?, configInfo?)
110         */
111
112        // explain/serverInfo (mandatory)
113        ServerInfo serverInfo = parseServerInfo(reader, ns);
114
115        // explain/databaseInfo (optional)
116        DatabaseInfo databaseInfo = null;
117        if (XmlStreamReaderUtils.readStart(reader, ns, "databaseInfo", false)) {
118            databaseInfo = parseDatabaseInfo(reader, ns, strict);
119            XmlStreamReaderUtils.readEnd(reader, ns, "databaseInfo");
120        }
121
122        // explain/metaInfo (optional)
123        if (XmlStreamReaderUtils.readStart(reader, ns, "metaInfo", false)) {
124            /*
125             * metaInfo (dateModified, (aggregatedFrom, dateAggregated)?)
126             */
127            logger.debug("metaInfo");
128            XmlStreamReaderUtils.readEnd(reader, ns, "metaInfo", true);
129        }
130
131        // explain/indexInfo (optional)
132        IndexInfo indexInfo = null;
133        if (XmlStreamReaderUtils.readStart(reader, ns, "indexInfo", false)) {
134            indexInfo = parseIndexInfo(reader, strict, ns);
135            XmlStreamReaderUtils.readEnd(reader, ns, "indexInfo");
136        } // if
137
138        // explain/recordInfo or explain/schemaInfo
139        List<Schema> schemaInfo = null;
140        if (XmlStreamReaderUtils.peekStart(reader, ns, "recordInfo") ||
141            XmlStreamReaderUtils.peekStart(reader, ns, "schemaInfo")) {
142            if (XmlStreamReaderUtils.readStart(reader,
143                    ns, "recordInfo", false)) {
144                logger.debug("skipping 'recordInfo'");
145                XmlStreamReaderUtils.readEnd(reader, ns, "recordInfo", true);
146            } else if (XmlStreamReaderUtils.readStart(reader,
147                    ns, "schemaInfo", false)) {
148                schemaInfo = parseSchemaInfo(reader, strict, ns);
149                XmlStreamReaderUtils.readEnd(reader, ns, "schemaInfo");
150            } else {
151                throw new XMLStreamException("unexpected start element '" +
152                        reader.getName() + "'", reader.getLocation());
153            }
154        }
155
156        // explain/configInfo (optional)
157        ConfigInfo configInfo = null;
158        if (XmlStreamReaderUtils.readStart(reader, ns, "configInfo", false)) {
159            configInfo = parseConfigInfo(reader, strict, ns);
160            XmlStreamReaderUtils.readEnd(reader, ns, "configInfo");
161        }
162
163        XmlStreamReaderUtils.readEnd(reader, ns, "explain", true);
164        return new SRUExplainRecordData(serverInfo, databaseInfo, indexInfo,
165                schemaInfo, configInfo);
166    }
167
168
169    private static ServerInfo parseServerInfo(XMLStreamReader reader,
170            String ns) throws XMLStreamException, SRUClientException {
171        XmlStreamReaderUtils.readStart(reader, ns,
172                "serverInfo", true, true);
173        String protocol = XmlStreamReaderUtils.readAttributeValue(reader,
174                null, "protocol");
175
176        SRUVersion version = SRUVersion.VERSION_1_2;
177        String s = XmlStreamReaderUtils.readAttributeValue(reader, null,
178                "version");
179        if (s != null) {
180            if (VERSION_1_1.equals(s)) {
181                version = SRUVersion.VERSION_1_1;
182            } else if (VERSION_1_2.equals(s)) {
183                version = SRUVersion.VERSION_1_2;
184            } else if (VERSION_2.equals(s) || VERSION_2_0.equals(s)) {
185                version = SRUVersion.VERSION_2_0;
186            } else {
187                throw new SRUClientException("invalid or unsupported value '" +
188                        s + " 'for attribute 'version' on element '" +
189                        reader.getName() + "'");
190            }
191        }
192
193        Set<String> transports = new HashSet<>();
194        s = XmlStreamReaderUtils.readAttributeValue(reader, null, "transport");
195        if (s != null) {
196            for (String i : s.split("\\s+")) {
197                String t = null;
198                if (TRANSPORT_HTTP.equalsIgnoreCase(i)) {
199                    t = TRANSPORT_HTTP;
200                } else if (TRANSPORT_HTTPS.equalsIgnoreCase(i)) {
201                    t = TRANSPORT_HTTPS;
202                } else {
203                    throw new SRUClientException("invalid value '" + i +
204                            "' for attribute 'transport' on element '" +
205                            reader.getName() +
206                            " (use either 'http' of 'https' or both " +
207                            "seperated by whitespace");
208                }
209                if (t != null) {
210                    if (!transports.contains(t)) {
211                        transports.add(t);
212                    } else {
213                        logger.warn("value '{}' already listed in " +
214                                "'transport' attribute of element '{}'",
215                                t, reader.getName());
216                    }
217                }
218
219            } // for
220        } else {
221            transports.add(TRANSPORT_HTTP);
222        }
223        XmlStreamReaderUtils.consumeStart(reader);
224
225        final String host = XmlStreamReaderUtils.readContent(reader,
226                ns, "host", true);
227        final int port = XmlStreamReaderUtils.readContent(reader,
228                ns, "port", true, -1);
229        if ((port < 0) || (port > 65535)) {
230            // FIXME: error message
231            throw new SRUClientException("invalid port number (" + port + ")");
232        }
233        String database = XmlStreamReaderUtils.readContent(reader, ns,
234                "database", true);
235        if (XmlStreamReaderUtils.readStart(reader, ns,
236                "authentication", false)) {
237            XmlStreamReaderUtils.readEnd(reader, ns,
238                    "authentication", true);
239        }
240        XmlStreamReaderUtils.readEnd(reader, ns, "serverInfo", true);
241        logger.debug("serverInfo: host={}, port={}, database={}, version={}, " +
242                "protocol={}, transport={}", host, port, database, version,
243                protocol, transports);
244        return new ServerInfo(host, port, database, protocol, version,
245                transports);
246    }
247
248
249    private static DatabaseInfo parseDatabaseInfo(XMLStreamReader reader,
250            String ns, boolean strict) throws XMLStreamException,
251            SRUClientException {
252        /*
253         * databaseInfo (title*, description*, (author | contact | extent |
254         *     history | langUsage | restrictions | subjects | links |
255         *     implementation)*)
256         */
257
258        List<LocalizedString> title = null;
259        List<LocalizedString> description = null;
260        List<LocalizedString> author = null;
261        List<LocalizedString> contact = null;
262        List<LocalizedString> extent = null;
263        List<LocalizedString> history = null;
264        List<LocalizedString> langUsage = null;
265        List<LocalizedString> restrictions = null;
266        List<LocalizedString> subjects = null;
267        List<LocalizedString> links = null;
268        List<LocalizedString> implementation = null;
269
270        byte mode = 0; /* 1 = title, 2 = description, 3 = others */
271        for (;;) {
272            if (XmlStreamReaderUtils.peekStart(reader, ns, "title")) {
273                if ((mode != 0) && (mode != 1)) {
274                    if (strict) {
275                        throw new XMLStreamException(
276                                "element '" + new QName(ns, "title") +
277                                        "' not allowed here [required content" +
278                                        " model is: title*, description*, " +
279                                        "(author | contact | extent | history" +
280                                        " | langUsage | restrictions | " +
281                                        "subjects | links | implementation)*]",
282                                        reader.getLocation());
283                    } else {
284                        logger.warn("element '{}' not allowed here [required " +
285                                "content model is: title*, description*, " +
286                                "(author | contact | extent | history | " +
287                                "langUsage | restrictions | subjects | links " +
288                                "| implementation)*] at position " +
289                                "[row, col]: [{}, {}]",
290                                new QName(ns, "title"),
291                                reader.getLocation().getLineNumber(),
292                                reader.getLocation().getColumnNumber());
293                    }
294                }
295                LocalizedString s =
296                        parseStringI18N(reader, strict, ns, "title", true);
297                if (title == null) {
298                    title = new ArrayList<>();
299                }
300                title.add(s);
301                mode = 1;
302            } else if (XmlStreamReaderUtils.peekStart(reader, ns, "description")) {
303                if ((mode != 0) && (mode != 1) && (mode != 2)) {
304                    if (strict) {
305                        throw new XMLStreamException(
306                                "element '" + new QName(ns, "description") +
307                                        "' not allowed here [required content" +
308                                        " model is: title*, description*, " +
309                                        "(author | contact | extent | history" +
310                                        " | langUsage | restrictions | " +
311                                        "subjects | links | implementation)*]",
312                                        reader.getLocation());
313                    } else {
314                        logger.warn("element '{}' not allowed here [required " +
315                                "content model is: title*, description*, " +
316                                "(author | contact | extent | history | " +
317                                "langUsage | restrictions | subjects | links " +
318                                "| implementation)*] at position " +
319                                "[row, col]: [{}, {}]",
320                                new QName(ns, "description"),
321                                reader.getLocation().getLineNumber(),
322                                reader.getLocation().getColumnNumber());
323                    }
324                }
325                LocalizedString s =
326                        parseStringI18N(reader, strict, ns, "description", true);
327                if (description == null) {
328                    description = new ArrayList<>();
329                }
330                description.add(s);
331                mode = 2;
332            } else if (XmlStreamReaderUtils.peekStart(reader, ns, "author")) {
333                LocalizedString s =
334                        parseStringI18N(reader, strict, ns, "author", true);
335                if (author == null) {
336                    author = new ArrayList<>();
337                }
338                author.add(s);
339                mode = 3;
340            } else if (XmlStreamReaderUtils.peekStart(reader, ns, "contact")) {
341                LocalizedString s =
342                        parseStringI18N(reader, strict, ns, "contact", true);
343                if (contact == null) {
344                    contact = new ArrayList<>();
345                }
346                contact.add(s);
347                mode = 3;
348            } else if (XmlStreamReaderUtils.peekStart(reader, ns, "extent")) {
349                LocalizedString s =
350                        parseStringI18N(reader, strict, ns, "extent", true);
351                if (extent == null) {
352                    extent = new ArrayList<>();
353                }
354                extent.add(s);
355                mode = 3;
356            } else if (XmlStreamReaderUtils.peekStart(reader, ns, "history")) {
357                LocalizedString s =
358                        parseStringI18N(reader, strict, ns, "history", true);
359                if (history == null) {
360                    history = new ArrayList<>();
361                }
362                history.add(s);
363                mode = 3;
364            } else if (XmlStreamReaderUtils.peekStart(reader,
365                    ns, "restrictions")) {
366                LocalizedString s =
367                        parseStringI18N(reader, strict, ns, "restrictions", true);
368                if (restrictions == null) {
369                    restrictions = new ArrayList<>();
370                }
371                restrictions.add(s);
372                mode = 3;
373            } else if (XmlStreamReaderUtils.peekStart(reader, ns, "subjects")) {
374                LocalizedString s =
375                        parseStringI18N(reader, strict, ns, "subjects", true);
376                if (subjects == null) {
377                    subjects = new ArrayList<>();
378                }
379                subjects.add(s);
380                mode = 3;
381            } else if (XmlStreamReaderUtils.peekStart(reader, ns, "links")) {
382                LocalizedString s =
383                        parseStringI18N(reader, strict, ns, "links", true);
384                if (links == null) {
385                    links = new ArrayList<>();
386                }
387                links.add(s);
388                mode = 3;
389            } else if (XmlStreamReaderUtils.peekStart(reader,
390                    ns, "implementation")) {
391                LocalizedString s =
392                        parseStringI18N(reader, strict, ns, "implementation", true);
393                if (implementation == null) {
394                    implementation = new ArrayList<>();
395                }
396                implementation.add(s);
397                mode = 3;
398            } else if (XmlStreamReaderUtils.peekStart(reader, ns, "langUsage")) {
399                // FIXME: implement!
400                XmlStreamReaderUtils.readContent(reader, ns, "langUsage", false);
401                mode = 3;
402            } else {
403                break;
404            }
405        } // for
406
407        return new DatabaseInfo(title, description, author, contact,
408                extent, history, langUsage, restrictions, subjects,
409                links, implementation);
410    }
411
412
413    private static IndexInfo parseIndexInfo(XMLStreamReader reader,
414            boolean strict, String ns) throws XMLStreamException,
415            SRUClientException {
416        /*
417         * indexInfo ((set | index | sortKeywords)+)
418         */
419        boolean found = false;
420        List<IndexInfo.Set> sets = null;
421        List<IndexInfo.Index> indexes = null;
422        for (;;) {
423            if (XmlStreamReaderUtils.readStart(reader, ns, "set", false, true)) {
424                final String identifier =
425                        XmlStreamReaderUtils.readAttributeValue(reader,
426                                null, "identifier");
427                final String name =
428                        XmlStreamReaderUtils.readAttributeValue(reader,
429                                null, "name");
430                XmlStreamReaderUtils.consumeStart(reader);
431
432                // indexInfo/set/title
433                List<LocalizedString> titles = null;
434                for (;;) {
435                    LocalizedString title =
436                            parseStringI18N(reader, strict, ns, "title", false);
437                    if (title == null) {
438                        break;
439                    }
440                    if (titles == null) {
441                        titles = new ArrayList<>();
442                    }
443                    titles.add(title);
444                } // for
445                XmlStreamReaderUtils.readEnd(reader, ns, "set");
446
447                if (sets == null) {
448                    sets = new ArrayList<>();
449                }
450                sets.add(new IndexInfo.Set(identifier, name, titles));
451                found = true;
452            } else if (XmlStreamReaderUtils.readStart(reader, ns,
453                    "index", false, true)) {
454                final String id =
455                        XmlStreamReaderUtils.readAttributeValue(reader, null, "id");
456                final boolean can_search = parseBooleanAttribute(reader,
457                        strict, null, "search", false);
458                final boolean can_scan = parseBooleanAttribute(reader,
459                        strict, null, "scan", false);
460                final boolean can_sort = parseBooleanAttribute(reader,
461                        strict, null, "sort", false);
462                XmlStreamReaderUtils.consumeStart(reader);
463
464                // indexInfo/index/title
465                List<LocalizedString> titles = null;
466                for (;;) {
467                    LocalizedString title =
468                            parseStringI18N(reader, strict, ns, "title", false);
469                    if (title == null) {
470                        break;
471                    }
472                    if (titles == null) {
473                        titles = new ArrayList<>();
474                    }
475                    titles.add(title);
476                } // for
477
478                // indexInfo/index/map ((attr+)|name)
479                List<IndexInfo.Index.Map> maps = null;
480                boolean first_map = true;
481                while (XmlStreamReaderUtils.readStart(reader, ns, "map",
482                        first_map, true)) {
483                    final boolean primary = parseBooleanAttribute(reader,
484                            strict, null, "primary", false);
485                    XmlStreamReaderUtils.consumeStart(reader);
486
487                    if (XmlStreamReaderUtils.peekStart(reader, ns, "attr")) {
488                        /*
489                         * skip "attr" elements, because they are not supported
490                         */
491                        while (XmlStreamReaderUtils.readStart(reader,
492                                ns, "attr", false)) {
493                            logger.debug("skipping 'attr'");
494                            XmlStreamReaderUtils.readEnd(reader, ns, "attr");
495                        } // while (attr)
496                    } else if (XmlStreamReaderUtils.peekStart(reader,
497                            ns, "name")) {
498                        XmlStreamReaderUtils.readStart(reader, ns, "name", true, true);
499                        final String set =
500                                XmlStreamReaderUtils.readAttributeValue(reader,
501                                        null, "set");
502                        // FIXME: check 'set'
503                        XmlStreamReaderUtils.consumeStart(reader);
504                        final String name =
505                                XmlStreamReaderUtils.readString(reader, false);
506                        // FIXME: check 'name'
507                        XmlStreamReaderUtils.readEnd(reader, ns, "name");
508                        if ((set != null) && (name != null)) {
509                            if (maps == null) {
510                                maps = new ArrayList<>();
511                            }
512                            maps.add(new IndexInfo.Index.Map(primary, set, name));
513                        }
514                    } else {
515                        // FIXME: error message
516                        throw new XMLStreamException(
517                                "expected 'attr' or 'name'",
518                                reader.getLocation());
519                    }
520
521                    XmlStreamReaderUtils.readEnd(reader, ns, "map");
522                    first_map = false;
523                } // while (map)
524
525                // indexInfo/index/configInfo (optional)
526                if (XmlStreamReaderUtils.readStart(reader, ns, "configInfo", false)) {
527                    logger.debug("skipping 'configInfo' within 'indexInfo/index'");
528                    XmlStreamReaderUtils.readEnd(reader, ns, "configInfo", true);
529                }
530
531                XmlStreamReaderUtils.readEnd(reader, ns, "index");
532                if (indexes == null) {
533                    indexes = new ArrayList<>();
534                }
535                indexes.add(new IndexInfo.Index(id, titles, can_search,
536                        can_scan, can_sort, maps));
537                found = true;
538            } else if (XmlStreamReaderUtils.readStart(reader, ns, "sortKeyword", false)) {
539                logger.debug("skipping 'sortKeywords'");
540                XmlStreamReaderUtils.readEnd(reader, ns, "sortKeyword", true);
541                found = true;
542            } else {
543                break;
544            }
545        } // for
546        if (!found) {
547            throw new XMLStreamException("expected at least one '" +
548                    new QName(ns, "set") + "', '" +
549                    new QName(ns, "index") + "' or '" +
550                    new QName(ns, "sortKeyword") +
551                    "' element within element '" +
552                    new QName(ns, "indexInfo") + "'",
553                    reader.getLocation());
554        }
555        return ((sets != null) || (indexes != null))
556                ? new IndexInfo(sets, indexes)
557                : null;
558    }
559
560
561    private static ConfigInfo parseConfigInfo(XMLStreamReader reader,
562            boolean strict, String ns) throws XMLStreamException,
563            SRUClientException {
564        /*
565         * configInfo ((default|setting|supports)*)
566         */
567        Map<String, String> defaults = null;
568        Map<String, String> settings = null;
569        Map<String, String> supports = null;
570        for (;;) {
571            if (XmlStreamReaderUtils.peekStart(reader, ns, "default")) {
572                defaults = parseConfigInfoItem(reader, strict, ns,
573                        "default", defaults);
574            } else if (XmlStreamReaderUtils.peekStart(reader, ns, "setting")) {
575                settings = parseConfigInfoItem(reader, strict, ns,
576                        "setting", settings);
577            } else if (XmlStreamReaderUtils.peekStart(reader, ns, "supports")) {
578                supports = parseConfigInfoItem(reader, strict, ns,
579                        "supports", supports);
580            } else {
581                break;
582            }
583        } // for
584
585        return ((defaults != null) || (settings != null) || (supports != null))
586                ? new ConfigInfo(defaults, settings, supports)
587                : null;
588    }
589
590
591    private static LocalizedString parseStringI18N(XMLStreamReader reader,
592            boolean strict, String ns, String localName, boolean required)
593            throws XMLStreamException {
594        if (!XmlStreamReaderUtils.readStart(reader, ns, localName, required,
595                true)) {
596            return null;
597        }
598        final String lang = XmlStreamReaderUtils.readAttributeValue(reader,
599                null, "lang", false);
600        if (lang != null) {
601            if (lang.length() != 2) {
602                // FIXME: message
603                logger.warn("ZeeRex sugguests to use 2-letter codes");
604            }
605        }
606        final boolean primary =
607                parseBooleanAttribute(reader, strict, null, "primary", false);
608        XmlStreamReaderUtils.consumeStart(reader);
609        String value = XmlStreamReaderUtils.readString(reader, false);
610        XmlStreamReaderUtils.readEnd(reader, ns, localName);
611        return new LocalizedString(value, lang, primary);
612    }
613
614
615    private static boolean parseBooleanAttribute(XMLStreamReader reader,
616            boolean strict, String ns, String localName, boolean defaultValue)
617            throws XMLStreamException {
618        boolean result = defaultValue;
619        final String s = XmlStreamReaderUtils.readAttributeValue(reader,
620                ns, localName, false);
621        if (s != null) {
622            if (STRING_TRUE.equalsIgnoreCase(s)) {
623                if (!STRING_TRUE.equals(s)) {
624                    if (strict) {
625                        throw new XMLStreamException("capitalization");
626                    } else {
627                        // FIXME: message
628                        logger.warn("capitalizaton");
629                    }
630                }
631                result = true;
632            } else if (PRIMARY_FALSE.equalsIgnoreCase(s)) {
633                if (!PRIMARY_FALSE.equals(s)) {
634                    if (strict) {
635                        throw new XMLStreamException("capitalization");
636                    } else {
637                        // FIXME: message
638                        logger.warn("capitalizaton");
639                    }
640                }
641                result = false;
642            } else {
643                // FIXME: message
644                throw new XMLStreamException("value of @" + localName + " invalid");
645            }
646        }
647        return result;
648    }
649
650
651    private static List<Schema> parseSchemaInfo(XMLStreamReader reader,
652            boolean strict, String ns) throws XMLStreamException {
653        /*
654         * schemaInfo (schema+)
655         * schema (title*)
656         */
657        List<Schema> schemaInfo = null;
658        boolean first_schema = true;
659        while (XmlStreamReaderUtils.readStart(reader, ns, "schema",
660                first_schema, true)) {
661            final String identifier =
662                    XmlStreamReaderUtils.readAttributeValue(reader,
663                            null, "identifier", true);
664            final String name = XmlStreamReaderUtils.readAttributeValue(reader,
665                    null, "name", true);
666            final String location =
667                    XmlStreamReaderUtils.readAttributeValue(reader,
668                            null, "location");
669            final boolean sort = parseBooleanAttribute(reader, strict,
670                    null, "sort", false);
671            final boolean retrieve = parseBooleanAttribute(reader, strict,
672                    null, "retrieve", true);
673            XmlStreamReaderUtils.consumeStart(reader);
674
675            List<LocalizedString> titles = null;
676            for (;;) {
677                LocalizedString title =
678                        parseStringI18N(reader, strict, ns, "title", false);
679                if (title == null) {
680                    break;
681                }
682                if (titles == null) {
683                    titles = new ArrayList<>();
684                }
685                titles.add(title);
686            } // for
687            XmlStreamReaderUtils.readEnd(reader, ns, "schema");
688
689            if (schemaInfo == null) {
690                schemaInfo = new ArrayList<>();
691            }
692            schemaInfo.add(new Schema(identifier, name, location, sort,
693                    retrieve, titles));
694            first_schema = false;
695        }
696        return schemaInfo;
697    }
698
699
700    private static Map<String, String> parseConfigInfoItem(
701            XMLStreamReader reader, boolean strict, String ns,
702            String localName, Map<String, String> map)
703            throws XMLStreamException {
704        XmlStreamReaderUtils.readStart(reader, ns, localName, true, true);
705        final String type = XmlStreamReaderUtils.readAttributeValue(reader,
706                null, "type", true);
707        XmlStreamReaderUtils.consumeStart(reader);
708        final String value = XmlStreamReaderUtils.readString(reader, true);
709        XmlStreamReaderUtils.readEnd(reader, ns, localName);
710
711        if ((type != null) && (value != null)) {
712            if (map == null) {
713                map = new HashMap<>();
714            }
715            if (map.containsKey(type)) {
716                logger.warn(
717                        "{} with type '{}' is already present, skipping duplicate entry",
718                        localName, type);
719            } else {
720                map.put(type, value);
721            }
722        }
723        return map;
724    }
725
726} // class SRUExplainRecordDataParser
Note: See TracBrowser for help on using the repository browser.