Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jaxp/src/org/xml/sax/helpers/NamespaceSupport.java
48576 views
1
/*
2
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
// NamespaceSupport.java - generic Namespace support for SAX.
27
// http://www.saxproject.org
28
// Written by David Megginson
29
// This class is in the Public Domain. NO WARRANTY!
30
// $Id: NamespaceSupport.java,v 1.5 2004/11/03 22:53:09 jsuttor Exp $
31
32
package org.xml.sax.helpers;
33
34
import java.util.ArrayList;
35
import java.util.Collections;
36
import java.util.EmptyStackException;
37
import java.util.Enumeration;
38
import java.util.HashMap;
39
import java.util.List;
40
import java.util.Map;
41
42
43
/**
44
* Encapsulate Namespace logic for use by applications using SAX,
45
* or internally by SAX drivers.
46
*
47
* <blockquote>
48
* <em>This module, both source code and documentation, is in the
49
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
50
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
51
* for further information.
52
* </blockquote>
53
*
54
* <p>This class encapsulates the logic of Namespace processing: it
55
* tracks the declarations currently in force for each context and
56
* automatically processes qualified XML names into their Namespace
57
* parts; it can also be used in reverse for generating XML qnames
58
* from Namespaces.</p>
59
*
60
* <p>Namespace support objects are reusable, but the reset method
61
* must be invoked between each session.</p>
62
*
63
* <p>Here is a simple session:</p>
64
*
65
* <pre>
66
* String parts[] = new String[3];
67
* NamespaceSupport support = new NamespaceSupport();
68
*
69
* support.pushContext();
70
* support.declarePrefix("", "http://www.w3.org/1999/xhtml");
71
* support.declarePrefix("dc", "http://www.purl.org/dc#");
72
*
73
* parts = support.processName("p", parts, false);
74
* System.out.println("Namespace URI: " + parts[0]);
75
* System.out.println("Local name: " + parts[1]);
76
* System.out.println("Raw name: " + parts[2]);
77
*
78
* parts = support.processName("dc:title", parts, false);
79
* System.out.println("Namespace URI: " + parts[0]);
80
* System.out.println("Local name: " + parts[1]);
81
* System.out.println("Raw name: " + parts[2]);
82
*
83
* support.popContext();
84
* </pre>
85
*
86
* <p>Note that this class is optimized for the use case where most
87
* elements do not contain Namespace declarations: if the same
88
* prefix/URI mapping is repeated for each context (for example), this
89
* class will be somewhat less efficient.</p>
90
*
91
* <p>Although SAX drivers (parsers) may choose to use this class to
92
* implement namespace handling, they are not required to do so.
93
* Applications must track namespace information themselves if they
94
* want to use namespace information.
95
*
96
* @since SAX 2.0
97
* @author David Megginson
98
*/
99
public class NamespaceSupport
100
{
101
102
103
////////////////////////////////////////////////////////////////////
104
// Constants.
105
////////////////////////////////////////////////////////////////////
106
107
108
/**
109
* The XML Namespace URI as a constant.
110
* The value is <code>http://www.w3.org/XML/1998/namespace</code>
111
* as defined in the "Namespaces in XML" * recommendation.
112
*
113
* <p>This is the Namespace URI that is automatically mapped
114
* to the "xml" prefix.</p>
115
*/
116
public final static String XMLNS =
117
"http://www.w3.org/XML/1998/namespace";
118
119
120
/**
121
* The namespace declaration URI as a constant.
122
* The value is <code>http://www.w3.org/xmlns/2000/</code>, as defined
123
* in a backwards-incompatible erratum to the "Namespaces in XML"
124
* recommendation. Because that erratum postdated SAX2, SAX2 defaults
125
* to the original recommendation, and does not normally use this URI.
126
*
127
*
128
* <p>This is the Namespace URI that is optionally applied to
129
* <em>xmlns</em> and <em>xmlns:*</em> attributes, which are used to
130
* declare namespaces. </p>
131
*
132
* @since SAX 2.1alpha
133
* @see #setNamespaceDeclUris
134
* @see #isNamespaceDeclUris
135
*/
136
public final static String NSDECL =
137
"http://www.w3.org/xmlns/2000/";
138
139
140
/**
141
* An empty enumeration.
142
*/
143
private final static Enumeration EMPTY_ENUMERATION =
144
Collections.enumeration(new ArrayList<String>());
145
146
147
////////////////////////////////////////////////////////////////////
148
// Constructor.
149
////////////////////////////////////////////////////////////////////
150
151
152
/**
153
* Create a new Namespace support object.
154
*/
155
public NamespaceSupport ()
156
{
157
reset();
158
}
159
160
161
162
////////////////////////////////////////////////////////////////////
163
// Context management.
164
////////////////////////////////////////////////////////////////////
165
166
167
/**
168
* Reset this Namespace support object for reuse.
169
*
170
* <p>It is necessary to invoke this method before reusing the
171
* Namespace support object for a new session. If namespace
172
* declaration URIs are to be supported, that flag must also
173
* be set to a non-default value.
174
* </p>
175
*
176
* @see #setNamespaceDeclUris
177
*/
178
public void reset ()
179
{
180
contexts = new Context[32];
181
namespaceDeclUris = false;
182
contextPos = 0;
183
contexts[contextPos] = currentContext = new Context();
184
currentContext.declarePrefix("xml", XMLNS);
185
}
186
187
188
/**
189
* Start a new Namespace context.
190
* The new context will automatically inherit
191
* the declarations of its parent context, but it will also keep
192
* track of which declarations were made within this context.
193
*
194
* <p>Event callback code should start a new context once per element.
195
* This means being ready to call this in either of two places.
196
* For elements that don't include namespace declarations, the
197
* <em>ContentHandler.startElement()</em> callback is the right place.
198
* For elements with such a declaration, it'd done in the first
199
* <em>ContentHandler.startPrefixMapping()</em> callback.
200
* A boolean flag can be used to
201
* track whether a context has been started yet. When either of
202
* those methods is called, it checks the flag to see if a new context
203
* needs to be started. If so, it starts the context and sets the
204
* flag. After <em>ContentHandler.startElement()</em>
205
* does that, it always clears the flag.
206
*
207
* <p>Normally, SAX drivers would push a new context at the beginning
208
* of each XML element. Then they perform a first pass over the
209
* attributes to process all namespace declarations, making
210
* <em>ContentHandler.startPrefixMapping()</em> callbacks.
211
* Then a second pass is made, to determine the namespace-qualified
212
* names for all attributes and for the element name.
213
* Finally all the information for the
214
* <em>ContentHandler.startElement()</em> callback is available,
215
* so it can then be made.
216
*
217
* <p>The Namespace support object always starts with a base context
218
* already in force: in this context, only the "xml" prefix is
219
* declared.</p>
220
*
221
* @see org.xml.sax.ContentHandler
222
* @see #popContext
223
*/
224
public void pushContext ()
225
{
226
int max = contexts.length;
227
228
contextPos++;
229
230
// Extend the array if necessary
231
if (contextPos >= max) {
232
Context newContexts[] = new Context[max*2];
233
System.arraycopy(contexts, 0, newContexts, 0, max);
234
max *= 2;
235
contexts = newContexts;
236
}
237
238
// Allocate the context if necessary.
239
currentContext = contexts[contextPos];
240
if (currentContext == null) {
241
contexts[contextPos] = currentContext = new Context();
242
}
243
244
// Set the parent, if any.
245
if (contextPos > 0) {
246
currentContext.setParent(contexts[contextPos - 1]);
247
}
248
}
249
250
251
/**
252
* Revert to the previous Namespace context.
253
*
254
* <p>Normally, you should pop the context at the end of each
255
* XML element. After popping the context, all Namespace prefix
256
* mappings that were previously in force are restored.</p>
257
*
258
* <p>You must not attempt to declare additional Namespace
259
* prefixes after popping a context, unless you push another
260
* context first.</p>
261
*
262
* @see #pushContext
263
*/
264
public void popContext ()
265
{
266
contexts[contextPos].clear();
267
contextPos--;
268
if (contextPos < 0) {
269
throw new EmptyStackException();
270
}
271
currentContext = contexts[contextPos];
272
}
273
274
275
276
////////////////////////////////////////////////////////////////////
277
// Operations within a context.
278
////////////////////////////////////////////////////////////////////
279
280
281
/**
282
* Declare a Namespace prefix. All prefixes must be declared
283
* before they are referenced. For example, a SAX driver (parser)
284
* would scan an element's attributes
285
* in two passes: first for namespace declarations,
286
* then a second pass using {@link #processName processName()} to
287
* interpret prefixes against (potentially redefined) prefixes.
288
*
289
* <p>This method declares a prefix in the current Namespace
290
* context; the prefix will remain in force until this context
291
* is popped, unless it is shadowed in a descendant context.</p>
292
*
293
* <p>To declare the default element Namespace, use the empty string as
294
* the prefix.</p>
295
*
296
* <p>Note that there is an asymmetry in this library: {@link
297
* #getPrefix getPrefix} will not return the "" prefix,
298
* even if you have declared a default element namespace.
299
* To check for a default namespace,
300
* you have to look it up explicitly using {@link #getURI getURI}.
301
* This asymmetry exists to make it easier to look up prefixes
302
* for attribute names, where the default prefix is not allowed.</p>
303
*
304
* @param prefix The prefix to declare, or the empty string to
305
* indicate the default element namespace. This may never have
306
* the value "xml" or "xmlns".
307
* @param uri The Namespace URI to associate with the prefix.
308
* @return true if the prefix was legal, false otherwise
309
*
310
* @see #processName
311
* @see #getURI
312
* @see #getPrefix
313
*/
314
public boolean declarePrefix (String prefix, String uri)
315
{
316
if (prefix.equals("xml") || prefix.equals("xmlns")) {
317
return false;
318
} else {
319
currentContext.declarePrefix(prefix, uri);
320
return true;
321
}
322
}
323
324
325
/**
326
* Process a raw XML qualified name, after all declarations in the
327
* current context have been handled by {@link #declarePrefix
328
* declarePrefix()}.
329
*
330
* <p>This method processes a raw XML qualified name in the
331
* current context by removing the prefix and looking it up among
332
* the prefixes currently declared. The return value will be the
333
* array supplied by the caller, filled in as follows:</p>
334
*
335
* <dl>
336
* <dt>parts[0]</dt>
337
* <dd>The Namespace URI, or an empty string if none is
338
* in use.</dd>
339
* <dt>parts[1]</dt>
340
* <dd>The local name (without prefix).</dd>
341
* <dt>parts[2]</dt>
342
* <dd>The original raw name.</dd>
343
* </dl>
344
*
345
* <p>All of the strings in the array will be internalized. If
346
* the raw name has a prefix that has not been declared, then
347
* the return value will be null.</p>
348
*
349
* <p>Note that attribute names are processed differently than
350
* element names: an unprefixed element name will receive the
351
* default Namespace (if any), while an unprefixed attribute name
352
* will not.</p>
353
*
354
* @param qName The XML qualified name to be processed.
355
* @param parts An array supplied by the caller, capable of
356
* holding at least three members.
357
* @param isAttribute A flag indicating whether this is an
358
* attribute name (true) or an element name (false).
359
* @return The supplied array holding three internalized strings
360
* representing the Namespace URI (or empty string), the
361
* local name, and the XML qualified name; or null if there
362
* is an undeclared prefix.
363
* @see #declarePrefix
364
* @see java.lang.String#intern */
365
public String [] processName (String qName, String parts[],
366
boolean isAttribute)
367
{
368
String myParts[] = currentContext.processName(qName, isAttribute);
369
if (myParts == null) {
370
return null;
371
} else {
372
parts[0] = myParts[0];
373
parts[1] = myParts[1];
374
parts[2] = myParts[2];
375
return parts;
376
}
377
}
378
379
380
/**
381
* Look up a prefix and get the currently-mapped Namespace URI.
382
*
383
* <p>This method looks up the prefix in the current context.
384
* Use the empty string ("") for the default Namespace.</p>
385
*
386
* @param prefix The prefix to look up.
387
* @return The associated Namespace URI, or null if the prefix
388
* is undeclared in this context.
389
* @see #getPrefix
390
* @see #getPrefixes
391
*/
392
public String getURI (String prefix)
393
{
394
return currentContext.getURI(prefix);
395
}
396
397
398
/**
399
* Return an enumeration of all prefixes whose declarations are
400
* active in the current context.
401
* This includes declarations from parent contexts that have
402
* not been overridden.
403
*
404
* <p><strong>Note:</strong> if there is a default prefix, it will not be
405
* returned in this enumeration; check for the default prefix
406
* using the {@link #getURI getURI} with an argument of "".</p>
407
*
408
* @return An enumeration of prefixes (never empty).
409
* @see #getDeclaredPrefixes
410
* @see #getURI
411
*/
412
public Enumeration getPrefixes ()
413
{
414
return currentContext.getPrefixes();
415
}
416
417
418
/**
419
* Return one of the prefixes mapped to a Namespace URI.
420
*
421
* <p>If more than one prefix is currently mapped to the same
422
* URI, this method will make an arbitrary selection; if you
423
* want all of the prefixes, use the {@link #getPrefixes}
424
* method instead.</p>
425
*
426
* <p><strong>Note:</strong> this will never return the empty (default) prefix;
427
* to check for a default prefix, use the {@link #getURI getURI}
428
* method with an argument of "".</p>
429
*
430
* @param uri the namespace URI
431
* @return one of the prefixes currently mapped to the URI supplied,
432
* or null if none is mapped or if the URI is assigned to
433
* the default namespace
434
* @see #getPrefixes(java.lang.String)
435
* @see #getURI
436
*/
437
public String getPrefix (String uri)
438
{
439
return currentContext.getPrefix(uri);
440
}
441
442
443
/**
444
* Return an enumeration of all prefixes for a given URI whose
445
* declarations are active in the current context.
446
* This includes declarations from parent contexts that have
447
* not been overridden.
448
*
449
* <p>This method returns prefixes mapped to a specific Namespace
450
* URI. The xml: prefix will be included. If you want only one
451
* prefix that's mapped to the Namespace URI, and you don't care
452
* which one you get, use the {@link #getPrefix getPrefix}
453
* method instead.</p>
454
*
455
* <p><strong>Note:</strong> the empty (default) prefix is <em>never</em> included
456
* in this enumeration; to check for the presence of a default
457
* Namespace, use the {@link #getURI getURI} method with an
458
* argument of "".</p>
459
*
460
* @param uri The Namespace URI.
461
* @return An enumeration of prefixes (never empty).
462
* @see #getPrefix
463
* @see #getDeclaredPrefixes
464
* @see #getURI
465
*/
466
public Enumeration getPrefixes (String uri)
467
{
468
List<String> prefixes = new ArrayList<>();
469
Enumeration allPrefixes = getPrefixes();
470
while (allPrefixes.hasMoreElements()) {
471
String prefix = (String)allPrefixes.nextElement();
472
if (uri.equals(getURI(prefix))) {
473
prefixes.add(prefix);
474
}
475
}
476
return Collections.enumeration(prefixes);
477
}
478
479
480
/**
481
* Return an enumeration of all prefixes declared in this context.
482
*
483
* <p>The empty (default) prefix will be included in this
484
* enumeration; note that this behaviour differs from that of
485
* {@link #getPrefix} and {@link #getPrefixes}.</p>
486
*
487
* @return An enumeration of all prefixes declared in this
488
* context.
489
* @see #getPrefixes
490
* @see #getURI
491
*/
492
public Enumeration getDeclaredPrefixes ()
493
{
494
return currentContext.getDeclaredPrefixes();
495
}
496
497
/**
498
* Controls whether namespace declaration attributes are placed
499
* into the {@link #NSDECL NSDECL} namespace
500
* by {@link #processName processName()}. This may only be
501
* changed before any contexts have been pushed.
502
*
503
* @since SAX 2.1alpha
504
*
505
* @exception IllegalStateException when attempting to set this
506
* after any context has been pushed.
507
*/
508
public void setNamespaceDeclUris (boolean value)
509
{
510
if (contextPos != 0)
511
throw new IllegalStateException ();
512
if (value == namespaceDeclUris)
513
return;
514
namespaceDeclUris = value;
515
if (value)
516
currentContext.declarePrefix ("xmlns", NSDECL);
517
else {
518
contexts[contextPos] = currentContext = new Context();
519
currentContext.declarePrefix("xml", XMLNS);
520
}
521
}
522
523
/**
524
* Returns true if namespace declaration attributes are placed into
525
* a namespace. This behavior is not the default.
526
*
527
* @since SAX 2.1alpha
528
*/
529
public boolean isNamespaceDeclUris ()
530
{ return namespaceDeclUris; }
531
532
533
534
////////////////////////////////////////////////////////////////////
535
// Internal state.
536
////////////////////////////////////////////////////////////////////
537
538
private Context contexts[];
539
private Context currentContext;
540
private int contextPos;
541
private boolean namespaceDeclUris;
542
543
544
////////////////////////////////////////////////////////////////////
545
// Internal classes.
546
////////////////////////////////////////////////////////////////////
547
548
/**
549
* Internal class for a single Namespace context.
550
*
551
* <p>This module caches and reuses Namespace contexts,
552
* so the number allocated
553
* will be equal to the element depth of the document, not to the total
554
* number of elements (i.e. 5-10 rather than tens of thousands).
555
* Also, data structures used to represent contexts are shared when
556
* possible (child contexts without declarations) to further reduce
557
* the amount of memory that's consumed.
558
* </p>
559
*/
560
final class Context {
561
562
/**
563
* Create the root-level Namespace context.
564
*/
565
Context ()
566
{
567
copyTables();
568
}
569
570
571
/**
572
* (Re)set the parent of this Namespace context.
573
* The context must either have been freshly constructed,
574
* or must have been cleared.
575
*
576
* @param context The parent Namespace context object.
577
*/
578
void setParent (Context parent)
579
{
580
this.parent = parent;
581
declarations = null;
582
prefixTable = parent.prefixTable;
583
uriTable = parent.uriTable;
584
elementNameTable = parent.elementNameTable;
585
attributeNameTable = parent.attributeNameTable;
586
defaultNS = parent.defaultNS;
587
declSeen = false;
588
}
589
590
/**
591
* Makes associated state become collectible,
592
* invalidating this context.
593
* {@link #setParent} must be called before
594
* this context may be used again.
595
*/
596
void clear ()
597
{
598
parent = null;
599
prefixTable = null;
600
uriTable = null;
601
elementNameTable = null;
602
attributeNameTable = null;
603
defaultNS = null;
604
}
605
606
607
/**
608
* Declare a Namespace prefix for this context.
609
*
610
* @param prefix The prefix to declare.
611
* @param uri The associated Namespace URI.
612
* @see org.xml.sax.helpers.NamespaceSupport#declarePrefix
613
*/
614
void declarePrefix (String prefix, String uri)
615
{
616
// Lazy processing...
617
// if (!declsOK)
618
// throw new IllegalStateException (
619
// "can't declare any more prefixes in this context");
620
if (!declSeen) {
621
copyTables();
622
}
623
if (declarations == null) {
624
declarations = new ArrayList<>();
625
}
626
627
prefix = prefix.intern();
628
uri = uri.intern();
629
if ("".equals(prefix)) {
630
if ("".equals(uri)) {
631
defaultNS = null;
632
} else {
633
defaultNS = uri;
634
}
635
} else {
636
prefixTable.put(prefix, uri);
637
uriTable.put(uri, prefix); // may wipe out another prefix
638
}
639
declarations.add(prefix);
640
}
641
642
643
/**
644
* Process an XML qualified name in this context.
645
*
646
* @param qName The XML qualified name.
647
* @param isAttribute true if this is an attribute name.
648
* @return An array of three strings containing the
649
* URI part (or empty string), the local part,
650
* and the raw name, all internalized, or null
651
* if there is an undeclared prefix.
652
* @see org.xml.sax.helpers.NamespaceSupport#processName
653
*/
654
String [] processName (String qName, boolean isAttribute)
655
{
656
String name[];
657
Map<String, String[]> table;
658
659
// Select the appropriate table.
660
if (isAttribute) {
661
table = attributeNameTable;
662
} else {
663
table = elementNameTable;
664
}
665
666
// Start by looking in the cache, and
667
// return immediately if the name
668
// is already known in this content
669
name = (String[])table.get(qName);
670
if (name != null) {
671
return name;
672
}
673
674
// We haven't seen this name in this
675
// context before. Maybe in the parent
676
// context, but we can't assume prefix
677
// bindings are the same.
678
name = new String[3];
679
name[2] = qName.intern();
680
int index = qName.indexOf(':');
681
682
683
// No prefix.
684
if (index == -1) {
685
if (isAttribute) {
686
if (qName == "xmlns" && namespaceDeclUris)
687
name[0] = NSDECL;
688
else
689
name[0] = "";
690
} else if (defaultNS == null) {
691
name[0] = "";
692
} else {
693
name[0] = defaultNS;
694
}
695
name[1] = name[2];
696
}
697
698
// Prefix
699
else {
700
String prefix = qName.substring(0, index);
701
String local = qName.substring(index+1);
702
String uri;
703
if ("".equals(prefix)) {
704
uri = defaultNS;
705
} else {
706
uri = (String)prefixTable.get(prefix);
707
}
708
if (uri == null
709
|| (!isAttribute && "xmlns".equals (prefix))) {
710
return null;
711
}
712
name[0] = uri;
713
name[1] = local.intern();
714
}
715
716
// Save in the cache for future use.
717
// (Could be shared with parent context...)
718
table.put(name[2], name);
719
return name;
720
}
721
722
723
/**
724
* Look up the URI associated with a prefix in this context.
725
*
726
* @param prefix The prefix to look up.
727
* @return The associated Namespace URI, or null if none is
728
* declared.
729
* @see org.xml.sax.helpers.NamespaceSupport#getURI
730
*/
731
String getURI (String prefix)
732
{
733
if ("".equals(prefix)) {
734
return defaultNS;
735
} else if (prefixTable == null) {
736
return null;
737
} else {
738
return (String)prefixTable.get(prefix);
739
}
740
}
741
742
743
/**
744
* Look up one of the prefixes associated with a URI in this context.
745
*
746
* <p>Since many prefixes may be mapped to the same URI,
747
* the return value may be unreliable.</p>
748
*
749
* @param uri The URI to look up.
750
* @return The associated prefix, or null if none is declared.
751
* @see org.xml.sax.helpers.NamespaceSupport#getPrefix
752
*/
753
String getPrefix (String uri)
754
{
755
if (uriTable == null) {
756
return null;
757
} else {
758
return (String)uriTable.get(uri);
759
}
760
}
761
762
763
/**
764
* Return an enumeration of prefixes declared in this context.
765
*
766
* @return An enumeration of prefixes (possibly empty).
767
* @see org.xml.sax.helpers.NamespaceSupport#getDeclaredPrefixes
768
*/
769
Enumeration getDeclaredPrefixes ()
770
{
771
if (declarations == null) {
772
return EMPTY_ENUMERATION;
773
} else {
774
return Collections.enumeration(declarations);
775
}
776
}
777
778
/**
779
* Return an enumeration of all prefixes currently in force.
780
*
781
* <p>The default prefix, if in force, is <em>not</em>
782
* returned, and will have to be checked for separately.</p>
783
*
784
* @return An enumeration of prefixes (never empty).
785
* @see org.xml.sax.helpers.NamespaceSupport#getPrefixes
786
*/
787
Enumeration getPrefixes ()
788
{
789
if (prefixTable == null) {
790
return EMPTY_ENUMERATION;
791
} else {
792
return Collections.enumeration(prefixTable.keySet());
793
}
794
}
795
796
797
798
////////////////////////////////////////////////////////////////
799
// Internal methods.
800
////////////////////////////////////////////////////////////////
801
802
803
/**
804
* Copy on write for the internal tables in this context.
805
*
806
* <p>This class is optimized for the normal case where most
807
* elements do not contain Namespace declarations.</p>
808
*/
809
private void copyTables ()
810
{
811
if (prefixTable != null) {
812
prefixTable = new HashMap<>(prefixTable);
813
} else {
814
prefixTable = new HashMap<>();
815
}
816
if (uriTable != null) {
817
uriTable = new HashMap<>(uriTable);
818
} else {
819
uriTable = new HashMap<>();
820
}
821
elementNameTable = new HashMap<>();
822
attributeNameTable = new HashMap<>();
823
declSeen = true;
824
}
825
826
827
828
////////////////////////////////////////////////////////////////
829
// Protected state.
830
////////////////////////////////////////////////////////////////
831
832
Map<String, String> prefixTable;
833
Map<String, String> uriTable;
834
Map<String, String[]> elementNameTable;
835
Map<String, String[]> attributeNameTable;
836
String defaultNS = null;
837
838
839
840
////////////////////////////////////////////////////////////////
841
// Internal state.
842
////////////////////////////////////////////////////////////////
843
844
private List<String> declarations = null;
845
private boolean declSeen = false;
846
private Context parent = null;
847
}
848
}
849
850
// end of NamespaceSupport.java
851
852