Skip to content

Commit

Permalink
#422: Support JSON representation of the HPD DSMLv2 data model
Browse files Browse the repository at this point in the history
  • Loading branch information
unixoid committed Jul 13, 2023
1 parent 55b78c2 commit dd3c59b
Show file tree
Hide file tree
Showing 12 changed files with 362 additions and 15 deletions.
8 changes: 8 additions & 0 deletions commons/ihe/hpd/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

<!-- Dependencies for test -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
Expand Down Expand Up @@ -59,6 +61,7 @@ public class BatchResponse {
@XmlElementRef(name = "authResponse", namespace = "urn:oasis:names:tc:DSML:2:0:core", type = JAXBElement.class, required = false),
@XmlElementRef(name = "addResponse", namespace = "urn:oasis:names:tc:DSML:2:0:core", type = JAXBElement.class, required = false)
})
@JsonSerialize(using = JaxbElementListSerializer.class)
protected List<JAXBElement<?>> batchResponses;
@XmlAttribute(name = "requestID")
protected String requestID;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2;

import com.fasterxml.jackson.annotation.JsonTypeInfo;

/**
* Marker interface for whatever can appear in {@link BatchResponse#batchResponses}.
*
* @author Dmytro Rud
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)
public interface BatchResponseElement {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2;

import lombok.Getter;
import lombok.Setter;

import java.util.List;

/**
* Intermediary representation of an HPD {@link BatchResponse} required because the JSON deserializer cannot handle lists of JAXBElements.
* <p>
* Usage:
* <pre>
* ObjectMapper mapper = new ObjectMapper();
* BatchResponseIntermediary intermediary = mapper.readValue(json1, BatchResponseIntermediary.class);
* BatchResponse batchResponse = batchResponseIntermediary.toBatchResponse();
* </pre>
*
* @author Dmytro Rud
*/
public class BatchResponseIntermediary {

private static final ObjectFactory OBJECT_FACTORY = new ObjectFactory();

@Getter
@Setter
private List<BatchResponseElement> batchResponses;

@Getter
@Setter
private String requestID;

/**
* Transforms this intermediary representation into a proper JAXB POJO.
*/
public BatchResponse toBatchResponse() {
BatchResponse batchResponse = new BatchResponse();
batchResponse.setRequestID(requestID);
if (batchResponses != null) {
for (Object response : batchResponses) {
if (response instanceof ExtendedResponse) {
batchResponse.getBatchResponses().add(OBJECT_FACTORY.createBatchResponseExtendedResponse((ExtendedResponse) response));
} else if (response instanceof SearchResponse) {
batchResponse.getBatchResponses().add(OBJECT_FACTORY.createBatchResponseSearchResponse((SearchResponse) response));
} else if (response instanceof ErrorResponse) {
batchResponse.getBatchResponses().add(OBJECT_FACTORY.createBatchResponseErrorResponse((ErrorResponse) response));
} else if (response instanceof LDAPResult) {
LDAPResult ldapResult = (LDAPResult) response;
switch (ldapResult.getElementName()) {
case "modDNResponse":
batchResponse.getBatchResponses().add(OBJECT_FACTORY.createBatchResponseModDNResponse(ldapResult));
break;
case "compareResponse":
batchResponse.getBatchResponses().add(OBJECT_FACTORY.createBatchResponseCompareResponse(ldapResult));
break;
case "delResponse":
batchResponse.getBatchResponses().add(OBJECT_FACTORY.createBatchResponseDelResponse(ldapResult));
break;
case "modifyResponse":
batchResponse.getBatchResponses().add(OBJECT_FACTORY.createBatchResponseModifyResponse(ldapResult));
break;
case "authResponse":
batchResponse.getBatchResponses().add(OBJECT_FACTORY.createBatchResponseAuthResponse(ldapResult));
break;
case "addResponse":
batchResponse.getBatchResponses().add(OBJECT_FACTORY.createBatchResponseAddResponse(ldapResult));
break;
default:
throw new IllegalStateException("Cannot handle LDAPResult element name " + ldapResult.getElementName());
}
} else {
throw new IllegalStateException("Cannot handle class " + response.getClass().getName());
}
}
}
return batchResponse;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2;

import com.fasterxml.jackson.annotation.JsonTypeInfo;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
Expand Down Expand Up @@ -62,6 +64,7 @@
ExtendedRequest.class,
SearchResultEntry.class
})
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)
public class DsmlMessage {

protected List<Control> control;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"message",
"detail"
})
public class ErrorResponse {
public class ErrorResponse implements BatchResponseElement {

protected String message;
protected Detail detail;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.databind.type.SimpleType;

import javax.xml.bind.JAXBElement;
import java.io.IOException;
import java.util.List;

/**
* JSON serializer for {@link List}&lt;{@link JAXBElement}&gt;.
*
* @author Dmytro Rud
*/
public class JaxbElementListSerializer extends StdSerializer<List> {

public JaxbElementListSerializer() {
super(List.class);
}

@Override
public void serialize(List list, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartArray(list);
for (Object object : list) {
JAXBElement<?> jaxbElement = (JAXBElement<?>) object;
Object value = jaxbElement.getValue();
if (value instanceof LDAPResult) {
((LDAPResult) value).setElementName(jaxbElement.getName().getLocalPart());
}
JsonSerializer<Object> valueSerializer = provider.findValueSerializer(value.getClass());
TypeSerializer typeSerializer = provider.findTypeSerializer(SimpleType.constructUnsafe(value.getClass()));
valueSerializer.serializeWithType(value, gen, provider, typeSerializer);
}
gen.writeEndArray();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@
*/
package org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.*;


/**
Expand Down Expand Up @@ -58,9 +56,15 @@
ExtendedResponse.class
})
public class LDAPResult
extends DsmlMessage
extends DsmlMessage implements BatchResponseElement
{

// this attribute is required only in JSON serialization to hold the actual element name
@XmlTransient
@JsonProperty("@e")
@Getter @Setter
private String elementName;

@XmlElement(required = true)
protected ResultCode resultCode;
protected String errorMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"searchResultReference",
"searchResultDone"
})
public class SearchResponse {
public class SearchResponse implements BatchResponseElement {

protected List<SearchResultEntry> searchResultEntry;
protected List<SearchResultReference> searchResultReference;
Expand Down
Loading

0 comments on commit dd3c59b

Please sign in to comment.