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 public SynchronizationInfoEnum getType() 080 { 081 return type; 082 } 083 084 085 /** 086 * {@inheritDoc} 087 */ 088 public void setType( SynchronizationInfoEnum type ) 089 { 090 this.type = type; 091 } 092 093 094 /** 095 * {@inheritDoc} 096 */ 097 public byte[] getCookie() 098 { 099 return cookie; 100 } 101 102 103 /** 104 * {@inheritDoc} 105 */ 106 public void setCookie( byte[] cookie ) 107 { 108 this.cookie = cookie; 109 } 110 111 112 /** 113 * {@inheritDoc} 114 */ 115 public boolean isRefreshDone() 116 { 117 return refreshDone; 118 } 119 120 121 /** 122 * {@inheritDoc} 123 */ 124 public void setRefreshDone( boolean refreshDone ) 125 { 126 this.refreshDone = refreshDone; 127 } 128 129 130 /** 131 * {@inheritDoc} 132 */ 133 public boolean isRefreshDeletes() 134 { 135 return refreshDeletes; 136 } 137 138 139 /** 140 * {@inheritDoc} 141 */ 142 public void setRefreshDeletes( boolean refreshDeletes ) 143 { 144 this.refreshDeletes = refreshDeletes; 145 } 146 147 148 /** 149 * {@inheritDoc} 150 */ 151 public List<byte[]> getSyncUUIDs() 152 { 153 return syncUUIDs; 154 } 155 156 157 /** 158 * {@inheritDoc} 159 */ 160 public void setSyncUUIDs( List<byte[]> syncUUIDs ) 161 { 162 this.syncUUIDs = syncUUIDs; 163 } 164 165 166 /** 167 * {@inheritDoc} 168 */ 169 public void addSyncUUID( byte[] syncUUID ) 170 { 171 if ( syncUUIDs == null ) 172 { 173 syncUUIDs = new ArrayList<byte[]>(); 174 } 175 176 syncUUIDs.add( syncUUID ); 177 } 178 179 180 /** 181 * @see Object#hashCode() 182 */ 183 @Override 184 public int hashCode() 185 { 186 int h = 37; 187 188 h = h * 17 + super.hashCode(); 189 h = h * 17 + type.getValue(); 190 h = h * 17 + ( refreshDone ? 1 : 0 ); 191 h = h * 17 + ( refreshDeletes ? 1 : 0 ); 192 193 if ( cookie != null ) 194 { 195 for ( byte b : cookie ) 196 { 197 h = h * 17 + b; 198 } 199 } 200 201 if ( syncUUIDs != null ) 202 { 203 for ( byte[] bytes : syncUUIDs ) 204 { 205 if ( bytes != null ) 206 { 207 for ( byte b : bytes ) 208 { 209 h = h * 17 + b; 210 } 211 } 212 } 213 } 214 215 return h; 216 } 217 218 219 /** 220 * @see Object#equals(Object) 221 */ 222 @Override 223 public boolean equals( Object o ) 224 { 225 if ( this == o ) 226 { 227 return true; 228 } 229 230 if ( !( o instanceof SyncInfoValue ) ) 231 { 232 return false; 233 } 234 235 SyncInfoValue otherControl = ( SyncInfoValue ) o; 236 237 if ( syncUUIDs != null ) 238 { 239 if ( otherControl.getSyncUUIDs() == null ) 240 { 241 return false; 242 } 243 244 // @TODO : this is extremely heavy... We have to find a better way to 245 // compare the lists of suncUuids, but atm, it's enough. 246 for ( byte[] syncUuid : syncUUIDs ) 247 { 248 boolean found = false; 249 250 for ( byte[] otherSyncUuid : otherControl.getSyncUUIDs() ) 251 { 252 if ( Arrays.equals( syncUuid, otherSyncUuid ) ) 253 { 254 found = true; 255 break; 256 } 257 } 258 259 if ( !found ) 260 { 261 return false; 262 } 263 } 264 } 265 else 266 { 267 if ( otherControl.getSyncUUIDs() != null ) 268 { 269 return false; 270 } 271 } 272 273 return ( refreshDeletes == otherControl.isRefreshDeletes() ) && 274 ( refreshDone == otherControl.isRefreshDone() ) && 275 ( type == otherControl.getType() ) && 276 ( Arrays.equals( cookie, otherControl.getCookie() ) && 277 ( isCritical() == otherControl.isCritical() ) ); 278 } 279 280 281 /** 282 * @see Object#toString() 283 */ 284 @Override 285 public String toString() 286 { 287 StringBuilder sb = new StringBuilder(); 288 289 sb.append( " SyncInfoValue control :\n" ); 290 sb.append( " oid : " ).append( getOid() ).append( '\n' ); 291 sb.append( " critical : " ).append( isCritical() ).append( '\n' ); 292 293 switch ( getType() ) 294 { 295 case NEW_COOKIE: 296 sb.append( " newCookie : '" ). 297 append( Strings.utf8ToString( getCookie() ) ).append( "'\n" ); 298 break; 299 300 case REFRESH_DELETE: 301 sb.append( " refreshDelete : \n" ); 302 303 if ( getCookie() != null ) 304 { 305 sb.append( " cookie : '" ). 306 append( Strings.dumpBytes( getCookie() ) ).append( "'\n" ); 307 } 308 309 sb.append( " refreshDone : " ).append( isRefreshDone() ).append( '\n' ); 310 break; 311 312 case REFRESH_PRESENT: 313 sb.append( " refreshPresent : \n" ); 314 315 if ( getCookie() != null ) 316 { 317 sb.append( " cookie : '" ). 318 append( Strings.dumpBytes( getCookie() ) ).append( "'\n" ); 319 } 320 321 sb.append( " refreshDone : " ).append( isRefreshDone() ).append( '\n' ); 322 break; 323 324 case SYNC_ID_SET: 325 sb.append( " syncIdSet : \n" ); 326 327 if ( getCookie() != null ) 328 { 329 sb.append( " cookie : '" ). 330 append( Strings.dumpBytes( getCookie() ) ).append( "'\n" ); 331 } 332 333 sb.append( " refreshDeletes : " ).append( isRefreshDeletes() ).append( '\n' ); 334 sb.append( " syncUUIDS : " ); 335 336 if ( getSyncUUIDs().size() != 0 ) 337 { 338 boolean isFirst = true; 339 340 for ( byte[] syncUUID : getSyncUUIDs() ) 341 { 342 if ( isFirst ) 343 { 344 isFirst = false; 345 } 346 else 347 { 348 sb.append( ", " ); 349 } 350 351 sb.append( Arrays.toString( syncUUID ) ); 352 } 353 354 sb.append( '\n' ); 355 } 356 else 357 { 358 sb.append( "empty\n" ); 359 } 360 361 break; 362 } 363 364 return sb.toString(); 365 } 366}