org.openmrs.module.openconceptlab.ImportServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.openconceptlab.ImportServiceImpl.java

Source

/**
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
 * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
 *
 * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
 * graphic logo is a trademark of OpenMRS Inc.
 */
package org.openmrs.module.openconceptlab;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.openmrs.Concept;
import org.openmrs.ConceptMap;
import org.openmrs.ConceptName;
import org.openmrs.ConceptReferenceTerm;
import org.openmrs.GlobalProperty;
import org.openmrs.api.AdministrationService;
import org.openmrs.api.ConceptNameType;
import org.openmrs.api.ConceptService;
import org.openmrs.api.db.hibernate.DbSession;
import org.openmrs.api.db.hibernate.DbSessionFactory;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

public class ImportServiceImpl implements ImportService {

    DbSessionFactory sessionFactory;

    AdministrationService adminService;

    ConceptService conceptService;

    public void setSessionFactory(DbSessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void setAdminService(AdministrationService adminService) {
        this.adminService = adminService;
    }

    public void setConceptService(ConceptService conceptService) {
        this.conceptService = conceptService;
    }

    /**
     * @should return all updates ordered descending by ids
     */
    @Override
    public List<Import> getImportsInOrder(int first, int max) {
        Criteria update = getSession().createCriteria(Import.class);
        update.addOrder(Order.desc("importId"));
        update.setFirstResult(first);
        update.setMaxResults(max);

        @SuppressWarnings("unchecked")
        List<Import> list = update.list();
        return list;
    }

    @Override
    public List<Concept> getConceptsByName(String name, Locale locale) {
        Criteria criteria = getSession().createCriteria(ConceptName.class);
        criteria.add(Restrictions.eq("voided", false));
        if (adminService.isDatabaseStringComparisonCaseSensitive()) {
            criteria.add(Restrictions.eq("name", name).ignoreCase());
        } else {
            criteria.add(Restrictions.eq("name", name));
        }
        criteria.add(Restrictions.eq("locale", locale));

        @SuppressWarnings("unchecked")
        List<ConceptName> conceptNames = criteria.list();

        Set<Concept> concepts = new LinkedHashSet<Concept>();
        for (ConceptName conceptName : conceptNames) {
            concepts.add(conceptName.getConcept());
        }
        return new ArrayList<Concept>(concepts);
    }

    @Override
    public List<ConceptName> changeDuplicateConceptNamesToIndexTerms(Concept conceptToImport) {
        List<ConceptName> result = new ArrayList<ConceptName>();

        if (conceptToImport.isRetired()) {
            return Collections.emptyList();
        }

        boolean dbCaseSensitive = adminService.isDatabaseStringComparisonCaseSensitive();
        Iterator<ConceptName> it = conceptToImport.getNames().iterator();
        while (it.hasNext()) {
            ConceptName nameToImport = it.next();

            if (nameToImport.isVoided()) {
                continue;
            }

            if (ConceptNameType.INDEX_TERM.equals(nameToImport.getConceptNameType())) {
                continue; //index terms are never considered duplicates
            }

            if (nameToImport.isLocalePreferred() || nameToImport.isFullySpecifiedName()
                    || nameToImport.equals(nameToImport.getConcept().getName(nameToImport.getLocale()))) {
                Criteria criteria = getSession().createCriteria(ConceptName.class);
                criteria.add(Restrictions.eq("voided", false));
                if (dbCaseSensitive) {
                    criteria.add(Restrictions.eq("name", nameToImport.getName()).ignoreCase());
                } else {
                    criteria.add(Restrictions.eq("name", nameToImport.getName()));
                }
                criteria.add(Restrictions.or(Restrictions.eq("locale", nameToImport.getLocale()),
                        Restrictions.eq("locale", new Locale(nameToImport.getLocale().getLanguage()))));

                @SuppressWarnings("unchecked")
                List<ConceptName> conceptNames = criteria.list();

                for (ConceptName conceptName : conceptNames) {
                    if (conceptName.getConcept().isRetired()) {
                        continue;
                    } else if (conceptName.getConcept().getUuid().equals(conceptToImport.getUuid())) {
                        continue;
                    } else if (conceptName.isLocalePreferred() || conceptName.isFullySpecifiedName()
                            || conceptName.equals(conceptName.getConcept().getName(nameToImport.getLocale()))) {
                        //if it is the default name for locale
                        nameToImport.setConceptNameType(ConceptNameType.INDEX_TERM);
                        nameToImport.setLocalePreferred(false);
                        result.add(nameToImport);

                        //start again since any previous name to import can be the default name for locale now
                        it = conceptToImport.getNames().iterator();
                        break;
                    }
                }
            }
        }

        return result;
    }

    /**
     * @should return update with id
     * @should throw IllegalArgumentException if update does not exist
     */
    @Override
    public Import getImport(Long id) {
        Import update = (Import) getSession().get(Import.class, id);
        if (update == null) {
            throw new IllegalArgumentException("No update with the given id " + id);
        }
        return update;
    }

    @Override
    public Import getImport(String uuid) {
        Import update = (Import) getSession().createQuery("from OclImport i where i.uuid = :uuid")
                .setString("uuid", uuid).uniqueResult();
        return update;
    }

    @Override
    public Import getLastImport() {
        Criteria update = getSession().createCriteria(Import.class);
        update.addOrder(Order.desc("importId"));
        update.setMaxResults(1);
        return (Import) update.uniqueResult();
    }

    @Override
    public Import getLastSuccessfulSubscriptionImport() {
        Criteria updateCriteria = getSession().createCriteria(Import.class);
        updateCriteria.add(Restrictions.isNull("errorMessage"));
        updateCriteria.add(Restrictions.isNotNull("oclDateStarted"));
        updateCriteria.addOrder(Order.desc("importId"));
        updateCriteria.setMaxResults(1);

        return (Import) updateCriteria.uniqueResult();
    }

    @Override
    public Boolean isLastImportSuccessful() {

        Import lastSuccessfulSubscriptionImport = getLastSuccessfulSubscriptionImport();
        if (lastSuccessfulSubscriptionImport != null) {
            Import lastUpdate = getLastImport();
            return lastSuccessfulSubscriptionImport.equals(lastUpdate);
        } else {
            return false;
        }
    }

    @Override
    public void ignoreAllErrors(Import anImport) {
        Query query = getSession().createQuery(
                "update OclItem i set i.state = :newState where i.anImport = :anImport and i.state = :oldState");
        query.setParameter("newState", ItemState.IGNORED_ERROR);
        query.setParameter("anImport", anImport);
        query.setParameter("oldState", ItemState.ERROR);
        query.executeUpdate();

        anImport.setErrorMessage(null);
        getSession().saveOrUpdate(anImport);
    }

    @Override
    public void failImport(Import anImport) {
        failImport(anImport, null);
    }

    @Override
    public void failImport(Import update, String errorMessage) {
        update = getImport(update.getImportId());

        if (!StringUtils.isBlank(errorMessage)) {
            update.setErrorMessage(errorMessage);
        } else {
            update.setErrorMessage("Errors found");
        }
        getSession().saveOrUpdate(update);
    }

    /**
     * @should throw IllegalStateException if another update is in progress
     */
    @Override
    public void startImport(Import anImport) {
        Import lastImport = getLastImport();
        if (lastImport != null && !lastImport.isStopped()) {
            throw new IllegalStateException("Cannot start the import, if there is another import in progress.");
        }
        getSession().save(anImport);
    }

    @Override
    public void updateOclDateStarted(Import update, Date oclDateStarted) {
        update.setOclDateStarted(oclDateStarted);
        getSession().save(update);
    }

    @Override
    public void updateReleaseVersion(Import anImport, String version) {
        anImport.setReleaseVersion(version);
        getSession().save(anImport);
    }

    /**
     * @should throw IllegalArgumentException if not scheduled
     * @should throw IllegalStateException if trying to stop twice
     */
    @Override
    public void stopImport(Import anImport) {
        if (anImport.getImportId() == null) {
            throw new IllegalArgumentException("Cannot stop the import, if it has not been started.");
        }
        if (anImport.getLocalDateStopped() != null) {
            throw new IllegalStateException("Cannot stop the import twice.");
        }

        anImport = getImport(anImport.getImportId());

        anImport.stop();

        getSession().saveOrUpdate(anImport);
    }

    @Override
    public Item getLastSuccessfulItemByUrl(String url) {
        Criteria criteria = getSession().createCriteria(Item.class);
        criteria.add(Restrictions.eq("hashedUrl", Item.hashUrl(url)));
        criteria.add(Restrictions.not(Restrictions.eq("state", ItemState.ERROR)));
        criteria.addOrder(Order.desc("itemId"));
        criteria.setMaxResults(1);

        Item item = ((Item) criteria.uniqueResult());
        if (item != null) {
            switch (item.getType()) {
            case MAPPING:
                ConceptMap map = getConceptMapByUuid(item.getUuid());
                if (map == null) {
                    return null;
                }
                break;
            case CONCEPT:
                Concept concept = conceptService.getConceptByUuid(item.getUuid());
                if (concept == null) {
                    return null;
                }
                break;
            default:
                throw new RuntimeException(
                        "Item with UUID=" + item.getUuid() + " couldn't be recognized as Concept or Mapping");
            }
        }
        return item;
    }

    @Override
    public void saveItem(Item item) {
        getSession().saveOrUpdate(item);
    }

    @Override
    public void saveItems(Iterable<? extends Item> items) {
        for (Item item : items) {
            Import update = getImport(item.getAnImport().getImportId());
            item.setAnImport(update); //replace with attached object

            saveItem(item);
        }
    }

    @Override
    public Item getItem(String uuid) {
        Item item = (Item) getSession().createQuery("from OclItem i where i.uuid = :uuid").setString("uuid", uuid)
                .uniqueResult();
        return item;
    }

    @Override
    public Subscription getSubscription() {
        String url = adminService.getGlobalProperty(OpenConceptLabConstants.GP_SUBSCRIPTION_URL);
        if (url == null) {
            return null;
        }
        Subscription subscription = new Subscription();
        subscription.setUrl(url);

        String uuid = adminService.getGlobalProperty(OpenConceptLabConstants.GP_SUBSCRIPTION_UUID);
        subscription.setUuid(uuid);

        String token = adminService.getGlobalProperty(OpenConceptLabConstants.GP_TOKEN);
        subscription.setToken(token);

        String validationType = adminService.getGlobalProperty(OpenConceptLabConstants.GP_VALIDATION_TYPE);
        if (StringUtils.isNotBlank(validationType)) {
            subscription.setValidationType(ValidationType.valueOf(validationType));
        }

        String days = adminService.getGlobalProperty(OpenConceptLabConstants.GP_SCHEDULED_DAYS);
        if (!StringUtils.isBlank(days)) {
            subscription.setDays(Integer.valueOf(days));
        }

        String subscribedToSnapshot = adminService
                .getGlobalProperty(OpenConceptLabConstants.GP_SUBSCRIBED_TO_SNAPSHOT);
        subscription.setSubscribedToSnapshot(Boolean.valueOf(subscribedToSnapshot));

        String time = adminService.getGlobalProperty(OpenConceptLabConstants.GP_SCHEDULED_TIME);
        if (!StringUtils.isBlank(time)) {
            String[] formattedTime = time.split(":");
            if (formattedTime.length != 2) {
                throw new IllegalStateException("Time in the wrong format. Expected 'HH:mm', given: " + time);
            }

            subscription.setHours(Integer.valueOf(formattedTime[0]));
            subscription.setMinutes(Integer.valueOf(formattedTime[1]));
        }

        return subscription;
    }

    private DbSession getSession() {
        return sessionFactory.getCurrentSession();
    }

    @Override
    public void saveSubscription(Subscription subscription) {
        GlobalProperty uuid = adminService.getGlobalPropertyObject(OpenConceptLabConstants.GP_SUBSCRIPTION_UUID);
        if (uuid == null) {
            uuid = new GlobalProperty(OpenConceptLabConstants.GP_SUBSCRIPTION_UUID);
        }
        uuid.setPropertyValue(subscription.getUuid());
        adminService.saveGlobalProperty(uuid);

        GlobalProperty url = adminService.getGlobalPropertyObject(OpenConceptLabConstants.GP_SUBSCRIPTION_URL);
        if (url == null) {
            url = new GlobalProperty(OpenConceptLabConstants.GP_SUBSCRIPTION_URL);
        }
        url.setPropertyValue(prependApiIfAbsent(subscription.getUrl()));
        adminService.saveGlobalProperty(url);

        GlobalProperty token = adminService.getGlobalPropertyObject(OpenConceptLabConstants.GP_TOKEN);
        if (token == null) {
            token = new GlobalProperty(OpenConceptLabConstants.GP_TOKEN);
        }
        token.setPropertyValue(subscription.getToken());
        adminService.saveGlobalProperty(token);

        GlobalProperty validationType = adminService
                .getGlobalPropertyObject(OpenConceptLabConstants.GP_VALIDATION_TYPE);
        if (validationType == null) {
            validationType = new GlobalProperty(OpenConceptLabConstants.GP_VALIDATION_TYPE);
        }
        validationType.setPropertyValue(subscription.getValidationType().name());
        adminService.saveGlobalProperty(validationType);

        GlobalProperty days = adminService.getGlobalPropertyObject(OpenConceptLabConstants.GP_SCHEDULED_DAYS);
        if (days == null) {
            days = new GlobalProperty(OpenConceptLabConstants.GP_SCHEDULED_DAYS);
        }

        if (subscription.getDays() != null) {
            days.setPropertyValue(subscription.getDays().toString());
        } else {
            days.setPropertyValue("");
        }
        adminService.saveGlobalProperty(days);

        GlobalProperty time = adminService.getGlobalPropertyObject(OpenConceptLabConstants.GP_SCHEDULED_TIME);
        if (time == null) {
            time = new GlobalProperty(OpenConceptLabConstants.GP_SCHEDULED_TIME);
        }
        if (subscription.getHours() != null && subscription.getMinutes() != null) {
            time.setPropertyValue(subscription.getHours() + ":" + subscription.getMinutes());
        } else {
            time.setPropertyValue("");
        }
        adminService.saveGlobalProperty(time);

        GlobalProperty subscribedToSnapshot = adminService
                .getGlobalPropertyObject(OpenConceptLabConstants.GP_SUBSCRIBED_TO_SNAPSHOT);
        if (subscribedToSnapshot == null) {
            subscribedToSnapshot = new GlobalProperty(OpenConceptLabConstants.GP_SUBSCRIBED_TO_SNAPSHOT);
        }
        subscribedToSnapshot.setPropertyValue(String.valueOf(subscription.isSubscribedToSnapshot()));
        adminService.saveGlobalProperty(subscribedToSnapshot);

    }

    private String prependApiIfAbsent(String stringUrl) {
        if (StringUtils.isNotBlank(stringUrl)) {
            try {
                URL url = new URL(stringUrl);
                String host = url.getHost();
                if (!host.startsWith("api.")) {
                    return url.toString().replace(host, "api." + host);
                }
                return url.toString();
            } catch (MalformedURLException e) {
                throw new IllegalStateException("Wrong url address");
            }
        } else {
            return stringUrl;
        }
    }

    @Override
    public void unsubscribe() {
        saveSubscription(new Subscription());
        getSession().createQuery("delete from OclItem").executeUpdate();
        getSession().createQuery("delete from OclImport").executeUpdate();
    }

    /**
     * @param anImport the update to be passed
     * @param first starting index
     * @param max maximum limit
     * @return a list of items
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<Item> getImportItems(Import anImport, int first, int max, Set<ItemState> states) {
        Criteria items = getSession().createCriteria(Item.class);
        items.add(Restrictions.eq("anImport", anImport));
        if (!states.isEmpty()) {
            items.add(Restrictions.in("state", states));
        }
        items.addOrder(Order.desc("state"));
        items.setFirstResult(first);
        items.setMaxResults(max);

        return items.list();
    }

    /**
     * @param anImport the update to be passed
     * @param states set of states passed
     * @return a count of items
     */
    @Override
    public Integer getImportItemsCount(Import anImport, Set<ItemState> states) {
        Criteria items = getSession().createCriteria(Item.class);
        items.add(Restrictions.eq("anImport", anImport));
        if (!(states.isEmpty())) {
            items.add(Restrictions.in("state", states));
        }
        return ((Long) items.setProjection(Projections.rowCount()).uniqueResult()).intValue();
    }

    /**
     * @param uuid the uuid to search a concept with
     * @return true if subscribed else false
     */
    @Override
    public Boolean isSubscribedConcept(String uuid) {
        boolean isSubscribed = false;
        Criteria items = getSession().createCriteria(Item.class);
        items.add(Restrictions.eq("type", ItemType.CONCEPT));
        items.add(Restrictions.eq("uuid", uuid));
        if ((Long) (items.setProjection(Projections.rowCount()).uniqueResult()) > 0) {
            isSubscribed = true;
        }

        return isSubscribed;
    }

    @Override
    public ConceptMap getConceptMapByUuid(String uuid) {
        Criteria criteria = getSession().createCriteria(ConceptMap.class);
        criteria.add(Restrictions.eq("uuid", uuid));
        return (ConceptMap) criteria.uniqueResult();
    }

    @Override
    public Concept updateConceptWithoutValidation(Concept concept) {
        getSession().saveOrUpdate(concept);
        return concept;
    }

    @Override
    public ConceptReferenceTerm updateConceptReferenceTermWithoutValidation(ConceptReferenceTerm term) {
        getSession().saveOrUpdate(term);
        return term;
    }

    @Override
    public void updateSubscriptionUrl(Import anImport, String url) {
        anImport.setSubscriptionUrl(url);
        getSession().saveOrUpdate(anImport);
    }

}