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}