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 */
020
021package org.apache.directory.api.ldap.model.message;
022
023
024import org.apache.directory.api.ldap.model.name.Dn;
025
026
027/**
028 * The LdapResult implementation. RFC 4511 definition for a LdapResult is given below. <br>
029 * 
030 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
031 */
032public class LdapResultImpl implements LdapResult
033{
034    /** Lowest matched entry Dn - defaults to empty string */
035    private Dn matchedDn;
036
037    /** Referral associated with this LdapResult if the errorCode is REFERRAL */
038    private Referral referral;
039
040    /** Decriptive diagnostic message - defaults to empty string */
041    private String diagnosticMessage;
042
043    /** Resultant operation error code - defaults to SUCCESS */
044    private ResultCodeEnum resultCode = ResultCodeEnum.SUCCESS;
045
046    /** A flag set when the LdapResult is a SUCESS with no additional information */
047    private boolean isDefaultSuccess = true;
048
049
050    // ------------------------------------------------------------------------
051    // LdapResult Interface Method Implementations
052    // ------------------------------------------------------------------------
053    /**
054     * {@inheritDoc}
055     */
056    @Override
057    public String getDiagnosticMessage()
058    {
059        return diagnosticMessage;
060    }
061
062
063    /**
064     * {@inheritDoc}
065     */
066    @Override
067    public void setDiagnosticMessage( String diagnosticMessage )
068    {
069        this.diagnosticMessage = diagnosticMessage;
070        isDefaultSuccess = false;
071    }
072
073
074    /**
075     * {@inheritDoc}
076     */
077    @Override
078    public Dn getMatchedDn()
079    {
080        return matchedDn;
081    }
082
083
084    /**
085     * {@inheritDoc}
086     */
087    @Override
088    public void setMatchedDn( Dn matchedDn )
089    {
090        this.matchedDn = matchedDn;
091        isDefaultSuccess = false;
092    }
093
094
095    /**
096     * {@inheritDoc}
097     */
098    @Override
099    public ResultCodeEnum getResultCode()
100    {
101        return resultCode;
102    }
103
104
105    /**
106     * {@inheritDoc}
107     */
108    @Override
109    public void setResultCode( ResultCodeEnum resultCode )
110    {
111        this.resultCode = resultCode;
112
113        isDefaultSuccess = isDefaultSuccess && ( resultCode == ResultCodeEnum.SUCCESS );
114    }
115
116
117    /**
118     * {@inheritDoc}
119     */
120    @Override
121    public Referral getReferral()
122    {
123        return referral;
124    }
125
126
127    /**
128     * {@inheritDoc}
129     */
130    @Override
131    public boolean isReferral()
132    {
133        return referral != null;
134    }
135
136
137    /**
138     * {@inheritDoc}
139     */
140    @Override
141    public void setReferral( Referral referral )
142    {
143        this.referral = referral;
144        isDefaultSuccess = false;
145    }
146
147
148    /**
149     * {@inheritDoc}
150     */
151    @Override
152    public boolean isDefaultSuccess()
153    {
154        return isDefaultSuccess;
155    }
156
157
158    /**
159     * @see Object#hashCode()
160     * @return the instance's hash code 
161     */
162    @Override
163    public int hashCode()
164    {
165        int hash = 37;
166
167        if ( referral != null )
168        {
169            hash = hash * 17 + referral.hashCode();
170        }
171
172        hash = hash * 17 + resultCode.hashCode();
173
174        if ( diagnosticMessage != null )
175        {
176            hash = hash * 17 + diagnosticMessage.hashCode();
177        }
178
179        if ( matchedDn != null )
180        {
181            hash = hash * 17 + matchedDn.hashCode();
182        }
183
184        return hash;
185    }
186
187
188    /**
189     * @param obj The object to compare with
190     * @return <code>true</code> if both objects are equals
191     */
192    @Override
193    public boolean equals( Object obj )
194    {
195        // quickly return true if this is the obj
196        if ( obj == this )
197        {
198            return true;
199        }
200
201        // return false if object does not implement interface
202        if ( !( obj instanceof LdapResult ) )
203        {
204            return false;
205        }
206
207        // compare all the like elements of the two LdapResult objects
208        LdapResult result = ( LdapResult ) obj;
209
210        if ( referral == null && result.getReferral() != null )
211        {
212            return false;
213        }
214
215        if ( result.getReferral() == null && referral != null )
216        {
217            return false;
218        }
219
220        if ( referral != null && result.getReferral() != null && !referral.equals( result.getReferral() ) )
221        {
222            return false;
223        }
224
225        if ( !resultCode.equals( result.getResultCode() ) )
226        {
227            return false;
228        }
229
230        // Handle diagnostic Messages where "" is considered equivalent to null
231        String errMsg0 = diagnosticMessage;
232        String errMsg1 = result.getDiagnosticMessage();
233
234        if ( errMsg0 == null )
235        {
236            errMsg0 = "";
237        }
238
239        if ( errMsg1 == null )
240        {
241            errMsg1 = "";
242        }
243
244        if ( !errMsg0.equals( errMsg1 ) )
245        {
246            return false;
247        }
248
249        if ( matchedDn != null )
250        {
251            if ( !matchedDn.equals( result.getMatchedDn() ) )
252            {
253                return false;
254            }
255        }
256        // one is null other is not
257        else if ( result.getMatchedDn() != null )
258        {
259            return false;
260        }
261
262        return true;
263    }
264
265
266    /**
267     * Get a String representation of a LdapResult
268     * 
269     * @return A LdapResult String
270     */
271    @Override
272    public String toString()
273    {
274        StringBuilder sb = new StringBuilder();
275
276        sb.append( "        Ldap Result\n" );
277        sb.append( "            Result code : (" ).append( resultCode ).append( ')' );
278
279        switch ( resultCode )
280        {
281
282            case SUCCESS:
283                sb.append( " success\n" );
284                break;
285
286            case OPERATIONS_ERROR:
287                sb.append( " operationsError\n" );
288                break;
289
290            case PROTOCOL_ERROR:
291                sb.append( " protocolError\n" );
292                break;
293
294            case TIME_LIMIT_EXCEEDED:
295                sb.append( " timeLimitExceeded\n" );
296                break;
297
298            case SIZE_LIMIT_EXCEEDED:
299                sb.append( " sizeLimitExceeded\n" );
300                break;
301
302            case COMPARE_FALSE:
303                sb.append( " compareFalse\n" );
304                break;
305
306            case COMPARE_TRUE:
307                sb.append( " compareTrue\n" );
308                break;
309
310            case AUTH_METHOD_NOT_SUPPORTED:
311                sb.append( " authMethodNotSupported\n" );
312                break;
313
314            case STRONG_AUTH_REQUIRED:
315                sb.append( " strongAuthRequired\n" );
316                break;
317
318            case REFERRAL:
319                sb.append( " referral -- new\n" );
320                break;
321
322            case ADMIN_LIMIT_EXCEEDED:
323                sb.append( " adminLimitExceeded -- new\n" );
324                break;
325
326            case UNAVAILABLE_CRITICAL_EXTENSION:
327                sb.append( " unavailableCriticalExtension -- new\n" );
328                break;
329
330            case CONFIDENTIALITY_REQUIRED:
331                sb.append( " confidentialityRequired -- new\n" );
332                break;
333
334            case SASL_BIND_IN_PROGRESS:
335                sb.append( " saslBindInProgress -- new\n" );
336                break;
337
338            case NO_SUCH_ATTRIBUTE:
339                sb.append( " noSuchAttribute\n" );
340                break;
341
342            case UNDEFINED_ATTRIBUTE_TYPE:
343                sb.append( " undefinedAttributeType\n" );
344                break;
345
346            case INAPPROPRIATE_MATCHING:
347                sb.append( " inappropriateMatching\n" );
348                break;
349
350            case CONSTRAINT_VIOLATION:
351                sb.append( " constraintViolation\n" );
352                break;
353
354            case ATTRIBUTE_OR_VALUE_EXISTS:
355                sb.append( " attributeOrValueExists\n" );
356                break;
357
358            case INVALID_ATTRIBUTE_SYNTAX:
359                sb.append( " invalidAttributeSyntax\n" );
360                break;
361
362            case NO_SUCH_OBJECT:
363                sb.append( " noSuchObject\n" );
364                break;
365
366            case ALIAS_PROBLEM:
367                sb.append( " aliasProblem\n" );
368                break;
369
370            case INVALID_DN_SYNTAX:
371                sb.append( " invalidDNSyntax\n" );
372                break;
373
374            case ALIAS_DEREFERENCING_PROBLEM:
375                sb.append( " aliasDereferencingProblem\n" );
376                break;
377
378            case INAPPROPRIATE_AUTHENTICATION:
379                sb.append( " inappropriateAuthentication\n" );
380                break;
381
382            case INVALID_CREDENTIALS:
383                sb.append( " invalidCredentials\n" );
384                break;
385
386            case INSUFFICIENT_ACCESS_RIGHTS:
387                sb.append( " insufficientAccessRights\n" );
388                break;
389
390            case BUSY:
391                sb.append( " busy\n" );
392                break;
393
394            case UNAVAILABLE:
395                sb.append( " unavailable\n" );
396                break;
397
398            case UNWILLING_TO_PERFORM:
399                sb.append( " unwillingToPerform\n" );
400                break;
401
402            case LOOP_DETECT:
403                sb.append( " loopDetect\n" );
404                break;
405
406            case NAMING_VIOLATION:
407                sb.append( " namingViolation\n" );
408                break;
409
410            case OBJECT_CLASS_VIOLATION:
411                sb.append( " objectClassViolation\n" );
412                break;
413
414            case NOT_ALLOWED_ON_NON_LEAF:
415                sb.append( " notAllowedOnNonLeaf\n" );
416                break;
417
418            case NOT_ALLOWED_ON_RDN:
419                sb.append( " notAllowedOnRDN\n" );
420                break;
421
422            case ENTRY_ALREADY_EXISTS:
423                sb.append( " entryAlreadyExists\n" );
424                break;
425
426            case OBJECT_CLASS_MODS_PROHIBITED:
427                sb.append( " objectClassModsProhibited\n" );
428                break;
429
430            case AFFECTS_MULTIPLE_DSAS:
431                sb.append( " affectsMultipleDSAs -- new\n" );
432                break;
433
434            case E_SYNC_REFRESH_REQUIRED:
435                sb.append( " eSyncRefreshRequired\n" );
436                break;
437
438            case OTHER:
439                sb.append( " other\n" );
440                break;
441
442            default:
443                switch ( resultCode.getResultCode() )
444                {
445                    case 9:
446                        sb.append( " -- 9 reserved --\n" );
447                        break;
448
449                    case 22:
450                    case 23:
451                    case 24:
452                    case 25:
453                    case 26:
454                    case 27:
455                    case 28:
456                    case 29:
457                    case 30:
458                    case 31:
459                        sb.append( " -- 22-31 unused --\n" );
460                        break;
461
462                    case 35:
463                        sb.append( " -- 35 reserved for undefined isLeaf --\n" );
464                        break;
465
466                    case 37:
467                    case 38:
468                    case 39:
469                    case 40:
470                    case 41:
471                    case 42:
472                    case 43:
473                    case 44:
474                    case 45:
475                    case 46:
476                    case 47:
477                        sb.append( " -- 37-47 unused --\n" );
478                        break;
479
480                    case 55:
481                    case 56:
482                    case 57:
483                    case 58:
484                    case 59:
485                    case 60:
486                    case 61:
487                    case 62:
488                    case 63:
489                        sb.append( " -- 55-63 unused --\n" );
490                        break;
491
492                    case 70:
493                        sb.append( " -- 70 reserved for CLDAP --\n" );
494                        break;
495
496                    case 72:
497                    case 73:
498                    case 74:
499                    case 75:
500                    case 76:
501                    case 77:
502                    case 78:
503                    case 79:
504                        sb.append( " -- 72-79 unused --\n" );
505                        break;
506
507                    case 81:
508                    case 82:
509                    case 83:
510                    case 84:
511                    case 85:
512                    case 86:
513                    case 87:
514                    case 88:
515                    case 89:
516                    case 90:
517                        sb.append( " -- 81-90 reserved for APIs --" );
518                        break;
519
520                    default:
521                        sb.append( "Unknown error code : " ).append( resultCode );
522                        break;
523                }
524        }
525
526        sb.append( "            Matched Dn : '" ).append( matchedDn ).append( "'\n" );
527        sb.append( "            Diagnostic message : '" ).append( diagnosticMessage ).append( "'\n" );
528
529        if ( referral != null )
530        {
531            sb.append( "            Referrals :\n" );
532
533            sb.append( "                Referral :" ).append( referral.toString() ).append( '\n' );
534        }
535
536        return sb.toString();
537    }
538}