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