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

org.integratedmodelling.engine.modelling.runtime.DirectObservation Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (C) 2007, 2015:
 * 
 * - Ferdinando Villa  - integratedmodelling.org - any
 * other authors listed in @author annotations
 *
 * All rights reserved. This file is part of the k.LAB software suite, meant to enable
 * modular, collaborative, integrated development of interoperable data and model
 * components. For details, see http://integratedmodelling.org.
 * 
 * This program is free software; you can redistribute it and/or modify it under the terms
 * of the Affero General Public License Version 3 or any later version.
 *
 * This program is distributed in the hope that it will be useful, but without any
 * warranty; without even the implied warranty of merchantability or fitness for a
 * particular purpose. See the Affero General Public License for more details.
 * 
 * You should have received a copy of the Affero General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite
 * 330, Boston, MA 02111-1307, USA. The license is also available at:
 * https://www.gnu.org/licenses/agpl.html
 *******************************************************************************/
package org.integratedmodelling.engine.modelling.runtime;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.integratedmodelling.api.knowledge.IConcept;
import org.integratedmodelling.api.knowledge.IObservation;
import org.integratedmodelling.api.knowledge.IProperty;
import org.integratedmodelling.api.knowledge.ISemantic;
import org.integratedmodelling.api.metadata.IMetadata;
import org.integratedmodelling.api.modelling.IAction;
import org.integratedmodelling.api.modelling.IActiveDirectObservation;
import org.integratedmodelling.api.modelling.IActiveEvent;
import org.integratedmodelling.api.modelling.IActiveProcess;
import org.integratedmodelling.api.modelling.IActiveRelationship;
import org.integratedmodelling.api.modelling.IActiveSubject;
import org.integratedmodelling.api.modelling.ICoverage;
import org.integratedmodelling.api.modelling.IDirectObservation;
import org.integratedmodelling.api.modelling.IEvent;
import org.integratedmodelling.api.modelling.IModel;
import org.integratedmodelling.api.modelling.INamespace;
import org.integratedmodelling.api.modelling.IObservableSemantics;
import org.integratedmodelling.api.modelling.IProcess;
import org.integratedmodelling.api.modelling.IRelationship;
import org.integratedmodelling.api.modelling.IScale;
import org.integratedmodelling.api.modelling.IState;
import org.integratedmodelling.api.modelling.ISubject;
import org.integratedmodelling.api.modelling.agents.IAgentState;
import org.integratedmodelling.api.modelling.agents.ICollision;
import org.integratedmodelling.api.modelling.agents.IObservationController;
import org.integratedmodelling.api.modelling.agents.IObservationGraphNode;
import org.integratedmodelling.api.modelling.resolution.IResolutionScope;
import org.integratedmodelling.api.modelling.scheduling.ITransition;
import org.integratedmodelling.api.monitoring.IMonitor;
import org.integratedmodelling.api.provenance.IProvenance;
import org.integratedmodelling.api.runtime.IContext;
import org.integratedmodelling.api.time.ITemporalExtent;
import org.integratedmodelling.api.time.ITimePeriod;
import org.integratedmodelling.collections.Pair;
import org.integratedmodelling.common.beans.State;
import org.integratedmodelling.common.beans.responses.LocalExportResponse;
import org.integratedmodelling.common.configuration.KLAB;
import org.integratedmodelling.common.interfaces.Monitorable;
import org.integratedmodelling.common.interfaces.actuators.IDirectActuator;
import org.integratedmodelling.common.interfaces.actuators.IStateActuator;
import org.integratedmodelling.common.kim.KIMAction;
import org.integratedmodelling.common.kim.KIMModel;
import org.integratedmodelling.common.kim.KIMObservableSemantics;
import org.integratedmodelling.common.knowledge.Observation;
import org.integratedmodelling.common.metadata.Metadata;
import org.integratedmodelling.common.model.Coverage;
import org.integratedmodelling.common.model.actuators.Actuator;
import org.integratedmodelling.common.model.actuators.EventActuator;
import org.integratedmodelling.common.model.actuators.ProcessActuator;
import org.integratedmodelling.common.model.actuators.RelationshipActuator;
import org.integratedmodelling.common.model.actuators.SubjectContextualizerActuator;
import org.integratedmodelling.common.model.runtime.Transition;
import org.integratedmodelling.common.states.States;
import org.integratedmodelling.common.utils.NameGenerator;
import org.integratedmodelling.common.vocabulary.NS;
import org.integratedmodelling.common.vocabulary.ObservableSemantics;
import org.integratedmodelling.engine.modelling.AgentState;
import org.integratedmodelling.engine.modelling.TemporalCausalGraph;
import org.integratedmodelling.engine.modelling.resolver.Dataflow;
import org.integratedmodelling.engine.modelling.resolver.ResolutionScope;
import org.integratedmodelling.engine.modelling.resolver.Resolver;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.exceptions.KlabValidationException;

/**
 * Holds the methods that interface each directly observed object (subject/agent, process,
 * event) with the multiagent/multiscale contextualizer. Moved all methods from Subject to
 * here so that Process and Event can react to transitions.
 * 
 * @author Ferd
 * @author Luke
 */
public abstract class DirectObservation extends Observation
        implements IActiveDirectObservation, Monitorable {

    /**
     * Saved with artifact IDs; will build the artifact on demand.
     * 
     * @author ferdinando.villa
     *
     */
    public static interface ArtifactGenerator {

        /**
         * Build the artifact and return the bean allowing access to the outputs.
         * 
         * This is called only after a user has selected the export option on the
         * local engine, so it should be free to simply export any files needed to
         * a temporary directory and set their path and (if applicable) local paths
         * into the response, including, if applicable, model source code.
         * 
         * @return
         */
        LocalExportResponse generateArtifact();
    }

    protected boolean                                                              initialized                = false;
    // index value of _scale.getTime().getExtent(i) corresponding to agent's
    // temporal
    // location
    protected int                                                                  currentTemporalExtentIndex = 0;
    protected ITimePeriod                                                          currentTimePeriodCache     = null;
    protected TemporalCausalGraph causalGraph;
    protected INamespace                                                           namespace;
    protected String                                                               name;
    protected IMonitor                                                             monitor;
    protected IMetadata                                                            metadata                   = new Metadata();
    protected ResolutionScope                                                      resolutionContext;
    protected ITransition                                                          lastTransitionSeen;
    protected ArrayList>                                   states                     = new ArrayList<>();

    /*
     * for the Groovy interface. See setVar/getVar
     */
    private Map                                                    vars                       = new HashMap<>();

    /*
     * internal ID for observation paths
     */
    protected String                                                               internalID                 = NameGenerator
            .shortUUID();

    private List                                                directObservations         = new ArrayList<>();
    IDirectObservation                                                             contextSubject             = null;
    ArrayList>                                           processes                  = new ArrayList<>();

    /*
     * holders for exportable artifacts other than observations
     */
    protected Map                                       datasetOutputs             = new HashMap<>();
    protected Map                                       modelOutputs               = new HashMap<>();

    /**
     * Roles stated or inferred from the model chosen.
     */
    List>                                     localRoles                 = new ArrayList<>();

    /**
     * Coverage for all observables already observed in our context, whether successfully
     * or not.
     */
    protected Map                                 resolved                   = new HashMap<>();

    // we store compiled versions of any actions coming from the model.
    List                                                                  initActions                = new ArrayList<>();
    List                                                                  timeActions                = new ArrayList<>();
    boolean                                                                        actionsStored;

    private int                                                                    priorityOrder              = 0;
    /*
     * set in top subject after dataflow is compiled.
     */
    protected Dataflow                                                             dataflow;

    protected DirectObservation(IObservableSemantics observable,
            IActiveDirectObservation contextObservation, IScale scale, IContext context,
            INamespace namespace,
            String name,
            IMonitor monitor) {
        this.scale = scale;
        this.namespace = namespace;
        this.name = name;
        this.monitor = monitor;
        this.context = context;
        setObservable(observable, context, name);
    }

    public void setModel(IModel model) {
        this.model = model;
        if (model instanceof KIMModel) {
            this.localRoles.addAll(((KIMModel) model).getLocalRoles());
        }
    }

    @Override
    public Collection getRolesFor(ISemantic observable) {

        Set ret = new HashSet<>();

        IConcept concept = observable.getType();

        if (observable instanceof IObservation) {
            /*
             * add roles set directly by the client. These are not specific of our context
             * but they're always valid.
             */
            ret.addAll(((Observation) observable).getExplicitRoles());

            /*
             * switch to the concept to proceed with role inference
             */
            concept = ((IObservation) observable).getObservable().getType();
        }

        if (observable instanceof KIMObservableSemantics) {
            ret.add(((KIMObservableSemantics) observable).getStatedRole());
        }

        for (Pair rd : localRoles) {
            if (concept.is(rd.getFirst().getType())) {
                ret.add(rd.getSecond());
            }
        }
        return ret;
    }

    @Override
    public IModel getModel() {
        return resolutionContext == null ? null : resolutionContext.getModel();
    }

    public void setResolutionContext(ResolutionScope resolutionContext) {
        this.resolutionContext = resolutionContext;
    }

    public void setVar(String id, Object value) {
        vars.put(id, value);
    }

    public Object getVar(String id) {
        return vars.get(id);
    }

    public IResolutionScope getResolutionScope() {
        return this.resolutionContext;
    }

    @Override
    public IMetadata getMetadata() {
        return metadata;
    }

    @Override
    public IDirectObservation getContextObservation() {
        return contextSubject;
    }

    public void prepareForTransition(ITransition transition) {

        if (lastTransitionSeen == null
                || transition.getTimeIndex() > lastTransitionSeen.getTimeIndex()) {
            lastTransitionSeen = transition;
        }

        /*
         * ensure that all states are tuned to the current transition
         */
        for (IState state : (this instanceof ISubject || this instanceof IEvent ? this.getStates()
                : context.getSubject().getStates())) {
            ((org.integratedmodelling.common.states.State) state).flushStorage(transition);
        }
    }

    public ICoverage initialize(IResolutionScope context, IProvenance.Action cause, IMonitor monitor)
            throws KlabException {

        ICoverage ret = Coverage.EMPTY;
        try {
            Resolver resolver = new Resolver(context, cause);
            ret = resolver.resolve(this, monitor);
        } catch (Exception e) {
            monitor.error(e);
        }

        initialized = true;
        return ret;
    }

    public void addProcess(IProcess process) throws KlabException {
        IProperty p = NS
                .getPropertyFor(process, getObservable().getSemantics(), getNamespace());
        processes.add(new Pair<>(p, process));
        addDirectObservation((DirectObservation) process);
    }

    public void addEvent(IEvent event) throws KlabException {
        addDirectObservation((DirectObservation) event);
        /*
         * TODO notify
         */
    }

    /**
     * Called by instantiators that have actions other than initialization or resolution.
     * These are added to the actuator if we have one, or a new actuator is created if
     * missing. Will only be called after resolution by
     * {@link Dataflow#initializeDirectActuator}.
     * 
     * @param action
     */
    public void addAction(IAction action) {

        if (actuator == null) {
            if (this instanceof ISubject) {
                actuator = new SubjectContextualizerActuator((IActiveSubject) this, null, null, Collections
                        .singletonList(action), monitor);
            } else if (this instanceof IProcess) {
                actuator = new ProcessActuator((IActiveProcess) this, null, null, Collections
                        .singletonList(action), monitor);
            } else if (this instanceof IEvent) {
                actuator = new EventActuator((IActiveEvent) this, null, null, Collections
                        .singletonList(action), monitor);
            } else if (this instanceof IRelationship) {
                actuator = new RelationshipActuator((IActiveRelationship) this, null, null, Collections
                        .singletonList(action), monitor);
            }
        } else {
            ((Actuator) actuator).addAction(action);
        }

        /*
         * TODO
         */
    }

    /**
     * Re-evaluate states given the new temporal location of this agent. The agent has
     * access to the current states during execution of this method because they have not
     * yet changed. The agent is expected to update the state values and set them in the
     * result. this method is intended to be overridden by subclasses as appropriate.
     * 
     * @param timePeriod
     * @return new transition
     */
    @Override
    public ITransition reEvaluateStates(ITimePeriod timePeriod) {

        Map currentStates = getObjectStateCopy();
        IAgentState agentState = new AgentState(this, timePeriod, currentStates);
        ITransition noTransition = new Transition(getScale(), agentState, true);
        return noTransition;
    }

    @Override
    public ICollision detectCollision(IObservationGraphNode myAgentState, IObservationGraphNode otherAgentState) {
        // TODO not going to implement this. Collision detection is extremely
        // difficult.
        return null;
    }

    @Override
    public boolean doesThisCollisionAffectYou(IAgentState agentState, ICollision collision) {
        // TODO not going to implement this. Collision detection is extremely
        // difficult.
        return false;
    }

    @Override
    public IState getState(IObservableSemantics obs, Object... data)
            throws KlabException {

        for (Pair s : this.states) {
            /*
             * Only compare observable and observation: the inherent type has been set to
             * equal the subject's, so it may differ without incompatibility. FIXME -
             * should be OK if the observable doesn't have it but not OK if it does and
             * it's not the same type (using is()).
             */
            if (((ObservableSemantics) obs).equalsWithoutInherency(s.getSecond()
                    .getObservable().getSemantics())) {
                return s.getSecond();
            }
        }
        if (!NS.isQuality(obs)) {
            throw new KlabValidationException("cannot create a state for a non-quality: "
                    + obs.getType());
        }

        // if (obs.getInherentType() == null) {
        // obs = ((Observable)
        // obs).withInherentType(this.getObservable().getType());
        // }

        IState ret = States.create(obs, this);
        // FIXME remove this - we do not need a data property until we need it.
        this.states.add(new Pair<>(NS
                .getPropertyFor(ret, this.getObservable()
                        .getSemantics(), getNamespace()), ret));
        ((Context) this.context).addDelta(ret);

        ((org.integratedmodelling.common.states.State) ret).setContext(this.context);

        return ret;
    }

    public IState getStateFor(IObservableSemantics obs, IStateActuator actuator)
            throws KlabException {

        for (Pair s : this.states) {
            /*
             * Only compare observable and observation: the inherent type has been set to
             * equal the subject's, so it may differ without incompatibility. FIXME -
             * should be OK if the observable doesn't have it but not OK if it does and
             * it's not the same type (using is()).
             */
            if (((ObservableSemantics) obs).equalsWithoutInherency(s.getSecond()
                    .getObservable().getSemantics())) {
                return s.getSecond();
            }
        }
        if (!NS.isQuality(obs) && !NS.isTrait(obs)) {
            throw new KlabValidationException("cannot create a state for a non-quality: "
                    + obs.getType());
        }

        IState ret = null;
        Map dummy = new HashMap<>();
        if (actuator.isConstant()) {

            ret = new org.integratedmodelling.common.states.State(actuator
                    .process(0, dummy, ITransition.INITIALIZATION)
                    .get(actuator.getName()), obs, this, false, false);

        } else {

            /*
             * TODO for now we only let process contextualizers create dynamic states
             * explicitly.
             */

            ret = actuator.isProbabilistic()
                    ? (/*
                        * actuator.isTemporal() ? States.createProbabilistic(obs, this) :
                        */ States.createProbabilisticStatic(obs, this))
                    : (/*
                        * actuator.isTemporal() ? States.create(obs, this) :
                        */ States.createStatic(obs, this));
        }

        // FIXME remove this - we do not need a data property until we need it.
        this.states.add(new Pair<>(NS
                .getPropertyFor(ret, this.getObservable()
                        .getSemantics(), getNamespace()), ret));
        ((Context) this.context).addDelta(ret);
        ((org.integratedmodelling.common.states.State) ret).setContext(this.context);

        return ret;
    }

    @Override
    public Collection getStates() {
        ArrayList ret = new ArrayList<>();
        for (Pair pd : this.states) {
            ret.add(pd.getSecond());
        }
        return ret;
    }

    @Override
    public IState getStaticState(IObservableSemantics obs) throws KlabException {

        for (Pair s : this.states) {
            /*
             * Only compare observable and observation: the inherent type has been set to
             * equal the subject's, so it may differ without incompatibility. FIXME -
             * should be OK if the observable doesn't have it but not OK if it does and
             * it's not the same type (using is()).
             */
            if (((ObservableSemantics) obs).equalsWithoutInherency(s.getSecond()
                    .getObservable().getSemantics())) {
                return s.getSecond();
            }
        }
        if (!NS.isQuality(obs)) {
            throw new KlabValidationException("cannot create a state for a non-quality: "
                    + obs.getType());
        }

        // if (obs.getInherentType() == null) {
        // obs = ((Observable)
        // obs).withInherentType(this.getObservable().getType());
        // }

        IState ret = States.createStatic(obs, this);
        // FIXME remove this - we do not need a data property until we need it.
        this.states.add(new Pair<>(NS
                .getPropertyFor(ret, this.getObservable()
                        .getSemantics(), getNamespace()), ret));
        ((org.integratedmodelling.common.states.State) ret).setContext(this.context);

        ((Context) this.context).addDelta(ret);

        return ret;
    }

    /**
     * @return context subject
     */
    public IDirectObservation getContextSubject() {
        return this.contextSubject;
    }

    /**
     * @param subject
     */
    public void setContextSubject(IDirectObservation subject) {
        this.contextSubject = subject;
        this.parentId = ((Observation) subject).getInternalId();
        if (subject instanceof Subject) {
            this.context = ((Subject) subject).getContext();
        }
    }

    /**
     * Return all direct observations in order of dependency (stated order in model).
     * 
     * @return direct observations
     */
    public List getDirectObservations() {
        return this.directObservations;
    }

    /*
     * called to add a direct observation to the observation graph. The order of addition
     * will determine the order of contextualization.
     */
    protected void addDirectObservation(DirectObservation obs) {
        this.directObservations.add(obs);
        ((Context) this.context).addDelta(obs);

        /*
         * TODO synchronize event handlers with interceptor - use semantics
         */

    }

    /**
     * Recursively add the subject and all its dependencies to the observation graph
     * (which is contained in the controller parameter). Keep a list of what's been added
     * already, to speed up performance, avoid infinite recursion, and avoid duplicating
     * the initial observation tasks for the agents.
     * 
     * @param subjectObserver
     * @param simulationTimePeriod
     * @param controller
     * @param alreadyAdded
     */
    protected void addSubjectToObservationGraph(DirectObservation subject, ITimePeriod simulationTimePeriod, IObservationController controller, HashSet alreadyAdded) {

        if (alreadyAdded == null) {
            alreadyAdded = new HashSet<>();
        }
        if (!alreadyAdded.contains(subject)) {

            alreadyAdded.add(subject);

            for (DirectObservation child : subject.getDirectObservations()) {
                addSubjectToObservationGraph(child, simulationTimePeriod, controller, alreadyAdded);
            }

            ITimePeriod agentCreationTimePeriod = simulationTimePeriod;
            ITemporalExtent subjectTime = subject.getScale().getTime();
            if (subjectTime != null) {
                // agent has its own temporal scale, so don't inherit the
                // default. Start
                // with extent 0.
                agentCreationTimePeriod = subjectTime.getExtent(0).collapse();
            }
            AgentState initialState = new AgentState(subject, agentCreationTimePeriod, ((IActiveDirectObservation) subject)
                    .getObjectStateCopy());
            controller
                    .createAgent(subject, initialState, agentCreationTimePeriod, null, null, true);
        }
    }

    /**
     * Default implementation for Subjects (non-agents) without any explicit view of time.
     * This means that they can be re-evaluated over time by repeating the same
     * observations, but they do not perform any logic or application of rules based on
     * states or state transitions.
     * 
     * @throws KlabException
     */
    @Override
    public ITransition performTemporalTransitionFromCurrentState() throws KlabException {
        ITransition result;

        // set the clock forward
        if (moveToNextTimePeriod() == null) {

            // we went beyond the agent's last temporal extent, so the agent
            // dies
            result = new Transition(getScale(), null, false);

        } else {

            result = reEvaluateStates(getCurrentTimePeriod());
            if (result.agentSurvives()) {
                prepareForTransition(result);
                if (actuator instanceof IDirectActuator) {
                    ((IDirectActuator) actuator).processTransition(result, monitor);
                }
            }
        }

        return result;
    }

    protected ITimePeriod moveToNextTimePeriod() {

        if (getCurrentTimePeriod() == null) {
            // if we're already beyond the valid index numbers, then don't
            // increment any
            // more.
            return null;
        }

        // set the clock forward & invalidate the cache
        currentTemporalExtentIndex++;
        currentTimePeriodCache = null;

        // reload the cache and validate that we're still within the subject's
        // temporal
        // scale
        ITimePeriod result = getCurrentTimePeriod();
        if (result == null) {
            // TODO either extend the scale or the agent must die
            // currently, the agent dies by default
        }

        return result;
    }

    @Override
    public String getName() {
        return name;
    }

    /**
     * get the TemporalExtent (which is also a TimePeriod) of the agent's current temporal
     * location. Will return null if the index has gone beyond the agent's temporal scale.
     * 
     * @return
     */
    protected ITimePeriod getCurrentTimePeriod() {
        if (currentTimePeriodCache == null) {
            ITemporalExtent time = getScale().getTime();
            if (time != null) {
                // FIXME check the -1 - not sure yet
                if (currentTemporalExtentIndex >= (time.getMultiplicity()) - 1)
                    return null;
                ITemporalExtent extent = time.getExtent(currentTemporalExtentIndex);
                currentTimePeriodCache = extent.collapse();
            }
        }
        return currentTimePeriodCache;
    }

    /**
     * @return the causal graph
     */
    public TemporalCausalGraph getCausalGraph() {
        return causalGraph;
    }

    /**
     * @return true if initialization has completed
     */
    public boolean isInitialized() {
        return this.initialized;
    }

    @Override
    public INamespace getNamespace() {
        return namespace;
    }

    private void storeActions() {
        if (!actionsStored) {
            actionsStored = true;
            if (getModel() != null) {
                for (IAction a : getModel().getActions()) {
                    if (a.getDomain().isEmpty()) {
                        initActions.add(((KIMAction) a)
                                .compileFor(this.getScale(), getModel()));
                    } else if (a.getDomain().contains(KLAB.c(NS.TIME_DOMAIN))) {
                        timeActions.add(((KIMAction) a)
                                .compileFor(this.getScale(), getModel()));
                    }
                }
            }
        }
    }

    /**
     * @param transition
     * @throws KlabException
     */
    public void execActions(ITransition transition) throws KlabException {

        if (!actionsStored) {
            storeActions();
        }

        if (transition == null) {
            for (IAction a : initActions) {
                ((KIMAction) a).execute(contextSubject, this, transition, monitor);
            }
        } else {
            for (IAction a : timeActions) {
                ((KIMAction) a).execute(contextSubject, this, transition, monitor);
            }
        }
    }

    @Override
    public void setMonitor(IMonitor monitor) {
        this.monitor = monitor;
    }

    /**
     * @param ret
     */
    public void serialize(org.integratedmodelling.common.beans.DirectObservation ret) {

        // TODO Auto-generated method stub
        super.serialize(ret);

        ret.setName(getName());
        for (IState s : getStates()) {
            ret.getStates().add(KLAB.MFACTORY.adapt(s, State.class));
        }
        for (IDirectObservation d : directObservations) {

        }

        /**
         * export any other artifacts
         */
        for (String m : modelOutputs.keySet()) {
            ret.getModelOutputs().add(m);
        }
        for (String m : datasetOutputs.keySet()) {
            ret.getDatasetOutputs().add(m);
        }
    }

    @Override
    public IObservation find(String id) {
        if (this.id.equals(id)) {
            return this;
        }
        IObservation ret = null;
        for (IState sub : getStates()) {
            ret = ((Observation) sub).find(id);
            if (ret != null) {
                return ret;
            }
        }
        return ret;
    }

    @Override
    public void addEventHandler(IAction action) {
        // TODO Auto-generated method stub

    }

    public void addOutputModel(String artifactId, ArtifactGenerator artifactGenerator) {
        modelOutputs.put(artifactId, artifactGenerator);
    }

    public void addOutputDataset(String artifactId, ArtifactGenerator artifactGenerator) {
        datasetOutputs.put(artifactId, artifactGenerator);
    }

    /**
     * Return our priority in the dataflow we're in, if any. If this is 0, we can
     * contextualize concurrently with others having 0 order.
     * 
     * @return
     */
    public int getPriorityOrder() {
        return this.priorityOrder;
    }

    public void computePriorityOrder(Dataflow dataflow) {

        if (this instanceof Subject) {
            for (ISubject s : ((Subject) this).getSubjects()) {
                ((DirectObservation) s).computePriorityOrder(dataflow);
            }
            for (IProcess s : ((Subject) this).getProcesses()) {
                ((DirectObservation) s).computePriorityOrder(dataflow);
            }
            /*
             * relationships and events are only created later.
             */
        }

        /*
         * if this is a subject and has a dataflow, its priority is the depth of the
         * dataflow plus one, so that we are guaranteed to be contextualized after all of
         * our children.
         */
        if (this instanceof Subject && dataflow.getSubject().equals(this)) {
            this.priorityOrder = dataflow.getDepth() + 1;
        } else {
            int d = dataflow.getDepth(this);
            /*
             * subtract 1 if < 0 so that children with no dependencies get the fully
             * contextualized subject in their actions.
             */
            this.priorityOrder = dataflow.getDepth() - (d < 0 ? (d - 1) : d);
        }

        KLAB.info("Priority for " + this + " is " + priorityOrder);
    }

    public void setDataflow(Dataflow dataflow) {
        this.dataflow = dataflow;
    }

    @Override
    public ICoverage getResolvedCoverage(ISemantic concept) {

        for (IObservableSemantics os : resolved.keySet()) {
            if (os.getType().is(concept)) {
                return resolved.get(os);
            }
        }
        return null;
    }

    public LocalExportResponse buildArtifact(String artifactId, boolean isModel) {
        ArtifactGenerator builder = isModel ? modelOutputs.get(artifactId) : datasetOutputs.get(artifactId);
        return builder == null ? null : builder.generateArtifact() ;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy