1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: SimpleFormat.java,v 1.1 2008/02/07 17:12:27 mark Exp $
7 */
8
9package com.sleepycat.persist.impl;
10
11import java.lang.reflect.Field;
12import java.math.BigInteger;
13import java.util.Date;
14import java.util.Map;
15import java.util.Set;
16
17import com.sleepycat.db.DatabaseEntry;
18
19/**
20 * Format for simple types, including primitives.  Additional methods are
21 * included to optimize the handling of primitives.  Other classes such as
22 * PrimitiveArrayFormat and ReflectAccessor take advantage of these methods.
23 *
24 * @author Mark Hayes
25 */
26public abstract class SimpleFormat extends Format {
27
28    private static final long serialVersionUID = 4595245575868697702L;
29
30    private boolean primitive;
31    private SimpleFormat wrapperFormat;
32
33    SimpleFormat(Class type, boolean primitive) {
34        super(type);
35        this.primitive = primitive;
36    }
37
38    void setWrapperFormat(SimpleFormat wrapperFormat) {
39        this.wrapperFormat = wrapperFormat;
40    }
41
42    @Override
43    Format getWrapperFormat() {
44        return wrapperFormat;
45    }
46
47    @Override
48    public boolean isSimple() {
49        return true;
50    }
51
52    @Override
53    public boolean isPrimitive() {
54        return primitive;
55    }
56
57    @Override
58    void collectRelatedFormats(Catalog catalog,
59                               Map<String,Format> newFormats) {
60    }
61
62    @Override
63    void initialize(Catalog catalog, int initVersion) {
64    }
65
66    @Override
67    public Object readObject(Object o, EntityInput input, boolean rawAccess) {
68        /* newInstance reads the value -- do nothing here. */
69        return o;
70    }
71
72    @Override
73    boolean evolve(Format newFormat, Evolver evolver) {
74        evolver.useOldFormat(this, newFormat);
75        return true;
76    }
77
78    /* -- Begin methods to be overridden by primitive formats only. -- */
79
80    Object newPrimitiveArray(int len, EntityInput input) {
81        throw new UnsupportedOperationException();
82    }
83
84    void writePrimitiveArray(Object o, EntityOutput output) {
85        throw new UnsupportedOperationException();
86    }
87
88    int getPrimitiveLength() {
89        throw new UnsupportedOperationException();
90    }
91
92    void readPrimitiveField(Object o, EntityInput input, Field field)
93        throws IllegalAccessException {
94
95        throw new UnsupportedOperationException();
96    }
97
98    void writePrimitiveField(Object o, EntityOutput output, Field field)
99        throws IllegalAccessException {
100
101        throw new UnsupportedOperationException();
102    }
103
104    /* -- End methods to be overridden by primitive formats only. -- */
105
106    void skipPrimitiveArray(int len, RecordInput input) {
107        input.skipFast(len * getPrimitiveLength());
108    }
109
110    void copySecMultiKeyPrimitiveArray(int len,
111                                       RecordInput input,
112                                       Set results) {
113        int primLen = getPrimitiveLength();
114        for (int i = 0; i < len; i += 1) {
115            DatabaseEntry entry = new DatabaseEntry
116                (input.getBufferBytes(), input.getBufferOffset(), primLen);
117            results.add(entry);
118            input.skipFast(primLen);
119        }
120    }
121
122    public static class FBool extends SimpleFormat {
123
124        private static final long serialVersionUID = -7724949525068533451L;
125
126        FBool(boolean primitive) {
127            super(primitive ? Boolean.TYPE : Boolean.class, primitive);
128        }
129
130        @Override
131        Object newArray(int len) {
132            return new Boolean[len];
133        }
134
135        @Override
136        public Object newInstance(EntityInput input, boolean rawAccess) {
137            return Boolean.valueOf(input.readBoolean());
138        }
139
140        @Override
141        void writeObject(Object o, EntityOutput output, boolean rawAccess) {
142            output.writeBoolean(((Boolean) o).booleanValue());
143        }
144
145        @Override
146        void skipContents(RecordInput input) {
147            input.skipFast(1);
148        }
149
150        @Override
151        void copySecKey(RecordInput input, RecordOutput output) {
152            output.writeFast(input.readFast());
153        }
154
155        @Override
156        Object newPrimitiveArray(int len, EntityInput input) {
157            boolean[] a = new boolean[len];
158            for (int i = 0; i < len; i += 1) {
159                a[i] = input.readBoolean();
160            }
161            return a;
162        }
163
164        @Override
165        void writePrimitiveArray(Object o, EntityOutput output) {
166            boolean[] a = (boolean[]) o;
167            int len = a.length;
168            output.writeArrayLength(len);
169            for (int i = 0; i < len; i += 1) {
170                output.writeBoolean(a[i]);
171            }
172        }
173
174        @Override
175        int getPrimitiveLength() {
176            return 1;
177        }
178
179        @Override
180        void readPrimitiveField(Object o, EntityInput input, Field field)
181            throws IllegalAccessException {
182
183            field.setBoolean(o, input.readBoolean());
184        }
185
186        @Override
187        void writePrimitiveField(Object o, EntityOutput output, Field field)
188            throws IllegalAccessException {
189
190            output.writeBoolean(field.getBoolean(o));
191        }
192    }
193
194    public static class FByte extends SimpleFormat {
195
196        private static final long serialVersionUID = 3651752958101447257L;
197
198        FByte(boolean primitive) {
199            super(primitive ? Byte.TYPE : Byte.class, primitive);
200        }
201
202        @Override
203        Object newArray(int len) {
204            return new Byte[len];
205        }
206
207        @Override
208        public Object newInstance(EntityInput input, boolean rawAccess) {
209            return Byte.valueOf(input.readByte());
210        }
211
212        @Override
213        void writeObject(Object o, EntityOutput output, boolean rawAccess) {
214            output.writeByte(((Number) o).byteValue());
215        }
216
217        @Override
218        void skipContents(RecordInput input) {
219            input.skipFast(1);
220        }
221
222        @Override
223        void copySecKey(RecordInput input, RecordOutput output) {
224            output.writeFast(input.readFast());
225        }
226
227        @Override
228        Object newPrimitiveArray(int len, EntityInput input) {
229            byte[] a = new byte[len];
230            for (int i = 0; i < len; i += 1) {
231                a[i] = input.readByte();
232            }
233            return a;
234        }
235
236        @Override
237        void writePrimitiveArray(Object o, EntityOutput output) {
238            byte[] a = (byte[]) o;
239            int len = a.length;
240            output.writeArrayLength(len);
241            for (int i = 0; i < len; i += 1) {
242                output.writeByte(a[i]);
243            }
244        }
245
246        @Override
247        int getPrimitiveLength() {
248            return 1;
249        }
250
251        @Override
252        void readPrimitiveField(Object o, EntityInput input, Field field)
253            throws IllegalAccessException {
254
255            field.setByte(o, input.readByte());
256        }
257
258        @Override
259        void writePrimitiveField(Object o, EntityOutput output, Field field)
260            throws IllegalAccessException {
261
262            output.writeByte(field.getByte(o));
263        }
264
265        @Override
266        Format getSequenceKeyFormat() {
267            return this;
268        }
269    }
270
271    public static class FShort extends SimpleFormat {
272
273        private static final long serialVersionUID = -4909138198491785624L;
274
275        FShort(boolean primitive) {
276            super(primitive ? Short.TYPE : Short.class, primitive);
277        }
278
279        @Override
280        Object newArray(int len) {
281            return new Short[len];
282        }
283
284        @Override
285        public Object newInstance(EntityInput input, boolean rawAccess) {
286            return Short.valueOf(input.readShort());
287        }
288
289        @Override
290        void writeObject(Object o, EntityOutput output, boolean rawAccess) {
291            output.writeShort(((Number) o).shortValue());
292        }
293
294        @Override
295        void skipContents(RecordInput input) {
296            input.skipFast(2);
297        }
298
299        @Override
300        void copySecKey(RecordInput input, RecordOutput output) {
301            output.writeFast(input.readFast());
302            output.writeFast(input.readFast());
303        }
304
305        @Override
306        Object newPrimitiveArray(int len, EntityInput input) {
307            short[] a = new short[len];
308            for (int i = 0; i < len; i += 1) {
309                a[i] = input.readShort();
310            }
311            return a;
312        }
313
314        @Override
315        void writePrimitiveArray(Object o, EntityOutput output) {
316            short[] a = (short[]) o;
317            int len = a.length;
318            output.writeArrayLength(len);
319            for (int i = 0; i < len; i += 1) {
320                output.writeShort(a[i]);
321            }
322        }
323
324        @Override
325        int getPrimitiveLength() {
326            return 2;
327        }
328
329        @Override
330        void readPrimitiveField(Object o, EntityInput input, Field field)
331            throws IllegalAccessException {
332
333            field.setShort(o, input.readShort());
334        }
335
336        @Override
337        void writePrimitiveField(Object o, EntityOutput output, Field field)
338            throws IllegalAccessException {
339
340            output.writeShort(field.getShort(o));
341        }
342
343        @Override
344        Format getSequenceKeyFormat() {
345            return this;
346        }
347    }
348
349    public static class FInt extends SimpleFormat {
350
351        private static final long serialVersionUID = 2695910006049980013L;
352
353        FInt(boolean primitive) {
354            super(primitive ? Integer.TYPE : Integer.class, primitive);
355        }
356
357        @Override
358        Object newArray(int len) {
359            return new Integer[len];
360        }
361
362        @Override
363        public Object newInstance(EntityInput input, boolean rawAccess) {
364            return Integer.valueOf(input.readInt());
365        }
366
367        @Override
368        void writeObject(Object o, EntityOutput output, boolean rawAccess) {
369            output.writeInt(((Number) o).intValue());
370        }
371
372        @Override
373        void skipContents(RecordInput input) {
374            input.skipFast(4);
375        }
376
377        @Override
378        void copySecKey(RecordInput input, RecordOutput output) {
379            output.writeFast(input.readFast());
380            output.writeFast(input.readFast());
381            output.writeFast(input.readFast());
382            output.writeFast(input.readFast());
383        }
384
385        @Override
386        Object newPrimitiveArray(int len, EntityInput input) {
387            int[] a = new int[len];
388            for (int i = 0; i < len; i += 1) {
389                a[i] = input.readInt();
390            }
391            return a;
392        }
393
394        @Override
395        void writePrimitiveArray(Object o, EntityOutput output) {
396            int[] a = (int[]) o;
397            int len = a.length;
398            output.writeArrayLength(len);
399            for (int i = 0; i < len; i += 1) {
400                output.writeInt(a[i]);
401            }
402        }
403
404        @Override
405        int getPrimitiveLength() {
406            return 4;
407        }
408
409        @Override
410        void readPrimitiveField(Object o, EntityInput input, Field field)
411            throws IllegalAccessException {
412
413            field.setInt(o, input.readInt());
414        }
415
416        @Override
417        void writePrimitiveField(Object o, EntityOutput output, Field field)
418            throws IllegalAccessException {
419
420            output.writeInt(field.getInt(o));
421        }
422
423        @Override
424        Format getSequenceKeyFormat() {
425            return this;
426        }
427    }
428
429    public static class FLong extends SimpleFormat {
430
431        private static final long serialVersionUID = 1872661106534776520L;
432
433        FLong(boolean primitive) {
434            super(primitive ? Long.TYPE : Long.class, primitive);
435        }
436
437        @Override
438        Object newArray(int len) {
439            return new Long[len];
440        }
441
442        @Override
443        public Object newInstance(EntityInput input, boolean rawAccess) {
444            return Long.valueOf(input.readLong());
445        }
446
447        @Override
448        void writeObject(Object o, EntityOutput output, boolean rawAccess) {
449            output.writeLong(((Number) o).longValue());
450        }
451
452        @Override
453        void skipContents(RecordInput input) {
454            input.skipFast(8);
455        }
456
457        @Override
458        void copySecKey(RecordInput input, RecordOutput output) {
459            output.writeFast
460                (input.getBufferBytes(), input.getBufferOffset(), 8);
461            input.skipFast(8);
462        }
463
464        @Override
465        Object newPrimitiveArray(int len, EntityInput input) {
466            long[] a = new long[len];
467            for (int i = 0; i < len; i += 1) {
468                a[i] = input.readLong();
469            }
470            return a;
471        }
472
473        @Override
474        void writePrimitiveArray(Object o, EntityOutput output) {
475            long[] a = (long[]) o;
476            int len = a.length;
477            output.writeArrayLength(len);
478            for (int i = 0; i < len; i += 1) {
479                output.writeLong(a[i]);
480            }
481        }
482
483        @Override
484        int getPrimitiveLength() {
485            return 8;
486        }
487
488        @Override
489        void readPrimitiveField(Object o, EntityInput input, Field field)
490            throws IllegalAccessException {
491
492            field.setLong(o, input.readLong());
493        }
494
495        @Override
496        void writePrimitiveField(Object o, EntityOutput output, Field field)
497            throws IllegalAccessException {
498
499            output.writeLong(field.getLong(o));
500        }
501
502        @Override
503        Format getSequenceKeyFormat() {
504            return this;
505        }
506    }
507
508    public static class FFloat extends SimpleFormat {
509
510        private static final long serialVersionUID = 1033413049495053602L;
511
512        FFloat(boolean primitive) {
513            super(primitive ? Float.TYPE : Float.class, primitive);
514        }
515
516        @Override
517        Object newArray(int len) {
518            return new Float[len];
519        }
520
521        @Override
522        public Object newInstance(EntityInput input, boolean rawAccess) {
523            return Float.valueOf(input.readSortedFloat());
524        }
525
526        @Override
527        void writeObject(Object o, EntityOutput output, boolean rawAccess) {
528            output.writeSortedFloat(((Number) o).floatValue());
529        }
530
531        @Override
532        void skipContents(RecordInput input) {
533            input.skipFast(4);
534        }
535
536        @Override
537        void copySecKey(RecordInput input, RecordOutput output) {
538            output.writeFast(input.readFast());
539            output.writeFast(input.readFast());
540            output.writeFast(input.readFast());
541            output.writeFast(input.readFast());
542        }
543
544        @Override
545        Object newPrimitiveArray(int len, EntityInput input) {
546            float[] a = new float[len];
547            for (int i = 0; i < len; i += 1) {
548                a[i] = input.readSortedFloat();
549            }
550            return a;
551        }
552
553        @Override
554        void writePrimitiveArray(Object o, EntityOutput output) {
555            float[] a = (float[]) o;
556            int len = a.length;
557            output.writeArrayLength(len);
558            for (int i = 0; i < len; i += 1) {
559                output.writeSortedFloat(a[i]);
560            }
561        }
562
563        @Override
564        int getPrimitiveLength() {
565            return 4;
566        }
567
568        @Override
569        void readPrimitiveField(Object o, EntityInput input, Field field)
570            throws IllegalAccessException {
571
572            field.setFloat(o, input.readSortedFloat());
573        }
574
575        @Override
576        void writePrimitiveField(Object o, EntityOutput output, Field field)
577            throws IllegalAccessException {
578
579            output.writeSortedFloat(field.getFloat(o));
580        }
581    }
582
583    public static class FDouble extends SimpleFormat {
584
585        private static final long serialVersionUID = 646904456811041423L;
586
587        FDouble(boolean primitive) {
588            super(primitive ? Double.TYPE : Double.class, primitive);
589        }
590
591        @Override
592        Object newArray(int len) {
593            return new Double[len];
594        }
595
596        @Override
597        public Object newInstance(EntityInput input, boolean rawAccess) {
598            return Double.valueOf(input.readSortedDouble());
599        }
600
601        @Override
602        void writeObject(Object o, EntityOutput output, boolean rawAccess) {
603            output.writeSortedDouble(((Number) o).doubleValue());
604        }
605
606        @Override
607        void skipContents(RecordInput input) {
608            input.skipFast(8);
609        }
610
611        @Override
612        void copySecKey(RecordInput input, RecordOutput output) {
613            output.writeFast
614                (input.getBufferBytes(), input.getBufferOffset(), 8);
615            input.skipFast(8);
616        }
617
618        @Override
619        Object newPrimitiveArray(int len, EntityInput input) {
620            double[] a = new double[len];
621            for (int i = 0; i < len; i += 1) {
622                a[i] = input.readSortedDouble();
623            }
624            return a;
625        }
626
627        @Override
628        void writePrimitiveArray(Object o, EntityOutput output) {
629            double[] a = (double[]) o;
630            int len = a.length;
631            output.writeArrayLength(len);
632            for (int i = 0; i < len; i += 1) {
633                output.writeSortedDouble(a[i]);
634            }
635        }
636
637        @Override
638        int getPrimitiveLength() {
639            return 8;
640        }
641
642        @Override
643        void readPrimitiveField(Object o, EntityInput input, Field field)
644            throws IllegalAccessException {
645
646            field.setDouble(o, input.readSortedDouble());
647        }
648
649        @Override
650        void writePrimitiveField(Object o, EntityOutput output, Field field)
651            throws IllegalAccessException {
652
653            output.writeSortedDouble(field.getDouble(o));
654        }
655    }
656
657    public static class FChar extends SimpleFormat {
658
659        private static final long serialVersionUID = -7609118195770005374L;
660
661        FChar(boolean primitive) {
662            super(primitive ? Character.TYPE : Character.class, primitive);
663        }
664
665        @Override
666        Object newArray(int len) {
667            return new Character[len];
668        }
669
670        @Override
671        public Object newInstance(EntityInput input, boolean rawAccess) {
672            return Character.valueOf(input.readChar());
673        }
674
675        @Override
676        void writeObject(Object o, EntityOutput output, boolean rawAccess) {
677            output.writeChar(((Character) o).charValue());
678        }
679
680        @Override
681        void skipContents(RecordInput input) {
682            input.skipFast(2);
683        }
684
685        @Override
686        void copySecKey(RecordInput input, RecordOutput output) {
687            output.writeFast(input.readFast());
688            output.writeFast(input.readFast());
689        }
690
691        @Override
692        Object newPrimitiveArray(int len, EntityInput input) {
693            char[] a = new char[len];
694            for (int i = 0; i < len; i += 1) {
695                a[i] = input.readChar();
696            }
697            return a;
698        }
699
700        @Override
701        void writePrimitiveArray(Object o, EntityOutput output) {
702            char[] a = (char[]) o;
703            int len = a.length;
704            output.writeArrayLength(len);
705            for (int i = 0; i < len; i += 1) {
706                output.writeChar(a[i]);
707            }
708        }
709
710        @Override
711        int getPrimitiveLength() {
712            return 2;
713        }
714
715        @Override
716        void readPrimitiveField(Object o, EntityInput input, Field field)
717            throws IllegalAccessException {
718
719            field.setChar(o, input.readChar());
720        }
721
722        @Override
723        void writePrimitiveField(Object o, EntityOutput output, Field field)
724            throws IllegalAccessException {
725
726            output.writeChar(field.getChar(o));
727        }
728    }
729
730    public static class FString extends SimpleFormat {
731
732        private static final long serialVersionUID = 5710392786480064612L;
733
734        FString() {
735            super(String.class, false);
736        }
737
738        @Override
739        Object newArray(int len) {
740            return new String[len];
741        }
742
743        @Override
744        public Object newInstance(EntityInput input, boolean rawAccess) {
745            return input.readString();
746        }
747
748        @Override
749        void writeObject(Object o, EntityOutput output, boolean rawAccess) {
750            output.writeString((String) o);
751        }
752
753        @Override
754        void skipContents(RecordInput input) {
755            input.skipFast(input.getStringByteLength());
756        }
757
758        @Override
759        void copySecKey(RecordInput input, RecordOutput output) {
760            int len = input.getStringByteLength();
761            output.writeFast
762                (input.getBufferBytes(), input.getBufferOffset(), len);
763            input.skipFast(len);
764        }
765    }
766
767    public static class FBigInt extends SimpleFormat {
768
769        private static final long serialVersionUID = -5027098112507644563L;
770
771        FBigInt() {
772            super(BigInteger.class, false);
773        }
774
775        @Override
776        Object newArray(int len) {
777            return new BigInteger[len];
778        }
779
780        @Override
781        public Object newInstance(EntityInput input, boolean rawAccess) {
782            return input.readBigInteger();
783        }
784
785        @Override
786        void writeObject(Object o, EntityOutput output, boolean rawAccess) {
787            output.writeBigInteger((BigInteger) o);
788        }
789
790        @Override
791        void skipContents(RecordInput input) {
792            input.skipFast(input.getBigIntegerByteLength());
793        }
794
795        @Override
796        void copySecKey(RecordInput input, RecordOutput output) {
797            int len = input.getBigIntegerByteLength();
798            output.writeFast
799                (input.getBufferBytes(), input.getBufferOffset(), len);
800            input.skipFast(len);
801        }
802    }
803
804    public static class FDate extends SimpleFormat {
805
806        private static final long serialVersionUID = -5665773229869034145L;
807
808        FDate() {
809            super(Date.class, false);
810        }
811
812        @Override
813        Object newArray(int len) {
814            return new Date[len];
815        }
816
817        @Override
818        public Object newInstance(EntityInput input, boolean rawAccess) {
819            return new Date(input.readLong());
820        }
821
822        @Override
823        void writeObject(Object o, EntityOutput output, boolean rawAccess) {
824            output.writeLong(((Date) o).getTime());
825        }
826
827        @Override
828        void skipContents(RecordInput input) {
829            input.skipFast(8);
830        }
831
832        @Override
833        void copySecKey(RecordInput input, RecordOutput output) {
834            output.writeFast
835                (input.getBufferBytes(), input.getBufferOffset(), 8);
836            input.skipFast(8);
837        }
838    }
839}
840