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

com.centurylink.mdw.service.data.process.ProcessCache Maven / Gradle / Ivy

/*
 * Copyright (C) 2017 CenturyLink, Inc.
 *
 * 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 com.centurylink.mdw.service.data.process;

import com.centurylink.mdw.cache.CacheService;
import com.centurylink.mdw.cache.asset.AssetCache;
import com.centurylink.mdw.dataaccess.DataAccessException;
import com.centurylink.mdw.model.JsonObject;
import com.centurylink.mdw.model.Jsonable;
import com.centurylink.mdw.model.asset.Asset;
import com.centurylink.mdw.model.asset.AssetVersionSpec;
import com.centurylink.mdw.model.variable.Document;
import com.centurylink.mdw.model.workflow.Activity;
import com.centurylink.mdw.model.workflow.Process;
import com.centurylink.mdw.service.data.WorkflowDataAccess;
import com.centurylink.mdw.services.cache.CacheRegistration;
import com.centurylink.mdw.util.log.LoggerUtil;
import com.centurylink.mdw.util.log.StandardLogger;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.centurylink.mdw.constant.WorkAttributeConstant.MONITORS;

/**
 * Lazily loads the Processes for use by the RuntimeEngine.
 */
public class ProcessCache implements CacheService {

    private static StandardLogger logger = LoggerUtil.getStandardLogger();

    private static List allProcesses;
    private static final Map allById = new ConcurrentHashMap<>();
    private static List latestProcesses;
    private static final Map latestByPath = new ConcurrentHashMap<>();

    private ProcessCache() {
    }

    static {
        new CacheRegistration().registerCache("ProcessCache", new ProcessCache());
    }

    public void clearCache() {
        synchronized(ProcessCache.class) {
            allProcesses = null;
            allById.clear();
            latestProcesses = null;
            latestByPath.clear();
        }
    }

    public void refreshCache() {
        clearCache();
    }

    public static synchronized List getProcesses(boolean withArchived) {
        if (withArchived) {
            if (allProcesses == null)
                allProcesses = loadProcesses(true);
            return allProcesses;
        }
        else {
            if (latestProcesses == null)
                latestProcesses = loadProcesses(false);
            return latestProcesses;
        }
    }

    public static Process getProcess(Long id) throws IOException {
        Process process = allById.get(id);
        if (process == null) {
            synchronized (ProcessCache.class) {
                process = allById.get(id);
                if (process == null) {
                    for (Process proc : getProcesses(true)) {
                        if (proc.getId().equals(id)) {
                            process = proc;
                            if (!process.isLoaded()) {
                                process = loadProcess(process);
                                Process latest = getProcess(process.getPath());
                                // latest is null if process has been deleted
                                if (latest != null && latest.getVersion() != process.getVersion()) {
                                    // old processes use latest monitor config
                                    applyMonitors(process);
                                }
                            }
                            allById.put(process.getId(), process);
                            break;
                        }
                    }
                }
            }
        }
        return process;
    }

    public static Process getProcess(String path) {
        if (!path.endsWith(".proc"))
            path += ".proc";
        Process process = latestByPath.get(path);
        if (process == null) {
            synchronized (ProcessCache.class) {
                process = latestByPath.get(path);
                if (process == null) {
                    for (Process proc : getProcesses(false)) {
                        if (proc.getPath().equals(path)) {
                            process = proc;
                            latestByPath.put(process.getPath(), process);
                            break;
                        }
                    }
                }
            }
        }
        return process;
    }

    public static Process getProcessSmart(AssetVersionSpec spec) throws IOException {
        if (!spec.getPath().endsWith(".proc"))
            spec = new AssetVersionSpec(spec.getPath() + ".proc", spec.getVersion());
        Asset asset = AssetCache.getAsset(spec);
        return asset == null ? null : getProcess(asset.getId());
    }

    public static Process getProcess(String path, int version) throws IOException {
        if (!path.endsWith(".proc"))
            path += ".proc";
        Asset asset = AssetCache.getAsset(path, version);
        return asset == null ? null : getProcess(asset.getId());
    }

    /**
     * Archived are unloaded processes.
     */
    private static List loadProcesses(boolean withArchived) {
        List processes = new ArrayList<>();
        for (Asset asset : AssetCache.getAssets("proc", withArchived)) {
            String name = asset.getName().substring(0, asset.getName().length() - 5);
            Process process = new Process(asset.getId(), name, asset.getPackageName(), asset.getVersion());
            if (!processes.contains(process)) {
                if (!withArchived && !process.isLoaded()) {
                    // latest processes are always loaded (and their monitors are verbatim)
                    try {
                        process = loadProcess(process);
                    }
                    catch (Exception ex) {
                        logger.error("Cannot load process: " + process.getLabel(), ex);
                    }
                }
                processes.add(process);
            }
        }
        Collections.sort(processes);
        return processes;
    }

    private static Process loadProcess(Asset asset) throws IOException {
        Asset loadedAsset = AssetCache.getAsset(asset.getId());
        Process process = Process.fromString(loadedAsset.getText());
        process.setId(loadedAsset.getId());
        process.setName(loadedAsset.getName().substring(0, loadedAsset.getName().length() - 5));
        process.setVersion(loadedAsset.getVersion());
        process.setPackageName(loadedAsset.getPackageName());
        process.setFile(loadedAsset.getFile());
        process.setArchived(loadedAsset.isArchived());
        return process;
    }

    /**
     * Monitors for archived processes are taken from latest process definition.
     * If process has been deleted, monitors are removed from archived.
     */
    private static void applyMonitors(Process process) {
        Process latestProcess = getProcess(process.getPath());
        if (latestProcess == null || latestProcess.getVersion() != process.getVersion()) {
            // apply monitors from latest process/activities
            process.setAttribute(MONITORS, latestProcess == null ? null : latestProcess.getAttribute(MONITORS));
            for (Activity activity : process.getActivities()) {
                Activity latestActivity = latestProcess == null ? null : latestProcess.getActivity(activity.getId());
                activity.setAttribute(MONITORS, latestActivity == null ? null : latestActivity.getAttribute(MONITORS));
            }
        }
    }

    public static Process getInstanceDefinition(Long processId, Long instanceDefinitionId) {
        try {
            Process procdef = getProcess(processId);
            if (procdef != null) {
                Document instanceDoc = new WorkflowDataAccess().getDocument(instanceDefinitionId);
                String content = instanceDoc.getContent(null);
                Process process = null;
                if (Jsonable.class.getName().equals(instanceDoc.getType())) {
                    // compatibility for previously-saved instances
                    JsonObject json = new JsonObject(content);
                    for (String key : json.keySet()) {
                        if (!"_type".equals(key)) {
                            process = new Process(json.getJSONObject(key));
                            break;
                        }
                    }
                }
                else {
                    process = Process.fromString(content);
                }
                if (process != null) {
                    process.setName(procdef.getName());
                    process.setPackageName(procdef.getPackageName());
                }
                return process;
            }
        }
        catch (DataAccessException | IOException ex) {
            logger.error("Error retrieving instance document: " + instanceDefinitionId, ex);
        }
        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy