001/*
002 * Copyright 2011-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2011-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) 2011-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.ldap.sdk.unboundidds;
037
038
039
040import java.io.Serializable;
041import java.util.StringTokenizer;
042
043import com.unboundid.ldap.sdk.LDAPException;
044import com.unboundid.ldap.sdk.ResultCode;
045import com.unboundid.util.Debug;
046import com.unboundid.util.NotMutable;
047import com.unboundid.util.NotNull;
048import com.unboundid.util.Nullable;
049import com.unboundid.util.StaticUtils;
050import com.unboundid.util.ThreadSafety;
051import com.unboundid.util.ThreadSafetyLevel;
052
053import static com.unboundid.ldap.sdk.unboundidds.UnboundIDDSMessages.*;
054
055
056
057/**
058 * This class provides a data structure for holding information read from a
059 * value of the ds-changelog-attr-exceeded-max-values-count attribute.  Values
060 * should be in the form "attr=X,beforeCount=Y,afterCount=Z", where "X" is the
061 * name of the attribute which had too many values before and/or after the
062 * change, "Y" is the number of values the attribute had before the change, and
063 * "Z" is the number of values the attribute had after the change.
064 * <BR>
065 * <BLOCKQUOTE>
066 *   <B>NOTE:</B>  This class, and other classes within the
067 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
068 *   supported for use against Ping Identity, UnboundID, and
069 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
070 *   for proprietary functionality or for external specifications that are not
071 *   considered stable or mature enough to be guaranteed to work in an
072 *   interoperable way with other types of LDAP servers.
073 * </BLOCKQUOTE>
074 */
075@NotMutable()
076@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
077public final class ChangeLogEntryAttributeExceededMaxValuesCount
078       implements Serializable
079{
080  /**
081   * The name of the token used to provide the name of the associated attribute.
082   */
083  @NotNull private static final String TOKEN_NAME_ATTR = "attr";
084
085
086
087  /**
088   * The name of the token used to provide the number of values before the
089   * change.
090   */
091  @NotNull private static final String TOKEN_NAME_BEFORE_COUNT =
092       StaticUtils.toLowerCase("beforeCount");
093
094
095
096  /**
097   * The name of the token used to provide the number of values after the
098   * change.
099   */
100  @NotNull private static final String TOKEN_NAME_AFTER_COUNT =
101       StaticUtils.toLowerCase("afterCount");
102
103
104  /**
105   * The serial version UID for this serializable class.
106   */
107  private static final long serialVersionUID = -4689107630879614032L;
108
109
110
111  // The number of values the associated attribute had after the change.
112  private final long afterCount;
113
114  // The number of values the associated attribute had before the change.
115  private final long beforeCount;
116
117  // The name of the updated attribute for which the number of values exceeded
118  // the maximum display count before and/or after the change.
119  @NotNull private final String attributeName;
120
121  // The string representation for this element.
122  @NotNull private final String stringRepresentation;
123
124
125
126  /**
127   * Creates a new instance of this object from the provided string value from
128   * the ds-changelog-attr-exceeded-max-values-count.
129   *
130   * @param  s  The value to be parsed.
131   *
132   * @throws  LDAPException  If an error occurred while attempting to parse the
133   *                         value.
134   */
135  public ChangeLogEntryAttributeExceededMaxValuesCount(@NotNull final String s)
136         throws LDAPException
137  {
138    stringRepresentation = s;
139
140    String name   = null;
141    Long   before = null;
142    Long   after  = null;
143
144    final StringTokenizer tokenizer = new StringTokenizer(s, ",");
145    while (tokenizer.hasMoreTokens())
146    {
147      final String token = tokenizer.nextToken();
148      final int equalPos = token.indexOf('=');
149      if (equalPos < 0)
150      {
151        throw new LDAPException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
152             ERR_CHANGELOG_EXCEEDED_VALUE_COUNT_MALFORMED_TOKEN.get(s, token));
153      }
154
155      final String tokenName =
156           StaticUtils.toLowerCase(token.substring(0, equalPos).trim());
157      final String value = token.substring(equalPos+1).trim();
158
159      if (tokenName.equals(TOKEN_NAME_ATTR))
160      {
161        if (name == null)
162        {
163          name = value;
164        }
165        else
166        {
167          throw new LDAPException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
168               ERR_CHANGELOG_EXCEEDED_VALUE_COUNT_REPEATED_TOKEN.get(s,
169                    tokenName));
170        }
171      }
172      else if (tokenName.equals(TOKEN_NAME_BEFORE_COUNT))
173      {
174        if (before == null)
175        {
176          try
177          {
178            before = Long.parseLong(value);
179          }
180          catch (final Exception e)
181          {
182            Debug.debugException(e);
183            throw new LDAPException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
184                 ERR_CHANGELOG_EXCEEDED_VALUE_COUNT_MALFORMED_COUNT.get(s,
185                      tokenName),
186                 e);
187          }
188        }
189        else
190        {
191          throw new LDAPException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
192               ERR_CHANGELOG_EXCEEDED_VALUE_COUNT_REPEATED_TOKEN.get(s,
193                    tokenName));
194        }
195      }
196      else if (tokenName.equals(TOKEN_NAME_AFTER_COUNT))
197      {
198        if (after == null)
199        {
200          try
201          {
202            after = Long.parseLong(value);
203          }
204          catch (final Exception e)
205          {
206            Debug.debugException(e);
207            throw new LDAPException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
208                 ERR_CHANGELOG_EXCEEDED_VALUE_COUNT_REPEATED_TOKEN.get(s,
209                      tokenName),
210                 e);
211          }
212        }
213        else
214        {
215          throw new LDAPException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
216               ERR_CHANGELOG_EXCEEDED_VALUE_COUNT_REPEATED_TOKEN.get(s,
217                    tokenName));
218        }
219      }
220    }
221
222    if (name == null)
223    {
224      throw new LDAPException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
225           ERR_CHANGELOG_EXCEEDED_VALUE_COUNT_MISSING_TOKEN.get(s,
226                TOKEN_NAME_ATTR));
227    }
228
229    if (before == null)
230    {
231      throw new LDAPException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
232           ERR_CHANGELOG_EXCEEDED_VALUE_COUNT_MISSING_TOKEN.get(s,
233                TOKEN_NAME_BEFORE_COUNT));
234    }
235
236    if (after == null)
237    {
238      throw new LDAPException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
239           ERR_CHANGELOG_EXCEEDED_VALUE_COUNT_MISSING_TOKEN.get(s,
240                TOKEN_NAME_AFTER_COUNT));
241    }
242
243    attributeName = name;
244    beforeCount   = before;
245    afterCount    = after;
246  }
247
248
249
250  /**
251   * Retrieves the name of the attribute that exceeded the maximum number of
252   * values for inclusion in the ds-changelog-before-values and/or
253   * ds-changelog-after-values attribute of the changelog entry.
254   *
255   * @return  The name of the attribute that exceeded the maximum number of
256   *          values for inclusion in the ds-changelog-before-values and/or
257   *          ds-changelog-after-values attribute of the changelog entry.
258   */
259  @NotNull()
260  public String getAttributeName()
261  {
262    return attributeName;
263  }
264
265
266
267  /**
268   * Retrieves the number of values the specified attribute had in the
269   * target entry before the associated change was processed.
270   *
271   * @return  The number of values the specified attribute had in the target
272   *          entry before the associated change was processed, or zero if the
273   *          attribute was not present in the entry before the change.
274   */
275  public long getBeforeCount()
276  {
277    return beforeCount;
278  }
279
280
281
282  /**
283   * Retrieves the number of values the specified attribute had in the
284   * target entry after the associated change was processed.
285   *
286   * @return  The number of values the specified attribute had in the target
287   *          entry after the associated change was processed, or zero if the
288   *          attribute was not present in the entry after the change.
289   */
290  public long getAfterCount()
291  {
292    return afterCount;
293  }
294
295
296
297  /**
298   * Generates a hash code for this changelog attribute exceeded max values
299   * count object.
300   *
301   * @return  The generated hash code for this changelog attribute exceeded max
302   *          values count object.
303   */
304  @Override()
305  public int hashCode()
306  {
307    int hashCode = StaticUtils.toLowerCase(attributeName).hashCode();
308
309    hashCode = (int) ((hashCode * 31) + beforeCount);
310    hashCode = (int) ((hashCode * 31) + afterCount);
311
312    return hashCode;
313  }
314
315
316
317  /**
318   * Indicates whether the provided object is equal to this changelog attribute
319   * exceeded max values count object.
320   *
321   * @param  o  The object for which to make the determination.
322   *
323   * @return  {@code true} if the provided object may be considered equal to
324   *          this changelog attribute exceeded max values count object, or
325   *          {@code false} if not.
326   */
327  @Override()
328  public boolean equals(@Nullable final Object o)
329  {
330    if (o == null)
331    {
332      return false;
333    }
334
335    if (o == this)
336    {
337      return true;
338    }
339
340    if (! (o instanceof ChangeLogEntryAttributeExceededMaxValuesCount))
341    {
342      return false;
343    }
344
345    final ChangeLogEntryAttributeExceededMaxValuesCount c =
346         (ChangeLogEntryAttributeExceededMaxValuesCount) o;
347    return ((beforeCount == c.beforeCount) && (afterCount == c.afterCount) &&
348         attributeName.equalsIgnoreCase(c.attributeName));
349  }
350
351
352
353  /**
354   * Retrieves a string representation of this changelog entry attribute
355   * exceeded max values count.
356   *
357   * @return  A string representation of this changelog entry attribute exceeded
358   *          max values count.
359   */
360  @Override()
361  @NotNull()
362  public String toString()
363  {
364    return stringRepresentation;
365  }
366}