001    /**
002     * JDBM LICENSE v1.00
003     *
004     * Redistribution and use of this software and associated documentation
005     * ("Software"), with or without modification, are permitted provided
006     * that the following conditions are met:
007     *
008     * 1. Redistributions of source code must retain copyright
009     *    statements and notices.  Redistributions must also contain a
010     *    copy of this document.
011     *
012     * 2. Redistributions in binary form must reproduce the
013     *    above copyright notice, this list of conditions and the
014     *    following disclaimer in the documentation and/or other
015     *    materials provided with the distribution.
016     *
017     * 3. The name "JDBM" must not be used to endorse or promote
018     *    products derived from this Software without prior written
019     *    permission of Cees de Groot.  For written permission,
020     *    please contact cg@cdegroot.com.
021     *
022     * 4. Products derived from this Software may not be called "JDBM"
023     *    nor may "JDBM" appear in their names without prior written
024     *    permission of Cees de Groot.
025     *
026     * 5. Due credit should be given to the JDBM Project
027     *    (http://jdbm.sourceforge.net/).
028     *
029     * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS
030     * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
031     * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
032     * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
033     * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
034     * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
035     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
036     * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
037     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
038     * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
039     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
040     * OF THE POSSIBILITY OF SUCH DAMAGE.
041     *
042     * Copyright 2001 (C) Alex Boisvert. All Rights Reserved.
043     * Contributions are Copyright (C) 2001 by their associated contributors.
044     *
045     */
046    
047    package jdbm.helper;
048    
049    import java.io.IOException;
050    import java.io.Serializable;
051    import java.util.Comparator;
052    
053    import org.apache.directory.server.i18n.I18n;
054    
055    /**
056     * Comparator for objects which have been serialized into byte arrays.
057     * In effect, it wraps another Comparator which compares object and provides
058     * transparent deserialization from byte array to object.
059     *
060     * @author <a href="mailto:boisvert@intalio.com">Alex Boisvert</a>
061     * @version $Id: ObjectBAComparator.java,v 1.1 2002/05/31 06:33:20 boisvert Exp $
062     */
063    public final class ObjectBAComparator
064        implements Comparator, Serializable
065    {
066    
067        /**
068         * Version id for serialization.
069         */
070        final static long serialVersionUID = 1L;
071    
072    
073        /**
074         * Wrapped comparator.
075         */
076        private Comparator _comparator;
077    
078    
079        /**
080         * Construct an ObjectByteArrayComparator which wraps an Object Comparator.
081         *
082         * @param comparator Object comparator.
083         */
084        public ObjectBAComparator( Comparator comparator )
085        {
086            if ( comparator == null ) {
087                throw new IllegalArgumentException( I18n.err( I18n.ERR_518 ) );
088            }
089    
090            _comparator = comparator;
091        }
092    
093    
094        /**
095         * Compare two objects.
096         *
097         * @param obj1 First object
098         * @param obj2 Second object
099         * @return 1 if obj1 > obj2, 0 if obj1 == obj2, -1 if obj1 < obj2
100         */
101         public int compare( Object obj1, Object obj2 )
102         {
103            if ( obj1 == null ) {
104                throw new IllegalArgumentException( I18n.err( I18n.ERR_525 ) );
105            }
106    
107            if ( obj2 == null ) {
108                throw new IllegalArgumentException( I18n.err( I18n.ERR_526 ) );
109            }
110    
111            try {
112                obj1 = Serialization.deserialize( (byte[]) obj1 );
113                obj2 = Serialization.deserialize( (byte[]) obj2 );
114    
115                return _comparator.compare( obj1, obj2 );
116            } catch ( IOException except ) {
117                throw new WrappedRuntimeException( except );
118            } catch ( ClassNotFoundException except ) {
119                throw new WrappedRuntimeException( except );
120            }
121         }
122    
123    
124        /**
125         * Compare two byte arrays.
126         */
127        public static int compareByteArray( byte[] thisKey, byte[] otherKey )
128        {
129            int len = Math.min( thisKey.length, otherKey.length );
130    
131            // compare the byte arrays
132            for ( int i=0; i<len; i++ ) {
133                if ( thisKey[i] >= 0 ) {
134                    if ( otherKey[i] >= 0 ) {
135                        // both positive
136                        if ( thisKey[i] < otherKey[i] ) {
137                            return -1;
138                        } else if ( thisKey[i] > otherKey[i] ) {
139                            return 1;
140                        }
141                    } else {
142                        // otherKey is negative => greater (because MSB is 1)
143                        return -1;
144                    }
145                } else {
146                    if ( otherKey[i] >= 0 ) {
147                        // thisKey is negative => greater (because MSB is 1)
148                        return 1;
149                    } else {
150                        // both negative
151                        if ( thisKey[i] < otherKey[i] ) {
152                            return -1;
153                        } else if ( thisKey[i] > otherKey[i] ) {
154                            return 1;
155                        }
156                    }
157                }
158            }
159            if ( thisKey.length == otherKey.length) {
160                return 0;
161            }
162            if ( thisKey.length < otherKey.length ) {
163                return -1;
164            }
165            return 1;
166        }
167    
168    }