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}