001    /*
002     * Copyright 2007-2014 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2014 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.asn1;
022    
023    
024    
025    
026    import static com.unboundid.asn1.ASN1Constants.*;
027    import static com.unboundid.asn1.ASN1Messages.*;
028    import static com.unboundid.util.Debug.*;
029    
030    
031    
032    /**
033     * This class provides an ASN.1 Boolean element, whose value is a single byte
034     * and represents either "TRUE" or "FALSE".  A value whose only byte is 0x00 is
035     * considered "false", while any other single-byte value is considered "true".
036     */
037    public final class ASN1Boolean
038           extends ASN1Element
039    {
040      /**
041       * A pre-allocated ASN.1 Boolean element with the universal Boolean BER type
042       * and a value of "FALSE".
043       */
044      public static final ASN1Boolean UNIVERSAL_BOOLEAN_FALSE_ELEMENT =
045             new ASN1Boolean(false);
046    
047    
048    
049      /**
050       * A pre-allocated ASN.1 Boolean element with the universal Boolean BER type
051       * and a value of "TRUE".
052       */
053      public static final ASN1Boolean UNIVERSAL_BOOLEAN_TRUE_ELEMENT =
054             new ASN1Boolean(true);
055    
056    
057    
058      /**
059       * The serial version UID for this serializable class.
060       */
061      private static final long serialVersionUID = 7131700816847855524L;
062    
063    
064    
065      // The boolean value for this element.
066      private final boolean booleanValue;
067    
068    
069    
070      /**
071       * Creates a new ASN.1 Boolean element with the default BER type and the
072       * provided boolean value.
073       *
074       * @param  booleanValue  The boolean value to use for this element.
075       */
076      public ASN1Boolean(final boolean booleanValue)
077      {
078        super(UNIVERSAL_BOOLEAN_TYPE,
079              (booleanValue ? BOOLEAN_VALUE_TRUE : BOOLEAN_VALUE_FALSE));
080    
081        this.booleanValue = booleanValue;
082      }
083    
084    
085    
086      /**
087       * Creates a new ASN.1 Boolean element with the specified BER type and the
088       * provided boolean value.
089       *
090       * @param  type          The BER type to use for this element.
091       * @param  booleanValue  The boolean value to use for this element.
092       */
093      public ASN1Boolean(final byte type, final boolean booleanValue)
094      {
095        super(type, (booleanValue ? BOOLEAN_VALUE_TRUE : BOOLEAN_VALUE_FALSE));
096    
097        this.booleanValue = booleanValue;
098      }
099    
100    
101    
102      /**
103       * Creates a new ASN.1 Boolean element with the provided information.
104       *
105       * @param  type          The BER type to use for this element.
106       * @param  booleanValue  The boolean value to use for this element.
107       * @param  value         The pre-encoded value to use for this element.
108       */
109      private ASN1Boolean(final byte type, final boolean booleanValue,
110                          final byte[] value)
111      {
112        super(type, value);
113    
114        this.booleanValue = booleanValue;
115      }
116    
117    
118    
119      /**
120       * Retrieves the boolean value for this element.
121       *
122       * @return  {@code true} if this element has a value of "TRUE", or
123       *          {@code false} if it has a value of "FALSE".
124       */
125      public boolean booleanValue()
126      {
127        return booleanValue;
128      }
129    
130    
131    
132      /**
133       * Decodes the contents of the provided byte array as a Boolean element.
134       *
135       * @param  elementBytes  The byte array to decode as an ASN.1 Boolean element.
136       *
137       * @return  The decoded ASN.1 Boolean element.
138       *
139       * @throws  ASN1Exception  If the provided array cannot be decoded as a
140       *                         Boolean element.
141       */
142      public static ASN1Boolean decodeAsBoolean(final byte[] elementBytes)
143             throws ASN1Exception
144      {
145        try
146        {
147          int valueStartPos = 2;
148          int length = (elementBytes[1] & 0x7F);
149          if (length != elementBytes[1])
150          {
151            final int numLengthBytes = length;
152    
153            length = 0;
154            for (int i=0; i < numLengthBytes; i++)
155            {
156              length <<= 8;
157              length |= (elementBytes[valueStartPos++] & 0xFF);
158            }
159          }
160    
161          if ((elementBytes.length - valueStartPos) != length)
162          {
163            throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length,
164                                         (elementBytes.length - valueStartPos)));
165          }
166    
167          if (length != 1)
168          {
169            throw new ASN1Exception(ERR_BOOLEAN_INVALID_LENGTH.get());
170          }
171    
172          final byte[] value = { elementBytes[valueStartPos] };
173          final boolean booleanValue = (value[0] != 0x00);
174          return new ASN1Boolean(elementBytes[0], booleanValue, value);
175        }
176        catch (final ASN1Exception ae)
177        {
178          debugException(ae);
179          throw ae;
180        }
181        catch (final Exception e)
182        {
183          debugException(e);
184          throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e);
185        }
186      }
187    
188    
189    
190      /**
191       * Decodes the provided ASN.1 element as a Boolean element.
192       *
193       * @param  element  The ASN.1 element to be decoded.
194       *
195       * @return  The decoded ASN.1 Boolean element.
196       *
197       * @throws  ASN1Exception  If the provided element cannot be decoded as a
198       *                         Boolean element.
199       */
200      public static ASN1Boolean decodeAsBoolean(final ASN1Element element)
201             throws ASN1Exception
202      {
203        final byte[] value = element.getValue();
204        if (value.length != 1)
205        {
206          throw new ASN1Exception(ERR_BOOLEAN_INVALID_LENGTH.get());
207        }
208    
209        if (value[0] == 0x00)
210        {
211          return new ASN1Boolean(element.getType(), false, value);
212        }
213        else
214        {
215          return new ASN1Boolean(element.getType(), true, value);
216        }
217      }
218    
219    
220    
221      /**
222       * Appends a string representation of this ASN.1 element to the provided
223       * buffer.
224       *
225       * @param  buffer  The buffer to which to append the information.
226       */
227      @Override
228      public void toString(final StringBuilder buffer)
229      {
230        buffer.append(booleanValue);
231      }
232    }