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 * https://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.intermediate.syncrepl; 021 022 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.List; 026 027import org.apache.directory.api.i18n.I18n; 028import org.apache.directory.api.ldap.model.message.IntermediateResponseImpl; 029import org.apache.directory.api.util.Strings; 030 031 032/** 033 * A simple {@link SyncInfoValue} implementation to store response properties. 034 * 035 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 036 * @version $Rev$, $Date$ 037 */ 038public class SyncInfoValueImpl extends IntermediateResponseImpl implements SyncInfoValue 039{ 040 /** The kind of syncInfoValue we are dealing with */ 041 private SynchronizationInfoEnum type; 042 043 /** The cookie */ 044 private byte[] cookie; 045 046 /** The refreshDone flag if we are dealing with refreshXXX syncInfo. Default to true */ 047 private boolean refreshDone = true; 048 049 /** The refreshDeletes flag if we are dealing with syncIdSet syncInfo. Defaults to false */ 050 private boolean refreshDeletes = false; 051 052 /** The list of UUIDs if we are dealing with syncIdSet syncInfo */ 053 private List<byte[]> syncUUIDs; 054 055 056 /** 057 * Creates a new instance of SyncInfoValueImpl. 058 */ 059 public SyncInfoValueImpl() 060 { 061 super( OID ); 062 } 063 064 065 /** 066 * {@inheritDoc} 067 */ 068 @Override 069 public byte[] getCookie() 070 { 071 return cookie; 072 } 073 074 075 /** 076 * {@inheritDoc} 077 */ 078 @Override 079 public void setCookie( byte[] cookie ) 080 { 081 this.cookie = cookie; 082 } 083 084 085 /** 086 * {@inheritDoc} 087 */ 088 @Override 089 public boolean isRefreshDone() 090 { 091 return refreshDone; 092 } 093 094 095 /** 096 * {@inheritDoc} 097 */ 098 @Override 099 public void setRefreshDone( boolean refreshDone ) 100 { 101 this.refreshDone = refreshDone; 102 } 103 104 105 /** 106 * {@inheritDoc} 107 */ 108 @Override 109 public boolean isRefreshDeletes() 110 { 111 return refreshDeletes; 112 } 113 114 115 /** 116 * {@inheritDoc} 117 */ 118 @Override 119 public void setRefreshDeletes( boolean refreshDeletes ) 120 { 121 this.refreshDeletes = refreshDeletes; 122 } 123 124 125 /** 126 * {@inheritDoc} 127 */ 128 @Override 129 public List<byte[]> getSyncUUIDs() 130 { 131 if ( syncUUIDs == null ) 132 { 133 syncUUIDs = new ArrayList<>(); 134 } 135 136 return syncUUIDs; 137 } 138 139 140 /** 141 * {@inheritDoc} 142 */ 143 @Override 144 public void setSyncUUIDs( List<byte[]> syncUUIDs ) 145 { 146 this.syncUUIDs = syncUUIDs; 147 } 148 149 150 /** 151 * {@inheritDoc} 152 */ 153 @Override 154 public void addSyncUUID( byte[] syncUUID ) 155 { 156 if ( syncUUIDs == null ) 157 { 158 syncUUIDs = new ArrayList<>(); 159 } 160 161 syncUUIDs.add( syncUUID ); 162 } 163 164 165 /** 166 * @see Object#hashCode() 167 */ 168 @Override 169 public int hashCode() 170 { 171 int h = super.hashCode(); 172 173 h = h * 17 + type.getValue(); 174 h = h * 17 + ( refreshDone ? 1 : 0 ); 175 h = h * 17 + ( refreshDeletes ? 1 : 0 ); 176 177 if ( cookie != null ) 178 { 179 for ( byte b : cookie ) 180 { 181 h = h * 17 + b; 182 } 183 } 184 185 if ( syncUUIDs != null ) 186 { 187 for ( byte[] bytes : syncUUIDs ) 188 { 189 if ( bytes != null ) 190 { 191 for ( byte b : bytes ) 192 { 193 h = h * 17 + b; 194 } 195 } 196 } 197 } 198 199 return h; 200 } 201 202 203 /** 204 * @see Object#equals(Object) 205 */ 206 @Override 207 public boolean equals( Object o ) 208 { 209 if ( this == o ) 210 { 211 return true; 212 } 213 214 if ( !( o instanceof SyncInfoValue ) ) 215 { 216 return false; 217 } 218 219 SyncInfoValue otherResponse = ( SyncInfoValue ) o; 220 221 if ( syncUUIDs != null ) 222 { 223 if ( otherResponse.getSyncUUIDs() == null ) 224 { 225 return false; 226 } 227 228 // @TODO : this is extremely heavy... We have to find a better way to 229 // compare the lists of suncUuids, but atm, it's enough. 230 for ( byte[] syncUuid : syncUUIDs ) 231 { 232 boolean found = false; 233 234 for ( byte[] otherSyncUuid : otherResponse.getSyncUUIDs() ) 235 { 236 if ( Arrays.equals( syncUuid, otherSyncUuid ) ) 237 { 238 found = true; 239 break; 240 } 241 } 242 243 if ( !found ) 244 { 245 return false; 246 } 247 } 248 } 249 else 250 { 251 if ( otherResponse.getSyncUUIDs() != null ) 252 { 253 return false; 254 } 255 } 256 257 return super.equals( o ) 258 && ( refreshDeletes == otherResponse.isRefreshDeletes() ) 259 && ( refreshDone == otherResponse.isRefreshDone() ) 260 && ( Arrays.equals( cookie, otherResponse.getCookie() ) ); 261 } 262 263 264 /** 265 * @see Object#toString() 266 */ 267 @Override 268 public String toString() 269 { 270 StringBuilder sb = new StringBuilder(); 271 272 sb.append( " SyncInfoValue :\n" ); 273 274 switch ( type ) 275 { 276 case NEW_COOKIE: 277 sb.append( " newCookie : '" ). 278 append( Strings.utf8ToString( getCookie() ) ).append( "'\n" ); 279 break; 280 281 case REFRESH_DELETE: 282 sb.append( " refreshDelete : \n" ); 283 284 if ( getCookie() != null ) 285 { 286 sb.append( " cookie : '" ). 287 append( Strings.dumpBytes( getCookie() ) ).append( "'\n" ); 288 } 289 290 sb.append( " refreshDone : " ).append( isRefreshDone() ).append( '\n' ); 291 break; 292 293 case REFRESH_PRESENT: 294 sb.append( " refreshPresent : \n" ); 295 296 if ( getCookie() != null ) 297 { 298 sb.append( " cookie : '" ). 299 append( Strings.dumpBytes( getCookie() ) ).append( "'\n" ); 300 } 301 302 sb.append( " refreshDone : " ).append( isRefreshDone() ).append( '\n' ); 303 break; 304 305 case SYNC_ID_SET: 306 sb.append( " syncIdSet : \n" ); 307 308 if ( getCookie() != null ) 309 { 310 sb.append( " cookie : '" ). 311 append( Strings.dumpBytes( getCookie() ) ).append( "'\n" ); 312 } 313 314 sb.append( " refreshDeletes : " ).append( isRefreshDeletes() ).append( '\n' ); 315 sb.append( " syncUUIDS : " ); 316 317 if ( !getSyncUUIDs().isEmpty() ) 318 { 319 boolean isFirst = true; 320 321 for ( byte[] syncUUID : getSyncUUIDs() ) 322 { 323 if ( isFirst ) 324 { 325 isFirst = false; 326 } 327 else 328 { 329 sb.append( ", " ); 330 } 331 332 sb.append( Arrays.toString( syncUUID ) ); 333 } 334 335 sb.append( '\n' ); 336 } 337 else 338 { 339 sb.append( "empty\n" ); 340 } 341 342 break; 343 344 default: 345 throw new IllegalArgumentException( I18n.err( I18n.ERR_9300_UNEXPECTED_SYNCINFO, getType() ) ); 346 } 347 348 return sb.toString(); 349 } 350 351 352 @Override 353 public SynchronizationInfoEnum getSyncInfoValueType() 354 { 355 return type; 356 } 357 358 359 @Override 360 public void setSyncInfoValueType( SynchronizationInfoEnum type ) 361 { 362 this.type = type; 363 } 364}