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.model.message;
021
022
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.Collections;
026import java.util.Iterator;
027import java.util.List;
028
029
030/**
031 * A Referral implementation. For the time being this implementation uses a
032 * String representation for LDAPURLs. In the future an LdapUrl interface with
033 * default implementations will be used once a parser for an LdapUrl is created.
034 * 
035 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
036 */
037public class ReferralImpl implements Referral
038{
039    static final long serialVersionUID = 2638820668325359096L;
040
041    /** Sequence of LDAPUrls composing this Referral */
042    private final List<String> urls = new ArrayList<String>();
043
044    /** The encoded LdapURL */
045    private final List<byte[]> urlsBytes = new ArrayList<byte[]>();
046
047    /** The length of the referral */
048    private int referralLength;
049
050
051    // ------------------------------------------------------------------------
052    // LdapResult Interface Method Implementations
053    // ------------------------------------------------------------------------
054    /**
055     * {@inheritDoc}
056     */
057    public int getReferralLength()
058    {
059        return referralLength;
060    }
061
062
063    /**
064     * {@inheritDoc}
065     */
066    public void setReferralLength( int referralLength )
067    {
068        this.referralLength = referralLength;
069    }
070
071
072    /**
073     * Gets an unmodifiable set of alternative referral urls.
074     * 
075     * @return the alternative url objects.
076     */
077    public Collection<String> getLdapUrls()
078    {
079        return Collections.unmodifiableCollection( urls );
080    }
081
082
083    /**
084     * {@inheritDoc}
085     */
086    public Collection<byte[]> getLdapUrlsBytes()
087    {
088        return urlsBytes;
089    }
090
091
092    /**
093     * Adds an LDAPv3 URL to this Referral.
094     * 
095     * @param url the LDAPv3 URL to add
096     */
097    public void addLdapUrl( String url )
098    {
099        urls.add( url );
100    }
101
102
103    /**
104     * {@inheritDoc}
105     */
106    public void addLdapUrlBytes( byte[] urlBytes )
107    {
108        urlsBytes.add( urlBytes );
109    }
110
111
112    /**
113     * Removes an LDAPv3 URL to this Referral.
114     * 
115     * @param url
116     *            the LDAPv3 URL to remove
117     */
118    public void removeLdapUrl( String url )
119    {
120        urls.remove( url );
121    }
122
123
124    /**
125     * @see Object#hashCode()
126     * @return the instance's hash code 
127     */
128    public int hashCode()
129    {
130        int hash = 37;
131        hash = hash * 17 + urls.size();
132
133        // Order doesn't matter, so just add the url hashCode
134        for ( String url : urls )
135        {
136            hash = hash + url.hashCode();
137        }
138
139        return hash;
140    }
141
142
143    /**
144     * Compares this Referral implementation to see if it is the same as
145     * another. The classes do not have to be the same implementation to return
146     * true. Both this and the compared Referral must have the same entries
147     * exactly. The order of Referral URLs does not matter.
148     * 
149     * @param obj
150     *            the object to compare this ReferralImpl to
151     * @return true if both implementations contain exactly the same URLs
152     */
153    public boolean equals( Object obj )
154    {
155        // just in case for speed return true if obj is this object
156        if ( obj == this )
157        {
158            return true;
159        }
160
161        if ( obj instanceof Referral )
162        {
163            Collection<String> refs = ( ( Referral ) obj ).getLdapUrls();
164
165            // if their sizes do not match they are not equal
166            if ( refs.size() != urls.size() )
167            {
168                return false;
169            }
170
171            Iterator<String> list = urls.iterator();
172
173            while ( list.hasNext() )
174            {
175                // if one of our urls is not contained in the obj return false
176                if ( !refs.contains( list.next() ) )
177                {
178                    return false;
179                }
180            }
181
182            // made it through the checks so we have a match
183            return true;
184        }
185
186        return false;
187    }
188
189
190    /**
191     * Get a String representation of a Referral
192     * 
193     * @return A Referral String
194     */
195    public String toString()
196    {
197        StringBuffer sb = new StringBuffer();
198
199        if ( ( urls != null ) && ( urls.size() != 0 ) )
200        {
201            sb.append( "            Referrals :\n" );
202
203            Object[] urlsArray = urls.toArray();
204
205            for ( int i = 0; i < urlsArray.length; i++ )
206            {
207
208                String referral = ( String ) urlsArray[i];
209
210                sb.append( "                Referral[" ).append( i ).append( "] :" ).append( referral ).append( '\n' );
211            }
212        }
213
214        return sb.toString();
215    }
216}