From 1cc487c3f6cf4b46b1fdd727183a9483e3bc05bb Mon Sep 17 00:00:00 2001 From: jsimomaa Date: Mon, 5 Jun 2017 15:00:05 +0300 Subject: [PATCH] Make prettyPrintTG available via SCL from Simantics/DB-module refs #7276 Change-Id: I640f4cb6d929482577ed8874e6b8fadcaa05ba64 --- .../simantics/db/layer0/util/Layer0Utils.java | 10 +- .../refactoring/GraphRefactoringUtils.java | 16 + .../graph/representation/PrettyPrintTG.java | 383 +++++++++++++----- .../TransferableGraphUtils.java | 3 + .../org.simantics.scl.db/scl/Simantics/DB.scl | 1 + 5 files changed, 314 insertions(+), 99 deletions(-) diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java index adc51c16d..08dd63ce0 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java @@ -106,6 +106,7 @@ import org.simantics.graph.db.TransferableGraphs; import org.simantics.graph.diff.Diff; import org.simantics.graph.diff.TransferableGraphDelta1; import org.simantics.graph.refactoring.GraphRefactoringUtils; +import org.simantics.graph.representation.PrettyPrintTG; import org.simantics.graph.representation.TransferableGraph1; import org.simantics.layer0.Layer0; import org.simantics.operation.Layer0X; @@ -1193,7 +1194,7 @@ public class Layer0Utils { } - private static TransferableGraphSource makeTGSource(ReadGraph graph, Resource r) throws DatabaseException { + public static TransferableGraphSource makeTGSource(ReadGraph graph, Resource r) throws DatabaseException { SimanticsClipboardImpl cp = new SimanticsClipboardImpl(); CopyHandler c1 = graph.adapt(r, CopyHandler.class); @@ -1378,4 +1379,11 @@ public class Layer0Utils { } + public static String prettyPrintResource(ReadGraph graph, Resource resource) throws Exception { + TransferableGraphSource source = makeTGSource(graph, resource); + TransferableGraph1 tg = TransferableGraphs.create(graph, source); + GraphRefactoringUtils.fixOntologyExport(tg); + return PrettyPrintTG.print(tg); + } + } diff --git a/bundles/org.simantics.graph/src/org/simantics/graph/refactoring/GraphRefactoringUtils.java b/bundles/org.simantics.graph/src/org/simantics/graph/refactoring/GraphRefactoringUtils.java index 9f8eca398..90b134e33 100644 --- a/bundles/org.simantics.graph/src/org/simantics/graph/refactoring/GraphRefactoringUtils.java +++ b/bundles/org.simantics.graph/src/org/simantics/graph/refactoring/GraphRefactoringUtils.java @@ -128,6 +128,22 @@ public class GraphRefactoringUtils { return; + } else if (ext.type.startsWith("http://")) { + String first = "http://Projects/Development Project"; + Identity path = recursePath(tg, first); + id.definition = new Internal(path.resource, ext.name); + + GraphStore store = TransferableGraphConversion.convert(tg); + int rootId = store.identities.createPathToId(UriUtils.uriToPath(first + "/" + ext.name)); + propagateNewMarks(store.identities, rootId); + + TransferableGraph1 tgNew = TransferableGraphConversion.convert(store); + + tg.resourceCount = tgNew.resourceCount; + tg.identities = tgNew.identities; + tg.values = tgNew.values; + tg.statements = tgNew.statements; + } } } diff --git a/bundles/org.simantics.graph/src/org/simantics/graph/representation/PrettyPrintTG.java b/bundles/org.simantics.graph/src/org/simantics/graph/representation/PrettyPrintTG.java index 00d17100e..bb776d5df 100644 --- a/bundles/org.simantics.graph/src/org/simantics/graph/representation/PrettyPrintTG.java +++ b/bundles/org.simantics.graph/src/org/simantics/graph/representation/PrettyPrintTG.java @@ -11,6 +11,7 @@ import java.nio.file.Paths; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -19,22 +20,29 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.simantics.databoard.Bindings; -import org.simantics.databoard.Datatypes; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.mutable.Variant; import org.simantics.databoard.container.DataContainers; -import org.simantics.databoard.type.Datatype; +import org.simantics.databoard.parser.DataValuePrinter; +import org.simantics.databoard.parser.PrintFormat; +import org.simantics.databoard.parser.repository.DataValueRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TIntIntHashMap; import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.procedure.TIntIntProcedure; import gnu.trove.set.hash.TLongHashSet; /** * @author Antti Villberg * @since 1.24.0 */ -public class PrettyPrintTG extends TransferableGraphUtils { +public class PrettyPrintTG { + private static final Logger LOGGER = LoggerFactory.getLogger(PrettyPrintTG.class); + int blankCounter = 0; MessageDigest m; @@ -50,16 +58,33 @@ public class PrettyPrintTG extends TransferableGraphUtils { final int resource; boolean newResource = false; + int parent; + + boolean inlined = false; + // -1 = no owner, -2 = multiple owners - int owner = -1; - int ownerPredicate = 0; + + // Set ownedBy + Set ownedBy = new HashSet<>(); + + // A Map containing information about resource that this resource owns and what are the predicates for forming this ownership + TIntIntHashMap ownedResourcesWithPredicates = new TIntIntHashMap(); + +// int owner = -1; +// int ownerPredicate = 0; String aliasURI = null; TIntArrayList owned = new TIntArrayList(); //TIntObjectHashMap statements = new TIntObjectHashMap(); - public ResourceInfo(boolean hasURI, String name, int resource) { + public ResourceInfo(boolean hasURI, String name, int resource, int parent) { this.hasURI = hasURI; this.name = name; this.resource = resource; + this.parent = parent; + } + + @Override + public String toString() { + return name + (aliasURI != null ? " = <" + aliasURI + ">" : ""); } } @@ -79,32 +104,32 @@ public class PrettyPrintTG extends TransferableGraphUtils { else return name; } - ResourceInfo recurseURI(TransferableGraph1 graph, Identity parent, String parentName) { - String name = parentName + "." + tgNodeName(getName(parent)); - ResourceInfo info = new ResourceInfo(true, name, parent.resource); + ResourceInfo recurseURI(TransferableGraph1 graph, Identity parent, String parentName, int parentId) { + String name = parentName + "." + tgNodeName(TransferableGraphUtils.getName(parent)); + ResourceInfo info = new ResourceInfo(true, name, parent.resource, parentId); infos.put(parent.resource, info); - for(Identity child : getChildren(graph, parent)) { - recurseURI(graph, child, name); + for(Identity child : TransferableGraphUtils.getChildren(graph, parent)) { + recurseURI(graph, child, name, info.resource); } return info; } void discoverBlank(TransferableGraph1 graph, int resource, TIntArrayList todo) throws Exception { - TIntArrayList statements = getStatements(graph, resource); + TIntArrayList statements = TransferableGraphUtils.getStatements(graph, resource); for(int i=0;i " + predicateURI + " " + existing.name); - } else { - existing.owner = -2; - //System.err.println("Multiple owners " + info.name + " => " + predicateURI + " " + existing.name); + if(existing != null) { + // Add all owners here for now and resolve the best owner later + existing.ownedResourcesWithPredicates.put(resource, predicate); + // Check if predicate is inverse, this just resolves all predicates to be inverse with ending "Inverse".. + String predicateUri = rewritePredicateURI(graph, predicate); + if (!predicateUri.endsWith("Inverse")) { + existing.ownedBy.add(info); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(" " + existing + " owns " + info + " with " + predicateUri); + } + } } } - } - String printValue(Value value) throws Exception { - Variant variant = value.value; - Datatype dt = variant.getBinding().type(); - if(Datatypes.STRING.equals(dt)) { - String s = (String)variant.getValue(Bindings.STRING); - if(s.contains("\n")) { - return "\"\"\"" + s + "\"\"\""; - } else { - return "\"" + s + "\""; - } - } else if(Datatypes.BOOLEAN.equals(dt)) { - Boolean i = (Boolean)variant.getValue(Bindings.BOOLEAN); - return i ? "true" : "false"; - } else if(Datatypes.INTEGER.equals(dt)) { - Integer i = (Integer)variant.getValue(Bindings.INTEGER); - return i.toString(); - } else if(Datatypes.LONG.equals(dt)) { - Long i = (Long)variant.getValue(Bindings.LONG); - return i.toString(); - } else { - byte[] data = variant.getBinding().serializer().serialize(variant.getValue()); - m.reset(); - m.update(data, 0, data.length); - return "\"" + new BigInteger(1, m.digest()).toString(16) + "\""; - } - - } + DataValueRepository repo = new DataValueRepository(); + DataValuePrinter printer = new DataValuePrinter(null, repo); + + String printValue(Value value) throws Exception { + StringBuilder sb = new StringBuilder(); + printer.setFormat(PrintFormat.SINGLE_LINE); + printer.setOutput(sb); + + Variant variant = value.value; + printer.print(variant.getBinding(), variant.getValue()); + String formattedOutput = sb.toString(); + if (formattedOutput.length() > 100) { + // Ok, value too long, lets calculate a hash for it and store first 100 chars as comment + byte[] data = Bindings.getSerializerUnchecked(variant.getBinding()).serialize(variant.getValue()); + m.reset(); + m.update(data, 0, data.length); + String hash = "\"" + new BigInteger(1, m.digest()).toString(16) + "\""; + return hash + " // " + formattedOutput.substring(0, 100) + ".."; + } else { + return formattedOutput; + } +// +// Variant variant = value.value; +// Datatype dt = variant.getBinding().type(); +// if (Datatypes.STRING.equals(dt)) { +// String s = (String) variant.getValue(Bindings.STRING); +// if (s.contains("\n")) { +// return "\"\"\"" + s + "\"\"\""; +// } else { +// return "\"" + s + "\""; +// } +// } else if (Datatypes.BOOLEAN.equals(dt)) { +// Boolean i = (Boolean) variant.getValue(Bindings.BOOLEAN); +// return i ? "true" : "false"; +// } else if (Datatypes.INTEGER.equals(dt)) { +// Integer i = (Integer) variant.getValue(Bindings.INTEGER); +// return i.toString(); +// } else if (Datatypes.LONG.equals(dt)) { +// Long i = (Long) variant.getValue(Bindings.LONG); +// return i.toString(); +// } else if (Datatypes.DOUBLE.equals(dt)) { +// Double d = (Double) variant.getValue(); +// return d.toString(); +// } else if (Datatypes.FLOAT.equals(dt)) { +// Float f = (Float) variant.getValue(); +// return f.toString(); +// } else if (Datatypes.STRING_ARRAY.equals(dt)) { +// return Arrays.toString((String []) variant.getValue()); +// } else if (Datatypes.BOOLEAN_ARRAY.equals(dt)) { +// return Arrays.toString((boolean []) variant.getValue()); +// } else if (Datatypes.INTEGER_ARRAY.equals(dt)) { +// return Arrays.toString((int []) variant.getValue()); +// } else if (Datatypes.LONG_ARRAY.equals(dt)) { +// return Arrays.toString((long []) variant.getValue()); +// } else if (Datatypes.DOUBLE_ARRAY.equals(dt)) { +// return Arrays.toString((double []) variant.getValue()); +// } else if (Datatypes.FLOAT_ARRAY.equals(dt)) { +// return Arrays.toString((float []) variant.getValue()); +// } else if (Datatypes.BYTE_ARRAY.equals(dt)) { +// return Arrays.toString((byte []) variant.getValue()); +//// } else if (dt instanceof ArrayType) { +//// return Arrays.toString((Object []) variant.getValue()); +// } else { +// byte[] data = Bindings.getSerializerUnchecked(variant.getBinding()).serialize(variant.getValue()); +// m.reset(); +// m.update(data, 0, data.length); +// return "\"" + new BigInteger(1, m.digest()).toString(16) + "\""; +// } + + } // void fixInstanceOf(TransferableGraph1 graph, ResourceInfo info) { // Identity id = getIdentity(graph, info.resource); @@ -176,7 +248,7 @@ public class PrettyPrintTG extends TransferableGraphUtils { int parentId = ext.parent; //if(parentId == 0) return ext.name; // else { - Identity id = getIdentity(tg, parentId); + Identity id = TransferableGraphUtils.getIdentity(tg, parentId); if(id.definition instanceof External) { return getExternalURI(tg, (External)id.definition) + "/" + name; } else if(id.definition instanceof Root) { @@ -189,7 +261,7 @@ public class PrettyPrintTG extends TransferableGraphUtils { } public static String getExternalURI(TransferableGraph1 tg, int resource) { - Identity id = getIdentity(tg, resource); + Identity id = TransferableGraphUtils.getIdentity(tg, resource); if(id == null) return null; if(id.definition instanceof External) { External ext = (External)id.definition; @@ -221,27 +293,56 @@ public class PrettyPrintTG extends TransferableGraphUtils { } - void indent(int indent) { - for(int i=0;i> statements, String predicate, ResourceInfo objectInfo, int indent) { + Set objects = statements.get(predicate); + if(objects == null) { + objects = new TreeSet<>(); + statements.put(predicate, objects); + } + String uri = printURI(graph, objectInfo, false, indent + 1, true); + if (uri != null) { + // TODO: this is not the right place to remove trailing newline + uri = uri.endsWith("\n") ? uri.substring(0, uri.length() - 2) : uri; + objects.add(uri); + } + objectInfo.inlined = true; + } + + void addStatement(Map> statements, String predicate, String object) { + // TODO: fix this + if (predicate.endsWith("Inverse")) + return; Set objects = statements.get(predicate); if(objects == null) { objects = new TreeSet<>(); @@ -250,19 +351,24 @@ public class PrettyPrintTG extends TransferableGraphUtils { objects.add(object); } - void printURI(TransferableGraph1 graph, ResourceInfo info, boolean requireURI, int indent) { + String printURI(TransferableGraph1 graph, ResourceInfo info, boolean requireURI, int indent, boolean inline) { - if(requireURI && !info.hasURI) return; + if(requireURI && !info.hasURI) + return null; + + // Check if this ResourceInfo is already inlined with some other ResourceInfo + if (info.inlined) + return null; Map> statements = new TreeMap<>(); - Identity consistsOf = findExternal(graph, "http://www.simantics.org/Layer0-1.1/ConsistsOf"); + Identity consistsOf = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Layer0-1.1/ConsistsOf"); TLongHashSet processed = new TLongHashSet(); for(int i=0;i debug = new HashSet<>(); + info.ownedResourcesWithPredicates.forEachEntry(new TIntIntProcedure() { + + @Override + public boolean execute(int owner, int predicate) { + ResourceInfo ownerInfo = infos.get(owner); + debug.add(ownerInfo); +// ResourceInfo predicateInfo = infos.get(predicate); +// debug.add(predicateInfo); + return true; + } + }); + + StringBuilder output = new StringBuilder(); + + if(indent == 0 || inline) { if("ROOT".equals(info.name)) { output.append("ROOT="); } else if (info.aliasURI != null) { output.append(info.name + " = <" + info.aliasURI + ">"); } else { - output.append(info.name); + if (inline) + System.out.println("asdasd"); + output.append(inline ? "_" : info.name); } Set instanceOfs = statements.get("L0.InstanceOf"); if(instanceOfs != null) { @@ -316,14 +442,13 @@ public class PrettyPrintTG extends TransferableGraphUtils { if("L0.Inherits".equals(predicate)) continue; if("L0.PartOf".equals(predicate)) continue; Set objects = entry.getValue(); + indent(output, indent+1); if(objects.size() == 1) { - indent(indent+1); output.append(predicate + " " + objects.iterator().next() + "\n"); } else{ - indent(indent+1); output.append(predicate + "\n"); for(String object : objects) { - indent(indent+1); + indent(output, indent+1); output.append(" " + object + "\n"); } } @@ -332,12 +457,15 @@ public class PrettyPrintTG extends TransferableGraphUtils { for(int i=0;i= 0) { - ResourceInfo ownerInfo = infos.get(info.owner); - ownerInfo.owned.add(info.ownerPredicate); - ownerInfo.owned.add(info.resource); - } - + + for (ResourceInfo info : infos.valueCollection()) { +// Old implementation +// if (info.owner >= 0) { +// ResourceInfo ownerInfo = infos.get(info.owner); +// System.out.println("originalOwner : " + info.owner + " originalPredicate: " + info.ownerPredicate); +// ownerInfo.owned.add(info.ownerPredicate); +// ownerInfo.owned.add(info.resource); +// } + + if (!info.ownedResourcesWithPredicates.isEmpty() && info.ownedResourcesWithPredicates.size() == 1) { + info.ownedResourcesWithPredicates.forEachEntry(new TIntIntProcedure() { + + @Override + public boolean execute(int owner, int predicate) { + ResourceInfo ownerInfo = infos.get(owner); + ownerInfo.owned.add(predicate); + ownerInfo.owned.add(info.resource); + return false; + } + }); + } + } + + // Resolve inverses from ownedBy list + for (ResourceInfo info : infos.valueCollection()) { + for (int i = 0; i < info.owned.size(); i+=2) { + int object = info.owned.get(i+1); + ResourceInfo inf = infos.get(object); + if (inf != null) { + info.ownedBy.remove(inf); + } + } + } + TreeMap order = new TreeMap<>(); for(ResourceInfo info : infos.valueCollection()) order.put(info.name, info); - for(ResourceInfo info : order.values()) - printURI(graph, info, true, 0); + for(ResourceInfo info : order.values()) { + String uri = printURI(graph, info, true, 0, false); + if (uri != null) + output.append(uri); + } - for(ResourceInfo info : order.values()) - if(!info.hasURI && info.owner < 0) - printURI(graph, info, false, 0); + for (ResourceInfo info : order.values()) { + if (!info.hasURI && info.ownedResourcesWithPredicates.size() != 1) { + String uri = printURI(graph, info, false, 0, false); + if (uri != null) + output.append(uri); + } + } +// for(ResourceInfo info : order.values()) +// if(!info.hasURI && info.owner < 0) +// printURI(graph, info, false, 0); StringBuilder refs = new StringBuilder(); for(String ontology : referencedOntologies) { String key = ontologies.get(ontology); refs.append(key + " = <" + ontology + ">\n"); } + if (!referencedOntologies.isEmpty()) + refs.append("\n"); output.insert(0, refs.toString()); } - public static String print(TransferableGraph1 tg) throws Exception { + public static String print(TransferableGraph1 tg) throws Exception { StringBuilder b = new StringBuilder(); new PrettyPrintTG(b).prettyPrint(tg); return b.toString(); diff --git a/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphUtils.java b/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphUtils.java index 4b113fa49..a7b92c8d0 100644 --- a/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphUtils.java +++ b/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphUtils.java @@ -71,6 +71,9 @@ public class TransferableGraphUtils { String[] tokens = uri.substring("http://".length()).split("/"); for(String token : tokens) { identity = findExternalWithNameAndParent(tg, identity.resource, token); + if (identity == null) { + return null; + } } return identity; diff --git a/bundles/org.simantics.scl.db/scl/Simantics/DB.scl b/bundles/org.simantics.scl.db/scl/Simantics/DB.scl index b725d6c74..19e83d30b 100644 --- a/bundles/org.simantics.scl.db/scl/Simantics/DB.scl +++ b/bundles/org.simantics.scl.db/scl/Simantics/DB.scl @@ -343,6 +343,7 @@ importJava "org.simantics.db.layer0.util.Layer0Utils" where listOntologies :: () -> [Resource] emptyTrashBin :: () -> () purgeDatabase :: () -> () + prettyPrintResource :: Resource -> String @private @JavaName copyTo -- 2.43.2