1    package org.bouncycastle.asn1;
2    
3    import java.io.*;
4    import java.util.*;
5    
6    abstract public class ASN1Set
7        extends DERObject
8    {
9        protected Vector set = new Vector();
10   
11       /**
12        * return an ASN1Set from the given object.
13        *
14        * @param obj the object we want converted.
15        * @exception IllegalArgumentException if the object cannot be converted.
16        */
17       public static ASN1Set getInstance(
18           Object  obj)
19       {
20           if (obj == null || obj instanceof ASN1Set)
21           {
22               return (ASN1Set)obj;
23           }
24   
25           throw new IllegalArgumentException("unknown object in getInstance");
26       }
27   
28       /**
29        * Return an ASN1 set from a tagged object. There is a special
30        * case here, if an object appears to have been explicitly tagged on 
31        * reading but we were expecting it to be implictly tagged in the 
32        * normal course of events it indicates that we lost the surrounding
33        * set - so we need to add it back (this will happen if the tagged
34        * object is a sequence that contains other sequences). If you are
35        * dealing with implicitly tagged sets you really <b>should</b>
36        * be using this method.
37        *
38        * @param obj the tagged object.
39        * @param explicit true if the object is meant to be explicitly tagged
40        *          false otherwise.
41        * @exception IllegalArgumentException if the tagged object cannot
42        *          be converted.
43        */
44       public static ASN1Set getInstance(
45           ASN1TaggedObject    obj,
46           boolean             explicit)
47       {
48           if (explicit)
49           {
50               if (!obj.isExplicit())
51               {
52                   throw new IllegalArgumentException("object implicit - explicit expected.");
53               }
54   
55               return (ASN1Set)obj.getObject();
56           }
57           else
58           {
59               //
60               // constructed object which appears to be explicitly tagged
61               // and it's really implicit means we have to add the
62               // surrounding sequence.
63               //
64               if (obj.isExplicit())
65               {
66                   ASN1Set    set = new DERSet(obj.getObject());
67   
68                   return set;
69               }
70               else
71               {
72                   //
73                   // in this case the parser returns a sequence, convert it
74                   // into a set.
75                   //
76                   DEREncodableVector  v = new DEREncodableVector();
77   
78                   if (obj.getObject() instanceof ASN1Sequence)
79                   {
80                       ASN1Sequence s = (ASN1Sequence)obj.getObject();
81                       Enumeration e = s.getObjects();
82   
83                       while (e.hasMoreElements())
84                       {
85                           v.add((DEREncodable)e.nextElement());
86                       }
87   
88                       return new DERSet(v);
89                   }
90               }
91           }
92   
93           throw new IllegalArgumentException(
94                       "unknown object in getInstanceFromTagged");
95       }
96   
97       public ASN1Set()
98       {
99       }
100  
101      public Enumeration getObjects()
102      {
103          return set.elements();
104      }
105  
106      /**
107       * return the object at the set postion indicated by index.
108       *
109       * @param the set number (starting at zero) of the object
110       * @return the object at the set postion indicated by index.
111       */
112      public DEREncodable getObjectAt(
113          int index)
114      {
115          return (DEREncodable)set.elementAt(index);
116      }
117  
118      /**
119       * return the number of objects in this set.
120       *
121       * @return the number of objects in this set.
122       */
123      public int size()
124      {
125          return set.size();
126      }
127  
128      public int hashCode()
129      {
130          Enumeration             e = this.getObjects();
131          int                     hashCode = 0;
132  
133          while (e.hasMoreElements())
134          {
135              hashCode ^= e.nextElement().hashCode();
136          }
137  
138          return hashCode;
139      }
140  
141      public boolean equals(
142          Object  o)
143      {
144          if (o == null || !(o instanceof ASN1Set))
145          {
146              return false;
147          }
148  
149          ASN1Set   other = (ASN1Set)o;
150  
151          if (this.size() != other.size())
152          {
153              return false;
154          }
155  
156          Enumeration s1 = this.getObjects();
157          Enumeration s2 = other.getObjects();
158  
159          while (s1.hasMoreElements())
160          {
161              if (!s1.nextElement().equals(s2.nextElement()))
162              {
163                  return false;
164              }
165          }
166  
167          return true;
168      }
169  
170      protected void addObject(
171          DEREncodable obj)
172      {
173          set.addElement(obj);
174      }
175  
176      abstract void encode(DEROutputStream out)
177              throws IOException;
178  }
179