From fb898a1a276d4f188bfe74c3b6c64ab13e222105 Mon Sep 17 00:00:00 2001 From: Dmytro Rud Date: Fri, 16 Aug 2024 09:06:48 +0200 Subject: [PATCH] #451: extensible set of supported controls --- .../ihe/hpd/controls/ControlUtils.java | 37 +++++++---- .../controls/strategies/ControlStrategy.java | 35 ++++++++++ .../strategies/PaginationControlStrategy.java | 50 +++++++++++++++ .../strategies/SortControlStrategy.java | 64 +++++++++++++++++++ .../SortResponseControlStrategy.java | 49 ++++++++++++++ .../stub/json/ControlListDeserializer.java | 26 ++------ .../hpd/stub/json/ControlListSerializer.java | 49 ++++---------- 7 files changed, 243 insertions(+), 67 deletions(-) create mode 100644 commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/ControlStrategy.java create mode 100644 commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/PaginationControlStrategy.java create mode 100644 commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/SortControlStrategy.java create mode 100644 commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/SortResponseControlStrategy.java diff --git a/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/ControlUtils.java b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/ControlUtils.java index b694d66716..53b9aab0a1 100644 --- a/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/ControlUtils.java +++ b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/ControlUtils.java @@ -17,15 +17,19 @@ import lombok.experimental.UtilityClass; import org.apache.commons.lang3.NotImplementedException; -import org.openehealth.ipf.commons.ihe.hpd.controls.sorting.SortControl2; -import org.openehealth.ipf.commons.ihe.hpd.controls.sorting.SortResponseControl2; +import org.openehealth.ipf.commons.ihe.hpd.controls.strategies.ControlStrategy; +import org.openehealth.ipf.commons.ihe.hpd.controls.strategies.PaginationControlStrategy; +import org.openehealth.ipf.commons.ihe.hpd.controls.strategies.SortControlStrategy; +import org.openehealth.ipf.commons.ihe.hpd.controls.strategies.SortResponseControlStrategy; import org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2.Control; import org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2.DsmlMessage; import org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2.SearchResponse; import javax.naming.ldap.*; import java.io.IOException; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * Methods for mapping of Controls to and from DSMLv2 and Strings. @@ -36,16 +40,27 @@ @UtilityClass public class ControlUtils { + /** + * Map from control OIDs to control strategies. Applications can extend this map. + */ + private static final Map STRATEGIES = new HashMap<>(); + + static { + STRATEGIES.put(PagedResultsControl.OID, new PaginationControlStrategy()); + STRATEGIES.put(SortControl.OID, new SortControlStrategy()); + STRATEGIES.put(SortResponseControl.OID, new SortResponseControlStrategy()); + } + + public static Map getStrategies() { + return STRATEGIES; + } + public static T extractControl(byte[] berBytes, String type, boolean criticality) throws IOException { - switch (type) { - case PagedResultsControl.OID: - return (T) new PagedResultsResponseControl(PagedResultsResponseControl.OID, criticality, berBytes); - case SortControl.OID: - return (T) new SortControl2(berBytes, criticality); - case SortResponseControl.OID: - return (T) new SortResponseControl2(berBytes, criticality); - default: - throw new NotImplementedException("Cannot handle control type " + type); + ControlStrategy strategy = STRATEGIES.get(type); + if (strategy != null) { + return (T) strategy.deserializeDsml2(berBytes, criticality); + } else { + throw new NotImplementedException("Cannot handle control type " + type); } } diff --git a/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/ControlStrategy.java b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/ControlStrategy.java new file mode 100644 index 0000000000..125f2b0aca --- /dev/null +++ b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/ControlStrategy.java @@ -0,0 +1,35 @@ +/* + * Copyright 2024 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.controls.strategies; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonNode; + +import javax.naming.ldap.BasicControl; +import java.io.IOException; + +/** + * @author Dmytro Rud + */ +public interface ControlStrategy { + + BasicControl deserializeDsml2(byte[] berBytes, boolean criticality) throws IOException; + + BasicControl deserializeJson(JsonNode node) throws IOException; + + void serializeJson(BasicControl control, JsonGenerator gen) throws IOException; + +} diff --git a/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/PaginationControlStrategy.java b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/PaginationControlStrategy.java new file mode 100644 index 0000000000..0da8eefc74 --- /dev/null +++ b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/PaginationControlStrategy.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 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.controls.strategies; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonNode; + +import javax.naming.ldap.BasicControl; +import javax.naming.ldap.PagedResultsControl; +import javax.naming.ldap.PagedResultsResponseControl; +import java.io.IOException; + +/** + * @author Dmytro Rud + */ +public class PaginationControlStrategy implements ControlStrategy { + + @Override + public BasicControl deserializeDsml2(byte[] berBytes, boolean criticality) throws IOException { + return new PagedResultsResponseControl(PagedResultsResponseControl.OID, criticality, berBytes); + } + + @Override + public BasicControl deserializeJson(JsonNode node) throws IOException { + return new PagedResultsControl(node.get("size").intValue(), node.get("cookie").binaryValue(), node.get("critical").booleanValue()); + } + + @Override + public void serializeJson(BasicControl control, JsonGenerator gen) throws IOException { + PagedResultsResponseControl paginationControl = (PagedResultsResponseControl) control; + gen.writeNumberField("size", paginationControl.getResultSize()); + if (paginationControl.getCookie() != null) { + gen.writeBinaryField("cookie", paginationControl.getCookie()); + } + } + +} diff --git a/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/SortControlStrategy.java b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/SortControlStrategy.java new file mode 100644 index 0000000000..7c282617bf --- /dev/null +++ b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/SortControlStrategy.java @@ -0,0 +1,64 @@ +/* + * Copyright 2024 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.controls.strategies; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonNode; +import org.openehealth.ipf.commons.ihe.hpd.controls.sorting.SortControl2; + +import javax.naming.ldap.BasicControl; +import javax.naming.ldap.SortKey; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; + +/** + * @author Dmytro Rud + */ +public class SortControlStrategy implements ControlStrategy { + + @Override + public BasicControl deserializeDsml2(byte[] berBytes, boolean criticality) throws IOException { + return new SortControl2(berBytes, criticality); + } + + @Override + public BasicControl deserializeJson(JsonNode node) throws IOException { + ArrayList keys = new ArrayList<>(); + JsonNode keysNode = node.get("keys"); + Iterator keyNodes = keysNode.elements(); + while (keyNodes.hasNext()) { + JsonNode keyNode = keyNodes.next(); + keys.add(new SortKey(keyNode.get("attrId").textValue(), keyNode.get("ascending").booleanValue(), keyNode.get("matchingRuleId").textValue())); + } + return new SortControl2(node.get("critical").asBoolean(), keys.toArray(new SortKey[0])); + } + + @Override + public void serializeJson(BasicControl control, JsonGenerator gen) throws IOException { + SortControl2 sortControl = (SortControl2) control; + gen.writeArrayFieldStart("keys"); + for (SortKey sortKey : sortControl.getKeys()) { + gen.writeStartObject(); + gen.writeStringField("attrId", sortKey.getAttributeID()); + gen.writeStringField("matchingRuleId", sortKey.getMatchingRuleID()); + gen.writeBooleanField("ascending", sortKey.isAscending()); + gen.writeEndObject(); + } + gen.writeEndArray(); + } + +} diff --git a/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/SortResponseControlStrategy.java b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/SortResponseControlStrategy.java new file mode 100644 index 0000000000..65426e0090 --- /dev/null +++ b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/controls/strategies/SortResponseControlStrategy.java @@ -0,0 +1,49 @@ +/* + * Copyright 2024 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.controls.strategies; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonNode; +import org.openehealth.ipf.commons.ihe.hpd.controls.sorting.SortResponseControl2; + +import javax.naming.ldap.BasicControl; +import java.io.IOException; + +/** + * @author Dmytro Rud + */ +public class SortResponseControlStrategy implements ControlStrategy { + + @Override + public BasicControl deserializeDsml2(byte[] berBytes, boolean criticality) throws IOException { + return new SortResponseControl2(berBytes, criticality); + } + + @Override + public BasicControl deserializeJson(JsonNode node) throws IOException { + return new SortResponseControl2(node.get("resultCode").intValue(), node.get("failedAttrId").asText(), node.get("critical").booleanValue()); + } + + @Override + public void serializeJson(BasicControl control, JsonGenerator gen) throws IOException { + SortResponseControl2 sortResponseControl = (SortResponseControl2) control; + gen.writeNumberField("resultCode", sortResponseControl.getResultCode()); + if (sortResponseControl.getFailedAttributeName() != null) { + gen.writeStringField("failedAttrId", sortResponseControl.getFailedAttributeName()); + } + } + +} diff --git a/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/stub/json/ControlListDeserializer.java b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/stub/json/ControlListDeserializer.java index 5621f3c476..bd5ad9c491 100644 --- a/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/stub/json/ControlListDeserializer.java +++ b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/stub/json/ControlListDeserializer.java @@ -22,11 +22,10 @@ import com.fasterxml.jackson.databind.JsonNode; import org.apache.commons.lang3.NotImplementedException; import org.openehealth.ipf.commons.ihe.hpd.controls.ControlUtils; -import org.openehealth.ipf.commons.ihe.hpd.controls.sorting.SortControl2; -import org.openehealth.ipf.commons.ihe.hpd.controls.sorting.SortResponseControl2; +import org.openehealth.ipf.commons.ihe.hpd.controls.strategies.ControlStrategy; import org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2.Control; -import javax.naming.ldap.*; +import javax.naming.ldap.BasicControl; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; @@ -54,22 +53,11 @@ public List deserialize(JsonParser jsonParser, DeserializationContext deserializ } private static BasicControl deserializeControl(JsonNode node) throws IOException { - switch (node.get("type").textValue()) { - case PagedResultsControl.OID: - return new PagedResultsControl(node.get("size").intValue(), node.get("cookie").binaryValue(), node.get("critical").booleanValue()); - case SortControl.OID: - ArrayList keys = new ArrayList<>(); - JsonNode keysNode = node.get("keys"); - Iterator keyNodes = keysNode.elements(); - while (keyNodes.hasNext()) { - JsonNode keyNode = keyNodes.next(); - keys.add(new SortKey(keyNode.get("attrId").textValue(), keyNode.get("ascending").booleanValue(), keyNode.get("matchingRuleId").textValue())); - } - return new SortControl2(node.get("critical").asBoolean(), keys.toArray(new SortKey[0])); - case SortResponseControl.OID: - return new SortResponseControl2(node.get("resultCode").intValue(), node.get("failedAttrId").asText(), node.get("critical").booleanValue()); - default: - throw new NotImplementedException("Cannot handle control type " + node.get("type").asText()); + ControlStrategy strategy = ControlUtils.getStrategies().get(node.get("type").textValue()); + if (strategy != null) { + return strategy.deserializeJson(node); + } else { + throw new NotImplementedException("Cannot handle control type " + node.get("type").asText()); } } diff --git a/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/stub/json/ControlListSerializer.java b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/stub/json/ControlListSerializer.java index 01e89ddfbe..5512fab415 100644 --- a/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/stub/json/ControlListSerializer.java +++ b/commons/ihe/hpd/src/main/java/org/openehealth/ipf/commons/ihe/hpd/stub/json/ControlListSerializer.java @@ -20,11 +20,10 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer; import org.apache.commons.lang3.NotImplementedException; import org.openehealth.ipf.commons.ihe.hpd.controls.ControlUtils; -import org.openehealth.ipf.commons.ihe.hpd.controls.sorting.SortControl2; -import org.openehealth.ipf.commons.ihe.hpd.controls.sorting.SortResponseControl2; +import org.openehealth.ipf.commons.ihe.hpd.controls.strategies.ControlStrategy; import org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2.Control; -import javax.naming.ldap.*; +import javax.naming.ldap.BasicControl; import java.io.IOException; import java.util.List; @@ -44,41 +43,17 @@ public void serialize(List list, JsonGenerator gen, SerializerProvider provider) gen.writeStartArray(list); for (Object object : list) { Control dsmlcontrol = (Control) object; - BasicControl control = ControlUtils.extractControl((byte[]) dsmlcontrol.getControlValue(), dsmlcontrol.getType(), dsmlcontrol.isCriticality()); - gen.writeStartObject(); - gen.writeStringField("type", control.getID()); - gen.writeBooleanField("critical", control.isCritical()); - switch (dsmlcontrol.getType()) { - case PagedResultsControl.OID: - PagedResultsResponseControl paginationControl = (PagedResultsResponseControl) control; - gen.writeNumberField("size", paginationControl.getResultSize()); - if (paginationControl.getCookie() != null) { - gen.writeBinaryField("cookie", paginationControl.getCookie()); - } - break; - case SortControl.OID: - SortControl2 sortControl = (SortControl2) control; - gen.writeArrayFieldStart("keys"); - for (SortKey sortKey : sortControl.getKeys()) { - gen.writeStartObject(); - gen.writeStringField("attrId", sortKey.getAttributeID()); - gen.writeStringField("matchingRuleId", sortKey.getMatchingRuleID()); - gen.writeBooleanField("ascending", sortKey.isAscending()); - gen.writeEndObject(); - } - gen.writeEndArray(); - break; - case SortResponseControl.OID: - SortResponseControl2 sortResponseControl = (SortResponseControl2) control; - gen.writeNumberField("resultCode", sortResponseControl.getResultCode()); - if (sortResponseControl.getFailedAttributeName() != null) { - gen.writeStringField("failedAttrId", sortResponseControl.getFailedAttributeName()); - } - break; - default: - throw new NotImplementedException("Cannot handle control type " + dsmlcontrol.getType()); + ControlStrategy strategy = ControlUtils.getStrategies().get(dsmlcontrol.getType()); + if (strategy != null) { + BasicControl control = strategy.deserializeDsml2((byte[]) dsmlcontrol.getControlValue(), dsmlcontrol.isCriticality()); + gen.writeStartObject(); + gen.writeStringField("type", control.getID()); + gen.writeBooleanField("critical", control.isCritical()); + strategy.serializeJson(control, gen); + gen.writeEndObject(); + } else { + throw new NotImplementedException("Cannot handle control type " + dsmlcontrol.getType()); } - gen.writeEndObject(); } gen.writeEndArray(); }