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