diff --git a/quickfixj-from-fix-orchestra-repository/quickfixj-from-fix-orchestra-generator/src/main/java/org/quickfixj/orchestra/DataDictionaryGenerator.java b/quickfixj-from-fix-orchestra-repository/quickfixj-from-fix-orchestra-generator/src/main/java/org/quickfixj/orchestra/DataDictionaryGenerator.java index 736dd65..df6643c 100644 --- a/quickfixj-from-fix-orchestra-repository/quickfixj-from-fix-orchestra-generator/src/main/java/org/quickfixj/orchestra/DataDictionaryGenerator.java +++ b/quickfixj-from-fix-orchestra-repository/quickfixj-from-fix-orchestra-generator/src/main/java/org/quickfixj/orchestra/DataDictionaryGenerator.java @@ -32,10 +32,14 @@ import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; +import javax.xml.bind.util.JAXBSource; import javax.xml.namespace.NamespaceContext; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; @@ -67,6 +71,24 @@ */ public class DataDictionaryGenerator { + private static class UnmarshalResult { + private final Repository repository; + private final Node repositoryNode; + + public UnmarshalResult(Repository repository, Node repositoryNode) { + this.repository = repository; + this.repositoryNode = repositoryNode; + } + + public Repository getRepository() { + return repository; + } + + public Node getRepositoryNode() { + return repositoryNode; + } + } + private static class KeyValue { final String key; final T value; @@ -112,19 +134,30 @@ public static void main(String[] args) { private final Map components = new HashMap<>(); private final Map groups = new HashMap<>(); private final Map fields = new HashMap<>(); - private Document xmlDocument; private static final String FIX_LATEST = "FIX.Latest"; public void generate(InputStream inputFile, File outputDir) throws JAXBException, IOException, ParserConfigurationException, SAXException, XPathExpressionException { - final Repository repository = unmarshal(inputFile); - generate(repository, outputDir); + final UnmarshalResult result = unmarshal(inputFile); + generate(result.getRepository(), outputDir, result.getRepositoryNode()); } public void generate(Repository repository, File outputDir) throws IOException, XPathExpressionException { + try { + JAXBContext jaxbContext = JAXBContext.newInstance(Repository.class); + DOMResult domResult = new DOMResult(); + TransformerFactory.newInstance().newTransformer().transform(new JAXBSource(jaxbContext, repository), domResult); + Node repositoryNode = domResult.getNode(); + generate(repository, outputDir, repositoryNode); + } catch (JAXBException | TransformerException e) { + throw new RuntimeException("Failed to transform repository to document", e); + } + } - Set requiredGroupIds = getRequiredGroups(); + private void generate(Repository repository, File outputDir, Node repositoryNode) + throws IOException, XPathExpressionException { + Set requiredGroupIds = getRequiredGroups(repositoryNode); final List codeSetList = repository.getCodeSets().getCodeSet(); for (final CodeSetType codeSet : codeSetList) { @@ -252,8 +285,9 @@ private File getSpecFilePath(File outputDir, String versionPath, String extensio return new File(outputDir, sb.toString()); } - private Set getRequiredGroups() throws XPathExpressionException { + private Set getRequiredGroups(Node repositoryNode) throws XPathExpressionException { Set groupIds = new HashSet<>(); + XPath xPath = XPathFactory.newInstance().newXPath(); xPath.setNamespaceContext(new NamespaceContext() { @@ -280,7 +314,7 @@ public Iterator getPrefixes(String namespaceURI) { }); String expression = "//fixr:groupRef[@presence='required']"; NodeList nodeList = (NodeList) xPath.compile(expression) - .evaluate(xmlDocument.getDocumentElement(), XPathConstants.NODESET); + .evaluate(repositoryNode, XPathConstants.NODESET); for (int i = 0; i < nodeList.getLength(); i++) { if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) nodeList.item(i); @@ -311,15 +345,16 @@ private String toConstantName(String symbolicName) { return sb.toString().toUpperCase(); } - private Repository unmarshal(InputStream inputFile) + private UnmarshalResult unmarshal(InputStream inputFile) throws JAXBException, ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); builderFactory.setNamespaceAware(true); DocumentBuilder builder = builderFactory.newDocumentBuilder(); - xmlDocument = builder.parse(inputFile); + Document document = builder.parse(inputFile); final JAXBContext jaxbContext = JAXBContext.newInstance(Repository.class); final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - return (Repository) jaxbUnmarshaller.unmarshal(xmlDocument); + Repository repository = (Repository) jaxbUnmarshaller.unmarshal(document); + return new UnmarshalResult(repository, document.getDocumentElement()); } private void usage() { diff --git a/quickfixj-from-fix-orchestra-repository/quickfixj-from-fix-orchestra-generator/src/test/java/org/quickfixj/orchestra/DataDictionaryGeneratorTest.java b/quickfixj-from-fix-orchestra-repository/quickfixj-from-fix-orchestra-generator/src/test/java/org/quickfixj/orchestra/DataDictionaryGeneratorTest.java index 982840e..f680cdd 100644 --- a/quickfixj-from-fix-orchestra-repository/quickfixj-from-fix-orchestra-generator/src/test/java/org/quickfixj/orchestra/DataDictionaryGeneratorTest.java +++ b/quickfixj-from-fix-orchestra-repository/quickfixj-from-fix-orchestra-generator/src/test/java/org/quickfixj/orchestra/DataDictionaryGeneratorTest.java @@ -4,11 +4,19 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileReader; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.fixprotocol._2020.orchestra.repository.Repository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Unmarshaller; public class DataDictionaryGeneratorTest { @@ -47,6 +55,27 @@ public void testGenerateFIXLatest() throws Exception { } } + @Test + public void testGenerateFIXLatestFromRepository(@TempDir Path tempDir) throws Exception { + JAXBContext jaxbContext = JAXBContext.newInstance(Repository.class); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + Repository repository; + + try (InputStream stream = Thread.currentThread().getContextClassLoader().getResource("trade-latest.xml").openStream()) { + repository = (Repository) unmarshaller.unmarshal(stream); + } + + Path outputDir = tempDir.resolve("output"); + Files.createDirectory(outputDir); + + generator.generate(repository, outputDir.toFile()); + try (BufferedReader brTest = Files.newBufferedReader(outputDir.resolve("FIXLatest.xml"))) { + String firstLine = brTest.readLine(); + assertEquals("", + firstLine); + } + } + @Test public void testExtract() throws Exception { assertEquals("0", generator.extractServicePack("FIX.5.0"));