com.ethercis.ehr.knowledge.CacheKnowledgeService.java Source code

Java tutorial

Introduction

Here is the source code for com.ethercis.ehr.knowledge.CacheKnowledgeService.java

Source

/*
 * Copyright (c) 2015 Christian Chevalley
 * This file is part of Project Ethercis
 *
 * 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.
 */
//Copyright
package com.ethercis.ehr.knowledge;

import com.ethercis.ehr.json.FlatJsonUtil;
import com.ethercis.ehr.json.JsonUtil;
import com.ethercis.ehr.util.FlatJsonCompositionConverter;
import com.ethercis.ehr.util.I_FlatJsonCompositionConverter;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.openehr.rm.common.generic.PartyIdentified;
import com.ethercis.ehr.building.I_ContentBuilder;
import com.ethercis.ehr.building.util.CompositionAttributesHelper;
import com.ethercis.ehr.building.util.ContextHelper;
import com.ethercis.ehr.encode.CompositionSerializer;
import com.ethercis.ehr.keyvalues.EcisFlattener;
import com.ethercis.logonservice.session.I_SessionManager;
import com.ethercis.servicemanager.annotation.*;
import com.ethercis.servicemanager.cluster.RunTimeSingleton;
import com.ethercis.servicemanager.cluster.ClusterInfo;
import com.ethercis.servicemanager.cluster.I_Info;
import com.ethercis.servicemanager.common.I_SessionClientProperties;
import com.ethercis.servicemanager.common.MetaBuilder;
import com.ethercis.servicemanager.common.def.Constants;
import com.ethercis.servicemanager.common.def.MethodName;
import com.ethercis.servicemanager.common.def.SysErrorCode;
import com.ethercis.servicemanager.exceptions.ServiceManagerException;
import com.ethercis.servicemanager.runlevel.I_ServiceRunMode;
import com.ethercis.servicemanager.service.ServiceInfo;
import org.apache.log4j.Logger;
import org.openehr.rm.common.archetyped.Locatable;
import org.openehr.rm.composition.Composition;
import org.openehr.rm.composition.EventContext;
import org.openehr.rm.support.identification.ObjectVersionID;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import static com.ethercis.ehr.building.util.CompositionAttributesHelper.createComposer;

/**
 * Cache Knowledge Service class
 * <p>
 *     The Cache service scans ADL, OET and OPT resources in specified directories. It either reference
 *     or cache the parse resource according to its configuration. The service parameters are:<br>
 *         <ul>
 *             <li>knowledge.path.archetype : path where archetypes (ADL) are to be search</li>
 *              <li>knowledge.path.template : path for templates (OET)</li>
 *              <li>knowledge.path.opt : path for operational templates (OPT)</li>
 *              <li>knowledge.forcecache : "true|false" specifies if force caching is enabled</li>
 *         </ul>
 *         <br>
 *         The path search is recursive.
 *         forcecache tells the service to parse resources at load time.
 *         The service can be administered with JMX, the following commands are implemented:<br>
 *             <ul>
 *               <li>reload: reload the current caches </li>
 *               <li>statistics: get current statistics in cache</li>
 *               <li>showArchetypes: get the list of current archetypes</li>
 *               <li>showTemplates: get the list of templates</li>
 *               <li>showOPT: get the list of operational templates</li>
 *               <li>setForceCache (true|false): enable/disable force caching on reload</li>
 *               <li>settings: show the current service settings</li>
 *               <li>errors: display the faulty openEhr objects detected at load time</li>
 *             </ul>
 * </p>
 */
@Service(id = "CacheKnowledgeService", version = "1.0", system = true)

@RunLevelActions(value = { @RunLevelAction(onStartupRunlevel = 9, sequence = 1, action = "LOAD"),
        @RunLevelAction(onShutdownRunlevel = 9, sequence = 1, action = "STOP") })

public class CacheKnowledgeService extends ClusterInfo
        implements I_CacheKnowledgeService, CacheKnowledgeServiceMBean {

    private String ME = "CacheKnowledgeService";
    private String version = "1.0";
    private Logger log = Logger.getLogger(ME);
    private RunTimeSingleton global;
    private I_KnowledgeCache cache;
    private ServiceInfo serviceInfo = null; //used for JMX reload()

    public CacheKnowledgeService() {

    }

    /* (non-Javadoc)
     * @see com.ethercis.ehr.cache.I_ResourceService#getKnowledgeCache()
     */
    @Override
    public I_KnowledgeCache getKnowledgeCache() {
        return cache;
    }

    @Override
    protected void doInit(RunTimeSingleton global, ServiceInfo serviceInfo) throws ServiceManagerException {
        log.info("Starting " + ME + " version=" + version);
        this.global = global;
        this.serviceInfo = serviceInfo;

        //initialize the ArchetypeRepository controller
        try {
            this.cache = new KnowledgeCache(global.getProperty().getProperties(), serviceInfo.getParameters());
        } catch (Exception e) {
            throw new ServiceManagerException(global, SysErrorCode.INTERNAL_ILLEGALARGUMENT, ME,
                    "Severe error while loading cache:" + e);
        }

        putObject(I_Info.JMX_PREFIX + ME, this);

        log.info(ME + " successfully started");
        log.info("Statistics:\n" + statistics());
    }

    @QuerySetting(dialect = {
            @QuerySyntax(mode = I_ServiceRunMode.DialectSpace.STANDARD, httpMethod = "GET", method = "get", path = "vehr/template", responseType = ResponseType.Json),
            @QuerySyntax(mode = I_ServiceRunMode.DialectSpace.EHRSCAPE, httpMethod = "GET", method = "get", path = "rest/v1/template", responseType = ResponseType.Json) })
    public Object retrieve(I_SessionClientProperties props) throws ServiceManagerException {

        try {
            Map retmap = this.getKnowledgeCache().listOperationalTemplates();
            if (retmap.size() == 0) {
                global.getProperty().set(MethodName.RETURN_TYPE_PROPERTY, "" + MethodName.RETURN_NO_CONTENT);
                //build the relative part of the link to the existing last version
                Map<String, Object> retMap = new HashMap<>();
                retMap.put("Reason", "No templates");
                return retMap;
            }
            Map<String, Map<String, String>> metaref = MetaBuilder.add2MetaMap(null, "href", Constants.URI_TAG);
            retmap.putAll(metaref);
            return retmap;
        } catch (IOException e) {
            throw new ServiceManagerException(global, SysErrorCode.INTERNAL_ILLEGALARGUMENT, ME,
                    "Could not generate templates list, reason:" + e);
        }
    }

    @QuerySetting(dialect = {
            @QuerySyntax(mode = I_ServiceRunMode.DialectSpace.STANDARD, httpMethod = "GET", method = "get", path = "vehr/template/example", responseType = ResponseType.Json),
            @QuerySyntax(mode = I_ServiceRunMode.DialectSpace.EHRSCAPE, httpMethod = "GET", method = "get", path = "rest/v1/template/example", responseType = ResponseType.Json) })
    public Object example(I_SessionClientProperties props) throws ServiceManagerException {

        String templateId = props.getClientProperty(I_CacheKnowledgeService.TEMPLATE_ID, (String) null);
        String format = props.getClientProperty(I_CacheKnowledgeService.FORMAT, "XML");

        if (templateId == null)
            throw new ServiceManagerException(global, SysErrorCode.INTERNAL_ILLEGALARGUMENT, ME,
                    "No template Id give (templateId missing)");

        Object retObj = null;

        try {
            I_ContentBuilder contentBuilder = I_ContentBuilder.getInstance(null, I_ContentBuilder.OPT,
                    this.getKnowledgeCache(), templateId);

            Object generated = contentBuilder.generate();

            if (generated == null)
                throw new ServiceManagerException(global, SysErrorCode.INTERNAL_ILLEGALARGUMENT, ME,
                        "Could not generate an example for template Id:" + templateId);

            if (generated instanceof Composition) {
                EventContext context = ContextHelper.createDummyContext();
                PartyIdentified partyIdentified = CompositionAttributesHelper.createComposer("Composer", "ETHERCIS",
                        "1234-5678");

                ((Composition) generated).setContext(context);
                ((Composition) generated).setComposer(partyIdentified);
                ((Composition) generated)
                        .setUid(new ObjectVersionID(UUID.randomUUID() + "::example.ethercis.com::1"));

                switch (format) {
                case "XML":
                    global.getProperty().set(MethodName.RETURN_TYPE_PROPERTY, "" + MethodName.RETURN_XML);
                    byte[] exportXml = contentBuilder.exportCanonicalXML((Composition) generated, true, true);
                    if (exportXml == null)
                        throw new ServiceManagerException(global, SysErrorCode.INTERNAL_ILLEGALARGUMENT, ME,
                                "Could not export an example for template Id:" + templateId);
                    retObj = new String(exportXml);
                    break;
                case "ECISFLAT":
                    global.getProperty().set(MethodName.RETURN_TYPE_PROPERTY, "" + MethodName.RETURN_STRING);
                    Map<String, String> testRetMap = EcisFlattener.renderFlat((Composition) generated, true,
                            CompositionSerializer.WalkerOutputMode.PATH);
                    GsonBuilder builder = new GsonBuilder();
                    Gson gson = builder.setPrettyPrinting().disableHtmlEscaping().create();
                    String jsonString = gson.toJson(testRetMap);
                    retObj = jsonString;
                    break;
                case "FLAT":
                    global.getProperty().set(MethodName.RETURN_TYPE_PROPERTY, "" + MethodName.RETURN_STRING);
                    I_FlatJsonCompositionConverter flatJsonCompositionConverter = FlatJsonCompositionConverter
                            .getInstance(cache);
                    Map<String, Object> retMap = flatJsonCompositionConverter.fromComposition(templateId,
                            (Composition) generated, true);
                    jsonString = JsonUtil.toJsonString(retMap);
                    retObj = jsonString;
                    break;
                }
            } else if (generated instanceof Locatable) {
                switch (format) {
                case "XML":
                    global.getProperty().set(MethodName.RETURN_TYPE_PROPERTY, "" + MethodName.RETURN_XML);
                    byte[] exportXml = contentBuilder.exportCanonicalXML((Locatable) generated, true, true);
                    if (exportXml == null)
                        throw new ServiceManagerException(global, SysErrorCode.INTERNAL_ILLEGALARGUMENT, ME,
                                "Could not export an example for template Id:" + templateId);
                    retObj = new String(exportXml);
                    break;
                case "ECISFLAT":
                    global.getProperty().set(MethodName.RETURN_TYPE_PROPERTY, "" + MethodName.RETURN_JSON);
                    Map<String, String> testRetMap = EcisFlattener.renderFlat((Locatable) generated, true,
                            CompositionSerializer.WalkerOutputMode.PATH);

                    GsonBuilder builder = new GsonBuilder();
                    Gson gson = builder.setPrettyPrinting().disableHtmlEscaping().create();

                    String jsonString = gson.toJson(testRetMap);

                    retObj = jsonString;
                    break;

                }
            }
        } catch (Exception e) {
            throw new ServiceManagerException(global, SysErrorCode.INTERNAL_ILLEGALARGUMENT, ME,
                    "Could not generate templates list, reason:" + e);
        }
        return retObj;
    }

    @QuerySetting(dialect = {
            @QuerySyntax(mode = I_ServiceRunMode.DialectSpace.STANDARD, httpMethod = "GET", method = "create", path = "vehr/template", responseType = ResponseType.Json),
            @QuerySyntax(mode = I_ServiceRunMode.DialectSpace.EHRSCAPE, httpMethod = "POST", method = "post", path = "rest/v1/template", responseType = ResponseType.Json) })
    public Object create(I_SessionClientProperties props) throws Exception {

        //get body stuff
        String content = props.getClientProperty(Constants.REQUEST_CONTENT, (String) null);

        String templateId;
        try {
            templateId = this.getKnowledgeCache().addOperationalTemplate(content.getBytes());
        } catch (Exception e) {
            throw new ServiceManagerException(global, SysErrorCode.USER_ILLEGALARGUMENT, ME,
                    "Could not add template, reason:" + e);
        }

        Map<String, Object> retmap = new HashMap<>();
        retmap.put("action", "CREATE");
        retmap.put("templateId", templateId);
        Map<String, Map<String, String>> metaref = MetaBuilder.add2MetaMap(null, "href", Constants.URI_TAG);
        retmap.putAll(metaref);
        return retmap;
    }

    @Override
    public String usage() {
        StringBuffer sb = new StringBuffer();

        sb.append(ME + " version:" + version + "\n");
        sb.append("Available commands:\n");
        sb.append("reload: reload the current caches\n");
        sb.append("statistics: get current statistics in cache\n");
        sb.append("showArchetypes: get the list of current archetypes\n");
        sb.append("showTemplates: get the list of templates=\n");
        sb.append("showOPT: get the list of operational templates\n");
        sb.append("setForceCache (true|false): enable/disable force caching on reload\n");
        sb.append("settings: show the current service settings\n");
        sb.append("errors: display the faulty openEhr objects detected at load time\n");
        return sb.toString();
    }

    @Override
    public String reload() {
        try {
            if (serviceInfo != null && serviceInfo.getParameters().size() > 0)
                this.cache = new KnowledgeCache(global.getProperty().getProperties(), serviceInfo.getParameters());
            else
                this.cache = new KnowledgeCache(global.getProperty().getProperties(), null); //assume from environment
        } catch (Exception e) {
            return "Could not reload cache with exception:" + e;
        }
        return "Reload successfully done\n";
    }

    @Override
    public String statistics() {
        return cache.statistics();
    }

    @Override
    public String showArcheypes() {
        return cache.archeypesList();
    }

    @Override
    public String showTemplates() {
        return cache.oetList();
    }

    @Override
    public String showOPT() {
        return cache.optList();
    }

    @Override
    public String setForceCache(boolean set) {
        cache.setForceCache(set);
        return "Force Cache is now " + (set ? "enabled\n" : "disabled\n");
    }

    @Override
    public String settings() {
        return cache.settings();
    }

    @Override
    public String errors() {
        return cache.processingErrors();
    }
}