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