1    package org.bouncycastle.asn1;
2    
3    import java.io.*;
4    
5    /**
6     * ASN.1 TaggedObject - in ASN.1 nottation this is any object proceeded by
7     * a [n] where n is some number - these are assume to follow the construction
8     * rules (as with sequences).
9     */
10   public abstract class ASN1TaggedObject
11       extends DERObject
12   {
13       int             tagNo;
14       boolean         empty = false;
15       boolean         explicit = true;
16       DEREncodable    obj = null;
17   
18       /**
19        * @param tagNo the tag number for this object.
20        * @param obj the tagged object.
21        */
22       public ASN1TaggedObject(
23           int             tagNo,
24           DEREncodable    obj)
25       {
26           this.explicit = true;
27           this.tagNo = tagNo;
28           this.obj = obj;
29       }
30   
31       /**
32        * @param explicit true if the object is explicitly tagged.
33        * @param tagNo the tag number for this object.
34        * @param obj the tagged object.
35        */
36       public ASN1TaggedObject(
37           boolean         explicit,
38           int             tagNo,
39           DEREncodable    obj)
40       {
41           this.explicit = explicit;
42           this.tagNo = tagNo;
43           this.obj = obj;
44       }
45           
46           public boolean equals(
47                   Object o)
48           {
49           if (o == null || !(o instanceof ASN1TaggedObject))
50           {
51               return false;
52           }
53           
54           ASN1TaggedObject other = (ASN1TaggedObject)o;
55           
56           if(tagNo != other.tagNo || empty != other.empty || explicit != other.explicit)
57           {
58                           return false;
59                   }
60                   
61                   if(obj == null)
62                   {
63                           if(other.obj != null)
64                           {
65                                   return false;
66                           }
67                   }
68                   else
69                   {
70                           if(!(obj.equals(other.obj)))
71                           {
72                                   return false;
73                           }
74                   }
75                   
76                   return true;
77           }
78           
79       public int getTagNo()
80       {
81           return tagNo;
82       }
83   
84       /**
85        * return whether or not the object may be explicitly tagged. 
86        * <p>
87        * Note: if the object has been read from an input stream, the only
88        * time you can be sure if isExplicit is returning the true state of
89        * affairs is if it returns false. An implicitly tagged object may appear
90        * to be explicitly tagged, so you need to understand the context under
91        * which the reading was done as well, see getObject below.
92        */
93       public boolean isExplicit()
94       {
95           return explicit;
96       }
97   
98       public boolean isEmpty()
99       {
100          return empty;
101      }
102  
103      /**
104       * return whatever was following the tag.
105       * <p>
106       * Note: tagged objects are generally context dependent if you're
107       * trying to extract a tagged object you should be going via the
108       * appropriate getInstance method.
109       */
110      public DERObject getObject()
111      {
112          if (obj != null)
113          {
114              return obj.getDERObject();
115          }
116  
117          return null;
118      }
119  
120      abstract void encode(DEROutputStream  out)
121          throws IOException;
122  }
123