1 /*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002, 2013 Oracle and/or its affiliates. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9 package collections.ship.sentity; 10 11 import java.io.FileNotFoundException; 12 import java.util.Iterator; 13 import java.util.Set; 14 15 import com.sleepycat.collections.StoredIterator; 16 import com.sleepycat.collections.TransactionRunner; 17 import com.sleepycat.collections.TransactionWorker; 18 import com.sleepycat.db.DatabaseException; 19 20 /** 21 * Sample is the main entry point for the sample program and may be run as 22 * follows: 23 * 24 * <pre> 25 * java collections.ship.sentity.Sample 26 * [-h <home-directory> ] 27 * </pre> 28 * 29 * <p> The default for the home directory is ./tmp -- the tmp subdirectory of 30 * the current directory where the sample is run. To specify a different home 31 * directory, use the -home option. The home directory must exist before 32 * running the sample. To recreate the sample database from scratch, delete 33 * all files in the home directory before running the sample. </p> 34 * 35 * @author Mark Hayes 36 */ 37 public class Sample { 38 39 private SampleDatabase db; 40 private SampleViews views; 41 42 /** 43 * Run the sample program. 44 */ main(String[] args)45 public static void main(String[] args) { 46 47 System.out.println("\nRunning sample: " + Sample.class); 48 49 // Parse the command line arguments. 50 // 51 String homeDir = "./tmp"; 52 for (int i = 0; i < args.length; i += 1) { 53 if (args[i].equals("-h") && i < args.length - 1) { 54 i += 1; 55 homeDir = args[i]; 56 } else { 57 System.err.println("Usage:\n java " + Sample.class.getName() + 58 "\n [-h <home-directory>]"); 59 System.exit(2); 60 } 61 } 62 63 // Run the sample. 64 // 65 Sample sample = null; 66 try { 67 sample = new Sample(homeDir); 68 sample.run(); 69 } catch (Exception e) { 70 // If an exception reaches this point, the last transaction did not 71 // complete. If the exception is RunRecoveryException, follow 72 // the Berkeley DB recovery procedures before running again. 73 e.printStackTrace(); 74 } finally { 75 if (sample != null) { 76 try { 77 // Always attempt to close the database cleanly. 78 sample.close(); 79 } catch (Exception e) { 80 System.err.println("Exception during database close:"); 81 e.printStackTrace(); 82 } 83 } 84 } 85 } 86 87 /** 88 * Open the database and views. 89 */ Sample(String homeDir)90 private Sample(String homeDir) 91 throws DatabaseException, FileNotFoundException { 92 93 db = new SampleDatabase(homeDir); 94 views = new SampleViews(db); 95 } 96 97 /** 98 * Close the database cleanly. 99 */ close()100 private void close() 101 throws DatabaseException { 102 103 db.close(); 104 } 105 106 /** 107 * Run two transactions to populate and print the database. A 108 * TransactionRunner is used to ensure consistent handling of transactions, 109 * including deadlock retries. But the best transaction handling mechanism 110 * to use depends on the application. 111 */ run()112 private void run() 113 throws Exception { 114 115 TransactionRunner runner = new TransactionRunner(db.getEnvironment()); 116 runner.run(new PopulateDatabase()); 117 runner.run(new PrintDatabase()); 118 } 119 120 /** 121 * Populate the database in a single transaction. 122 */ 123 private class PopulateDatabase implements TransactionWorker { 124 doWork()125 public void doWork() 126 throws Exception { 127 addSuppliers(); 128 addParts(); 129 addShipments(); 130 } 131 } 132 133 /** 134 * Print the database in a single transaction. All entities are printed 135 * and the indices are used to print the entities for certain keys. 136 * 137 * <p> Note the use of special iterator() methods. These are used here 138 * with indices to find the shipments for certain keys. For details on 139 * database iterators see {@link StoredIterator}. </p> 140 */ 141 private class PrintDatabase implements TransactionWorker { 142 doWork()143 public void doWork() 144 throws Exception { 145 printValues("Parts", 146 views.getPartSet().iterator()); 147 printValues("Suppliers", 148 views.getSupplierSet().iterator()); 149 printValues("Suppliers for City Paris", 150 views.getSupplierByCityMap().duplicates( 151 "Paris").iterator()); 152 printValues("Shipments", 153 views.getShipmentSet().iterator()); 154 printValues("Shipments for Part P1", 155 views.getShipmentByPartMap().duplicates( 156 new PartKey("P1")).iterator()); 157 printValues("Shipments for Supplier S1", 158 views.getShipmentBySupplierMap().duplicates( 159 new SupplierKey("S1")).iterator()); 160 } 161 } 162 163 /** 164 * Populate the part entities in the database. If the part set is not 165 * empty, assume that this has already been done. 166 */ addParts()167 private void addParts() { 168 169 Set parts = views.getPartSet(); 170 if (parts.isEmpty()) { 171 System.out.println("Adding Parts"); 172 parts.add(new Part("P1", "Nut", "Red", 173 new Weight(12.0, Weight.GRAMS), "London")); 174 parts.add(new Part("P2", "Bolt", "Green", 175 new Weight(17.0, Weight.GRAMS), "Paris")); 176 parts.add(new Part("P3", "Screw", "Blue", 177 new Weight(17.0, Weight.GRAMS), "Rome")); 178 parts.add(new Part("P4", "Screw", "Red", 179 new Weight(14.0, Weight.GRAMS), "London")); 180 parts.add(new Part("P5", "Cam", "Blue", 181 new Weight(12.0, Weight.GRAMS), "Paris")); 182 parts.add(new Part("P6", "Cog", "Red", 183 new Weight(19.0, Weight.GRAMS), "London")); 184 } 185 } 186 187 /** 188 * Populate the supplier entities in the database. If the supplier set is 189 * not empty, assume that this has already been done. 190 */ addSuppliers()191 private void addSuppliers() { 192 193 Set suppliers = views.getSupplierSet(); 194 if (suppliers.isEmpty()) { 195 System.out.println("Adding Suppliers"); 196 suppliers.add(new Supplier("S1", "Smith", 20, "London")); 197 suppliers.add(new Supplier("S2", "Jones", 10, "Paris")); 198 suppliers.add(new Supplier("S3", "Blake", 30, "Paris")); 199 suppliers.add(new Supplier("S4", "Clark", 20, "London")); 200 suppliers.add(new Supplier("S5", "Adams", 30, "Athens")); 201 } 202 } 203 204 /** 205 * Populate the shipment entities in the database. If the shipment set 206 * is not empty, assume that this has already been done. 207 */ addShipments()208 private void addShipments() { 209 210 Set shipments = views.getShipmentSet(); 211 if (shipments.isEmpty()) { 212 System.out.println("Adding Shipments"); 213 shipments.add(new Shipment("P1", "S1", 300)); 214 shipments.add(new Shipment("P2", "S1", 200)); 215 shipments.add(new Shipment("P3", "S1", 400)); 216 shipments.add(new Shipment("P4", "S1", 200)); 217 shipments.add(new Shipment("P5", "S1", 100)); 218 shipments.add(new Shipment("P6", "S1", 100)); 219 shipments.add(new Shipment("P1", "S2", 300)); 220 shipments.add(new Shipment("P2", "S2", 400)); 221 shipments.add(new Shipment("P2", "S3", 200)); 222 shipments.add(new Shipment("P2", "S4", 200)); 223 shipments.add(new Shipment("P4", "S4", 300)); 224 shipments.add(new Shipment("P5", "S4", 400)); 225 } 226 } 227 228 /** 229 * Print the objects returned by an iterator of entity value objects. 230 * 231 * <p><b> IMPORTANT: All database iterators must be closed to avoid 232 * serious database problems. If the iterator is not closed, the 233 * underlying Berkeley DB cursor is not closed either. </b></p> 234 */ printValues(String label, Iterator iterator)235 private void printValues(String label, Iterator iterator) { 236 237 System.out.println("\n--- " + label + " ---"); 238 try { 239 while (iterator.hasNext()) { 240 System.out.println(iterator.next().toString()); 241 } 242 } finally { 243 // IMPORTANT: Use StoredIterator to close all database 244 // iterators. If java.util.Iterator is in hand, you can safely 245 // close it by calling StoredIterator.close(Iterator). 246 StoredIterator.close(iterator); 247 } 248 } 249 } 250