KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > om > NamePool


1 package net.sf.saxon.om;
2
3 import net.sf.saxon.style.StandardNames;
4 import net.sf.saxon.trans.DynamicError;
5
6 import java.io.Serializable JavaDoc;
7 import java.util.HashMap JavaDoc;
8 import java.util.StringTokenizer JavaDoc;
9
10 /**
11  * An object representing a collection of XML names, each containing a Namespace URI,
12  * a Namespace prefix, and a local name; plus a collection of namespaces, each
13  * consisting of a prefix/URI pair. <br>
14  * <p/>
15  * <p>The equivalence betweem names depends only on the URI and the local name.
16  * The prefix is retained for documentary purposes only: it is useful when
17  * reconstructing a document to use prefixes that the user is familiar with.</p>
18  * <p/>
19  * <p>The NamePool eliminates duplicate names if they have the same prefix, uri,
20  * and local part. It retains duplicates if they have different prefixes</p>
21  *
22  * @author Michael H. Kay
23  */

24
25 public class NamePool implements Serializable JavaDoc {
26
27     // The NamePool holds two kinds of entry: name entries, representing
28
// expanded names (local name + prefix + URI), identified by a name code,
29
// and namespace entries (prefix + URI) identified by a namespace code.
30
//
31
// The data structure of the name table is as follows.
32
//
33
// There is a fixed size hash table; names are allocated to slots in this
34
// table by hashing on the local name. Each entry in the table is the head of
35
// a chain of NameEntry objects representing names that have the same hash code.
36
//
37
// Each NameEntry represents a distinct name (same URI and local name). It contains
38
// The local name as a string, plus a short integer representing the URI (as an
39
// offset into the array uris[]).
40
//
41
// The fingerprint of a name consists of the hash slot number (in the bottom 10 bits)
42
// concatenated with the depth of the entry down the chain of hash synonyms (in the
43
// next 10 bits). Fingerprints with depth 0 (i.e., in the range 0-1023) are reserved
44
// for predefined names (names of XSLT elements and attributes, and of built-in types).
45
// These names are not stored in the name pool, but are accessible as if they were.
46
//
47
// A nameCode contains the fingerprint in the bottom 20 bits. It also contains
48
// an 8-bit prefix index. This distinguishes the prefix used, among all the
49
// prefixes that have been used with this namespace URI. If the prefix index is
50
// zero, the prefix is null. Otherwise, it indexes an space-separated list of
51
// prefix Strings associated with the namespace URI.
52

53     /**
54      * FP_MASK is a mask used to obtain a fingerprint from a nameCode. Given a
55      * nameCode nc, the fingerprint is <code>nc & NamePool.FP_MASK</code>.
56      * (In practice, Saxon code often uses the literal constant 0xfffff.)
57      * The difference between a nameCode is that a nameCode contains information
58      * about the prefix of a name, the fingerprint depends only on the namespace
59      * URI and local name. Note that the "null" nameCode (-1) does not produce
60      * the "null" fingerprint (also -1) when this mask is applied.
61      */

62
63     public static final int FP_MASK = 0xfffff;
64
65
66     // The default singular instance, used unless the user deliberately wants to
67
// manage name pools himself
68

69     private static NamePool defaultNamePool = new NamePool();
70
71     /**
72      * Get the singular default NamePool
73      */

74
75     public static NamePool getDefaultNamePool() {
76         return defaultNamePool;
77     }
78
79     /**
80      * Set the default NamePool
81      * (used after loading a compiled stylesheet)
82      */

83
84     public static void setDefaultNamePool(NamePool pool) {
85         defaultNamePool = pool;
86     }
87
88
89     private static class NameEntry implements Serializable JavaDoc {
90         String JavaDoc localName;
91         short uriCode;
92         NameEntry nextEntry; // next NameEntry with the same hashcode
93

94         public NameEntry(short uriCode, String JavaDoc localName) {
95             this.uriCode = uriCode;
96             this.localName = localName.intern();
97             this.nextEntry = null;
98         }
99
100     }
101
102     NameEntry[] hashslots = new NameEntry[1024];
103
104     String JavaDoc[] prefixes = new String JavaDoc[100];
105     short prefixesUsed = 0;
106     String JavaDoc[] uris = new String JavaDoc[100];
107     String JavaDoc[] prefixesForUri = new String JavaDoc[100];
108     short urisUsed = 0;
109
110     // General purpose cache for data held by clients of the namePool
111

112     private HashMap JavaDoc clientData;
113
114     public NamePool() {
115
116         prefixes[NamespaceConstant.NULL_CODE] = "";
117         uris[NamespaceConstant.NULL_CODE] = NamespaceConstant.NULL;
118         prefixesForUri[NamespaceConstant.NULL_CODE] = "";
119
120         prefixes[NamespaceConstant.XML_CODE] = "xml";
121         uris[NamespaceConstant.XML_CODE] = NamespaceConstant.XML;
122         prefixesForUri[NamespaceConstant.XML_CODE] = "xml ";
123
124         prefixes[NamespaceConstant.XSLT_CODE] = "xsl";
125         uris[NamespaceConstant.XSLT_CODE] = NamespaceConstant.XSLT;
126         prefixesForUri[NamespaceConstant.XSLT_CODE] = "xsl ";
127
128         prefixes[NamespaceConstant.SAXON_CODE] = "saxon";
129         uris[NamespaceConstant.SAXON_CODE] = NamespaceConstant.SAXON;
130         prefixesForUri[NamespaceConstant.SAXON_CODE] = "saxon ";
131
132         prefixes[NamespaceConstant.SCHEMA_CODE] = "xs";
133         uris[NamespaceConstant.SCHEMA_CODE] = NamespaceConstant.SCHEMA;
134         prefixesForUri[NamespaceConstant.SCHEMA_CODE] = "xs ";
135
136         prefixes[NamespaceConstant.XDT_CODE] = "xdt";
137         uris[NamespaceConstant.XDT_CODE] = NamespaceConstant.XDT;
138         prefixesForUri[NamespaceConstant.XDT_CODE] = "xdt ";
139
140         prefixes[NamespaceConstant.XSI_CODE] = "xsi";
141         uris[NamespaceConstant.XSI_CODE] = NamespaceConstant.SCHEMA_INSTANCE;
142         prefixesForUri[NamespaceConstant.XSI_CODE] = "xsi ";
143
144         prefixesUsed = 7;
145         urisUsed = 7;
146
147     }
148
149     /**
150      * Get a name entry corresponding to a given name code
151      *
152      * @return null if there is none.
153      */

154
155     private NameEntry getNameEntry(int nameCode) {
156         int hash = nameCode & 0x3ff;
157         int depth = (nameCode >> 10) & 0x3ff;
158         NameEntry entry = hashslots[hash];
159
160         for (int i = 1; i < depth; i++) {
161             if (entry == null) {
162                 return null;
163             }
164             entry = entry.nextEntry;
165         }
166         return entry;
167     }
168
169     /**
170      * Allocate the namespace code for a namespace prefix/URI pair.
171      * Create it if not already present
172      *
173      * @param prefix the namespace prefix
174      * @param uri the namespace URI
175      * @return an integer code identifying the namespace. The namespace code
176      * identifies both the prefix and the URI.
177      */

178
179     public /**/synchronized/**/ int allocateNamespaceCode(String JavaDoc prefix, String JavaDoc uri) {
180         // System.err.println("allocate nscode for " + prefix + " = " + uri);
181

182         int prefixCode = allocateCodeForPrefix(prefix);
183         int uriCode = allocateCodeForURI(uri);
184
185         if (prefixCode != 0) {
186             // ensure the prefix is in the list of prefixes used with this URI
187
String JavaDoc key = prefix + ' ';
188             if (prefixesForUri[uriCode].indexOf(key) < 0) {
189                 prefixesForUri[uriCode] += key;
190             }
191         }
192
193         return (prefixCode << 16) + uriCode;
194     }
195
196     /**
197      * Get the existing namespace code for a namespace prefix/URI pair.
198      *
199      * @return -1 if there is none present
200      */

201
202     public int getNamespaceCode(String JavaDoc prefix, String JavaDoc uri) {
203         //System.err.println("get nscode for " + prefix + " = " + uri);
204
int prefixCode = getCodeForPrefix(prefix);
205         if (prefixCode < 0) {
206             return -1;
207         }
208         int uriCode = getCodeForURI(uri);
209         if (uriCode < 0) {
210             return -1;
211         }
212
213         if (prefixCode != 0) {
214             // ensure the prefix is in the list of prefixes used with this URI
215
String JavaDoc key = prefix + ' ';
216             if (prefixesForUri[uriCode].indexOf(key) < 0) {
217                 return -1;
218             }
219         }
220
221         return (prefixCode << 16) + uriCode;
222     }
223
224     /**
225      * Allocate a namespace code for a given namecode
226      *
227      * @param namecode a code identifying an expanded QName, e.g. of an element or attribute
228      * @return a code identifying the namespace used in the given name. The namespace code
229      * identifies both the prefix and the URI. Return -1 if no namespace code has been allocated
230      * (in this case the caller should call allocateNamespaceCode() to get one).
231      */

232
233     public int getNamespaceCode(int namecode) {
234         short uriCode;
235         int fp = namecode & 0xfffff;
236         if ((fp & 0xffc00) == 0) {
237             uriCode = StandardNames.getURICode(fp);
238         } else {
239             NameEntry entry = getNameEntry(namecode);
240             if (entry == null) {
241                 return -1;
242             } else {
243                 uriCode = entry.uriCode;
244             }
245         }
246         int prefixIndex = (namecode >> 20) & 0xff;
247         String JavaDoc prefix = getPrefixWithIndex(uriCode, prefixIndex);
248         if (prefix == null) {
249             return -1;
250         }
251         int prefixCode = getCodeForPrefix(prefix);
252         if (prefixCode == -1) {
253             return -1;
254         }
255         return (prefixCode << 16) + uriCode;
256     }
257
258
259     /**
260      * Allocate the uri code for a given URI;
261      * create one if not found
262      */

263
264     public /**/synchronized/**/ short allocateCodeForURI(String JavaDoc uri) {
265 //System.err.println("allocate code for URI " + uri);
266
for (short j = 0; j < urisUsed; j++) {
267             if (uris[j].equals(uri)) {
268                 return j;
269             }
270         }
271         if (urisUsed >= uris.length) {
272             if (urisUsed > 32000) {
273                 throw new NamePoolLimitException("Too many namespace URIs");
274             }
275             String JavaDoc[] p = new String JavaDoc[urisUsed * 2];
276             String JavaDoc[] u = new String JavaDoc[urisUsed * 2];
277             System.arraycopy(prefixesForUri, 0, p, 0, urisUsed);
278             System.arraycopy(uris, 0, u, 0, urisUsed);
279             prefixesForUri = p;
280             uris = u;
281         }
282         uris[urisUsed] = uri;
283         prefixesForUri[urisUsed] = "";
284         return urisUsed++;
285     }
286
287
288     /**
289      * Get the uri code for a given URI
290      *
291      * @return -1 if not present in the name pool
292      */

293
294     public short getCodeForURI(String JavaDoc uri) {
295         for (short j = 0; j < urisUsed; j++) {
296             if (uris[j].equals(uri)) {
297                 return j;
298             }
299         }
300         return -1;
301     }
302
303     /**
304      * Allocate the prefix code for a given Prefix; create one if not found
305      *
306      * @param prefix the namespace prefix whose code is to be allocated or returned
307      * @return the numeric code for this prefix
308      */

309
310     private short allocateCodeForPrefix(String JavaDoc prefix) {
311         // Not synchronized, because it's always called from a synchronized method
312

313         // exploit knowledge of the standard prefixes to shorten the search
314
short start = 1;
315         if (prefix.equals("")) {
316             return NamespaceConstant.NULL_CODE;
317         }
318         if (prefix.charAt(0) != 'x') {
319             if (prefix.equals("saxon")) {
320                 return NamespaceConstant.SAXON_CODE;
321             }
322             start = NamespaceConstant.XSI_CODE + 1;
323         }
324
325         for (short i=start; i < prefixesUsed; i++) {
326             if (prefixes[i].equals(prefix)) {
327                 return i;
328             }
329         }
330         if (prefixesUsed >= prefixes.length) {
331             if (prefixesUsed > 32000) {
332                 throw new NamePoolLimitException("Too many namespace prefixes");
333             }
334             String JavaDoc[] p = new String JavaDoc[prefixesUsed * 2];
335             System.arraycopy(prefixes, 0, p, 0, prefixesUsed);
336             prefixes = p;
337         }
338         prefixes[prefixesUsed] = prefix;
339         return prefixesUsed++;
340     }
341
342
343     /**
344      * Get the prefix code for a given Prefix
345      *
346      * @return -1 if not found
347      */

348
349     public short getCodeForPrefix(String JavaDoc prefix) {
350         for (short i = 0; i < prefixesUsed; i++) {
351             if (prefixes[i].equals(prefix)) {
352                 return i;
353             }
354         }
355         return -1;
356     }
357
358     /**
359      * Suggest a prefix for a given URI. If there are several, it's undefined which one is returned.
360      * If there are no prefixes registered for this URI, return null.
361      */

362
363     public String JavaDoc suggestPrefixForURI(String JavaDoc URI) {
364         short uriCode = getCodeForURI(URI);
365         if (uriCode == -1) {
366             return null;
367         }
368         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(prefixesForUri[uriCode]);
369         if (tok.hasMoreElements()) {
370             return (String JavaDoc)tok.nextElement();
371         }
372         return null;
373     }
374
375     /**
376      * Get the index of a prefix among all the prefixes used with a given URI
377      *
378      * @return -1 if not found
379      */

380
381     private int getPrefixIndex(short uriCode, String JavaDoc prefix) {
382
383         // look for quick wins
384
if (prefix.equals("")) {
385             return 0;
386         }
387         if (prefixesForUri[uriCode].equals(prefix + ' ')) {
388             return 1;
389         }
390
391         // search for the prefix in the list
392
int i = 1;
393         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(prefixesForUri[uriCode]);
394         while (tok.hasMoreElements()) {
395             if (prefix.equals(tok.nextElement())) {
396                 return i;
397             }
398             if (i++ == 255) {
399                 throw new NamePoolLimitException("Too many prefixes for one namespace URI");
400             }
401         }
402         return -1;
403     }
404
405     /**
406      * Get a prefix among all the prefixes used with a given URI, given its index
407      *
408      * @return null if not found
409      */

410
411     public String JavaDoc getPrefixWithIndex(short uriCode, int index) {
412         if (index == 0) {
413             return "";
414         }
415         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(prefixesForUri[uriCode]);
416         int i = 1;
417         while (tok.hasMoreElements()) {
418             String JavaDoc prefix = (String JavaDoc)tok.nextElement();
419             if (i++ == index) {
420                 return prefix;
421             }
422         }
423         return null;
424     }
425
426     /**
427      * Allocate a name from the pool, or a new Name if there is not a matching one there
428      *
429      * @param prefix
430      * @param uri - the namespace URI. The null URI is represented as an empty string.
431      * @param localName
432      * @return an integer (the "namecode") identifying the name within the namepool.
433      * The Name itself may be retrieved using the getName(int) method
434      */

435
436     public /**/synchronized/**/ int allocate(String JavaDoc prefix, String JavaDoc uri, String JavaDoc localName) {
437         if (NamespaceConstant.isReserved(uri) || uri.equals(NamespaceConstant.SAXON)) {
438             int fp = StandardNames.getFingerprint(uri, localName);
439             if (fp != -1) {
440                 short uriCode = StandardNames.getURICode(fp);
441                 int prefixIndex = getPrefixIndex(uriCode, prefix);
442
443                 if (prefixIndex < 0) {
444                     prefixesForUri[uriCode] += (prefix + ' ');
445                     prefixIndex = getPrefixIndex(uriCode, prefix);
446                 }
447
448                 return (prefixIndex << 20) + fp;
449             }
450         }
451         // otherwise register the name in this NamePool
452
short uriCode = allocateCodeForURI(uri);
453         return allocate(prefix, uriCode, localName);
454     }
455
456     /**
457      * Allocate a name from the pool, or a new Name if there is not a matching one there
458      *
459      * @param prefix - the namespace prefix
460      * @param uriCode - the code of the URI
461      * @param localName - the local part of the QName
462      * @return an integer (the "namecode") identifying the name within the namepool.
463      */

464
465     public /**/synchronized/**/ int allocate(String JavaDoc prefix, short uriCode, String JavaDoc localName) {
466         // System.err.println("Allocate " + prefix + " : " + uriCode + " : " + localName);
467
int hash = (localName.hashCode() & 0x7fffffff) % 1023;
468         int depth = 1;
469         int prefixIndex = getPrefixIndex(uriCode, prefix);
470
471         if (prefixIndex < 0) {
472             prefixesForUri[uriCode] += (prefix + ' ');
473             prefixIndex = getPrefixIndex(uriCode, prefix);
474         }
475         NameEntry entry;
476
477         if (hashslots[hash] == null) {
478             entry = new NameEntry(uriCode, localName);
479             hashslots[hash] = entry;
480         } else {
481             entry = hashslots[hash];
482             while (true) {
483                 boolean sameLocalName = (entry.localName.equals(localName));
484                 boolean sameURI = (entry.uriCode == uriCode);
485
486                 if (sameLocalName && sameURI) {
487                     // may need to add a new prefix to the entry
488
break;
489                 } else {
490                     NameEntry next = entry.nextEntry;
491                     depth++;
492                     if (depth >= 1024) {
493                         throw new NamePoolLimitException("Saxon name pool is full");
494                     }
495                     if (next == null) {
496                         NameEntry newentry = new NameEntry(uriCode, localName);
497                         entry.nextEntry = newentry;
498                         break;
499                     } else {
500                         entry = next;
501                     }
502                 }
503             }
504         }
505         // System.err.println("name code = " + prefixIndex + "/" + depth + "/" + hash);
506
return ((prefixIndex << 20) + (depth << 10) + hash);
507     }
508
509     /**
510      * Allocate a namespace code for the prefix/URI of a given namecode
511      *
512      * @param namecode a code identifying an expanded QName, e.g. of an element or attribute
513      * @return a code identifying the namespace used in the given name. The namespace code
514      * identifies both the prefix and the URI.
515      */

516
517     public /**/synchronized/**/ int allocateNamespaceCode(int namecode) {
518         short uriCode;
519         int fp = namecode & 0xfffff;
520         if ((fp & 0xffc00) == 0) {
521             uriCode = StandardNames.getURICode(fp);
522         } else {
523             NameEntry entry = getNameEntry(namecode);
524             if (entry == null) {
525                 unknownNameCode(namecode);
526                 return -1; // to keep the compiler happy
527
} else {
528                 uriCode = entry.uriCode;
529             }
530         }
531         int prefixIndex = (namecode >> 20) & 0xff;
532         String JavaDoc prefix = getPrefixWithIndex(uriCode, prefixIndex);
533         int prefixCode = allocateCodeForPrefix(prefix);
534         return (prefixCode << 16) + uriCode;
535     }
536
537     /**
538      * Get the namespace-URI of a name, given its name code or fingerprint
539      */

540
541     public String JavaDoc getURI(int nameCode) {
542         if ((nameCode & 0xffc00) == 0) {
543             return StandardNames.getURI(nameCode & 0xfffff);
544         }
545         NameEntry entry = getNameEntry(nameCode);
546         if (entry == null) {
547             unknownNameCode(nameCode);
548             return null; // to keep the compiler happy
549
}
550         return uris[entry.uriCode];
551     }
552
553     /**
554      * Get the URI code of a name, given its name code or fingerprint
555      */

556
557     public short getURICode(int nameCode) {
558         if ((nameCode & 0xffc00) == 0) {
559             return StandardNames.getURICode(nameCode & 0xfffff);
560         }
561         NameEntry entry = getNameEntry(nameCode);
562         if (entry == null) {
563             unknownNameCode(nameCode);
564             return -1;
565         }
566         return entry.uriCode;
567     }
568
569     /**
570      * Get the local part of a name, given its name code or fingerprint
571      */

572
573     public String JavaDoc getLocalName(int nameCode) {
574         if ((nameCode & 0xffc00) == 0) {
575             return StandardNames.getLocalName(nameCode & 0xfffff);
576         }
577         NameEntry entry = getNameEntry(nameCode);
578         if (entry == null) {
579             unknownNameCode(nameCode);
580             return null;
581         }
582         return entry.localName;
583     }
584
585     /**
586      * Get the prefix part of a name, given its name code or fingerprint
587      */

588
589     public String JavaDoc getPrefix(int nameCode) {
590         if ((nameCode & 0xffc00) == 0) {
591             return StandardNames.getPrefix(nameCode & 0xfffff);
592         }
593         short uriCode = getURICode(nameCode);
594         int prefixIndex = (nameCode >> 20) & 0xff;
595         return getPrefixWithIndex(uriCode, prefixIndex);
596     }
597
598     /**
599      * Get the display form of a name (the QName), given its name code or fingerprint
600      */

601
602     public String JavaDoc getDisplayName(int nameCode) {
603         if ((nameCode & 0xffc00) == 0) {
604 // This indicates a standard name known to the system (but it might have a non-standard prefix)
605
int prefixIndex = (nameCode >> 20) & 0xff;
606             short uriCode = getURICode(nameCode);
607             String JavaDoc prefix = getPrefixWithIndex(uriCode, prefixIndex);
608             if (prefix.equals("")) {
609                 return StandardNames.getLocalName(nameCode & 0xfffff);
610             } else {
611                 return prefix + ':' + StandardNames.getLocalName(nameCode & 0xfffff);
612             }
613         }
614
615         NameEntry entry = getNameEntry(nameCode);
616         if (entry == null) {
617             unknownNameCode(nameCode);
618             return null;
619         }
620         int prefixIndex = (nameCode >> 20) & 0xff;
621         String JavaDoc prefix = getPrefixWithIndex(entry.uriCode, prefixIndex);
622         if (prefix == null || prefix.equals("")) {
623             return entry.localName;
624         } else {
625             return prefix + ':' + entry.localName;
626         }
627     }
628
629     /**
630      * Get the Clark form of a name, given its name code or fingerprint
631      *
632      * @return the local name if the name is in the null namespace, or "{uri}local"
633      * otherwise. The name is always interned.
634      */

635
636     public String JavaDoc getClarkName(int nameCode) {
637         if ((nameCode & 0xffc00) == 0) {
638             return StandardNames.getClarkName(nameCode & 0xfffff);
639         }
640         NameEntry entry = getNameEntry(nameCode);
641         if (entry == null) {
642             unknownNameCode(nameCode);
643             return null;
644         }
645         if (entry.uriCode == 0) {
646             return entry.localName;
647         } else {
648             String JavaDoc n =
649                     '{' + getURIFromURICode(entry.uriCode) + '}' + entry.localName;
650             return n.intern();
651         }
652     }
653
654     /**
655      * Allocate a fingerprint given a Clark Name
656      */

657
658     public int allocateClarkName(String JavaDoc expandedName) {
659         String JavaDoc namespace;
660         String JavaDoc localName;
661         if (expandedName.charAt(0) == '{') {
662             int closeBrace = expandedName.indexOf('}');
663             if (closeBrace < 0) {
664                 throw new IllegalArgumentException JavaDoc("No closing '}' in Clark name");
665             }
666             namespace = expandedName.substring(1, closeBrace);
667             if (closeBrace == expandedName.length()) {
668                 throw new IllegalArgumentException JavaDoc("Missing local part in Clark name");
669             }
670             localName = expandedName.substring(closeBrace + 1);
671         } else {
672             namespace = "";
673             localName = expandedName;
674         }
675
676         return allocate("", namespace, localName);
677     }
678
679
680     /**
681      * Internal error: name not found in namepool
682      * (Usual cause is allocating a name code from one name pool and trying to
683      * find it in another)
684      */

685
686     private void unknownNameCode(int nameCode) {
687         //System.err.println("Unknown name code " + nameCode);
688
//diagnosticDump();
689
//(new IllegalArgumentException("Unknown name")).printStackTrace();
690
throw new IllegalArgumentException JavaDoc("Unknown name code " + nameCode);
691     }
692
693     /**
694      * Get a fingerprint for the name with a given uri and local name.
695      * These must be present in the NamePool.
696      * The fingerprint has the property that if two fingerprint are the same, the names
697      * are the same (ie. same local name and same URI).
698      *
699      * @return -1 if not found
700      */

701
702     public int getFingerprint(String JavaDoc uri, String JavaDoc localName) {
703         // A read-only version of allocate()
704

705         short uriCode;
706         if (uri.equals("")) {
707             uriCode = 0;
708         } else {
709             if (NamespaceConstant.isReserved(uri) || uri.equals(NamespaceConstant.SAXON)) {
710                 int fp = StandardNames.getFingerprint(uri, localName);
711                 if (fp != -1) {
712                     return fp;
713 // otherwise, look for the name in this namepool
714
}
715             }
716             uriCode = -1;
717             for (short j = 0; j < urisUsed; j++) {
718                 if (uris[j].equals(uri)) {
719                     uriCode = j;
720                     break;
721                 }
722             }
723             if (uriCode == -1) {
724                 return -1;
725             }
726         }
727
728         int hash = (localName.hashCode() & 0x7fffffff) % 1023;
729         int depth = 1;
730
731         NameEntry entry;
732
733         if (hashslots[hash] == null) {
734             return -1;
735         }
736
737         entry = hashslots[hash];
738         while (true) {
739             if (entry.uriCode == uriCode && entry.localName.equals(localName)) {
740                 break;
741             } else {
742                 NameEntry next = entry.nextEntry;
743                 depth++;
744                 if (next == null) {
745                     return -1;
746                 } else {
747                     entry = next;
748                 }
749             }
750         }
751         return (depth << 10) + hash;
752     }
753
754     /**
755      * Get the namespace URI from a namespace code.
756      */

757
758     public String JavaDoc getURIFromNamespaceCode(int code) {
759         return uris[code & 0xffff];
760     }
761
762     /**
763      * Get the namespace URI from a URI code.
764      */

765
766     public String JavaDoc getURIFromURICode(short code) {
767         return uris[code];
768     }
769
770     /**
771      * Get the namespace prefix from a namespace code.
772      */

773
774     public String JavaDoc getPrefixFromNamespaceCode(int code) {
775         // System.err.println("get prefix for " + code);
776
return prefixes[code >> 16];
777     }
778
779     /**
780      * Get the nameCode for a lexical QName, given a namespace resolver.
781      * @param qname the lexical QName.
782      * @param useDefault if true, an absent prefix is resolved by the NamespaceResolver
783      * to the namespace URI assigned to the prefix "". If false, an absent prefix is
784      * interpreted as meaning the name is in no namespace.
785      * @return the corresponding nameCode
786      * @throws net.sf.saxon.trans.DynamicError if the string is not a valid lexical QName or
787      * if the namespace prefix has not been declared*
788      */

789
790     public int allocateLexicalQName(CharSequence JavaDoc qname, boolean useDefault, NamespaceResolver resolver)
791     throws DynamicError {
792         try {
793             String JavaDoc[] parts = Name.getQNameParts(qname);
794             String JavaDoc uri = resolver.getURIForPrefix(parts[0], useDefault);
795             return allocate(parts[0], uri, parts[1]);
796         } catch (QNameException e) {
797             throw new DynamicError(e.getMessage());
798         }
799     }
800     /**
801      * Get fingerprint for expanded name in {uri}local format
802      */

803
804     public int getFingerprintForExpandedName(String JavaDoc expandedName) {
805
806         String JavaDoc localName;
807         String JavaDoc namespace;
808
809         if (expandedName.charAt(0) == '{') {
810             int closeBrace = expandedName.indexOf('}');
811             if (closeBrace < 0) {
812                 throw new IllegalArgumentException JavaDoc("No closing '}' in parameter name");
813             }
814             namespace = expandedName.substring(1, closeBrace);
815             if (closeBrace == expandedName.length()) {
816                 throw new IllegalArgumentException JavaDoc("Missing local part in parameter name");
817             }
818             localName = expandedName.substring(closeBrace + 1);
819         } else {
820             namespace = "";
821             localName = expandedName;
822         }
823
824         return allocate("", namespace, localName);
825     }
826
827     /**
828      * Save client data on behalf of a user of the namepool
829      */

830
831     public void setClientData(Class JavaDoc key, Object JavaDoc value) {
832         if (clientData == null) {
833             clientData = new HashMap JavaDoc(10);
834         }
835         clientData.put(key, value);
836     }
837
838     /**
839      * Retrieve client data on behalf of a user of the namepool
840      */

841
842     public Object JavaDoc getClientData(Class JavaDoc key) {
843         if (clientData == null) {
844             return null;
845         }
846         return clientData.get(key);
847     }
848
849     /**
850      * Diagnostic print of the namepool contents.
851      */

852
853     public synchronized void diagnosticDump() {
854         System.err.println("Contents of NamePool " + this);
855         for (int i = 0; i < 1024; i++) {
856             NameEntry entry = hashslots[i];
857             int depth = 0;
858             while (entry != null) {
859                 System.err.println("Fingerprint " + depth + '/' + i);
860                 System.err.println(" local name = " + entry.localName +
861                         " uri code = " + entry.uriCode);
862                 entry = entry.nextEntry;
863                 depth++;
864             }
865         }
866
867         for (int p = 0; p < prefixesUsed; p++) {
868             System.err.println("Prefix " + p + " = " + prefixes[p]);
869         }
870         for (int u = 0; u < urisUsed; u++) {
871             System.err.println("URI " + u + " = " + uris[u]);
872             System.err.println("Prefixes for URI " + u + " = " + prefixesForUri[u]);
873         }
874     }
875
876     /**
877      * Statistics summarizing the namepool contents.
878      * This method outputs summary statistical information to System.err
879      */

880
881     public synchronized void statistics() {
882         int slots = 0;
883         int entries = 0;
884         for (int i = 0; i < 1024; i++) {
885             NameEntry entry = hashslots[i];
886             if (entry != null) slots++;
887             while (entry != null) {
888                 entry = entry.nextEntry;
889                 entries++;
890             }
891         }
892         System.err.println("NamePool contents: " + entries + " entries in " + slots + " chains. " +
893                  + prefixesUsed + " prefixes, " + urisUsed + " URIs");
894     }
895
896
897     public static class NamePoolLimitException extends RuntimeException JavaDoc {
898
899         public NamePoolLimitException(String JavaDoc message) {
900             super(message);
901         }
902     }
903
904 }
905
906 //
907
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
908
// you may not use this file except in compliance with the License. You may obtain a copy of the
909
// License at http://www.mozilla.org/MPL/
910
//
911
// Software distributed under the License is distributed on an "AS IS" basis,
912
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
913
// See the License for the specific language governing rights and limitations under the License.
914
//
915
// The Original Code is: all this file.
916
//
917
// The Initial Developer of the Original Code is Michael H. Kay.
918
//
919
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
920
//
921
// Contributor(s): none.
922
//
923
Popular Tags