Changeset 1072
- Timestamp:
- 07/09/08 15:53:52 (4 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/java/org/jcoderz/testdata/Importer.java
r1070 r1072 1 1 package org.jcoderz.testdata; 2 2 3 3 4 import java.io.File; … … 31 32 import org.hibernate.mapping.Table; 32 33 34 33 35 /** 34 * Generic Test data importer. 35 * 36 * Recursively scans a directory for test data items and submits them via 37 * JDBC to a predefined database. The tables and attribute names are mapped 38 * straightforward to the hibernate configuration expected on the classpath. 39 * This implementation relies on auto index of all tables. 36 * Generic Test data importer. Recursively scans a directory for test 37 * data items and submits them via JDBC to a predefined database. The 38 * tables and attribute names are mapped straightforward to the 39 * hibernate configuration expected on the classpath. This 40 * implementation relies on auto index of all tables. 40 41 * 41 42 * @author Torsten Stolpmann 42 *43 43 */ 44 public class Importer {45 44 public class Importer 45 { 46 46 private static final String DEFAULT_TABLE_PREFIX = "S0IR_"; 47 47 … … 53 53 54 54 private static final XPathContext TD_CONTEXT = new XPathContext("td", 55 "http://jcoderz.org/test-data");55 "http://jcoderz.org/test-data"); 56 56 57 57 static final Logger logger = Logger.getLogger(Importer.class.getName()); 58 58 59 59 private String tablePrefix; 60 60 61 private long sequenceBase; 61 62 … … 65 66 * @param args Command line arguments. 66 67 */ 67 public static void main(String[] args) { 68 69 if (args.length < 1) { 68 public static void main (String[] args) 69 { 70 if (args.length < 1) 71 { 70 72 System.out.println("Usage: " + Importer.class.getName() 71 + " <sourceDirectory>"); 72 } 73 73 + " <sourceDirectory>"); 74 } 74 75 String sourceDirectory = args[0]; 75 76 76 Properties properties = new Properties(); 77 77 List<String> tableNames = new ArrayList<String>(); 78 79 78 logger.info("Starting import ..."); 80 try { 79 try 80 { 81 81 String defaultPropertiesName = "/testdata.properties"; 82 83 82 InputStream defaultInput = Importer.class 84 .getResourceAsStream(defaultPropertiesName); 85 if (defaultInput != null) { 86 logger.fine("Loading default properties (" + defaultPropertiesName + ")"); 83 .getResourceAsStream(defaultPropertiesName); 84 if (defaultInput != null) 85 { 86 logger.fine("Loading default properties (" 87 + defaultPropertiesName + ")"); 87 88 properties.load(defaultInput); //$NON-NLS-1$ 88 } else { 89 } 90 else 91 { 89 92 logger.fine("Default properties not found"); 90 93 } 91 String userPropertiesName = FILE_SEPARATOR + System.getProperty("user.name")92 + ".properties";94 String userPropertiesName = FILE_SEPARATOR 95 + System.getProperty("user.name") + ".properties"; 93 96 InputStream userInput = Importer.class 94 .getResourceAsStream(userPropertiesName); 95 if (userInput != null) { 97 .getResourceAsStream(userPropertiesName); 98 if (userInput != null) 99 { 96 100 logger.fine("Loading user properties"); 97 101 properties.load(userInput); //$NON-NLS-1$ 98 } else { 99 logger.fine("User properties (" + userPropertiesName + ") not found"); 100 } 101 102 } 103 else 104 { 105 logger.fine("User properties (" + userPropertiesName 106 + ") not found"); 107 } 102 108 Configuration hibernateConfig = new Configuration(); 103 109 hibernateConfig.addProperties(properties); 104 110 hibernateConfig.configure(); 105 hibernateConfig.getProperties().remove("hibernate.connection.datasource");106 111 hibernateConfig.getProperties().remove( 107 "hibernate.transaction.manager_lookup_class"); 108 hibernateConfig.getProperties().remove("hibernate.transaction.factory_class"); 109 112 "hibernate.connection.datasource"); 113 hibernateConfig.getProperties().remove( 114 "hibernate.transaction.manager_lookup_class"); 115 hibernateConfig.getProperties().remove( 116 "hibernate.transaction.factory_class"); 110 117 Iterator<?> iter = hibernateConfig.getTableMappings(); 111 while (iter.hasNext()) { 118 while (iter.hasNext()) 119 { 112 120 Table table = (Table) iter.next(); 113 121 tableNames.add(table.getName()); 114 122 } 115 } catch (IOException e) { 123 } 124 catch (IOException e) 125 { 116 126 logger.severe(e.getMessage()); 117 127 } 118 119 Importer importer = new Importer(DEFAULT_TABLE_PREFIX, DEFAULT_SEQUENCE_BASE); 120 128 Importer importer = new Importer(DEFAULT_TABLE_PREFIX, 129 DEFAULT_SEQUENCE_BASE); 121 130 Map<String, Document> items = new HashMap<String, Document>(); 122 123 131 importer.loadItems(sourceDirectory, items); 124 125 Map<String, Set<String>> dependencyMap = importer.buildDependencyMap(items);126 127 if (importer.validateDependencies(items, dependencyMap)){132 Map<String, Set<String>> dependencyMap = importer 133 .buildDependencyMap(items); 134 if (importer.validateDependencies(items, dependencyMap)) 135 { 128 136 List<String> result = new ArrayList<String>(); 129 130 if (importer.reOrderItems(items, dependencyMap, result)){137 if (importer.reOrderItems(items, dependencyMap, result)) 138 { 131 139 List<String> queries = new ArrayList<String>(); 132 133 if (importer.generateQueries(result, items, queries, tableNames)) { 140 if (importer 141 .generateQueries(result, items, queries, tableNames)) 142 { 134 143 importer.executeQueries(properties, queries); 135 } else { 136 logger.severe("No insert statements have been executed since errors are detected."); 137 } 138 } 139 } 140 } 141 142 public Importer(final String prefix, final long base) { 143 144 } 145 else 146 { 147 logger 148 .severe("No insert statements have been executed since errors are detected."); 149 } 150 } 151 } 152 } 153 154 public Importer (final String prefix, final long base) 155 { 144 156 tablePrefix = prefix; 145 157 sequenceBase = base; 146 147 158 } 148 159 … … 153 164 * @param queries the queries 154 165 */ 155 private void executeQueries(final Properties hibernateProperties, 156 final List<String> queries) { 157 158 try { 166 private void executeQueries (final Properties hibernateProperties, 167 final List<String> queries) 168 { 169 try 170 { 159 171 Class.forName(hibernateProperties 160 .getProperty("hibernate.connection.driver_class")); 161 172 .getProperty("hibernate.connection.driver_class")); 162 173 Properties info = new Properties(); 163 174 info.setProperty("user", hibernateProperties 164 .getProperty("hibernate.connection.username"));175 .getProperty("hibernate.connection.username")); 165 176 info.setProperty("password", hibernateProperties 166 .getProperty("hibernate.connection.password"));177 .getProperty("hibernate.connection.password")); 167 178 info.setProperty("useUnicode", "true"); 168 179 info.setProperty("characterEncoding", "UTF-8"); 169 170 180 Connection conn = DriverManager.getConnection(hibernateProperties 171 .getProperty("hibernate.connection.url"), info); 172 181 .getProperty("hibernate.connection.url"), info); 173 182 for (SQLWarning warn = conn.getWarnings(); warn != null; warn = warn 174 .getNextWarning()) { 183 .getNextWarning()) 184 { 175 185 logger.warning("SQL Warning:"); 176 186 logger.warning("State : " + warn.getSQLState()); … … 178 188 logger.warning("Error : " + warn.getErrorCode()); 179 189 } 180 181 for (String query : queries) { 182 190 for (String query : queries) 191 { 183 192 Statement stmt = conn.createStatement(); 184 193 ResultSet rs = stmt.executeQuery(query); 185 186 194 rs.close(); 187 195 stmt.close(); 188 196 } 189 197 conn.close(); 190 } catch (SQLException e) { 191 198 } 199 catch (SQLException e) 200 { 192 201 logger.severe("SQL Exception:"); 193 194 while (e != null){202 while (e != null) 203 { 195 204 logger.severe("State : " + e.getSQLState()); 196 205 logger.severe("Message: " + e.getMessage()); 197 206 logger.severe("Error : " + e.getErrorCode()); 198 199 207 e = e.getNextException(); 200 208 } 201 } catch (Exception e) { 209 } 210 catch (Exception e) 211 { 202 212 logger.severe("Exception: " + e.getMessage()); 203 213 } … … 213 223 * @return true, if write 214 224 */ 215 private boolean generateQueries (final List<String> idList,216 final Map<String, Document> items, final List<String> queries,217 final List<String> tableNames) {218 225 private boolean generateQueries (final List<String> idList, 226 final Map<String, Document> items, final List<String> queries, 227 final List<String> tableNames) 228 { 219 229 boolean valid = true; 220 221 for (String id : idList) { 222 230 for (String id : idList) 231 { 223 232 StringBuffer query = new StringBuffer(); 224 233 StringBuffer names = new StringBuffer("("); 225 234 StringBuffer values = new StringBuffer("("); 226 227 235 Document item = items.get(id); 228 236 String tableName = getTableName(item); 229 if (!tableNames.contains(tableName)) { 237 if (!tableNames.contains(tableName)) 238 { 230 239 logger.severe("The type " + getItemType(item) + " of item " 231 + getItemId(item)232 + " has no matching table in the current configuration ("233 + tableName + ")");240 + getItemId(item) 241 + " has no matching table in the current configuration (" 242 + tableName + ")"); 234 243 valid = false; 235 244 } 236 245 Map<String, Node> attributes = getAttributes(item); 237 238 246 int position = 0; 239 247 int end = attributes.entrySet().size(); 240 241 for (Map.Entry<String, Node> attribute : attributes.entrySet()) { 242 248 for (Map.Entry<String, Node> attribute : attributes.entrySet()) 249 { 243 250 position++; 244 245 251 String name = attribute.getKey().toUpperCase(); 246 252 Node node = attribute.getValue(); 247 248 if (node instanceof Element){253 if (node instanceof Element) 254 { 249 255 Element element = (Element) node; 250 if (element.getLocalName().equals("value")) { 256 if (element.getLocalName().equals("value")) 257 { 251 258 names.append(name); 252 259 values.append("'"); 253 260 values.append(element.getValue()); 254 261 values.append("'"); 255 } else if (element.getLocalName().equals("autovalue")) { 262 } 263 else if (element.getLocalName().equals("autovalue")) 264 { 256 265 names.append(name); 257 266 values.append(getAsPrimaryKey(id)); 258 } else if (element.getLocalName().equals("ref")) { 267 } 268 else if (element.getLocalName().equals("ref")) 269 { 259 270 String reference = element.getValue(); 260 if (reference.length() > 0) { 261 if (items.containsKey(reference)) { 271 if (reference.length() > 0) 272 { 273 if (items.containsKey(reference)) 274 { 262 275 names.append(name); 263 values.append(getAsPrimaryKey(element.getValue())); 264 } else { 265 logger.severe("ERROR! the reference " + reference 266 + " could not be resolved."); 276 values.append(getAsPrimaryKey(element 277 .getValue())); 278 } 279 else 280 { 281 logger.severe("ERROR! the reference " 282 + reference + " could not be resolved."); 267 283 valid = false; 268 284 } … … 270 286 } 271 287 } 272 if (position == end) { 288 if (position == end) 289 { 273 290 names.append(") "); 274 291 values.append(") "); 275 } else { 292 } 293 else 294 { 276 295 names.append(", "); 277 296 values.append(", "); 278 297 } 279 298 } 280 if (attributes.size() > 0) { 299 if (attributes.size() > 0) 300 { 281 301 query.append("INSERT INTO " + tableName); 282 302 query.append(" "); … … 285 305 query.append(values); 286 306 } 287 logger.info(query.toString());307 // logger.info(query.toString()); 288 308 queries.add(query.toString()); 289 309 } … … 298 318 * @param result the resulting list of id's 299 319 */ 300 private boolean reOrderItems (final Map<String, Document> items,301 final Map<String, Set<String>> dependencyMap, final List<String> result) {302 320 private boolean reOrderItems (final Map<String, Document> items, 321 final Map<String, Set<String>> dependencyMap, final List<String> result) 322 { 303 323 boolean success; 304 324 boolean changed; 305 306 final Map<String, Document> itemPool = new HashMap<String, Document>(items); 307 do { 325 final Map<String, Document> itemPool = new HashMap<String, Document>( 326 items); 327 do 328 { 308 329 changed = false; 309 310 330 Iterator<Map.Entry<String, Document>> entries = itemPool.entrySet() 311 .iterator(); 312 while (entries.hasNext()) { 331 .iterator(); 332 while (entries.hasNext()) 333 { 313 334 Map.Entry<String, Document> item = entries.next(); 314 335 String id = item.getKey(); 315 336 boolean accepted = true; 316 317 337 Set<String> dependencies = dependencyMap.get(id); 318 for (String dependency : dependencies) { 319 if (!result.contains(dependency)) { 338 for (String dependency : dependencies) 339 { 340 if (!result.contains(dependency)) 341 { 320 342 accepted = false; 321 343 break; 322 344 } 323 345 } 324 if (accepted) { 346 if (accepted) 347 { 325 348 entries.remove(); 326 349 result.add(id); … … 328 351 } 329 352 } 330 } while (changed); 331 332 if (!itemPool.isEmpty()) { 333 logger.severe("Reference loop detected! The following items are invalid:"); 334 for (String id : itemPool.keySet()) { 353 } 354 while (changed); 355 if (!itemPool.isEmpty()) 356 { 357 logger 358 .severe("Reference loop detected! The following items are invalid:"); 359 for (String id : itemPool.keySet()) 360 { 335 361 StringBuffer dependencyList = new StringBuffer(); 336 362 Set<String> dependencies = dependencyMap.get(id); 337 for (String dependency : dependencies) { 363 for (String dependency : dependencies) 364 { 338 365 dependencyList.append(dependency); 339 366 dependencyList.append(" "); 340 367 } 341 342 368 logger.severe(id + ": [" + dependencyList.toString() + "]"); 343 369 } 344 370 success = false; 345 } else { 371 } 372 else 373 { 346 374 success = true; 347 375 } … … 356 384 * @return true, if successful 357 385 */ 358 private boolean validateDependencies (Map<String, Document> items,359 Map<String, Set<String>> dependencyMap) {360 386 private boolean validateDependencies (Map<String, Document> items, 387 Map<String, Set<String>> dependencyMap) 388 { 361 389 boolean valid = true; 362 363 for (Map.Entry<String, Set<String>> dependenciesEntry : dependencyMap.entrySet()) {364 390 for (Map.Entry<String, Set<String>> dependenciesEntry : dependencyMap 391 .entrySet()) 392 { 365 393 String id = dependenciesEntry.getKey(); 366 394 Set<String> dependencies = dependenciesEntry.getValue(); 367 for (String dependency : dependencies) { 368 if (!items.containsKey(dependency)) { 369 logger.severe("Item " + id + " contains invalid reference: " 370 + dependency + " (Note: Self references are not allowed!)"); 395 for (String dependency : dependencies) 396 { 397 if (!items.containsKey(dependency)) 398 { 399 logger.severe("Item " + id 400 + " contains invalid reference: " + dependency 401 + " (Note: Self references are not allowed!)"); 371 402 valid = false; 372 403 } 373 404 } 374 405 } 375 376 406 return valid; 377 407 } … … 383 413 * @return the Map of dependencies. 384 414 */ 385 private Map<String, Set<String>> buildDependencyMap(final Map<String, Document> items) { 386 415 private Map<String, Set<String>> buildDependencyMap ( 416 final Map<String, Document> items) 417 { 387 418 Map<String, Set<String>> dependencyMap = new HashMap<String, Set<String>>(); 388 389 for (Map.Entry<String, Document> item : items.entrySet()) { 390 419 for (Map.Entry<String, Document> item : items.entrySet()) 420 { 391 421 String id = item.getKey(); 392 422 Document document = item.getValue(); 393 394 423 Set<String> dependencies = new HashSet<String>(); 395 396 Nodes references = document.query("/td:item/td:attribute/td:ref",TD_CONTEXT);397 398 for (int j = 0; j < references.size(); j++){424 Nodes references = document.query("/td:item/td:attribute/td:ref", 425 TD_CONTEXT); 426 for (int j = 0; j < references.size(); j++) 427 { 399 428 Node node = references.get(j); 400 429 String refId = node.getValue(); 401 if (refId.length() > 0) { 430 if (refId.length() > 0) 431 { 402 432 dependencies.add(refId); 403 } else { 433 } 434 else 435 { 404 436 // Drop empty references. 405 437 node.getParent().detach(); 406 438 } 407 439 } 408 409 440 dependencyMap.put(id, dependencies); 410 441 } … … 418 449 * @param itemMap the item map 419 450 */ 420 private void loadItems (String dirName, Map<String, Document> itemMap) {421 451 private void loadItems (String dirName, Map<String, Document> itemMap) 452 { 422 453 File rootDir = new File(dirName); 423 if (!rootDir.exists()) { 454 if (!rootDir.exists()) 455 { 424 456 logger.severe("Root directory '" + dirName + "' not found."); 425 457 return; 426 458 } 427 459 String[] entries = rootDir.list(); 428 for (int i = 0; i < entries.length; i++) { 460 for (int i = 0; i < entries.length; i++) 461 { 429 462 String entry = dirName + FILE_SEPARATOR + entries[i]; 430 463 File subFile = new File(entry); 431 if (subFile.isDirectory()) { 464 if (subFile.isDirectory()) 465 { 432 466 loadItems(entry, itemMap); 433 } else { 434 if (subFile.getName().endsWith(SUFFIX_XML)) { 467 } 468 else 469 { 470 if (subFile.getName().endsWith(SUFFIX_XML)) 471 { 435 472 Builder parser = new Builder(false); 436 try { 473 try 474 { 437 475 Document raw = parser.build(entry); 438 476 Document document = XIncluder.resolve(raw); 439 477 String id = getItemId(document); 440 441 if (itemMap.containsKey(id)){478 if (itemMap.containsKey(id)) 479 { 442 480 logger.severe("Duplicate id detected: " + id 443 + " - item will be skipped"); 444 } else { 481 + " - item will be skipped"); 482 } 483 else 484 { 445 485 itemMap.put(id, document); 446 486 logger.fine("Adding item: " + id); 447 487 } 448 } catch (Exception e) { 488 } 489 catch (Exception e) 490 { 449 491 e.printStackTrace(); 450 492 logger.severe("Error parsing file " + entry + ": " 451 + e.getMessage());493 + e.getMessage()); 452 494 } 453 495 } … … 462 504 * @return the primary key 463 505 */ 464 protected String getAsPrimaryKey (final String id) {465 506 protected String getAsPrimaryKey (final String id) 507 { 466 508 return "" + (sequenceBase + Long.parseLong(id.substring(3))); 467 509 } … … 471 513 * 472 514 * @param item the item 473 *474 515 * @return the table name 475 516 */ 476 protected String getTableName (final Document item) {477 517 protected String getTableName (final Document item) 518 { 478 519 Node type = item.query("//td:item/td:type", TD_CONTEXT).get(0); 479 520 return tablePrefix + type.getValue().toUpperCase(); … … 486 527 * @return the item id if any, null else. 487 528 */ 488 private String getItemType (final Document document) {489 529 private String getItemType (final Document document) 530 { 490 531 String type = null; 491 492 532 Nodes nodes = document.query("//td:item/td:type", TD_CONTEXT); 493 for (int j = 0; j < nodes.size(); j++) { 533 for (int j = 0; j < nodes.size(); j++) 534 { 494 535 Node node = nodes.get(j); 495 536 type = node.getValue(); 496 537 break; 497 538 } 498 if (type == null) { 539 if (type == null) 540 { 499 541 logger.severe(getItemId(document) + " contains no type element!"); 500 542 } … … 508 550 * @return the item id if any, null else. 509 551 */ 510 private String getItemId (final Document document) {511 552 private String getItemId (final Document document) 553 { 512 554 String id = null; 513 514 555 Nodes nodes = document.query("//td:item/td:id", TD_CONTEXT); 515 for (int j = 0; j < nodes.size(); j++) { 556 for (int j = 0; j < nodes.size(); j++) 557 { 516 558 Node node = nodes.get(j); 517 559 id = node.getValue(); … … 527 569 * @return the attributes of this item. 528 570 */ 529 private Map<String, Node> getAttributes (final Document document) {530 571 private Map<String, Node> getAttributes (final Document document) 572 { 531 573 Map<String, Node> attributeMap = new HashMap<String, Node>(); 532 533 574 Nodes attributes = document.query("//td:item/td:attribute", TD_CONTEXT); 534 for (int j = 0; j < attributes.size(); j++) { 575 for (int j = 0; j < attributes.size(); j++) 576 { 535 577 Node attribute = attributes.get(j); 536 String name = attribute.query("td:name", TD_CONTEXT).get(0).getValue(); 537 Nodes values = attribute.query("td:value|td:autovalue|td:ref", TD_CONTEXT); 538 if (values.size() > 0) { 578 String name = attribute.query("td:name", TD_CONTEXT).get(0) 579 .getValue(); 580 Nodes values = attribute.query("td:value|td:autovalue|td:ref", 581 TD_CONTEXT); 582 if (values.size() > 0) 583 { 539 584 attributeMap.put(name, values.get(0)); 540 585 }
