diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 0000000..3096444 --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,228 @@ + + + + 4.0.0 + + io.openepcis + openepcis-document-converter-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + openepcis-document-converter + openepcis-document-converter + Project to convert EPCIS events in XML format to JSON/JSON-LD and vice-versa. Also, supports the conversion of EPCIS 1.2 XML document to 2.0 XML document and vice + versa. + https://github.com/openepcis/openepcis-document-converter + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + + Aravinda Baliga B + aravinda.baliga@benelog.com + benelog GmbH & Co. KG + https://www.benelog.com + + + Sven Boeckelmann + sven.boeckelmann@benelog.com + benelog GmbH & Co. KG + https://www.benelog.com + + + + + scm:git:git://github.com/openepcis/openepcis-document-converter.git + scm:git:ssh://github.com:openepcis/openepcis-document-converter.git + https://github.com/openepcis/openepcis-document-converter/tree/main + + + + + io.openepcis + openepcis-model-rest + ${project.parent.version} + + + io.openepcis + openepcis-model-epcis + ${project.parent.version} + + + io.openepcis + openepcis-document-validation-service + ${project.parent.version} + + + io.openepcis + openepcis-repository-common + + + io.smallrye.reactive + mutiny + + + jakarta.enterprise + jakarta.enterprise.cdi-api + provided + + + jakarta.ws.rs + jakarta.ws.rs-api + provided + + + + org.projectlombok + lombok + provided + + + + + jakarta.xml.bind + jakarta.xml.bind-api + + + org.eclipse.persistence + org.eclipse.persistence.moxy + + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + commons-io + commons-io + + + + + io.openepcis + openepcis-epcis-constants + ${project.parent.version} + + + + + io.openepcis + openepcis-test-resources + ${project.parent.version} + + + + org.junit.jupiter + junit-jupiter + test + + + org.slf4j + slf4j-simple + test + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + maven-surefire-plugin + 3.1.2 + + + + + + + + coverage + + false + + + + + org.jacoco + jacoco-maven-plugin + + + report + + report + + verify + + + + + + + + + + + + sonatype-releases + https://s01.oss.sonatype.org/content/repositories/releases + + + + sonatype-staging + https://s01.oss.sonatype.org/content/repositories/snapshots + + true + always + + + + + diff --git a/src/main/java/io/openepcis/convert/AttributePreScanUtil.java b/core/src/main/java/io/openepcis/converter/AttributePreScanUtil.java similarity index 98% rename from src/main/java/io/openepcis/convert/AttributePreScanUtil.java rename to core/src/main/java/io/openepcis/converter/AttributePreScanUtil.java index 7530312..40fd16d 100644 --- a/src/main/java/io/openepcis/convert/AttributePreScanUtil.java +++ b/core/src/main/java/io/openepcis/converter/AttributePreScanUtil.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert; +package io.openepcis.converter; import java.io.BufferedInputStream; import java.io.IOException; diff --git a/src/main/java/io/openepcis/convert/Conversion.java b/core/src/main/java/io/openepcis/converter/Conversion.java similarity index 99% rename from src/main/java/io/openepcis/convert/Conversion.java rename to core/src/main/java/io/openepcis/converter/Conversion.java index 9fa19ac..6473e32 100644 --- a/src/main/java/io/openepcis/convert/Conversion.java +++ b/core/src/main/java/io/openepcis/converter/Conversion.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert; +package io.openepcis.converter; import io.openepcis.constants.EPCISFormat; import io.openepcis.constants.EPCISVersion; diff --git a/src/main/java/io/openepcis/convert/EventsConverter.java b/core/src/main/java/io/openepcis/converter/EventsConverter.java similarity index 91% rename from src/main/java/io/openepcis/convert/EventsConverter.java rename to core/src/main/java/io/openepcis/converter/EventsConverter.java index 240854c..2d4e3a2 100644 --- a/src/main/java/io/openepcis/convert/EventsConverter.java +++ b/core/src/main/java/io/openepcis/converter/EventsConverter.java @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert; +package io.openepcis.converter; -import io.openepcis.convert.collector.EPCISEventCollector; -import io.openepcis.convert.collector.EventHandler; +import io.openepcis.converter.collector.EPCISEventCollector; +import io.openepcis.converter.collector.EventHandler; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; import java.io.IOException; diff --git a/src/main/java/io/openepcis/convert/VersionTransformer.java b/core/src/main/java/io/openepcis/converter/VersionTransformer.java similarity index 95% rename from src/main/java/io/openepcis/convert/VersionTransformer.java rename to core/src/main/java/io/openepcis/converter/VersionTransformer.java index f248aec..c9c013a 100644 --- a/src/main/java/io/openepcis/convert/VersionTransformer.java +++ b/core/src/main/java/io/openepcis/converter/VersionTransformer.java @@ -13,24 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert; +package io.openepcis.converter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; -import io.openepcis.constants.EPCIS; import io.openepcis.constants.EPCISFormat; import io.openepcis.constants.EPCISVersion; -import io.openepcis.convert.collector.EventHandler; -import io.openepcis.convert.collector.JsonEPCISEventCollector; -import io.openepcis.convert.collector.XmlEPCISEventCollector; -import io.openepcis.convert.exception.FormatConverterException; -import io.openepcis.convert.json.JSONEventValueTransformer; -import io.openepcis.convert.json.JsonToXmlConverter; -import io.openepcis.convert.util.ChannelUtil; -import io.openepcis.convert.xml.ProblemResponseBodyMarshaller; -import io.openepcis.convert.xml.XMLEventValueTransformer; -import io.openepcis.convert.xml.XmlToJsonConverter; -import io.openepcis.convert.xml.XmlVersionTransformer; +import io.openepcis.converter.collector.EventHandler; +import io.openepcis.converter.collector.JsonEPCISEventCollector; +import io.openepcis.converter.collector.XmlEPCISEventCollector; +import io.openepcis.converter.exception.FormatConverterException; +import io.openepcis.converter.json.JSONEventValueTransformer; +import io.openepcis.converter.json.JsonToXmlConverter; +import io.openepcis.converter.util.ChannelUtil; +import io.openepcis.converter.xml.ProblemResponseBodyMarshaller; +import io.openepcis.converter.xml.XMLEventValueTransformer; +import io.openepcis.converter.xml.XmlToJsonConverter; +import io.openepcis.converter.xml.XmlVersionTransformer; import io.openepcis.model.rest.ProblemResponseBody; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; @@ -55,6 +54,19 @@ public class VersionTransformer { .setSerializationInclusion(JsonInclude.Include.NON_EMPTY); private final ExecutorService executorService; + + public XmlVersionTransformer getXmlVersionTransformer() { + return xmlVersionTransformer; + } + + public XmlToJsonConverter getXmlToJsonConverter() { + return xmlToJsonConverter; + } + + public JsonToXmlConverter getJsonToXmlConverter() { + return jsonToXmlConverter; + } + private final XmlVersionTransformer xmlVersionTransformer; private final XmlToJsonConverter xmlToJsonConverter; private final JsonToXmlConverter jsonToXmlConverter; diff --git a/src/main/java/io/openepcis/convert/VersionTransformerFeature.java b/core/src/main/java/io/openepcis/converter/VersionTransformerFeature.java similarity index 97% rename from src/main/java/io/openepcis/convert/VersionTransformerFeature.java rename to core/src/main/java/io/openepcis/converter/VersionTransformerFeature.java index 35dc2c6..29a5749 100644 --- a/src/main/java/io/openepcis/convert/VersionTransformerFeature.java +++ b/core/src/main/java/io/openepcis/converter/VersionTransformerFeature.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert; +package io.openepcis.converter; import java.util.Collections; import java.util.List; diff --git a/src/main/java/io/openepcis/convert/collector/EPCISEventCollector.java b/core/src/main/java/io/openepcis/converter/collector/EPCISEventCollector.java similarity index 97% rename from src/main/java/io/openepcis/convert/collector/EPCISEventCollector.java rename to core/src/main/java/io/openepcis/converter/collector/EPCISEventCollector.java index 2f49a85..e991d65 100644 --- a/src/main/java/io/openepcis/convert/collector/EPCISEventCollector.java +++ b/core/src/main/java/io/openepcis/converter/collector/EPCISEventCollector.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.collector; +package io.openepcis.converter.collector; import java.util.Map; diff --git a/src/main/java/io/openepcis/convert/collector/EventHandler.java b/core/src/main/java/io/openepcis/converter/collector/EventHandler.java similarity index 95% rename from src/main/java/io/openepcis/convert/collector/EventHandler.java rename to core/src/main/java/io/openepcis/converter/collector/EventHandler.java index f7c0dd6..4751d1a 100644 --- a/src/main/java/io/openepcis/convert/collector/EventHandler.java +++ b/core/src/main/java/io/openepcis/converter/collector/EventHandler.java @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.collector; +package io.openepcis.converter.collector; + +import io.openepcis.converter.exception.FormatConverterException; +import io.openepcis.converter.validator.EPCISEventValidator; -import io.openepcis.convert.exception.FormatConverterException; -import io.openepcis.convert.validator.EPCISEventValidator; import java.util.Map; /** diff --git a/src/main/java/io/openepcis/convert/collector/EventListCollector.java b/core/src/main/java/io/openepcis/converter/collector/EventListCollector.java similarity index 97% rename from src/main/java/io/openepcis/convert/collector/EventListCollector.java rename to core/src/main/java/io/openepcis/converter/collector/EventListCollector.java index f90d134..95e4b86 100644 --- a/src/main/java/io/openepcis/convert/collector/EventListCollector.java +++ b/core/src/main/java/io/openepcis/converter/collector/EventListCollector.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.collector; +package io.openepcis.converter.collector; import java.util.List; diff --git a/src/main/java/io/openepcis/convert/collector/JsonEPCISEventCollector.java b/core/src/main/java/io/openepcis/converter/collector/JsonEPCISEventCollector.java similarity index 98% rename from src/main/java/io/openepcis/convert/collector/JsonEPCISEventCollector.java rename to core/src/main/java/io/openepcis/converter/collector/JsonEPCISEventCollector.java index ea4b384..247da2a 100644 --- a/src/main/java/io/openepcis/convert/collector/JsonEPCISEventCollector.java +++ b/core/src/main/java/io/openepcis/converter/collector/JsonEPCISEventCollector.java @@ -13,20 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.collector; +package io.openepcis.converter.collector; import static io.openepcis.constants.EPCIS.*; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import io.openepcis.constants.EPCISVersion; -import io.openepcis.convert.exception.FormatConverterException; +import io.openepcis.converter.exception.FormatConverterException; import io.openepcis.model.epcis.util.DefaultJsonSchemaNamespaceURIResolver; import java.io.IOException; import java.io.OutputStream; import java.util.Map; -import lombok.Getter; -import lombok.Setter; + import org.apache.commons.lang3.StringUtils; /** diff --git a/src/main/java/io/openepcis/convert/collector/XmlEPCISEventCollector.java b/core/src/main/java/io/openepcis/converter/collector/XmlEPCISEventCollector.java similarity index 98% rename from src/main/java/io/openepcis/convert/collector/XmlEPCISEventCollector.java rename to core/src/main/java/io/openepcis/converter/collector/XmlEPCISEventCollector.java index 3077695..6b889ce 100644 --- a/src/main/java/io/openepcis/convert/collector/XmlEPCISEventCollector.java +++ b/core/src/main/java/io/openepcis/converter/collector/XmlEPCISEventCollector.java @@ -13,18 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.collector; +package io.openepcis.converter.collector; import io.openepcis.constants.EPCIS; -import io.openepcis.convert.exception.FormatConverterException; +import io.openepcis.converter.exception.FormatConverterException; import java.io.OutputStream; import java.io.StringReader; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.stream.*; import javax.xml.stream.util.EventReaderDelegate; -import lombok.Getter; -import lombok.Setter; + import org.apache.commons.lang3.StringUtils; /** diff --git a/core/src/main/java/io/openepcis/converter/common/GS1FormatSupport.java b/core/src/main/java/io/openepcis/converter/common/GS1FormatSupport.java new file mode 100644 index 0000000..fd0e58a --- /dev/null +++ b/core/src/main/java/io/openepcis/converter/common/GS1FormatSupport.java @@ -0,0 +1,77 @@ +package io.openepcis.converter.common; + +import io.openepcis.constants.EPCISFormat; +import io.openepcis.model.epcis.EPCISEvent; +import io.openepcis.model.epcis.constants.CommonConstants; +import io.openepcis.model.epcis.format.CBVFormat; +import io.openepcis.model.epcis.format.EPCFormat; +import io.openepcis.model.epcis.format.FormatPreference; +import io.openepcis.repository.model.EPCISEventES; +import io.openepcis.repository.util.EventConvertor; +import jakarta.ws.rs.core.MediaType; + +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Function; + +public class GS1FormatSupport { + + public interface RequestHeaderFacade { + String getHeader(String name); + } + + public static final RequestHeaderFacade createRequestFacade(final Function function) { + return new RequestHeaderFacade() { + @Override + public String getHeader(String name) { + return function.apply(name); + } + }; + } + + public static final FormatPreference getFormatPreference(RequestHeaderFacade requestHeaderFacade) { + Optional epcFormat = + Optional.ofNullable(requestHeaderFacade.getHeader(CommonConstants.GS1_EPC_FORMAT)); + Optional cbvFormat = + Optional.ofNullable(requestHeaderFacade.getHeader(CommonConstants.GS1_CBV_XML_FORMAT)); + return FormatPreference.getInstance(epcFormat, cbvFormat); + } + + public static final BiFunction, Object> createMapper(final FormatPreference formatPreference) { + if (formatPreference.getEpcFormat() != EPCFormat.No_Preference + || formatPreference.getCbvFormat() != CBVFormat.No_Preference) { + return (o, context) -> { + if (o != null && EPCISEvent.class.isAssignableFrom(o.getClass())) { + EPCISEventES esEvent = + EventConvertor.getESRepresentation((EPCISEvent) o, new HashMap<>(), context); + return esEvent.getCoreModel(formatPreference, context); + } + return o; + }; + } + // default function - return same + return (o, context) -> o; + } + + public static boolean isValidMediaType(MediaType mediaType) { + String type = mediaType.getType(); + String subtype = mediaType.getSubtype(); + + return (MediaType.APPLICATION_XML_TYPE.getType().equals(type) && MediaType.APPLICATION_XML_TYPE.getSubtype().equals(subtype)) + || (MediaType.APPLICATION_JSON_TYPE.getType().equals(type) && MediaType.APPLICATION_JSON_TYPE.getSubtype().equals(subtype)) + || ("application".equals(type) && "ld+json".equals(subtype)); + } + + public static EPCISFormat getEPCISFormat(MediaType mediaType) { + String type = mediaType.getType(); + String subtype = mediaType.getSubtype(); + + if (MediaType.APPLICATION_XML_TYPE.getType().equals(type) && MediaType.APPLICATION_XML_TYPE.getSubtype().equals(subtype)) { + return EPCISFormat.XML; + } else { + return EPCISFormat.JSON_LD; + } + } +} diff --git a/core/src/main/java/io/openepcis/converter/common/IdentifierConverterUtil.java b/core/src/main/java/io/openepcis/converter/common/IdentifierConverterUtil.java new file mode 100644 index 0000000..a71e33c --- /dev/null +++ b/core/src/main/java/io/openepcis/converter/common/IdentifierConverterUtil.java @@ -0,0 +1,78 @@ +package io.openepcis.converter.common; + +import io.openepcis.converter.exception.FormatConverterException; +import io.openepcis.epc.translator.util.ConverterUtil; + +import java.util.Map; + +public class IdentifierConverterUtil { + + public static final String toWebURI(final String urn) { + try { + // Differentiate between Instance/Class level URN identifiers & call the respective + // method for conversion + if (urn.contains(":idpat:") || urn.contains(":class:")) { + return ConverterUtil.toURIForClassLevelIdentifier(urn); + } else { + return ConverterUtil.toURI(urn); + } + } catch (Exception exception) { + throw new FormatConverterException(exception); + } + } + + public static Map toURN(final String webURI) { + Map convertedURN; + try { + // Try to convert WebURI into URN assuming the WebURI is Instance level identifier + + // If WebURI contains the space character then consider the digit after space as GCP + // Length + if (webURI.contains(" ")) { + // Get the GCP Length provided after the identifier by separating the space + String gcpLength = webURI.substring(webURI.indexOf(" ") + 1); + + // Call the method to convert to URN from Instance WebURI by providing the WebURI + // and + // GCPLength + convertedURN = + ConverterUtil.toURN(webURI.split(" ")[0], Integer.parseInt(gcpLength)); + } else { + // If Class WebURI does not contain whitespace then directly convert to URN + convertedURN = ConverterUtil.toURN(webURI); + } + } catch (Exception exception) { + // If error is thrown during Instance level Web URI conversion then try to convert + // the Web URI into Class level URN + try { + + // If WebURI contains the space character then consider the digit after space as + // GCP Length + if (webURI.contains(" ")) { + // Get the GCP Length provided after the identifier by separating the space + String gcpLength = webURI.substring(webURI.indexOf(" ") + 1); + + // Call the method to convert to URN from Class WebURI by providing the WebURI + // and GCPLength + convertedURN = + ConverterUtil.toURNForClassLevelIdentifier( + webURI.split(" ")[0], Integer.parseInt(gcpLength)); + } else { + // If Class WebURI does not contain whitespace then directly convert to URN + convertedURN = ConverterUtil.toURNForClassLevelIdentifier(webURI); + } + } catch (Exception e) { + // If error is thrown during both conversion then show both message to the user + throw new FormatConverterException( + "Instance Level Identifiers : " + + exception.getMessage() + + System.lineSeparator() + + System.lineSeparator() + + "Class Level Identifier : " + + e.getMessage(), + e); + } + } + return convertedURN; + } +} diff --git a/src/main/java/io/openepcis/convert/exception/FormatConverterException.java b/core/src/main/java/io/openepcis/converter/exception/FormatConverterException.java similarity index 97% rename from src/main/java/io/openepcis/convert/exception/FormatConverterException.java rename to core/src/main/java/io/openepcis/converter/exception/FormatConverterException.java index 0310279..4701d3c 100644 --- a/src/main/java/io/openepcis/convert/exception/FormatConverterException.java +++ b/core/src/main/java/io/openepcis/converter/exception/FormatConverterException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.exception; +package io.openepcis.converter.exception; import java.io.Serial; diff --git a/src/main/java/io/openepcis/convert/json/JSONEventValueTransformer.java b/core/src/main/java/io/openepcis/converter/json/JSONEventValueTransformer.java similarity index 94% rename from src/main/java/io/openepcis/convert/json/JSONEventValueTransformer.java rename to core/src/main/java/io/openepcis/converter/json/JSONEventValueTransformer.java index caa1256..898d9ff 100644 --- a/src/main/java/io/openepcis/convert/json/JSONEventValueTransformer.java +++ b/core/src/main/java/io/openepcis/converter/json/JSONEventValueTransformer.java @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.json; +package io.openepcis.converter.json; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -import io.openepcis.convert.EventsConverter; -import io.openepcis.convert.collector.EPCISEventCollector; -import io.openepcis.convert.collector.EventHandler; -import io.openepcis.convert.exception.FormatConverterException; +import io.openepcis.converter.EventsConverter; +import io.openepcis.converter.collector.EPCISEventCollector; +import io.openepcis.converter.collector.EventHandler; +import io.openepcis.converter.exception.FormatConverterException; import io.openepcis.model.epcis.EPCISEvent; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; @@ -35,7 +35,6 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; -import java.util.function.Function; public class JSONEventValueTransformer extends JsonEventParser implements EventsConverter { diff --git a/src/main/java/io/openepcis/convert/json/JsonEventParser.java b/core/src/main/java/io/openepcis/converter/json/JsonEventParser.java similarity index 96% rename from src/main/java/io/openepcis/convert/json/JsonEventParser.java rename to core/src/main/java/io/openepcis/converter/json/JsonEventParser.java index 3add1e9..c9090f3 100644 --- a/src/main/java/io/openepcis/convert/json/JsonEventParser.java +++ b/core/src/main/java/io/openepcis/converter/json/JsonEventParser.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.json; +package io.openepcis.converter.json; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; @@ -22,11 +22,11 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import io.openepcis.constants.EPCIS; -import io.openepcis.convert.collector.EPCISEventCollector; -import io.openepcis.convert.collector.EventHandler; -import io.openepcis.convert.exception.FormatConverterException; -import io.openepcis.convert.util.IndentingXMLStreamWriter; -import io.openepcis.convert.util.NonEPCISNamespaceXMLStreamWriter; +import io.openepcis.converter.collector.EPCISEventCollector; +import io.openepcis.converter.collector.EventHandler; +import io.openepcis.converter.exception.FormatConverterException; +import io.openepcis.converter.util.IndentingXMLStreamWriter; +import io.openepcis.converter.util.NonEPCISNamespaceXMLStreamWriter; import io.openepcis.model.epcis.EPCISEvent; import io.openepcis.model.epcis.XmlSupportExtension; import io.openepcis.model.epcis.util.DefaultJsonSchemaNamespaceURIResolver; @@ -46,7 +46,6 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; -import java.util.function.Function; import java.util.stream.Collectors; @Slf4j diff --git a/src/main/java/io/openepcis/convert/json/JsonNodeDupeFieldHandlingDeserializer.java b/core/src/main/java/io/openepcis/converter/json/JsonNodeDupeFieldHandlingDeserializer.java similarity index 98% rename from src/main/java/io/openepcis/convert/json/JsonNodeDupeFieldHandlingDeserializer.java rename to core/src/main/java/io/openepcis/converter/json/JsonNodeDupeFieldHandlingDeserializer.java index 3589d9e..43ba680 100644 --- a/src/main/java/io/openepcis/convert/json/JsonNodeDupeFieldHandlingDeserializer.java +++ b/core/src/main/java/io/openepcis/converter/json/JsonNodeDupeFieldHandlingDeserializer.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.json; +package io.openepcis.converter.json; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; diff --git a/src/main/java/io/openepcis/convert/json/JsonToXmlConverter.java b/core/src/main/java/io/openepcis/converter/json/JsonToXmlConverter.java similarity index 94% rename from src/main/java/io/openepcis/convert/json/JsonToXmlConverter.java rename to core/src/main/java/io/openepcis/converter/json/JsonToXmlConverter.java index 06d86cf..3eec7d9 100644 --- a/src/main/java/io/openepcis/convert/json/JsonToXmlConverter.java +++ b/core/src/main/java/io/openepcis/converter/json/JsonToXmlConverter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.json; +package io.openepcis.converter.json; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; @@ -22,11 +22,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import io.openepcis.convert.EventsConverter; -import io.openepcis.convert.collector.EventHandler; -import io.openepcis.convert.exception.FormatConverterException; -import io.openepcis.convert.util.IndentingXMLStreamWriter; -import io.openepcis.convert.util.NonEPCISNamespaceXMLStreamWriter; +import io.openepcis.converter.EventsConverter; +import io.openepcis.converter.collector.EventHandler; +import io.openepcis.converter.collector.EPCISEventCollector; +import io.openepcis.converter.exception.FormatConverterException; +import io.openepcis.converter.util.IndentingXMLStreamWriter; +import io.openepcis.converter.util.NonEPCISNamespaceXMLStreamWriter; import io.openepcis.model.epcis.EPCISEvent; import io.openepcis.model.epcis.util.EPCISNamespacePrefixMapper; import jakarta.enterprise.context.RequestScoped; @@ -108,7 +109,7 @@ public JsonToXmlConverter() throws JAXBException { @Override public void convert( InputStream jsonStream, - EventHandler eventHandler) + EventHandler eventHandler) throws IOException, JAXBException { convert(jsonStream, eventHandler, this.jaxbContext); } @@ -127,7 +128,7 @@ public void convert( @Override public void convert( InputStream jsonStream, - EventHandler eventHandler, + EventHandler eventHandler, JAXBContext jaxbContext) throws IOException, JAXBException { diff --git a/src/main/java/io/openepcis/convert/util/ChannelUtil.java b/core/src/main/java/io/openepcis/converter/util/ChannelUtil.java similarity index 98% rename from src/main/java/io/openepcis/convert/util/ChannelUtil.java rename to core/src/main/java/io/openepcis/converter/util/ChannelUtil.java index 748e4e8..aff4dd3 100644 --- a/src/main/java/io/openepcis/convert/util/ChannelUtil.java +++ b/core/src/main/java/io/openepcis/converter/util/ChannelUtil.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.util; +package io.openepcis.converter.util; import java.io.IOException; import java.io.InputStream; diff --git a/src/main/java/io/openepcis/convert/util/DelegatingXMLStreamWriter.java b/core/src/main/java/io/openepcis/converter/util/DelegatingXMLStreamWriter.java similarity index 99% rename from src/main/java/io/openepcis/convert/util/DelegatingXMLStreamWriter.java rename to core/src/main/java/io/openepcis/converter/util/DelegatingXMLStreamWriter.java index 58986e1..8a1d6d9 100644 --- a/src/main/java/io/openepcis/convert/util/DelegatingXMLStreamWriter.java +++ b/core/src/main/java/io/openepcis/converter/util/DelegatingXMLStreamWriter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.util; +package io.openepcis.converter.util; import javax.xml.namespace.NamespaceContext; import javax.xml.stream.XMLStreamException; diff --git a/src/main/java/io/openepcis/convert/util/IndentingXMLStreamWriter.java b/core/src/main/java/io/openepcis/converter/util/IndentingXMLStreamWriter.java similarity index 99% rename from src/main/java/io/openepcis/convert/util/IndentingXMLStreamWriter.java rename to core/src/main/java/io/openepcis/converter/util/IndentingXMLStreamWriter.java index d87af96..6dfa367 100644 --- a/src/main/java/io/openepcis/convert/util/IndentingXMLStreamWriter.java +++ b/core/src/main/java/io/openepcis/converter/util/IndentingXMLStreamWriter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.util; +package io.openepcis.converter.util; import java.util.Stack; import javax.xml.stream.XMLStreamException; diff --git a/src/main/java/io/openepcis/convert/util/NonEPCISNamespaceXMLStreamWriter.java b/core/src/main/java/io/openepcis/converter/util/NonEPCISNamespaceXMLStreamWriter.java similarity index 97% rename from src/main/java/io/openepcis/convert/util/NonEPCISNamespaceXMLStreamWriter.java rename to core/src/main/java/io/openepcis/converter/util/NonEPCISNamespaceXMLStreamWriter.java index a381a71..f3c769c 100644 --- a/src/main/java/io/openepcis/convert/util/NonEPCISNamespaceXMLStreamWriter.java +++ b/core/src/main/java/io/openepcis/converter/util/NonEPCISNamespaceXMLStreamWriter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.util; +package io.openepcis.converter.util; import io.openepcis.model.epcis.util.EPCISNamespacePrefixMapper; import java.util.Set; diff --git a/src/main/java/io/openepcis/convert/util/TrimmingXMLStreamWriter.java b/core/src/main/java/io/openepcis/converter/util/TrimmingXMLStreamWriter.java similarity index 96% rename from src/main/java/io/openepcis/convert/util/TrimmingXMLStreamWriter.java rename to core/src/main/java/io/openepcis/converter/util/TrimmingXMLStreamWriter.java index 717f91a..b378816 100644 --- a/src/main/java/io/openepcis/convert/util/TrimmingXMLStreamWriter.java +++ b/core/src/main/java/io/openepcis/converter/util/TrimmingXMLStreamWriter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.util; +package io.openepcis.converter.util; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; diff --git a/src/main/java/io/openepcis/convert/util/XMLFormatter.java b/core/src/main/java/io/openepcis/converter/util/XMLFormatter.java similarity index 95% rename from src/main/java/io/openepcis/convert/util/XMLFormatter.java rename to core/src/main/java/io/openepcis/converter/util/XMLFormatter.java index e062499..6e93e8a 100644 --- a/src/main/java/io/openepcis/convert/util/XMLFormatter.java +++ b/core/src/main/java/io/openepcis/converter/util/XMLFormatter.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.util; +package io.openepcis.converter.util; -import io.openepcis.convert.exception.FormatConverterException; +import io.openepcis.converter.exception.FormatConverterException; import java.io.StringReader; import java.io.StringWriter; import javax.xml.XMLConstants; diff --git a/src/main/java/io/openepcis/convert/validator/EPCISEventValidator.java b/core/src/main/java/io/openepcis/converter/validator/EPCISEventValidator.java similarity index 94% rename from src/main/java/io/openepcis/convert/validator/EPCISEventValidator.java rename to core/src/main/java/io/openepcis/converter/validator/EPCISEventValidator.java index 017cf2a..01622b1 100644 --- a/src/main/java/io/openepcis/convert/validator/EPCISEventValidator.java +++ b/core/src/main/java/io/openepcis/converter/validator/EPCISEventValidator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.validator; +package io.openepcis.converter.validator; /** Interface to validate the converted event against the XSD or JSON-Schema */ public interface EPCISEventValidator { diff --git a/src/main/java/io/openepcis/convert/validator/EventValidator.java b/core/src/main/java/io/openepcis/converter/validator/EventValidator.java similarity index 98% rename from src/main/java/io/openepcis/convert/validator/EventValidator.java rename to core/src/main/java/io/openepcis/converter/validator/EventValidator.java index a2d3b3f..f5cf7d1 100644 --- a/src/main/java/io/openepcis/convert/validator/EventValidator.java +++ b/core/src/main/java/io/openepcis/converter/validator/EventValidator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.validator; +package io.openepcis.converter.validator; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -22,7 +22,7 @@ import com.networknt.schema.SpecVersion; import com.networknt.schema.ValidationMessage; import io.openepcis.constants.EPCIS; -import io.openepcis.convert.exception.FormatConverterException; +import io.openepcis.converter.exception.FormatConverterException; import jakarta.ws.rs.ProcessingException; import lombok.extern.slf4j.Slf4j; import org.xml.sax.SAXException; diff --git a/src/main/java/io/openepcis/convert/xml/DefaultXmlVersionTransformer.java b/core/src/main/java/io/openepcis/converter/xml/DefaultXmlVersionTransformer.java similarity index 97% rename from src/main/java/io/openepcis/convert/xml/DefaultXmlVersionTransformer.java rename to core/src/main/java/io/openepcis/converter/xml/DefaultXmlVersionTransformer.java index 383afba..b08a335 100644 --- a/src/main/java/io/openepcis/convert/xml/DefaultXmlVersionTransformer.java +++ b/core/src/main/java/io/openepcis/converter/xml/DefaultXmlVersionTransformer.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.xml; +package io.openepcis.converter.xml; import io.openepcis.constants.EPCISVersion; -import io.openepcis.convert.Conversion; -import io.openepcis.convert.VersionTransformerFeature; -import io.openepcis.convert.exception.FormatConverterException; +import io.openepcis.converter.Conversion; +import io.openepcis.converter.VersionTransformerFeature; +import io.openepcis.converter.exception.FormatConverterException; import javax.xml.XMLConstants; import javax.xml.transform.Transformer; diff --git a/src/main/java/io/openepcis/convert/xml/ProblemResponseBodyMarshaller.java b/core/src/main/java/io/openepcis/converter/xml/ProblemResponseBodyMarshaller.java similarity index 97% rename from src/main/java/io/openepcis/convert/xml/ProblemResponseBodyMarshaller.java rename to core/src/main/java/io/openepcis/converter/xml/ProblemResponseBodyMarshaller.java index 2a12427..a32b519 100644 --- a/src/main/java/io/openepcis/convert/xml/ProblemResponseBodyMarshaller.java +++ b/core/src/main/java/io/openepcis/converter/xml/ProblemResponseBodyMarshaller.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.xml; +package io.openepcis.converter.xml; import io.openepcis.model.rest.ProblemResponseBody; import jakarta.xml.bind.JAXBContext; diff --git a/src/main/java/io/openepcis/convert/xml/XMLEventParser.java b/core/src/main/java/io/openepcis/converter/xml/XMLEventParser.java similarity index 97% rename from src/main/java/io/openepcis/convert/xml/XMLEventParser.java rename to core/src/main/java/io/openepcis/converter/xml/XMLEventParser.java index c9780cb..2011c58 100644 --- a/src/main/java/io/openepcis/convert/xml/XMLEventParser.java +++ b/core/src/main/java/io/openepcis/converter/xml/XMLEventParser.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.xml; +package io.openepcis.converter.xml; import io.openepcis.constants.EPCIS; -import io.openepcis.convert.collector.EPCISEventCollector; -import io.openepcis.convert.collector.EventHandler; -import io.openepcis.convert.exception.FormatConverterException; +import io.openepcis.converter.collector.EPCISEventCollector; +import io.openepcis.converter.collector.EventHandler; +import io.openepcis.converter.exception.FormatConverterException; import io.openepcis.model.epcis.*; import io.openepcis.model.epcis.util.DefaultJsonSchemaNamespaceURIResolver; import jakarta.xml.bind.JAXBContext; @@ -37,7 +37,6 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; -import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; diff --git a/src/main/java/io/openepcis/convert/xml/XMLEventValueTransformer.java b/core/src/main/java/io/openepcis/converter/xml/XMLEventValueTransformer.java similarity index 95% rename from src/main/java/io/openepcis/convert/xml/XMLEventValueTransformer.java rename to core/src/main/java/io/openepcis/converter/xml/XMLEventValueTransformer.java index 33c98bd..4735d99 100644 --- a/src/main/java/io/openepcis/convert/xml/XMLEventValueTransformer.java +++ b/core/src/main/java/io/openepcis/converter/xml/XMLEventValueTransformer.java @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.xml; +package io.openepcis.converter.xml; import io.openepcis.constants.EPCIS; -import io.openepcis.convert.EventsConverter; -import io.openepcis.convert.collector.EPCISEventCollector; -import io.openepcis.convert.collector.EventHandler; -import io.openepcis.convert.exception.FormatConverterException; -import io.openepcis.convert.util.IndentingXMLStreamWriter; -import io.openepcis.convert.util.NonEPCISNamespaceXMLStreamWriter; +import io.openepcis.converter.EventsConverter; +import io.openepcis.converter.collector.EPCISEventCollector; +import io.openepcis.converter.collector.EventHandler; +import io.openepcis.converter.exception.FormatConverterException; +import io.openepcis.converter.util.IndentingXMLStreamWriter; +import io.openepcis.converter.util.NonEPCISNamespaceXMLStreamWriter; import io.openepcis.model.epcis.util.EPCISNamespacePrefixMapper; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; @@ -42,7 +42,6 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; -import java.util.function.Function; public class XMLEventValueTransformer extends XMLEventParser implements EventsConverter { diff --git a/src/main/java/io/openepcis/convert/xml/XmlToJsonConverter.java b/core/src/main/java/io/openepcis/converter/xml/XmlToJsonConverter.java similarity index 97% rename from src/main/java/io/openepcis/convert/xml/XmlToJsonConverter.java rename to core/src/main/java/io/openepcis/converter/xml/XmlToJsonConverter.java index fe20c13..7a96ce4 100644 --- a/src/main/java/io/openepcis/convert/xml/XmlToJsonConverter.java +++ b/core/src/main/java/io/openepcis/converter/xml/XmlToJsonConverter.java @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.xml; +package io.openepcis.converter.xml; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import io.openepcis.constants.EPCIS; -import io.openepcis.convert.EventsConverter; -import io.openepcis.convert.collector.EPCISEventCollector; -import io.openepcis.convert.collector.EventHandler; -import io.openepcis.convert.exception.FormatConverterException; +import io.openepcis.converter.EventsConverter; +import io.openepcis.converter.collector.EPCISEventCollector; +import io.openepcis.converter.collector.EventHandler; +import io.openepcis.converter.exception.FormatConverterException; import io.openepcis.model.epcis.util.EPCISNamespacePrefixMapper; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; diff --git a/src/main/java/io/openepcis/convert/xml/XmlVersionTransformer.java b/core/src/main/java/io/openepcis/converter/xml/XmlVersionTransformer.java similarity index 95% rename from src/main/java/io/openepcis/convert/xml/XmlVersionTransformer.java rename to core/src/main/java/io/openepcis/converter/xml/XmlVersionTransformer.java index fd2ed71..52de682 100644 --- a/src/main/java/io/openepcis/convert/xml/XmlVersionTransformer.java +++ b/core/src/main/java/io/openepcis/converter/xml/XmlVersionTransformer.java @@ -13,10 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.xml; +package io.openepcis.converter.xml; -import io.openepcis.constants.EPCISVersion; -import io.openepcis.convert.Conversion; +import io.openepcis.converter.Conversion; import java.io.IOException; import java.io.InputStream; diff --git a/src/main/java/io/openepcis/convert/xml/XmlVersionTransformerFactory.java b/core/src/main/java/io/openepcis/converter/xml/XmlVersionTransformerFactory.java similarity index 95% rename from src/main/java/io/openepcis/convert/xml/XmlVersionTransformerFactory.java rename to core/src/main/java/io/openepcis/converter/xml/XmlVersionTransformerFactory.java index ede8331..4de081e 100644 --- a/src/main/java/io/openepcis/convert/xml/XmlVersionTransformerFactory.java +++ b/core/src/main/java/io/openepcis/converter/xml/XmlVersionTransformerFactory.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.openepcis.convert.xml; +package io.openepcis.converter.xml; import java.util.concurrent.ExecutorService; diff --git a/src/main/resources/eventSchemas/AggregationEventSchema.json b/core/src/main/resources/eventSchemas/AggregationEventSchema.json similarity index 100% rename from src/main/resources/eventSchemas/AggregationEventSchema.json rename to core/src/main/resources/eventSchemas/AggregationEventSchema.json diff --git a/src/main/resources/eventSchemas/AssociationEventSchema.json b/core/src/main/resources/eventSchemas/AssociationEventSchema.json similarity index 100% rename from src/main/resources/eventSchemas/AssociationEventSchema.json rename to core/src/main/resources/eventSchemas/AssociationEventSchema.json diff --git a/src/main/resources/eventSchemas/EPCISEventXSD.xsd b/core/src/main/resources/eventSchemas/EPCISEventXSD.xsd similarity index 100% rename from src/main/resources/eventSchemas/EPCISEventXSD.xsd rename to core/src/main/resources/eventSchemas/EPCISEventXSD.xsd diff --git a/src/main/resources/eventSchemas/ObjectEventSchema.json b/core/src/main/resources/eventSchemas/ObjectEventSchema.json similarity index 100% rename from src/main/resources/eventSchemas/ObjectEventSchema.json rename to core/src/main/resources/eventSchemas/ObjectEventSchema.json diff --git a/src/main/resources/eventSchemas/TransactionEventSchema.json b/core/src/main/resources/eventSchemas/TransactionEventSchema.json similarity index 100% rename from src/main/resources/eventSchemas/TransactionEventSchema.json rename to core/src/main/resources/eventSchemas/TransactionEventSchema.json diff --git a/src/main/resources/eventSchemas/TransformationEventSchema.json b/core/src/main/resources/eventSchemas/TransformationEventSchema.json similarity index 100% rename from src/main/resources/eventSchemas/TransformationEventSchema.json rename to core/src/main/resources/eventSchemas/TransformationEventSchema.json diff --git a/src/main/resources/xalan-conversion/1.2/XML/AggregationEvent.xml b/core/src/main/resources/xalan-conversion/1.2/XML/AggregationEvent.xml similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XML/AggregationEvent.xml rename to core/src/main/resources/xalan-conversion/1.2/XML/AggregationEvent.xml diff --git a/src/main/resources/xalan-conversion/1.2/XML/AssociationEvent.xml b/core/src/main/resources/xalan-conversion/1.2/XML/AssociationEvent.xml similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XML/AssociationEvent.xml rename to core/src/main/resources/xalan-conversion/1.2/XML/AssociationEvent.xml diff --git a/src/main/resources/xalan-conversion/1.2/XML/ObjectEvent.xml b/core/src/main/resources/xalan-conversion/1.2/XML/ObjectEvent.xml similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XML/ObjectEvent.xml rename to core/src/main/resources/xalan-conversion/1.2/XML/ObjectEvent.xml diff --git a/src/main/resources/xalan-conversion/1.2/XML/TransactionEvent.xml b/core/src/main/resources/xalan-conversion/1.2/XML/TransactionEvent.xml similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XML/TransactionEvent.xml rename to core/src/main/resources/xalan-conversion/1.2/XML/TransactionEvent.xml diff --git a/src/main/resources/xalan-conversion/1.2/XML/TransformationEvent.xml b/core/src/main/resources/xalan-conversion/1.2/XML/TransformationEvent.xml similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XML/TransformationEvent.xml rename to core/src/main/resources/xalan-conversion/1.2/XML/TransformationEvent.xml diff --git a/src/main/resources/xalan-conversion/1.2/XSD/BasicTypes.xsd b/core/src/main/resources/xalan-conversion/1.2/XSD/BasicTypes.xsd similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XSD/BasicTypes.xsd rename to core/src/main/resources/xalan-conversion/1.2/XSD/BasicTypes.xsd diff --git a/src/main/resources/xalan-conversion/1.2/XSD/BusinessScope.xsd b/core/src/main/resources/xalan-conversion/1.2/XSD/BusinessScope.xsd similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XSD/BusinessScope.xsd rename to core/src/main/resources/xalan-conversion/1.2/XSD/BusinessScope.xsd diff --git a/src/main/resources/xalan-conversion/1.2/XSD/DocumentIdentification.xsd b/core/src/main/resources/xalan-conversion/1.2/XSD/DocumentIdentification.xsd similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XSD/DocumentIdentification.xsd rename to core/src/main/resources/xalan-conversion/1.2/XSD/DocumentIdentification.xsd diff --git a/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-1_2.xsd b/core/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-1_2.xsd similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-1_2.xsd rename to core/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-1_2.xsd diff --git a/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-masterdata-1_2.xsd b/core/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-masterdata-1_2.xsd similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-masterdata-1_2.xsd rename to core/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-masterdata-1_2.xsd diff --git a/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-query-1_2.xsd b/core/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-query-1_2.xsd similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-query-1_2.xsd rename to core/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal-epcis-query-1_2.xsd diff --git a/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal.xsd b/core/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal.xsd similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XSD/EPCglobal.xsd rename to core/src/main/resources/xalan-conversion/1.2/XSD/EPCglobal.xsd diff --git a/src/main/resources/xalan-conversion/1.2/XSD/Manifest.xsd b/core/src/main/resources/xalan-conversion/1.2/XSD/Manifest.xsd similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XSD/Manifest.xsd rename to core/src/main/resources/xalan-conversion/1.2/XSD/Manifest.xsd diff --git a/src/main/resources/xalan-conversion/1.2/XSD/Partner.xsd b/core/src/main/resources/xalan-conversion/1.2/XSD/Partner.xsd similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XSD/Partner.xsd rename to core/src/main/resources/xalan-conversion/1.2/XSD/Partner.xsd diff --git a/src/main/resources/xalan-conversion/1.2/XSD/StandardBusinessDocumentHeader.xsd b/core/src/main/resources/xalan-conversion/1.2/XSD/StandardBusinessDocumentHeader.xsd similarity index 100% rename from src/main/resources/xalan-conversion/1.2/XSD/StandardBusinessDocumentHeader.xsd rename to core/src/main/resources/xalan-conversion/1.2/XSD/StandardBusinessDocumentHeader.xsd diff --git a/src/main/resources/xalan-conversion/Makefile b/core/src/main/resources/xalan-conversion/Makefile similarity index 100% rename from src/main/resources/xalan-conversion/Makefile rename to core/src/main/resources/xalan-conversion/Makefile diff --git a/src/main/resources/xalan-conversion/convert-1.2-to-2.0.xsl b/core/src/main/resources/xalan-conversion/convert-1.2-to-2.0.xsl similarity index 100% rename from src/main/resources/xalan-conversion/convert-1.2-to-2.0.xsl rename to core/src/main/resources/xalan-conversion/convert-1.2-to-2.0.xsl diff --git a/src/main/resources/xalan-conversion/convert-2.0-to-1.2.xsl b/core/src/main/resources/xalan-conversion/convert-2.0-to-1.2.xsl similarity index 100% rename from src/main/resources/xalan-conversion/convert-2.0-to-1.2.xsl rename to core/src/main/resources/xalan-conversion/convert-2.0-to-1.2.xsl diff --git a/src/test/java/com/io/openepcis/convert/JsonToXmlTest.java b/core/src/test/java/com/io/openepcis/convert/JsonToXmlTest.java similarity index 96% rename from src/test/java/com/io/openepcis/convert/JsonToXmlTest.java rename to core/src/test/java/com/io/openepcis/convert/JsonToXmlTest.java index 961ad84..6d2800e 100644 --- a/src/test/java/com/io/openepcis/convert/JsonToXmlTest.java +++ b/core/src/test/java/com/io/openepcis/convert/JsonToXmlTest.java @@ -17,13 +17,13 @@ import io.openepcis.constants.EPCISFormat; import io.openepcis.constants.EPCISVersion; -import io.openepcis.convert.Conversion; -import io.openepcis.convert.VersionTransformer; -import io.openepcis.convert.collector.EventHandler; -import io.openepcis.convert.collector.XmlEPCISEventCollector; -import io.openepcis.convert.json.JsonToXmlConverter; -import io.openepcis.convert.util.XMLFormatter; -import io.openepcis.convert.validator.EventValidator; +import io.openepcis.converter.Conversion; +import io.openepcis.converter.VersionTransformer; +import io.openepcis.converter.collector.EventHandler; +import io.openepcis.converter.collector.XmlEPCISEventCollector; +import io.openepcis.converter.json.JsonToXmlConverter; +import io.openepcis.converter.util.XMLFormatter; +import io.openepcis.converter.validator.EventValidator; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/io/openepcis/convert/XmlToJsonTest.java b/core/src/test/java/com/io/openepcis/convert/XmlToJsonTest.java similarity index 97% rename from src/test/java/com/io/openepcis/convert/XmlToJsonTest.java rename to core/src/test/java/com/io/openepcis/convert/XmlToJsonTest.java index 37a536f..100de5b 100644 --- a/src/test/java/com/io/openepcis/convert/XmlToJsonTest.java +++ b/core/src/test/java/com/io/openepcis/convert/XmlToJsonTest.java @@ -17,12 +17,12 @@ import io.openepcis.constants.EPCISFormat; import io.openepcis.constants.EPCISVersion; -import io.openepcis.convert.VersionTransformer; -import io.openepcis.convert.collector.EventHandler; -import io.openepcis.convert.collector.JsonEPCISEventCollector; -import io.openepcis.convert.exception.FormatConverterException; -import io.openepcis.convert.validator.EventValidator; -import io.openepcis.convert.xml.XmlToJsonConverter; +import io.openepcis.converter.VersionTransformer; +import io.openepcis.converter.collector.EventHandler; +import io.openepcis.converter.collector.JsonEPCISEventCollector; +import io.openepcis.converter.exception.FormatConverterException; +import io.openepcis.converter.validator.EventValidator; +import io.openepcis.converter.xml.XmlToJsonConverter; import jakarta.xml.bind.JAXBException; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/src/test/java/com/io/openepcis/version/Transform12To20Test.java b/core/src/test/java/com/io/openepcis/version/Transform12To20Test.java similarity index 97% rename from src/test/java/com/io/openepcis/version/Transform12To20Test.java rename to core/src/test/java/com/io/openepcis/version/Transform12To20Test.java index c0500b4..d71a580 100644 --- a/src/test/java/com/io/openepcis/version/Transform12To20Test.java +++ b/core/src/test/java/com/io/openepcis/version/Transform12To20Test.java @@ -17,8 +17,8 @@ import io.openepcis.constants.EPCISFormat; import io.openepcis.constants.EPCISVersion; -import io.openepcis.convert.Conversion; -import io.openepcis.convert.VersionTransformer; +import io.openepcis.converter.Conversion; +import io.openepcis.converter.VersionTransformer; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; diff --git a/src/test/java/com/io/openepcis/version/Transform20To12Test.java b/core/src/test/java/com/io/openepcis/version/Transform20To12Test.java similarity index 96% rename from src/test/java/com/io/openepcis/version/Transform20To12Test.java rename to core/src/test/java/com/io/openepcis/version/Transform20To12Test.java index f6e1bd7..eb1b5fb 100644 --- a/src/test/java/com/io/openepcis/version/Transform20To12Test.java +++ b/core/src/test/java/com/io/openepcis/version/Transform20To12Test.java @@ -17,11 +17,10 @@ import io.openepcis.constants.EPCISFormat; import io.openepcis.constants.EPCISVersion; -import io.openepcis.convert.Conversion; -import io.openepcis.convert.VersionTransformer; +import io.openepcis.converter.Conversion; +import io.openepcis.converter.VersionTransformer; import jakarta.xml.bind.JAXBException; import org.apache.commons.io.IOUtils; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.io.IOException; diff --git a/src/test/java/com/io/openepcis/version/VersionDetectorTest.java b/core/src/test/java/com/io/openepcis/version/VersionDetectorTest.java similarity index 97% rename from src/test/java/com/io/openepcis/version/VersionDetectorTest.java rename to core/src/test/java/com/io/openepcis/version/VersionDetectorTest.java index 73ca609..768a829 100644 --- a/src/test/java/com/io/openepcis/version/VersionDetectorTest.java +++ b/core/src/test/java/com/io/openepcis/version/VersionDetectorTest.java @@ -16,7 +16,7 @@ package com.io.openepcis.version; import io.openepcis.constants.EPCISVersion; -import io.openepcis.convert.VersionTransformer; +import io.openepcis.converter.VersionTransformer; import io.openepcis.resources.util.Commons; import jakarta.xml.bind.JAXBException; import org.junit.jupiter.api.Assertions; diff --git a/pom.xml b/pom.xml index f2d818b..bdfb0a3 100644 --- a/pom.xml +++ b/pom.xml @@ -26,8 +26,9 @@ 1.0.0-SNAPSHOT - openepcis-document-converter - openepcis-document-converter + openepcis-document-converter-parent + openepcis-document-converter-parent + pom Project to convert EPCIS events in XML format to JSON/JSON-LD and vice-versa. Also, supports the conversion of EPCIS 1.2 XML document to 2.0 XML document and vice versa. https://github.com/openepcis/openepcis-document-converter @@ -60,148 +61,78 @@ https://github.com/openepcis/openepcis-document-converter/tree/main - - - io.openepcis - openepcis-model-rest - ${project.parent.version} - - - io.openepcis - openepcis-model-epcis - ${project.parent.version} - - - io.openepcis - openepcis-document-validation-service - ${project.parent.version} - - - io.smallrye.reactive - mutiny - - - jakarta.enterprise - jakarta.enterprise.cdi-api - provided - - - jakarta.ws.rs - jakarta.ws.rs-api - provided - - - - org.projectlombok - lombok - provided - - - - - jakarta.xml.bind - jakarta.xml.bind-api - - - org.eclipse.persistence - org.eclipse.persistence.moxy - - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-annotations - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - - - commons-io - commons-io - - - - - io.openepcis - openepcis-epcis-constants - ${project.parent.version} - - - + + core + quarkus/runtime + quarkus/deployment + service/converter-service-restassured + service/converter-service-rest + service/converter-service-servlet + + + + + + io.openepcis.quarkus + quarkus-openepcis-model + ${project.parent.version} + + + io.openepcis.quarkus + quarkus-openepcis-model-deployment + ${project.parent.version} + + + io.openepcis.quarkus + quarkus-document-converter + ${project.parent.version} + + + io.openepcis + openepcis-document-converter + ${project.parent.version} + + + io.openepcis + converter-service-restassured + ${project.parent.version} + + + io.openepcis + converter-service-rest + ${project.parent.version} + + + io.openepcis + converter-service-servlet + ${project.parent.version} + + + io.openepcis + openepcis-document-converter-sax + ${project.parent.version} + + + + + io.openepcis + openepcis-epc-digitallink-translator + ${project.parent.version} + + + + + io.openepcis + openepcis-repository-common + ${project.parent.version} + io.openepcis openepcis-test-resources ${project.parent.version} - - - org.junit.jupiter - junit-jupiter - test - - - org.slf4j - slf4j-simple - test - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - ${java.version} - ${java.version} - ${project.build.sourceEncoding} - - - - maven-surefire-plugin - 3.1.2 - - - - - - - - coverage - - false - - - - - org.jacoco - jacoco-maven-plugin - - - report - - report - - verify - - - - - - - + diff --git a/quarkus/deployment/pom.xml b/quarkus/deployment/pom.xml new file mode 100644 index 0000000..19a7ffe --- /dev/null +++ b/quarkus/deployment/pom.xml @@ -0,0 +1,122 @@ + + + + 4.0.0 + + io.openepcis + openepcis-document-converter-parent + 1.0.0-SNAPSHOT + ../../pom.xml + + + io.openepcis.quarkus + quarkus-document-converter-deployment + quarkus-document-converter-deployment + Quarkus OpenEPCIS Document Converter Deployment + https://github.com/openepcis/openepcis-document-converter + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + + Sven Boeckelmann + sven.boeckelmann@benelog.com + benelog GmbH & Co. KG + https://www.benelog.com + + + + + scm:git:git://github.com/openepcis/openepcis-document-converter.git + scm:git:ssh://github.com:openepcis/openepcis-document-converter.git + https://github.com/openepcis/openepcis-document-converter/tree/main + + + + + io.openepcis.quarkus + quarkus-document-converter + + + io.openepcis.quarkus + quarkus-openepcis-model-deployment + + + io.quarkus + quarkus-arc-deployment + + + io.quarkus + quarkus-jackson-deployment + + + io.quarkus + quarkus-smallrye-health-deployment + + + io.quarkus + quarkus-smallrye-health-spi + + + io.quarkus + quarkus-devservices-deployment + + + + + io.quarkus + quarkus-junit5-internal + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${quarkus.platform.version} + + + + + + maven-surefire-plugin + + + org.jboss.logmanager.LogManager + + + + + + + diff --git a/quarkus/deployment/src/main/java/io/openepcis/quarkus/deployment/convert/OpenEPCISConverterProcessor.java b/quarkus/deployment/src/main/java/io/openepcis/quarkus/deployment/convert/OpenEPCISConverterProcessor.java new file mode 100644 index 0000000..2367453 --- /dev/null +++ b/quarkus/deployment/src/main/java/io/openepcis/quarkus/deployment/convert/OpenEPCISConverterProcessor.java @@ -0,0 +1,47 @@ +/* + * Copyright 2022-2024 benelog GmbH & Co. KG + * + * 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 io.openepcis.quarkus.deployment.convert; + +import io.openepcis.quarkus.convert.OpenEPCISConverterHealthCheck; +import io.openepcis.quarkus.convert.VersionTransformerProducer; +import io.openepcis.quarkus.deployment.model.OpenEPCISBuildTimeConfig; +import io.quarkus.arc.deployment.AdditionalBeanBuildItem; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem; + +public class OpenEPCISConverterProcessor { + + private static final String FEATURE = "opensearch-document-converter"; + + + @BuildStep + FeatureBuildItem feature() { + return new FeatureBuildItem(FEATURE); + } + + @BuildStep() + AdditionalBeanBuildItem buildOpenEPCISJAXBContext() { + return AdditionalBeanBuildItem.unremovableOf(VersionTransformerProducer.class); + } + + @BuildStep + HealthBuildItem addHealthCheck(OpenEPCISBuildTimeConfig buildTimeConfig) { + return new HealthBuildItem(OpenEPCISConverterHealthCheck.class.getName(), + buildTimeConfig.healthEnabled); + } + +} diff --git a/quarkus/deployment/src/main/resources/META-INF/quarkus-extension.yaml b/quarkus/deployment/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 0000000..8797c47 --- /dev/null +++ b/quarkus/deployment/src/main/resources/META-INF/quarkus-extension.yaml @@ -0,0 +1,11 @@ +--- +artifact: ${project.groupId}:${project.artifactId}:${project.version} +name: "OpenEPCIS EPCIS Model" +metadata: + keywords: + - "epcis" + - "xml" + - "json" + categories: + - "data" + status: "stable" \ No newline at end of file diff --git a/quarkus/deployment/src/test/java/io/openepcis/quarkus/deployment/convert/test/VersionTransformerTest.java b/quarkus/deployment/src/test/java/io/openepcis/quarkus/deployment/convert/test/VersionTransformerTest.java new file mode 100644 index 0000000..3aa555b --- /dev/null +++ b/quarkus/deployment/src/test/java/io/openepcis/quarkus/deployment/convert/test/VersionTransformerTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2022-2024 benelog GmbH & Co. KG + * + * 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 io.openepcis.quarkus.deployment.convert.test; + +import io.openepcis.converter.VersionTransformer; +import io.openepcis.quarkus.convert.VersionTransformerProducer; +import io.quarkus.test.QuarkusUnitTest; +import jakarta.inject.Inject; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class VersionTransformerTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest() + .setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class)); + + @Inject + VersionTransformerProducer versionTransformerProducer; + + @Inject + VersionTransformer versionTransformer; + + + @Test + void testVersionTransformerInjection() throws Exception { + assertNotNull(versionTransformerProducer); + assertNotNull(versionTransformer); + assertNotNull(versionTransformer.getXmlToJsonConverter()); + assertNotNull(versionTransformer.getJsonToXmlConverter()); + assertNotNull(versionTransformer.getXmlVersionTransformer()); + } + +} diff --git a/quarkus/runtime/pom.xml b/quarkus/runtime/pom.xml new file mode 100644 index 0000000..b42dc89 --- /dev/null +++ b/quarkus/runtime/pom.xml @@ -0,0 +1,112 @@ + + + + 4.0.0 + + io.openepcis + openepcis-document-converter-parent + 1.0.0-SNAPSHOT + ../../pom.xml + + + io.openepcis.quarkus + quarkus-document-converter + quarkus-document-converter + Quarkus OpenEPCIS Document Converter + https://github.com/openepcis/openepcis-document-converter + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + + Sven Boeckelmann + sven.boeckelmann@benelog.com + benelog GmbH & Co. KG + https://www.benelog.com + + + + + scm:git:git://github.com/openepcis/openepcis-document-converter.git + scm:git:ssh://github.com:openepcis/openepcis-document-converter.git + https://github.com/openepcis/openepcis-document-converter/tree/main + + + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-smallrye-health + + + io.openepcis.quarkus + quarkus-openepcis-model + + + io.openepcis + openepcis-document-converter + + + + + + + + io.quarkus + quarkus-extension-maven-plugin + ${quarkus.platform.version} + + + compile + + extension-descriptor + + + ${project.groupId}:${project.artifactId}-deployment:${project.version} + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${quarkus.platform.version} + + + + + + + + + diff --git a/quarkus/runtime/src/main/java/io/openepcis/quarkus/convert/OpenEPCISConverterHealthCheck.java b/quarkus/runtime/src/main/java/io/openepcis/quarkus/convert/OpenEPCISConverterHealthCheck.java new file mode 100644 index 0000000..13cf10a --- /dev/null +++ b/quarkus/runtime/src/main/java/io/openepcis/quarkus/convert/OpenEPCISConverterHealthCheck.java @@ -0,0 +1,41 @@ +/* + * Copyright 2022-2024 benelog GmbH & Co. KG + * + * 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 io.openepcis.quarkus.convert; + +import io.openepcis.converter.VersionTransformer; +import jakarta.enterprise.context.ApplicationScoped; +import org.eclipse.microprofile.health.HealthCheck; +import org.eclipse.microprofile.health.HealthCheckResponse; +import org.eclipse.microprofile.health.HealthCheckResponseBuilder; +import org.eclipse.microprofile.health.Readiness; + +@Readiness +@ApplicationScoped +public class OpenEPCISConverterHealthCheck implements HealthCheck { + + private final VersionTransformer versionTransformer; + + public OpenEPCISConverterHealthCheck(final VersionTransformer versionTransformer) { + this.versionTransformer = versionTransformer; + } + + @Override + public HealthCheckResponse call() { + HealthCheckResponseBuilder builder = HealthCheckResponse.named("OpenEPCIS EPCIS Model health check").up(); + builder.up().withData("xmlToJsonConverter", versionTransformer.getXmlToJsonConverter().getClass().getName() ); + return builder.build(); + } +} diff --git a/quarkus/runtime/src/main/java/io/openepcis/quarkus/convert/VersionTransformerProducer.java b/quarkus/runtime/src/main/java/io/openepcis/quarkus/convert/VersionTransformerProducer.java new file mode 100644 index 0000000..2b3c741 --- /dev/null +++ b/quarkus/runtime/src/main/java/io/openepcis/quarkus/convert/VersionTransformerProducer.java @@ -0,0 +1,40 @@ +/* + * Copyright 2022-2024 benelog GmbH & Co. KG + * + * 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 io.openepcis.quarkus.convert; + +import io.openepcis.converter.VersionTransformer; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import jakarta.xml.bind.JAXBContext; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.microprofile.context.ManagedExecutor; + +@ApplicationScoped +@Slf4j +public class VersionTransformerProducer { + @Inject + ManagedExecutor managedExecutor; + + @Inject + JAXBContext jaxbContext; + + @Produces + public VersionTransformer createVersionTransformer() throws Exception { + return new VersionTransformer(managedExecutor, jaxbContext); + } + +} diff --git a/quarkus/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/quarkus/runtime/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 0000000..8e654ef --- /dev/null +++ b/quarkus/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -0,0 +1,11 @@ +--- +artifact: ${project.groupId}:${project.artifactId}:${project.version} +name: "OpenEPCIS Document Convert" +metadata: + keywords: + - "epcis" + - "xml" + - "json" + categories: + - "data" + status: "stable" \ No newline at end of file diff --git a/service/converter-service-rest/pom.xml b/service/converter-service-rest/pom.xml new file mode 100644 index 0000000..c980a2d --- /dev/null +++ b/service/converter-service-rest/pom.xml @@ -0,0 +1,183 @@ + + + 4.0.0 + + io.openepcis + openepcis-document-converter-parent + 1.0.0-SNAPSHOT + ../../pom.xml + + + converter-service-rest + converter-service-rest + REST Resources to convert the EPCIS 2.0 documents and identifiers from one standard format to another + + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + + io.quarkus + quarkus-extension-maven-plugin + + + io.quarkus:quarkus-bootstrap-core + io.quarkus:quarkus-development-mode-spi + org.jboss.logmanager:jboss-logmanager-embedded + org.jboss.logging:jboss-logging + jakarta.xml.bind:jakarta.xml.bind-api + + + + + maven-compiler-plugin + + + -parameters + + + + + + + + + coverage + + + + org.jacoco + jacoco-maven-plugin + + + prepare-agent + + prepare-agent + + + + report + + report + + + + report-aggregate + verify + + report-aggregate + + + + + + + + + + + + + io.openepcis + openepcis-document-converter + + + + + + io.openepcis + openepcis-document-converter + + + + io.openepcis + openepcis-document-converter-sax + + + + + io.openepcis + openepcis-epc-digitallink-translator + + + + + io.openepcis + openepcis-repository-common + + + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-resteasy-reactive-jackson + + + io.quarkus + quarkus-smallrye-openapi + + + + + io.openepcis + openepcis-test-resources + test + + + io.openepcis + converter-service-restassured + test + + + + + io.openepcis.quarkus + quarkus-document-converter + test + + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + org.junit.jupiter + junit-jupiter + ${junit.version} + test + + + javax.inject + javax.inject + 1 + test + + + + diff --git a/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/exception/ExceptionMapper.java b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/exception/ExceptionMapper.java new file mode 100644 index 0000000..c3024ca --- /dev/null +++ b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/exception/ExceptionMapper.java @@ -0,0 +1,19 @@ +package io.openepcis.epc.converter.exception; + +import io.openepcis.converter.exception.FormatConverterException; +import io.openepcis.model.rest.ProblemResponseBody; +import lombok.extern.slf4j.Slf4j; +import org.jboss.resteasy.reactive.RestResponse; +import org.jboss.resteasy.reactive.server.ServerExceptionMapper; + +@Slf4j +public class ExceptionMapper { + + @ServerExceptionMapper + public final RestResponse mapException(final FormatConverterException exception) { + log.error(exception.getMessage(), exception); + ProblemResponseBody responseBody = ProblemResponseBody.fromException(exception, RestResponse.Status.BAD_REQUEST); + return RestResponse.status(RestResponse.Status.BAD_REQUEST, responseBody); + } + +} \ No newline at end of file diff --git a/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/resource/DocumentConverterResource.java b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/resource/DocumentConverterResource.java new file mode 100644 index 0000000..7b06bf6 --- /dev/null +++ b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/resource/DocumentConverterResource.java @@ -0,0 +1,486 @@ +package io.openepcis.epc.converter.resource; + +import io.openepcis.constants.EPCISFormat; +import io.openepcis.constants.EPCISVersion; +import io.openepcis.converter.Conversion; +import io.openepcis.converter.VersionTransformer; +import io.openepcis.converter.exception.FormatConverterException; +import io.openepcis.converter.util.ChannelUtil; +import io.openepcis.converter.common.GS1FormatSupport; +import io.openepcis.epc.converter.util.GS1FormatProvider; +import io.openepcis.model.epcis.EPCISDocument; +import io.openepcis.model.epcis.EPCISEvent; +import io.openepcis.model.epcis.exception.UnsupportedMediaTypeException; +import io.openepcis.model.rest.ProblemResponseBody; +import io.smallrye.common.annotation.Blocking; +import io.smallrye.mutiny.Uni; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.*; +import org.eclipse.microprofile.context.ManagedExecutor; +import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.ParameterIn; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.ExampleObject; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; +import org.jboss.resteasy.reactive.RestHeader; +import org.jboss.resteasy.reactive.RestMulti; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +@Path("/api") +@Tag( + name = "Format Converter", + description = "Convert EPCIS document or single event from XML to JSON/JSON-LD and vice versa.") +public class DocumentConverterResource { + + @Inject + VersionTransformer versionTransformer; + + @Inject + GS1FormatProvider gs1FormatProvider; + + @Inject + ManagedExecutor managedExecutor; + + // Method to convert the input XML EPCIS events into JSON EPCIS events + @Operation( + summary = "Convert EPCIS document or single event from XML version 1.2 or 2.0 or JSON/JSON-LD 2.0 to EPCIS 2.0 JSON/JSON-LD.") + @Path("/convert/json/2.0") + @POST + @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/ld+json"}) + @Produces(MediaType.APPLICATION_JSON) + @RequestBody( + description = "Convert EPCIS document or single event from XML version 1.2 or 2.0 or JSON/JSON-LD 2.0 to EPCIS 2.0 JSON/JSON-LD.", + content = { + @Content( + mediaType = MediaType.APPLICATION_XML, + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 1.2 XML document", + ref = "xml1.2Document", + description = "Example EPCIS 1.2 document"), + @ExampleObject( + name = "EPCIS 2.0 XML document", + ref = "xmlDocument", + description = "Example EPCIS 2.0 document in XML format.") + }), + @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 2.0 JSON document", + ref = "jsonDocument", + description = "Example EPCIS 2.0 document in JSON format.") + }), + @Content( + mediaType = "application/ld+json", + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 2.0 JSON document", + ref = "jsonDocument", + description = "Example EPCIS 2.0 document in JSON format.") + }) + } + ) + @APIResponses( + value = { + @APIResponse( + responseCode = "200", + description = "OK: Converted to EPCIS 2.0 JSON/JSON-LD successfully.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 2.0 JSON document", + ref = "jsonDocument", + description = "Example EPCIS 2.0 document in JSON format.") + }) + ), + @APIResponse( + responseCode = "400", + description = "Bad Request: Input EPCIS document or single event contains missing/invalid information.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "401", + description = "Unauthorized: Unable to convert document or single event as request contains missing/invalid authorization.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "404", + description = "Not Found: Unable to convert document or single event as the requested resource not found.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "406", + description = "Not Acceptable: Unable to convert document or single event as server cannot find content confirming request.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "500", + description = "Internal Server Error: Unable to convert document or single event as server encountered problem.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))) + }) + @Blocking + public Uni convertToJson_2_0( + final InputStream inputDocument, + @Parameter( + name = "GS1-EPC-Format", + description = ParameterDescription.GS1_EPC_FORMAT, + schema = @Schema(type = SchemaType.STRING, + enumeration = {"No_Preference", "Always_GS1_Digital_Link", "Always_EPC_URN", "Never_Translates"} + ), + in = ParameterIn.HEADER) + @RestHeader(value = "GS1-EPC-Format") + String epcFormat, + @Context HttpHeaders httpHeaders) + throws FormatConverterException, IOException { + + final MediaType mediaType = httpHeaders.getMediaType(); + + if (mediaType == null || !GS1FormatSupport.isValidMediaType(mediaType)) { + throw new UnsupportedMediaTypeException("Unsupported media type: " + mediaType); + } + + return Uni.createFrom().item(versionTransformer + .mapWith(GS1FormatSupport.createMapper(gs1FormatProvider.getFormatPreference())) + .convert( + inputDocument, + Conversion.builder() + .fromMediaType(GS1FormatSupport.getEPCISFormat(mediaType)) + .toMediaType(EPCISFormat.JSON_LD) + .toVersion(EPCISVersion.VERSION_2_0_0) + .build())); + } + + // Method to convert the input JSON 2.0 EPCIS events into XML 2.0 EPCIS events + @Operation( + summary = + "Convert EPCIS document or single event from XML version 1.2 or 2.0 or JSON/JSON-LD 2.0 to EPCIS 2.0 XML.") + @Path("/convert/xml/2.0") + @POST + @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/ld+json"}) + @Produces({MediaType.APPLICATION_XML}) + @RequestBody( + description = + "Convert EPCIS document or single event from XML version 1.2 or 2.0 or JSON/JSON-LD 2.0 to EPCIS 2.0 XML.", + content = { + @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 2.0 JSON document", + ref = "jsonDocument", + description = "Example EPCIS 2.0 document in JSON format.") + }), + @Content( + mediaType = MediaType.APPLICATION_XML, + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 1.2 XML document", + ref = "xml1.2Document", + description = "Example EPCIS 1.2 document"), + @ExampleObject( + name = "EPCIS 2.0 XML document", + ref = "xmlDocument", + description = "Example EPCIS 2.0 document in XML format.") + }), + @Content( + mediaType = "application/ld+json", + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 2.0 JSON document", + ref = "jsonDocument", + description = "Example EPCIS 2.0 document in JSON format.") + }) + }) + @APIResponses( + value = { + @APIResponse( + responseCode = "200", + description = + "OK: Converted to EPCIS 2.0 XML successfully.", + content = + @Content( + schema = @Schema(implementation = EPCISDocument.class), + examples = @ExampleObject( + name = "EPCIS 2.0 XML document", + ref = "xmlDocument", + description = "Example EPCIS 2.0 document in XML format.") + )), + @APIResponse( + responseCode = "400", + description = + "Bad Request: Input EPCIS document or single event contains missing/invalid information.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "401", + description = + "Unauthorized: Unable to convert document or single event as request contains missing/invalid authorization.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "404", + description = + "Not Found: Unable to convert document or single event as the requested resource not found.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "406", + description = + "Not Acceptable: Unable to convert EPCIS document or single event as server cannot find content confirming request.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "500", + description = + "Internal Server Error: Unable to convert document or single event as server encountered problem.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))) + }) + public RestMulti convertToXml_2_0( + final InputStream jsonEvents, + @Parameter( + name = "GS1-EPC-Format", + description = ParameterDescription.GS1_EPC_FORMAT, + schema = @Schema(type = SchemaType.STRING, + enumeration = {"No_Preference", "Always_GS1_Digital_Link", "Always_EPC_URN", "Never_Translates"} + ), + in = ParameterIn.HEADER) + @RestHeader(value = "GS1-EPC-Format") + String epcFormat, + @Parameter( + name = "GS1-CBV-XML-Format", + description = ParameterDescription.GS1_CBV_XML_FORMAT, + schema = @Schema(type = SchemaType.STRING, + enumeration = {"No_Preference", "Always_Web_URI", "Always_URN", "Never_Translates"} + ), + in = ParameterIn.HEADER) + @RestHeader(value = "GS1-CBV-XML-Format") + String cbvFormat, + @Context HttpHeaders httpHeaders) + throws FormatConverterException, IOException { + + final MediaType mediaType = httpHeaders.getMediaType(); + + if (mediaType == null || !GS1FormatSupport.isValidMediaType(mediaType)) { + throw new UnsupportedMediaTypeException("Unsupported media type: " + mediaType); + } + + + return RestMulti.fromMultiData( + ChannelUtil.toMulti(versionTransformer + .mapWith(GS1FormatSupport.createMapper(gs1FormatProvider.getFormatPreference())) + .convert( + new BufferedInputStream(jsonEvents, 8192), + Conversion.builder() + .fromMediaType(GS1FormatSupport.getEPCISFormat(mediaType)) + .toMediaType(EPCISFormat.XML) + .toVersion(EPCISVersion.VERSION_2_0_0) + .build())) + .runSubscriptionOn(managedExecutor) + ).build(); + } + + // Method to convert the input JSON 2.0 EPCIS events into XML 1.2 EPCIS events + @Operation( + summary = + "Convert EPCIS document or single event from XML version 1.2 or 2.0 or JSON/JSON-LD 2.0 to EPCIS 1.2 XML.") + @Path("/convert/xml/1.2") + @POST + @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/ld+json"}) + @Produces(MediaType.APPLICATION_XML) + @RequestBody( + description = + "Convert EPCIS document or single event from XML version 1.2 or 2.0 or JSON/JSON-LD 2.0 to EPCIS 1.2 XML.", + content = { + @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 2.0 JSON document", + ref = "jsonDocument", + description = "Example EPCIS 2.0 document in JSON format.") + }), + @Content( + mediaType = MediaType.APPLICATION_XML, + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 2.0 XML document", + ref = "xmlDocument", + description = "Example EPCIS 2.0 document in XML format."), + @ExampleObject( + name = "EPCIS 1.2 XML document", + ref = "xml1.2Document", + description = "Example EPCIS 1.2 document") + + }), + @Content( + mediaType = "application/ld+json", + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 2.0 JSON document", + ref = "jsonDocument", + description = "Example EPCIS 2.0 document in JSON format.") + }) + }) + @APIResponses( + value = { + @APIResponse( + responseCode = "200", + description = + "OK: Converted to EPCIS 1.2 XML successfully.", + content = + @Content( + schema = @Schema(type = SchemaType.ARRAY, implementation = EPCISEvent.class), + examples = @ExampleObject( + name = "EPCIS 1.2 XML document", + ref = "xml1.2Document", + description = "Example EPCIS 1.2 document") + )), + @APIResponse( + responseCode = "400", + description = + "Bad Request: Input EPCIS JSON/JSON-LD document or EPCIS 1.2 XML or single event contains missing/invalid information.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "401", + description = + "Unauthorized: Unable to convert EPCIS JSON/JSON-LD document or EPCIS 1.2 XML or single event as request contains missing/invalid authorization.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "404", + description = + "Not Found: Unable to convert EPCIS JSON/JSON-LD document or EPCIS 1.2 XML or single event as the requested resource not found.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "406", + description = + "Not Acceptable: Unable to convert EPCIS JSON/JSON-LD document or EPCIS 1.2 XML or single event as server cannot find content confirming request.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "500", + description = + "Internal Server Error: Unable to convert EPCIS JSON/JSON-LD document or EPCIS 1.2 XML or single event as server encountered problem.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))) + }) + public RestMulti convertToXml_1_2( + final InputStream jsonEvents, + @Parameter( + name = "GS1-EPC-Format", + description = ParameterDescription.GS1_EPC_FORMAT, + schema = @Schema(type = SchemaType.STRING, + enumeration = {"No_Preference", "Always_GS1_Digital_Link", "Always_EPC_URN", "Never_Translates"} + ), + in = ParameterIn.HEADER) + @RestHeader(value = "GS1-EPC-Format") + String epcFormat, + @Parameter( + name = "GS1-CBV-XML-Format", + description = ParameterDescription.GS1_CBV_XML_FORMAT, + schema = @Schema(type = SchemaType.STRING, + enumeration = {"No_Preference", "Always_Web_URI", "Always_URN", "Never_Translates"} + ), + in = ParameterIn.HEADER) + @RestHeader(value = "GS1-CBV-XML-Format") + String cbvFormat, + @Context HttpHeaders httpHeaders) + throws FormatConverterException, IOException { + + final MediaType mediaType = httpHeaders.getMediaType(); + + if (mediaType == null || !GS1FormatSupport.isValidMediaType(mediaType)) { + throw new UnsupportedMediaTypeException("Unsupported media type: " + mediaType); + } + + return RestMulti.fromMultiData(ChannelUtil.toMulti(versionTransformer + .mapWith(GS1FormatSupport.createMapper(gs1FormatProvider.getFormatPreference())) + .convert( + jsonEvents, + Conversion.builder() + .fromMediaType(GS1FormatSupport.getEPCISFormat(mediaType)) + .toMediaType(EPCISFormat.XML) + .toVersion(EPCISVersion.VERSION_1_2_0) + .build())).runSubscriptionOn(managedExecutor) + ).build(); + } + + @Operation(summary = "Detect the version of provided EPCIS document.", hidden = false) + @Path("/document/version") + @POST + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces(MediaType.APPLICATION_JSON) + @RequestBody( + description = + "Convert EPCIS document or single event from JSON/JSON-LD or EPCIS 2.0 XML to EPCIS 2.0 XML.", + content = { + @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 2.0 JSON document", + ref = "jsonDocument", + description = "Example EPCIS 2.0 document in JSON format.") + }), + @Content( + mediaType = MediaType.APPLICATION_XML, + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 1.2 XML document", + ref = "xml1.2Document", + description = "Example EPCIS 1.2 document"), + @ExampleObject( + name = "EPCIS 2.0 XML document", + ref = "xmlDocument", + description = "Example EPCIS 2.0 document in XML format.") + }), + @Content( + mediaType = "application/ld+json", + schema = @Schema(implementation = EPCISDocument.class), + examples = { + @ExampleObject( + name = "EPCIS 2.0 JSON document", + ref = "jsonDocument", + description = "Example EPCIS 2.0 document in JSON format.") + }) + }) + @APIResponses(value = { + @APIResponse( + responseCode = "200", + description = + "OK: version detected", + content = @Content(schema = @Schema(type = SchemaType.OBJECT), + example = """ + { + "version": "1.2.0" + }""")), + @APIResponse( + responseCode = "400", + description = + "Bad Request: Input EPCIS document contains missing/invalid information.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))) + + }) + public Uni versionDetection(final InputStream epcisDocument) throws IOException { + final String version = versionTransformer.versionDetector(new BufferedInputStream(epcisDocument, 8192)).getVersion(); + final Map response = new HashMap<>() {{ + put("version", version); + }}; + return Uni.createFrom().item(Response.ok(response).build()); + } +} diff --git a/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/resource/IdentifierConverterResource.java b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/resource/IdentifierConverterResource.java new file mode 100644 index 0000000..d76a254 --- /dev/null +++ b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/resource/IdentifierConverterResource.java @@ -0,0 +1,169 @@ +package io.openepcis.epc.converter.resource; + +import io.openepcis.converter.exception.FormatConverterException; +import io.openepcis.converter.common.IdentifierConverterUtil; +import io.openepcis.model.rest.ProblemResponseBody; +import io.smallrye.mutiny.Uni; + +import java.util.Map; + +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.ExampleObject; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; + +@Path("/api") +@Tag( + name = "Identifier Converter", + description = + "Convert EPCIS instance or class identifier from URN to digital link WebURI and vice versa.") +public class IdentifierConverterResource { + + // Method to convert the URN identifier into Web URI identifier + @Operation( + summary = + "Convert EPCIS instance or class identifier from URN to digital link WebURI format.") + @Path(value = "/convert/identifier/web-uri") + @POST + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + @RequestBody( + description = "Convert EPCIS instance or class identifier from URN to WebURI.", + content = + @Content( + schema = @Schema(implementation = String.class), + mediaType = MediaType.TEXT_PLAIN, + examples = { + @ExampleObject( + name = "Instance Identifier", + value = "urn:epc:id:sgtin:4068194.000000.9999", + description = "Example Instance Identifier."), + @ExampleObject( + name = "Class Identifier", + value = "urn:epc:idpat:sgtin:4068194.000000.*", + description = "Example Class Identifier.") + })) + @APIResponses( + value = { + @APIResponse( + responseCode = "200", + description = "OK: Identifiers from URN to WebURI converted successfully.", + content = @Content( + schema = @Schema(type = SchemaType.STRING), + mediaType = MediaType.TEXT_PLAIN, + example = "https://id.gs1.org/01/04068194000004/21/9999" + ) + ), + @APIResponse( + responseCode = "400", + description = "Bad Request: Input URN identifier contains missing/invalid information.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "401", + description = + "Unauthorized: Unable to convert URN identifier as request contains missing/invalid authorization.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "404", + description = + "Not Found: Unable to convert URN identifier as the requested resource not found.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "406", + description = + "Not Acceptable: Unable to convert URN identifier as server cannot find content confirming request.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "500", + description = + "Internal Server Error: Unable to convert Identifier URN as server encountered problem.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))) + }) + public Uni convertToWebURI(String urn) throws FormatConverterException { + return Uni.createFrom().item(IdentifierConverterUtil.toWebURI(urn)); + } + + // Method to convert the Web URI identifier into URN identifier + @Operation( + summary = + "Convert EPCIS instance or class identifier from digital link WebURI to URN format.") + // @io.quarkus.vertx.web.Route(path = "/convert/identifier/urn", methods = + // io.quarkus.vertx.web.Route.HttpMethod.POST, order = 2) + @Path(value = "/convert/identifier/urn") + @POST + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.APPLICATION_JSON) + @RequestBody( + description = "Convert instance or class identifiers from WebURI -> URN", + content = + @Content( + schema = @Schema(implementation = String.class), + mediaType = MediaType.TEXT_PLAIN, + examples = { + @ExampleObject( + name = "Instance Identifier", + value = "https://id.gs1.org/01/04068194000004/21/1234", + description = "Example Instance Identifier."), + @ExampleObject( + name = "Class Identifier", + value = "https://id.gs1.org/01/04068194000004", + description = "Example Class Identifier.") + })) + @APIResponses( + value = { + @APIResponse( + responseCode = "200", + description = "OK: Identifiers from WebURI to URN converted successfully.", + content = + @Content(schema = @Schema(type = SchemaType.OBJECT), + mediaType = MediaType.APPLICATION_JSON, + example = """ + { + "gtin": "4068194000004", + "asURN": "urn:epc:id:sgtin:4068194.000000.1234", + "serial": "1234", + "asCaptured": "https://id.gs1.org/01/04068194000004/21/1234", + "canonicalDL": "https://id.gs1.org/01/04068194000004/21/1234" + }""" + ) + ), + @APIResponse( + responseCode = "400", + description = + "Bad Request: Input WebURI identifier contains missing/invalid information.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "401", + description = + "Unauthorized: Unable to convert WebURI identifier as request contains missing/invalid authorization.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "404", + description = + "Not Found: Unable to convert WebURI identifier as the requested resource not found.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "406", + description = + "Not Acceptable: Unable to convert WebURI identifier as server cannot find content confirming request.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))), + @APIResponse( + responseCode = "500", + description = + "Internal Server Error: Unable to convert WebURI identifier as server encountered problem.", + content = @Content(schema = @Schema(implementation = ProblemResponseBody.class))) + }) + public Uni> convertToURN(final String uri) throws FormatConverterException { + return Uni.createFrom().item(IdentifierConverterUtil.toURN(uri)); + } +} diff --git a/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/resource/ParameterDescription.java b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/resource/ParameterDescription.java new file mode 100644 index 0000000..a47b11d --- /dev/null +++ b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/resource/ParameterDescription.java @@ -0,0 +1,19 @@ +package io.openepcis.epc.converter.resource; + +public interface ParameterDescription { + String GS1_EPC_FORMAT = + "Header used by the client to indicate whether EPCs are expressed as GS1 Digital Link URIs or as EPC URNs.\n" + + "It is also used by the server to announce which EPC formats are supported. \n" + + "- No_Preference: No preference in the representation, i.e. any format is accepted.\n" + + "- Always_GS1_Digital_Link: URIs are returned as GS1 Digital Link.\n" + + "- Always_EPC_URN: URIs are returned as URN.\n" + + "- Never_Translates: EPCs are never translated, i.e. the original format is kept."; + String GS1_CBV_XML_FORMAT = + "When requesting XML content-type only, users can use this header to request\n" + + "receiving events with CBV values in either URN or Web URI format.\n" + + "This option is not available for JSON/JSON-LD.\n" + + "- No_Preference: The server chooses the representation.\n" + + "- Always_Web_URI: CBV values are returned as Web URI.\n" + + "- Always_URN: CBV values are returned as URNs.\n" + + "- Never_Translates: The original format is kept."; +} diff --git a/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/util/GS1FormatProvider.java b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/util/GS1FormatProvider.java new file mode 100644 index 0000000..a86b2e0 --- /dev/null +++ b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/util/GS1FormatProvider.java @@ -0,0 +1,21 @@ +package io.openepcis.epc.converter.util; + +import io.openepcis.converter.common.GS1FormatSupport; +import io.openepcis.model.epcis.format.FormatPreference; +import io.vertx.core.http.HttpServerRequest; + +import jakarta.enterprise.context.RequestScoped; + +@RequestScoped +public class GS1FormatProvider { + + private final GS1FormatSupport.RequestHeaderFacade request; + public GS1FormatProvider(final HttpServerRequest request) { + this.request = GS1FormatSupport.createRequestFacade(request::getHeader); + } + + public FormatPreference getFormatPreference() { + return GS1FormatSupport.getFormatPreference(request); + } + +} diff --git a/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/util/StreamingOutputMessageBodyWriter.java b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/util/StreamingOutputMessageBodyWriter.java new file mode 100644 index 0000000..211e52b --- /dev/null +++ b/service/converter-service-rest/src/main/java/io/openepcis/epc/converter/util/StreamingOutputMessageBodyWriter.java @@ -0,0 +1,35 @@ +package io.openepcis.epc.converter.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.StreamingOutput; +import jakarta.ws.rs.ext.MessageBodyWriter; +import jakarta.ws.rs.ext.Provider; + +@Provider +public class StreamingOutputMessageBodyWriter implements MessageBodyWriter { + + @Override + public boolean isWriteable( + Class aClass, Type type, Annotation[] annotations, MediaType mediaType) { + return StreamingOutput.class.isAssignableFrom(aClass); + } + + @Override + public void writeTo( + StreamingOutput streamingOutput, + Class aClass, + Type type, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap httpHeaders, + OutputStream outputStream) + throws IOException, WebApplicationException { + streamingOutput.write(outputStream); + } +} diff --git a/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/DocumentConverterResourceTest.java b/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/DocumentConverterResourceTest.java new file mode 100644 index 0000000..259805b --- /dev/null +++ b/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/DocumentConverterResourceTest.java @@ -0,0 +1,23 @@ +package io.openepcis.converter.resource.test; + +import io.openepcis.converter.service.restassured.AbstractDocumentConverterTest; +import io.openepcis.epc.converter.resource.DocumentConverterResource; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.test.junit.QuarkusTest; + +import java.net.URL; + +@QuarkusTest +public class DocumentConverterResourceTest extends AbstractDocumentConverterTest { + + @TestHTTPEndpoint(DocumentConverterResource.class) + @TestHTTPResource + URL url; + + @Override + public String url() { + return url + "/convert"; + } + +} diff --git a/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/DocumentVersionConverterResourceTest.java b/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/DocumentVersionConverterResourceTest.java new file mode 100644 index 0000000..ce8f8ed --- /dev/null +++ b/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/DocumentVersionConverterResourceTest.java @@ -0,0 +1,23 @@ +package io.openepcis.converter.resource.test; + +import io.openepcis.converter.service.restassured.AbstractDocumentVersionConverterTest; +import io.openepcis.epc.converter.resource.DocumentVersionConverterResource; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.test.junit.QuarkusTest; + +import java.net.URL; + +@QuarkusTest +public class DocumentVersionConverterResourceTest extends AbstractDocumentVersionConverterTest { + + @TestHTTPEndpoint(DocumentVersionConverterResource.class) + @TestHTTPResource + URL url; + + @Override + public String url() { + return url + "/convert/version"; + } + +} diff --git a/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/DocumentVersionDetectionTest.java b/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/DocumentVersionDetectionTest.java new file mode 100644 index 0000000..6ed8d59 --- /dev/null +++ b/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/DocumentVersionDetectionTest.java @@ -0,0 +1,23 @@ +package io.openepcis.converter.resource.test; + +import io.openepcis.converter.service.restassured.AbstractDocumentVersionDetectionTest; +import io.openepcis.epc.converter.resource.DocumentConverterResource; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.test.junit.QuarkusTest; + +import java.net.URL; + +@QuarkusTest +public class DocumentVersionDetectionTest extends AbstractDocumentVersionDetectionTest { + + @TestHTTPEndpoint(DocumentConverterResource.class) + @TestHTTPResource + URL url; + + @Override + public String url() { + return url.toString(); + } + +} diff --git a/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/IdentifierConverterResourceTest.java b/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/IdentifierConverterResourceTest.java new file mode 100644 index 0000000..b447a44 --- /dev/null +++ b/service/converter-service-rest/src/test/java/io/openepcis/converter/resource/test/IdentifierConverterResourceTest.java @@ -0,0 +1,28 @@ +package io.openepcis.converter.resource.test; + +import io.openepcis.converter.service.restassured.AbstractIdentifierConverterTest; +import io.openepcis.epc.converter.resource.IdentifierConverterResource; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.test.junit.QuarkusTest; + +import java.net.URL; + +@QuarkusTest +public class IdentifierConverterResourceTest extends AbstractIdentifierConverterTest { + + @TestHTTPEndpoint(IdentifierConverterResource.class) + @TestHTTPResource + URL url; + + @Override + public String webURIUrl() { + return url + "/convert/identifier/web-uri"; + } + + @Override + public String urnUrl() { + return url + "/convert/identifier/urn"; + } + +} diff --git a/service/converter-service-restassured/pom.xml b/service/converter-service-restassured/pom.xml new file mode 100644 index 0000000..bbcd5f9 --- /dev/null +++ b/service/converter-service-restassured/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + io.openepcis + openepcis-document-converter-parent + 1.0.0-SNAPSHOT + ../../pom.xml + + + converter-service-restassured + converter-service-restassured + restassured tests for converter-services + + + + + io.openepcis + openepcis-test-resources + provided + + + + + io.quarkus + quarkus-junit5 + provided + + + io.rest-assured + rest-assured + provided + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} + provided + + + + io.openepcis + openepcis-document-converter + + + + diff --git a/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractDocumentConverterTest.java b/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractDocumentConverterTest.java new file mode 100644 index 0000000..c0618d4 --- /dev/null +++ b/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractDocumentConverterTest.java @@ -0,0 +1,434 @@ +package io.openepcis.converter.service.restassured; + +import io.openepcis.resources.util.Commons; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import io.restassured.response.Response; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; + +@QuarkusTest +public abstract class AbstractDocumentConverterTest { + + private static String jsonConverterAPI_2_0; + private static String xmlConverterAPI_2_0; + private static String xmlConverterAPI_1_2; + + public abstract String url(); + + @BeforeEach + public void testApiEndpoint() { + jsonConverterAPI_2_0 = url() + "/json/2.0"; + xmlConverterAPI_2_0 = url() + "/xml/2.0"; + xmlConverterAPI_1_2 = url() + "/xml/1.2"; + } + + /** + * REST Assured test cases for converting the XML to JSON/JSON-LD + */ + + // Invalid input content type + @Test + public void jsonConverterInvalidContentTypeTest() { + final Response response = + RestAssured.given() + .contentType(ContentType.TEXT) + .body(Commons.getInputStream("2.0/EPCIS/XML/Capture/Documents/AggregationEvent.xml")) + .when() + .post(jsonConverterAPI_2_0); + + Assertions.assertEquals(415, response.getStatusCode()); + Assertions.assertEquals("NotSupportedException", response.jsonPath().get("type")); + Assertions.assertEquals( + "The content-type header value did not match the value in @Consumes", + response.jsonPath().get("detail")); + } + + // Invalid request body value + @Test + public void jsonConverterInvalidRequestBodyTest() { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body(Commons.getInputStream("2.0/EPCIS/JSON/Capture/Documents/AggregationEvent.json")) + .when() + .post(jsonConverterAPI_2_0); + Assertions.assertEquals(400, response.getStatusCode()); + } + + // Empty request body + @Test + public void jsonConverterEmptyRequestBodyTest() { + // Use assertThrows to catch and verify the expected exception + IllegalArgumentException exception = + Assertions.assertThrows( + IllegalArgumentException.class, + () -> + RestAssured.given() + .contentType(ContentType.XML) + .body( + Commons.getInputStream( + "2.0/EPCIS/XML/Capture/Documents/AggregationEvent1.xml")) + .when() + .post(jsonConverterAPI_2_0)); + + // Verify the error message of the caught exception + Assertions.assertEquals("body cannot be null", exception.getMessage()); + } + + // Valid request for converting to JSON/JSON-LD + @Test + public void jsonConverterValidRequestTest() throws IOException { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body( + IOUtils.toString( + Commons.getInputStream("2.0/EPCIS/XML/Capture/Documents/ObjectEvent.xml"), + StandardCharsets.UTF_8)) + .when() + .post(jsonConverterAPI_2_0); + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json;charset=UTF-8", response.getContentType()); + Assertions.assertEquals(2, (int) response.jsonPath().get("epcisBody.eventList.size()")); + } + + // Valid request for converting to JSON/JSON-LD + @Test + public void jsonConverterValidRequest2Test() throws IOException { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body( + IOUtils.toString( + Commons.getInputStream( + "2.0/EPCIS/XML/Capture/Documents/Combination_of_different_event.xml"), + StandardCharsets.UTF_8)) + .when() + .post(jsonConverterAPI_2_0); + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json;charset=UTF-8", response.getContentType()); + Assertions.assertEquals(6, (int) response.jsonPath().get("epcisBody.eventList.size()")); + } + + /** + * REST Assured test cases for converting JSON/JSON-LD to 2.0 XML + */ + + // Invalid input content type + @Test + public void xmlConverterInvalidContentTypeTest() { + final Response response = + RestAssured.given() + .contentType(ContentType.TEXT) + .body(Commons.getInputStream("2.0/EPCIS/JSON/Capture/Documents/AggregationEvent.json")) + .when() + .post(xmlConverterAPI_2_0); + + Assertions.assertEquals(415, response.getStatusCode()); + Assertions.assertEquals("NotSupportedException", response.jsonPath().get("type")); + Assertions.assertEquals( + "The content-type header value did not match the value in @Consumes", + response.jsonPath().get("detail")); + } + + // Empty request body + @Test + public void xmlConverterEmptyRequestBodyTest() { + // Use assertThrows to catch and verify the expected exception + IllegalArgumentException exception = + Assertions.assertThrows( + IllegalArgumentException.class, + () -> + RestAssured.given() + .contentType(ContentType.JSON) + .body( + Commons.getInputStream( + "2.0/EPCIS/JSON/Capture/Documents/AggregationEvent1.json")) + .when() + .post(xmlConverterAPI_2_0)); + + // Verify the error message of the caught exception + Assertions.assertEquals("body cannot be null", exception.getMessage()); + } + + // Valid request for converting JSON to XML 2.0 + @Test + public void xmlConverterValidRequestTest() { + final Response response = + RestAssured.given() + .contentType(ContentType.JSON) + .body(Commons.getInputStream("2.0/EPCIS/JSON/Capture/Documents/AggregationEvent.json")) + .when() + .post(xmlConverterAPI_2_0); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + Assertions.assertEquals(1, Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".AggregationEvent").size()); + } + + // Valid request for converting JSON to XML 2.0 + @Test + public void xmlConverterValidRequest2Test() { + final Response response = + RestAssured.given() + .contentType(ContentType.JSON) + .body( + Commons.getInputStream( + "2.0/EPCIS/JSON/Capture/Documents/Namespaces_at_different_level.json")) + .when() + .post(xmlConverterAPI_2_0); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + Assertions.assertEquals(5, Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".ObjectEvent").size()); + } + + // Valid request for converting JSON to XML 2.0 + @Test + public void xmlConverterValidRequest3Test() { + final Response response = + RestAssured.given() + .contentType(ContentType.JSON) + .body( + Commons.getInputStream( + "2.0/EPCIS/JSON/Capture/Documents/Combination_of_different_event.json")) + .when() + .post(xmlConverterAPI_2_0); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + Assertions.assertEquals(1, Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".ObjectEvent").size()); + Assertions.assertEquals(1, Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".TransformationEvent").size()); + Assertions.assertEquals(2, Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".AssociationEvent").size()); + } + + /** + * REST Assured test cases for converting XML to 2.0 XML + */ + + @Test + public void xmlConverterValidRequest4Test() throws Exception { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body(IOUtils.toString(Commons.getInputStream("2.0/EPCIS/XML/Capture/Documents/AssociationEvent.xml"), StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_2_0); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + Assertions.assertEquals( + 2, + Commons.getXmlPath(responseBody) + .getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".AssociationEvent") + .size()); + } + + @Test + public void xmlConverterValidRequest5Test() throws Exception { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body(IOUtils.toString(Commons.getInputStream("1.2/EPCIS/XML/Capture/Documents/ObjectEvent.xml"), StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_2_0); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + Assertions.assertEquals( + 1, + Commons.getXmlPath(responseBody) + .getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".ObjectEvent") + .size()); + } + /** + * REST Assured test cases for converting JSON/JSON-LD to 1.2 XML + */ + + // Invalid input content type + @Test + public void xmlConverter_1_2_InvalidContentTypeTest() { + final Response response = + RestAssured.given() + .contentType(ContentType.TEXT) + .body(Commons.getInputStream("2.0/EPCIS/JSON/Capture/Documents/AggregationEvent.json")) + .when() + .post(xmlConverterAPI_1_2); + + Assertions.assertEquals(415, response.getStatusCode()); + Assertions.assertEquals("NotSupportedException", response.jsonPath().get("type")); + Assertions.assertEquals( + "The content-type header value did not match the value in @Consumes", + response.jsonPath().get("detail")); + } + + // Empty request body + @Test + public void xmlConverter_1_2_EmptyRequestBodyTest() { + // Use assertThrows to catch and verify the expected exception + IllegalArgumentException exception = + Assertions.assertThrows( + IllegalArgumentException.class, + () -> + RestAssured.given() + .contentType(ContentType.JSON) + .body( + Commons.getInputStream( + "2.0/EPCIS/JSON/Capture/Documents/AggregationEvent1.json")) + .when() + .post(xmlConverterAPI_2_0)); + + // Verify the error message of the caught exception + Assertions.assertEquals("body cannot be null", exception.getMessage()); + } + + // Valid request for converting JSON to XML 1.2 + @Test + @Disabled + public void xmlConverter_1_2_ValidRequestTest() { + final Response response = + RestAssured.given() + .contentType(ContentType.JSON) + .body( + Commons.getInputStream( + "2.0/EPCIS/JSON/Capture/Documents/Combination_of_different_event.json")) + .when() + .post(xmlConverterAPI_1_2); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + Assertions.assertEquals(1, Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".ObjectEvent").size()); + Assertions.assertEquals( + 1, + Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".extension.TransformationEvent").size()); + Assertions.assertEquals( + 0, + Commons.getXmlPath(responseBody) + .getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".extension.extension.AssociationEvent") + .size()); + } + + @Test + public void xmlConverter_1_2_ValidRequest2Test() { + final Response response = + RestAssured.given() + .contentType(ContentType.JSON) + .body( + Commons.getInputStream( + "2.0/EPCIS/JSON/Capture/Documents/Namespaces_at_different_level.json")) + .when() + .post(xmlConverterAPI_1_2); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + Assertions.assertEquals(5, Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".ObjectEvent").size()); + } + + @Test + @Disabled + public void xmlConverter_1_2_ValidRequest3Test() { + final Response response = + RestAssured.given() + .contentType(ContentType.JSON) + .body(Commons.getInputStream("2.0/EPCIS/JSON/Capture/Documents/AssociationEvent.json")) + .when() + .post(xmlConverterAPI_1_2); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + Assertions.assertEquals( + 0, + Commons.getXmlPath(responseBody) + .getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".extension.extension.AssociationEvent") + .size()); + } + + + /** + * REST Assured test cases for converting the XML to 1.2 XML + */ + @Test + @Disabled + public void xmlConverter_1_2_ValidRequest4Test() throws Exception { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body(IOUtils.toString(Commons.getInputStream("2.0/EPCIS/XML/Capture/Documents/AssociationEvent.xml"), StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_1_2); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + Assertions.assertEquals( + 0, + Commons.getXmlPath(responseBody) + .getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".extension.extension.AssociationEvent") + .size()); + } + + @Test + public void xmlConverter_1_2_ValidRequest5Test() throws Exception { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body(IOUtils.toString(Commons.getInputStream("1.2/EPCIS/XML/Capture/Documents/ObjectEvent.xml"), StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_1_2); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + Assertions.assertEquals( + 1, + Commons.getXmlPath(responseBody) + .getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".ObjectEvent") + .size()); + } + + /** + * Disabled Test for non-functional XML 1.2 -> JSON conversion with GS1-EPC-Format Always_GS1_Digital_Link + * @throws Exception + */ + @Test + @Disabled + public void xmlConverter_1_2_ValidRequestEPCFormatTest() throws Exception { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .header("GS1-EPC-Format", "Always_GS1_Digital_Link") + .body(IOUtils.toString(Commons.getInputStream("1.2/EPCIS/XML/Capture/Documents/All_eventTypes_in_single_document.xml"), StandardCharsets.UTF_8)) + .when() + .post(jsonConverterAPI_2_0); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json;charset=UTF-8", response.getContentType()); + Assertions.assertEquals( + 1, + response.getBody().jsonPath() + .getList("epcisBody.eventList", HashMap.class) + .stream() + .filter(eventAsMap -> eventAsMap.get("type") + .equals("ObjectEvent")) + .count() + ); + } + +} diff --git a/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractDocumentVersionConverterTest.java b/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractDocumentVersionConverterTest.java new file mode 100644 index 0000000..35df3d5 --- /dev/null +++ b/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractDocumentVersionConverterTest.java @@ -0,0 +1,186 @@ +package io.openepcis.converter.service.restassured; + +import io.openepcis.resources.util.Commons; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import io.restassured.response.Response; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@QuarkusTest +public abstract class AbstractDocumentVersionConverterTest { + + + private String xmlConverterAPI_2_0; + private String xmlConverterAPI_1_2; + + public abstract String url(); + + @BeforeEach + public void testApiEndpoint() { + xmlConverterAPI_2_0 = url() + "/2.0"; + xmlConverterAPI_1_2 = url() + "/1.2"; + } + + /** Convert the XML 2.0 document into XML 1.2 */ + + // Invalid input content type + @Test + public void xml_1_2_ConverterInvalidContentTypeTest() throws IOException { + final Response response = + RestAssured.given() + .contentType(ContentType.JSON) + .body( + IOUtils.toString( + Commons.getInputStream("2.0/EPCIS/XML/Capture/Documents/AggregationEvent.xml"), + StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_1_2); + assertEquals(415, response.getStatusCode()); + assertEquals("NotSupportedException", response.jsonPath().get("type")); + assertEquals( + "The content-type header value did not match the value in @Consumes", + response.jsonPath().get("detail")); + } + + // Valid request body value + @Test + public void xml_1_2_ConverterValidTest() throws IOException { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body( + IOUtils.toString( + Commons.getInputStream("2.0/EPCIS/XML/Capture/Documents/AggregationEvent.xml"), + StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_1_2); + assertEquals(200, response.getStatusCode()); + assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + assertEquals(1, Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".AggregationEvent").size()); + } + + @Test + @Disabled + public void xml_1_2_ConverterValid2Test() throws IOException { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body( + IOUtils.toString( + Commons.getInputStream("2.0/EPCIS/XML/Capture/Documents/AssociationEvent.xml"), + StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_1_2); + assertEquals(200, response.getStatusCode()); + assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + assertEquals( + 0, + Commons.getXmlPath(responseBody) + .getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".extension.extension.AssociationEvent") + .size()); + } + + @Test + public void xml_1_2_ConverterValid3Test() throws IOException { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body( + IOUtils.toString( + Commons.getInputStream( + "2.0/EPCIS/XML/Capture/Documents/TransformationEvent.xml"), + StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_1_2); + assertEquals(200, response.getStatusCode()); + assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + assertEquals( + 1, + Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".extension.TransformationEvent").size()); + } + + /** Convert the XML 1.2 document into XML 2.0 */ + // Invalid input content type + @Test + public void xml_2_0_ConverterInvalidContentTypeTest() throws IOException { + final Response response = + RestAssured.given() + .contentType(ContentType.JSON) + .body( + IOUtils.toString( + Commons.getInputStream("1.2/EPCIS/XML/Capture/Documents/AggregationEvent.xml"), + StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_2_0); + assertEquals(415, response.getStatusCode()); + assertEquals("NotSupportedException", response.jsonPath().get("type")); + assertEquals( + "The content-type header value did not match the value in @Consumes", + response.jsonPath().get("detail")); + } + + // Valid request body value + @Test + public void xml_2_0_ConverterValidTest() throws IOException { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body( + IOUtils.toString( + Commons.getInputStream("1.2/EPCIS/XML/Capture/Documents/AggregationEvent.xml"), + StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_2_0); + assertEquals(200, response.getStatusCode()); + assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + assertEquals(1, Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".AggregationEvent").size()); + } + + @Test + public void xml_2_0_ConverterValid2Test() throws IOException { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body( + IOUtils.toString( + Commons.getInputStream("1.2/EPCIS/XML/Capture/Documents/AssociationEvent.xml"), + StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_2_0); + assertEquals(200, response.getStatusCode()); + assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + assertEquals(1, Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".AssociationEvent").size()); + } + + @Test + public void xml_2_0_ConverterValid3Test() throws IOException { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body( + IOUtils.toString( + Commons.getInputStream( + "1.2/EPCIS/XML/Capture/Documents/TransformationEvent.xml"), + StandardCharsets.UTF_8)) + .when() + .post(xmlConverterAPI_2_0); + assertEquals(200, response.getStatusCode()); + assertEquals("application/xml;charset=UTF-8", response.getContentType()); + final String responseBody = response.getBody().asString(); + assertEquals(1, Commons.getXmlPath(responseBody).getList(Commons.EPCIS_EPCISDOCUMENT_EPCISBODY_EVENT_LIST + ".TransformationEvent").size()); + } +} diff --git a/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractDocumentVersionDetectionTest.java b/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractDocumentVersionDetectionTest.java new file mode 100644 index 0000000..fbcb892 --- /dev/null +++ b/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractDocumentVersionDetectionTest.java @@ -0,0 +1,65 @@ +package io.openepcis.converter.service.restassured; + +import io.openepcis.resources.util.Commons; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import io.restassured.response.Response; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.nio.charset.StandardCharsets; + +@QuarkusTest +public abstract class AbstractDocumentVersionDetectionTest { + + private String documentVersionDetectionAPI; + + public abstract String url(); + + @BeforeEach + public void testApiEndpoint() { + documentVersionDetectionAPI = url() + "/document/version"; + } + + @Test + public void versionDetectionTest_XML_1_2_0() throws Exception { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body(IOUtils.toString(Commons.getInputStream("1.2/EPCIS/XML/Capture/Documents/ObjectEvent.xml"), StandardCharsets.UTF_8)) + .when() + .post(documentVersionDetectionAPI); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("1.2.0", response.jsonPath().get("version")); + } + + @Test + public void versionDetectionTest_JSON_2_0_0() throws Exception { + final Response response = + RestAssured.given() + .contentType(ContentType.JSON) + .body(IOUtils.toString(Commons.getInputStream("2.0/EPCIS/JSON/Capture/Documents/ObjectEvent.json"), StandardCharsets.UTF_8)) + .when() + .post(documentVersionDetectionAPI); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("2.0.0", response.jsonPath().get("version")); + } + + @Test + public void versionDetectionTest_XML_2_0_0() throws Exception { + final Response response = + RestAssured.given() + .contentType(ContentType.XML) + .body(IOUtils.toString(Commons.getInputStream("2.0/EPCIS/XML/Capture/Documents/ObjectEvent.xml"), StandardCharsets.UTF_8)) + .when() + .post(documentVersionDetectionAPI); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("2.0.0", response.jsonPath().get("version")); + } +} diff --git a/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractIdentifierConverterTest.java b/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractIdentifierConverterTest.java new file mode 100644 index 0000000..3ed89d4 --- /dev/null +++ b/service/converter-service-restassured/src/main/java/io/openepcis/converter/service/restassured/AbstractIdentifierConverterTest.java @@ -0,0 +1,149 @@ +package io.openepcis.converter.service.restassured; + +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import io.restassured.response.Response; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +public abstract class AbstractIdentifierConverterTest { + + private String webURIConvertAPI; + private String urnConvertAPI; + + public abstract String webURIUrl(); + + public abstract String urnUrl(); + + @BeforeEach + public void testApiEndpoint() { + webURIConvertAPI = webURIUrl(); + urnConvertAPI = urnUrl(); + } + + /** REST Assured test cases for converting the URN to WebURI */ + + // For valid data API returns status code of 200 + @Test + public void convertToWebURIStatusCodeTest() { + RestAssured.given() + .body("urn:epc:id:sgtin:234567890.1123.9999") + .when() + .post(webURIConvertAPI) + .then() + .assertThat() + .statusCode(200); + } + + // For invalid data API returns status code of 400 + @Test + public void convertToWebURIInvalidDataTest() { + RestAssured.given() + .body("urn:epc:id:sgtin:234567890.1123.") + .when() + .post(webURIConvertAPI) + .then() + .assertThat() + .statusCode(400); + } + + // Compare the returned value with correct value for Instance Identifier + @Test + public void convertToInstanceWebURITest() { + final Response response = + RestAssured.given().body("urn:epc:id:sgtin:234567890.1123.9999").when().post(webURIConvertAPI); + + assertEquals(200, response.getStatusCode()); + assertEquals("https://id.gs1.org/01/12345678901231/21/9999", response.getBody().asString()); + } + + // Compare the returned value with correct value for Class Identifier + @Test + public void convertToClassWebURITest() { + final Response response = + RestAssured.given().body("urn:epc:idpat:itip:483478.7347834.92.93.*").when().post(webURIConvertAPI); + + assertEquals(200, response.getStatusCode()); + assertEquals("https://id.gs1.org/8006/748347834783449293", response.getBody().asString()); + } + + // Invalid media type in request + @Test + public void convertToWebURIInvalidContentTypeTest() { + RestAssured.given() + .contentType(ContentType.JSON) + .body("urn:epc:idpat:itip:483478.7347834.92.93.*") + .when() + .post(webURIConvertAPI) + .then() + .assertThat() + .statusCode(415) + .body("title", Matchers.equalTo("Unsupported Media Type")); + } + + /** REST Assured test cases for converting the WebURI to URN */ + + // For valid data API returns status code of 200 + @Test + public void convertToURNStatusCodeTest() { + RestAssured.given() + .body("https://id.gs1.org/00/012345678901234567 6") + .when() + .post(urnConvertAPI) + .then() + .assertThat() + .statusCode(200); + } + + // For invalid data API returns status code of 400 + @Test + public void convertToURNInvalidDataTest() { + RestAssured.given() + .body("https://id.gs1.org/00/01234567890123456A 10") + .when() + .post(urnConvertAPI) + .then() + .assertThat() + .statusCode(400); + } + + // Compare the returned value with correct value for Instance Identifier + @Test + public void convertToInstanceURNTest() { + final Response response = + RestAssured.given().body("https://id.gs1.org/414/6880009384938 12").when().post(urnConvertAPI); + + assertEquals(200, response.getStatusCode()); + assertEquals("urn:epc:id:sgln:688000938493..0", response.jsonPath().getString("asURN")); + } + + // Compare the returned value with correct value for Class Identifier + @Test + public void convertToClassURNTest() { + final Response response = + RestAssured.given() + .body("https://id.gs1.org/01/49557283728732/10//8484892%") + .when() + .post(urnConvertAPI); + + assertEquals(200, response.getStatusCode()); + assertEquals( + "urn:epc:class:lgtin:9557283.472873./8484892%", response.jsonPath().getString("asURN")); + } + + // Invalid media type in request + @Test + public void convertToURNInvalidContentTypeTest() { + RestAssured.given() + .contentType(ContentType.JSON) + .body("https://eclipse.org/401/12345678901234A") + .when() + .post(urnConvertAPI) + .then() + .assertThat() + .statusCode(415) + .body("title", Matchers.equalTo("Unsupported Media Type")); + } +} diff --git a/service/converter-service-servlet/pom.xml b/service/converter-service-servlet/pom.xml new file mode 100644 index 0000000..f77432e --- /dev/null +++ b/service/converter-service-servlet/pom.xml @@ -0,0 +1,132 @@ + + + 4.0.0 + + io.openepcis + openepcis-document-converter-parent + 1.0.0-SNAPSHOT + ../../pom.xml + + + converter-service-servlet + converter-service-servlet + Servlet implementation to convert the EPCIS 2.0 documents and identifiers from one standard format to another + + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + + io.openepcis + openepcis-document-converter + + + + + + io.openepcis + openepcis-document-converter + + + + io.openepcis + openepcis-document-converter-sax + + + + + io.openepcis + openepcis-epc-digitallink-translator + + + + + io.openepcis + openepcis-repository-common + + + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-undertow + + + + jakarta.ws.rs + jakarta.ws.rs-api + provided + + + org.eclipse.persistence + org.eclipse.persistence.moxy + compile + + + + + io.openepcis + openepcis-test-resources + test + + + io.openepcis + converter-service-restassured + test + + + + + io.quarkus + quarkus-smallrye-context-propagation + test + + + io.quarkus + quarkus-resteasy-reactive-jackson + test + + + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + org.junit.jupiter + junit-jupiter + ${junit.version} + test + + + javax.inject + javax.inject + 1 + test + + + + diff --git a/service/converter-service-servlet/src/main/java/io/openepcis/converter/servlet/DetectDocumentVersionServlet.java b/service/converter-service-servlet/src/main/java/io/openepcis/converter/servlet/DetectDocumentVersionServlet.java new file mode 100644 index 0000000..4b7cad7 --- /dev/null +++ b/service/converter-service-servlet/src/main/java/io/openepcis/converter/servlet/DetectDocumentVersionServlet.java @@ -0,0 +1,61 @@ +package io.openepcis.converter.servlet; + +import io.openepcis.converter.VersionTransformer; +import io.openepcis.model.rest.servlet.ServletSupport; +import jakarta.inject.Inject; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.core.MediaType; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@WebServlet(name = "DetectDocumentVersionServlet", urlPatterns = "/api/document/version") +public class DetectDocumentVersionServlet extends HttpServlet { + @Inject + VersionTransformer versionTransformer; + + @Inject + ServletSupport servletSupport; + + private static final List PRODUCES = List.of( + MediaType.APPLICATION_JSON, + "application/problem+json", + MediaType.WILDCARD); + + private static final List CONSUMES = List.of( + MediaType.APPLICATION_JSON, + MediaType.APPLICATION_XML, + "application/ld+json"); + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + final Optional accept = servletSupport.accept(PRODUCES, req, resp); + if (accept.isEmpty()) { + return; + } + final Optional contentType = servletSupport.contentType(CONSUMES, accept.get(), req, resp); + if (contentType.isEmpty()) { + return; + } + try { + final String version = versionTransformer.versionDetector(new BufferedInputStream(req.getInputStream(), 8192)).getVersion(); + final Map response = new HashMap<>() {{ + put("version", version); + }}; + resp.setContentType(MediaType.APPLICATION_JSON + ";charset=UTF-8"); + servletSupport.writeJson(resp, response); + } catch (Exception e) { + servletSupport.writeException(new BadRequestException(e.getMessage(), e), accept.get(), resp); + } + } + +} diff --git a/service/converter-service-servlet/src/main/java/io/openepcis/converter/servlet/DocumentConverterServlet.java b/service/converter-service-servlet/src/main/java/io/openepcis/converter/servlet/DocumentConverterServlet.java new file mode 100644 index 0000000..9663409 --- /dev/null +++ b/service/converter-service-servlet/src/main/java/io/openepcis/converter/servlet/DocumentConverterServlet.java @@ -0,0 +1,106 @@ +package io.openepcis.converter.servlet; + +import io.openepcis.constants.EPCISFormat; +import io.openepcis.constants.EPCISVersion; +import io.openepcis.converter.Conversion; +import io.openepcis.converter.VersionTransformer; +import io.openepcis.epc.converter.common.GS1FormatSupport; +import io.openepcis.model.epcis.format.FormatPreference; +import io.openepcis.model.rest.servlet.ServletSupport; +import jakarta.inject.Inject; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.core.MediaType; + +import java.io.IOException; +import java.util.List; +import java.util.Optional; + +@WebServlet(name = "DocumentConverterServlet", urlPatterns = "/api/convert/*") +public class DocumentConverterServlet extends HttpServlet { + + private static final List PRODUCES = List.of( + MediaType.APPLICATION_JSON, + MediaType.APPLICATION_XML, + "application/problem+json", + MediaType.WILDCARD); + + private static final List CONSUMES = List.of( + MediaType.APPLICATION_JSON, + MediaType.APPLICATION_XML, + "application/ld+json"); + + private static final String CONVERT_JSON_2_0 = "/convert/json/2.0"; + + private static final String CONVERT_XML_2_0 = "/convert/xml/2.0"; + + private static final String CONVERT_XML_1_2 = "/convert/xml/1.2"; + + @Inject + VersionTransformer versionTransformer; + + @Inject + ServletSupport servletSupport; + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + final Optional accept = servletSupport.accept(PRODUCES, req, resp); + if (accept.isEmpty()) { + return; + } + final Optional contentType =servletSupport.contentType(CONSUMES, accept.get(), req, resp); + if (contentType.isEmpty()) { + return; + } + final Optional from = EPCISFormat.fromString(contentType.get()); + if (from.isEmpty()) { + servletSupport.writeException(new BadRequestException("unable to detect EPCISFormat"), accept.get(), resp); + return; + } + try { + if (req.getRequestURI().endsWith(CONVERT_JSON_2_0)) { + if (!servletSupport.accepted(accept, "json", resp)) { + return; + } + resp.setContentType(MediaType.APPLICATION_JSON + ";charset=UTF-8"); + runVersionTransformer(req, resp, from.get(), EPCISFormat.JSON_LD, EPCISVersion.VERSION_2_0_0); + } else { + if (!servletSupport.accepted(accept, "xml", resp)) { + return; + } + resp.setContentType(MediaType.APPLICATION_XML + ";charset=UTF-8"); + if (req.getRequestURI().endsWith(CONVERT_XML_2_0)) { + runVersionTransformer(req, resp, from.get(), EPCISFormat.XML, EPCISVersion.VERSION_2_0_0); + } else if (req.getRequestURI().endsWith(CONVERT_XML_1_2)) { + runVersionTransformer(req, resp, from.get(), EPCISFormat.XML, EPCISVersion.VERSION_1_2_0); + } else { + resp.sendError(HttpServletResponse.SC_NOT_FOUND); + } + } + } catch (Exception e) { + servletSupport.writeException(new BadRequestException(e.getMessage(), e), accept.get(), resp); + } + } + + private void runVersionTransformer(HttpServletRequest req, HttpServletResponse resp, final EPCISFormat from, final EPCISFormat to, final EPCISVersion version) throws IOException { + versionTransformer + .mapWith(GS1FormatSupport.createMapper(getFormatPreference(req))) + .convert( + req.getInputStream(), + Conversion.builder().fromMediaType(from) + .toMediaType(to) + .toVersion(version) + .build() + ) + .transferTo(resp.getOutputStream()); + } + + private FormatPreference getFormatPreference(HttpServletRequest req) { + return GS1FormatSupport.getFormatPreference(GS1FormatSupport.createRequestFacade(req::getHeader)); + } + +} diff --git a/service/converter-service-servlet/src/main/java/io/openepcis/converter/servlet/IdentifierConverterServlets.java b/service/converter-service-servlet/src/main/java/io/openepcis/converter/servlet/IdentifierConverterServlets.java new file mode 100644 index 0000000..f597144 --- /dev/null +++ b/service/converter-service-servlet/src/main/java/io/openepcis/converter/servlet/IdentifierConverterServlets.java @@ -0,0 +1,73 @@ +package io.openepcis.converter.servlet; + +import io.openepcis.epc.converter.common.IdentifierConverterUtil; +import io.openepcis.model.rest.servlet.ServletSupport; +import jakarta.inject.Inject; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.core.MediaType; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class IdentifierConverterServlets { + + @WebServlet(name = "IdentifierConverterServlets.ConvertToWebURI", urlPatterns = "/api/convert/identifier/web-uri") + public static final class ConvertToWebURI extends HttpServlet { + + @Inject + ServletSupport servletSupport; + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + final Optional accept = servletSupport.accept(List.of(MediaType.APPLICATION_JSON, MediaType.WILDCARD), req, resp); + if (!servletSupport.accepted(accept, MediaType.APPLICATION_JSON, resp)) { + return; + } + if (servletSupport.contentType(List.of(MediaType.TEXT_PLAIN), accept.get(), req, resp).isEmpty()) { + return; + } + try { + final String result = IdentifierConverterUtil.toWebURI(IOUtils.toString(req.getInputStream(), StandardCharsets.UTF_8)); + resp.setContentType(MediaType.TEXT_PLAIN); + resp.getWriter().write(result); + } catch (Exception e) { + servletSupport.writeException(new BadRequestException(e.getMessage(), e), MediaType.APPLICATION_JSON, resp); + } + } + } + + @WebServlet(name = "IdentifierConverterServlets.ConvertToURN", urlPatterns = "/api/convert/identifier/urn") + public static final class ConvertToURN extends HttpServlet { + + @Inject + ServletSupport servletSupport; + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + final Optional accept = servletSupport.accept(List.of(MediaType.APPLICATION_JSON, MediaType.WILDCARD), req, resp); + if (!servletSupport.accepted(accept, MediaType.TEXT_PLAIN, resp)) { + return; + } + if (servletSupport.contentType(List.of(MediaType.TEXT_PLAIN), accept.get(), req, resp).isEmpty()) { + return; + } + try { + final Map result = IdentifierConverterUtil.toURN(IOUtils.toString(req.getInputStream(), StandardCharsets.UTF_8)); + resp.setContentType(MediaType.APPLICATION_JSON); + servletSupport.writeJson(resp, result); + } catch (Exception e) { + servletSupport.writeException(new BadRequestException(e.getMessage(), e), MediaType.APPLICATION_JSON, resp); + } + } + + } +} diff --git a/service/converter-service-servlet/src/test/java/io/openepcis/converter/servlet/test/CDITestProducer.java b/service/converter-service-servlet/src/test/java/io/openepcis/converter/servlet/test/CDITestProducer.java new file mode 100644 index 0000000..35e420e --- /dev/null +++ b/service/converter-service-servlet/src/test/java/io/openepcis/converter/servlet/test/CDITestProducer.java @@ -0,0 +1,31 @@ +package io.openepcis.converter.servlet.test; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.openepcis.model.rest.ProblemResponseBody; +import io.quarkus.logging.Log; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import jakarta.xml.bind.Marshaller; + +public class CDITestProducer { + + + @Produces + Marshaller marshaller() throws JAXBException { + try { + final JAXBContext ctx = + JAXBContext.newInstance(ProblemResponseBody.class); + Log.info("created Validation Test JAXBContext : " + ctx.getClass().getName()); + return ctx.createMarshaller(); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Produces + ObjectMapper objectMapper() { + return new ObjectMapper(); + } +} diff --git a/service/converter-service-servlet/src/test/java/io/openepcis/converter/servlet/test/DocumentConverterServletTest.java b/service/converter-service-servlet/src/test/java/io/openepcis/converter/servlet/test/DocumentConverterServletTest.java new file mode 100644 index 0000000..943a1f4 --- /dev/null +++ b/service/converter-service-servlet/src/test/java/io/openepcis/converter/servlet/test/DocumentConverterServletTest.java @@ -0,0 +1,25 @@ +package io.openepcis.converter.servlet.test; + +import io.openepcis.converter.service.restassured.AbstractDocumentConverterTest; +import io.openepcis.converter.servlet.DocumentConverterServlet; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.test.junit.QuarkusTest; + +import java.net.URL; + +@QuarkusTest +public class DocumentConverterServletTest extends AbstractDocumentConverterTest { + + + @TestHTTPEndpoint(DocumentConverterServlet.class) + @TestHTTPResource + URL url; + + @Override + public String url() { + // need to remove trailing slash being introduced by wildcard url pattern + return url.toString().substring(0, url.toString().length()-1); + } + +} diff --git a/service/converter-service-servlet/src/test/java/io/openepcis/converter/servlet/test/IdentifierConverterServletTest.java b/service/converter-service-servlet/src/test/java/io/openepcis/converter/servlet/test/IdentifierConverterServletTest.java new file mode 100644 index 0000000..b07b220 --- /dev/null +++ b/service/converter-service-servlet/src/test/java/io/openepcis/converter/servlet/test/IdentifierConverterServletTest.java @@ -0,0 +1,31 @@ +package io.openepcis.converter.servlet.test; + +import io.openepcis.converter.service.restassured.AbstractIdentifierConverterTest; +import io.openepcis.converter.servlet.IdentifierConverterServlets; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.test.junit.QuarkusTest; + +import java.net.URL; + +@QuarkusTest +public class IdentifierConverterServletTest extends AbstractIdentifierConverterTest { + + @TestHTTPEndpoint(IdentifierConverterServlets.ConvertToURN.class) + @TestHTTPResource + URL urnUrl; + + @TestHTTPEndpoint(IdentifierConverterServlets.ConvertToWebURI.class) + @TestHTTPResource + URL webURIUrl; + @Override + public String webURIUrl() { + return webURIUrl.toString(); + } + + @Override + public String urnUrl() { + return urnUrl.toString(); + } + +}