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}