001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: SampleDatabase.java,v 1.24.2.2 2008/01/07 15:14:02 cwl Exp $
007: */
008:
009: package collections.ship.sentity;
010:
011: import java.io.File;
012: import java.io.FileNotFoundException;
013:
014: import com.sleepycat.bind.serial.ClassCatalog;
015: import com.sleepycat.bind.serial.StoredClassCatalog;
016: import com.sleepycat.bind.serial.TupleSerialKeyCreator;
017: import com.sleepycat.bind.tuple.TupleInput;
018: import com.sleepycat.bind.tuple.TupleOutput;
019: import com.sleepycat.je.Database;
020: import com.sleepycat.je.DatabaseConfig;
021: import com.sleepycat.je.DatabaseException;
022: import com.sleepycat.je.Environment;
023: import com.sleepycat.je.EnvironmentConfig;
024: import com.sleepycat.je.ForeignKeyDeleteAction;
025: import com.sleepycat.je.SecondaryConfig;
026: import com.sleepycat.je.SecondaryDatabase;
027:
028: /**
029: * SampleDatabase defines the storage containers, indices and foreign keys
030: * for the sample database.
031: *
032: * @author Mark Hayes
033: */
034: public class SampleDatabase {
035:
036: private static final String CLASS_CATALOG = "java_class_catalog";
037: private static final String SUPPLIER_STORE = "supplier_store";
038: private static final String PART_STORE = "part_store";
039: private static final String SHIPMENT_STORE = "shipment_store";
040: private static final String SHIPMENT_PART_INDEX = "shipment_part_index";
041: private static final String SHIPMENT_SUPPLIER_INDEX = "shipment_supplier_index";
042: private static final String SUPPLIER_CITY_INDEX = "supplier_city_index";
043:
044: private Environment env;
045: private Database partDb;
046: private Database supplierDb;
047: private Database shipmentDb;
048: private SecondaryDatabase supplierByCityDb;
049: private SecondaryDatabase shipmentByPartDb;
050: private SecondaryDatabase shipmentBySupplierDb;
051: private StoredClassCatalog javaCatalog;
052:
053: /**
054: * Open all storage containers, indices, and catalogs.
055: */
056: public SampleDatabase(String homeDirectory)
057: throws DatabaseException, FileNotFoundException {
058:
059: // Open the Berkeley DB environment in transactional mode.
060: //
061: System.out.println("Opening environment in: " + homeDirectory);
062: EnvironmentConfig envConfig = new EnvironmentConfig();
063: envConfig.setTransactional(true);
064: envConfig.setAllowCreate(true);
065: env = new Environment(new File(homeDirectory), envConfig);
066:
067: // Set the Berkeley DB config for opening all stores.
068: //
069: DatabaseConfig dbConfig = new DatabaseConfig();
070: dbConfig.setTransactional(true);
071: dbConfig.setAllowCreate(true);
072:
073: // Create the Serial class catalog. This holds the serialized class
074: // format for all database records of serial format.
075: //
076: Database catalogDb = env.openDatabase(null, CLASS_CATALOG,
077: dbConfig);
078: javaCatalog = new StoredClassCatalog(catalogDb);
079:
080: // Open the Berkeley DB database for the part, supplier and shipment
081: // stores. The stores are opened with no duplicate keys allowed.
082: //
083: partDb = env.openDatabase(null, PART_STORE, dbConfig);
084:
085: supplierDb = env.openDatabase(null, SUPPLIER_STORE, dbConfig);
086:
087: shipmentDb = env.openDatabase(null, SHIPMENT_STORE, dbConfig);
088:
089: // Open the SecondaryDatabase for the city index of the supplier store,
090: // and for the part and supplier indices of the shipment store.
091: // Duplicate keys are allowed since more than one supplier may be in
092: // the same city, and more than one shipment may exist for the same
093: // supplier or part. A foreign key constraint is defined for the
094: // supplier and part indices to ensure that a shipment only refers to
095: // existing part and supplier keys. The CASCADE delete action means
096: // that shipments will be deleted if their associated part or supplier
097: // is deleted.
098: //
099: SecondaryConfig secConfig = new SecondaryConfig();
100: secConfig.setTransactional(true);
101: secConfig.setAllowCreate(true);
102: secConfig.setSortedDuplicates(true);
103:
104: secConfig.setKeyCreator(new SupplierByCityKeyCreator(
105: javaCatalog, Supplier.class));
106: supplierByCityDb = env.openSecondaryDatabase(null,
107: SUPPLIER_CITY_INDEX, supplierDb, secConfig);
108:
109: secConfig.setForeignKeyDatabase(partDb);
110: secConfig
111: .setForeignKeyDeleteAction(ForeignKeyDeleteAction.CASCADE);
112: secConfig.setKeyCreator(new ShipmentByPartKeyCreator(
113: javaCatalog, Shipment.class));
114: shipmentByPartDb = env.openSecondaryDatabase(null,
115: SHIPMENT_PART_INDEX, shipmentDb, secConfig);
116:
117: secConfig.setForeignKeyDatabase(supplierDb);
118: secConfig
119: .setForeignKeyDeleteAction(ForeignKeyDeleteAction.CASCADE);
120: secConfig.setKeyCreator(new ShipmentBySupplierKeyCreator(
121: javaCatalog, Shipment.class));
122: shipmentBySupplierDb = env.openSecondaryDatabase(null,
123: SHIPMENT_SUPPLIER_INDEX, shipmentDb, secConfig);
124: }
125:
126: /**
127: * Return the storage environment for the database.
128: */
129: public final Environment getEnvironment() {
130:
131: return env;
132: }
133:
134: /**
135: * Return the class catalog.
136: */
137: public final StoredClassCatalog getClassCatalog() {
138:
139: return javaCatalog;
140: }
141:
142: /**
143: * Return the part storage container.
144: */
145: public final Database getPartDatabase() {
146:
147: return partDb;
148: }
149:
150: /**
151: * Return the supplier storage container.
152: */
153: public final Database getSupplierDatabase() {
154:
155: return supplierDb;
156: }
157:
158: /**
159: * Return the shipment storage container.
160: */
161: public final Database getShipmentDatabase() {
162:
163: return shipmentDb;
164: }
165:
166: /**
167: * Return the shipment-by-part index.
168: */
169: public final SecondaryDatabase getShipmentByPartDatabase() {
170:
171: return shipmentByPartDb;
172: }
173:
174: /**
175: * Return the shipment-by-supplier index.
176: */
177: public final SecondaryDatabase getShipmentBySupplierDatabase() {
178:
179: return shipmentBySupplierDb;
180: }
181:
182: /**
183: * Return the supplier-by-city index.
184: */
185: public final SecondaryDatabase getSupplierByCityDatabase() {
186:
187: return supplierByCityDb;
188: }
189:
190: /**
191: * Close all stores (closing a store automatically closes its indices).
192: */
193: public void close() throws DatabaseException {
194:
195: // Close secondary databases, then primary databases.
196: supplierByCityDb.close();
197: shipmentByPartDb.close();
198: shipmentBySupplierDb.close();
199: partDb.close();
200: supplierDb.close();
201: shipmentDb.close();
202: // And don't forget to close the catalog and the environment.
203: javaCatalog.close();
204: env.close();
205: }
206:
207: /**
208: * The SecondaryKeyCreator for the SupplierByCity index. This is an
209: * extension of the abstract class TupleSerialKeyCreator, which implements
210: * SecondaryKeyCreator for the case where the data keys are of the format
211: * TupleFormat and the data values are of the format SerialFormat.
212: */
213: private static class SupplierByCityKeyCreator extends
214: TupleSerialKeyCreator {
215:
216: /**
217: * Construct the city key extractor.
218: * @param catalog is the class catalog.
219: * @param valueClass is the supplier value class.
220: */
221: private SupplierByCityKeyCreator(ClassCatalog catalog,
222: Class valueClass) {
223:
224: super (catalog, valueClass);
225: }
226:
227: /**
228: * Extract the city key from a supplier key/value pair. The city key
229: * is stored in the supplier value, so the supplier key is not used.
230: */
231: public boolean createSecondaryKey(TupleInput primaryKeyInput,
232: Object valueInput, TupleOutput indexKeyOutput) {
233:
234: Supplier supplier = (Supplier) valueInput;
235: String city = supplier.getCity();
236: if (city != null) {
237: indexKeyOutput.writeString(supplier.getCity());
238: return true;
239: } else {
240: return false;
241: }
242: }
243: }
244:
245: /**
246: * The SecondaryKeyCreator for the ShipmentByPart index. This is an
247: * extension of the abstract class TupleSerialKeyCreator, which implements
248: * SecondaryKeyCreator for the case where the data keys are of the format
249: * TupleFormat and the data values are of the format SerialFormat.
250: */
251: private static class ShipmentByPartKeyCreator extends
252: TupleSerialKeyCreator {
253:
254: /**
255: * Construct the part key extractor.
256: * @param catalog is the class catalog.
257: * @param valueClass is the shipment value class.
258: */
259: private ShipmentByPartKeyCreator(ClassCatalog catalog,
260: Class valueClass) {
261: super (catalog, valueClass);
262: }
263:
264: /**
265: * Extract the part key from a shipment key/value pair. The part key
266: * is stored in the shipment key, so the shipment value is not used.
267: */
268: public boolean createSecondaryKey(TupleInput primaryKeyInput,
269: Object valueInput, TupleOutput indexKeyOutput) {
270:
271: String partNumber = primaryKeyInput.readString();
272: // don't bother reading the supplierNumber
273: indexKeyOutput.writeString(partNumber);
274: return true;
275: }
276: }
277:
278: /**
279: * The SecondaryKeyCreator for the ShipmentBySupplier index. This is an
280: * extension of the abstract class TupleSerialKeyCreator, which implements
281: * SecondaryKeyCreator for the case where the data keys are of the format
282: * TupleFormat and the data values are of the format SerialFormat.
283: */
284: private static class ShipmentBySupplierKeyCreator extends
285: TupleSerialKeyCreator {
286:
287: /**
288: * Construct the supplier key extractor.
289: * @param catalog is the class catalog.
290: * @param valueClass is the shipment value class.
291: */
292: private ShipmentBySupplierKeyCreator(ClassCatalog catalog,
293: Class valueClass) {
294: super (catalog, valueClass);
295: }
296:
297: /**
298: * Extract the supplier key from a shipment key/value pair. The
299: * supplier key is stored in the shipment key, so the shipment value is
300: * not used.
301: */
302: public boolean createSecondaryKey(TupleInput primaryKeyInput,
303: Object valueInput, TupleOutput indexKeyOutput) {
304:
305: primaryKeyInput.readString(); // skip the partNumber
306: String supplierNumber = primaryKeyInput.readString();
307: indexKeyOutput.writeString(supplierNumber);
308: return true;
309: }
310: }
311: }
|