Source Code Cross Referenced for NamePool.java in  » XML » saxonb » net » sf » saxon » om » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » XML » saxonb » net.sf.saxon.om 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package net.sf.saxon.om;
002:
003:        import net.sf.saxon.style.StandardNames;
004:        import net.sf.saxon.trans.DynamicError;
005:        import net.sf.saxon.type.TypeHierarchy;
006:
007:        import java.io.Serializable;
008:        import java.util.HashMap;
009:        import java.util.StringTokenizer;
010:
011:        /**
012:         * An object representing a collection of XML names, each containing a Namespace URI,
013:         * a Namespace prefix, and a local name; plus a collection of namespaces, each
014:         * consisting of a prefix/URI pair. <br>
015:         * <p/>
016:         * <p>The equivalence betweem names depends only on the URI and the local name.
017:         * The prefix is retained for documentary purposes only: it is useful when
018:         * reconstructing a document to use prefixes that the user is familiar with.</p>
019:         * <p/>
020:         * <p>The NamePool eliminates duplicate names if they have the same prefix, uri,
021:         * and local part. It retains duplicates if they have different prefixes</p>
022:         *
023:         * @author Michael H. Kay
024:         */
025:
026:        public class NamePool implements  Serializable {
027:
028:            // The NamePool holds two kinds of entry: name entries, representing
029:            // expanded names (local name + prefix + URI), identified by a name code,
030:            // and namespace entries (prefix + URI) identified by a namespace code.
031:            //
032:            // The data structure of the name table is as follows.
033:            //
034:            // There is a fixed size hash table; names are allocated to slots in this
035:            // table by hashing on the local name. Each entry in the table is the head of
036:            // a chain of NameEntry objects representing names that have the same hash code.
037:            //
038:            // Each NameEntry represents a distinct name (same URI and local name). It contains
039:            // The local name as a string, plus a short integer representing the URI (as an
040:            // offset into the array uris[]).
041:            //
042:            // The fingerprint of a name consists of the hash slot number (in the bottom 10 bits)
043:            // concatenated with the depth of the entry down the chain of hash synonyms (in the
044:            // next 10 bits). Fingerprints with depth 0 (i.e., in the range 0-1023) are reserved
045:            // for predefined names (names of XSLT elements and attributes, and of built-in types).
046:            // These names are not stored in the name pool, but are accessible as if they were.
047:            //
048:            // A nameCode contains the fingerprint in the bottom 20 bits. It also contains
049:            // an 8-bit prefix index. This distinguishes the prefix used, among all the
050:            // prefixes that have been used with this namespace URI. If the prefix index is
051:            // zero, the prefix is null. Otherwise, it indexes an space-separated list of
052:            // prefix Strings associated with the namespace URI.
053:
054:            /**
055:             * FP_MASK is a mask used to obtain a fingerprint from a nameCode. Given a
056:             * nameCode nc, the fingerprint is <code>nc & NamePool.FP_MASK</code>.
057:             * (In practice, Saxon code often uses the literal constant 0xfffff.)
058:             * The difference between a nameCode is that a nameCode contains information
059:             * about the prefix of a name, the fingerprint depends only on the namespace
060:             * URI and local name. Note that the "null" nameCode (-1) does not produce
061:             * the "null" fingerprint (also -1) when this mask is applied.
062:             */
063:
064:            public static final int FP_MASK = 0xfffff;
065:
066:            // The default singular instance, used unless the user deliberately wants to
067:            // manage name pools himself
068:
069:            private static NamePool defaultNamePool = new NamePool();
070:
071:            /**
072:             * Get the singular default NamePool
073:             */
074:
075:            public static NamePool getDefaultNamePool() {
076:                return defaultNamePool;
077:            }
078:
079:            /**
080:             * Set the default NamePool
081:             * (used after loading a compiled stylesheet)
082:             */
083:
084:            public static void setDefaultNamePool(NamePool pool) {
085:                defaultNamePool = pool;
086:            }
087:
088:            private static class NameEntry implements  Serializable {
089:                String localName;
090:                short uriCode;
091:                NameEntry nextEntry; // next NameEntry with the same hashcode
092:
093:                public NameEntry(short uriCode, String localName) {
094:                    this .uriCode = uriCode;
095:                    this .localName = localName.intern();
096:                    this .nextEntry = null;
097:                }
098:
099:            }
100:
101:            NameEntry[] hashslots = new NameEntry[1024];
102:
103:            String[] prefixes = new String[100];
104:            short prefixesUsed = 0;
105:            String[] uris = new String[100];
106:            String[] prefixesForUri = new String[100];
107:            short urisUsed = 0;
108:
109:            // General purpose cache for data held by clients of the namePool
110:
111:            private HashMap clientData;
112:
113:            private transient TypeHierarchy typeHierarchy;
114:
115:            public NamePool() {
116:
117:                prefixes[NamespaceConstant.NULL_CODE] = "";
118:                uris[NamespaceConstant.NULL_CODE] = NamespaceConstant.NULL;
119:                prefixesForUri[NamespaceConstant.NULL_CODE] = "";
120:
121:                prefixes[NamespaceConstant.XML_CODE] = "xml";
122:                uris[NamespaceConstant.XML_CODE] = NamespaceConstant.XML;
123:                prefixesForUri[NamespaceConstant.XML_CODE] = "xml ";
124:
125:                prefixes[NamespaceConstant.XSLT_CODE] = "xsl";
126:                uris[NamespaceConstant.XSLT_CODE] = NamespaceConstant.XSLT;
127:                prefixesForUri[NamespaceConstant.XSLT_CODE] = "xsl ";
128:
129:                prefixes[NamespaceConstant.SAXON_CODE] = "saxon";
130:                uris[NamespaceConstant.SAXON_CODE] = NamespaceConstant.SAXON;
131:                prefixesForUri[NamespaceConstant.SAXON_CODE] = "saxon ";
132:
133:                prefixes[NamespaceConstant.SCHEMA_CODE] = "xs";
134:                uris[NamespaceConstant.SCHEMA_CODE] = NamespaceConstant.SCHEMA;
135:                prefixesForUri[NamespaceConstant.SCHEMA_CODE] = "xs ";
136:
137:                prefixes[NamespaceConstant.XDT_CODE] = "xdt";
138:                uris[NamespaceConstant.XDT_CODE] = NamespaceConstant.XDT;
139:                prefixesForUri[NamespaceConstant.XDT_CODE] = "xdt ";
140:
141:                prefixes[NamespaceConstant.XSI_CODE] = "xsi";
142:                uris[NamespaceConstant.XSI_CODE] = NamespaceConstant.SCHEMA_INSTANCE;
143:                prefixesForUri[NamespaceConstant.XSI_CODE] = "xsi ";
144:
145:                prefixesUsed = 7;
146:                urisUsed = 7;
147:
148:            }
149:
150:            /**
151:             * Get the TypeHierarchy
152:             */
153:
154:            public final TypeHierarchy getTypeHierarchy() {
155:                if (typeHierarchy == null) {
156:                    typeHierarchy = new TypeHierarchy();
157:                }
158:                return typeHierarchy;
159:            }
160:
161:            /**
162:             * Get a name entry corresponding to a given name code
163:             *
164:             * @return null if there is none.
165:             */
166:
167:            private NameEntry getNameEntry(int nameCode) {
168:                int hash = nameCode & 0x3ff;
169:                int depth = (nameCode >> 10) & 0x3ff;
170:                NameEntry entry = hashslots[hash];
171:
172:                for (int i = 1; i < depth; i++) {
173:                    if (entry == null) {
174:                        return null;
175:                    }
176:                    entry = entry.nextEntry;
177:                }
178:                return entry;
179:            }
180:
181:            /**
182:             * Allocate the namespace code for a namespace prefix/URI pair.
183:             * Create it if not already present
184:             *
185:             * @param prefix the namespace prefix
186:             * @param uri    the namespace URI
187:             * @return an integer code identifying the namespace. The namespace code
188:             *         identifies both the prefix and the URI.
189:             */
190:
191:            public/**/synchronized/**/int allocateNamespaceCode(
192:                    String prefix, String uri) {
193:                // System.err.println("allocate nscode for " + prefix + " = " + uri);
194:
195:                int prefixCode = allocateCodeForPrefix(prefix);
196:                int uriCode = allocateCodeForURI(uri);
197:
198:                if (prefixCode != 0) {
199:                    // ensure the prefix is in the list of prefixes used with this URI
200:                    String key = prefix + ' ';
201:                    if (prefixesForUri[uriCode].indexOf(key) < 0) {
202:                        prefixesForUri[uriCode] += key;
203:                    }
204:                }
205:
206:                return (prefixCode << 16) + uriCode;
207:            }
208:
209:            /**
210:             * Get the existing namespace code for a namespace prefix/URI pair.
211:             *
212:             * @return -1 if there is none present
213:             */
214:
215:            public int getNamespaceCode(String prefix, String uri) {
216:                //System.err.println("get nscode for " + prefix + " = " + uri);
217:                int prefixCode = getCodeForPrefix(prefix);
218:                if (prefixCode < 0) {
219:                    return -1;
220:                }
221:                int uriCode = getCodeForURI(uri);
222:                if (uriCode < 0) {
223:                    return -1;
224:                }
225:
226:                if (prefixCode != 0) {
227:                    // ensure the prefix is in the list of prefixes used with this URI
228:                    String key = prefix + ' ';
229:                    if (prefixesForUri[uriCode].indexOf(key) < 0) {
230:                        return -1;
231:                    }
232:                }
233:
234:                return (prefixCode << 16) + uriCode;
235:            }
236:
237:            /**
238:             * Allocate a namespace code for a given namecode
239:             *
240:             * @param namecode a code identifying an expanded QName, e.g. of an element or attribute
241:             * @return a code identifying the namespace used in the given name. The namespace code
242:             *         identifies both the prefix and the URI. Return -1 if no namespace code has been allocated
243:             *         (in this case the caller should call allocateNamespaceCode() to get one).
244:             */
245:
246:            public int getNamespaceCode(int namecode) {
247:                short uriCode;
248:                int fp = namecode & 0xfffff;
249:                if ((fp & 0xffc00) == 0) {
250:                    uriCode = StandardNames.getURICode(fp);
251:                } else {
252:                    NameEntry entry = getNameEntry(namecode);
253:                    if (entry == null) {
254:                        return -1;
255:                    } else {
256:                        uriCode = entry.uriCode;
257:                    }
258:                }
259:                int prefixIndex = (namecode >> 20) & 0xff;
260:                String prefix = getPrefixWithIndex(uriCode, prefixIndex);
261:                if (prefix == null) {
262:                    return -1;
263:                }
264:                int prefixCode = getCodeForPrefix(prefix);
265:                if (prefixCode == -1) {
266:                    return -1;
267:                }
268:                return (prefixCode << 16) + uriCode;
269:            }
270:
271:            /**
272:             * Allocate the uri code for a given URI;
273:             * create one if not found
274:             */
275:
276:            public/**/synchronized/**/short allocateCodeForURI(String uri) {
277:                //System.err.println("allocate code for URI " + uri);
278:                for (short j = 0; j < urisUsed; j++) {
279:                    if (uris[j].equals(uri)) {
280:                        return j;
281:                    }
282:                }
283:                if (urisUsed >= uris.length) {
284:                    if (urisUsed > 32000) {
285:                        throw new NamePoolLimitException(
286:                                "Too many namespace URIs");
287:                    }
288:                    String[] p = new String[urisUsed * 2];
289:                    String[] u = new String[urisUsed * 2];
290:                    System.arraycopy(prefixesForUri, 0, p, 0, urisUsed);
291:                    System.arraycopy(uris, 0, u, 0, urisUsed);
292:                    prefixesForUri = p;
293:                    uris = u;
294:                }
295:                uris[urisUsed] = uri;
296:                prefixesForUri[urisUsed] = "";
297:                return urisUsed++;
298:            }
299:
300:            /**
301:             * Get the uri code for a given URI
302:             *
303:             * @return -1 if not present in the name pool
304:             */
305:
306:            public short getCodeForURI(String uri) {
307:                for (short j = 0; j < urisUsed; j++) {
308:                    if (uris[j].equals(uri)) {
309:                        return j;
310:                    }
311:                }
312:                return -1;
313:            }
314:
315:            /**
316:             * Allocate the prefix code for a given Prefix; create one if not found
317:             *
318:             * @param prefix the namespace prefix whose code is to be allocated or returned
319:             * @return the numeric code for this prefix
320:             */
321:
322:            private short allocateCodeForPrefix(String prefix) {
323:                // Not synchronized, because it's always called from a synchronized method
324:
325:                // exploit knowledge of the standard prefixes to shorten the search
326:                short start = 1;
327:                if (prefix.equals("")) {
328:                    return NamespaceConstant.NULL_CODE;
329:                }
330:                if (prefix.charAt(0) != 'x') {
331:                    if (prefix.equals("saxon")) {
332:                        return NamespaceConstant.SAXON_CODE;
333:                    }
334:                    start = NamespaceConstant.XSI_CODE + 1;
335:                }
336:
337:                for (short i = start; i < prefixesUsed; i++) {
338:                    if (prefixes[i].equals(prefix)) {
339:                        return i;
340:                    }
341:                }
342:                if (prefixesUsed >= prefixes.length) {
343:                    if (prefixesUsed > 32000) {
344:                        throw new NamePoolLimitException(
345:                                "Too many namespace prefixes");
346:                    }
347:                    String[] p = new String[prefixesUsed * 2];
348:                    System.arraycopy(prefixes, 0, p, 0, prefixesUsed);
349:                    prefixes = p;
350:                }
351:                prefixes[prefixesUsed] = prefix;
352:                return prefixesUsed++;
353:            }
354:
355:            /**
356:             * Get the prefix code for a given Prefix
357:             *
358:             * @return -1 if not found
359:             */
360:
361:            public short getCodeForPrefix(String prefix) {
362:                for (short i = 0; i < prefixesUsed; i++) {
363:                    if (prefixes[i].equals(prefix)) {
364:                        return i;
365:                    }
366:                }
367:                return -1;
368:            }
369:
370:            /**
371:             * Suggest a prefix for a given URI. If there are several, it's undefined which one is returned.
372:             * If there are no prefixes registered for this URI, return null.
373:             */
374:
375:            public String suggestPrefixForURI(String URI) {
376:                short uriCode = getCodeForURI(URI);
377:                if (uriCode == -1) {
378:                    return null;
379:                }
380:                StringTokenizer tok = new StringTokenizer(
381:                        prefixesForUri[uriCode]);
382:                if (tok.hasMoreElements()) {
383:                    return (String) tok.nextElement();
384:                }
385:                return null;
386:            }
387:
388:            /**
389:             * Get the index of a prefix among all the prefixes used with a given URI
390:             *
391:             * @return -1 if not found
392:             */
393:
394:            private int getPrefixIndex(short uriCode, String prefix) {
395:
396:                // look for quick wins
397:                if (prefix.equals("")) {
398:                    return 0;
399:                }
400:                if (prefixesForUri[uriCode].equals(prefix + ' ')) {
401:                    return 1;
402:                }
403:
404:                // search for the prefix in the list
405:                int i = 1;
406:                StringTokenizer tok = new StringTokenizer(
407:                        prefixesForUri[uriCode]);
408:                while (tok.hasMoreElements()) {
409:                    if (prefix.equals(tok.nextElement())) {
410:                        return i;
411:                    }
412:                    if (i++ == 255) {
413:                        throw new NamePoolLimitException(
414:                                "Too many prefixes for one namespace URI");
415:                    }
416:                }
417:                return -1;
418:            }
419:
420:            /**
421:             * Get a prefix among all the prefixes used with a given URI, given its index
422:             *
423:             * @return null if not found
424:             */
425:
426:            public String getPrefixWithIndex(short uriCode, int index) {
427:                if (index == 0) {
428:                    return "";
429:                }
430:                StringTokenizer tok = new StringTokenizer(
431:                        prefixesForUri[uriCode]);
432:                int i = 1;
433:                while (tok.hasMoreElements()) {
434:                    String prefix = (String) tok.nextElement();
435:                    if (i++ == index) {
436:                        return prefix;
437:                    }
438:                }
439:                return null;
440:            }
441:
442:            /**
443:             * Allocate a name from the pool, or a new Name if there is not a matching one there
444:             *
445:             * @param prefix
446:             * @param uri       - the namespace URI. The null URI is represented as an empty string.
447:             * @param localName
448:             * @return an integer (the "namecode") identifying the name within the namepool.
449:             *         The Name itself may be retrieved using the getName(int) method
450:             */
451:
452:            public synchronized int allocate(String prefix, String uri,
453:                    String localName) {
454:                if (NamespaceConstant.isReserved(uri)
455:                        || uri.equals(NamespaceConstant.SAXON)) {
456:                    int fp = StandardNames.getFingerprint(uri, localName);
457:                    if (fp != -1) {
458:                        short uriCode = StandardNames.getURICode(fp);
459:                        int prefixIndex = getPrefixIndex(uriCode, prefix);
460:
461:                        if (prefixIndex < 0) {
462:                            prefixesForUri[uriCode] += (prefix + ' ');
463:                            prefixIndex = getPrefixIndex(uriCode, prefix);
464:                        }
465:
466:                        return (prefixIndex << 20) + fp;
467:                    }
468:                }
469:                // otherwise register the name in this NamePool
470:                short uriCode = allocateCodeForURI(uri);
471:                return allocateInternal(prefix, uriCode, localName);
472:            }
473:
474:            /**
475:             * Allocate a name from the pool, or a new Name if there is not a matching one there
476:             *
477:             * @param prefix    - the namespace prefix
478:             * @param uriCode   - the code of the URI
479:             * @param localName - the local part of the QName
480:             * @return an integer (the "namecode") identifying the name within the namepool.
481:             */
482:
483:            public synchronized int allocate(String prefix, short uriCode,
484:                    String localName) {
485:                // System.err.println("Allocate " + prefix + " : " + uriCode + " : " + localName);
486:                if (NamespaceConstant.isSpecialURICode(uriCode)) {
487:                    return allocate(prefix, getURIFromURICode(uriCode),
488:                            localName);
489:                } else {
490:                    return allocateInternal(prefix, uriCode, localName);
491:                }
492:            }
493:
494:            private int allocateInternal(String prefix, short uriCode,
495:                    String localName) {
496:                int hash = (localName.hashCode() & 0x7fffffff) % 1023;
497:                int depth = 1;
498:                int prefixIndex = getPrefixIndex(uriCode, prefix);
499:
500:                if (prefixIndex < 0) {
501:                    prefixesForUri[uriCode] += (prefix + ' ');
502:                    prefixIndex = getPrefixIndex(uriCode, prefix);
503:                }
504:                NameEntry entry;
505:
506:                if (hashslots[hash] == null) {
507:                    entry = new NameEntry(uriCode, localName);
508:                    hashslots[hash] = entry;
509:                } else {
510:                    entry = hashslots[hash];
511:                    while (true) {
512:                        boolean sameLocalName = (entry.localName
513:                                .equals(localName));
514:                        boolean sameURI = (entry.uriCode == uriCode);
515:
516:                        if (sameLocalName && sameURI) {
517:                            // may need to add a new prefix to the entry
518:                            break;
519:                        } else {
520:                            NameEntry next = entry.nextEntry;
521:                            depth++;
522:                            if (depth >= 1024) {
523:                                throw new NamePoolLimitException(
524:                                        "Saxon name pool is full");
525:                            }
526:                            if (next == null) {
527:                                NameEntry newentry = new NameEntry(uriCode,
528:                                        localName);
529:                                entry.nextEntry = newentry;
530:                                break;
531:                            } else {
532:                                entry = next;
533:                            }
534:                        }
535:                    }
536:                }
537:                // System.err.println("name code = " + prefixIndex + "/" + depth + "/" + hash);
538:                return ((prefixIndex << 20) + (depth << 10) + hash);
539:            }
540:
541:            /**
542:             * Allocate a namespace code for the prefix/URI of a given namecode
543:             *
544:             * @param namecode a code identifying an expanded QName, e.g. of an element or attribute
545:             * @return a code identifying the namespace used in the given name. The namespace code
546:             *         identifies both the prefix and the URI.
547:             */
548:
549:            public/**/synchronized/**/int allocateNamespaceCode(int namecode) {
550:                short uriCode;
551:                int fp = namecode & 0xfffff;
552:                if ((fp & 0xffc00) == 0) {
553:                    uriCode = StandardNames.getURICode(fp);
554:                } else {
555:                    NameEntry entry = getNameEntry(namecode);
556:                    if (entry == null) {
557:                        unknownNameCode(namecode);
558:                        return -1; // to keep the compiler happy
559:                    } else {
560:                        uriCode = entry.uriCode;
561:                    }
562:                }
563:                int prefixIndex = (namecode >> 20) & 0xff;
564:                String prefix = getPrefixWithIndex(uriCode, prefixIndex);
565:                int prefixCode = allocateCodeForPrefix(prefix);
566:                return (prefixCode << 16) + uriCode;
567:            }
568:
569:            /**
570:             * Get the namespace-URI of a name, given its name code or fingerprint
571:             */
572:
573:            public String getURI(int nameCode) {
574:                if ((nameCode & 0xffc00) == 0) {
575:                    return StandardNames.getURI(nameCode & 0xfffff);
576:                }
577:                NameEntry entry = getNameEntry(nameCode);
578:                if (entry == null) {
579:                    unknownNameCode(nameCode);
580:                    return null; // to keep the compiler happy
581:                }
582:                return uris[entry.uriCode];
583:            }
584:
585:            /**
586:             * Get the URI code of a name, given its name code or fingerprint
587:             */
588:
589:            public short getURICode(int nameCode) {
590:                if ((nameCode & 0xffc00) == 0) {
591:                    return StandardNames.getURICode(nameCode & 0xfffff);
592:                }
593:                NameEntry entry = getNameEntry(nameCode);
594:                if (entry == null) {
595:                    unknownNameCode(nameCode);
596:                    return -1;
597:                }
598:                return entry.uriCode;
599:            }
600:
601:            /**
602:             * Get the local part of a name, given its name code or fingerprint
603:             */
604:
605:            public String getLocalName(int nameCode) {
606:                if ((nameCode & 0xffc00) == 0) {
607:                    return StandardNames.getLocalName(nameCode & 0xfffff);
608:                }
609:                NameEntry entry = getNameEntry(nameCode);
610:                if (entry == null) {
611:                    unknownNameCode(nameCode);
612:                    return null;
613:                }
614:                return entry.localName;
615:            }
616:
617:            /**
618:             * Get the prefix part of a name, given its name code or fingerprint
619:             */
620:
621:            public String getPrefix(int nameCode) {
622:                if ((nameCode & 0xffc00) == 0) {
623:                    return StandardNames.getPrefix(nameCode & 0xfffff);
624:                }
625:                short uriCode = getURICode(nameCode);
626:                int prefixIndex = (nameCode >> 20) & 0xff;
627:                return getPrefixWithIndex(uriCode, prefixIndex);
628:            }
629:
630:            /**
631:             * Get the display form of a name (the QName), given its name code or fingerprint
632:             */
633:
634:            public String getDisplayName(int nameCode) {
635:                if ((nameCode & 0xffc00) == 0) {
636:                    // This indicates a standard name known to the system (but it might have a non-standard prefix)
637:                    int prefixIndex = (nameCode >> 20) & 0xff;
638:                    short uriCode = getURICode(nameCode);
639:                    String prefix = getPrefixWithIndex(uriCode, prefixIndex);
640:                    if (prefix.equals("")) {
641:                        return StandardNames.getLocalName(nameCode & 0xfffff);
642:                    } else {
643:                        return prefix
644:                                + ':'
645:                                + StandardNames
646:                                        .getLocalName(nameCode & 0xfffff);
647:                    }
648:                }
649:
650:                NameEntry entry = getNameEntry(nameCode);
651:                if (entry == null) {
652:                    unknownNameCode(nameCode);
653:                    return null;
654:                }
655:                int prefixIndex = (nameCode >> 20) & 0xff;
656:                String prefix = getPrefixWithIndex(entry.uriCode, prefixIndex);
657:                if (prefix == null || prefix.equals("")) {
658:                    return entry.localName;
659:                } else {
660:                    return prefix + ':' + entry.localName;
661:                }
662:            }
663:
664:            /**
665:             * Get the Clark form of a name, given its name code or fingerprint
666:             *
667:             * @return the local name if the name is in the null namespace, or "{uri}local"
668:             *         otherwise. The name is always interned.
669:             */
670:
671:            public String getClarkName(int nameCode) {
672:                if ((nameCode & 0xffc00) == 0) {
673:                    return StandardNames.getClarkName(nameCode & 0xfffff);
674:                }
675:                NameEntry entry = getNameEntry(nameCode);
676:                if (entry == null) {
677:                    unknownNameCode(nameCode);
678:                    return null;
679:                }
680:                if (entry.uriCode == 0) {
681:                    return entry.localName;
682:                } else {
683:                    String n = '{' + getURIFromURICode(entry.uriCode) + '}'
684:                            + entry.localName;
685:                    return n.intern();
686:                }
687:            }
688:
689:            /**
690:             * Allocate a fingerprint given a Clark Name
691:             */
692:
693:            public int allocateClarkName(String expandedName) {
694:                String namespace;
695:                String localName;
696:                if (expandedName.charAt(0) == '{') {
697:                    int closeBrace = expandedName.indexOf('}');
698:                    if (closeBrace < 0) {
699:                        throw new IllegalArgumentException(
700:                                "No closing '}' in Clark name");
701:                    }
702:                    namespace = expandedName.substring(1, closeBrace);
703:                    if (closeBrace == expandedName.length()) {
704:                        throw new IllegalArgumentException(
705:                                "Missing local part in Clark name");
706:                    }
707:                    localName = expandedName.substring(closeBrace + 1);
708:                } else {
709:                    namespace = "";
710:                    localName = expandedName;
711:                }
712:
713:                return allocate("", namespace, localName);
714:            }
715:
716:            /**
717:             * Parse a Clark-format expanded name, returning the URI and local name
718:             */
719:
720:            public static String[] parseClarkName(String expandedName) {
721:                String namespace;
722:                String localName;
723:                if (expandedName.charAt(0) == '{') {
724:                    int closeBrace = expandedName.indexOf('}');
725:                    if (closeBrace < 0) {
726:                        throw new IllegalArgumentException(
727:                                "No closing '}' in Clark name");
728:                    }
729:                    namespace = expandedName.substring(1, closeBrace);
730:                    if (closeBrace == expandedName.length()) {
731:                        throw new IllegalArgumentException(
732:                                "Missing local part in Clark name");
733:                    }
734:                    localName = expandedName.substring(closeBrace + 1);
735:                } else {
736:                    namespace = "";
737:                    localName = expandedName;
738:                }
739:                String[] result = { namespace, localName };
740:                return result;
741:            }
742:
743:            /**
744:             * Internal error: name not found in namepool
745:             * (Usual cause is allocating a name code from one name pool and trying to
746:             * find it in another)
747:             */
748:
749:            private void unknownNameCode(int nameCode) {
750:                //System.err.println("Unknown name code " + nameCode);
751:                //diagnosticDump();
752:                //(new IllegalArgumentException("Unknown name")).printStackTrace();
753:                throw new IllegalArgumentException("Unknown name code "
754:                        + nameCode);
755:            }
756:
757:            /**
758:             * Get a fingerprint for the name with a given uri and local name.
759:             * These must be present in the NamePool.
760:             * The fingerprint has the property that if two fingerprint are the same, the names
761:             * are the same (ie. same local name and same URI).
762:             *
763:             * @return -1 if not found
764:             */
765:
766:            public int getFingerprint(String uri, String localName) {
767:                // A read-only version of allocate()
768:
769:                short uriCode;
770:                if (uri.equals("")) {
771:                    uriCode = 0;
772:                } else {
773:                    if (NamespaceConstant.isReserved(uri)
774:                            || uri.equals(NamespaceConstant.SAXON)) {
775:                        int fp = StandardNames.getFingerprint(uri, localName);
776:                        if (fp != -1) {
777:                            return fp;
778:                            // otherwise, look for the name in this namepool
779:                        }
780:                    }
781:                    uriCode = -1;
782:                    for (short j = 0; j < urisUsed; j++) {
783:                        if (uris[j].equals(uri)) {
784:                            uriCode = j;
785:                            break;
786:                        }
787:                    }
788:                    if (uriCode == -1) {
789:                        return -1;
790:                    }
791:                }
792:
793:                int hash = (localName.hashCode() & 0x7fffffff) % 1023;
794:                int depth = 1;
795:
796:                NameEntry entry;
797:
798:                if (hashslots[hash] == null) {
799:                    return -1;
800:                }
801:
802:                entry = hashslots[hash];
803:                while (true) {
804:                    if (entry.uriCode == uriCode
805:                            && entry.localName.equals(localName)) {
806:                        break;
807:                    } else {
808:                        NameEntry next = entry.nextEntry;
809:                        depth++;
810:                        if (next == null) {
811:                            return -1;
812:                        } else {
813:                            entry = next;
814:                        }
815:                    }
816:                }
817:                return (depth << 10) + hash;
818:            }
819:
820:            /**
821:             * Get the namespace URI from a namespace code.
822:             */
823:
824:            public String getURIFromNamespaceCode(int code) {
825:                return uris[code & 0xffff];
826:            }
827:
828:            /**
829:             * Get the namespace URI from a URI code.
830:             */
831:
832:            public String getURIFromURICode(short code) {
833:                return uris[code];
834:            }
835:
836:            /**
837:             * Get the namespace prefix from a namespace code.
838:             */
839:
840:            public String getPrefixFromNamespaceCode(int code) {
841:                // System.err.println("get prefix for " + code);
842:                return prefixes[code >> 16];
843:            }
844:
845:            /**
846:             * Get the nameCode for a lexical QName, given a namespace resolver.
847:             * @param qname the lexical QName.
848:             * @param useDefault if true, an absent prefix is resolved by the NamespaceResolver
849:             * to the namespace URI assigned to the prefix "". If false, an absent prefix is
850:             * interpreted as meaning the name is in no namespace.
851:             * @param checker NameChecker used to check names against the XML 1.0 or 1.1 specification
852:             * @return the corresponding nameCode
853:             * @throws net.sf.saxon.trans.DynamicError if the string is not a valid lexical QName or
854:             * if the namespace prefix has not been declared*
855:             */
856:
857:            public int allocateLexicalQName(CharSequence qname,
858:                    boolean useDefault, NamespaceResolver resolver,
859:                    NameChecker checker) throws DynamicError {
860:                try {
861:                    String[] parts = checker.getQNameParts(qname);
862:                    String uri = resolver.getURIForPrefix(parts[0], useDefault);
863:                    if (uri == null) {
864:                        throw new DynamicError("Namespace prefix '" + parts[0]
865:                                + "' has not been declared");
866:                    }
867:                    return allocate(parts[0], uri, parts[1]);
868:                } catch (QNameException e) {
869:                    throw new DynamicError(e.getMessage());
870:                }
871:            }
872:
873:            /**
874:             * Get fingerprint for expanded name in {uri}local format
875:             */
876:
877:            public int getFingerprintForExpandedName(String expandedName) {
878:
879:                String localName;
880:                String namespace;
881:
882:                if (expandedName.charAt(0) == '{') {
883:                    int closeBrace = expandedName.indexOf('}');
884:                    if (closeBrace < 0) {
885:                        throw new IllegalArgumentException(
886:                                "No closing '}' in parameter name");
887:                    }
888:                    namespace = expandedName.substring(1, closeBrace);
889:                    if (closeBrace == expandedName.length()) {
890:                        throw new IllegalArgumentException(
891:                                "Missing local part in parameter name");
892:                    }
893:                    localName = expandedName.substring(closeBrace + 1);
894:                } else {
895:                    namespace = "";
896:                    localName = expandedName;
897:                }
898:
899:                return allocate("", namespace, localName);
900:            }
901:
902:            /**
903:             * Save client data on behalf of a user of the namepool
904:             */
905:
906:            public void setClientData(Class key, Object value) {
907:                if (clientData == null) {
908:                    clientData = new HashMap(10);
909:                }
910:                clientData.put(key, value);
911:            }
912:
913:            /**
914:             * Retrieve client data on behalf of a user of the namepool
915:             */
916:
917:            public Object getClientData(Class key) {
918:                if (clientData == null) {
919:                    return null;
920:                }
921:                return clientData.get(key);
922:            }
923:
924:            /**
925:             * Diagnostic print of the namepool contents.
926:             */
927:
928:            public synchronized void diagnosticDump() {
929:                System.err.println("Contents of NamePool " + this );
930:                for (int i = 0; i < 1024; i++) {
931:                    NameEntry entry = hashslots[i];
932:                    int depth = 0;
933:                    while (entry != null) {
934:                        System.err.println("Fingerprint " + depth + '/' + i);
935:                        System.err.println("  local name = " + entry.localName
936:                                + " uri code = " + entry.uriCode);
937:                        entry = entry.nextEntry;
938:                        depth++;
939:                    }
940:                }
941:
942:                for (int p = 0; p < prefixesUsed; p++) {
943:                    System.err.println("Prefix " + p + " = " + prefixes[p]);
944:                }
945:                for (int u = 0; u < urisUsed; u++) {
946:                    System.err.println("URI " + u + " = " + uris[u]);
947:                    System.err.println("Prefixes for URI " + u + " = "
948:                            + prefixesForUri[u]);
949:                }
950:            }
951:
952:            /**
953:             * Statistics summarizing the namepool contents.
954:             * This method outputs summary statistical information to System.err
955:             */
956:
957:            public synchronized void statistics() {
958:                int slots = 0;
959:                int entries = 0;
960:                for (int i = 0; i < 1024; i++) {
961:                    NameEntry entry = hashslots[i];
962:                    if (entry != null)
963:                        slots++;
964:                    while (entry != null) {
965:                        entry = entry.nextEntry;
966:                        entries++;
967:                    }
968:                }
969:                System.err.println("NamePool contents: " + entries
970:                        + " entries in " + slots + " chains. " + +prefixesUsed
971:                        + " prefixes, " + urisUsed + " URIs");
972:            }
973:
974:            public static class NamePoolLimitException extends RuntimeException {
975:
976:                public NamePoolLimitException(String message) {
977:                    super (message);
978:                }
979:            }
980:
981:        }
982:
983:        //
984:        // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
985:        // you may not use this file except in compliance with the License. You may obtain a copy of the
986:        // License at http://www.mozilla.org/MPL/
987:        //
988:        // Software distributed under the License is distributed on an "AS IS" basis,
989:        // WITHOUT WARRANTY OF ANY KIND, either express or implied.
990:        // See the License for the specific language governing rights and limitations under the License.
991:        //
992:        // The Original Code is: all this file.
993:        //
994:        // The Initial Developer of the Original Code is Michael H. Kay.
995:        //
996:        // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
997:        //
998:        // Contributor(s): none.
999:        //
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.