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