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

com.ibm.fhir.persistence.helper.FHIRPersistenceHelper Maven / Gradle / Ivy

There is a newer version: 4.11.1
Show newest version
/*
 * (C) Copyright IBM Corp. 2016, 2021
 *
 * SPDX-License-Identifier: Apache-2.0
 */

package com.ibm.fhir.persistence.helper;

import static com.ibm.fhir.config.FHIRConfiguration.PROPERTY_PERSISTENCE_FACTORY;

import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.ibm.fhir.config.FHIRConfiguration;
import com.ibm.fhir.config.PropertyGroup;
import com.ibm.fhir.persistence.FHIRPersistence;
import com.ibm.fhir.persistence.FHIRPersistenceFactory;
import com.ibm.fhir.persistence.exception.FHIRPersistenceException;

/**
 * This class serves as a helper for obtaining the correct persistence implementation to be used by the FHIR REST API
 * layer.
 */
public class FHIRPersistenceHelper implements PersistenceHelper {
    private static final Logger log = Logger.getLogger(FHIRPersistenceHelper.class.getName());

    protected PropertyGroup fhirConfig = null;

    // Issue #1366. Keep one instance of each type of persistence factory instead of instantiating it every time
    private final ConcurrentHashMap persistenceFactoryCache = new ConcurrentHashMap<>();

    public FHIRPersistenceHelper() {
        log.entering(this.getClass().getName(), "FHIRPersistenceHelper ctor");
        try {
            fhirConfig = FHIRConfiguration.getInstance().loadConfiguration();
        } catch (Throwable t) {
            String msg = "Unexpected error while retrieving configuration.";
            log.severe(msg + " " + t);
            throw new RuntimeException(msg, t);
        } finally {
            log.exiting(this.getClass().getName(), "FHIRPersistenceHelper ctor");
        }
    }

    /**
     * Retrieves the name of the factory class that should be instantiated for use by the server.
     * @param factoryPropertyName name of the property that contains the {@link FHIRPersistenceFactory} class name.
     * @return Name of the factory class that will be loaded.
     */
    protected String retrieveFactoryClassName(String factoryPropertyName) throws FHIRPersistenceException {
        try {
            String factoryClassName = fhirConfig.getStringProperty(factoryPropertyName);
            if (factoryClassName == null) {
                throw new FHIRPersistenceException("Unable to find configuration property: " + factoryPropertyName);
            } else {
                if (log.isLoggable(Level.FINE)) {
                    log.fine("Retrieved persistence factory property '" + factoryPropertyName + "': " + factoryClassName);
                }
            }
            return factoryClassName;
        } catch (Throwable t) {
            throw new FHIRPersistenceException("Unexpected error while retrieving configuration.", t);
        }
    }

    @Override
    public FHIRPersistence getFHIRPersistenceImplementation() throws FHIRPersistenceException {
        return getFHIRPersistenceImplementation(PROPERTY_PERSISTENCE_FACTORY);
    }

    @Override
    public FHIRPersistence getFHIRPersistenceImplementation(String factoryPropertyName) throws FHIRPersistenceException {
        log.entering(this.getClass().getName(), "getFHIRPersistenceImplementation");

        try {
            String factoryClassName = retrieveFactoryClassName(factoryPropertyName);
            if (log.isLoggable(Level.FINE)) {
                log.fine("Using FHIR persistence factory class name: " + factoryClassName);
            }

            FHIRPersistenceFactory factory = persistenceFactoryCache.computeIfAbsent(factoryClassName, FHIRPersistenceHelper::newInstance );

            if (factory != null) {
                // Call the factory and return the implementation instance.
                return factory.getInstance();
            } else {
                throw new FHIRPersistenceException(PROPERTY_PERSISTENCE_FACTORY + " is configured incorrectly");
            }
        } catch (FHIRPersistenceException fpe) {
            throw fpe;
        } catch (Throwable t) {
            throw new FHIRPersistenceException(PROPERTY_PERSISTENCE_FACTORY + " is configured incorrectly", t);
        } finally {
            log.exiting(this.getClass().getName(), "getFHIRPersistenceImplementation");
        }
    }

    /**
     * Create a new instance of the class
     * @param factoryClassName
     * @return
     */
    private static FHIRPersistenceFactory newInstance(String factoryClassName) {
        Class factoryClass = null;
        try {
            factoryClass = Class.forName(factoryClassName);
        } catch (ClassNotFoundException e) {
            String msg = "An error occurred while trying to load FHIR persistence factory class '" + factoryClassName + "'";
            log.severe(msg + ": " + e);

            throw new IllegalStateException("Failed to load persistence implementation class");
        }

        try {
            if (FHIRPersistenceFactory.class.isAssignableFrom(factoryClass)) {
                return (FHIRPersistenceFactory) factoryClass.getDeclaredConstructor().newInstance();
            } else {
                throw new IllegalArgumentException("FHIRPersistenceFactory is not assignable from " + factoryClassName);
            }
        } catch (Throwable t) {
            log.log(Level.SEVERE, "Failed creating new instance of " + factoryClassName, t);
            throw new IllegalStateException("Failed to create persistence implementation class");
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy