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