package org.simantics.graph.db; import gnu.trove.list.array.TIntArrayList; import gnu.trove.map.hash.THashMap; import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.set.hash.THashSet; import java.util.ArrayList; import org.simantics.databoard.Bindings; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.mutable.Variant; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Statement; import org.simantics.db.VirtualGraph; import org.simantics.db.exception.DatabaseException; import org.simantics.db.service.VirtualGraphSupport; import org.simantics.graph.representation.External; import org.simantics.graph.representation.Identity; import org.simantics.graph.representation.IdentityDefinition; import org.simantics.graph.representation.Internal; import org.simantics.graph.representation.TransferableGraph1; import org.simantics.graph.representation.Value; import org.simantics.layer0.Layer0; public class VirtualGraphExport { ReadGraph g; VirtualGraph vg; VirtualGraphSupport vgs; Layer0 L0; THashSet nameResources = new THashSet(); THashMap names = new THashMap(); TObjectIntHashMap resourceIds = new TObjectIntHashMap(); ArrayList identities = new ArrayList(); ArrayList values = new ArrayList(); TIntArrayList statements = new TIntArrayList(); private VirtualGraphExport(ReadGraph g, VirtualGraph vg) { this.g = g; this.vg = vg; this.vgs = g.getService(VirtualGraphSupport.class); this.L0 = Layer0.getInstance(g); } /** * Finds resource names and name resources. */ private void processNames() throws DatabaseException { for(Statement stat : vgs.listStatements(vg)) { Resource p = stat.getPredicate(); if(p.equals(L0.HasName)) { Resource s = stat.getSubject(); Resource o = stat.getObject(); names.put(s, (String)g.getValue(o)); nameResources.add(o); } } } /** * If the resource is encountered first time, adds it * to resourceIds map and creates an identity for it. */ private void prepareResource(Resource resource) throws DatabaseException { if(!resourceIds.containsKey(resource)) { int newId = resourceIds.size(); resourceIds.put(resource, newId); String name = names.get(resource); if(name != null) { Resource parent = g.getPossibleObject(resource, L0.PartOf); if(parent != null) { prepareResource(parent); int parentId = resourceIds.get(parent); IdentityDefinition def = resource.isPersistent() ? new External(parentId, name) : new Internal(parentId, name); identities.add(new Identity(newId, def)); } } } } /** * Process all statements of the virtual graph and * adds them to integer table that will be part of the * transferable graph, */ private void processStatements() throws DatabaseException { for(Statement stat : vgs.listStatements(vg)) { /* * Skips the statement if its subject or object is * a name literal or if its predicate is ConsistsOf, * HasName or inverse of these relations. */ Resource s = stat.getSubject(); if(nameResources.contains(s)) continue; Resource p = stat.getPredicate(); if(p.equals(L0.PartOf) || p.equals(L0.ConsistsOf) || p.equals(L0.HasName) || p.equals(L0.NameOf)) continue; Resource o = stat.getObject(); if(nameResources.contains(o)) continue; /* * Adds resources to resourceIds map and generates identities. */ prepareResource(s); prepareResource(p); prepareResource(o); /* * Adds a statement */ statements.add(resourceIds.get(s)); statements.add(resourceIds.get(p)); statements.add(-1); statements.add(resourceIds.get(o)); } } /** * Process all values of the virtual graph. */ private void processValues() throws DatabaseException { for(Resource resourceWithValue : vgs.listValues(vg)) { if(nameResources.contains(resourceWithValue)) continue; Binding binding = Bindings.getBeanBinding(g.getDataType(resourceWithValue)); Object value = g.getValue(resourceWithValue, binding); values.add(new Value(resourceIds.get(resourceWithValue), new Variant(binding, value) )); } } /** * Creates a virtual graph. */ private TransferableGraph1 getTransferableGraph() { return new TransferableGraph1(resourceIds.size(), identities.toArray(new Identity[identities.size()]), statements.toArray(), values.toArray(new Value[values.size()])); } /** * Converts the contents of a virtual graph to a transferable graph. */ public static TransferableGraph1 export(ReadGraph g, VirtualGraph vg) throws DatabaseException { VirtualGraphExport export = new VirtualGraphExport(g, vg); export.processNames(); export.processStatements(); export.processValues(); return export.getTransferableGraph(); } }