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