OSDN Git Service

* Add ASN1Extendable annotation.
[bm-asn1/bm-asn1.git] / jp / bitmeister / asn1 / codec / xer / XerDecoder.java
1 /*
2  * Copyright 2011 BitMeister Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package jp.bitmeister.asn1.codec.xer;
17
18 import static jp.bitmeister.asn1.codec.xer.XerConstants.BOOLEAN_FALSE;
19 import static jp.bitmeister.asn1.codec.xer.XerConstants.BOOLEAN_TRUE;
20 import static jp.bitmeister.asn1.codec.xer.XerConstants.REAL_MINUS_INFINITY;
21 import static jp.bitmeister.asn1.codec.xer.XerConstants.REAL_PLUS_INFINITY;
22
23 import java.io.InputStream;
24 import java.math.BigInteger;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import jp.bitmeister.asn1.codec.ASN1Decoder;
29 import jp.bitmeister.asn1.exception.ASN1DecodingException;
30 import jp.bitmeister.asn1.processor.ASN1Visitor;
31 import jp.bitmeister.asn1.type.ASN1Module;
32 import jp.bitmeister.asn1.type.ASN1ModuleManager;
33 import jp.bitmeister.asn1.type.ASN1Type;
34 import jp.bitmeister.asn1.type.CollectionType;
35 import jp.bitmeister.asn1.type.NamedTypeSpecification;
36 import jp.bitmeister.asn1.type.StringType;
37 import jp.bitmeister.asn1.type.StructuredType;
38 import jp.bitmeister.asn1.type.TimeType;
39 import jp.bitmeister.asn1.type.UnknownType;
40 import jp.bitmeister.asn1.type.builtin.ANY;
41 import jp.bitmeister.asn1.type.builtin.BIT_STRING;
42 import jp.bitmeister.asn1.type.builtin.BOOLEAN;
43 import jp.bitmeister.asn1.type.builtin.CHOICE;
44 import jp.bitmeister.asn1.type.builtin.ENUMERATED;
45 import jp.bitmeister.asn1.type.builtin.INTEGER;
46 import jp.bitmeister.asn1.type.builtin.NULL;
47 import jp.bitmeister.asn1.type.builtin.OBJECT_IDENTIFIER;
48 import jp.bitmeister.asn1.type.builtin.OCTET_STRING;
49 import jp.bitmeister.asn1.type.builtin.REAL;
50 import jp.bitmeister.asn1.type.builtin.RELATIVE_OID;
51 import jp.bitmeister.asn1.type.builtin.SEQUENCE;
52 import jp.bitmeister.asn1.type.builtin.SEQUENCE_OF;
53 import jp.bitmeister.asn1.type.builtin.SET;
54 import jp.bitmeister.asn1.type.builtin.SET_OF;
55 import jp.bitmeister.asn1.value.BinString;
56 import jp.bitmeister.asn1.value.HexString;
57
58 import org.xml.sax.Attributes;
59 import org.xml.sax.InputSource;
60 import org.xml.sax.SAXException;
61 import org.xml.sax.XMLReader;
62 import org.xml.sax.helpers.DefaultHandler;
63 import org.xml.sax.helpers.XMLReaderFactory;
64
65 /**
66  * XER (XML Encoding Rules) decoder.
67  * 
68  * <p>
69  * {@code XerDecoder} is an implementation of {@code ASN1Decoder}. It reads a
70  * number of bytes from an {@code InputStream} that is specified when a decoder
71  * is instantiated, and decodes them to an ASN.1 data with XML Encoding Rules
72  * (XER).
73  * </p>
74  * 
75  * @author WATANABE, Jun. <jwat at bitmeister.jp>
76  * 
77  * @see ASN1Decoder
78  * @see XerEncoder
79  */
80 public class XerDecoder implements ASN1Decoder,
81                 ASN1Visitor<XerDecoder.DataDecoder, SAXException> {
82
83         /**
84          * Abstract handler class used for decoding an XML element to an ASN.1 data.
85          * 
86          * @author WATANABE, Jun. <jwat at bitmeister.jp>
87          */
88         abstract class DataDecoder {
89
90                 /**
91                  * Callback method that is called when the data element started.
92                  */
93                 void startElement(String qName) throws SAXException {
94                 }
95
96                 /**
97                  * Callback method that is called when a child element started.
98                  * 
99                  * @param qName
100                  *            The element name.
101                  * @throws SAXException
102                  *             Thrown when an error occurred while the process.
103                  */
104                 void startChildElement(String qName) throws SAXException {
105                 }
106
107                 /**
108                  * Callback method that is called when a character sequence detected in
109                  * the XML element.
110                  * 
111                  * @param characters
112                  *            The character sequence.
113                  */
114                 void characters(String characters) {
115                 }
116
117                 /**
118                  * Callback method that is called when a child element ended.
119                  * 
120                  * @param qName
121                  *            The element name.
122                  * @throws SAXException
123                  *             Thrown when an error occurred while the process.
124                  */
125                 void endChildElement(String qName) {
126                 }
127
128                 /**
129                  * Callback method that is called when the data element ended.
130                  */
131                 void endElement() {
132                 }
133
134         }
135
136         /**
137          * Handler class for constructed data ({@code CollectionType} and
138          * {@code StructuredType}).
139          * 
140          * @author WATANABE, Jun. <jwat at bitmeister.jp>
141          */
142         private abstract class ConstructedDataDecoder extends DataDecoder {
143
144                 ElementDecoder decoder;
145
146                 /*
147                  * (non-Javadoc)
148                  * 
149                  * @see
150                  * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#characters(java
151                  * .lang.String)
152                  */
153                 @Override
154                 void characters(String characters) {
155                         if (decoder != null) {
156                                 decoder.characters(characters);
157                         }
158                 }
159
160         }
161
162         /**
163          * Abstract handler class used for decoding a sequence of XML elements to an
164          * ASN.1 type data.
165          * 
166          * @author WATANABE, Jun. <jwat at bitmeister.jp>
167          */
168         private abstract class ElementDecoder {
169
170                 DataDecoder decoder;
171
172                 /**
173                  * Instantiate an {@code ElementDecoder}.
174                  * 
175                  * @param decoder
176                  *            The {@code DataDecoder} used for decode the data.
177                  */
178                 ElementDecoder(DataDecoder decoder) {
179                         this.decoder = decoder;
180                 }
181
182                 /**
183                  * Callback method that is called when an XML element started.
184                  * 
185                  * @param qName
186                  *            The tag name of the element.
187                  * @throws SAXException
188                  *             Thrown when an error occurred while the process.
189                  */
190                 abstract void startElement(String qName) throws SAXException;
191
192                 /**
193                  * Callback method that is called when a character sequence detected in
194                  * an XML element.
195                  * 
196                  * @param characters
197                  *            The character sequence.
198                  */
199                 void characters(String characters) {
200                         decoder.characters(characters);
201                 }
202
203                 /**
204                  * Callback method that is called when an XML element ended.
205                  * 
206                  * @param qName
207                  *            The tag name of the element.
208                  * @return {@code true} when the element is enclosing element.
209                  */
210                 abstract boolean endElement(String qName);
211
212         }
213
214         /**
215          * Handler class used for decoding a sequence of data elements that enclosed
216          * by an element.
217          * 
218          * @author WATANABE, Jun. <jwat at bitmeister.jp>
219          */
220         private class NamedElementDecoder extends ElementDecoder {
221
222                 private String tagName;
223
224                 /**
225                  * Instantiate a {@code NamedElementDecoder}.
226                  * 
227                  * @param tagName
228                  *            The tag name of enclosing element.
229                  * @param decoder
230                  *            The {@code DataDecoder} used for decoding data elements.
231                  */
232                 NamedElementDecoder(String tagName, DataDecoder decoder) {
233                         super(decoder);
234                         this.tagName = tagName;
235                 }
236
237                 /*
238                  * (non-Javadoc)
239                  * 
240                  * @see
241                  * jp.bitmeister.asn1.codec.xer.XerDecoder.ElementDecoder#startElement
242                  * (java.lang.String)
243                  */
244                 public void startElement(String qName) throws SAXException {
245                         if (qName.equals(tagName)) {
246                                 decoder.startElement(qName);
247                         } else {
248                                 decoder.startChildElement(qName);
249                         }
250                 }
251
252                 /*
253                  * (non-Javadoc)
254                  * 
255                  * @see
256                  * jp.bitmeister.asn1.codec.xer.XerDecoder.ElementDecoder#endElement
257                  * (java.lang.String)
258                  */
259                 public boolean endElement(String qName) {
260                         if (qName.equals(tagName)) {
261                                 decoder.endElement();
262                                 return true;
263                         } else {
264                                 decoder.endChildElement(qName);
265                                 return false;
266                         }
267                 }
268
269         }
270
271         /**
272          * Handler class used for decoding an data element that is not enclosed by
273          * element.
274          * 
275          * @author WATANABE, Jun. <jwat at bitmeister.jp>
276          */
277         private class ValueListElementDecoder extends ElementDecoder {
278
279                 /**
280                  * Instantiate a {@code ValueListElementDecoder}.
281                  * 
282                  * @param decoder
283                  *            The {@code DataDecoder} used for decoding the data
284                  *            element.
285                  */
286                 ValueListElementDecoder(DataDecoder decoder) {
287                         super(decoder);
288                 }
289
290                 /*
291                  * (non-Javadoc)
292                  * 
293                  * @see
294                  * jp.bitmeister.asn1.codec.xer.XerDecoder.ElementDecoder#startElement
295                  * (java.lang.String)
296                  */
297                 public void startElement(String qName) throws SAXException {
298                         decoder.startElement(qName);
299                         decoder.startChildElement(qName);
300                 }
301
302                 /*
303                  * (non-Javadoc)
304                  * 
305                  * @see
306                  * jp.bitmeister.asn1.codec.xer.XerDecoder.ElementDecoder#endElement
307                  * (java.lang.String)
308                  */
309                 public boolean endElement(String qName) {
310                         decoder.endChildElement(qName);
311                         decoder.endElement();
312                         return true;
313                 }
314
315         }
316
317         /**
318          * Abstract handler class used for decosing an XML document to an ASN.1
319          * data.
320          * 
321          * @author WATANABE, Jun. <jwat at bitmeister.jp>
322          */
323         private abstract class XerHandler<T extends ASN1Type> extends
324                         DefaultHandler {
325
326                 T data;
327
328                 private ElementDecoder decoder;
329
330                 /**
331                  * Instantiates an ASN.1 data and sets it to this instance.
332                  * 
333                  * @param qName
334                  *            The tag name of the head element of the XML document.
335                  * @throws SAXException
336                  *             Thrown when an error occurred while the process.
337                  */
338                 abstract void initializeData(String qName) throws SAXException;
339
340                 /*
341                  * (non-Javadoc)
342                  * 
343                  * @see
344                  * org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
345                  * java.lang.String, java.lang.String, org.xml.sax.Attributes)
346                  */
347                 @Override
348                 public void startElement(String uri, String localName, String qName,
349                                 Attributes attributes) throws SAXException {
350                         if (data == null) {
351                                 initializeData(qName);
352                                 decoder = new NamedElementDecoder(qName,
353                                                 data.accept(XerDecoder.this));
354                         }
355                         decoder.startElement(qName);
356                 }
357
358                 /*
359                  * (non-Javadoc)
360                  * 
361                  * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
362                  */
363                 @Override
364                 public void characters(char[] ch, int start, int length) {
365                         char[] tmp = new char[length];
366                         System.arraycopy(ch, start, tmp, 0, length);
367                         decoder.characters(String.valueOf(tmp));
368                 }
369
370                 /*
371                  * (non-Javadoc)
372                  * 
373                  * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
374                  * java.lang.String, java.lang.String)
375                  */
376                 @Override
377                 public void endElement(String uri, String localName, String qName) {
378                         decoder.endElement(qName);
379                 }
380
381         }
382         
383         private Class<? extends ASN1Module> module;
384
385         private InputStream in;
386
387         private XMLReader reader;
388
389         /**
390          * Instantiates a {@code XerDecoder}.
391          * 
392          * @param in
393          *            The {@code InputStream} to be read.
394          */
395         public XerDecoder(InputStream in) {
396                 this.in = in;
397         }
398
399         /**
400          * Instantiates a {@code XerDecoder}.
401          * 
402          * @param in
403          *            The {@code InputStream} to be read.
404          */
405         public XerDecoder(Class<? extends ASN1Module> module, InputStream in) {
406                 this(in);
407                 this.module = module;
408         }
409         
410         /*
411          * (non-Javadoc)
412          * 
413          * @see jp.bitmeister.asn1.codec.ASN1Decoder#decode(java.lang.Class)
414          */
415         public <T extends ASN1Type> T decode(final Class<T> type)
416                         throws ASN1DecodingException {
417                 XerHandler<T> handler = new XerHandler<T>() {
418
419                         /*
420                          * (non-Javadoc)
421                          * 
422                          * @see
423                          * jp.bitmeister.asn1.codec.xer.XerDecoder.XerHandler#initializeData
424                          * (java.lang.String)
425                          */
426                         void initializeData(String qName) throws SAXException {
427                                 data = ASN1Type.instantiate(type);
428                                 if (module == null) {
429                                         module = data.specification().module();
430                                 }
431                                 if (!(data instanceof ANY)
432                                                 && !qName.equals(data.specification().xmlTypeName(module))) {
433                                         throw new SAXException("Unexpected xml tag name '" + qName
434                                                         + "'. '" + data.specification().xmlTypeName(module)
435                                                         + "' is expected.");
436                                 }
437                         }
438
439                 };
440                 parse(handler);
441                 return handler.data;
442         }
443
444         /*
445          * (non-Javadoc)
446          * 
447          * @see jp.bitmeister.asn1.codec.ASN1Decoder#decode()
448          */
449         public ASN1Type decode() throws ASN1DecodingException {
450                 XerHandler<ASN1Type> handler = new XerHandler<ASN1Type>() {
451
452                         /*
453                          * (non-Javadoc)
454                          * 
455                          * @see
456                          * jp.bitmeister.asn1.codec.xer.XerDecoder.XerHandler#initializeData
457                          * (java.lang.String)
458                          */
459                         void initializeData(String qName) throws SAXException {
460                                 data = ASN1ModuleManager.instantiate(module, qName);
461                                 if (data == null) {
462                                         throw new SAXException("Unknown data type '" + qName + "'.");
463                                 }
464                         }
465
466                 };
467                 parse(handler);
468                 return handler.data;
469         }
470
471         /**
472          * Decodes the source XML data read from the {@code InputStream} to the
473          * ASN.1 data.
474          * 
475          * @throws ASN1DecodingException
476          *             When an error occurred while the decoding process.
477          */
478         private void parse(XerHandler<?> handler) throws ASN1DecodingException {
479                 try {
480                         reader = XMLReaderFactory.createXMLReader();
481                         reader.setContentHandler(handler);
482                         reader.parse(new InputSource(in));
483                 } catch (Exception e) {
484                         ASN1DecodingException ex = new ASN1DecodingException();
485                         ex.setMessage("An exception thrown while decoding process.", e,
486                                         null, null, null);
487                         throw ex;
488                 }
489         }
490
491         /*
492          * (non-Javadoc)
493          * 
494          * @see
495          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
496          * .builtin.BOOLEAN)
497          */
498         public DataDecoder visit(final BOOLEAN data) {
499                 return new DataDecoder() {
500
501                         /*
502                          * (non-Javadoc)
503                          * 
504                          * @see
505                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#startChildElement
506                          * (java.lang.String)
507                          */
508                         @Override
509                         void startChildElement(String qName) {
510                                 if (qName.equals(BOOLEAN_TRUE)) {
511                                         data.set(true);
512                                 } else if (qName.equals(BOOLEAN_FALSE)) {
513                                         data.set(false);
514                                 }
515                         }
516
517                 };
518         }
519
520         /*
521          * (non-Javadoc)
522          * 
523          * @see
524          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
525          * .builtin.INTEGER)
526          */
527         public DataDecoder visit(final INTEGER data) {
528                 return new DataDecoder() {
529
530                         /*
531                          * (non-Javadoc)
532                          * 
533                          * @see
534                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#startChildElement
535                          * (java.lang.String)
536                          */
537                         @Override
538                         void startChildElement(String qName) {
539                                 data.set(qName);
540                         }
541
542                         /*
543                          * (non-Javadoc)
544                          * 
545                          * @see
546                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#characters
547                          * (java.lang.String)
548                          */
549                         @Override
550                         public void characters(String characters) {
551                                 data.set(new BigInteger(characters));
552                         }
553
554                 };
555         }
556
557         /*
558          * (non-Javadoc)
559          * 
560          * @see
561          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
562          * .builtin.BIT_STRING)
563          */
564         public DataDecoder visit(final BIT_STRING data) {
565                 return new DataDecoder() {
566
567                         /*
568                          * (non-Javadoc)
569                          * 
570                          * @see
571                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#startChildElement
572                          * (java.lang.String)
573                          */
574                         @Override
575                         public void startChildElement(String qName) {
576                                 data.set(qName);
577                         }
578
579                         /*
580                          * (non-Javadoc)
581                          * 
582                          * @see
583                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#characters
584                          * (java.lang.String)
585                          */
586                         @Override
587                         public void characters(String characters) {
588                                 data.set(new BinString(characters));
589                         }
590
591                 };
592         }
593
594         /*
595          * (non-Javadoc)
596          * 
597          * @see
598          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
599          * .builtin.OCTET_STRING)
600          */
601         public DataDecoder visit(final OCTET_STRING data) {
602                 return new DataDecoder() {
603
604                         /*
605                          * (non-Javadoc)
606                          * 
607                          * @see
608                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#characters
609                          * (java.lang.String)
610                          */
611                         @Override
612                         public void characters(String characters) {
613                                 data.set(new HexString(characters));
614                         }
615
616                 };
617         }
618
619         /*
620          * (non-Javadoc)
621          * 
622          * @see
623          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
624          * .builtin.NULL)
625          */
626         public DataDecoder visit(NULL data) {
627                 return new DataDecoder() {
628                 };
629         }
630
631         /*
632          * (non-Javadoc)
633          * 
634          * @see
635          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
636          * .builtin.OBJECT_IDENTIFIER)
637          */
638         public DataDecoder visit(final OBJECT_IDENTIFIER data) {
639                 return new DataDecoder() {
640
641                         /*
642                          * (non-Javadoc)
643                          * 
644                          * @see
645                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#characters
646                          * (java.lang.String)
647                          */
648                         @Override
649                         public void characters(String characters) {
650                                 List<Integer> oids = new ArrayList<Integer>();
651                                 for (String e : characters.split("\\.")) {
652                                         e.trim();
653                                         if (Character.isLetter(e.charAt(0))) {
654                                                 if (!e.endsWith(")")) {
655                                                         oids.add(OBJECT_IDENTIFIER.nameFormToInt(oids, e));
656                                                         continue;
657                                                 }
658                                                 e = e.substring(e.indexOf('(') + 1, e.indexOf(')'));
659                                         }
660                                         oids.add(Integer.parseInt(e));
661                                 }
662                                 data.set(oids);
663                         }
664
665                 };
666         }
667
668         /*
669          * (non-Javadoc)
670          * 
671          * @see
672          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
673          * .builtin.REAL)
674          */
675         public DataDecoder visit(final REAL data) {
676                 return new DataDecoder() {
677
678                         /*
679                          * (non-Javadoc)
680                          * 
681                          * @see
682                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#startChildElement
683                          * (java.lang.String)
684                          */
685                         @Override
686                         public void startChildElement(String qName) {
687                                 if (qName.equals(REAL_PLUS_INFINITY)) {
688                                         data.set(Double.POSITIVE_INFINITY);
689                                 } else if (qName.equals(REAL_MINUS_INFINITY)) {
690                                         data.set(Double.NEGATIVE_INFINITY);
691                                 }
692                         }
693
694                         /*
695                          * (non-Javadoc)
696                          * 
697                          * @see
698                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#characters
699                          * (java.lang.String)
700                          */
701                         @Override
702                         public void characters(String characters) {
703                                 data.set(Double.parseDouble(characters));
704                         }
705
706                 };
707         }
708
709         /*
710          * (non-Javadoc)
711          * 
712          * @see
713          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
714          * .builtin.ENUMERATED)
715          */
716         public DataDecoder visit(ENUMERATED data) {
717                 return visit((INTEGER) data);
718         }
719
720         /*
721          * (non-Javadoc)
722          * 
723          * @see
724          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
725          * .builtin.RELATIVE_OID)
726          */
727         public DataDecoder visit(RELATIVE_OID data) {
728                 return visit((OBJECT_IDENTIFIER) data);
729         }
730
731         /*
732          * (non-Javadoc)
733          * 
734          * @see
735          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
736          * .builtin.ANY)
737          */
738         public DataDecoder visit(final ANY data) {
739                 return new DataDecoder() {
740
741                         private DataDecoder decoder;
742
743                         @Override
744                         void startElement(String qName) throws SAXException {
745                                 data.set(ASN1ModuleManager.instantiate(module, qName));
746                                 decoder = data.value().accept(XerDecoder.this);
747                                 decoder.startElement(qName);
748                         }
749
750                         @Override
751                         void startChildElement(String qName) throws SAXException {
752                                 decoder.startChildElement(qName);
753                         }
754
755                         @Override
756                         void characters(String characters) {
757                                 decoder.characters(characters);
758                         }
759
760                         @Override
761                         void endChildElement(String qName) {
762                                 decoder.endChildElement(qName);
763                         }
764
765                         @Override
766                         void endElement() {
767                                 decoder.endElement();
768                         }
769
770                 };
771         }
772
773         /*
774          * (non-Javadoc)
775          * 
776          * @see
777          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
778          * .builtin.CHOICE)
779          */
780         public DataDecoder visit(CHOICE data) {
781                 return decoderForStructuredType(data);
782         }
783
784         /*
785          * (non-Javadoc)
786          * 
787          * @see
788          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
789          * .builtin.SEQUENCE_OF)
790          */
791         public DataDecoder visit(SEQUENCE_OF<? extends ASN1Type> data) {
792                 return decoderForCollectionType(data);
793         }
794
795         /*
796          * (non-Javadoc)
797          * 
798          * @see
799          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
800          * .builtin.SEQUENCE)
801          */
802         public DataDecoder visit(SEQUENCE data) {
803                 return decoderForStructuredType(data);
804         }
805
806         /*
807          * (non-Javadoc)
808          * 
809          * @see
810          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
811          * .builtin.SET_OF)
812          */
813         public DataDecoder visit(SET_OF<? extends ASN1Type> data) {
814                 return decoderForCollectionType(data);
815         }
816
817         /*
818          * (non-Javadoc)
819          * 
820          * @see
821          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
822          * .builtin.SET)
823          */
824         public DataDecoder visit(SET data) {
825                 return decoderForStructuredType(data);
826         }
827
828         /*
829          * (non-Javadoc)
830          * 
831          * @see
832          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
833          * .StringType)
834          */
835         public DataDecoder visit(final StringType data) {
836                 return new DataDecoder() {
837
838                         private StringBuilder builder = new StringBuilder();
839
840                         /*
841                          * (non-Javadoc)
842                          * 
843                          * @see
844                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#startChildElement
845                          * (java.lang.String)
846                          */
847                         @Override
848                         public void startChildElement(String qName) {
849                                 builder.append(XerStringEscapeUtil.unescapeCtrl(qName));
850                         }
851
852                         /*
853                          * (non-Javadoc)
854                          * 
855                          * @see
856                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#characters
857                          * (java.lang.String)
858                          */
859                         @Override
860                         public void characters(String characters) {
861                                 builder.append(characters);
862                         }
863
864                         /*
865                          * (non-Javadoc)
866                          * 
867                          * @see
868                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#endElement()
869                          */
870                         @Override
871                         void endElement() {
872                                 if (builder.length() > 0) {
873                                         data.set(builder.toString());
874                                 }
875                         }
876
877                 };
878         }
879
880         /*
881          * (non-Javadoc)
882          * 
883          * @see
884          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
885          * .TimeType)
886          */
887         public DataDecoder visit(TimeType data) {
888                 return visit((StringType) data);
889         }
890
891         /*
892          * (non-Javadoc)
893          * 
894          * @see
895          * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
896          * .UnknownType)
897          */
898         public DataDecoder visit(UnknownType data) throws SAXException {
899                 throw new SAXException("UnkownType is not supported by XerDecoder.");
900         }
901
902         /**
903          * Returns handler for the {@code StructuredType}.
904          * 
905          * @param data
906          *            The {@code StructuredType} data.
907          * @return Handler for the data.
908          */
909         private DataDecoder decoderForStructuredType(final StructuredType data) {
910                 return new ConstructedDataDecoder() {
911
912                         private NamedTypeSpecification namedType;
913
914                         private ASN1Type element;
915
916                         /*
917                          * (non-Javadoc)
918                          * 
919                          * @see
920                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#startChildElement
921                          * (java.lang.String)
922                          */
923                         @Override
924                         void startChildElement(String qName) throws SAXException {
925                                 if (decoder == null) {
926                                         namedType = data.getElement(qName);
927                                         element = namedType.instantiate();
928                                         decoder = new NamedElementDecoder(qName,
929                                                         element.accept(XerDecoder.this));
930                                 }
931                                 decoder.startElement(qName);
932                         }
933
934                         /*
935                          * (non-Javadoc)
936                          * 
937                          * @see
938                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#endChildElement
939                          * (java.lang.String)
940                          */
941                         @Override
942                         void endChildElement(String qName) {
943                                 if (decoder.endElement(qName)) {
944                                         data.set(namedType, element);
945                                         decoder = null;
946                                 }
947                         }
948
949                 };
950         }
951
952         /**
953          * Returns handler for the {@code CollectionType}.
954          * 
955          * @param data
956          *            The {@code CollectionType} data.
957          * @return Handler for the data.
958          */
959         private <T extends ASN1Type> DataDecoder decoderForCollectionType(
960                         final CollectionType<T, ?> data) {
961                 return new ConstructedDataDecoder() {
962
963                         private T component;
964
965                         private boolean useXmlValueList = false;
966
967                         /*
968                          * (non-Javadoc)
969                          * 
970                          * @see
971                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#startElement
972                          * ()
973                          */
974                         @Override
975                         void startElement(String qName) {
976                                 if (BOOLEAN.class.isAssignableFrom(data.componentType())
977                                                 || ENUMERATED.class.isAssignableFrom(data.componentType())
978                                                 || CHOICE.class.isAssignableFrom(data.componentType())) {
979                                         useXmlValueList = true;
980                                 }
981                         }
982
983                         /*
984                          * (non-Javadoc)
985                          * 
986                          * @see
987                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#startChildElement
988                          * (java.lang.String)
989                          */
990                         @Override
991                         void startChildElement(String qName) throws SAXException {
992                                 if (decoder == null) {
993                                         component = ASN1Type.instantiate(data.componentType());
994                                         if (useXmlValueList) {
995                                                 decoder = new ValueListElementDecoder(
996                                                                 component.accept(XerDecoder.this));
997                                         } else {
998                                                 decoder = new NamedElementDecoder(qName,
999                                                                 component.accept(XerDecoder.this));
1000                                         }
1001                                 }
1002                                 decoder.startElement(qName);
1003                         }
1004
1005                         /*
1006                          * (non-Javadoc)
1007                          * 
1008                          * @see
1009                          * jp.bitmeister.asn1.codec.xer.XerDecoder.DataDecoder#endChildElement
1010                          * (java.lang.String)
1011                          */
1012                         @Override
1013                         void endChildElement(String qName) {
1014                                 if (decoder.endElement(qName)) {
1015                                         data.collection().add(component);
1016                                         decoder = null;
1017                                 }
1018                         }
1019
1020                 };
1021         }
1022
1023 }