package org.concordion.internal; import nu.xom.Attribute; import nu.xom.Document; import nu.xom.Elements; import org.concordion.api.Command; import org.concordion.api.CommandFactory; import org.concordion.api.Element; import org.concordion.api.Resource; import org.concordion.api.Specification; import org.concordion.internal.util.Announcer; import org.concordion.internal.util.Check; public class DocumentParser { private final CommandFactory commandFactory; private final Announcer<DocumentParsingListener> listeners = Announcer.to(DocumentParsingListener.class); public DocumentParser(CommandFactory commandFactory) { this.commandFactory = commandFactory; } public void addDocumentParsingListener(DocumentParsingListener listener) { listeners.addListener(listener); } public void removeDocumentParsingListener(DocumentParsingListener listener) { listeners.removeListener(listener); } private void announceBeforeParsing(Document document) { listeners.announce().beforeParsing(document); } public Specification parse(Document document, Resource resource) { announceBeforeParsing(document); nu.xom.Element xomElement = document.getRootElement(); CommandCall rootCommandCall = new CommandCall(createSpecificationCommand(), new Element(xomElement), "", resource); generateCommandCallTree(xomElement, rootCommandCall, resource); return new XMLSpecification(rootCommandCall); } private void generateCommandCallTree(nu.xom.Element xomElement, CommandCall parentCommandCall, Resource resource) { boolean commandIsAssigned = false; for (int i = 0; i < xomElement.getAttributeCount(); i++) { Attribute attribute = xomElement.getAttribute(i); String namespaceURI = attribute.getNamespaceURI(); if (!namespaceURI.equals("")) { String commandName = attribute.getLocalName(); Command command = createCommand(namespaceURI, commandName); if (command != null) { Check.isFalse(commandIsAssigned, "Multiple commands per element is currently not supported."); commandIsAssigned = true; String expression = attribute.getValue(); CommandCall commandCall = new CommandCall(command, new Element(xomElement), expression, resource); parentCommandCall.appendChild(commandCall); parentCommandCall = commandCall; } } } Elements children = xomElement.getChildElements(); for (int i = 0; i < children.size(); i++) { generateCommandCallTree(children.get(i), parentCommandCall, resource); } } private Command createSpecificationCommand() { Command specCmd = createCommand("", "specification"); return specCmd; } private Command createCommand(String namespaceURI, String commandName) { return commandFactory.createCommand(namespaceURI, commandName); } }