Skip to content
This repository has been archived by the owner on Dec 21, 2022. It is now read-only.

Commit

Permalink
Fixes Jackson's XML QName parser to the correct namespace (#605)
Browse files Browse the repository at this point in the history
* Mapping QName to the correct namespace.

* Import cleanup
  • Loading branch information
vitorpamplona authored Aug 26, 2022
1 parent ac9e80c commit db59f30
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
Expand All @@ -15,6 +16,7 @@
import org.cqframework.cql.elm.execution.TypeSpecifier;
import org.opencds.cqf.cql.engine.elm.execution.Executable;
import org.opencds.cqf.cql.engine.serializing.jackson.mixins.*;
import org.opencds.cqf.cql.engine.serializing.jackson.modules.QNameFixerXMLMapperModifier;

public class XmlCqlMapper {
private static final XmlMapper mapper = XmlMapper.builder()
Expand All @@ -27,6 +29,8 @@ public class XmlCqlMapper {
.enable(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL)
.defaultPropertyInclusion(JsonInclude.Value.construct(JsonInclude.Include.NON_NULL, JsonInclude.Include.NON_NULL))
.addModule(new JaxbAnnotationModule())
// Jackson's base QName deserializer does not unpack the namespace. This Modifier fixes it.
.addModule(new SimpleModule().setDeserializerModifier(new QNameFixerXMLMapperModifier()))
//.addMixIn(Library.class, LibraryMixin.class) // Some case sensitivity issue in the name [L]ibrary
// The ordering here of the mix ins for
// ExpressionDef -> CodeSystemRef -> Expression -> Element matters,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.opencds.cqf.cql.engine.serializing.jackson.modules;

import javax.xml.namespace.QName;

import java.io.IOException;

import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser;

public class QNameFixerXMLMapperDeserializer extends JsonDeserializer<QName> {
JsonDeserializer<?> originalDeserializer;
public QNameFixerXMLMapperDeserializer(JsonDeserializer<?> deserializer) {
originalDeserializer = deserializer;
}

@Override
public QName deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
var qName = (QName) originalDeserializer.deserialize(jsonParser, deserializationContext);

if (qName.getLocalPart().indexOf(":") > 0) {
var prefix = qName.getLocalPart().split(":")[0];
var localPart = qName.getLocalPart().split(":")[1];
var namespace = ((FromXmlParser)deserializationContext.getParser()).getStaxReader().getNamespaceContext().getNamespaceURI(prefix);

return new QName(namespace, localPart, prefix);
}

return qName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.opencds.cqf.cql.engine.serializing.jackson.modules;

import javax.xml.namespace.QName;

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;

public class QNameFixerXMLMapperModifier extends BeanDeserializerModifier {
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
if (beanDesc.getBeanClass() == QName.class) {
return new QNameFixerXMLMapperDeserializer(deserializer);
}
return super.modifyDeserializer(config, beanDesc, deserializer);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.opencds.cqf.cql.engine.serializing;

import static org.testng.AssertJUnit.assertEquals;

import java.io.IOException;

import org.cqframework.cql.cql2elm.LibraryContentType;
import org.cqframework.cql.elm.execution.IntervalTypeSpecifier;
import org.cqframework.cql.elm.execution.NamedTypeSpecifier;
import org.testng.annotations.Test;

public class QNameIssueJacksonTest {
@Test
void loaderIsAvailable() throws IOException {
var lib =
CqlLibraryReaderFactory.getReader(LibraryContentType.XML.mimeType())
.read(QNameIssueJacksonTest.class.getResourceAsStream("QNameIssue.xml"));

var actual = ((NamedTypeSpecifier)
((IntervalTypeSpecifier) lib.getParameters().getDef().get(0).getParameterTypeSpecifier()).getPointType()
).getName();

assertEquals("{urn:hl7-org:elm-types:r1}DateTime", actual.toString());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<library
xmlns="urn:hl7-org:elm:r1"
xmlns:t="urn:hl7-org:elm-types:r1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<parameters>
<def localId="25" locator="25:1-26:66" name="Measurement Period" accessLevel="Public">
<parameterTypeSpecifier localId="24" locator="25:32-25:49" xsi:type="IntervalTypeSpecifier">
<pointType localId="23" locator="25:41-25:48" name="t:DateTime" xsi:type="NamedTypeSpecifier"/>
</parameterTypeSpecifier>
</def>
</parameters>
</library>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.opencds.cqf.cql.engine.serializing;

import static org.testng.AssertJUnit.assertEquals;

import java.io.IOException;

import org.cqframework.cql.cql2elm.LibraryContentType;
import org.cqframework.cql.elm.execution.IntervalTypeSpecifier;
import org.cqframework.cql.elm.execution.NamedTypeSpecifier;
import org.testng.annotations.Test;

public class QNameIssueJaxbTest {
@Test
void loaderIsAvailable() throws IOException {
var lib =
CqlLibraryReaderFactory.getReader(LibraryContentType.XML.mimeType())
.read(QNameIssueJaxbTest.class.getResourceAsStream("QNameIssue.xml"));

var actual = ((NamedTypeSpecifier)
((IntervalTypeSpecifier) lib.getParameters().getDef().get(0).getParameterTypeSpecifier()).getPointType()
).getName();

assertEquals("{urn:hl7-org:elm-types:r1}DateTime", actual.toString());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<library
xmlns="urn:hl7-org:elm:r1"
xmlns:t="urn:hl7-org:elm-types:r1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<parameters>
<def localId="25" locator="25:1-26:66" name="Measurement Period" accessLevel="Public">
<parameterTypeSpecifier localId="24" locator="25:32-25:49" xsi:type="IntervalTypeSpecifier">
<pointType localId="23" locator="25:41-25:48" name="t:DateTime" xsi:type="NamedTypeSpecifier"/>
</parameterTypeSpecifier>
</def>
</parameters>
</library>

0 comments on commit db59f30

Please sign in to comment.