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

org.integratedmodelling.engine.modelling.runtime.Subject 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.HashMap;
import java.util.Map;

import org.integratedmodelling.api.knowledge.IConcept;
import org.integratedmodelling.api.knowledge.IObservation;
import org.integratedmodelling.api.knowledge.IProperty;
import org.integratedmodelling.api.metadata.IMetadata;
import org.integratedmodelling.api.modelling.IActiveDirectObservation;
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.IExtent;
import org.integratedmodelling.api.modelling.IModelBean;
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.IScale.Locator;
import org.integratedmodelling.api.modelling.IState;
import org.integratedmodelling.api.modelling.IStructure;
import org.integratedmodelling.api.modelling.ISubject;
import org.integratedmodelling.api.modelling.agents.IObservationController;
import org.integratedmodelling.api.modelling.agents.IObservationWorker;
import org.integratedmodelling.api.modelling.contextualization.IRelationshipInstantiator;
import org.integratedmodelling.api.modelling.resolution.IResolutionScope;
import org.integratedmodelling.api.modelling.scheduling.ITransition;
import org.integratedmodelling.api.modelling.storage.IDataset;
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.generic.Graph;
import org.integratedmodelling.common.configuration.KLAB;
import org.integratedmodelling.common.interfaces.NetworkSerializable;
import org.integratedmodelling.common.knowledge.Observation;
import org.integratedmodelling.common.model.Coverage;
import org.integratedmodelling.common.model.runtime.Structure;
import org.integratedmodelling.common.states.State;
import org.integratedmodelling.common.storage.MemoryDataset;
import org.integratedmodelling.common.storage.NetCDFdataset;
import org.integratedmodelling.common.vocabulary.NS;
import org.integratedmodelling.common.vocabulary.ObservableSemantics;
import org.integratedmodelling.engine.modelling.ObservationController;
import org.integratedmodelling.engine.modelling.ObservationWorker;
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.KlabRuntimeException;

public class Subject extends DirectObservation
        implements IActiveSubject, Cloneable, NetworkSerializable {

    ArrayList>     subjects         = new ArrayList<>();

    IDataset                                 backingDataset   = null;
    Structure                                structure;
    boolean                                  isPrimary;
    Map relInstantiators = new HashMap<>();

    public Subject(IObservableSemantics type, IActiveDirectObservation contextObservation,
            IScale scale, IContext context, INamespace namespace, String name,
            IMonitor monitor) {
        super(type, contextObservation, scale, context, namespace, name, monitor);
        structure = new Structure(this);
        if (scale.isTemporallyDistributed()) {
            try {
                requireBackingDataset();
            } catch (KlabException e) {
                KLAB.error(e);
            }
        }
    }

    public boolean isPrimary() {
        return isPrimary;
    }

    @Override
    public Map getObjectStateCopy() {
        HashMap result = new HashMap<>();
        IState state;
        for (Pair pd : this.states) {
            state = pd.getSecond();
            if (!(state instanceof IExtent)) {
                result.put(pd.getFirst(), state);
            }
        }
        return result;
    }

    @Override
    public void addState(IState s) throws KlabException {

        IProperty p = NS
                .getPropertyFor(s, getObservable().getSemantics(), getNamespace());
        this.states.add(new Pair<>(p, s));
        ((Observation) s).setParentId(this.getInternalId());
        if (this.context != null) {
            ((Context) this.context).addDelta(s);
        }
    }

    @Override
    public ISubject clone() {

        Subject ret = new Subject(getObservable()
                .getSemantics(), (IActiveDirectObservation) getContextObservation(), getScale(), getContext(), getNamespace(), name, monitor);
        ret.states.addAll(states);
        ret.subjects.addAll(subjects);

        return ret;
    }

    @Override
    public Collection getSubjects() {

        // FIXME this should already be ISubject and we should just return the vertexSet
        ArrayList ret = new ArrayList<>();
        for (IObservation o : structure.vertexSet()) {
            if (!o.equals(this)) {
                ret.add((ISubject) o);
            }
        }
        return ret;
    }

    public IObservation get(String path) {

        if (path.startsWith("/")) {
            path = path.substring(1);
        }
        String[] s = path.split("\\/");
        IDirectObservation ret = this;

        for (String id : s) {

            for (IState state : ret.getStates()) {
                // states have no children, so we can just return it
                if (((State) state).getInternalId().equals(id))
                    return state;
            }
            if (ret instanceof ISubject) {
                boolean found = false;
                for (ISubject subject : ((ISubject) ret).getSubjects()) {
                    if (((Subject) subject).getInternalId().equals(id)) {
                        ret = subject;
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    for (IEvent subject : ((ISubject) ret).getEvents()) {
                        if (((Observation) subject).getInternalId().equals(id)) {
                            ret = subject;
                            found = true;
                            break;
                        }
                    }
                }
                if (!found) {
                    for (IProcess subject : ((ISubject) ret).getProcesses()) {
                        if (((Observation) subject).getInternalId().equals(id)) {
                            ret = subject;
                            found = true;
                            break;
                        }
                    }
                }
                if (!found) {
                    for (IRelationship subject : ((ISubject) ret).getStructure()
                            .getRelationships()) {
                        if (((Observation) subject).getInternalId().equals(id)) {
                            ret = subject;
                            found = true;
                            break;
                        }
                    }
                }
            }
        }

        return ret;
    }

    public void removeStates() {
        states.clear();
    }

    @Override
    public String toString() {
        return "S" + getObservable().getSemantics() + ": " + getName();
    }

    public ICoverage observe(IObservableSemantics observable, Collection scenarios, boolean isOptional, IProvenance.Action cause, IMonitor monitor)
            throws KlabException {

        ICoverage ret = Coverage.EMPTY;

        if (initialized) {
            try {
                // at this point we still have the monitor for any previous task.
                resolutionContext.setMonitor(monitor);
                IResolutionScope scope = resolutionContext.forObservable(observable);
                Resolver resolver = new Resolver(scope, scenarios, cause);
                ret = resolver.resolve(observable, monitor, this);

                if (ret.isRelevant()) {
                    monitor.send(KLAB.MFACTORY
                            .adapt(scope.getResolutionGraph(), Graph.class));
                    Dataflow dataflow = new Dataflow(this, scope, monitor);
                    monitor.send(KLAB.MFACTORY.adapt(dataflow, Graph.class));
                    dataflow.run(ITransition.INITIALIZATION);
                }

            } catch (Throwable e) {
                monitor.error(e);
                throw e;
            }
        }

        return ret;
    }

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

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

        initialized = true;
        return ret;
    }

    @Override
    public void contextualize() throws KlabException {

        if (dataflow != null) {
            computePriorityOrder(dataflow);
        }

        ITemporalExtent time = getScale().getTime();
        if (time != null) {

            causalGraph = new TemporalCausalGraph<>();
            IObservationController controller = new ObservationController(causalGraph, monitor, time
                    .getEnd());

            // add the root subject (and its children) to the controller's causal graph
            // insert the FIRST time period of the temporal extent
            ITimePeriod simulationTimePeriod = time.collapse();
            addSubjectToObservationGraph(this, simulationTimePeriod, controller, null);

            // TODO for now, only create one observation worker for single-threaded
            // demonstration
            IObservationWorker worker = new ObservationWorker(controller, monitor);
            try {
                worker.run();
            } catch (Throwable e) {
                monitor.error(e);
            }
        }
    }

    /**
     * Return the backing dataset, creating if necessary. If the context is
     * spatial, use a netcdf backing file, otherwise use in-memory storage.
     * 
     * @return the non-null backing dataset.
     * @throws KlabException
     */
    public IDataset requireBackingDataset() throws KlabException {

        if (backingDataset == null) {
            if (!this.getScale().isSpatiallyDistributed()) {
                backingDataset = new MemoryDataset(this.getScale());
            } else {
                backingDataset = new NetCDFdataset(this.getScale());
            }
        }
        return backingDataset;
    }

    @Override
    public IDataset getBackingDataset() {
        return backingDataset;
    }

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

    public IMonitor getMonitor() {
        return monitor;
    }

    public void setBreakpoint(IObservation obs, boolean b) {
        // TODO Auto-generated method stub
        System.out.println("xx");
    }

    @Override
    public IStructure getStructure(Locator... locators) {
        return this.structure;
    }

    public ISubject newSubject(IObservableSemantics observable, IScale scale, String name, IProperty relationship, boolean addToParent) {

        ISubject ret = new Subject(observable, this, scale, getContext(), getNamespace(), name, monitor);
        ((Subject) ret).context = this.context;
        ((Subject) ret).contextSubject = this;
        ((Subject) ret).parentId = this.getInternalId();

        if (addToParent) {
            this.structure.addSubject(ret);
            addDirectObservation((DirectObservation) ret);
        }

        return ret;
    }

    @Override
    public ISubject newSubject(IObservableSemantics observable, IScale scale, String name, IProperty relationship)
            throws KlabException {
        return newSubject(observable, scale, name, relationship, true);
    }
    
    public IRelationship createRelationship(IObservableSemantics observable, IScale scale, String name, ISubject source, ISubject target) {
        IRelationship ret = new Relationship(getStructure(), observable, scale, getNamespace(), source, target, name, monitor);
        ((Relationship) ret).setParentId(this.getInternalId());
        ((Relationship) ret).setContext(this.context);
        ((Relationship) ret).setContextSubject(this);
        return ret;
    }
    
    @Override
    public IRelationship newRelationship(IObservableSemantics observable, IScale scale, String name, ISubject source, ISubject target) {
        IRelationship ret = createRelationship(observable, scale, name, source, target);
        addDirectObservation((DirectObservation) ret);
        return ret;
    }

    public ISubject addSubject(ISubject subject, IProperty relationship)
            throws KlabException {

        ((Subject) subject).context = this.context;
        ((Subject) subject).contextSubject = this;
        ((Subject) subject).parentId = this.getInternalId();

        this.structure.addSubject(subject);
        addDirectObservation((DirectObservation) subject);

        return subject;
    }

    @Override
    public IProcess newProcess(IObservableSemantics observable, IScale scale, String name)
            throws KlabException {
        // TODO Auto-generated method stub
        // TODO addDelta
        return null;
    }

    @Override
    public IEvent newEvent(IObservableSemantics observable, IScale scale, String name)
            throws KlabException {
        // TODO Auto-generated method stub
        // TODO addDelta
        return null;
    }

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

    public void setId(String id) {
        name = id;
    }

    @Override
    public Collection getEvents() {
        return new ArrayList<>();
    }

    public void setPrimary(boolean b) {
        isPrimary = b;
    }

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

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

        org.integratedmodelling.common.beans.Subject ret = new org.integratedmodelling.common.beans.Subject();
        super.serialize(ret);

        return (T) ret;
    }

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

    public ICoverage findPreviousObservation(IObservableSemantics observable) {
        return resolved.get(observable);
    }

    public void addPreviousObservation(IObservableSemantics observable, ICoverage coverage) {
        resolved.put(observable, coverage);
    }

    @Override
    public IRelationship connect(IActiveSubject source, IActiveSubject destination, IConcept relationshipType, ITransition transition, boolean reuse)
            throws KlabException {

        IRelationship ret = null;
        IRelationshipInstantiator ri = null;
        Map inputs = new HashMap<>();

        if (reuse) {
            ri = relInstantiators.get(relationshipType);
        }

        if (ri == null) {

            IObservableSemantics obs = new ObservableSemantics(relationshipType);
            IResolutionScope scope = resolutionContext.forObservable(obs);
            ((ResolutionScope)scope).setInstantiatingContext(true);
            Resolver resolver = new Resolver(scope, resolutionContext.getScenarios(), null);
            ICoverage coverage = resolver.resolve(obs, monitor, this);

            if (coverage.isRelevant()) {
                
                /*
                 * setup dataflow listener to grab model and instantiator
                 */
            }
            
        } else {
            ret = ri.createRelationship(source, destination, transition, inputs);
        }

        if (ri != null && reuse) {
            relInstantiators.put(relationshipType, ri);
        }

        return ret;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy