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.marshal;
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 MarshalledKeyCreator(javaCatalog,
105: Supplier.class, Supplier.CITY_KEY));
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 MarshalledKeyCreator(javaCatalog,
113: Shipment.class, Shipment.PART_KEY));
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 MarshalledKeyCreator(javaCatalog,
121: Shipment.class, Shipment.SUPPLIER_KEY));
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 MarshalledEntity objects. 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 MarshalledKeyCreator extends
214: TupleSerialKeyCreator {
215:
216: private String keyName;
217:
218: /**
219: * Construct the key creator.
220: * @param catalog is the class catalog.
221: * @param valueClass is the supplier value class.
222: * @param keyName is the key name passed to the marshalling methods.
223: */
224: private MarshalledKeyCreator(ClassCatalog catalog,
225: Class valueClass, String keyName) {
226:
227: super (catalog, valueClass);
228: this .keyName = keyName;
229: }
230:
231: /**
232: * Extract the city key from a supplier key/value pair. The city key
233: * is stored in the supplier value, so the supplier key is not used.
234: */
235: public boolean createSecondaryKey(TupleInput primaryKeyInput,
236: Object valueInput, TupleOutput indexKeyOutput) {
237:
238: // the primary key is unmarshalled before marshalling the index
239: // key, to account for cases where the index key is composed of
240: // data elements from the primary key
241: MarshalledEntity entity = (MarshalledEntity) valueInput;
242: entity.unmarshalPrimaryKey(primaryKeyInput);
243: return entity.marshalSecondaryKey(keyName, indexKeyOutput);
244: }
245: }
246: }
|