eu.itesla_project.offline.server.OfflineApplicationMock.java Source code

Java tutorial

Introduction

Here is the source code for eu.itesla_project.offline.server.OfflineApplicationMock.java

Source

/**
 * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium)
 * 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/.
 */
package eu.itesla_project.offline.server;

import eu.itesla_project.modules.histo.HistoDbAttr;
import eu.itesla_project.modules.histo.HistoDbMetaAttributeId;
import eu.itesla_project.modules.histo.HistoDbMetaAttributeType;
import eu.itesla_project.modules.histo.HistoDbNetworkAttributeId;
import eu.itesla_project.modules.offline.OfflineTaskStatus;
import eu.itesla_project.modules.offline.OfflineTaskType;
import eu.itesla_project.modules.offline.OfflineWorkflowCreationParameters;
import eu.itesla_project.modules.offline.SecurityIndexSynthesis;
import eu.itesla_project.modules.rules.*;
import eu.itesla_project.modules.rules.expr.*;
import eu.itesla_project.simulation.securityindexes.SecurityIndexId;
import eu.itesla_project.simulation.securityindexes.SecurityIndexType;
import eu.itesla_project.offline.*;
import eu.itesla_project.offline.monitoring.BusyCoresSeries;
import org.joda.time.DateTime;
import org.joda.time.Interval;

import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
 */
public class OfflineApplicationMock implements RemoteOfflineApplication {

    private class Notifier implements OfflineApplicationListener {

        public final Collection<OfflineApplicationListener> listeners = Collections
                .synchronizedCollection(new ArrayList<OfflineApplicationListener>());

        public void addListener(OfflineApplicationListener l) {
            listeners.add(l);
        }

        public void removeListener(OfflineApplicationListener l) {
            listeners.remove(l);
        }

        @Override
        public void onWorkflowCreation(OfflineWorkflowStatus status) {
            for (OfflineApplicationListener l : listeners) {
                l.onWorkflowCreation(status);
            }
        }

        @Override
        public void onWorkflowRemoval(String workflowId) {
            for (OfflineApplicationListener l : listeners) {
                l.onWorkflowRemoval(workflowId);
            }
        }

        @Override
        public void onBusyCoresUpdate(BusyCoresSeries busyCoresSeries) {
            for (OfflineApplicationListener l : listeners) {
                l.onBusyCoresUpdate(busyCoresSeries);
            }
        }

        @Override
        public void onWorkflowStatusChange(OfflineWorkflowStatus status) {
            for (OfflineApplicationListener l : listeners) {
                l.onWorkflowStatusChange(status);
            }
        }

        @Override
        public void onWorkflowListChange(Collection<OfflineWorkflowStatus> statuses) {
            for (OfflineApplicationListener l : listeners) {
                l.onWorkflowListChange(statuses);
            }
        }

        @Override
        public void onSamplesChange(String workflowId, Collection<SampleSynthesis> samples) {
            for (OfflineApplicationListener l : listeners) {
                l.onSamplesChange(workflowId, samples);
            }
        }

        @Override
        public void onSecurityIndexesChange(String workflowId, SecurityIndexSynthesis synthesis) {
            for (OfflineApplicationListener l : listeners) {
                l.onSecurityIndexesChange(workflowId, synthesis);
            }
        }

        @Override
        public void onSecurityRulesChange(String workflowId, Collection<RuleId> ruleIds) {
            for (OfflineApplicationListener l : listeners) {
                l.onSecurityRulesChange(workflowId, ruleIds);
            }
        }

        @Override
        public void onSecurityRulesProgress(String workflowId, Float progress) {
            for (OfflineApplicationListener l : listeners) {
                l.onSecurityRulesProgress(workflowId, progress);
            }
        }

        @Override
        public void onSecurityRuleDescription(String workflowId, SecurityRule rule) {
            for (OfflineApplicationListener l : listeners) {
                l.onSecurityRuleDescription(workflowId, rule);
            }
        }
    };

    private final Notifier notify = new Notifier();

    private class OfflineWorkflowRandom extends Random {
        private SecurityIndexType nextSecurityIndexType() {
            return SecurityIndexType.values()[random.nextInt(SecurityIndexType.values().length)];
        }

        private RuleAttributeSet nextRuleAttributeSet() {
            return RuleAttributeSet.values()[random.nextInt(RuleAttributeSet.values().length)];
        }

        private HistoDbAttr nextHistoDbAttr() {
            return HistoDbAttr.values()[random.nextInt(HistoDbAttr.values().length)];
        }

        private HistoDbNetworkAttributeId nextHistoDbNetworkAttributeId() {
            return new HistoDbNetworkAttributeId("equipment-" + nextInt(), nextHistoDbAttr());
        }

        private ComparisonOperator.Type nextComparisonOperatorType() {
            return ComparisonOperator.Type.values()[random.nextInt(ComparisonOperator.Type.values().length)];
        }
    }

    private final static int AVAILABLE_CORES = 48;

    private class OfflineWorkflowMock implements OfflineWorkflow {

        private final String id;

        private final OfflineWorkflowCreationParameters creationParameters;

        private final SecurityIndexSynthesis securityIndexSynthesis = new SecurityIndexSynthesis();

        private final Map<RuleId, SecurityRuleExpression> securityRules = new HashMap<>();

        private OfflineWorkflowStartParameters startParameters;

        private long endsTime;

        private boolean running = false;

        private boolean computing = false;

        private float computingProgress = 0;

        private int sampleIdx = -1;

        private int taskIdx = 0;

        private OfflineWorkflowMock(String id, OfflineWorkflowCreationParameters creationParameters) {
            this.id = id;
            this.creationParameters = creationParameters;
            securityIndexSynthesis.addSecurityIndex(new SecurityIndexId("LINE1", SecurityIndexType.OVERLOAD), true);
            securityIndexSynthesis.addSecurityIndex(new SecurityIndexId("LINE1", SecurityIndexType.OVERLOAD), true);
            securityIndexSynthesis.addSecurityIndex(new SecurityIndexId("LINE1", SecurityIndexType.OVERLOAD),
                    false);
            securityIndexSynthesis.addSecurityIndex(new SecurityIndexId("LINE1", SecurityIndexType.TSO_FREQUENCY),
                    true);
            computeSecurityRules(100);
        }

        private void change() {
            boolean notifyStatusChange = false;
            if (running) {
                if (System.currentTimeMillis() > endsTime) {
                    running = false;
                }
                if (sampleIdx == -1) {
                    sampleIdx = 0;
                }
                taskIdx++;
                if (taskIdx >= OfflineTaskType.values().length) {
                    sampleIdx++;
                    taskIdx = 0;
                }
                notifySampleSynthesisChange();
                notifySecurityIndexesSynthesisChange();
                notifyStatusChange = true;
            }
            if (computing) {
                if (computingProgress >= 1) {
                    computing = false;
                    notify.onSecurityRulesChange(id, securityRules.keySet());
                } else {
                    computeSecurityRules(10);
                }
                computingProgress += .1f;
                notify.onSecurityRulesProgress(id, computingProgress);
                notifyStatusChange = true;
            }
            if (notifyStatusChange)
                notify.onWorkflowStatusChange(this.getStatus());
        }

        private void notifySampleSynthesisChange() {
            if (sampleIdx >= 0) {
                SampleSynthesis ss = new SampleSynthesis(sampleIdx,
                        new OfflineTaskEvent(OfflineTaskType.values()[taskIdx], OfflineTaskStatus.SUCCEED, null));
                notify.onSamplesChange(id, Collections.singleton(ss));
            }
        }

        private void notifySecurityIndexesSynthesisChange() {
            if (securityIndexSynthesis != null) {
                notify.onSecurityIndexesChange(id, securityIndexSynthesis);
            }
        }

        @Override
        public String getId() {
            return id;
        }

        @Override
        public void start(OfflineWorkflowStartParameters startParameters) throws Exception {
            this.startParameters = startParameters;
            endsTime = System.currentTimeMillis() + startParameters.getDuration() * 60 * 1000;
            running = true;
        }

        @Override
        public void stop() {
            running = false;
        }

        @Override
        public void computeSecurityRules() throws Exception {
            computingProgress = 0;
            computing = true;
        }

        @Override
        public OfflineWorkflowStatus getStatus() {
            if (running) {
                return new OfflineWorkflowStatus(id, OfflineWorkflowStep.SAMPLING, creationParameters,
                        startParameters);
            } else if (computing) {
                return new OfflineWorkflowStatus(id, OfflineWorkflowStep.SECURITY_RULES_COMPUTATION,
                        creationParameters);
            } else {
                return new OfflineWorkflowStatus(id, OfflineWorkflowStep.IDLE, creationParameters);
            }
        }

        @Override
        public OfflineWorkflowCreationParameters getCreationParameters() {
            return creationParameters;
        }

        @Override
        public void addListener(OfflineWorkflowListener listener) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }

        @Override
        public void removeListener(OfflineWorkflowListener listener) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }

        @Override
        public void addSynthesisListener(OfflineWorkflowSynthesisListener listener) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }

        @Override
        public void removeSynthesisListener(OfflineWorkflowSynthesisListener listener) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }

        private void computeSecurityRules(int count) {
            int size = securityRules.size();
            for (int i = size; i < (size + count); i++) {
                String contingencyId = "contingency-" + i;
                SecurityIndexType securityIndexType = random.nextSecurityIndexType();
                SecurityIndexId securityIndexId = new SecurityIndexId(contingencyId, securityIndexType);
                RuleAttributeSet ruleAttributeSet = random.nextRuleAttributeSet();
                RuleId ruleId = new RuleId(ruleAttributeSet, securityIndexId);

                SecurityRuleStatus securityRuleStatus = SecurityRuleStatus.values()[random
                        .nextInt(SecurityRuleStatus.values().length)];
                ExpressionNode condition = null;
                switch (securityRuleStatus) {
                case SECURE_IF: {
                    ComparisonOperator condition1 = new ComparisonOperator(
                            new Attribute(new HistoDbMetaAttributeId(HistoDbMetaAttributeType.values()[random
                                    .nextInt(HistoDbMetaAttributeType.values().length)])),
                            new Litteral(random.nextDouble()), random.nextComparisonOperatorType());
                    ComparisonOperator condition2 = new ComparisonOperator(
                            new Attribute(new HistoDbMetaAttributeId(HistoDbMetaAttributeType.values()[random
                                    .nextInt(HistoDbMetaAttributeType.values().length)])),
                            new Litteral(random.nextDouble()), random.nextComparisonOperatorType());
                    ComparisonOperator condition3 = new ComparisonOperator(
                            new Attribute(random.nextHistoDbNetworkAttributeId()),
                            new Litteral(random.nextDouble()), random.nextComparisonOperatorType());
                    AndOperator and = new AndOperator(condition1, condition2);
                    condition = new OrOperator(and, condition3);
                    break;
                }
                case ALWAYS_SECURE:
                case ALWAYS_UNSECURE:
                default:
                    break;
                }
                SecurityRuleExpression securityRuleExpression = new SecurityRuleExpression(ruleId,
                        securityRuleStatus, condition);
                securityRules.put(ruleId, securityRuleExpression);
            }
        }

        @Override
        public void notifySynthesisListeners() {
        }
    }

    private final Map<String, OfflineWorkflowMock> workflows = Collections
            .synchronizedMap(new LinkedHashMap<String, OfflineWorkflowMock>());

    private final ScheduledFuture<?> future;

    private final BusyCoresSeries busyCores = new BusyCoresSeries(AVAILABLE_CORES);

    private final OfflineWorkflowRandom random = new OfflineWorkflowRandom();

    private final AtomicInteger workflowIndex = new AtomicInteger();

    public OfflineApplicationMock(ScheduledExecutorService ses) {
        future = ses.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                int value;
                if (busyCores.getValues().isEmpty()) {
                    value = 0;
                } else {
                    int inc = (int) (random.nextDouble() * 10) - 5;
                    value = busyCores.getValues().get(busyCores.getValues().size() - 1).getBusyCores() + inc;
                    if (value < 0) {
                        value = 0;
                    }
                    if (value > AVAILABLE_CORES) {
                        value = AVAILABLE_CORES;
                    }
                }
                busyCores.addValue(new BusyCoresSeries.Value(value));

                notify.onBusyCoresUpdate(busyCores);

                for (OfflineWorkflowMock workflow : workflows.values()) {
                    workflow.change();
                }
            }
        }, 0, 2, TimeUnit.SECONDS);
    }

    @Override
    public boolean isConnected() {
        return true;
    }

    @Override
    public Map<String, OfflineWorkflowStatus> listWorkflows() {
        Map<String, OfflineWorkflowStatus> statuses = new HashMap<>();
        for (OfflineWorkflowMock workflow : workflows.values()) {
            statuses.put(workflow.id,
                    new OfflineWorkflowStatus(workflow.id, OfflineWorkflowStep.SAMPLING,
                            new OfflineWorkflowCreationParameters(new HashSet(), new DateTime(),
                                    new Interval(0, 100000), false, false)));
        }
        return statuses;
    }

    @Override
    public String createWorkflow(String workflowId, OfflineWorkflowCreationParameters parameters) {
        String workflowId2 = workflowId != null ? workflowId : "test-" + workflowIndex.getAndIncrement();
        OfflineWorkflowMock workflow = new OfflineWorkflowMock(workflowId2, parameters);
        workflows.put(workflowId2, workflow);
        notify.onWorkflowCreation(workflow.getStatus());
        return workflowId2;
    }

    @Override
    public OfflineWorkflowCreationParameters getWorkflowParameters(String workflowId) {
        return OfflineWorkflowCreationParameters.load();
    }

    @Override
    public void removeWorkflow(String workflowId) {
        workflows.remove(workflowId);
        notify.onWorkflowRemoval(workflowId);
    }

    @Override
    public void startWorkflow(String workflowId, OfflineWorkflowStartParameters startParameters) {
        OfflineWorkflowMock workflow = workflows.get(workflowId);
        try {
            workflow.start(startParameters);
            notify.onWorkflowStatusChange(workflow.getStatus());
        } catch (Exception ex) {
            Logger.getLogger(OfflineApplicationMock.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void stopWorkflow(String workflowId) {
        OfflineWorkflowMock workflow = workflows.get(workflowId);
        workflow.stop();
        notify.onWorkflowStatusChange(workflow.getStatus());
    }

    @Override
    public void computeSecurityRules(String workflowId) {
        OfflineWorkflowMock workflow = workflows.get(workflowId);
        workflow.securityRules.clear();
        workflow.computing = true;
        notify.onWorkflowStatusChange(workflow.getStatus());
    }

    @Override
    public SecurityIndexSynthesis getSecurityIndexesSynthesis(String workflowId) {
        OfflineWorkflowMock workflow = workflows.get(workflowId);
        return workflow.securityIndexSynthesis;
    }

    @Override
    public void addListener(OfflineApplicationListener l) {
        notify.addListener(l);
    }

    @Override
    public void removeListener(OfflineApplicationListener l) {
        notify.removeListener(l);
    }

    @Override
    public void refreshAll() {
        List<OfflineWorkflowStatus> workflowStatuses = new ArrayList<>(workflows.size());
        for (Map.Entry<String, OfflineWorkflowMock> entry : workflows.entrySet()) {
            OfflineWorkflowMock workflowMock = entry.getValue();
            workflowStatuses.add(workflowMock.getStatus());
        }
        notify.onWorkflowListChange(workflowStatuses);
        for (Map.Entry<String, OfflineWorkflowMock> entry : workflows.entrySet()) {
            OfflineWorkflowMock workflow = entry.getValue();
            notify.onWorkflowStatusChange(workflow.getStatus());
            workflow.notifySampleSynthesisChange();
            workflow.notifySecurityIndexesSynthesisChange();
            getSecurityRules(workflow.getId());
        }
    }

    @Override
    public void stopApplication() {
    }

    @Override
    public void close() throws Exception {
        future.cancel(true);
    }

    @Override
    public void getSecurityRules(String workflowId) {
        OfflineWorkflowMock workflow = workflows.get(workflowId);
        notify.onSecurityRulesChange(workflow.getId(), workflow.securityRules.keySet());
    }

    @Override
    public SecurityRuleExpression getSecurityRuleExpression(String workflowId, RuleId ruleId) {
        OfflineWorkflowMock workflow = workflows.get(workflowId);
        return workflow.securityRules.get(ruleId);
    }
}