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;
}
}