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

org.integratedmodelling.engine.modelling.runtime.Context 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.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.geotools.geometry.jts.ReferencedEnvelope;
import org.integratedmodelling.api.knowledge.IConcept;
import org.integratedmodelling.api.knowledge.IObservation;
import org.integratedmodelling.api.metadata.IReport;
import org.integratedmodelling.api.modelling.IActiveDirectObservation;
import org.integratedmodelling.api.modelling.IActiveSubject;
import org.integratedmodelling.api.modelling.IDirectObserver;
import org.integratedmodelling.api.modelling.IEvent;
import org.integratedmodelling.api.modelling.IExtent;
import org.integratedmodelling.api.modelling.IKnowledgeObject;
import org.integratedmodelling.api.modelling.IModel;
import org.integratedmodelling.api.modelling.IModelBean;
import org.integratedmodelling.api.modelling.IModelObject;
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.IState;
import org.integratedmodelling.api.modelling.ISubject;
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.monitoring.Messages;
import org.integratedmodelling.api.provenance.IProvenance;
import org.integratedmodelling.api.runtime.IContext;
import org.integratedmodelling.api.runtime.ISession;
import org.integratedmodelling.api.runtime.ITask;
import org.integratedmodelling.api.runtime.ITask.Status;
import org.integratedmodelling.api.space.ISpatialExtent;
import org.integratedmodelling.collections.Pair;
import org.integratedmodelling.common.configuration.KLAB;
import org.integratedmodelling.common.interfaces.NetworkSerializable;
import org.integratedmodelling.common.kim.KIMDirectObserver;
import org.integratedmodelling.common.knowledge.Definition;
import org.integratedmodelling.common.knowledge.Observation;
import org.integratedmodelling.common.knowledge.ObservationGroup;
import org.integratedmodelling.common.model.runtime.AbstractContext;
import org.integratedmodelling.common.model.runtime.Session;
import org.integratedmodelling.common.model.runtime.Space;
import org.integratedmodelling.common.monitoring.Monitor;
import org.integratedmodelling.common.provenance.Provenance;
import org.integratedmodelling.common.reporting.Report;
import org.integratedmodelling.common.states.State;
import org.integratedmodelling.common.utils.NameGenerator;
import org.integratedmodelling.common.utils.Path;
import org.integratedmodelling.common.vocabulary.GeoNS;
import org.integratedmodelling.common.vocabulary.NS;
import org.integratedmodelling.common.vocabulary.Observables;
import org.integratedmodelling.engine.ModelFactory;
import org.integratedmodelling.engine.geospace.Geospace;
import org.integratedmodelling.engine.geospace.literals.ShapeValue;
import org.integratedmodelling.engine.modelling.TemporalCausalGraph;
import org.integratedmodelling.engine.modelling.resolver.ResolutionScope;
import org.integratedmodelling.engine.visualization.VisualizationFactory;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.exceptions.KlabRuntimeException;
import org.integratedmodelling.exceptions.KlabValidationException;

import com.ibm.icu.text.NumberFormat;

/**
 * Manages observation and resolution. Initialized with a subject observer (and a
 * session/monitor). Holds the root subject and the correspondent resolution context.
 * Allows contextualization for all the dependent observations.
 * 
 * @author Ferd
 * 
 */
public class Context extends AbstractContext implements NetworkSerializable {

    // values for _status
    final static int            EMPTY                = 0;
    final static int            DEFINED              = 1;
    final static int            INITIALIZED          = 2;
    final static int            RUNNING              = 3;
    final static int            CONTEXTUALIZED       = 4;
    final static int            ERROR                = -1;
    final static int            INTERRUPTED          = -2;

    // this is set only when the object is created and is passed along to copies
    int                         status               = EMPTY;
    int                         currentTime          = -1;
    volatile Boolean            paused               = false;
    IResolutionScope            resolutionContext    = null;
    String                      deferredObservableId = null;
    Object                      deferredObservable   = null;
    boolean                     isDeferred           = false;
    Set           newObservations      = new HashSet<>();
    Provenance                  provenance;

    List          deltas               = new ArrayList<>();

    IMonitor                    monitor;
    List                scenarioIds          = new ArrayList<>();
    String                      name;
    Set                 breakpoints          = new HashSet<>();
    IReport                     report               = new Report();

    private long                timeOfLastChange     = new Date().getTime();
    private IDirectObserver     rootObserver;
    // forcings to apply to scale if deferred initialization is requested and
    // not null.
    private Collection forcings             = null;
    private double[]            locationOfInterest;

    @Override
    public IReport getReport() {
        return report;
    }

    public double[] getLocationOfInterest() {
        return locationOfInterest;
    }

    class RunThread implements Runnable {

        @Override
        public void run() {
            status = RUNNING;
            try {
                /**
                 * TODO install listener to be notified of structural changes
                 */
                ((IActiveSubject) subject).contextualize();
            } catch (KlabException e) {
                monitor.error(e);
                status = ERROR;
                return;
            }
            status = monitor.getTask().getStatus() == Status.INTERRUPTED ? INTERRUPTED
                    : CONTEXTUALIZED;
            if (status == CONTEXTUALIZED) {
                monitor.info("coverage from observation of " + subject.getName() + " is "
                        + coverage.getCoverage(), Messages.INFOCLASS_MODEL);
            }
        }
    }

    /**
     * @param session
     * @param monitor
     * @param observer
     * @throws KlabException
     */
    public Context(ISession session, IMonitor monitor, IDirectObserver observer)
            throws KlabException {
        this.name = observer.getId();
        this.monitor = ((Monitor) monitor).get(this);
        this.id = NameGenerator.shortUUID();
        this.rootObserver = observer;
        this.subject = (IActiveSubject) KLAB.MFACTORY
                .createSubject(observer, this, null, monitor);
        this.resolutionContext = ResolutionScope
                .root((IActiveSubject) subject, null, monitor, null);
        this.provenance = new Provenance(this);
        this.monitor.send(this);
    }

    /**
     * @param session
     * @param monitor
     * @param observerId
     * @param forcings
     * @throws KlabException
     */
    public Context(ISession session, IMonitor monitor, Object observable,
            Collection forcings)
            throws KlabException {

        /*
         * TODO may be a concept, direct observer or other. Forcings may contain spatial
         * context and drop location.
         */
        if (observable instanceof IDirectObserver) {
            this.name = Path.getLast(((IDirectObserver) observable).getId(), '.');
            this.deferredObservableId = ((IDirectObserver) observable).getName();
        } else {
            this.name = "UserContext";
            this.deferredObservable = observable;
            this.deferredObservableId = getName(observable);
        }
        this.monitor = ((Monitor) monitor).get(this);
        this.id = NameGenerator.shortUUID();
        this.isDeferred = true;
        this.forcings = (forcings == null || forcings.size() == 0) ? null : forcings;
        this.provenance = new Provenance(this);
        this.monitor.send(this);
    }

    private String getName(Object observable) {
        if (observable instanceof IModelObject) {
            return ((IModelObject) observable).getName();
        }
        return observable == null ? "(null)" : observable.toString();
    }

    public void resolveObservable(IMonitor monitor) throws KlabException {
        /*
         * 
         */
        KLAB.PMANAGER.load(false, KLAB.MFACTORY.getRootParsingContext());

        IDirectObserver observer = null;
        IConcept concept = null;
        boolean isROIonly = false;

        if (deferredObservable instanceof IDirectObserver) {
            observer = (IDirectObserver) deferredObservable;
        } else if (deferredObservable instanceof IConcept) {
            concept = (IConcept) deferredObservable;
        } else if (deferredObservableId != null || deferredObservable instanceof String) {

            String tofind = deferredObservableId == null ? getName(deferredObservable)
                    : deferredObservableId;

            isROIonly = (deferredObservable != null
                    && deferredObservable.toString().equals("region-of-interest"));

            IModelObject obs = KLAB.MMANAGER.findModelObject(tofind);
            if (obs == null) {
                concept = KLAB.KM.getConcept(tofind);
            }
            if (obs instanceof IDirectObserver) {
                observer = (IDirectObserver) obs;
            } else if (obs instanceof IModel) {
                /* TODO */
            } else if (obs instanceof IKnowledgeObject) {
                concept = ((IKnowledgeObject) obs).getConcept();
            } else if (concept == null && !isROIonly) {

                throw new KlabValidationException("cannot find observable "
                        + tofind);
            }

        }

        if (observer != null) {
            rootObserver = observer;
            if (forcings != null) {
                rootObserver = ModelFactory.forceScale(rootObserver, monitor, forcings);
            }
            initializeContextWith((IActiveSubject) KLAB.MFACTORY
                    .createSubject(rootObserver, this, null, this.monitor));
            // addDelta(subject);
            // resolutionContext = ResolutionScope
            // .root((IActiveSubject) subject, null, monitor, null);
            // ((Observation) subject).defineObservable();
            // isDeferred = false;
        } else if (concept != null) {
            /*
             * TODO
             */
            if (subject == null) {

                /*
                 * must have a ROI in the spatial forcing
                 */
                Pair roi = findROI(forcings);
                if (roi.getFirst() == null) {
                    throw new KlabValidationException("cannot observe a concept without a region of interest or a context "
                            + deferredObservableId);
                } else {
                    locationOfInterest = roi.getSecond();
                    rootObserver = new KIMDirectObserver(GeoNS.PLAIN_REGION, "region-of-interest", new Scale(Collections
                            .singleton(new ShapeValue(roi.getFirst()).asExtent())));
                    rootObserver = ModelFactory.forceScale(rootObserver, monitor, forcings);
                    initializeContextWith((IActiveSubject) KLAB.MFACTORY
                            .createSubject(rootObserver, this, null, monitor));
                    coverage = ((Subject) this.subject)
                            .initialize(resolutionContext, null /* userAction */, monitor);
                    status = Context.INITIALIZED;

                    if (coverage.isEmpty()) {
                        monitor.error("initialization of implicit region of interest failed: empty coverage");
                    }
                }

                if (subject != null && !coverage.isEmpty() && !isROIonly) {
                    observeConcept(concept, monitor);
                }

                /*
                 * there may be a point too, which we can use as the intersection point to
                 * find compatible context observations.
                 */

                /*
                 * workflow of finding objects for a distributed observation must be in
                 * independent call as it can apply to all observe calls
                 */

            }
        }
    }

    /**
     * @throws KlabException
     */
    public void resolveObservable() throws KlabException {
        resolveObservable(this.monitor);
    }

    private void observeConcept(IConcept concept, IMonitor monitor) throws KlabException {

        IConcept context = Observables.getContextType(concept);
        IConcept inherent = Observables.getInherentType(concept);
        boolean distributed = false;
        /*
         * if subject is incompatible with context, observe context and distribute concept
         * over results.
         */

        List subjects = new ArrayList<>();
        if (context != null && !checkContextCompatibility(subject.getObservable().getType(), context)) {

            distributed = true;

            coverage = ((Subject) subject).observe(Task
                    .makeObservable(context), scenarioIds, false, /* userAction */ null, monitor);

            for (IObservation o : getNewObservations()) {
                if (o instanceof ISubject && o.getObservable().getType().is(context)) {
                    subjects.add((ISubject) o);
                }
            }

        } else {
            subjects.add(this.subject);
        }

        /*
         * observe the concept in each of the resulting subjects
         */
        for (ISubject s : subjects) {

            coverage = ((Subject) s).observe(Task
                    .makeObservable(concept), scenarioIds, false, /* userAction */ null, monitor);

            if (!coverage.isEmpty()) {
                monitor.info("observation of " + NS.getDisplayName(concept) + " in "
                        + subject.getName()
                        + " covers " + NumberFormat.getPercentInstance()
                                .format(coverage.getCoverage()), Messages.INFOCLASS_MODEL);
            } else {
                monitor.warn("observation of " + NS.getDisplayName(concept) + " in "
                        + subject.getName()
                        + " is empty");
            }
        }

        /*
         * If observation of context produced only one result and result is subject, swap
         * subject with context and move from there.
         */
        if (distributed && subjects.size() == 1
                && subjects.get(0).getObservable().getType().is(this.subject.getObservable().getType())) {

            /*
             * TODO merge
             */

            distributed = false;
        }

        /*
         * If concept was a quality and distribution happened, add a state to the main
         * subject with the merge of the quality inherently to the distributing subjects.
         */
        if (NS.isQuality(concept) && distributed) {

        }

    }

    private boolean checkContextCompatibility(IConcept type, IConcept context) {

        // FIXME this is the proper check, as long as isCompatible can go and observe
        // missing
        // traits (such as whether a region is terrestrial) by running a classifier:

        // return Observables.isCompatible(subject.getType(), context);

        // weak check to use until we get smarter. For now assume users aren't monkeys and
        // can make some calls themselves, not observing watersheds in the open sea etc.
        IConcept coretype = Observables.getCoreObservable(type);
        IConcept corecont = Observables.getCoreObservable(context);
        return coretype.is(corecont);
    }

    private void initializeContextWith(IActiveSubject subject) throws KlabException {

        this.subject = subject;
        addDelta(subject);
        resolutionContext = ResolutionScope
                .root(subject, null, monitor, null);
        ((Observation) subject).defineObservable();
        isDeferred = false;
    }

    private Pair findROI(Collection forcings) {

        ReferencedEnvelope ret = null;
        double[] loi = null;

        for (IExtent e : forcings) {
            if (e instanceof ISpatialExtent) {

                if (!Double.isNaN(((ISpatialExtent) e).getMinX())) {

                    ret = new ReferencedEnvelope(((ISpatialExtent) e)
                            .getMinX(), ((ISpatialExtent) e)
                                    .getMaxX(), ((ISpatialExtent) e)
                                            .getMinY(), ((ISpatialExtent) e)
                                                    .getMaxY(), Geospace.get()
                                                            .getDefaultCRS());

                    if (e instanceof Space) {
                        loi = ((Space) e).getLocationOfInterest();
                    }
                }
                break;
            }
        }
        return new Pair<>(ret, loi);
    }

    /**
     * @param c
     */
    public Context(Context c) {

        /**
         * TODO some of these probably must be deep copies - particularly the observer.
         */
        super(c);
        this.name = c.name;
        this.coverage = c.coverage;
        this.monitor = ((Monitor) c.monitor).get(this);
        this.status = c.status;
        this.currentTime = c.currentTime;
        this.rootObserver = c.rootObserver;
        this.resolutionContext = c.resolutionContext;
        this.breakpoints.addAll(c.breakpoints);
        this.isDeferred = c.isDeferred;
        this.deferredObservableId = c.deferredObservableId;
        this.locationOfInterest = c.locationOfInterest;
    }

    private boolean isPaused() {
        synchronized (paused) {
            return paused;
        }
    }

    /**
     * @param status
     */
    public void pause(boolean status) {
        synchronized (paused) {
            paused = status;
        }
    }

    IMonitor getMonitor() {
        return monitor;
    }

    /**
     * Use to create the main subject or a single contextual observation in an existing
     * one.
     * 
     * @return the running task that is creating the subject.
     */
    public ITask observeAsynchronous() {

        Task ret = null;
        ret = observeInternal();
        ret.start();
        // FIXME move to task
        timeOfLastChange = new Date().getTime();
        return ret;
    }

    /**
     * @param observable
     * @param targetSubject
     * @return task observing subject within target subject.
     * @throws KlabValidationException
     */
    public ITask observeAsynchronous(Object observable, ISubject targetSubject)
            throws KlabValidationException {

        newObservations.clear();

        Task ret = null;
        ret = observeInternal(observable, targetSubject);
        ret.start();
        // FIXME move to task
        timeOfLastChange = new Date().getTime();
        return ret;
    }

    /**
     * Call after critical operations to decide whether to continue.
     * 
     * @return true if errors
     */
    public boolean hasErrors() {
        return monitor.hasErrors();
    }

    @Override
    public Collection getNewObservations() {
        Collection ret = new HashSet<>(newObservations);
        newObservations.clear();
        return ret;
    }

    public Context withScenario(Object... scenarios) throws KlabValidationException {

        scenarioIds.clear();

        for (Object o : scenarios) {
            if (o instanceof String) {
                scenarioIds.add((String) o);
            } else if (o instanceof INamespace && ((INamespace) o).isScenario()) {
                scenarioIds.add(((INamespace) o).getId());
            } else {
                throw new KlabValidationException("cannot use " + o + "  as a scenario");
            }
        }
        return this;
    }

    /**
     * Observe anything either in the current context or as a main observation. Pass only
     * one subject generator (or its ID), or however many things to observe in the current
     * subject; if doing the latter, you should call this indirectly with the with()
     * semantics.
     * 
     * @return
     */
    private Task observeInternal() {
        return new Task(this, monitor, scenarioIds);
    }

    private Task observeInternal(Object observable, ISubject target) {
        return new Task(this, monitor, scenarioIds, observable, target);
    }

    public static String describeObservable(Object observable) {

        if (observable instanceof IModel) {
            return "model " + ((IModel) observable).getName();
        } else if (observable instanceof IConcept) {
            return "concept " + observable;
        } else if (observable instanceof IDirectObserver) {
            return "object " + ((IDirectObserver) observable).getName();
        } else if (observable instanceof IObservableSemantics) {
            return ((IObservableSemantics) observable).getFormalName();
        }
        return observable.toString();
    }

    public List getScenarios() {
        return scenarioIds;
    }

    public TemporalCausalGraph getCausalGraph() {
        return ((Subject) subject).getCausalGraph();
    }

    public IState getState(Object o) {

        /**
         * TODO allow to search state by observer, model or anything else useful. TODO
         * ensure things work properly if called during run - must return most recent
         * state without conflicts.
         */
        IConcept c = o instanceof IConcept ? (IConcept) o : KLAB.c(o.toString());

        for (IState s : subject.getStates()) {
            if (s.getObservable().getSemantics().is(c))
                return s;
        }

        return null;
    }

    public static Context create(IDirectObserver sg, ISession session, IMonitor monitor)
            throws KlabException {
        return new Context(session, monitor, sg);
    }

    /**
     * Create a context that will defer resolution of the observable to the task started
     * by observeAsynchronous().
     * 
     * @param sg the subject observer ID. The project manager will be refreshed before the
     * name is resolved.
     * @param session
     * @param forcings
     * @return deferring context
     * @throws KlabException
     */
    public static Context createDeferred(Object observable, ISession session, Collection forcings)
            throws KlabException {
        return new Context(session, ((Session) session)
                .getMonitor(), observable, forcings);
    }

    @Override
    public boolean isEmpty() {
        return status == EMPTY;
    }

    @Override
    public boolean isFinished() {
        return status == CONTEXTUALIZED;
    }

    @Override
    public boolean isRunning() {
        return status == RUNNING;
    }

    @Override
    public IContext inScenario(String... scenarios) {

        if (scenarios == null || scenarios.length == 0) {
            return this;
        }

        // Context ret = new Context(this);
        for (String s : scenarios) {
            scenarioIds.add(s);
            // ret.scenarioIds.add(s);
        }

        // return ret;
        return this;
    }

    @Override
    public ITask run() {

        Task ret = Task.newTemporalTransitionTask(this, monitor);
        ret.start();
        return ret;
    }

    /**
     * @return timeslice we're currently on.
     */
    public int getCurrentTimeIndex() {
        return currentTime;
    }

    /**
     * @return timestamp of last change.
     */
    public long getLastChangeTimestamp() {
        return timeOfLastChange;
    }

    /**
     * Return the observation indexed by path, either a IState or ISubject. If not found
     * return null with no error.
     * 
     * @param path
     * @return observation for given path.
     */
    @Override
    public IObservation get(String path) {
        if (path.startsWith("G|")) {
            /*
             * make folder and return it
             */
            String[] def = path.split("\\|");
            if (def.length != 3) {
                throw new KlabRuntimeException("internal: wrong folder ID: " + path);
            }

            ISubject parent = (ISubject) get(def[1]);
            IConcept type = null;
            try {
                type = Definition.parse(def[2]).reconstruct(KLAB.REASONER.getOntology());
            } catch (KlabValidationException e) {
                throw new KlabRuntimeException(e);
            }
            if (parent == null || type == null) {
                return null;
            }
            
            ObservationGroup ret = new ObservationGroup(type, parent);

            ret.collectObservations();
            
            return ret;
        }
        return subject == null ? null : ((Subject) subject).get(path);
    }

    // @Override
    public IContext observe() {

        if (isEmpty()) {
            return this;
        }

        ITask task = observeAsynchronous();
        return task.finish();
    }

    @Override
    public void persist(File file, String path, Object... options) throws KlabException {

        if (path != null) {
            IObservation obs = this.get(path);
            VisualizationFactory.get().persist(obs, file, options);
        }
    }

    public IDirectObserver getRootSubjectGenerator() {
        return rootObserver;
    }

    public void setBreakpoint(IObservation obs) {
        if (obs instanceof State) {
            breakpoints.add(((State) obs).getInternalId());
        }
    }

    public boolean breakpointReached(Collection modifiedObservations) {

        if (breakpoints.size() > 0) {
            for (IObservation o : modifiedObservations) {
                if (o instanceof State
                        && breakpoints.contains(((State) o).getInternalId())) {
                    return true;
                }
            }
        }
        return false;
    }

    public void waitForResume() {

        pause(true);

        for (;;) {
            if (!isPaused()) {
                return;
            }
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                // nah
            }
        }
    }

    /**
     * Record a new observation made in this context. Deltas always go in the root
     * context.
     * 
     * @param observation
     */
    public void addDelta(IObservation observation) {
        newObservations.add(observation);
        getRootContext().deltas.add(observation);
    }

    private Context getRootContext() {
        if (parent == null) {
            return this;
        }
        return ((Context) parent).getRootContext();
    }

    @SuppressWarnings("unchecked")
    @Override
    public  T serialize(Class desiredClass) {

        if (!desiredClass
                .isAssignableFrom(org.integratedmodelling.common.beans.Context.class)) {
            throw new KlabRuntimeException("cannot serialize a Context to a "
                    + desiredClass.getCanonicalName());
        }

        org.integratedmodelling.common.beans.Context ret = new org.integratedmodelling.common.beans.Context();

        ret.setId(id);
        ret.setFinished(this.isFinished);

        // ret.setSubject(KLAB.MFACTORY.adapt(subject,
        // org.integratedmodelling.common.beans.Subject.class));
        if (coverage != null) {
            ret.setCoverage(coverage.getCoverage());
        }

        KLAB.info("got " + deltas.size() + " deltas to send");

        /*
         * send along any new observation. Must send all direct observations first, so
         * that the states are certain to have a defined parent when they reach the
         * client.
         */
        for (IObservation obs : deltas) {
            if (obs instanceof ISubject) {
                ret.addSubject(KLAB.MFACTORY
                        .adapt(obs, org.integratedmodelling.common.beans.Subject.class));
            } else if (obs instanceof IState) {
                ret.addState(KLAB.MFACTORY
                        .adapt(obs, org.integratedmodelling.common.beans.State.class));
            } else if (obs instanceof IEvent) {
                ret.addEvent(KLAB.MFACTORY
                        .adapt(obs, org.integratedmodelling.common.beans.Event.class));
            } else if (obs instanceof IProcess) {
                ret.addProcess(KLAB.MFACTORY
                        .adapt(obs, org.integratedmodelling.common.beans.Process.class));
            } else if (obs instanceof IRelationship) {
                ret.addRelationship(KLAB.MFACTORY
                        .adapt(obs, org.integratedmodelling.common.beans.Relationship.class));
            }
        }
        deltas.clear();

        return (T) ret;
    }

    /**
     * 
     * @return true if any new observation has been added since the last serialization.
     */
    public boolean hasDeltas() {
        return deltas.size() > 0;
    }

    @Override
    public IContext focus(ISubject observation) {
        if (subject.equals(observation)) {
            return this;
        }
        Context ret = new Context(this);
        ret.subject = observation;
        ((DirectObservation) observation).setContext(ret);
        return ret;
    }

    @Override
    public ITask observe(Object observable) throws KlabException {
        return observeAsynchronous(observable, subject);
    }

    @Override
    public ISession getSession() {
        return monitor.getSession();
    }

    @Override
    public ITransition getLastTemporalTransition() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public IProvenance getProvenance() {
        return provenance;
    }

    public void resetScenarios() {
        scenarioIds.clear();
        if (subject != null) {
            ((Subject) subject).resetExplicitRoles();
        }
    }

    @Override
    public IResolutionScope getScope() {
        return resolutionContext;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy