Skip to content

Commit

Permalink
Merge pull request #957 from richarda23/core-utils-tests-part2
Browse files Browse the repository at this point in the history
Core utils tests part2 - #944
  • Loading branch information
josemduarte committed Aug 22, 2021
2 parents b4d1e90 + 92cfa24 commit 3929dd7
Show file tree
Hide file tree
Showing 5 changed files with 402 additions and 54 deletions.
Expand Up @@ -50,6 +50,11 @@ public PrettyXMLWriter(PrintWriter writer) {
this.writer = writer;
}

/**
* Declare a namespace for current and following elements
* 'prefixHint' is ignored entirely in this implementation
*
*/
@Override
public void declareNamespace(String nsURI, String prefixHint)
throws IOException
Expand Down Expand Up @@ -269,6 +274,7 @@ public void print(String data)
afterNewline = false;
}

// does not work for adding literal XML elements.
@Override
public void printRaw(String data)
throws IOException
Expand Down
108 changes: 84 additions & 24 deletions biojava-core/src/main/java/org/biojava/nbio/core/util/XMLHelper.java
Expand Up @@ -45,18 +45,29 @@
import static org.biojava.nbio.core.sequence.io.util.IOUtils.openFile;

/**
*
* Helper methods to simplify boilerplate XML parsing code for {@code}org.w3c.dom{@code} XML objects
* @author Scooter
*/
public class XMLHelper {

static public Element addChildElement(Element parentElement, String elementName) {
/**
* Creates a new element called {@code}elementName{@code} and adds it to {@code}parentElement{@code}
* @param parentElement
* @param elementName
* @return the new child element
*/
public static Element addChildElement(Element parentElement, String elementName) {
Element childElement = parentElement.getOwnerDocument().createElement(elementName);
parentElement.appendChild(childElement);
return childElement;
}

static public Document getNewDocument() throws ParserConfigurationException {
/**
* Create a new, empty {@code}org.w3c.dom.Document{@code}
* @return a new {@code}org.w3c.dom.Document{@code}
* @throws ParserConfigurationException
*/
public static Document getNewDocument() throws ParserConfigurationException {

//Create instance of DocumentBuilderFactory
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Expand All @@ -67,14 +78,30 @@ static public Document getNewDocument() throws ParserConfigurationException {
return doc;
}

static public Document loadXML(String fileName) throws SAXException, IOException, ParserConfigurationException {
/**
* Given a path to an XML file, parses into an {@code}org.w3c.dom.Document{@code}
* @param fileName path to a readable XML file
* @return
* @throws SAXException
* @throws IOException
* @throws ParserConfigurationException
*/
public static Document loadXML(String fileName) throws SAXException, IOException, ParserConfigurationException {
InputStream is = openFile(new File(fileName));
Document doc = inputStreamToDocument(new BufferedInputStream(is));
close(is);
return doc;
}

static public Document inputStreamToDocument(InputStream inputStream) throws SAXException, IOException, ParserConfigurationException {
/**
* Creates an {@code}org.w3c.dom.Document{@code} from the content of the {@code}inputStream{@code}
* @param inputStream
* @return a {@code}Document{@code}
* @throws SAXException
* @throws IOException
* @throws ParserConfigurationException
*/
public static Document inputStreamToDocument(InputStream inputStream) throws SAXException, IOException, ParserConfigurationException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

DocumentBuilder db = dbf.newDocumentBuilder();
Expand All @@ -85,7 +112,13 @@ static public Document inputStreamToDocument(InputStream inputStream) throws SAX
return doc;
}

static public void outputToStream(Document document, OutputStream outputStream) throws TransformerException {
/**
* Given an {@code}org.w3c.dom.Document{@code}, writes it to the given {@code}outputStream{@code}
* @param document
* @param outputStream
* @throws TransformerException
*/
public static void outputToStream(Document document, OutputStream outputStream) throws TransformerException {
// Use a Transformer for output
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
Expand All @@ -94,26 +127,29 @@ static public void outputToStream(Document document, OutputStream outputStream)
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(outputStream);
transformer.transform(source, result);


}

static public void outputToStream(Element document, OutputStream outputStream) throws TransformerException {
// Use a Transformer for output
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
// transformer.setOutputProperty(OutputKeys.INDENT, "yes");

DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(outputStream);
transformer.transform(source, result);

}
//static XPath xpath = XPathFactory.newInstance().newXPath();

static public Element selectParentElement(Element element, String parentName) {
Element parentElement = (Element) element.getParentNode();
if (parentElement == null) {
/**
* Given an element, searches upwards through ancestor Elements till the first Element
* matching the requests {@code}parentName{@code} is found.
* @param element The starting element
* @param parentName The tag name of the requested Element.
* @return The found element, or {@code}null{@code} if no matching element is found,
*/
public static Element selectParentElement(Element element, String parentName) {

Node parentNode = element.getParentNode();
if (parentNode == null) {
return null;
}
// check that parent is actually an element, else return null
// this is to prevent ClassCastExceptions if element's parent is not an Element.
Element parentElement = null;
if (Node.ELEMENT_NODE == parentNode.getNodeType()){
parentElement = (Element)parentNode;
} else {
return null;
}
if (parentElement.getTagName().equals(parentName)) {
Expand All @@ -122,7 +158,21 @@ static public Element selectParentElement(Element element, String parentName) {
return selectParentElement(parentElement, parentName);
}

static public Element selectSingleElement(Element element, String xpathExpression) throws XPathExpressionException {
/**
* If {@code}xpathExpression{@code} is a plain string with no '/' characterr, this is
* interpreted as a child element name to search for.
* <b/>
* If {@code}xpathExpression{@code} is an XPath expression, this is evaluated and is assumed
* to identify a single element.
* @param element
* @param xpathExpression
* @return A single element or null if no match or the 1st match if matches more than 1
* @throws XPathExpressionException
*/
public static Element selectSingleElement(Element element, String xpathExpression) throws XPathExpressionException {
if (element == null) {
return null;
}
if (xpathExpression.indexOf("/") == -1) {
NodeList nodeList = element.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Expand All @@ -144,7 +194,17 @@ static public Element selectSingleElement(Element element, String xpathExpressio
}
}

static public ArrayList<Element> selectElements(Element element, String xpathExpression) throws XPathExpressionException {
/**
* Gets a list of elements matching {@code}xpathExpression{@code}. If xpathExpression lacks
* a '/' character, only immediate children o {@code}element{@code} are searched over.
* <br/>
* If {@code}xpathExpression{@code} contains an '/' character, a full XPath search is made
* @param element
* @param xpathExpression
* @return A possibly empty but non-null {@code}ArrayList{@code}
* @throws XPathExpressionException
*/
public static ArrayList<Element> selectElements(Element element, String xpathExpression) throws XPathExpressionException {
ArrayList<Element> resultVector = new ArrayList<Element>();
if (element == null) {
return resultVector;
Expand Down
Expand Up @@ -32,64 +32,64 @@

public interface XMLWriter {
/**
* Send raw data to the stream. Mainly useful for things like DOCTYPE
* declarations. Use with care!
* Send raw data to the stream. Mainly useful for things like DOCTYPE
* declarations. Use with care!
*
* @param s a string of data to include verbatim in the XML stream
*/

public void printRaw(String s) throws IOException;
void printRaw(String s) throws IOException;

/**
* Open a new namespace-qualified XML tag.
*
* @param nsURI A URI for the namespace to use
* @param nsURI A URI for the namespace to use
* @param localName The name of the tag
*/

public void openTag(String nsURI, String localName) throws IOException;
void openTag(String nsURI, String localName) throws IOException;

/**
* Open a new unqualified XML tag. This may also be used if you want
* to do namespace management yourself, independantly of the XMLWriter
* Open a new unqualified XML tag. This may also be used if you want to do
* namespace management yourself, independantly of the XMLWriter
*
* @param name The name of the tag.
*/

public void openTag(String name) throws IOException;
void openTag(String name) throws IOException;

/**
* Add an attribute to an element. This will throw an exception if it's not
* Add an attribute to an element. This will throw an exception if it's not
* called immediately after an <code>openTag</code> command.
*
* @param nsURI A URI for the namespace to use
* @param nsURI A URI for the namespace to use
* @param localName The name of the attribute
* @param value The textual value of the attribute
* @param value The textual value of the attribute
*/

public void attribute(String nsURI, String localName, String value) throws IOException;
void attribute(String nsURI, String localName, String value) throws IOException;

/**
* Add an un-qualified attribute to an element. This will throw an exception if it's not
* called immediately after an <code>openTag</code> command.
* Add an un-qualified attribute to an element. This will throw an exception if
* it's not called immediately after an <code>openTag</code> command.
*
* @param qName The name of the attribute to set
* @param value The textual value of the attribute
*/

public void attribute(String qName, String value) throws IOException;
void attribute(String qName, String value) throws IOException;

/**
* Prints some textual content in an element.
*/

public void print(String data) throws IOException;
void print(String data) throws IOException;

/**
* Prints some textual content, terminated with a newline character.
*/

public void println(String data) throws IOException;
void println(String data) throws IOException;

/**
* Closes an element
Expand All @@ -98,36 +98,38 @@ public interface XMLWriter {
* @param qName The name of the tag
*/

public void closeTag(String nsURI, String qName) throws IOException;
void closeTag(String nsURI, String qName) throws IOException;

/**
* Closes an un-qualified element.
*
* @param name The tag name
*/

public void closeTag(String name) throws IOException;
void closeTag(String name) throws IOException;

/**
* Hints that a namespace is going to be used in a sub-tree. Use this method
* to avoid namespaces that are used only in leaf-nodes of a tree being re-defined
* every time they are used. The XMLWriter will generally try to use the suggested
* prefix for this namespace, but there is no guarentee of this. In particular, if
* the namespace is already in use, the current prefix will still be used. Similarly
* if the suggested prefix has already been used for another namespace, a new one
* will be auto-generated.
* Hints that a namespace is going to be used in a sub-tree. Use this method to
* avoid namespaces that are used only in leaf-nodes of a tree being re-defined
* every time they are used. The XMLWriter will generally try to use the
* suggested prefix for this namespace, but there is no guarantee of this.
* <p/>
*
* In particular, if the namespace is already in use, the current prefix will still
* be used. Similarly if the suggested prefix has already been used for another
* namespace, a new one will be auto-generated.
*
* @param nsURI The namespace to declare
* @param nsURI The namespace to declare
* @param prefixHint A suggested prefix-string for this namespace.
*/

public void declareNamespace(String nsURI, String prefixHint) throws IOException;
void declareNamespace(String nsURI, String prefixHint) throws IOException;

/**
* Close this XMLWriter, and it's underlying stream.
* Close this XMLWriter, and its underlying stream.
*
* @since 1.4
*/

public void close() throws IOException;
void close() throws IOException;
}

0 comments on commit 3929dd7

Please sign in to comment.