OSDN Git Service

Made thread safe.
authorjwat <jwat@users.sourceforge.jp>
Thu, 16 Feb 2012 02:35:51 +0000 (11:35 +0900)
committerjwat <jwat@users.sourceforge.jp>
Thu, 16 Feb 2012 02:35:51 +0000 (11:35 +0900)
jp/bitmeister/asn1/processor/ASN1StringBuilder.java

index 1256024..96b2b2b 100644 (file)
@@ -63,8 +63,7 @@ import jp.bitmeister.asn1.value.HexString;
  * @see ASN1Type
  */
 public class ASN1StringBuilder implements
-               ASN1Processor<String, ASN1RuntimeException>,
-               ASN1Visitor<Void, ASN1RuntimeException> {
+               ASN1Processor<String, ASN1RuntimeException> {
 
        private static final String NEW_LINE = System.getProperty("line.separator");
        private static final String SPACE = " ";
@@ -100,10 +99,6 @@ public class ASN1StringBuilder implements
                }
        };
 
-       private StringBuilder builder;
-
-       private int indent;
-
        /**
         * Instantiates an {@code ASN1StringBuilder}.
         */
@@ -118,401 +113,420 @@ public class ASN1StringBuilder implements
         * @return A string representation of the ASN.1 data.
         */
        public String process(ASN1Type data) {
-               indent = 0;
-               builder = new StringBuilder();
-               write(data);
-               return builder.toString();
+               return new InternalProcessor().process(data);
        }
-
-       /**
-        * Writes descriptions of the data to the 'builder'.
-        * 
-        * @param data
-        *            The ASN.1 data.
-        */
-       private void write(ASN1Type data) {
-               TypeSpecification specification = data.specification();
-               while (true) {
-                       if (specification.hasIdentifier()) {
-                               builder.append(specification.identifier());
-                               if (specification.reference() == null) {
-                                       if (data instanceof CollectionType<?, ?>) {
-                                               CollectionType<?, ?> collection = (CollectionType<?, ?>) data;
-                                               if (!collection.componentType().equals(ANY.class)) {
-                                                       builder.append(COLLECTION_OF).append(
-                                                                       collection.componentSpecification()
-                                                                                       .identifier());
+       
+       private class InternalProcessor implements ASN1Visitor<Void, ASN1RuntimeException> {
+               
+               private StringBuilder builder;
+
+               private int indent;
+
+               /**
+                * Returns a string representation of the ASN.1 data.
+                * 
+                * @param data
+                *            The ASN.1 data.
+                * @return A string representation of the ASN.1 data.
+                */
+               private String process(ASN1Type data) {
+                       indent = 0;
+                       builder = new StringBuilder();
+                       write(data);
+                       return builder.toString();
+               }
+               
+               /**
+                * Writes descriptions of the data to the 'builder'.
+                * 
+                * @param data
+                *            The ASN.1 data.
+                */
+               private void write(ASN1Type data) {
+                       TypeSpecification specification = data.specification();
+                       while (true) {
+                               if (specification.hasIdentifier()) {
+                                       builder.append(specification.identifier());
+                                       if (specification.reference() == null) {
+                                               if (data instanceof CollectionType<?, ?>) {
+                                                       CollectionType<?, ?> collection = (CollectionType<?, ?>) data;
+                                                       if (!collection.componentType().equals(ANY.class)) {
+                                                               builder.append(COLLECTION_OF).append(
+                                                                               collection.componentSpecification()
+                                                                               .identifier());
+                                                       }
+                                               }
+                                               break;
+                                       } else {
+                                               builder.append(ASSIGN);
+                                               if (specification.tag() != null) {
+                                                       writeTag(specification.tag());
+                                                       builder.append(SPACE);
                                                }
-                                       }
-                                       break;
-                               } else {
-                                       builder.append(ASSIGN);
-                                       if (specification.tag() != null) {
-                                               writeTag(specification.tag());
-                                               builder.append(SPACE);
                                        }
                                }
+                               specification = specification.reference();
                        }
-                       specification = specification.reference();
-               }
-               if (data instanceof PrimitiveType<?>) {
-                       builder.append(VALUE_OPEN);
-                       if (data.hasValue()) {
-                               data.accept(this);
+                       if (data instanceof PrimitiveType<?>) {
+                               builder.append(VALUE_OPEN);
+                               if (data.hasValue()) {
+                                       data.accept(this);
+                               } else {
+                                       builder.append(NOT_SET);
+                               }
+                               builder.append(VALUE_CLOSE);
                        } else {
-                               builder.append(NOT_SET);
+                               builder.append(CONSTRUCTIVE_OPEN);
+                               indent++;
+                               data.accept(this);
+                               indent--;
+                               builder.append(CONSTRUCTIVE_CLOSE);
                        }
-                       builder.append(VALUE_CLOSE);
-               } else {
-                       builder.append(CONSTRUCTIVE_OPEN);
-                       indent++;
-                       data.accept(this);
-                       indent--;
-                       builder.append(CONSTRUCTIVE_CLOSE);
                }
-       }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.BOOLEAN)
-        */
-       public Void visit(BOOLEAN data) {
-               builder.append(data.value() ? "TRUE" : "FALSE");
-               return null;
-       }
+               /*
+                * (non-Javadoc)
+                
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.BOOLEAN)
+                */
+               public Void visit(BOOLEAN data) {
+                       builder.append(data.value() ? "TRUE" : "FALSE");
+                       return null;
+               }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.INTEGER)
-        */
-       public Void visit(INTEGER data) {
-               String numberId = data.identifier();
-               if (numberId != null) {
-                       builder.append(numberId);
+               /*
+                * (non-Javadoc)
+                * 
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.INTEGER)
+                */
+               public Void visit(INTEGER data) {
+                       String numberId = data.identifier();
+                       if (numberId != null) {
+                               builder.append(numberId);
+                       }
+                       builder.append(NUMBER_OPEN).append(data.value()).append(NUMBER_CLOSE);
+                       return null;
                }
-               builder.append(NUMBER_OPEN).append(data.value()).append(NUMBER_CLOSE);
-               return null;
-       }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.ENUMERATED)
-        */
-       public Void visit(ENUMERATED data) {
-               visit((INTEGER) data);
-               return null;
-       }
+               /*
+                * (non-Javadoc)
+                
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.ENUMERATED)
+                */
+               public Void visit(ENUMERATED data) {
+                       visit((INTEGER) data);
+                       return null;
+               }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.REAL)
-        */
-       public Void visit(REAL data) {
-               builder.append(NUMBER_OPEN).append(data.value()).append(NUMBER_CLOSE);
-               return null;
-       }
+               /*
+                * (non-Javadoc)
+                
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.REAL)
+                */
+               public Void visit(REAL data) {
+                       builder.append(NUMBER_OPEN).append(data.value()).append(NUMBER_CLOSE);
+                       return null;
+               }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.BIT_STRING)
-        */
-       public Void visit(BIT_STRING data) {
-               if (data.hasNamedBits()) {
-                       builder.append(NAMED_BITS_OPEN);
-                       boolean trailing = false;
-                       for (int i = 0; i < data.size(); i++) {
-                               if (data.bit(i)) {
-                                       String identifier = data.nameOfBit(i);
-                                       if (identifier != null) {
-                                               if (trailing) {
-                                                       builder.append(NAMED_BITS_SEPARATOR).append(SPACE);
-                                               } else {
-                                                       builder.append(SPACE);
-                                                       trailing = true;
+               /*
+                * (non-Javadoc)
+                * 
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.BIT_STRING)
+                */
+               public Void visit(BIT_STRING data) {
+                       if (data.hasNamedBits()) {
+                               builder.append(NAMED_BITS_OPEN);
+                               boolean trailing = false;
+                               for (int i = 0; i < data.size(); i++) {
+                                       if (data.bit(i)) {
+                                               String identifier = data.nameOfBit(i);
+                                               if (identifier != null) {
+                                                       if (trailing) {
+                                                               builder.append(NAMED_BITS_SEPARATOR).append(SPACE);
+                                                       } else {
+                                                               builder.append(SPACE);
+                                                               trailing = true;
+                                                       }
+                                                       builder.append(identifier);
                                                }
-                                               builder.append(identifier);
                                        }
                                }
+                               builder.append(SPACE).append(NAMED_BITS_CLOSE).append(SEPARATOR);
                        }
-                       builder.append(SPACE).append(NAMED_BITS_CLOSE).append(SEPARATOR);
+                       builder.append(new BinString(data.value()).toString());
+                       return null;
                }
-               builder.append(new BinString(data.value()).toString());
-               return null;
-       }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.OCTET_STRING)
-        */
-       public Void visit(OCTET_STRING data) {
-               builder.append(new HexString(data.value()).toString());
-               return null;
-       }
+               /*
+                * (non-Javadoc)
+                
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.OCTET_STRING)
+                */
+               public Void visit(OCTET_STRING data) {
+                       builder.append(new HexString(data.value()).toString());
+                       return null;
+               }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.NULL)
-        */
-       public Void visit(NULL data) {
-               builder.append(NULL);
-               return null;
-       }
+               /*
+                * (non-Javadoc)
+                
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.NULL)
+                */
+               public Void visit(NULL data) {
+                       builder.append(NULL);
+                       return null;
+               }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.SEQUENCE)
-        */
-       public Void visit(SEQUENCE data) {
-               writeConstructive(data);
-               return null;
-       }
+               /*
+                * (non-Javadoc)
+                
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.SEQUENCE)
+                */
+               public Void visit(SEQUENCE data) {
+                       writeConstructive(data);
+                       return null;
+               }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.SEQUENCE_OF)
-        */
-       public Void visit(SEQUENCE_OF<?> data) {
-               writeCollection(data);
-               return null;
-       }
+               /*
+                * (non-Javadoc)
+                
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.SEQUENCE_OF)
+                */
+               public Void visit(SEQUENCE_OF<?> data) {
+                       writeCollection(data);
+                       return null;
+               }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.SET)
-        */
-       public Void visit(SET data) {
-               writeConstructive(data);
-               return null;
-       }
+               /*
+                * (non-Javadoc)
+                
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.SET)
+                */
+               public Void visit(SET data) {
+                       writeConstructive(data);
+                       return null;
+               }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.SET_OF)
-        */
-       public Void visit(SET_OF<?> data) {
-               writeCollection(data);
-               return null;
-       }
+               /*
+                * (non-Javadoc)
+                
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.SET_OF)
+                */
+               public Void visit(SET_OF<?> data) {
+                       writeCollection(data);
+                       return null;
+               }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.CHOICE)
-        */
-       public Void visit(CHOICE data) {
-               indent();
-               if (!data.hasValue()) {
-                       builder.append(NOT_SET);
-               } else {
-                       builder.append(data.selectedIdentifier());
-                       if (data.selectedTag() != null) {
+               /*
+                * (non-Javadoc)
+                * 
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.CHOICE)
+                */
+               public Void visit(CHOICE data) {
+                       indent();
+                       if (!data.hasValue()) {
+                               builder.append(NOT_SET);
+                       } else {
+                               builder.append(data.selectedIdentifier());
+                               if (data.selectedTag() != null) {
+                                       builder.append(SEPARATOR);
+                                       writeTag(data.selectedTag());
+                               }
                                builder.append(SEPARATOR);
-                               writeTag(data.selectedTag());
+                               write(data.selectedValue());
                        }
-                       builder.append(SEPARATOR);
-                       write(data.selectedValue());
+                       return null;
                }
-               return null;
-       }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.OBJECT_IDENTIFIER)
-        */
-       public Void visit(OBJECT_IDENTIFIER data) {
-               builder.append(OID_OPEN);
-               if (data.value().size() > 0) {
-                       builder.append(SPACE).append(data.value().get(0));
-                       for (int i = 1; i < data.value().size(); i++) {
-                               builder.append('.').append(data.value().get(i));
+               /*
+                * (non-Javadoc)
+                * 
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.OBJECT_IDENTIFIER)
+                */
+               public Void visit(OBJECT_IDENTIFIER data) {
+                       builder.append(OID_OPEN);
+                       if (data.value().size() > 0) {
+                               builder.append(SPACE).append(data.value().get(0));
+                               for (int i = 1; i < data.value().size(); i++) {
+                                       builder.append('.').append(data.value().get(i));
+                               }
+                               builder.append(SPACE);
                        }
-                       builder.append(SPACE);
+                       builder.append(OID_CLOSE);
+                       return null;
                }
-               builder.append(OID_CLOSE);
-               return null;
-       }
-       
-       /* (non-Javadoc)
-        * @see jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type.builtin.RELATIVE_OID)
-        */
-       public Void visit(RELATIVE_OID data) {
-               return visit((OBJECT_IDENTIFIER)data);
-       }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .StringType)
-        */
-       public Void visit(StringType data) {
-               try {
-                       String value = data.stringValue();
-                       builder.append(STRING_OPEN).append(value).append(STRING_CLOSE);
-               } catch (Exception e) {
-                       builder.append(new HexString(data.value()).toString());
+               /* (non-Javadoc)
+                * @see jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type.builtin.RELATIVE_OID)
+                */
+               public Void visit(RELATIVE_OID data) {
+                       return visit((OBJECT_IDENTIFIER)data);
                }
-               return null;
-       }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .TimeType)
-        */
-       public Void visit(TimeType data) {
-               visit((StringType)data);
-               builder.append(SPACE).append(DATE_FORMAT.get().format(data.date()));
-               return null;
-       }
+               /*
+                * (non-Javadoc)
+                * 
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .StringType)
+                */
+               public Void visit(StringType data) {
+                       try {
+                               String value = data.stringValue();
+                               builder.append(STRING_OPEN).append(value).append(STRING_CLOSE);
+                       } catch (Exception e) {
+                               builder.append(new HexString(data.value()).toString());
+                       }
+                       return null;
+               }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .builtin.ANY)
-        */
-       public Void visit(ANY data) {
-               write(data.value());
-               return null;
-       }
+               /*
+                * (non-Javadoc)
+                * 
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .TimeType)
+                */
+               public Void visit(TimeType data) {
+                       visit((StringType)data);
+                       builder.append(SPACE).append(DATE_FORMAT.get().format(data.date()));
+                       return null;
+               }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
-        * .UnknownType)
-        */
-       public Void visit(UnknownType data) {
-               for (int i = 0; i < data.value().length; i++) {
-                       if (i % 16 == 0) {
-                               indent();
-                       }
-                       builder.append(String.format("%02X", data.value()[i]));
-                       builder.append(i % 16 == 15 ? NEW_LINE : SPACE);
+               /*
+                * (non-Javadoc)
+                * 
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .builtin.ANY)
+                */
+               public Void visit(ANY data) {
+                       write(data.value());
+                       return null;
                }
-               return null;
-       }
 
-       /**
-        * Writes descriptions of each element of {@code ConstructiveType}.
-        * 
-        * @param data
-        *            The constructive data.
-        */
-       private void writeConstructive(ConstructiveType data) {
-               ElementSpecification[] elements = data.getElementTypeList();
-               for (int i = 0; i < elements.length; i++) {
-                       if (i != 0) {
-                               builder.append(CONSTRUCTIVE_SEPARATOR);
-                       }
-                       indent();
-                       builder.append(elements[i].identifier()).append(SEPARATOR);
-                       if (elements[i].tag() != null) {
-                               writeTag(elements[i].tag());
-                               builder.append(SEPARATOR);
-                       }
-                       ASN1Type element = data.getComponent(elements[i]);
-                       if (element == null) {
-                               builder.append(NOT_SET);
-                       } else {
-                               write(element);
-                       }
-                       if (elements[i].optional()) {
-                               builder.append(OPTIONAL);
+               /*
+                * (non-Javadoc)
+                * 
+                * @see
+                * jp.bitmeister.asn1.processor.ASN1Visitor#visit(jp.bitmeister.asn1.type
+                * .UnknownType)
+                */
+               public Void visit(UnknownType data) {
+                       for (int i = 0; i < data.value().length; i++) {
+                               if (i % 16 == 0) {
+                                       indent();
+                               }
+                               builder.append(String.format("%02X", data.value()[i]));
+                               builder.append(i % 16 == 15 ? NEW_LINE : SPACE);
                        }
+                       return null;
                }
-       }
 
-       /**
-        * Writes descriptions of each member of {@code CollectionType}.
-        * 
-        * @param data
-        *            The collection data.
-        */
-       private void writeCollection(CollectionType<? extends ASN1Type, ?> data) {
-               Iterator<? extends ASN1Type> itr = data.collection().iterator();
-               if (itr.hasNext()) {
-                       while (true) {
+               /**
+                * Writes descriptions of each element of {@code ConstructiveType}.
+                * 
+                * @param data
+                *            The constructive data.
+                */
+               private void writeConstructive(ConstructiveType data) {
+                       ElementSpecification[] elements = data.getElementTypeList();
+                       for (int i = 0; i < elements.length; i++) {
+                               if (i != 0) {
+                                       builder.append(CONSTRUCTIVE_SEPARATOR);
+                               }
                                indent();
-                               write(itr.next());
-                               if (!itr.hasNext()) {
-                                       return;
+                               builder.append(elements[i].identifier()).append(SEPARATOR);
+                               if (elements[i].tag() != null) {
+                                       writeTag(elements[i].tag());
+                                       builder.append(SEPARATOR);
+                               }
+                               ASN1Type element = data.getComponent(elements[i]);
+                               if (element == null) {
+                                       builder.append(NOT_SET);
+                               } else {
+                                       write(element);
+                               }
+                               if (elements[i].optional()) {
+                                       builder.append(OPTIONAL);
                                }
-                               builder.append(CONSTRUCTIVE_SEPARATOR);
                        }
                }
-               indent();
-               builder.append(NOT_SET);
-       }
 
-       /**
-        * Writes tag description.
-        * 
-        * @param tag
-        *            The tag.
-        */
-       private void writeTag(ASN1TagValue tag) {
-               builder.append(TAG_OPEN);
-               if (tag.tagClass() != ASN1TagClass.CONTEXT_SPECIFIC) {
-                       builder.append(tag.tagClass()).append(SPACE);
+               /**
+                * Writes descriptions of each member of {@code CollectionType}.
+                * 
+                * @param data
+                *            The collection data.
+                */
+               private void writeCollection(CollectionType<? extends ASN1Type, ?> data) {
+                       Iterator<? extends ASN1Type> itr = data.collection().iterator();
+                       if (itr.hasNext()) {
+                               while (true) {
+                                       indent();
+                                       write(itr.next());
+                                       if (!itr.hasNext()) {
+                                               return;
+                                       }
+                                       builder.append(CONSTRUCTIVE_SEPARATOR);
+                               }
+                       }
+                       indent();
+                       builder.append(NOT_SET);
                }
-               builder.append(tag.tagNumber()).append(TAG_CLOSE);
-               if (tag.tagMode() == ASN1TagMode.IMPLICIT) {
-                       builder.append(IMPLICIT);
+
+               /**
+                * Writes tag description.
+                * 
+                * @param tag
+                *            The tag.
+                */
+               private void writeTag(ASN1TagValue tag) {
+                       builder.append(TAG_OPEN);
+                       if (tag.tagClass() != ASN1TagClass.CONTEXT_SPECIFIC) {
+                               builder.append(tag.tagClass()).append(SPACE);
+                       }
+                       builder.append(tag.tagNumber()).append(TAG_CLOSE);
+                       if (tag.tagMode() == ASN1TagMode.IMPLICIT) {
+                               builder.append(IMPLICIT);
+                       }
                }
-       }
 
-       /**
-        * Writes indents.
-        */
-       private void indent() {
-               for (int i = 0; i < indent; i++) {
-                       builder.append(INDENT);
+               /**
+                * Writes indents.
+                */
+               private void indent() {
+                       for (int i = 0; i < indent; i++) {
+                               builder.append(INDENT);
+                       }
                }
+               
        }
-
+       
 }