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    package org.apache.directory.shared.ldap.schema.comparators;
021    
022    
023    import org.apache.directory.shared.ldap.exception.LdapException;
024    import org.apache.directory.shared.ldap.exception.LdapInvalidDnException;
025    
026    import org.apache.directory.shared.i18n.I18n;
027    import org.apache.directory.shared.ldap.name.DN;
028    import org.apache.directory.shared.ldap.schema.LdapComparator;
029    import org.apache.directory.shared.ldap.schema.SchemaManager;
030    import org.slf4j.Logger;
031    import org.slf4j.LoggerFactory;
032    
033    
034    /**
035     * A comparator that sorts OIDs based on their numeric id value.  Needs a 
036     * OidRegistry to properly do it's job.  Public method to set the oid 
037     * registry will be used by the server after instantiation in deserialization.
038     *
039     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
040     * @version $Rev$
041     */
042    public class UniqueMemberComparator extends LdapComparator<String>
043    {
044        /** A logger for this class */
045        private static final Logger LOG = LoggerFactory.getLogger( UniqueMemberComparator.class );
046    
047        /** The serialVersionUID */
048        private static final long serialVersionUID = 1L;
049    
050        /** A reference to the schema manager */
051        private transient SchemaManager schemaManager;
052    
053    
054        /**
055         * The IntegerOrderingComparator constructor. Its OID is the IntegerOrderingMatch matching
056         * rule OID.
057         */
058        public UniqueMemberComparator( String oid )
059        {
060            super( oid );
061        }
062    
063    
064        /**
065         * Implementation of the Compare method
066         */
067        public int compare( String dnstr0, String dnstr1 )
068        {
069            int dash0 = dnstr0.lastIndexOf( '#' );
070            int dash1 = dnstr1.lastIndexOf( '#' );
071    
072            if ( ( dash0 == -1 ) && ( dash1 == -1 ) )
073            {
074                // no UID part
075                try
076                {
077                    return getDn( dnstr0 ).compareTo( getDn( dnstr1 ) );
078                }
079                catch ( LdapInvalidDnException ne )
080                {
081                    return -1;
082                }
083            }
084            else
085            {
086                // Now, check that we don't have another '#'
087                if ( dnstr0.indexOf( '#' ) != dash0 )
088                {
089                    // Yes, we have one : this is not allowed, it should have been
090                    // escaped.
091                    return -1;
092                }
093    
094                if ( dnstr1.indexOf( '#' ) != dash0 )
095                {
096                    // Yes, we have one : this is not allowed, it should have been
097                    // escaped.
098                    return 1;
099                }
100    
101                DN dn0 = null;
102                DN dn1 = null;
103    
104                // This is an UID if the '#' is immediatly
105                // followed by a BitString, except if the '#' is
106                // on the last position
107                String uid0 = dnstr0.substring( dash0 + 1 );
108    
109                if ( dash0 > 0 )
110                {
111                    try
112                    {
113                        dn0 = new DN( dnstr0.substring( 0, dash0 ) );
114                    }
115                    catch ( LdapException ne )
116                    {
117                        return -1;
118                    }
119                }
120                else
121                {
122                    return -1;
123                }
124    
125                // This is an UID if the '#' is immediatly
126                // followed by a BitString, except if the '#' is
127                // on the last position
128                String uid1 = dnstr1.substring( dash1 + 1 );
129    
130                if ( dash1 > 0 )
131                {
132                    try
133                    {
134                        dn1 = new DN( dnstr0.substring( 0, dash1 ) );
135                    }
136                    catch ( LdapException ne )
137                    {
138                        return 1;
139                    }
140                }
141                else
142                {
143                    return 1;
144                }
145    
146                int dnComp = dn0.compareTo( dn1 );
147    
148                if ( dnComp != 0 )
149                {
150                    return dnComp;
151                }
152    
153                return uid0.compareTo( uid1 );
154            }
155        }
156    
157    
158        /**
159         * {@inheritDoc}
160         */
161        public void setSchemaManager( SchemaManager schemaManager )
162        {
163            this.schemaManager = schemaManager;
164        }
165    
166    
167        public DN getDn( Object obj ) throws LdapInvalidDnException
168        {
169            DN dn = null;
170    
171            if ( obj instanceof DN )
172            {
173                dn = ( DN ) obj;
174    
175                dn = ( dn.isNormalized() ? dn : DN.normalize( dn, schemaManager.getNormalizerMapping() ) );
176            }
177            else if ( obj instanceof String )
178            {
179                dn = new DN( ( String ) obj );
180                dn.normalize( schemaManager.getNormalizerMapping() );
181            }
182            else
183            {
184                throw new IllegalStateException( I18n.err( I18n.ERR_04218, ( obj == null ? null : obj.getClass() ) ) );
185            }
186    
187            return dn;
188        }
189    }