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