1package org.bouncycastle.asn1.cms;
2
3import org.bouncycastle.asn1.ASN1Encodable;
4import org.bouncycastle.asn1.ASN1EncodableVector;
5import org.bouncycastle.asn1.ASN1Object;
6import org.bouncycastle.asn1.ASN1ObjectIdentifier;
7import org.bouncycastle.asn1.ASN1Primitive;
8import org.bouncycastle.asn1.ASN1Sequence;
9import org.bouncycastle.asn1.ASN1Set;
10import org.bouncycastle.asn1.DERObjectIdentifier;
11import org.bouncycastle.asn1.DERSequence;
12
13/**
14 * <a href="http://tools.ietf.org/html/rfc5652#page-14">RFC 5652</a>:
15 * Attribute is a pair of OID (as type identifier) + set of values.
16 * <p>
17 * <pre>
18 * Attribute ::= SEQUENCE {
19 *     attrType OBJECT IDENTIFIER,
20 *     attrValues SET OF AttributeValue
21 * }
22 *
23 * AttributeValue ::= ANY
24 * </pre>
25 * <p>
26 * General rule on values is that same AttributeValue must not be included
27 * multiple times into the set. That is, if the value is a SET OF INTEGERs,
28 * then having same value repeated is wrong: (1, 1), but different values is OK: (1, 2).
29 * Normally the AttributeValue syntaxes are more complicated than that.
30 * <p>
31 * General rule of Attribute usage is that the {@link Attributes} containers
32 * must not have multiple Attribute:s with same attrType (OID) there.
33 */
34public class Attribute
35    extends ASN1Object
36{
37    private ASN1ObjectIdentifier attrType;
38    private ASN1Set             attrValues;
39
40    /**
41     * Return an Attribute object from the given object.
42     * <p>
43     * Accepted inputs:
44     * <ul>
45     * <li> null &rarr; null
46     * <li> {@link Attribute} object
47     * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with Attribute structure inside
48     * </ul>
49     *
50     * @param o the object we want converted.
51     * @exception IllegalArgumentException if the object cannot be converted.
52     */
53    public static Attribute getInstance(
54        Object o)
55    {
56        if (o instanceof Attribute)
57        {
58            return (Attribute)o;
59        }
60
61        if (o != null)
62        {
63            return new Attribute(ASN1Sequence.getInstance(o));
64        }
65
66        return null;
67    }
68
69    private Attribute(
70        ASN1Sequence seq)
71    {
72        attrType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
73        attrValues = (ASN1Set)seq.getObjectAt(1);
74    }
75
76    /**
77     * @deprecated use ASN1ObjectIdentifier
78     */
79    public Attribute(
80        DERObjectIdentifier attrType,
81        ASN1Set             attrValues)
82    {
83        this.attrType = new ASN1ObjectIdentifier(attrType.getId());
84        this.attrValues = attrValues;
85    }
86
87    public Attribute(
88        ASN1ObjectIdentifier attrType,
89        ASN1Set             attrValues)
90    {
91        this.attrType = attrType;
92        this.attrValues = attrValues;
93    }
94
95    public ASN1ObjectIdentifier getAttrType()
96    {
97        return attrType;
98    }
99
100    public ASN1Set getAttrValues()
101    {
102        return attrValues;
103    }
104
105    public ASN1Encodable[] getAttributeValues()
106    {
107        return attrValues.toArray();
108    }
109
110    /**
111     * Produce an object suitable for an ASN1OutputStream.
112     */
113    public ASN1Primitive toASN1Primitive()
114    {
115        ASN1EncodableVector v = new ASN1EncodableVector();
116
117        v.add(attrType);
118        v.add(attrValues);
119
120        return new DERSequence(v);
121    }
122}
123