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 *    https://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.schema.LdapComparator;
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027
028
029/**
030 * A class for the bitStringMatch matchingRule (RFC 4517, par. 4.2.1)
031 * 
032 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
033 */
034public class BitStringComparator extends LdapComparator<String>
035{
036    /** The serial version UID */
037    private static final long serialVersionUID = 2L;
038
039    /** A logger for this class */
040    private static final Logger LOG = LoggerFactory.getLogger( BitStringComparator.class );
041
042
043    /**
044     * The BitStringComparator constructor. Its OID is the IntegerOrderingMatch matching
045     * rule OID.
046     * 
047     * @param oid The Comparator's OID
048     */
049    public BitStringComparator( String oid )
050    {
051        super( oid );
052    }
053
054
055    /**
056     * {@inheritDoc}
057     */
058    public int compare( String bs1, String bs2 )
059    {
060        if ( LOG.isDebugEnabled() )
061        {
062            LOG.debug( I18n.msg( I18n.MSG_13743_COMPARING_BITSTRING, bs1, bs2 ) );
063        }
064
065        // First, shortcut the process by comparing
066        // references. If they are equals, then bs1 and bs2
067        // reference the same object
068        if ( bs1 == bs2 )
069        {
070            return 0;
071        }
072
073        // Then, deal with one of bs1 or bs2 being null
074        // Both can't be null, because then they would
075        // have been caught by the previous test
076        if ( ( bs1 == null ) || ( bs2 == null ) )
077        {
078            return bs1 == null ? -1 : 1;
079        }
080
081        // We have to get rid of 0 from left of each BitString
082        char[] array1 = bs1.toCharArray();
083        char[] array2 = bs2.toCharArray();
084
085        int pos1 = bs1.indexOf( '1' );
086        int pos2 = bs2.indexOf( '1' );
087
088        if ( pos1 == -1 )
089        {
090            if ( pos2 == -1 )
091            {
092                return 0;
093            }
094            else
095            {
096                return -1;
097            }
098        }
099        else if ( pos2 == -1 )
100        {
101            return 1;
102        }
103
104        int length1 = array1.length - pos1;
105        int length2 = array2.length - pos2;
106
107        if ( length1 == length2 )
108        {
109            for ( int i = 0; i < length1; i++ )
110            {
111                int i1 = i + pos1;
112                int i2 = i + pos2;
113
114                if ( array1[i1] < array2[i2] )
115                {
116                    return -1;
117                }
118                else if ( array1[i1] > array2[i2] )
119                {
120                    return 1;
121                }
122            }
123
124            return 0;
125        }
126
127        if ( length1 < length2 )
128        {
129            return -1;
130        }
131        else
132        {
133            return 1;
134        }
135    }
136}