KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > xml > fastinfoset > Encoder


1 /*
2  * Fast Infoset ver. 0.1 software ("Software")
3  *
4  * Copyright, 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
5  *
6  * Software is licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License. You may
8  * obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15  * License for the specific language governing permissions and limitations.
16  *
17  * Sun supports and benefits from the global community of open source
18  * developers, and thanks the community for its important contributions and
19  * open standards-based technology, which Sun has adopted into many of its
20  * products.
21  *
22  * Please note that portions of Software may be provided with notices and
23  * open source licenses from such communities and third parties that govern the
24  * use of those portions, and any licenses granted hereunder do not alter any
25  * rights and obligations you may have under such open source licenses,
26  * however, the disclaimer of warranty and limitation of liability provisions
27  * in this License will apply to all Software in this distribution.
28  *
29  * You acknowledge that the Software is not designed, licensed or intended
30  * for use in the design, construction, operation or maintenance of any nuclear
31  * facility.
32  *
33  * Apache License
34  * Version 2.0, January 2004
35  * http://www.apache.org/licenses/
36  *
37  */

38
39
40 package com.sun.xml.fastinfoset;
41
42 import com.sun.xml.fastinfoset.algorithm.BuiltInEncodingAlgorithm;
43 import com.sun.xml.fastinfoset.algorithm.BuiltInEncodingAlgorithmFactory;
44 import com.sun.xml.fastinfoset.org.apache.xerces.util.XMLChar;
45 import com.sun.xml.fastinfoset.util.CharArrayIntMap;
46 import com.sun.xml.fastinfoset.util.KeyIntMap;
47 import com.sun.xml.fastinfoset.util.LocalNameQualifiedNamesMap;
48 import com.sun.xml.fastinfoset.util.StringIntMap;
49 import com.sun.xml.fastinfoset.vocab.SerializerVocabulary;
50 import java.io.IOException JavaDoc;
51 import java.io.OutputStream JavaDoc;
52 import java.util.HashMap JavaDoc;
53 import java.util.Map JavaDoc;
54 import org.jvnet.fastinfoset.EncodingAlgorithm;
55 import org.jvnet.fastinfoset.EncodingAlgorithmException;
56 import org.jvnet.fastinfoset.EncodingAlgorithmIndexes;
57 import org.jvnet.fastinfoset.FastInfosetException;
58 import org.jvnet.fastinfoset.FastInfosetSerializer;
59 import org.jvnet.fastinfoset.ReferencedVocabulary;
60 import org.jvnet.fastinfoset.Vocabulary;
61 import org.xml.sax.helpers.DefaultHandler JavaDoc;
62
63 public abstract class Encoder extends DefaultHandler JavaDoc implements FastInfosetSerializer {
64     
65     // Character encoding scheme system property
66
public static final String JavaDoc CHARACTER_ENCODING_SCHEME_SYSTEM_PROPERTY =
67         "com.sun.xml.fastinfoset.serializer.character-encoding-scheme";
68
69     protected static String JavaDoc _characterEncodingSchemeSystemDefault = UTF_8;
70         
71     static {
72         String JavaDoc p = System.getProperty(CHARACTER_ENCODING_SCHEME_SYSTEM_PROPERTY,
73             _characterEncodingSchemeSystemDefault);
74         if (p.equals(UTF_16BE)) {
75             _characterEncodingSchemeSystemDefault = UTF_16BE;
76         }
77     }
78
79     protected boolean _encodingStringsAsUtf8 = true;
80     
81     protected int _nonIdentifyingStringOnThirdBitCES;
82
83     protected int _nonIdentifyingStringOnFirstBitCES;
84     
85     protected Map _registeredEncodingAlgorithms = new HashMap JavaDoc();
86
87     protected SerializerVocabulary _v;
88
89     protected boolean _vIsInternal;
90
91     protected boolean _terminate = false;
92
93     protected int _b;
94
95     protected OutputStream JavaDoc _s;
96
97     protected char[] _charBuffer = new char[512];
98
99     protected byte[] _octetBuffer = new byte[1024];
100     
101     protected int _octetBufferIndex;
102    
103     protected int _markIndex = -1;
104
105     protected int attributeValueSizeConstraint = FastInfosetSerializer.ATTRIBUTE_VALUE_SIZE_CONSTRAINT;
106     
107     protected int characterContentChunkSizeContraint = FastInfosetSerializer.CHARACTER_CONTENT_CHUNK_SIZE_CONSTRAINT;
108
109     // FastInfosetSerializer
110

111     public Encoder() {
112         setCharacterEncodingScheme(_characterEncodingSchemeSystemDefault);
113     }
114     
115     public void reset() {
116         _terminate = false;
117     }
118     
119     public void setCharacterEncodingScheme(String JavaDoc characterEncodingScheme) {
120         if (characterEncodingScheme.equals(UTF_16BE)) {
121             _encodingStringsAsUtf8 = false;
122             _nonIdentifyingStringOnThirdBitCES = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_UTF_16_FLAG;
123             _nonIdentifyingStringOnFirstBitCES = EncodingConstants.NISTRING_UTF_16_FLAG;
124         } else {
125             _encodingStringsAsUtf8 = true;
126             _nonIdentifyingStringOnThirdBitCES = EncodingConstants.CHARACTER_CHUNK;
127             _nonIdentifyingStringOnFirstBitCES = 0;
128         }
129     }
130         
131     public String JavaDoc getCharacterEncodingScheme() {
132         return (_encodingStringsAsUtf8) ? UTF_8 : UTF_16BE;
133     }
134     
135     public void setRegisteredEncodingAlgorithms(Map algorithms) {
136         _registeredEncodingAlgorithms = algorithms;
137         if (_registeredEncodingAlgorithms == null) {
138             _registeredEncodingAlgorithms = new HashMap JavaDoc();
139         }
140     }
141
142     public Map getRegisteredEncodingAlgorithms() {
143         return _registeredEncodingAlgorithms;
144     }
145
146     public void setExternalVocabulary(ReferencedVocabulary referencedVocabulary) {
147         throw new UnsupportedOperationException JavaDoc();
148     }
149
150     public void setIntitialVocabulary(Vocabulary initialVocabulary) {
151         throw new UnsupportedOperationException JavaDoc();
152     }
153
154     public void setDynamicVocabulary(Vocabulary dynamicVocabulary) {
155         throw new UnsupportedOperationException JavaDoc();
156     }
157
158     public Vocabulary getDynamicVocabulary() {
159         throw new UnsupportedOperationException JavaDoc();
160     }
161
162     public Vocabulary getFinalVocabulary() {
163         throw new UnsupportedOperationException JavaDoc();
164     }
165
166     
167     
168     public void setOutputStream(OutputStream JavaDoc s) {
169         _octetBufferIndex = 0;
170         _markIndex = -1;
171         _s = s;
172     }
173
174     public void setVocabulary(SerializerVocabulary vocabulary) {
175         _v = vocabulary;
176         _vIsInternal = false;
177     }
178
179     public void setCharacterContentChunkSizeLimit(int size) {
180         if (size < 0 ) {
181             size = 0;
182         }
183                 
184         characterContentChunkSizeContraint = size;
185     }
186     
187     public int getCharacterContentChunkSizeLimit() {
188         return characterContentChunkSizeContraint;
189     }
190
191     public void setAttributeValueSizeLimit(int size) {
192         if (size < 0 ) {
193             size = 0;
194         }
195         
196         attributeValueSizeConstraint = size;
197     }
198     
199     public int getAttributeValueSizeLimit() {
200         return attributeValueSizeConstraint;
201     }
202     
203     protected final void encodeHeader(boolean encodeXmlDecl) throws IOException JavaDoc {
204         if (encodeXmlDecl) {
205             _s.write(EncodingConstants.XML_DECLARATION_VALUES[0]);
206         }
207         _s.write(EncodingConstants.BINARY_HEADER);
208     }
209
210     protected final void encodeInitialVocabulary() throws IOException JavaDoc {
211         if (_v == null) {
212             _v = new SerializerVocabulary();
213             _vIsInternal = true;
214         } else if (_vIsInternal) {
215             _v.clear();
216         }
217
218         if (_v.hasInitialVocabulary()) {
219             _b = EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG;
220             write(_b);
221
222             SerializerVocabulary initialVocabulary = _v.getReadOnlyVocabulary();
223
224             // TODO check for contents of vocabulary to assign bits
225
if (initialVocabulary.hasExternalVocabulary()) {
226                 _b = EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG;
227                 write(_b);
228                 write(0);
229             }
230
231             if (initialVocabulary.hasExternalVocabulary()) {
232                 encodeNonEmptyOctetStringOnSecondBit(_v.getExternalVocabularyURI().toString());
233             }
234
235             // TODO check for contents of vocabulary to encode values
236
} else if (_v.hasExternalVocabulary()) {
237             _b = EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG;
238             write(_b);
239
240             _b = EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG;
241             write(_b);
242             write(0);
243
244             encodeNonEmptyOctetStringOnSecondBit(_v.getExternalVocabularyURI().toString());
245         } else {
246             write(0);
247         }
248     }
249
250     protected final void encodeDocumentTermination() throws IOException JavaDoc {
251         encodeElementTermination();
252         encodeTermination();
253         _flush();
254         _s.flush();
255     }
256
257     protected final void encodeElementTermination() throws IOException JavaDoc {
258         _terminate = true;
259         switch (_b) {
260             case EncodingConstants.TERMINATOR:
261                 _b = EncodingConstants.DOUBLE_TERMINATOR;
262                 break;
263             case EncodingConstants.DOUBLE_TERMINATOR:
264                 write(EncodingConstants.DOUBLE_TERMINATOR);
265             default:
266                 _b = EncodingConstants.TERMINATOR;
267         }
268     }
269
270     protected final void encodeTermination() throws IOException JavaDoc {
271         if (_terminate) {
272             write(_b);
273             _terminate = false;
274         }
275     }
276
277     protected final void encodeNamespaceAttribute(String JavaDoc prefix, String JavaDoc uri) throws IOException JavaDoc {
278         _b = EncodingConstants.NAMESPACE_ATTRIBUTE;
279         if (prefix != "") {
280             _b |= EncodingConstants.NAMESPACE_ATTRIBUTE_PREFIX_FLAG;
281         }
282         if (uri != "") {
283             _b |= EncodingConstants.NAMESPACE_ATTRIBUTE_NAME_FLAG;
284         }
285
286         // NOTE a prefix with out a namespace name is an undeclaration
287
// of the namespace bound to the prefix
288
// TODO needs to investigate how the startPrefixMapping works in
289
// relation to undeclaration
290

291         write(_b);
292
293         if (prefix != "") {
294             encodeIdentifyingNonEmptyStringOnFirstBit(prefix, _v.prefix);
295         }
296         if (uri != "") {
297             encodeIdentifyingNonEmptyStringOnFirstBit(uri, _v.namespaceName);
298         }
299     }
300
301     protected final void encodeCharacters(char[] ch, int start, int length) throws IOException JavaDoc {
302         final boolean addToTable = (length < characterContentChunkSizeContraint) ? true : false;
303         encodeNonIdentifyingStringOnThirdBit(ch, start, length, _v.characterContentChunk, addToTable, true);
304     }
305
306     protected final void encodeCharactersNoClone(char[] ch, int start, int length) throws IOException JavaDoc {
307         final boolean addToTable = (length < characterContentChunkSizeContraint) ? true : false;
308         encodeNonIdentifyingStringOnThirdBit(ch, start, length, _v.characterContentChunk, addToTable, false);
309     }
310     
311     protected final void encodeFourBitCharacters(int id, int[] table, char[] ch, int start, int length) throws FastInfosetException, IOException JavaDoc {
312         // This procedure assumes that id <= 64
313
_b = (length < characterContentChunkSizeContraint) ?
314             EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG | EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG :
315             EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG;
316         write (_b);
317
318         // Encode bottom 6 bits of enoding algorithm id
319
_b = id << 2;
320
321         encodeNonEmptyFourBitCharacterStringOnSeventhBit(table, ch, start, length);
322     }
323     
324     protected final void encodeAlphabetCharacters(String JavaDoc alphabet, char[] ch, int start, int length) throws FastInfosetException, IOException JavaDoc {
325         int id = _v.restrictedAlphabet.get(alphabet);
326         if (id == KeyIntMap.NOT_PRESENT) {
327             throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.restrictedAlphabetNotPresent"));
328         }
329         id += EncodingConstants.RESTRICTED_ALPHABET_APPLICATION_START;
330         
331         _b = (length < characterContentChunkSizeContraint) ?
332             EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG | EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG :
333             EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG;
334         _b |= (id & 0xC0) >> 6;
335         write (_b);
336
337         // Encode bottom 6 bits of enoding algorithm id
338
_b = (id & 0x3F) << 2;
339
340         encodeNonEmptyNBitCharacterStringOnSeventhBit(alphabet, ch, start, length);
341     }
342             
343     protected final void encodeProcessingInstruction(String JavaDoc target, String JavaDoc data) throws IOException JavaDoc {
344         write(EncodingConstants.PROCESSING_INSTRUCTION);
345
346         // Target
347
encodeIdentifyingNonEmptyStringOnFirstBit(target, _v.otherNCName);
348
349         // Data
350
boolean addToTable = (data.length() < characterContentChunkSizeContraint) ? true : false;
351         encodeNonIdentifyingStringOnFirstBit(data, _v.otherString, addToTable);
352     }
353
354     protected final void encodeComment(char[] ch, int start, int length) throws IOException JavaDoc {
355         write(EncodingConstants.COMMENT);
356
357         boolean addToTable = (length < characterContentChunkSizeContraint) ? true : false;
358         encodeNonIdentifyingStringOnFirstBit(ch, start, length, _v.otherString, addToTable, true);
359     }
360
361     protected final void encodeCommentNoClone(char[] ch, int start, int length) throws IOException JavaDoc {
362         write(EncodingConstants.COMMENT);
363
364         boolean addToTable = (length < characterContentChunkSizeContraint) ? true : false;
365         encodeNonIdentifyingStringOnFirstBit(ch, start, length, _v.otherString, addToTable, false);
366     }
367
368     /*
369      * C.18
370      */

371     protected final void encodeElementQualifiedNameOnThirdBit(String JavaDoc namespaceURI, String JavaDoc prefix, String JavaDoc localName) throws IOException JavaDoc {
372         LocalNameQualifiedNamesMap.Entry entry = _v.elementName.obtainEntry(localName);
373         if (entry._valueIndex > 0) {
374             QualifiedName[] names = entry._value;
375             for (int i = 0; i < entry._valueIndex; i++) {
376                 if ((prefix == names[i].prefix || prefix.equals(names[i].prefix))
377                         && (namespaceURI == names[i].namespaceName || namespaceURI.equals(names[i].namespaceName))) {
378                     encodeNonZeroIntegerOnThirdBit(names[i].index);
379                     return;
380                 }
381             }
382         }
383
384         encodeLiteralElementQualifiedNameOnThirdBit(namespaceURI, prefix,
385                 localName, entry);
386     }
387
388     /*
389      * C.18
390      */

391     protected final void encodeLiteralElementQualifiedNameOnThirdBit(String JavaDoc namespaceURI, String JavaDoc prefix, String JavaDoc localName,
392             LocalNameQualifiedNamesMap.Entry entry) throws IOException JavaDoc {
393         QualifiedName name = new QualifiedName(prefix, namespaceURI, localName, "", _v.elementName.getNextIndex());
394         entry.addQualifiedName(name);
395
396         int namespaceURIIndex = KeyIntMap.NOT_PRESENT;
397         int prefixIndex = KeyIntMap.NOT_PRESENT;
398         if (namespaceURI != "") {
399             namespaceURIIndex = _v.namespaceName.get(namespaceURI);
400             if (namespaceURIIndex == KeyIntMap.NOT_PRESENT) {
401                 throw new IOException JavaDoc(CommonResourceBundle.getInstance().getString("message.namespaceURINotIndexed", new Object JavaDoc[]{namespaceURI}));
402             }
403
404             if (prefix != "") {
405                 prefixIndex = _v.prefix.get(prefix);
406                 if (prefixIndex == KeyIntMap.NOT_PRESENT) {
407                     throw new IOException JavaDoc(CommonResourceBundle.getInstance().getString("message.prefixNotIndexed", new Object JavaDoc[]{prefix}));
408                 }
409             }
410         }
411
412         int localNameIndex = _v.localName.obtainIndex(localName);
413
414         _b |= EncodingConstants.ELEMENT_LITERAL_QNAME_FLAG;
415         if (namespaceURIIndex >= 0) {
416             _b |= EncodingConstants.LITERAL_QNAME_NAMESPACE_NAME_FLAG;
417             if (prefixIndex >= 0) {
418                 _b |= EncodingConstants.LITERAL_QNAME_PREFIX_FLAG;
419             }
420         }
421         write(_b);
422
423         if (namespaceURIIndex >= 0) {
424             if (prefixIndex >= 0) {
425                 encodeNonZeroIntegerOnSecondBitFirstBitOne(prefixIndex);
426             }
427             encodeNonZeroIntegerOnSecondBitFirstBitOne(namespaceURIIndex);
428         }
429
430         if (localNameIndex >= 0) {
431             encodeNonZeroIntegerOnSecondBitFirstBitOne(localNameIndex);
432         } else {
433             encodeNonEmptyOctetStringOnSecondBit(localName);
434         }
435     }
436
437     /*
438      * C.17
439      */

440     protected final void encodeAttributeQualifiedNameOnSecondBit(String JavaDoc namespaceURI, String JavaDoc prefix, String JavaDoc localName) throws IOException JavaDoc {
441         LocalNameQualifiedNamesMap.Entry entry = _v.attributeName.obtainEntry(localName);
442         if (entry._valueIndex > 0) {
443             QualifiedName[] names = entry._value;
444             for (int i = 0; i < entry._valueIndex; i++) {
445                 if ((prefix == names[i].prefix || prefix.equals(names[i].prefix))
446                         && (namespaceURI == names[i].namespaceName || namespaceURI.equals(names[i].namespaceName))) {
447                     encodeNonZeroIntegerOnSecondBitFirstBitZero(names[i].index);
448                     return;
449                 }
450             }
451         }
452
453         encodeLiteralAttributeQualifiedNameOnSecondBit(namespaceURI, prefix,
454                 localName, entry);
455     }
456
457     /*
458      * C.17
459      */

460     protected final boolean encodeLiteralAttributeQualifiedNameOnSecondBit(String JavaDoc namespaceURI, String JavaDoc prefix, String JavaDoc localName,
461                 LocalNameQualifiedNamesMap.Entry entry) throws IOException JavaDoc {
462         int namespaceURIIndex = KeyIntMap.NOT_PRESENT;
463         int prefixIndex = KeyIntMap.NOT_PRESENT;
464         if (namespaceURI != "") {
465             namespaceURIIndex = _v.namespaceName.get(namespaceURI);
466             if (namespaceURIIndex == KeyIntMap.NOT_PRESENT) {
467                 if (namespaceURI == EncodingConstants.XMLNS_NAMESPACE_NAME ||
468                         namespaceURI.equals(EncodingConstants.XMLNS_NAMESPACE_NAME)) {
469                     return false;
470                 } else {
471                     throw new IOException JavaDoc(CommonResourceBundle.getInstance().getString("message.namespaceURINotIndexed", new Object JavaDoc[]{namespaceURI}));
472                 }
473             }
474             
475             if (prefix != "") {
476                 prefixIndex = _v.prefix.get(prefix);
477                 if (prefixIndex == KeyIntMap.NOT_PRESENT) {
478                     throw new IOException JavaDoc(CommonResourceBundle.getInstance().getString("message.prefixNotIndexed", new Object JavaDoc[]{prefix}));
479                 }
480             }
481         }
482
483         int localNameIndex = _v.localName.obtainIndex(localName);
484
485         QualifiedName name = new QualifiedName(prefix, namespaceURI, localName, "", _v.attributeName.getNextIndex());
486         entry.addQualifiedName(name);
487
488         _b = EncodingConstants.ATTRIBUTE_LITERAL_QNAME_FLAG;
489         if (namespaceURI != "") {
490             _b |= EncodingConstants.LITERAL_QNAME_NAMESPACE_NAME_FLAG;
491             if (prefix != "") {
492                 _b |= EncodingConstants.LITERAL_QNAME_PREFIX_FLAG;
493             }
494         }
495
496         write(_b);
497
498         if (namespaceURIIndex >= 0) {
499             if (prefixIndex >= 0) {
500                 encodeNonZeroIntegerOnSecondBitFirstBitOne(prefixIndex);
501             }
502             encodeNonZeroIntegerOnSecondBitFirstBitOne(namespaceURIIndex);
503         } else if (namespaceURI != "") {
504             // XML prefix and namespace name
505
encodeNonEmptyOctetStringOnSecondBit("xml");
506             encodeNonEmptyOctetStringOnSecondBit("http://www.w3.org/XML/1998/namespace");
507         }
508
509         if (localNameIndex >= 0) {
510             encodeNonZeroIntegerOnSecondBitFirstBitOne(localNameIndex);
511         } else {
512             encodeNonEmptyOctetStringOnSecondBit(localName);
513         }
514         
515         return true;
516     }
517
518     /*
519      * C.14
520      */

521     protected final void encodeNonIdentifyingStringOnFirstBit(String JavaDoc s, StringIntMap map, boolean addToTable) throws IOException JavaDoc {
522         if (s == null || s.length() == 0) {
523             // C.26 an index (first bit '1') with seven '1' bits for an empty string
524
write(0xFF);
525         } else {
526             if (addToTable) {
527                 int index = map.obtainIndex(s);
528                 if (index == KeyIntMap.NOT_PRESENT) {
529                     _b = EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG | _nonIdentifyingStringOnFirstBitCES;
530                     encodeNonEmptyCharacterStringOnFifthBit(s);
531                 } else {
532                     encodeNonZeroIntegerOnSecondBitFirstBitOne(index);
533                 }
534             } else {
535                 _b = _nonIdentifyingStringOnFirstBitCES;
536                 encodeNonEmptyCharacterStringOnFifthBit(s);
537             }
538         }
539     }
540
541     /*
542      * C.14
543      */

544     protected final void encodeNonIdentifyingStringOnFirstBit(String JavaDoc s, CharArrayIntMap map, boolean addToTable) throws IOException JavaDoc {
545         if (s == null || s.length() == 0) {
546             // C.26 an index (first bit '1') with seven '1' bits for an empty string
547
write(0xFF);
548         } else {
549             if (addToTable) {
550                 final char[] ch = s.toCharArray();
551                 final int length = s.length();
552                 int index = map.obtainIndex(ch, 0, length, false);
553                 if (index == KeyIntMap.NOT_PRESENT) {
554                     _b = EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG | _nonIdentifyingStringOnFirstBitCES;
555                     encodeNonEmptyCharacterStringOnFifthBit(ch, 0, length);
556                 } else {
557                     encodeNonZeroIntegerOnSecondBitFirstBitOne(index);
558                 }
559             } else {
560                 _b = _nonIdentifyingStringOnFirstBitCES;
561                 encodeNonEmptyCharacterStringOnFifthBit(s);
562             }
563         }
564     }
565
566     /*
567      * C.14
568      */

569     protected final void encodeNonIdentifyingStringOnFirstBit(char[] array, int start, int length, CharArrayIntMap map,
570             boolean addToTable, boolean clone) throws IOException JavaDoc {
571         if (length == 0) {
572             // C.26 an index (first bit '1') with seven '1' bits for an empty string
573
write(0xFF);
574         } else {
575             if (addToTable) {
576                 int index = map.obtainIndex(array, start, length, clone);
577                 if (index == KeyIntMap.NOT_PRESENT) {
578                     _b = EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG | _nonIdentifyingStringOnFirstBitCES;
579                     encodeNonEmptyCharacterStringOnFifthBit(array, start, length);
580                 } else {
581                     encodeNonZeroIntegerOnSecondBitFirstBitOne(index);
582                 }
583             } else {
584                 _b = _nonIdentifyingStringOnFirstBitCES;
585                 encodeNonEmptyCharacterStringOnFifthBit(array, start, length);
586             }
587         }
588     }
589
590     /*
591      * C.14
592      */

593     protected final void encodeNonIdentifyingStringOnFirstBit(String JavaDoc URI, int id, Object JavaDoc data) throws FastInfosetException, IOException JavaDoc {
594         if (URI != null) {
595             id = _v.encodingAlgorithm.get(URI);
596             if (id == KeyIntMap.NOT_PRESENT) {
597                 throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.EncodingAlgorithmURI", new Object JavaDoc[]{URI}));
598             }
599             id += EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START;
600
601             EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI);
602             if (ea != null) {
603                 encodeAIIObjectAlgorithmData(URI, id, data, ea);
604             } else {
605                 if (data instanceof byte[]) {
606                     byte[] d = (byte[])data;
607                     encodeAIIOctetAlgorithmData(id, d, 0, d.length);
608                 } else {
609                     throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.nullEncodingAlgorithmURI"));
610                 }
611             }
612         } else if (id <= EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
613             BuiltInEncodingAlgorithm a = BuiltInEncodingAlgorithmFactory.table[id];
614             int length = 0;
615             switch(id) {
616                 case EncodingAlgorithmIndexes.HEXADECIMAL:
617                     length = ((byte[])data).length;
618                     break;
619                 case EncodingAlgorithmIndexes.BASE64:
620                     length = ((byte[])data).length;
621                     break;
622                 case EncodingAlgorithmIndexes.SHORT:
623                     length = ((short[])data).length;
624                     break;
625                 case EncodingAlgorithmIndexes.INT:
626                     length = ((int[])data).length;
627                     break;
628                 case EncodingAlgorithmIndexes.LONG:
629                     length = ((long[])data).length;
630                     break;
631                 case EncodingAlgorithmIndexes.BOOLEAN:
632                     length = ((boolean[])data).length;
633                     break;
634                 case EncodingAlgorithmIndexes.FLOAT:
635                     length = ((float[])data).length;
636                     break;
637                 case EncodingAlgorithmIndexes.DOUBLE:
638                     length = ((double[])data).length;
639                     break;
640                 case EncodingAlgorithmIndexes.UUID:
641                     length = ((long[])data).length;
642                     break;
643                 case EncodingAlgorithmIndexes.CDATA:
644                     throw new UnsupportedOperationException JavaDoc(CommonResourceBundle.getInstance().getString("message.CDATA"));
645                 default:
646                     throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.UnsupportedBuiltInAlgorithm", new Object JavaDoc[]{new Integer JavaDoc(id)}));
647             }
648             encodeAIIBuiltInAlgorithmData(id, data, 0, length);
649         } else if (id >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
650             if (data instanceof byte[]) {
651                 byte[] d = (byte[])data;
652                 encodeAIIOctetAlgorithmData(id, d, 0, d.length);
653             } else {
654                 throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.nullEncodingAlgorithmURI"));
655             }
656         } else {
657             throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved"));
658         }
659     }
660
661     protected final void encodeAIIOctetAlgorithmData(int id, byte[] d, int start, int length) throws IOException JavaDoc {
662         // Encode identification and top four bits of encoding algorithm id
663
write (EncodingConstants.NISTRING_ENCODING_ALGORITHM_FLAG |
664                 ((id & 0xF0) >> 4));
665
666         // Encode bottom 4 bits of enoding algorithm id
667
_b = (id & 0x0F) << 4;
668
669         // Encode the length
670
encodeNonZeroOctetStringLengthOnFifthBit(length);
671
672         write(d, start, length);
673     }
674
675     protected final void encodeAIIObjectAlgorithmData(String JavaDoc URI, int id, Object JavaDoc data, EncodingAlgorithm ea) throws FastInfosetException, IOException JavaDoc {
676         // Encode identification and top four bits of encoding algorithm id
677
write (EncodingConstants.NISTRING_ENCODING_ALGORITHM_FLAG |
678                 ((id & 0xF0) >> 4));
679
680         // Encode bottom 4 bits of enoding algorithm id
681
_b = (id & 0x0F) << 4;
682
683         _encodingBufferOutputStream.reset();
684         ea.encodeToOutputStream(data, _encodingBufferOutputStream);
685         encodeNonZeroOctetStringLengthOnFifthBit(_encodingBufferIndex);
686         write(_encodingBuffer, _encodingBufferIndex);
687     }
688
689     protected final void encodeAIIBuiltInAlgorithmData(int id, Object JavaDoc o, int start, int length) throws IOException JavaDoc {
690         // Encode identification and top four bits of encoding algorithm id
691
write (EncodingConstants.NISTRING_ENCODING_ALGORITHM_FLAG |
692                 ((id & 0xF0) >> 4));
693
694         // Encode bottom 4 bits of enoding algorithm id
695
_b = (id & 0x0F) << 4;
696
697         final int octetLength = BuiltInEncodingAlgorithmFactory.table[id].
698                     getOctetLengthFromPrimitiveLength(length);
699
700         encodeNonZeroOctetStringLengthOnFifthBit(octetLength);
701
702         ensureSize(octetLength);
703         BuiltInEncodingAlgorithmFactory.table[id].
704                 encodeToBytes(o, start, length, _octetBuffer, _octetBufferIndex);
705         _octetBufferIndex += octetLength;
706     }
707
708     /*
709      * C.15
710      */

711     protected final void encodeNonIdentifyingStringOnThirdBit(char[] array, int start, int length,
712             CharArrayIntMap map, boolean addToTable, boolean clone) throws IOException JavaDoc {
713         // length cannot be zero since sequence of CIIs has to be > 0
714

715         if (addToTable) {
716             int index = map.obtainIndex(array, start, length, clone);
717             if (index == KeyIntMap.NOT_PRESENT) {
718                 _b = EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG |
719                         _nonIdentifyingStringOnThirdBitCES;
720                 encodeNonEmptyCharacterStringOnSeventhBit(array, start, length);
721             } else {
722                 _b = EncodingConstants.CHARACTER_CHUNK | 0x20;
723                 encodeNonZeroIntegerOnFourthBit(index);
724             }
725         } else {
726             _b = _nonIdentifyingStringOnThirdBitCES;
727             encodeNonEmptyCharacterStringOnSeventhBit(array, start, length);
728         }
729     }
730
731     protected final void encodeNonIdentifyingStringOnThirdBit(String JavaDoc URI, int id, Object JavaDoc data) throws FastInfosetException, IOException JavaDoc {
732         if (URI != null) {
733             id = _v.encodingAlgorithm.get(URI);
734             if (id == KeyIntMap.NOT_PRESENT) {
735                 throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.EncodingAlgorithmURI", new Object JavaDoc[]{URI}));
736             }
737             id += EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START;
738
739             EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI);
740             if (ea != null) {
741                 encodeCIIObjectAlgorithmData(URI, id, data, ea);
742             } else {
743                 if (data instanceof byte[]) {
744                     byte[] d = (byte[])data;
745