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

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