001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue; 021 022 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.List; 026 027import org.apache.directory.api.ldap.model.message.controls.AbstractControl; 028import org.apache.directory.api.util.Strings; 029 030 031/** 032 * A simple {@link SyncInfoValue} implementation to store control properties. 033 * 034 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 035 * @version $Rev$, $Date$ 036 */ 037public class SyncInfoValueImpl extends AbstractControl implements SyncInfoValue 038{ 039 /** The kind of syncInfoValue we are dealing with */ 040 private SynchronizationInfoEnum type; 041 042 /** The cookie */ 043 private byte[] cookie; 044 045 /** The refreshDone flag if we are dealing with refreshXXX syncInfo. Default to true */ 046 private boolean refreshDone = true; 047 048 /** The refreshDeletes flag if we are dealing with syncIdSet syncInfo. Defaults to false */ 049 private boolean refreshDeletes = false; 050 051 /** The list of UUIDs if we are dealing with syncIdSet syncInfo */ 052 private List<byte[]> syncUUIDs; 053 054 055 /** 056 * Creates a new instance of SyncInfoValueImpl. 057 */ 058 public SyncInfoValueImpl() 059 { 060 super( OID ); 061 } 062 063 064 /** 065 * 066 * Creates a new instance of SyncInfoValueImpl. 067 * 068 * @param isCritical The critical flag 069 */ 070 public SyncInfoValueImpl( boolean isCritical ) 071 { 072 super( OID, isCritical ); 073 } 074 075 076 /** 077 * {@inheritDoc} 078 */ 079 @Override 080 public SynchronizationInfoEnum getType() 081 { 082 return type; 083 } 084 085 086 /** 087 * {@inheritDoc} 088 */ 089 @Override 090 public void setType( SynchronizationInfoEnum type ) 091 { 092 this.type = type; 093 } 094 095 096 /** 097 * {@inheritDoc} 098 */ 099 @Override 100 public byte[] getCookie() 101 { 102 return cookie; 103 } 104 105 106 /** 107 * {@inheritDoc} 108 */ 109 @Override 110 public void setCookie( byte[] cookie ) 111 { 112 this.cookie = cookie; 113 } 114 115 116 /** 117 * {@inheritDoc} 118 */ 119 @Override 120 public boolean isRefreshDone() 121 { 122 return refreshDone; 123 } 124 125 126 /** 127 * {@inheritDoc} 128 */ 129 @Override 130 public void setRefreshDone( boolean refreshDone ) 131 { 132 this.refreshDone = refreshDone; 133 } 134 135 136 /** 137 * {@inheritDoc} 138 */ 139 @Override 140 public boolean isRefreshDeletes() 141 { 142 return refreshDeletes; 143 } 144 145 146 /** 147 * {@inheritDoc} 148 */ 149 @Override 150 public void setRefreshDeletes( boolean refreshDeletes ) 151 { 152 this.refreshDeletes = refreshDeletes; 153 } 154 155 156 /** 157 * {@inheritDoc} 158 */ 159 @Override 160 public List<byte[]> getSyncUUIDs() 161 { 162 return syncUUIDs; 163 } 164 165 166 /** 167 * {@inheritDoc} 168 */ 169 @Override 170 public void setSyncUUIDs( List<byte[]> syncUUIDs ) 171 { 172 this.syncUUIDs = syncUUIDs; 173 } 174 175 176 /** 177 * {@inheritDoc} 178 */ 179 @Override 180 public void addSyncUUID( byte[] syncUUID ) 181 { 182 if ( syncUUIDs == null ) 183 { 184 syncUUIDs = new ArrayList<>(); 185 } 186 187 syncUUIDs.add( syncUUID ); 188 } 189 190 191 /** 192 * @see Object#hashCode() 193 */ 194 @Override 195 public int hashCode() 196 { 197 int h = 37; 198 199 h = h * 17 + super.hashCode(); 200 h = h * 17 + type.getValue(); 201 h = h * 17 + ( refreshDone ? 1 : 0 ); 202 h = h * 17 + ( refreshDeletes ? 1 : 0 ); 203 204 if ( cookie != null ) 205 { 206 for ( byte b : cookie ) 207 { 208 h = h * 17 + b; 209 } 210 } 211 212 if ( syncUUIDs != null ) 213 { 214 for ( byte[] bytes : syncUUIDs ) 215 { 216 if ( bytes != null ) 217 { 218 for ( byte b : bytes ) 219 { 220 h = h * 17 + b; 221 } 222 } 223 } 224 } 225 226 return h; 227 } 228 229 230 /** 231 * @see Object#equals(Object) 232 */ 233 @Override 234 public boolean equals( Object o ) 235 { 236 if ( this == o ) 237 { 238 return true; 239 } 240 241 if ( !( o instanceof SyncInfoValue ) ) 242 { 243 return false; 244 } 245 246 SyncInfoValue otherControl = ( SyncInfoValue ) o; 247 248 if ( syncUUIDs != null ) 249 { 250 if ( otherControl.getSyncUUIDs() == null ) 251 { 252 return false; 253 } 254 255 // @TODO : this is extremely heavy... We have to find a better way to 256 // compare the lists of suncUuids, but atm, it's enough. 257 for ( byte[] syncUuid : syncUUIDs ) 258 { 259 boolean found = false; 260 261 for ( byte[] otherSyncUuid : otherControl.getSyncUUIDs() ) 262 { 263 if ( Arrays.equals( syncUuid, otherSyncUuid ) ) 264 { 265 found = true; 266 break; 267 } 268 } 269 270 if ( !found ) 271 { 272 return false; 273 } 274 } 275 } 276 else 277 { 278 if ( otherControl.getSyncUUIDs() != null ) 279 { 280 return false; 281 } 282 } 283 284 return ( refreshDeletes == otherControl.isRefreshDeletes() ) 285 && ( refreshDone == otherControl.isRefreshDone() ) 286 && ( type == otherControl.getType() ) 287 && ( Arrays.equals( cookie, otherControl.getCookie() ) ) 288 && ( isCritical() == otherControl.isCritical() ); 289 } 290 291 292 /** 293 * @see Object#toString() 294 */ 295 @Override 296 public String toString() 297 { 298 StringBuilder sb = new StringBuilder(); 299 300 sb.append( " SyncInfoValue control :\n" ); 301 sb.append( " oid : " ).append( getOid() ).append( '\n' ); 302 sb.append( " critical : " ).append( isCritical() ).append( '\n' ); 303 304 switch ( getType() ) 305 { 306 case NEW_COOKIE: 307 sb.append( " newCookie : '" ). 308 append( Strings.utf8ToString( getCookie() ) ).append( "'\n" ); 309 break; 310 311 case REFRESH_DELETE: 312 sb.append( " refreshDelete : \n" ); 313 314 if ( getCookie() != null ) 315 { 316 sb.append( " cookie : '" ). 317 append( Strings.dumpBytes( getCookie() ) ).append( "'\n" ); 318 } 319 320 sb.append( " refreshDone : " ).append( isRefreshDone() ).append( '\n' ); 321 break; 322 323 case REFRESH_PRESENT: 324 sb.append( " refreshPresent : \n" ); 325 326 if ( getCookie() != null ) 327 { 328 sb.append( " cookie : '" ). 329 append( Strings.dumpBytes( getCookie() ) ).append( "'\n" ); 330 } 331 332 sb.append( " refreshDone : " ).append( isRefreshDone() ).append( '\n' ); 333 break; 334 335 case SYNC_ID_SET: 336 sb.append( " syncIdSet : \n" ); 337 338 if ( getCookie() != null ) 339 { 340 sb.append( " cookie : '" ). 341 append( Strings.dumpBytes( getCookie() ) ).append( "'\n" ); 342 } 343 344 sb.append( " refreshDeletes : " ).append( isRefreshDeletes() ).append( '\n' ); 345 sb.append( " syncUUIDS : " ); 346 347 if ( !getSyncUUIDs().isEmpty() ) 348 { 349 boolean isFirst = true; 350 351 for ( byte[] syncUUID : getSyncUUIDs() ) 352 { 353 if ( isFirst ) 354 { 355 isFirst = false; 356 } 357 else 358 { 359 sb.append( ", " ); 360 } 361 362 sb.append( Arrays.toString( syncUUID ) ); 363 } 364 365 sb.append( '\n' ); 366 } 367 else 368 { 369 sb.append( "empty\n" ); 370 } 371 372 break; 373 374 default: 375 throw new IllegalArgumentException( "Unexpected SynchronizationInfo: " + getType() ); 376 } 377 378 return sb.toString(); 379 } 380}