1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002,2008 Oracle. All rights reserved. 5 * 6 * $Id: SampleDatabase.java,v 12.8 2008/02/07 17:12:22 mark Exp $ 7 */ 8 9package collections.ship.index; 10 11import java.io.File; 12import java.io.FileNotFoundException; 13 14import com.sleepycat.bind.serial.ClassCatalog; 15import com.sleepycat.bind.serial.SerialSerialKeyCreator; 16import com.sleepycat.bind.serial.StoredClassCatalog; 17import com.sleepycat.db.Database; 18import com.sleepycat.db.DatabaseConfig; 19import com.sleepycat.db.DatabaseException; 20import com.sleepycat.db.DatabaseType; 21import com.sleepycat.db.Environment; 22import com.sleepycat.db.EnvironmentConfig; 23import com.sleepycat.db.ForeignKeyDeleteAction; 24import com.sleepycat.db.SecondaryConfig; 25import com.sleepycat.db.SecondaryDatabase; 26 27/** 28 * SampleDatabase defines the storage containers, indices and foreign keys 29 * for the sample database. 30 * 31 * @author Mark Hayes 32 */ 33public class SampleDatabase { 34 35 private static final String CLASS_CATALOG = "java_class_catalog"; 36 private static final String SUPPLIER_STORE = "supplier_store"; 37 private static final String PART_STORE = "part_store"; 38 private static final String SHIPMENT_STORE = "shipment_store"; 39 private static final String SHIPMENT_PART_INDEX = "shipment_part_index"; 40 private static final String SHIPMENT_SUPPLIER_INDEX = 41 "shipment_supplier_index"; 42 private static final String SUPPLIER_CITY_INDEX = "supplier_city_index"; 43 44 private Environment env; 45 private Database partDb; 46 private Database supplierDb; 47 private Database shipmentDb; 48 private SecondaryDatabase supplierByCityDb; 49 private SecondaryDatabase shipmentByPartDb; 50 private SecondaryDatabase shipmentBySupplierDb; 51 private StoredClassCatalog javaCatalog; 52 53 /** 54 * Open all storage containers, indices, and catalogs. 55 */ 56 public SampleDatabase(String homeDirectory) 57 throws DatabaseException, FileNotFoundException { 58 59 // Open the Berkeley DB environment in transactional mode. 60 // 61 System.out.println("Opening environment in: " + homeDirectory); 62 EnvironmentConfig envConfig = new EnvironmentConfig(); 63 envConfig.setTransactional(true); 64 envConfig.setAllowCreate(true); 65 envConfig.setInitializeCache(true); 66 envConfig.setInitializeLocking(true); 67 env = new Environment(new File(homeDirectory), envConfig); 68 69 // Set the Berkeley DB config for opening all stores. 70 // 71 DatabaseConfig dbConfig = new DatabaseConfig(); 72 dbConfig.setTransactional(true); 73 dbConfig.setAllowCreate(true); 74 dbConfig.setType(DatabaseType.BTREE); 75 76 // Create the Serial class catalog. This holds the serialized class 77 // format for all database records of serial format. 78 // 79 Database catalogDb = env.openDatabase(null, CLASS_CATALOG, null, 80 dbConfig); 81 javaCatalog = new StoredClassCatalog(catalogDb); 82 83 // Open the Berkeley DB database for the part, supplier and shipment 84 // stores. The stores are opened with no duplicate keys allowed. 85 // 86 partDb = env.openDatabase(null, PART_STORE, null, dbConfig); 87 88 supplierDb = env.openDatabase(null, SUPPLIER_STORE, null, dbConfig); 89 90 shipmentDb = env.openDatabase(null, SHIPMENT_STORE, null, dbConfig); 91 92 // Open the SecondaryDatabase for the city index of the supplier store, 93 // and for the part and supplier indices of the shipment store. 94 // Duplicate keys are allowed since more than one supplier may be in 95 // the same city, and more than one shipment may exist for the same 96 // supplier or part. A foreign key constraint is defined for the 97 // supplier and part indices to ensure that a shipment only refers to 98 // existing part and supplier keys. The CASCADE delete action means 99 // that shipments will be deleted if their associated part or supplier 100 // is deleted. 101 // 102 SecondaryConfig secConfig = new SecondaryConfig(); 103 secConfig.setTransactional(true); 104 secConfig.setAllowCreate(true); 105 secConfig.setType(DatabaseType.BTREE); 106 secConfig.setSortedDuplicates(true); 107 108 secConfig.setKeyCreator( 109 new SupplierByCityKeyCreator(javaCatalog, 110 SupplierKey.class, 111 SupplierData.class, 112 String.class)); 113 supplierByCityDb = env.openSecondaryDatabase(null, SUPPLIER_CITY_INDEX, 114 null, supplierDb, 115 secConfig); 116 117 secConfig.setForeignKeyDatabase(partDb); 118 secConfig.setForeignKeyDeleteAction(ForeignKeyDeleteAction.CASCADE); 119 secConfig.setKeyCreator( 120 new ShipmentByPartKeyCreator(javaCatalog, 121 ShipmentKey.class, 122 ShipmentData.class, 123 PartKey.class)); 124 shipmentByPartDb = env.openSecondaryDatabase(null, SHIPMENT_PART_INDEX, 125 null, shipmentDb, 126 secConfig); 127 128 secConfig.setForeignKeyDatabase(supplierDb); 129 secConfig.setForeignKeyDeleteAction(ForeignKeyDeleteAction.CASCADE); 130 secConfig.setKeyCreator( 131 new ShipmentBySupplierKeyCreator(javaCatalog, 132 ShipmentKey.class, 133 ShipmentData.class, 134 SupplierKey.class)); 135 shipmentBySupplierDb = env.openSecondaryDatabase(null, 136 SHIPMENT_SUPPLIER_INDEX, 137 null, shipmentDb, 138 secConfig); 139 } 140 141 /** 142 * Return the storage environment for the database. 143 */ 144 public final Environment getEnvironment() { 145 146 return env; 147 } 148 149 /** 150 * Return the class catalog. 151 */ 152 public final StoredClassCatalog getClassCatalog() { 153 154 return javaCatalog; 155 } 156 157 /** 158 * Return the part storage container. 159 */ 160 public final Database getPartDatabase() { 161 162 return partDb; 163 } 164 165 /** 166 * Return the supplier storage container. 167 */ 168 public final Database getSupplierDatabase() { 169 170 return supplierDb; 171 } 172 173 /** 174 * Return the shipment storage container. 175 */ 176 public final Database getShipmentDatabase() { 177 178 return shipmentDb; 179 } 180 181 /** 182 * Return the shipment-by-part index. 183 */ 184 public final SecondaryDatabase getShipmentByPartDatabase() { 185 186 return shipmentByPartDb; 187 } 188 189 /** 190 * Return the shipment-by-supplier index. 191 */ 192 public final SecondaryDatabase getShipmentBySupplierDatabase() { 193 194 return shipmentBySupplierDb; 195 } 196 197 /** 198 * Return the supplier-by-city index. 199 */ 200 public final SecondaryDatabase getSupplierByCityDatabase() { 201 202 return supplierByCityDb; 203 } 204 205 /** 206 * Close all stores (closing a store automatically closes its indices). 207 */ 208 public void close() 209 throws DatabaseException { 210 211 // Close secondary databases, then primary databases. 212 supplierByCityDb.close(); 213 shipmentByPartDb.close(); 214 shipmentBySupplierDb.close(); 215 partDb.close(); 216 supplierDb.close(); 217 shipmentDb.close(); 218 // And don't forget to close the catalog and the environment. 219 javaCatalog.close(); 220 env.close(); 221 } 222 223 /** 224 * The SecondaryKeyCreator for the SupplierByCity index. This is an 225 * extension of the abstract class SerialSerialKeyCreator, which implements 226 * SecondaryKeyCreator for the case where the data keys and value are all 227 * of the serial format. 228 */ 229 private static class SupplierByCityKeyCreator 230 extends SerialSerialKeyCreator { 231 232 /** 233 * Construct the city key extractor. 234 * @param catalog is the class catalog. 235 * @param primaryKeyClass is the supplier key class. 236 * @param valueClass is the supplier value class. 237 * @param indexKeyClass is the city key class. 238 */ 239 private SupplierByCityKeyCreator(ClassCatalog catalog, 240 Class primaryKeyClass, 241 Class valueClass, 242 Class indexKeyClass) { 243 244 super(catalog, primaryKeyClass, valueClass, indexKeyClass); 245 } 246 247 /** 248 * Extract the city key from a supplier key/value pair. The city key 249 * is stored in the supplier value, so the supplier key is not used. 250 */ 251 public Object createSecondaryKey(Object primaryKeyInput, 252 Object valueInput) { 253 254 SupplierData supplierData = (SupplierData) valueInput; 255 return supplierData.getCity(); 256 } 257 } 258 259 /** 260 * The SecondaryKeyCreator for the ShipmentByPart index. This is an 261 * extension of the abstract class SerialSerialKeyCreator, which implements 262 * SecondaryKeyCreator for the case where the data keys and value are all 263 * of the serial format. 264 */ 265 private static class ShipmentByPartKeyCreator 266 extends SerialSerialKeyCreator { 267 268 /** 269 * Construct the part key extractor. 270 * @param catalog is the class catalog. 271 * @param primaryKeyClass is the shipment key class. 272 * @param valueClass is the shipment value class. 273 * @param indexKeyClass is the part key class. 274 */ 275 private ShipmentByPartKeyCreator(ClassCatalog catalog, 276 Class primaryKeyClass, 277 Class valueClass, 278 Class indexKeyClass) { 279 280 super(catalog, primaryKeyClass, valueClass, indexKeyClass); 281 } 282 283 /** 284 * Extract the part key from a shipment key/value pair. The part key 285 * is stored in the shipment key, so the shipment value is not used. 286 */ 287 public Object createSecondaryKey(Object primaryKeyInput, 288 Object valueInput) { 289 290 ShipmentKey shipmentKey = (ShipmentKey) primaryKeyInput; 291 return new PartKey(shipmentKey.getPartNumber()); 292 } 293 } 294 295 /** 296 * The SecondaryKeyCreator for the ShipmentBySupplier index. This is an 297 * extension of the abstract class SerialSerialKeyCreator, which implements 298 * SecondaryKeyCreator for the case where the data keys and value are all 299 * of the serial format. 300 */ 301 private static class ShipmentBySupplierKeyCreator 302 extends SerialSerialKeyCreator { 303 304 /** 305 * Construct the supplier key extractor. 306 * @param catalog is the class catalog. 307 * @param primaryKeyClass is the shipment key class. 308 * @param valueClass is the shipment value class. 309 * @param indexKeyClass is the supplier key class. 310 */ 311 private ShipmentBySupplierKeyCreator(ClassCatalog catalog, 312 Class primaryKeyClass, 313 Class valueClass, 314 Class indexKeyClass) { 315 316 super(catalog, primaryKeyClass, valueClass, indexKeyClass); 317 } 318 319 /** 320 * Extract the supplier key from a shipment key/value pair. The part 321 * key is stored in the shipment key, so the shipment value is not 322 * used. 323 */ 324 public Object createSecondaryKey(Object primaryKeyInput, 325 Object valueInput) { 326 327 ShipmentKey shipmentKey = (ShipmentKey) primaryKeyInput; 328 return new SupplierKey(shipmentKey.getSupplierNumber()); 329 } 330 } 331} 332