All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.fhir.server.notification.FHIRNotificationUtil Maven / Gradle / Ivy

/*
 * (C) Copyright IBM Corp. 2016, 2021
 *
 * SPDX-License-Identifier: Apache-2.0
 */

package com.ibm.fhir.server.notification;

import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;

import com.ibm.fhir.config.FHIRConfigHelper;
import com.ibm.fhir.config.FHIRConfiguration;
import com.ibm.fhir.exception.FHIRException;
import com.ibm.fhir.model.format.Format;
import com.ibm.fhir.model.parser.FHIRJsonParser;
import com.ibm.fhir.model.parser.FHIRParser;
import com.ibm.fhir.model.util.FHIRUtil;
import com.ibm.fhir.model.util.JsonSupport;
import com.ibm.fhir.search.SearchConstants;

import jakarta.json.Json;
import jakarta.json.JsonBuilderFactory;
import jakarta.json.JsonException;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonReader;
import jakarta.json.JsonReaderFactory;

/**
 * FHIRNotificationUtil supports serializing and deserializing the FHIRNotificationEvent based on conditions.
 */
public class FHIRNotificationUtil {
    private static final Logger LOG = Logger.getLogger(FHIRNotificationUtil.class.getSimpleName());
    private static final JsonReaderFactory JSON_READER_FACTORY = Json.createReaderFactory(null);
    private static final JsonBuilderFactory JSON_BUILDER_FACTORY = Json.createBuilderFactory(null);

    private static final int DEFAULT_MAX_SIZE = 1000000;

    private FHIRNotificationUtil() {
        // No Operation
    }

    /**
     * serialize the FHIRNotificationEvent
     *
     * @param jsonString the input string
     * @return FHIRNotificationEvent without the Resource
     */
    public static FHIRNotificationEvent toNotificationEvent(String jsonString) {
        try (JsonReader reader = JSON_READER_FACTORY.createReader(new StringReader(jsonString))) {
            JsonObject jsonObject = reader.readObject();
            FHIRNotificationEvent event = new FHIRNotificationEvent();
            event.setLastUpdated(jsonObject.getString("lastUpdated"));
            event.setLocation(jsonObject.getString("location"));
            event.setOperationType(jsonObject.getString("operationType"));
            event.setResourceId(jsonObject.getString("resourceId"));
            event.setDatasourceId(jsonObject.getString("datasourceId"));
            event.setTenantId(jsonObject.getString("tenantId"));
            return event;
        } catch (JsonException e) {
            LOG.warning("Failed to parse json string: " + e.getLocalizedMessage());
            return null;
        }
    }

    /**
     * Serializes the notification event into a JSON string.
     * @param event the FHIRNotificationEvent structure to be serialized
     * @param includeResource a flag that controls whether or not the resource object within
     * the event structure should be included in the serialized message.
     * @return the serialized message as a String
     * @throws FHIRException
     */
    public static String toJsonString(FHIRNotificationEvent event, boolean includeResource) throws FHIRException {
        JsonObjectBuilder builder = JSON_BUILDER_FACTORY.createObjectBuilder();
        builder.add("lastUpdated", event.getLastUpdated());
        builder.add("location", event.getLocation());
        builder.add("operationType", event.getOperationType());
        builder.add("resourceId", event.getResourceId());
        builder.add("datasourceId", event.getDatasourceId());
        builder.add("tenantId", event.getTenantId());

        // If it's a delete operation, don't add as there is no actual resource in the event.
        String jsonString;
        if (!"delete".equals(event.getOperationType()) && includeResource && event.getResource() != null) {
            builder.add("resource", JsonSupport.toJsonObject(event.getResource()));
            JsonObject jsonObject = builder.build();

            jsonString = jsonObject.toString();
            long length = jsonString.getBytes().length;

            int maxSize = FHIRConfigHelper.getIntProperty(FHIRConfiguration.PROPERTY_NOTIFICATION_MAX_SIZE, DEFAULT_MAX_SIZE);
            if (length > maxSize) {
                LOG.fine(() -> event.getResource().getClass().getSimpleName() + "/" + event.getResourceId() + " is over the size limit - '" + length + "' > '" + maxSize + "'");

                // the build method wipes out any preexisting values, we have to add them back.
                builder.add("lastUpdated", event.getLastUpdated());
                builder.add("location", event.getLocation());
                builder.add("operationType", event.getOperationType());
                builder.add("resourceId", event.getResourceId());
                builder.add("datasourceId", event.getDatasourceId());
                builder.add("tenantId", event.getTenantId());

                // If we are including a subset, we'll add here.
                String subset = FHIRConfigHelper.getStringProperty(FHIRConfiguration.PROPERTY_NOTIFICATION_NOTIFICATION_SIZE_BEHAVIOR, "subset");
                if ("subset".equals(subset)) {
                    List elements = Arrays.asList("id", "meta", "resourceType");
                    com.ibm.fhir.model.resource.Resource resource = FHIRParser.parser(Format.JSON)
                                                                        .as(FHIRJsonParser.class)
                                                                        .parseAndFilter(JsonSupport.toJsonObject(event.getResource()), elements);
                    // add a SUBSETTED tag to this resource to indicate that its elements have been filtered
                    if (!FHIRUtil.hasTag(resource, SearchConstants.SUBSETTED_TAG)) {
                        resource = FHIRUtil.addTag(resource, SearchConstants.SUBSETTED_TAG);
                    }
                    builder.add("resource", JsonSupport.toJsonObject(resource));
                } else {
                    LOG.fine(() -> "Omitting the resource in FHIRNotificationEvent");
                }

                jsonObject = builder.build();
                jsonString = jsonObject.toString();
            }
        } else {
            JsonObject jsonObject = builder.build();
            jsonString = jsonObject.toString();
        }
        return jsonString;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy