1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: SampleViews.java,v 12.7 2008/01/08 20:58:30 bostic Exp $
7 */
8
9package collections.ship.marshal;
10
11import com.sleepycat.bind.EntityBinding;
12import com.sleepycat.bind.EntryBinding;
13import com.sleepycat.bind.serial.ClassCatalog;
14import com.sleepycat.bind.serial.TupleSerialBinding;
15import com.sleepycat.bind.tuple.TupleBinding;
16import com.sleepycat.bind.tuple.TupleInput;
17import com.sleepycat.bind.tuple.TupleOutput;
18import com.sleepycat.collections.StoredSortedMap;
19import com.sleepycat.collections.StoredSortedValueSet;
20import com.sleepycat.util.RuntimeExceptionWrapper;
21
22/**
23 * SampleViews defines the data bindings and collection views for the sample
24 * database.
25 *
26 * @author Mark Hayes
27 */
28public class SampleViews {
29
30    private StoredSortedMap partMap;
31    private StoredSortedMap supplierMap;
32    private StoredSortedMap shipmentMap;
33    private StoredSortedMap shipmentByPartMap;
34    private StoredSortedMap shipmentBySupplierMap;
35    private StoredSortedMap supplierByCityMap;
36
37    /**
38     * Create the data bindings and collection views.
39     */
40    public SampleViews(SampleDatabase db) {
41
42        // Create the data bindings.
43        // In this sample, EntityBinding classes are used to bind the stored
44        // key/data entry pair to a combined data object; a "tricky" binding
45        // that uses transient fields is used--see PartBinding, etc, for
46        // details.  For keys, a one-to-one binding is implemented with
47        // EntryBinding classes to bind the stored tuple entry to a key Object.
48        //
49        ClassCatalog catalog = db.getClassCatalog();
50        EntryBinding partKeyBinding =
51            new MarshalledKeyBinding(PartKey.class);
52        EntityBinding partDataBinding =
53            new MarshalledEntityBinding(catalog, Part.class);
54        EntryBinding supplierKeyBinding =
55            new MarshalledKeyBinding(SupplierKey.class);
56        EntityBinding supplierDataBinding =
57            new MarshalledEntityBinding(catalog, Supplier.class);
58        EntryBinding shipmentKeyBinding =
59            new MarshalledKeyBinding(ShipmentKey.class);
60        EntityBinding shipmentDataBinding =
61            new MarshalledEntityBinding(catalog, Shipment.class);
62        EntryBinding cityKeyBinding =
63            TupleBinding.getPrimitiveBinding(String.class);
64
65        // Create map views for all stores and indices.
66        // StoredSortedMap is used since the stores and indices are ordered
67        // (they use the DB_BTREE access method).
68        //
69        partMap =
70            new StoredSortedMap(db.getPartDatabase(),
71				partKeyBinding, partDataBinding, true);
72        supplierMap =
73            new StoredSortedMap(db.getSupplierDatabase(),
74				supplierKeyBinding, supplierDataBinding, true);
75        shipmentMap =
76            new StoredSortedMap(db.getShipmentDatabase(),
77				shipmentKeyBinding, shipmentDataBinding, true);
78        shipmentByPartMap =
79            new StoredSortedMap(db.getShipmentByPartDatabase(),
80                                partKeyBinding, shipmentDataBinding, true);
81        shipmentBySupplierMap =
82            new StoredSortedMap(db.getShipmentBySupplierDatabase(),
83                                supplierKeyBinding, shipmentDataBinding, true);
84        supplierByCityMap =
85            new StoredSortedMap(db.getSupplierByCityDatabase(),
86                                cityKeyBinding, supplierDataBinding, true);
87    }
88
89    // The views returned below can be accessed using the java.util.Map or
90    // java.util.Set interfaces, or using the StoredSortedMap and
91    // StoredValueSet classes, which provide additional methods.  The entity
92    // sets could be obtained directly from the Map.values() method but
93    // convenience methods are provided here to return them in order to avoid
94    // down-casting elsewhere.
95
96    /**
97     * Return a map view of the part storage container.
98     */
99    public StoredSortedMap getPartMap() {
100
101        return partMap;
102    }
103
104    /**
105     * Return a map view of the supplier storage container.
106     */
107    public StoredSortedMap getSupplierMap() {
108
109        return supplierMap;
110    }
111
112    /**
113     * Return a map view of the shipment storage container.
114     */
115    public StoredSortedMap getShipmentMap() {
116
117        return shipmentMap;
118    }
119
120    /**
121     * Return an entity set view of the part storage container.
122     */
123    public StoredSortedValueSet getPartSet() {
124
125        return (StoredSortedValueSet) partMap.values();
126    }
127
128    /**
129     * Return an entity set view of the supplier storage container.
130     */
131    public StoredSortedValueSet getSupplierSet() {
132
133        return (StoredSortedValueSet) supplierMap.values();
134    }
135
136    /**
137     * Return an entity set view of the shipment storage container.
138     */
139    public StoredSortedValueSet getShipmentSet() {
140
141        return (StoredSortedValueSet) shipmentMap.values();
142    }
143
144    /**
145     * Return a map view of the shipment-by-part index.
146     */
147    public StoredSortedMap getShipmentByPartMap() {
148
149        return shipmentByPartMap;
150    }
151
152    /**
153     * Return a map view of the shipment-by-supplier index.
154     */
155    public StoredSortedMap getShipmentBySupplierMap() {
156
157        return shipmentBySupplierMap;
158    }
159
160    /**
161     * Return a map view of the supplier-by-city index.
162     */
163    public final StoredSortedMap getSupplierByCityMap() {
164
165        return supplierByCityMap;
166    }
167
168    /**
169     * MarshalledKeyBinding is used to bind the stored key tuple entry to a key
170     * object representation.  To do this, it calls the MarshalledKey interface
171     * implemented by the key class.
172     */
173    private static class MarshalledKeyBinding extends TupleBinding {
174
175        private Class keyClass;
176
177        /**
178         * Construct the binding object.
179         */
180        private MarshalledKeyBinding(Class keyClass) {
181
182            // The key class will be used to instantiate the key object.
183            //
184            if (!MarshalledKey.class.isAssignableFrom(keyClass)) {
185                throw new IllegalArgumentException(keyClass.toString() +
186                                       " does not implement MarshalledKey");
187            }
188            this.keyClass = keyClass;
189        }
190
191        /**
192         * Create the key object from the stored key tuple entry.
193         */
194        public Object entryToObject(TupleInput input) {
195
196            try {
197                MarshalledKey key = (MarshalledKey) keyClass.newInstance();
198                key.unmarshalKey(input);
199                return key;
200            } catch (IllegalAccessException e) {
201                throw new RuntimeExceptionWrapper(e);
202            } catch (InstantiationException e) {
203                throw new RuntimeExceptionWrapper(e);
204            }
205        }
206
207        /**
208         * Create the stored key tuple entry from the key object.
209         */
210        public void objectToEntry(Object object, TupleOutput output) {
211
212            MarshalledKey key = (MarshalledKey) object;
213            key.marshalKey(output);
214        }
215    }
216
217    /**
218     * MarshalledEntityBinding is used to bind the stored key/data entry pair
219     * to a combined to an entity object representation.  To do this, it calls
220     * the MarshalledEnt interface implemented by the entity class.
221     *
222     * <p> The binding is "tricky" in that it uses the entity class for both
223     * the stored data entry and the combined entity object.  To do this,
224     * entity's key field(s) are transient and are set by the binding after the
225     * data object has been deserialized. This avoids the use of a "data" class
226     * completely. </p>
227     */
228    private static class MarshalledEntityBinding extends TupleSerialBinding {
229
230        /**
231         * Construct the binding object.
232         */
233        private MarshalledEntityBinding(ClassCatalog classCatalog,
234                                        Class entityClass) {
235
236            super(classCatalog, entityClass);
237
238            // The entity class will be used to instantiate the entity object.
239            //
240            if (!MarshalledEnt.class.isAssignableFrom(entityClass)) {
241                throw new IllegalArgumentException(entityClass.toString() +
242                                       " does not implement MarshalledEnt");
243            }
244        }
245
246        /**
247         * Create the entity by combining the stored key and data.
248         * This "tricky" binding returns the stored data as the entity, but
249         * first it sets the transient key fields from the stored key.
250         */
251        public Object entryToObject(TupleInput tupleInput, Object javaInput) {
252
253            MarshalledEnt entity = (MarshalledEnt) javaInput;
254            entity.unmarshalPrimaryKey(tupleInput);
255            return entity;
256        }
257
258        /**
259         * Create the stored key from the entity.
260         */
261        public void objectToKey(Object object, TupleOutput output) {
262
263            MarshalledEnt entity = (MarshalledEnt) object;
264            entity.marshalPrimaryKey(output);
265        }
266
267        /**
268         * Return the entity as the stored data.  There is nothing to do here
269         * since the entity's key fields are transient.
270         */
271        public Object objectToData(Object object) {
272
273            return object;
274        }
275    }
276}
277