io.jenetics.xml.stream.Reader Maven / Gradle / Ivy
The newest version!
/*
* Java Genetic Algorithm Library (jenetics-8.1.0).
* Copyright (c) 2007-2024 Franz Wilhelmstötter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author:
* Franz Wilhelmstötter ([email protected])
*/
package io.jenetics.xml.stream;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import static javax.xml.stream.XMLStreamConstants.CDATA;
import static javax.xml.stream.XMLStreamConstants.CHARACTERS;
import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import io.jenetics.xml.stream.Reader.Type;
/**
* XML reader class, used for reading objects in XML format.
* XML
* {@code
*
* -2147483648
* 2147483647
*
* -1878762439
* -957346595
* -88668137
*
*
* }
*
* Reader definition
* {@snippet lang="java":
* final Reader reader =
* elem(
* (Object[] v) -> {
* final int length = (int)v[0];
* final int min = (int)v[1];
* final int max = (int)v[2];
* final List alleles = (List)v[3];
* assert alleles.size() == length;
*
* return IntegerChromosome.of(
* alleles.stream()
* .map(value -> IntegerGene.of(value, min, max))
* .toArray(IntegerGene[]::new)
* );
* },
* "int-chromosome",
* attr("length").map(Integer::parseInt),
* elem("min", text().map(Integer::parseInt)),
* elem("max", text().map(Integer::parseInt)),
* elem("alleles",
* elems(elem("allele", text().map(Integer::parseInt)))
* )
* );
* }
*
* @author Franz Wilhelmstötter
* @version 3.9
* @since 3.9
*/
public abstract class Reader {
/**
* Represents the XML element type.
*/
enum Type {
/**
* Denotes a element reader.
*/
ELEM,
/**
* Denotes a element attribute reader.
*/
ATTR,
/**
* Denotes a reader of elements of the same type.
*/
LIST,
/**
* Denotes a reader of the text of a element.
*/
TEXT
}
private final String _name;
private final Type _type;
/**
* Create a new XML reader with the given name and type.
*
* @param name the element name of the reader
* @param type the element type of the reader
* @throws NullPointerException if one of the give arguments is {@code null}
*/
Reader(final String name, final Type type) {
_name = requireNonNull(name);
_type = requireNonNull(type);
}
/**
* Read the given type from the underlying XML stream {@code reader}.
*
* {@snippet lang="java":
* try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
* // Move XML stream to first the element.
* xml.next();
* return reader.read(xml);
* }
* }
*
* @param xml the underlying XML stream {@code reader}
* @return the data read from the XML stream, maybe {@code null}
* @throws XMLStreamException if an error occurs while reading the value
* @throws NullPointerException if the given {@code xml} stream reader is
* {@code null}
*/
public abstract T read(final XMLStreamReader xml) throws XMLStreamException;
/**
* Create a new reader for the new mapped type {@code B}.
*
* @param mapper the mapper function
* @param the target type of the new reader
* @return a new reader
* @throws NullPointerException if the given {@code mapper} function is
* {@code null}
*/
public Reader map(final Function super T, ? extends B> mapper) {
requireNonNull(mapper);
return new Reader<>(_name, _type) {
@Override
public B read(final XMLStreamReader xml)
throws XMLStreamException {
try {
return mapper.apply(Reader.this.read(xml));
} catch (RuntimeException e) {
throw new XMLStreamException(e);
}
}
};
}
/**
* Return the name of the element processed by this reader.
*
* @return the element name the reader is processing
*/
String name() {
return _name;
}
/**
* Return the element type of the reader.
*
* @return the element type of the reader
*/
Type type() {
return _type;
}
@Override
public String toString() {
return format("Reader[%s, %s]", name(), type());
}
/* *************************************************************************
* Static reader factory methods.
* ************************************************************************/
/**
* Return a {@code Reader} for reading an attribute of an element.
*
* XML
*
{@code }
*
* Reader definition
* {@snippet lang="java":
* final Reader reader =
* elem(
* v -> (Integer)v[0],
* "element",
* attr("length").map(Integer::parseInt)
* );
* }
*
* @param name the attribute name
* @return an attribute reader
* @throws NullPointerException if the given {@code name} is {@code null}
*/
public static Reader attr(final String name) {
return new AttrReader(name);
}
/**
* Return a {@code Reader} for reading the text of an element.
*
* XML
*
{@code 1234}
*
* Reader definition
* {@snippet lang="java":
* final Reader reader =
* elem(
* v -> (Integer)v[0],
* "element",
* text().map(Integer::parseInt)
* );
* }
*
* @return an element text reader
*/
public static Reader text() {
return new TextReader();
}
/**
* Return a {@code Reader} for reading an object of type {@code T} from the
* XML element with the given {@code name}.
*
*
* XML
*
{@code 1234}
*
* Reader definition
* {@snippet lang="java":
* final Reader reader =
* elem(
* v -> {
* final String name = (String)v[0];
* final Integer value = (Integer)v[1];
* return Property.of(name, value);
* },
* "property",
* attr("name"),
* text().map(Integer::parseInt)
* );
* }
*
* @param generator the generator function, which build the result object
* from the given parameter array
* @param name the name of the root (subtree) element
* @param children the child element reader, which creates the values
* forwarded to the {@code generator} function
* @param the reader result type
* @return a node reader
* @throws NullPointerException if one of the given arguments is {@code null}
* @throws IllegalArgumentException if the given child readers contains more
* than one text reader
*/
public static Reader elem(
final Function