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 }