import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import org.simantics.db.Resource;
import org.simantics.db.ResourceMap;
import org.simantics.db.Statement;
+import org.simantics.db.common.StandardStatement;
import org.simantics.db.common.primitiverequest.Value;
import org.simantics.db.common.procedure.adapter.TransientCacheListener;
import org.simantics.db.common.utils.NameUtils;
import org.simantics.db.exception.CancelTransactionException;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus;
-import org.simantics.db.layer0.util.ConsistsOfProcess.InternalEntry;
+import org.simantics.db.layer0.util.ConsistsOfProcess.ConsistsOfProcessEntry;
import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest.Expansion3;
+import org.simantics.db.layer0.util.TransferableGraphConfiguration2.SeedSpec;
+import org.simantics.db.layer0.util.TransferableGraphConfiguration2.SeedSpec.SeedSpecType;
import org.simantics.db.service.CollectionSupport;
import org.simantics.db.service.SerialisationSupport;
import org.simantics.db.service.TransferableGraphSupport;
import org.simantics.graph.db.TransferableGraphSource;
import org.simantics.layer0.Layer0;
import org.simantics.scl.runtime.function.Function1;
+import org.simantics.utils.datastructures.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.hash.TIntIntHashMap;
public class DomainProcessor3 {
-
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DomainProcessor3.class);
+
public enum ExclusionDecision {
INCLUDE, EXCLUDE_OBJECT
}
int id = 0;
Set<Resource> fringe = null;
- Set<Resource> exclusions = null;
Function1<Statement,ExclusionDecision> exclusionFunction = null;
Set<Resource> predicates = null;
Map<Resource,Boolean> isRelatedToPredicates = null;
Set<Resource> deadPredicates = null;
Set<Resource> strongInverseSet = null;
-
+ List<Statement> unresolvedWeakLinks = new ArrayList<>();
TIntIntHashMap ids = null;
ResourceMap<ExtentStatus> status = null;
Map<Datatype, byte[]> bindings = new HashMap<Datatype, byte[]>();
ids = state.ids;
status = cs.createMap(ExtentStatus.class);
predicates = cs.createSet();
- exclusions = cs.createSet();
exclusionFunction = conf.exclusionFunction;
fringe = new TreeSet<Resource>();
isRelatedToPredicates = cs.createMap(Boolean.class);
deadPredicates = cs.createSet();
strongInverseSet = cs.createSet();
+ if(LOGGER.isDebugEnabled()) {
+
+ for(Map.Entry<Resource, ExtentStatus> entry : conf.preStatus.entrySet()) {
+ LOGGER.debug("prestatus: " + NameUtils.getSafeName(graph, entry.getKey()) + " " + entry.getValue());
+ }
+
+ for(SeedSpec ss : conf.seeds) {
+ LOGGER.debug("seed: " + NameUtils.getSafeName(graph, ss.resource) + " " + ss.name + " " + ss.specType + " " + ss.type);
+ }
+
+ }
+
for(Map.Entry<Resource, ExtentStatus> entry : conf.preStatus.entrySet()) {
- status.put(entry.getKey(), entry.getValue());
- if(ExtentStatus.EXCLUDED.equals(entry.getValue())) exclusions.add(entry.getKey());
- if(ExtentStatus.INTERNAL.equals(entry.getValue())) fringe.add(entry.getKey());
+ // INTERNAL prestatus shall be ignored. Domain processor will initialize statuses based on seeds.
+ if (entry.getValue().equals(ExtentStatus.INTERNAL)) {
+ LOGGER.info("Unexpected INTERNAL preStatus in DomainProcessor3 " + entry.getKey());
+ } else {
+ status.put(entry.getKey(), entry.getValue());
+ }
}
+ for(SeedSpec ss : conf.seeds) {
+ ExtentStatus pre = status.get(ss.resource);
+ // INTERNAL seeds are feed into ConsistsOfProcess
+ if(SeedSpecType.INTERNAL.equals(ss.specType)) {
+ if(pre != null && !ExtentStatus.INTERNAL.equals(pre))
+ LOGGER.info("Internal seed preclassification problem, expected INTERNAL preclassification, got " + pre.name());
+ continue;
+ } else if(SeedSpecType.ROOT.equals(ss.specType)) {
+ // Non-internal resources are not reported as internals by ConsistsOfProcess so they are manually entered into fringe
+ fringe.add(ss.resource);
+ if(pre != null)
+ LOGGER.info("Root preclassification problem, expected no preclassification, got " + pre.name());
+ // Roots are classified in status as INTERNAL
+ status.put(ss.resource, ExtentStatus.INTERNAL);
+ } else if(SeedSpecType.SPECIAL_ROOT.equals(ss.specType)) {
+ // Special roots e.g. %model are marked as EXTERNAL
+ if(pre != null && !ExtentStatus.EXTERNAL.equals(pre))
+ LOGGER.info("Special root preclassification problem, expected EXTERNAL preclassification, got " + pre.name());
+ status.put(ss.resource, ExtentStatus.EXTERNAL);
+ }
+ }
+
if(PROFILE)
startupTime += System.nanoTime();
-
-// for(RootSpec p : conf.roots) {
-// if(p.internal)
-// fringe.add(p.resource);
-// }
}
if(graph.isSubrelationOf(predicate, L0.IsRelatedTo)) {
isRelatedTo = Boolean.TRUE;
- if(ModelTransferableGraphSourceRequest.LOG) ModelTransferableGraphSourceRequest.log("isRelatedToPredicates4 => " + NameUtils.getSafeName(graph, predicate));
+ if(ModelTransferableGraphSourceRequest.DEBUG) ModelTransferableGraphSourceRequest.log("isRelatedToPredicates4 => " + NameUtils.getSafeName(graph, predicate));
} else {
if (!graph.hasStatement(predicate)) {
- if(ModelTransferableGraphSourceRequest.LOG) ModelTransferableGraphSourceRequest.log("FOUND DEAD PREDICATE (no statements): " + predicate);
+ if(ModelTransferableGraphSourceRequest.DEBUG) ModelTransferableGraphSourceRequest.log("FOUND DEAD PREDICATE (no statements): " + predicate);
deadPredicates.add(predicate);
// Prevents ModelTransferableGraphSource from
// trying to export these statements.
Resource predicate = stm.getPredicate();
Resource object = stm.getObject();
- if (exclusions.contains(object) || exclusions.contains(predicate))
- continue;
+ if(ExtentStatus.EXCLUDED.equals(status.get(predicate))) continue;
+ if(ExtentStatus.EXCLUDED.equals(status.get(object))) continue;
if (exclusionFunction != null) {
ExclusionDecision decision = exclusionFunction.apply(stm);
if(ExclusionDecision.EXCLUDE_OBJECT.equals(decision)) {
status.put(object, ExtentStatus.EXCLUDED);
- exclusions.add(object);
continue;
}
}
if(predicates.add(inverse)) schedule.add(inverse);
state.inverses.put(support.getTransientId(predicate), support.getTransientId(inverse));
state.inverses.put(support.getTransientId(inverse), support.getTransientId(predicate));
- if(ModelTransferableGraphSourceRequest.LOG) ModelTransferableGraphSourceRequest.log("INVERSE FOR " + graph.getPossibleURI(predicate) + " => " + graph.getPossibleURI(inverse));
+ if(ModelTransferableGraphSourceRequest.DEBUG) ModelTransferableGraphSourceRequest.log("INVERSE FOR " + graph.getPossibleURI(predicate) + " => " + graph.getPossibleURI(inverse));
} else {
state.inverses.put(support.getTransientId(predicate), 0);
- if(ModelTransferableGraphSourceRequest.LOG) ModelTransferableGraphSourceRequest.log("NO INVERSE FOR " + graph.getPossibleURI(predicate));
+ if(ModelTransferableGraphSourceRequest.DEBUG) ModelTransferableGraphSourceRequest.log("NO INVERSE FOR " + graph.getPossibleURI(predicate));
}
}
public void processValue(ReadGraph graph, Resource subject, int sId, final DomainProcessorState state) throws DatabaseException, IOException {
final InputStream valueStream = tgs.getValueStream(graph, subject);
if (valueStream != null) {
- if(ModelTransferableGraphSourceRequest.LOG) ModelTransferableGraphSourceRequest.log("[VALUE] " + NameUtils.getSafeName(graph, subject, true));
+ if(ModelTransferableGraphSourceRequest.DEBUG) ModelTransferableGraphSourceRequest.log("[VALUE] " + NameUtils.getSafeName(graph, subject, true));
state.valueOutput.writeInt(sId);
if (conf.values) {
Boolean isRelatedTo = isRelatedToPredicates.get(predicate);
if ((objectStatus != ExtentStatus.EXCLUDED) && isRelatedTo) {
- if(ModelTransferableGraphSourceRequest.LOG) logStatementWithExtent(graph, "related", objectStatus, subject, predicate, object);
+ if(ModelTransferableGraphSourceRequest.DEBUG) logStatementWithExtent(graph, "related", objectStatus, subject, predicate, object);
addToStream(predicate, object);
if(objectStatus == null || objectStatus == ExtentStatus.PENDING) {
- if(ModelTransferableGraphSourceRequest.LOG) ModelTransferableGraphSourceRequest.log("[ADDED TO FRINGE] " + NameUtils.getSafeName(graph, object));
+ if(ModelTransferableGraphSourceRequest.DEBUG) ModelTransferableGraphSourceRequest.log("[ADDED TO FRINGE] " + NameUtils.getSafeName(graph, object));
fringe.add(object);
}
// Dead predicate
if (deadPredicates.contains(predicate)) {
- if(ModelTransferableGraphSourceRequest.LOG) logStatementWithExtent(graph, "excluding statement with dead predicate ", objectStatus, subject, predicate, object);
+ if(ModelTransferableGraphSourceRequest.DEBUG) logStatementWithExtent(graph, "excluding statement with dead predicate ", objectStatus, subject, predicate, object);
return;
}
// Weak predicate
if(objectStatus == ExtentStatus.EXCLUDED) {
- if(ModelTransferableGraphSourceRequest.LOG) logStatementWithExtent(graph, "weak reference to excluded object ", objectStatus, subject, predicate, object);
+ if(ModelTransferableGraphSourceRequest.DEBUG) logStatementWithExtent(graph, "weak reference to excluded object ", objectStatus, subject, predicate, object);
} else {
// The inverse is also weak (or there is no inverse)
if(!strongInverseSet.contains(predicate)) {
-
- addToStream(predicate, object);
+
+ unresolvedWeakLinks.add(new StandardStatement(subject, predicate, object));
+ //addToStream(predicate, object);
if(objectStatus == null) {
status.put(object, ExtentStatus.PENDING);
}
- if(ModelTransferableGraphSourceRequest.LOG) logStatementWithExtent(graph, "fully weak internal", objectStatus, subject, predicate, object);
+ if(ModelTransferableGraphSourceRequest.DEBUG) logStatementWithExtent(graph, "fully weak internal", objectStatus, subject, predicate, object);
} else {
- if(ModelTransferableGraphSourceRequest.LOG) logStatementWithExtent(graph, "strong inverse internal ", objectStatus, subject, predicate, object);
+ if(ModelTransferableGraphSourceRequest.DEBUG) logStatementWithExtent(graph, "strong inverse internal ", objectStatus, subject, predicate, object);
}
}
status.put(subject, ExtentStatus.INTERNAL);
- if(ModelTransferableGraphSourceRequest.LOG) ModelTransferableGraphSourceRequest.log("[INTERNAL] " + NameUtils.getSafeName(graph, subject, true));
+ if(ModelTransferableGraphSourceRequest.DEBUG) ModelTransferableGraphSourceRequest.log("[INTERNAL] " + NameUtils.getSafeName(graph, subject, true));
int sId = support.getTransientId(subject);
}
ExtentStatus subjectStatus = status.get(subject);
- if(ModelTransferableGraphSourceRequest.LOG && subjectStatus != null) ModelTransferableGraphSourceRequest.log("EXISTING STATUS FOR " + graph.getPossibleURI(subject) + " - " + subjectStatus);
+ if(ModelTransferableGraphSourceRequest.DEBUG && subjectStatus != null) ModelTransferableGraphSourceRequest.log("EXISTING STATUS FOR " + graph.getPossibleURI(subject) + " - " + subjectStatus);
if(subjectStatus == ExtentStatus.EXTERNAL || subjectStatus == ExtentStatus.EXCLUDED) continue;
if(partOf && (subjectStatus == null || ExtentStatus.PENDING == subjectStatus) && graph.getPossibleURI(subject) != null) {
status.put(subject, ExtentStatus.EXTERNAL);
- if(ModelTransferableGraphSourceRequest.LOG) {
+ if(ModelTransferableGraphSourceRequest.DEBUG) {
String uri = graph.getPossibleURI(subject);
if(uri == null) ModelTransferableGraphSourceRequest.log("[EXTERNAL]: No URI for " + subject);
else ModelTransferableGraphSourceRequest.log("[EXTERNAL] " + uri);
this.datatypeBinding = Bindings.getBindingUnchecked(Datatype.class);
this.datatypeSerializer = graph.getService(Databoard.class).getSerializerUnchecked(this.datatypeBinding);
- state.internalEntries = ConsistsOfProcess.walk(graph, status, fringe, exclusions, ignoreVirtual);
+ Pair<List<ConsistsOfProcessEntry>,Set<Resource>> pair = ConsistsOfProcess.walk(graph, status, conf.seeds, ignoreVirtual);
+ state.internalEntries = pair.first;
- for(InternalEntry entry : state.internalEntries) {
+ for(ConsistsOfProcessEntry entry : state.internalEntries) {
Resource r = entry.resource;
if (status.put(r, ExtentStatus.INTERNAL) == null) {
- if(ModelTransferableGraphSourceRequest.LOG) {
+ if(ModelTransferableGraphSourceRequest.DEBUG) {
String URI = graph.getPossibleURI(r);
if(URI != null) ModelTransferableGraphSourceRequest.log("URI INTERNAL " + URI);
else ModelTransferableGraphSourceRequest.log("URI has no URI for " + r);
}
}
+ for(Resource unnamedChild : pair.second) {
+ if (status.put(unnamedChild, ExtentStatus.INTERNAL) == null) {
+ fringe.add(unnamedChild);
+ }
+ }
+
if (state.monitor.isCanceled())
throw new CancelTransactionException();
}
void logStatementWithExtent(ReadGraph graph, String header, ExtentStatus status, int sId, int pId, int oId) throws DatabaseException {
- if(ModelTransferableGraphSourceRequest.LOG) {
+ if(ModelTransferableGraphSourceRequest.DEBUG) {
SerialisationSupport support = graph.getService(SerialisationSupport.class);
String s = NameUtils.getURIOrSafeNameInternal(graph, support.getResource(sId));
String p = NameUtils.getURIOrSafeNameInternal(graph, support.getResource(pId));
}
void logStatementWithExtent(ReadGraph graph, String header, ExtentStatus status, Resource sId, Resource pId, Resource oId) throws DatabaseException {
- if(ModelTransferableGraphSourceRequest.LOG) {
+ if(ModelTransferableGraphSourceRequest.DEBUG) {
String s = NameUtils.getURIOrSafeNameInternal(graph, sId);
String p = NameUtils.getURIOrSafeNameInternal(graph, pId);
String o = NameUtils.getURIOrSafeNameInternal(graph, oId);