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.api.ldap.model.schema.comparators;
021
022
023import org.apache.directory.api.i18n.I18n;
024import org.apache.directory.api.ldap.model.exception.LdapException;
025import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
026import org.apache.directory.api.ldap.model.name.Dn;
027import org.apache.directory.api.ldap.model.schema.LdapComparator;
028import org.apache.directory.api.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    /**
048     * The IntegerComparator constructor. Its OID is the IntegerOrderingMatch matching
049     * rule OID.
050     * 
051     * @param oid The Comparator's OID
052     */
053    public UniqueMemberComparator( String oid )
054    {
055        super( oid );
056    }
057
058
059    /**
060     * {@inheritDoc}
061     */
062    public int compare( String dnstr1, String dnstr2 )
063    {
064        int dash1 = dnstr1.lastIndexOf( '#' );
065        int dash2 = dnstr2.lastIndexOf( '#' );
066
067        if ( ( dash1 == -1 ) && ( dash2 == -1 ) )
068        {
069            // no UID part
070            try
071            {
072                Dn dn1 = getDn( dnstr1 );
073                Dn dn2 = getDn( dnstr2 );
074
075                if ( dn1.equals( dn2 ) )
076                {
077                    return 0;
078                }
079                else
080                {
081                    return -1;
082                }
083            }
084            catch ( LdapInvalidDnException ne )
085            {
086                return -1;
087            }
088        }
089        else
090        {
091            // Now, check that we don't have another '#'
092            if ( dnstr1.indexOf( '#' ) != dash1 )
093            {
094                // Yes, we have one : this is not allowed, it should have been
095                // escaped.
096                return -1;
097            }
098
099            if ( dnstr2.indexOf( '#' ) != dash1 )
100            {
101                // Yes, we have one : this is not allowed, it should have been
102                // escaped.
103                return 1;
104            }
105
106            Dn dn1;
107            Dn dn2;
108
109            // This is an UID if the '#' is immediatly
110            // followed by a BitString, except if the '#' is
111            // on the last position
112            String uid1 = dnstr1.substring( dash1 + 1 );
113
114            if ( dash1 > 0 )
115            {
116                try
117                {
118                    dn1 = new Dn( dnstr1.substring( 0, dash1 ) );
119                }
120                catch ( LdapException ne )
121                {
122                    return -1;
123                }
124            }
125            else
126            {
127                return -1;
128            }
129
130            // This is an UID if the '#' is immediatly
131            // followed by a BitString, except if the '#' is
132            // on the last position
133            String uid2 = dnstr2.substring( dash2 + 1 );
134
135            if ( dash2 > 0 )
136            {
137                try
138                {
139                    dn2 = new Dn( dnstr1.substring( 0, dash2 ) );
140                }
141                catch ( LdapException ne )
142                {
143                    return 1;
144                }
145            }
146            else
147            {
148                return 1;
149            }
150
151            if ( dn1.equals( dn2 ) )
152            {
153                return uid1.compareTo( uid2 );
154            }
155
156            return -1;
157        }
158    }
159
160
161    /**
162     * {@inheritDoc}
163     */
164    @Override
165    public void setSchemaManager( SchemaManager schemaManager )
166    {
167        this.schemaManager = schemaManager;
168    }
169
170
171    /**
172     * Get the DN from the given object
173     *
174     * @param obj The object containing a DN (either as an instance of Dn or as a String)
175     * @return A Dn instance
176     * @throws LdapInvalidDnException If the Dn is invalid
177     */
178    public Dn getDn( Object obj ) throws LdapInvalidDnException
179    {
180        Dn dn;
181
182        if ( obj instanceof Dn )
183        {
184            dn = ( Dn ) obj;
185
186            dn = dn.isSchemaAware() ? dn : dn.apply( schemaManager );
187        }
188        else if ( obj instanceof String )
189        {
190            dn = new Dn( schemaManager, ( String ) obj );
191        }
192        else
193        {
194            throw new IllegalStateException( I18n.err( I18n.ERR_04218, obj == null ? null : obj.getClass()  ) );
195        }
196
197        return dn;
198    }
199}