Skip to content

Commit

Permalink
Add JXE integration
Browse files Browse the repository at this point in the history
Affects: #2
  • Loading branch information
io7m committed Oct 15, 2020
1 parent 0f7cb0a commit abe9129
Show file tree
Hide file tree
Showing 14 changed files with 714 additions and 30 deletions.
5 changes: 5 additions & 0 deletions com.io7m.blackthorne.api/pom.xml
Expand Up @@ -41,6 +41,11 @@
<artifactId>org.osgi.annotation.bundle</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.annotation.versioning</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.immutables</groupId>
<artifactId>value</artifactId>
Expand Down
@@ -0,0 +1,87 @@
/*
* Copyright © 2020 Mark Raynsford <code@io7m.com> http://io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

package com.io7m.blackthorne.api;

import java.util.List;
import java.util.Objects;

/**
* An exception raised by convenience methods.
*/

public final class BTException extends Exception
{
private final List<BTParseError> errors;

/**
* @return The parse errors encountered during parsing
*/

public List<BTParseError> errors()
{
return this.errors;
}

/**
* Construct an exception.
*
* @param inMessage The exception message
* @param inErrors The parse errors
*/

public BTException(
final String inMessage,
final List<BTParseError> inErrors)
{
super(Objects.requireNonNull(inMessage, "message"));
this.errors = Objects.requireNonNull(inErrors, "errors");
}

/**
* Construct an exception.
*
* @param inMessage The exception message
* @param inCause The cause
* @param inErrors The parse errors
*/

public BTException(
final String inMessage,
final Throwable inCause,
final List<BTParseError> inErrors)
{
super(
Objects.requireNonNull(inMessage, "message"),
Objects.requireNonNull(inCause, "cause"));
this.errors = Objects.requireNonNull(inErrors, "errors");
}

/**
* Construct an exception.
*
* @param inCause The cause
* @param inErrors The parse errors
*/

public BTException(
final Throwable inCause,
final List<BTParseError> inErrors)
{
super(Objects.requireNonNull(inCause, "cause"));
this.errors = Objects.requireNonNull(inErrors, "errors");
}
}
Expand Up @@ -16,19 +16,36 @@

package com.io7m.blackthorne.api;

import com.io7m.jlexing.core.LexicalPosition;
import com.io7m.junreachable.UnreachableCodeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.function.Function;

import static com.io7m.blackthorne.api.BTParseErrorType.Severity.ERROR;

/**
* Convenience functions.
*/

public final class Blackthorne
{
private static final Logger LOG =
LoggerFactory.getLogger(Blackthorne.class);

private Blackthorne()
{
throw new UnreachableCodeException();
Expand Down Expand Up @@ -198,7 +215,9 @@ public static <S> BTElementHandlerConstructorType<?, S> forScalarAttribute(
Objects.requireNonNull(namespaceURI, "namespaceURI");
Objects.requireNonNull(localName, "localName");
Objects.requireNonNull(parser, "parser");
return forScalarAttribute(BTQualifiedName.of(namespaceURI, localName), parser);
return forScalarAttribute(
BTQualifiedName.of(namespaceURI, localName),
parser);
}

/**
Expand All @@ -224,7 +243,11 @@ public static <S> BTElementHandlerConstructorType<S, List<S>> forListMono(
Objects.requireNonNull(childElementName, "childElementName");
Objects.requireNonNull(itemHandler, "itemHandler");
return context ->
new BTListMonoHandler<>(elementName, childElementName, itemHandler, ignoreUnrecognized);
new BTListMonoHandler<>(
elementName,
childElementName,
itemHandler,
ignoreUnrecognized);
}

/**
Expand All @@ -247,6 +270,87 @@ public static <S> BTElementHandlerConstructorType<S, List<S>> forListPoly(
{
Objects.requireNonNull(elementName, "elementName");
Objects.requireNonNull(itemHandlers, "itemHandlers");
return context -> new BTListPolyHandler<S>(elementName, itemHandlers, ignoreUnrecognized);
return context -> new BTListPolyHandler<S>(
elementName,
itemHandlers,
ignoreUnrecognized);
}

/**
* A convenience method to configure and execute a parser.
*
* @param source The source URI
* @param stream The input stream
* @param xmlReaders A supplier of XML readers
* @param rootElements The root element handlers
* @param <T> The type of returned values
*
* @return The parsed value
*
* @throws BTException On parse errors
*/

public static <T> T parse(
final URI source,
final InputStream stream,
final Callable<XMLReader> xmlReaders,
final Map<BTQualifiedName, BTElementHandlerConstructorType<?, T>> rootElements)
throws BTException
{
final var errors =
new ArrayList<BTParseError>(32);
final var contentHandler =
new BTContentHandler<>(source, errors::add, rootElements);

try {
final var reader = xmlReaders.call();
reader.setContentHandler(contentHandler);
reader.setErrorHandler(contentHandler);

final var inputSource = new InputSource(stream);
inputSource.setPublicId(source.toString());

reader.parse(inputSource);

final var resultOpt = contentHandler.result();
if (resultOpt.isEmpty()) {
throw new BTException("Parse failed.", new IOException(), errors);
}

return resultOpt.get();
} catch (final SAXParseException e) {
LOG.error("error encountered during parsing: ", e);

final var position =
LexicalPosition.of(
e.getLineNumber(),
e.getColumnNumber(),
Optional.of(source)
);

errors.add(
BTParseError.builder()
.setLexical(position)
.setSeverity(ERROR)
.setMessage(e.getMessage())
.build()
);

throw new BTException(e.getMessage(), e, errors);
} catch (final Exception e) {
LOG.error("error encountered during parsing: ", e);

final var position =
LexicalPosition.of(-1, -1, Optional.of(source));

errors.add(
BTParseError.builder()
.setLexical(position)
.setSeverity(ERROR)
.setMessage(e.getMessage())
.build()
);
throw new BTException(e.getMessage(), e, errors);
}
}
}
Expand Up @@ -18,5 +18,9 @@
* Typed XML stream processing (API)
*/

@org.osgi.annotation.bundle.Export
@Export
@Version("1.0.0")
package com.io7m.blackthorne.api;

import org.osgi.annotation.bundle.Export;
import org.osgi.annotation.versioning.Version;
1 change: 1 addition & 0 deletions com.io7m.blackthorne.api/src/main/java/module-info.java
Expand Up @@ -23,6 +23,7 @@
requires static com.io7m.immutables.style;
requires static org.immutables.value;
requires static org.osgi.annotation.bundle;
requires static org.osgi.annotation.versioning;

requires com.io7m.jaffirm.core;
requires com.io7m.jlexing.core;
Expand Down
44 changes: 44 additions & 0 deletions com.io7m.blackthorne.jxe/pom.xml
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>com.io7m.blackthorne</artifactId>
<groupId>com.io7m.blackthorne</groupId>
<version>0.0.6-SNAPSHOT</version>
</parent>

<artifactId>com.io7m.blackthorne.jxe</artifactId>

<name>com.io7m.blackthorne.jxe</name>
<description>Typed XML stream processing (JXE integration)</description>
<url>http://github.com/io7m/blackthorne</url>

<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>com.io7m.blackthorne.api</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.io7m.jxe</groupId>
<artifactId>com.io7m.jxe.core</artifactId>
</dependency>

<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.annotation.bundle</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.annotation.versioning</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

</project>

0 comments on commit abe9129

Please sign in to comment.