JaxbUtils.java
/*
* Copyright 2020-2022 the original author or authors.
*
* 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.
*/
package org.bremersee.xml;
import static java.util.Objects.nonNull;
import static java.util.Objects.requireNonNull;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlSchema;
import jakarta.xml.bind.annotation.XmlType;
import java.util.Optional;
import java.util.stream.Stream;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.Assert;
/**
* The jaxb utils.
*
* @author Christian Bremer
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
abstract class JaxbUtils {
/**
* Gets name space of element.
*
* @param clazz the class
* @return the name space of element
*/
static Optional<String> getNameSpaceOfElement(Class<?> clazz) {
return Optional.ofNullable(clazz)
.map(c -> c.getAnnotation(XmlRootElement.class))
.map(XmlRootElement::namespace)
.filter(ns -> !ns.isBlank() && !"##default".equals(ns))
.or(() -> isInJaxbModelPackage(clazz)
? getNameSpace(requireNonNull(clazz).getPackage())
: Optional.empty());
}
/**
* Gets name space of type.
*
* @param clazz the class
* @return the name space of type
*/
static Optional<String> getNameSpaceOfType(Class<?> clazz) {
return Optional.ofNullable(clazz)
.map(c -> c.getAnnotation(XmlType.class))
.map(XmlType::namespace)
.filter(ns -> !ns.isBlank() && !"##default".equals(ns))
.or(() -> isInJaxbModelPackage(clazz)
? getNameSpace(requireNonNull(clazz).getPackage())
: Optional.empty());
}
/**
* Gets name space.
*
* @param pakkage the package
* @return the name space
*/
static Optional<String> getNameSpace(Package pakkage) {
return Optional.ofNullable(pakkage)
.map(p -> p.getAnnotation(XmlSchema.class))
.map(XmlSchema::namespace)
.filter(ns -> !ns.isBlank());
}
/**
* Gets schema location.
*
* @param pakkage the package
* @return the schema location
*/
static Optional<String> getSchemaLocation(Package pakkage) {
return Optional.ofNullable(pakkage)
.map(p -> p.getAnnotation(XmlSchema.class))
.map(XmlSchema::location)
.filter(location -> !location.isBlank() && !XmlSchema.NO_LOCATION.equals(location));
}
/**
* Is in jaxb model package boolean.
*
* @param clazz the class
* @return the boolean
*/
static boolean isInJaxbModelPackage(Class<?> clazz) {
return nonNull(clazz) && isJaxbModelPackage(clazz.getPackage());
}
/**
* Is jaxb model package boolean.
*
* @param pakkage the package
* @return the boolean
*/
static boolean isJaxbModelPackage(Package pakkage) {
return objectFactoryExists(pakkage) || jaxbIndexExists(pakkage);
}
private static boolean objectFactoryExists(Package pakkage) {
return Optional.ofNullable(pakkage)
.map(p -> {
try {
Class.forName(pakkage.getName() + ".ObjectFactory");
return true;
} catch (ClassNotFoundException e) {
return false;
}
})
.orElse(false);
}
private static boolean jaxbIndexExists(Package pakkage) {
return Optional.ofNullable(pakkage)
.map(Package::getName)
.map(p -> p.replaceAll("[.]", "/"))
.map(path -> path + "/jaxb.index")
.map(resource -> new ClassPathResource(resource).exists())
.orElse(false);
}
/**
* Find jaxb classes stream.
*
* @param packageName the package name
* @param classLoaders the class loaders
* @return the stream
*/
static Stream<Class<?>> findJaxbClasses(String packageName, ClassLoader... classLoaders) {
Assert.hasText(packageName, "Package name must be present.");
return new Reflections(packageName)
.get(Scanners.SubTypes.of(Scanners.TypesAnnotated
.with(XmlRootElement.class, XmlType.class)).asClass(classLoaders))
.stream();
}
}