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