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