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