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