public MetadataRecordFactory(Map<String, String> namespaces) { this.namespaces = namespaces; try { documentBuilder = XMLToolFactory.documentBuilderFactory().newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new RuntimeException("Parser config?", e); } }
/** * Create a hierarchical dump based on a profile that is initially generated by introspecting the * database and then adjusted to determine the contents of the dump. * * @author Gerald de Jong <*****@*****.**> */ public class TableExtractor { private static final String DUMP_ENVELOP_TAG = "delving-db-dump"; private XMLOutputFactory outputFactory = XMLToolFactory.xmlOutputFactory(); private XMLEventFactory event = XMLToolFactory.xmlEventFactory(); private Stack<ResultSet> resultSets = new Stack<ResultSet>(); private XMLEventWriter out; private Connection connection; private RelationalProfile profile; private int maxRows; public TableExtractor(Connection connection, RelationalProfile profile) { this.connection = connection; this.profile = profile; } public void setMaxRows(int maxRows) { this.maxRows = maxRows; } public void fillCaches() throws SQLException { for (RelationalProfile.Table table : profile.tables) { if (!table.cached) continue; table.cache = new HashMap<String, Map<String, String>>(); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(table.toQuery(null)); while (resultSet.next()) { String key = null; Map<String, String> value = new TreeMap<String, String>(); for (RelationalProfile.Column column : table.columns) { if (column.key) key = resultSet.getString(column.name); String fieldValue = getValue(column, resultSet); if (fieldValue != null) value.put(column.name, fieldValue); } if (key == null) throw new RuntimeException("Table missing key column: " + table.name); table.cache.put(key, value); } statement.close(); } } public void dumpTo(OutputStream outputStream) throws FileNotFoundException, UnsupportedEncodingException, XMLStreamException, SQLException { out = outputFactory.createXMLEventWriter(new OutputStreamWriter(outputStream, "UTF-8")); startDocument(); dumpTo(profile.rootTable(), 0); endDocument(); } private void dumpTo(RelationalProfile.Table table, int indent) throws SQLException, XMLStreamException { String key = resultSets.isEmpty() ? null : resultSets.peek().getString(table.linkColumn.link.name); if (table.cached) { if (key == null) return; Map<String, String> result = table.cache.get(key); startWrapper(table.name, indent); for (RelationalProfile.Column column : table.columns) { putValue(column, result, indent + 1); } endWrapper(table.name, indent); } else { Statement statement = connection.createStatement(); if (maxRows > 0) statement.setMaxRows(maxRows); String sql = table.toQuery(key); resultSets.push(statement.executeQuery(sql)); int count = 0; while (resultSets.peek().next()) { if (resultSets.size() == 1) { System.out.println("=== Record " + (++count)); } startWrapper(table.name, indent); for (RelationalProfile.Column column : table.columns) { putValue(column, resultSets.peek(), indent + 1); } for (RelationalProfile.Table childTable : profile.childTables(table)) { if (childTable.wrap != null) { startWrapper(childTable.wrap, indent + 1); dumpTo(childTable, indent + 2); endWrapper(table.name, indent + 1); } else { dumpTo(childTable, indent + 1); } } endWrapper(table.name, indent); } resultSets.pop(); statement.close(); } } private String getValue(RelationalProfile.Column column, ResultSet resultSet) throws SQLException { String value = resultSet.getString(column.name); // todo: improve this if necessary if (value == null) return null; return checkEmpty(column, value); } private String getValue(RelationalProfile.Column column, Map<String, String> result) { String value = result.get(column.name); if (value == null) return null; return checkEmpty(column, value); } private String checkEmpty(RelationalProfile.Column column, String value) { value = value.trim(); return column.isEmpty(value) ? null : value; } private void putValue(RelationalProfile.Column column, Map<String, String> result, int indent) throws XMLStreamException, SQLException { String value = getValue(column, result); if (value == null) return; while (indent-- > 0) out.add(event.createCharacters(" ")); out.add(event.createStartElement("", "", column.name, null, null)); out.add(event.createCharacters(value)); out.add(event.createEndElement("", "", column.name)); out.add(event.createCharacters("\n")); } private void putValue(RelationalProfile.Column column, ResultSet resultSet, int indent) throws XMLStreamException, SQLException { String value = getValue(column, resultSet); if (value == null) return; while (indent-- > 0) out.add(event.createCharacters(" ")); out.add(event.createStartElement("", "", column.name, null, null)); out.add(event.createCharacters(value)); out.add(event.createEndElement("", "", column.name)); out.add(event.createCharacters("\n")); } private void startWrapper(String tag, int indent) throws XMLStreamException { while (indent-- > 0) out.add(event.createCharacters(" ")); out.add(event.createStartElement("", "", tag, null, null)); out.add(event.createCharacters("\n")); } private void endWrapper(String tag, int indent) throws XMLStreamException { while (indent-- > 0) out.add(event.createCharacters(" ")); out.add(event.createEndElement("", "", tag)); out.add(event.createCharacters("\n")); } private void startDocument() throws XMLStreamException { out.add(event.createStartDocument()); out.add(event.createCharacters("\n")); out.add(event.createStartElement("", "", DUMP_ENVELOP_TAG, null, null)); out.add(event.createCharacters("\n")); } private void endDocument() throws XMLStreamException { out.add(event.createEndElement("", "", DUMP_ENVELOP_TAG)); out.add(event.createCharacters("\n")); out.add(event.createEndDocument()); } }
/** * When the MetadataRecord instances are not coming from the parse of an input file using the * MetadataParser, they can be produced one by one using the metadataRecordFrom method, which first * cleverly wraps the record and then parses it. */ public class MetadataRecordFactory { private XMLInputFactory inputFactory = XMLToolFactory.xmlInputFactory(); private DocumentBuilder documentBuilder; private Map<String, String> namespaces; public MetadataRecordFactory(Map<String, String> namespaces) { this.namespaces = namespaces; try { documentBuilder = XMLToolFactory.documentBuilderFactory().newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new RuntimeException("Parser config?", e); } } public MetadataRecord fromGroovyNode(GroovyNode rootNode, int recordNumber, int recordCount) { return MetadataRecord.create(rootNode, recordNumber, recordCount); } public MetadataRecord metadataRecordFrom(String recordContents) throws XMLStreamException { try { Reader reader = new StringReader(recordContents); XMLStreamReader2 input = (XMLStreamReader2) inputFactory.createXMLStreamReader(reader); GroovyNode rootNode = null, node = null; StringBuilder value = new StringBuilder(); while (true) { switch (input.getEventType()) { case XMLEvent.START_DOCUMENT: break; case XMLEvent.START_ELEMENT: node = new GroovyNode( node, input.getNamespaceURI(), input.getLocalName(), input.getPrefix()); if (rootNode == null) { rootNode = node; } if (input.getAttributeCount() > 0) { for (int walk = 0; walk < input.getAttributeCount(); walk++) { QName attributeName = input.getAttributeName(walk); if (attributeName.getPrefix() == null || attributeName.getPrefix().isEmpty()) { node.attributes() .put(attributeName.getLocalPart(), input.getAttributeValue(walk)); } else { node.attributes() .put( String.format( "%s:%s", attributeName.getPrefix(), attributeName.getLocalPart()), input.getAttributeValue(walk)); } } } value.setLength(0); break; case XMLEvent.CHARACTERS: value.append(input.getText()); break; case XMLEvent.CDATA: value.append(String.format("<![CDATA[%s]]>", input.getText())); break; case XMLEvent.END_ELEMENT: if (node == null) throw new RuntimeException("Node cannot be null"); String valueString = value.toString().trim(); value.setLength(0); if (valueString.length() > 0) node.setNodeValue(valueString); node = node.parent(); break; case XMLEvent.END_DOCUMENT: { break; } } if (!input.hasNext()) { break; } input.next(); } return MetadataRecord.create(rootNode, -1, -1); } catch (WstxParsingException e) { throw new XMLStreamException("Problem parsing record:\n" + recordContents, e); } } }