View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    https://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.model.schema.comparators;
21  
22  
23  import org.apache.directory.api.i18n.I18n;
24  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
25  import org.apache.directory.api.ldap.model.exception.LdapException;
26  import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
27  import org.apache.directory.api.ldap.model.name.Dn;
28  import org.apache.directory.api.ldap.model.schema.LdapComparator;
29  import org.apache.directory.api.ldap.model.schema.SchemaManager;
30  
31  
32  /**
33   * A comparator that sorts OIDs based on their numeric id value.  Needs a 
34   * OidRegistry to properly do it's job.  Public method to set the oid 
35   * registry will be used by the server after instantiation in deserialization.
36   *
37   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
38   */
39  public class UniqueMemberComparator extends LdapComparator<String>
40  {
41      /** The serial version UID */
42      private static final long serialVersionUID = 2L;
43  
44      /** A reference to the schema manager */
45      private transient SchemaManager schemaManager;
46      
47      private transient ParsedDnComparator dnComparator = new ParsedDnComparator( SchemaConstants.ENTRY_DN_AT_OID );
48  
49  
50      /**
51       * The IntegerComparator constructor. Its OID is the IntegerOrderingMatch matching
52       * rule OID.
53       * 
54       * @param oid The Comparator's OID
55       */
56      public UniqueMemberComparator( String oid )
57      {
58          super( oid );
59      }
60  
61  
62      /**
63       * {@inheritDoc}
64       */
65      public int compare( String dnstr1, String dnstr2 )
66      {
67          int dash1 = dnstr1.lastIndexOf( '#' );
68          int dash2 = dnstr2.lastIndexOf( '#' );
69  
70          if ( ( dash1 == -1 ) && ( dash2 == -1 ) )
71          {
72              // no UID part
73              try
74              {
75                  Dn dn1 = getDn( dnstr1 );
76                  Dn dn2 = getDn( dnstr2 );
77  
78                  return dnComparator.compare( dn1, dn2 );
79              }
80              catch ( LdapInvalidDnException ne )
81              {
82                  return -1;
83              }
84          }
85          else
86          {
87              // Now, check that we don't have another '#'
88              if ( dnstr1.indexOf( '#' ) != dash1 )
89              {
90                  // Yes, we have one : this is not allowed, it should have been
91                  // escaped.
92                  return -1;
93              }
94  
95              if ( dnstr2.indexOf( '#' ) != dash1 )
96              {
97                  // Yes, we have one : this is not allowed, it should have been
98                  // escaped.
99                  return 1;
100             }
101 
102             Dn dn1;
103             Dn dn2;
104 
105             // This is an UID if the '#' is immediatly
106             // followed by a BitString, except if the '#' is
107             // on the last position
108             String uid1 = dnstr1.substring( dash1 + 1 );
109 
110             if ( dash1 > 0 )
111             {
112                 try
113                 {
114                     dn1 = new Dn( dnstr1.substring( 0, dash1 ) );
115                 }
116                 catch ( LdapException ne )
117                 {
118                     return -1;
119                 }
120             }
121             else
122             {
123                 return -1;
124             }
125 
126             // This is an UID if the '#' is immediately
127             // followed by a BitString, except if the '#' is
128             // on the last position
129             String uid2 = dnstr2.substring( dash2 + 1 );
130 
131             if ( dash2 > 0 )
132             {
133                 try
134                 {
135                     dn2 = new Dn( dnstr1.substring( 0, dash2 ) );
136                 }
137                 catch ( LdapException ne )
138                 {
139                     return 1;
140                 }
141             }
142             else
143             {
144                 return 1;
145             }
146 
147             int dnResult = dnComparator.compare( dn1, dn2 );
148             
149             if ( dnResult == 0 )
150             {
151                 return uid1.compareTo( uid2 );
152             }
153 
154             return dnResult;
155         }
156     }
157 
158 
159     /**
160      * {@inheritDoc}
161      */
162     @Override
163     public void setSchemaManager( SchemaManager schemaManager )
164     {
165         this.schemaManager = schemaManager;
166     }
167 
168 
169     /**
170      * Get the DN from the given object
171      *
172      * @param obj The object containing a DN (either as an instance of Dn or as a String)
173      * @return A Dn instance
174      * @throws LdapInvalidDnException If the Dn is invalid
175      */
176     public Dn getDn( Object obj ) throws LdapInvalidDnException
177     {
178         Dn dn;
179 
180         if ( obj instanceof Dn )
181         {
182             dn = ( Dn ) obj;
183 
184             dn = dn.isSchemaAware() ? dn : new Dn( schemaManager, dn );
185         }
186         else if ( obj instanceof String )
187         {
188             dn = new Dn( schemaManager, ( String ) obj );
189         }
190         else
191         {
192             throw new IllegalStateException( I18n.err( I18n.ERR_13720_CANNOT_HANDLE_DN_COMPARISONS, obj == null ? null : obj.getClass() ) );
193         }
194 
195         return dn;
196     }
197 }