001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/framework/util/BasicUUID.java $
002    /*
003    
004     This class orginaly has been part of the apache derby project. It has 
005     slightly been changed to match the requirements of deegree.
006    
007     Derby - Class org.apache.derby.impl.services.uuid.BasicUUID
008    
009     Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.
010    
011     Licensed under the Apache License, Version 2.0 (the "License");
012     you may not use this file except in compliance with the License.
013     You may obtain a copy of the License at
014    
015     http://www.apache.org/licenses/LICENSE-2.0
016    
017     Unless required by applicable law or agreed to in writing, software
018     distributed under the License is distributed on an "AS IS" BASIS,
019     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
020     See the License for the specific language governing permissions and
021     limitations under the License.
022    
023     */
024    package org.deegree.framework.util;
025    
026    import java.io.IOException;
027    import java.io.ObjectInput;
028    import java.io.ObjectOutput;
029    import java.io.StringReader;
030    
031    /**
032     * TODO add documentation here
033     * 
034     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
035     * @author last edited by: $Author: apoth $
036     * 
037     * @version $Revision: 9339 $, $Date: 2007-12-27 13:31:52 +0100 (Do, 27 Dez 2007) $
038     * @deprecated use
039     * @see UUID
040     */
041    public class BasicUUID implements UUID {
042        /*
043         * * Fields of BasicUUID
044         */
045    
046        private long majorId; // only using 48 bits
047    
048        private long timemillis;
049    
050        private int sequence;
051    
052        /*
053         * * Methods of BasicUUID
054         */
055    
056        /**
057         * Constructor only called by BasicUUIDFactory.
058         * 
059         * @param majorId
060         * @param timemillis
061         * @param sequence
062         */
063        public BasicUUID( long majorId, long timemillis, int sequence ) {
064            this.majorId = majorId;
065            this.timemillis = timemillis;
066            this.sequence = sequence;
067        }
068    
069        /**
070         * Constructor only called by BasicUUIDFactory. Constructs a UUID from the string representation
071         * produced by toString.
072         * 
073         * @param uuidstring
074         * @see BasicUUID#toString
075         */
076        public BasicUUID( String uuidstring ) {
077            StringReader sr = new StringReader( uuidstring );
078            sequence = (int) readMSB( sr );
079    
080            long ltimemillis = readMSB( sr ) << 32;
081            ltimemillis += readMSB( sr ) << 16;
082            ltimemillis += readMSB( sr );
083            timemillis = ltimemillis;
084            majorId = readMSB( sr );
085        }
086    
087        /**
088         * Constructor only called by BasicUUIDFactory. Constructs a UUID from the byte array
089         * representation produced by toByteArrayio.
090         * 
091         * @param b
092         * @see BasicUUID#toByteArray
093         */
094        public BasicUUID( byte[] b ) {
095            int lsequence = 0;
096            for ( int ix = 0; ix < 4; ix++ ) {
097                lsequence = lsequence << 8;
098                lsequence = lsequence | ( 0xff & b[ix] );
099            }
100    
101            long ltimemillis = 0;
102            for ( int ix = 4; ix < 10; ix++ ) {
103                ltimemillis = ltimemillis << 8;
104                ltimemillis = ltimemillis | ( 0xff & b[ix] );
105            }
106    
107            long linetaddr = 0;
108            for ( int ix = 10; ix < 16; ix++ ) {
109                linetaddr = linetaddr << 8;
110                linetaddr = linetaddr | ( 0xff & b[ix] );
111            }
112    
113            sequence = lsequence;
114            timemillis = ltimemillis;
115            majorId = linetaddr;
116        }
117    
118        /*
119         * Formatable methods
120         */
121    
122        // no-arg constructor, required by Formatable
123        public BasicUUID() {
124            super();
125        }
126    
127        /**
128         * Write this out.
129         * 
130         * @param out
131         * @exception IOException
132         *                error writing to log stream
133         */
134        public void writeExternal( ObjectOutput out )
135                                throws IOException {
136            // RESOLVE: write out the byte array instead?
137            out.writeLong( majorId );
138            out.writeLong( timemillis );
139            out.writeInt( sequence );
140        }
141    
142        /**
143         * Read this in
144         * 
145         * @param in
146         * @exception IOException
147         *                error reading from log stream
148         */
149        public void readExternal( ObjectInput in )
150                                throws IOException {
151            majorId = in.readLong();
152            timemillis = in.readLong();
153            sequence = in.readInt();
154        }
155    
156        private static void writeMSB( char[] data, int offset, long value, int nbytes ) {
157            for ( int i = nbytes - 1; i >= 0; i-- ) {
158                long b = ( value & ( 255L << ( 8 * i ) ) ) >>> ( 8 * i );
159    
160                int c = (int) ( ( b & 0xf0 ) >> 4 );
161                data[offset++] = (char) ( c < 10 ? c + '0' : ( c - 10 ) + 'a' );
162                c = (int) ( b & 0x0f );
163                data[offset++] = (char) ( c < 10 ? c + '0' : ( c - 10 ) + 'a' );
164            }
165        }
166    
167        /**
168         * Read a long value, msb first, from its character representation in the string reader, using
169         * '-' or end of string to delimit.
170         */
171        private static long readMSB( StringReader sr ) {
172            long value = 0;
173    
174            try {
175                int c;
176                while ( ( c = sr.read() ) != -1 ) {
177                    if ( c == '-' )
178                        break;
179                    value <<= 4;
180    
181                    int nibble;
182                    if ( c <= '9' )
183                        nibble = c - '0';
184                    else if ( c <= 'F' )
185                        nibble = c - 'A' + 10;
186                    else
187                        nibble = c - 'a' + 10;
188                    value += nibble;
189                }
190            } catch ( Exception e ) {
191            }
192    
193            return value;
194        }
195    
196        /*
197         * * Methods of UUID
198         */
199    
200        /**
201         * Implement value equality.
202         * 
203         * @return
204         * 
205         */
206        public boolean equals( Object otherObject ) {
207            if ( !( otherObject instanceof BasicUUID ) )
208                return false;
209    
210            BasicUUID other = (BasicUUID) otherObject;
211    
212            return ( this.sequence == other.sequence ) && ( this.timemillis == other.timemillis )
213                   && ( this.majorId == other.majorId );
214        }
215    
216        /**
217         * Provide a hashCode which is compatible with the equals() method.
218         * 
219         * @return a hashCode which is compatible with the equals() method.
220         */
221        public int hashCode() {
222            long hc = majorId ^ timemillis;
223    
224            return sequence ^ ( (int) ( hc >> 4 ) );
225        }
226    
227        /**
228         * Produce a string representation of this UUID which can be passed to UUIDFactory.recreateUUID
229         * later on to reconstruct it. The funny representation is designed to (sort of) match the
230         * format of Microsoft's UUIDGEN utility.
231         * 
232         * @return a string representation of this UUID
233         */
234        public String toString() {
235            return stringWorkhorse( '-' );
236        }
237    
238        /**
239         * Produce a string representation of this UUID which is suitable for use as a unique ANSI
240         * identifier.
241         * 
242         * @return a string representation of this UUID
243         */
244        public String toANSIidentifier() {
245            return stringWorkhorse( 'X' );
246        }
247    
248        /**
249         * Private workhorse of the string making routines.
250         * 
251         * @param separator
252         *            Character to separate number blocks. Null means do not include a separator.
253         * 
254         * @return string representation of UUID.
255         */
256        public String stringWorkhorse( char separator ) {
257            char[] data = new char[36];
258    
259            writeMSB( data, 0, sequence, 4 );
260    
261            int offset = 8;
262            if ( separator != 0 )
263                data[offset++] = separator;
264    
265            long ltimemillis = timemillis;
266            writeMSB( data, offset, ( ltimemillis & 0x0000ffff00000000L ) >>> 32, 2 );
267            offset += 4;
268            if ( separator != 0 )
269                data[offset++] = separator;
270            writeMSB( data, offset, ( ltimemillis & 0x00000000ffff0000L ) >>> 16, 2 );
271            offset += 4;
272            if ( separator != 0 )
273                data[offset++] = separator;
274            writeMSB( data, offset, ( ltimemillis & 0x000000000000ffffL ), 2 );
275            offset += 4;
276            if ( separator != 0 )
277                data[offset++] = separator;
278            writeMSB( data, offset, majorId, 6 );
279            offset += 12;
280    
281            return new String( data, 0, offset );
282        }
283    
284        /**
285         * Store this UUID in a byte array. Arrange the bytes in the UUID in the same order the code
286         * which stores a UUID in a string does.
287         * 
288         * @return UUID in a byte array.
289         * 
290         * @see "org.apache.derby.catalog.UUID#toByteArray"
291         */
292        public byte[] toByteArray() {
293            byte[] result = new byte[16];
294    
295            int lsequence = sequence;
296            result[0] = (byte) ( lsequence >>> 24 );
297            result[1] = (byte) ( lsequence >>> 16 );
298            result[2] = (byte) ( lsequence >>> 8 );
299            result[3] = (byte) lsequence;
300    
301            long ltimemillis = timemillis;
302            result[4] = (byte) ( ltimemillis >>> 40 );
303            result[5] = (byte) ( ltimemillis >>> 32 );
304            result[6] = (byte) ( ltimemillis >>> 24 );
305            result[7] = (byte) ( ltimemillis >>> 16 );
306            result[8] = (byte) ( ltimemillis >>> 8 );
307            result[9] = (byte) ltimemillis;
308    
309            long linetaddr = majorId;
310            result[10] = (byte) ( linetaddr >>> 40 );
311            result[11] = (byte) ( linetaddr >>> 32 );
312            result[12] = (byte) ( linetaddr >>> 24 );
313            result[13] = (byte) ( linetaddr >>> 16 );
314            result[14] = (byte) ( linetaddr >>> 8 );
315            result[15] = (byte) linetaddr;
316    
317            return result;
318        }
319    
320        /**
321         * Clone this UUID.
322         * 
323         * @return a copy of this UUID
324         */
325        public UUID cloneMe() {
326            return new BasicUUID( majorId, timemillis, sequence );
327        }
328    
329        /*
330         * (non-Javadoc)
331         * 
332         * @see org.deegree.framework.util.UUID#toHexString()
333         */
334        public String toHexString() {
335            return stringWorkhorse( (char) 0 );
336        }
337    }