Skip to content

Commit

Permalink
feat(XmlHandler): get element from xpath
Browse files Browse the repository at this point in the history
build(pom): updated, minor enhancement
test(XmlHandler: tested get element from xpath use-cases
chore: resource update
  • Loading branch information
rikkarth committed Feb 24, 2024
1 parent 5fa1145 commit 00fc2a0
Show file tree
Hide file tree
Showing 7 changed files with 244 additions and 10 deletions.
7 changes: 5 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@
</dependencies>

<properties>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

Expand Down Expand Up @@ -220,8 +223,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>8</source>
<target>8</target>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
Expand Down
43 changes: 36 additions & 7 deletions src/main/java/pt/codeforge/toolertools/xml/XmlHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
* Utility class for handling operations on XML files or XPath expressions.
* This class provides methods for querying and manipulating XML documents using XPath expressions.
* Utility class for handling operations on XML files or XPath expressions. This class provides methods for querying and
* manipulating XML documents using XPath expressions.
*/
public class XmlHandler {

Expand Down Expand Up @@ -73,9 +74,8 @@ public static Node getNodeFromXPath(String expression, Document document) {
try {
XPathExpression xPathExpression = createXPathExpression(expression);
return Objects.requireNonNull((Node) xPathExpression.evaluate(document, XPathConstants.NODE));
} catch (XPathExpressionException | NullPointerException e) {
Document doc = createEmptyDocument();
return doc.createElement("null");
} catch (XPathExpressionException | NullPointerException | ClassCastException e) {
return getEmptyElement();
}
}

Expand All @@ -97,11 +97,35 @@ public static Node getNodeFromXPath(String expression, Document document, boolea
if (onErrorReturnNull) {
return null;
}
Document doc = createEmptyDocument();
return doc.createElement("null");
return getEmptyElement();
}
}

/**
* Retrieves a Node from the specified XPath expression within the given XML document.
*
* @param expression The XPath expression.
* @param document The XML document.
* @return The Element corresponding to the XPath expression, or a new 'null' Element if an error occurs.
* @throws IllegalStateException if expression is not type Node.
*/
public static Element getElementFromXPath(String expression, Document document) {
return (Element) getNodeFromXPath(expression, document);
}

/**
* Retrieves an ELement from the specified XPath expression within the given XML document, with an option to return
* null on error.
*
* @param expression The XPath expression.
* @param document The XML document.
* @param onErrorReturnNull If true, returns null on error; otherwise, returns a new 'null' Node.
* @return The Element corresponding to the XPath expression, or null/a new 'null' Node.
*/
public static Element getElementFromXPath(String expression, Document document, boolean onErrorReturnNull) {
return (Element) getNodeFromXPath(expression, document, onErrorReturnNull);
}

/**
* Reads an XML file and returns an Optional containing the corresponding Document.
*
Expand All @@ -127,6 +151,11 @@ public static Optional<Document> getOptionalDomFromFile(final File file) {
}
}

private static Element getEmptyElement() {
Document doc = createEmptyDocument();
return doc.createElement("null");
}

private static XPathExpression createXPathExpression(String expression) throws XPathExpressionException {
XPath xpath = xPathFactory.newXPath();
return xpath.compile(expression);
Expand Down
102 changes: 102 additions & 0 deletions src/main/java/pt/codeforge/toolertools/zip/BaseZipBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package pt.codeforge.toolertools.zip;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class BaseZipBuilder implements ZipBuilder {

private final List<File> files = new ArrayList<>();
private Path targetPath;

public BaseZipBuilder() {
}

public BaseZipBuilder(Path targetPath) {
this.targetPath = targetPath;
}

public BaseZipBuilder(String targetPath) {
this.targetPath = Paths.get(targetPath);
}

@Override
public void createZip() {
if (this.targetPath == null) {
throw new IllegalStateException("Target path is not defined.");
}

try (FileOutputStream fos = new FileOutputStream(this.targetPath.toString());
ZipOutputStream zos = new ZipOutputStream(fos, StandardCharsets.UTF_8)) {

/* if(this.files.get(0).isDirectory()){
String name = this.files.get(0).getAbsolutePath() + File.separator + "output\\test2.properties";
System.out.println(name);
insertInZip(new File(name), zos);
}*/

this.files.forEach(file -> insertInZip(file, zos));
} catch (IOException ioe) {
throw new ZipBuilderException("Unable to create zip.", ioe);
}
}

@Override
public void addToZip(File file) {
if (file == null) {
throw new IllegalArgumentException("File cannot be null.");
}

this.files.add(file);
}

@Override
public void addAllToZip(List<File> files) {
if (files == null) {
throw new IllegalArgumentException("File's list cannot be null.");
}

List<File> filteredFiles = files.stream().filter(Objects::nonNull).collect(Collectors.toList());

this.files.addAll(filteredFiles);
}

@Override
public BaseZipBuilder setTargetPath(Path targetPath) {
this.targetPath = targetPath;
return this;
}

@Override
public BaseZipBuilder setTargetPath(String targetPath) {
this.targetPath = Paths.get(targetPath);
return this;
}

@Override
public int zipSize() {
return this.files.size();
}

private void insertInZip(File file, ZipOutputStream zos) {
try {
ZipEntry zipEntry = new ZipEntry(file.getName());
zos.putNextEntry(zipEntry);
Files.copy(file.getAbsoluteFile().toPath(), zos);
zos.closeEntry();
} catch (IOException ioe) {
throw new ZipBuilderException("unable to add to zip", ioe);
}
}
}
21 changes: 21 additions & 0 deletions src/main/java/pt/codeforge/toolertools/zip/ZipBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package pt.codeforge.toolertools.zip;

import java.io.File;
import java.nio.file.Path;
import java.util.List;

public interface ZipBuilder {

void createZip();

void addToZip(File file);

void addAllToZip(List<File> files);

int zipSize();

ZipBuilder setTargetPath(Path targetPath);

ZipBuilder setTargetPath(String targetPath);

}
25 changes: 25 additions & 0 deletions src/test/java/pt/codeforge/toolertools/xml/XmlHandlerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

class XmlHandlerTest {

private static final String TEST_ELEMENT_TEXT = "//test-element/text()";
private static final String TEST_ELEMENT_NODE = "//test-element";
private static final String NESTED_ELEMENT_TEXT = "//nested-element/text()";
private static final String EMPTY_ELEMENT_TEXT = "//empty-element/text()";
private static final String SELF_CLOSING_TEXT = "//self-closing/text()";
Expand Down Expand Up @@ -98,6 +100,29 @@ void givenCompliantValues_testGetNodeFromXPath_shouldReturnValidNode(String inpu
assertEquals(expectedNodeName, groupElement.getNodeName(), "Should be element node");
}

@ParameterizedTest
@ValueSource(strings = "src/test/resources/test_resource_1.xml")
void givenCompliantparams_testGetElementFromXPath_shouldReturnValidResults(String input){
Document doc = XmlHandler.getOptionalDomFromFile(new File(input)).orElseThrow(IllegalStateException::new);

Element groupElement = XmlHandler.getElementFromXPath(ELEMENT_GROUP_NODE, doc);
Element testElement = XmlHandler.getElementFromXPath(TEST_ELEMENT_NODE, doc);
Element malformedElement = XmlHandler.getElementFromXPath(MALFORMED_X_PATH, doc, true);

String expectedGroupNodeName = "element-group";
String expectedTestNodeName = "test-element";
String expectedAttribute = "test_attr";

assertNull(malformedElement);

assertEquals(Document.ELEMENT_NODE, groupElement.getNodeType(), "Should be element node");
assertEquals(expectedGroupNodeName, groupElement.getNodeName(), "Should be element-group");

assertEquals(Document.ELEMENT_NODE, testElement.getNodeType(), "Should be test element node");
assertEquals(expectedTestNodeName, testElement.getNodeName(), "Should be test element");
assertEquals(expectedAttribute, testElement.getAttribute("type"));
}

@ParameterizedTest
@ValueSource(strings = "src/test/resources/test_resource_1.xml")
void givenBadParams_getNodeFromXPath_nodesShouldBeInvalidButNotNull(String input) {
Expand Down
54 changes: 54 additions & 0 deletions src/test/java/pt/codeforge/toolertools/zip/BaseZipBuilderTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package pt.codeforge.toolertools.zip;

import static org.junit.jupiter.api.Assertions.assertThrows;

import java.io.File;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

class BaseZipBuilderTest {

@Test
void givenNoTargetPath_testCreateZip_shouldThrowIllegalStateException() {
BaseZipBuilder baseZipBuilder = new BaseZipBuilder();

assertThrows(IllegalStateException.class, baseZipBuilder::createZip);
}

@Test
void givenIncorrectPath_testCreateZip_shouldThrowZipBuilderException(){
BaseZipBuilder baseZipBuilder = new BaseZipBuilder("src/test/resources/output");

assertThrows(ZipBuilderException.class, baseZipBuilder::createZip);
}

@Test
void givenValidPath_testCreateZip(){
BaseZipBuilder baseZipBuilder = new BaseZipBuilder("src/test/resources/output/my.zip");

baseZipBuilder.createZip();
}

@Test
@Disabled("wip")
void test() {
BaseZipBuilder zipBuilder = new BaseZipBuilder().setTargetPath("src/test/resources/output/my.zip");

/*List<File> files = Arrays.asList(
new File("src/test/resources/test_resource_1.xml"),
new File("src/test/resources/test_resource_2.xml"),
new File("src/test/resources/test.properties")
);*/

List<File> files = Arrays.asList(
new File("src/test/resources/")
);

zipBuilder.addAllToZip(files);

zipBuilder.createZip();
}

}
2 changes: 1 addition & 1 deletion src/test/resources/test_resource_1.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://example.com/test">
<test-element>Test Value</test-element>
<test-element type="test_attr" >Test Value</test-element>
<empty-element></empty-element>
<self-closing/>
<element-group>
Expand Down

0 comments on commit 00fc2a0

Please sign in to comment.