1 package org.simantics.graph.representation;
3 import java.io.BufferedInputStream;
4 import java.io.DataInput;
5 import java.io.DataInputStream;
6 import java.io.InputStream;
7 import java.math.BigInteger;
8 import java.nio.file.Files;
9 import java.nio.file.Path;
10 import java.nio.file.Paths;
11 import java.security.MessageDigest;
12 import java.security.NoSuchAlgorithmException;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.List;
18 import java.util.Map.Entry;
20 import java.util.TreeMap;
21 import java.util.TreeSet;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24 import java.util.stream.Collectors;
26 import org.simantics.databoard.Bindings;
27 import org.simantics.databoard.binding.Binding;
28 import org.simantics.databoard.binding.mutable.Variant;
29 import org.simantics.databoard.container.DataContainers;
30 import org.simantics.databoard.parser.DataValuePrinter;
31 import org.simantics.databoard.parser.PrintFormat;
32 import org.simantics.databoard.parser.repository.DataValueRepository;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 import gnu.trove.list.array.TIntArrayList;
37 import gnu.trove.map.hash.THashMap;
38 import gnu.trove.map.hash.TIntIntHashMap;
39 import gnu.trove.map.hash.TIntObjectHashMap;
40 import gnu.trove.procedure.TIntIntProcedure;
41 import gnu.trove.set.hash.TLongHashSet;
44 * @author Antti Villberg
47 public class PrettyPrintTG {
49 private static final Logger LOGGER = LoggerFactory.getLogger(PrettyPrintTG.class);
51 private static final boolean DEBUG = false;
54 int newBlankCounter = 0;
55 Map<String, String> blankRewrites = new HashMap<>();
58 private final Pattern versionExtractPattern = Pattern.compile("^.*-(\\d+\\.\\d+)");
60 final StringBuilder output;
61 final Map<String, String> ontologies = new HashMap<>(knownOntologies);
62 final Set<String> referencedOntologies = new TreeSet<>();
64 private boolean ignoreIdentifiers;
66 private TransferableGraphQueries query;
68 static class ResourceInfo {
72 boolean newResource = false;
76 boolean inlined = false;
78 // -1 = no owner, -2 = multiple owners
80 // Set<ResourceInfo> ownedBy
81 Set<ResourceInfo> ownedBy = new HashSet<>();
83 // A Map<Integer, Integer> containing information about resource that
84 // this resource owns and what are the predicates for forming this
86 TIntIntHashMap ownedResourcesWithPredicates = new TIntIntHashMap();
89 // int ownerPredicate = 0;
90 String aliasURI = null;
91 TIntArrayList owned = new TIntArrayList();
93 // TIntObjectHashMap<TIntHashSet> statements = new
94 // TIntObjectHashMap<TIntHashSet>();
95 public ResourceInfo(boolean hasURI, String name, int resource, int parent) {
98 this.resource = resource;
103 public String toString() {
104 return name + (aliasURI != null ? " = <" + aliasURI + ">" : "");
108 public PrettyPrintTG(TransferableGraph1 tg, StringBuilder b, boolean ignoreIdentifiers) throws NoSuchAlgorithmException {
110 m = MessageDigest.getInstance("SHA-256");
111 this.ignoreIdentifiers = ignoreIdentifiers;
113 this.query = new TransferableGraphQueries(tg);
116 public PrettyPrintTG(TransferableGraph1 tg) throws NoSuchAlgorithmException {
117 this(tg, new StringBuilder(), false);
120 TreeMap<String, ResourceInfo> orderedInfos = new TreeMap<>();
121 TIntObjectHashMap<ResourceInfo> infos = new TIntObjectHashMap<>();
123 private static String tgNodeName(String name) {
124 if (name.contains(" "))
125 return "\"" + name + "\"";
130 private ResourceInfo recurseURI(Map<String, ResourceInfo> infos, Identity identity, String parentName, int parentId) {
131 String name = parentName + "." + tgNodeName(TransferableGraphUtils.getName(identity));
132 int identityResource = identity.resource;
133 ResourceInfo info = new ResourceInfo(true, name, identityResource, parentId);
134 infos.put(name, info);
135 for (Identity child : query.getChildren(identity))
136 recurseURI(infos, child, name, identityResource);
141 * Sorts statements by predicateURI in natural order
147 private TreeMap<String, TreeSet<Integer>> sortByPredicateUniqueStatements(int resource) {
148 TreeMap<String, TreeSet<Integer>> results = new TreeMap<>();
149 TIntArrayList statements = query.getStatements(resource);
150 for (int i = 0; i < statements.size(); i += 2) {
151 int predicate = statements.get(i);
152 String predicateURI = query.getURI(predicate);
153 TreeSet<Integer> objects = results.get(predicateURI);
154 if (objects == null) {
155 objects = new TreeSet<>();
157 objects.add(statements.get(i + 1));
158 results.put(predicateURI, objects);
163 void discoverBlank(int resource, TIntArrayList todo) throws Exception {
164 // TIntArrayList statements =
165 // TransferableGraphUtils.getStatements(graph, resource);
166 // for(int i=0;i<statements.size();i+=2) {
167 for (TreeSet<Integer> objects : sortByPredicateUniqueStatements(resource).values()) {
168 for (int object : objects) {
169 // int object = statements.get(i+1);
170 Identity objectId = query.getIdentity(object);
171 if (objectId != null) {
172 if (objectId.definition instanceof External)
175 Value value = query.findValue(object);
177 infos.put(object, new ResourceInfo(false, printValue(value), object, resource));
179 ResourceInfo existing = infos.get(object);
180 if (existing == null) {
182 existing = new ResourceInfo(false, "blank" + blankCounter++, object, resource);
184 // System.out.println("created blank" + blankCounter + "
185 // with object " + object + " resource " + resource);
186 infos.put(object, existing);
194 private String makeHash(byte[] data) {
196 m.update(data, 0, data.length);
197 return new BigInteger(1, m.digest()).toString(16);
200 void discoverOwners(ResourceInfo info) {
201 log("Discovering owners for {}", info);
202 int resource = info.resource;
203 TIntArrayList statements = query.getStatements(resource);
204 for (int i = 0; i < statements.size(); i += 2) {
205 int predicate = statements.get(i);
206 int object = statements.get(i + 1);
207 ResourceInfo existing = infos.get(object);
208 if (existing != null) {
209 // Add all owners here for now and resolve the best owner later
211 // Check if predicate is inverse, this just resolves all
212 // predicates to be inverse with ending "Inverse"..
213 String predicateUri = rewritePredicateURI(predicate);
214 if (!predicateUri.endsWith("Inverse") && !predicateUri.endsWith("Of")) {
215 existing.ownedResourcesWithPredicates.put(resource, predicate);
216 // if (predicateUri.endsWith("Of")) {
217 // System.out.println("asd");
219 existing.ownedBy.add(info);
220 log(" {} owns {} with {}", existing, info, predicateUri);
223 // System.out.println("asd");
229 DataValueRepository repo = new DataValueRepository();
230 DataValuePrinter printer = new DataValuePrinter(null, repo);
232 String printValue(Value value) throws Exception {
233 StringBuilder sb = new StringBuilder();
234 printer.setFormat(PrintFormat.SINGLE_LINE);
235 printer.setOutput(sb);
237 Variant variant = value.value;
238 printer.print(variant.getBinding(), variant.getValue());
239 String formattedOutput = sb.toString();
240 if (formattedOutput.length() > 100) {
241 // Ok, value too long, lets calculate a hash for it and store first
242 // 100 chars as comment
243 byte[] data = Bindings.getSerializerUnchecked(variant.getBinding()).serialize(variant.getValue());
245 m.update(data, 0, data.length);
246 String hash = "\"" + new BigInteger(1, m.digest()).toString(16) + "\"";
247 return hash + " // " + formattedOutput.substring(0, 100) + "..";
249 return formattedOutput;
253 public String getExternalURI(External ext) {
254 String name = ext.name;
255 if (name.contains(" "))
256 name = name.replace(" ", "_").replaceAll("@", "_");// name = "\"" +
258 int parentId = ext.parent;
259 // if(parentId == 0) return ext.name;
261 Identity id = query.getIdentity(parentId);
262 if (id.definition instanceof External) {
263 return getExternalURI((External) id.definition) + "/" + name;
264 } else if (id.definition instanceof Root) {
265 Root root = (Root) id.definition;
266 return "http:/" + root.name + "/" + name;
273 public String getExternalURI(int resource) {
274 Identity id = query.getIdentity(resource);
277 if (id.definition instanceof External) {
278 External ext = (External) id.definition;
279 return getExternalURI(ext);
284 String rewritePredicateURI(int predicate) {
286 String uri = getExternalURI(predicate);
288 ResourceInfo info = infos.get(predicate);
294 for (String ontology : ontologies.keySet()) {
295 if (uri.contains(ontology)) {
296 String key = ontologies.get(ontology);
297 uri = uri.replace(ontology, key);
298 referencedOntologies.add(ontology);
302 uri = uri.replace("/", ".");
308 static void indent(StringBuilder output, int indent) {
309 for (int i = 0; i < indent; i++)
313 String printBlank(String predicateURI2, ResourceInfo info, int indent) {
318 StringBuilder output = new StringBuilder();
320 String infoName = info.name;
321 if (infoName.startsWith("blank")) {
322 infoName = getBlankRewrite(infoName);
325 if (ignoreIdentifiers) {
326 if (predicateURI2.contains("L0.identifier")) {
329 indent(output, indent);
330 output.append(predicateURI2 + " " + infoName + "\n");
333 indent(output, indent);
334 output.append(predicateURI2 + " " + infoName + "\n");
337 if (info.ownedResourcesWithPredicates.isEmpty()) {
339 System.out.print("printBlank");
340 String uri = printURI(info, false, indent, false);
344 // if(info.owner < 0) {
345 // printURI(graph, info, false, indent);
347 return output.toString();
350 private String getBlankRewrite(String infoName) {
351 String rewrite = blankRewrites.get(infoName);
352 if (rewrite == null) {
353 rewrite = "rblank" + newBlankCounter++;
355 System.out.println("rewrote " + infoName + " to " + rewrite);
356 blankRewrites.put(infoName, rewrite);
362 static long longStm(int predicate, int object) {
363 return ((predicate & 0xffffffffL) << 32) | (object & 0xffffffffL);
366 private void addInlineStatement(Map<String, Set<String>> statements, String predicate,
367 ResourceInfo objectInfo, int indent) {
368 Set<String> objects = statements.get(predicate);
369 if (objects == null) {
370 objects = new TreeSet<>();
371 statements.put(predicate, objects);
373 String uri = printURI(objectInfo, false, indent + 1, true);
375 // TODO: this is not the right place to remove trailing newline
376 uri = uri.endsWith("\n") ? uri.substring(0, uri.length() - 2) : uri;
379 objectInfo.inlined = true;
382 void addStatement(Map<String, Set<String>> statements, String predicate, String object) {
384 if (predicate.endsWith("Inverse"))
386 Set<String> objects = statements.get(predicate);
387 if (objects == null) {
388 objects = new TreeSet<>();
389 statements.put(predicate, objects);
394 String printURI(ResourceInfo info, boolean requireURI, int indent, boolean inline) {
396 if (requireURI && !info.hasURI)
399 // Check if this ResourceInfo is already inlined with some other
404 Map<String, Set<String>> statements = new TreeMap<>();
405 Identity consistsOf = query.findExternalByURI("http://www.simantics.org/Layer0-1.1/ConsistsOf");
406 // Identity partOf = TransferableGraphUtils.findExternal(graph,
407 // "http://www.simantics.org/Layer0-1.1/PartOf");
408 TLongHashSet processed = new TLongHashSet();
410 System.out.println("info.owned.size " + info.owned.size() + info.owned);
411 for (int i = 0; i < info.owned.size(); i += 2) {
412 int predicate = info.owned.get(i);
413 int object = info.owned.get(i + 1);
414 long stmId = longStm(predicate, object);
417 " " + stmId + " is already processed as it is owned (" + predicate + " " + object + ")");
418 processed.add(stmId);
421 TreeMap<String, List<Integer>> predicateURIs = new TreeMap<>();
423 TIntArrayList rawStatements = query.getStatements(info.resource);
426 "rawStatements size for " + info.name + " : " + rawStatements.size() + " " + rawStatements);
427 for (int i = 0; i < rawStatements.size(); i += 2) {
428 int predicate = rawStatements.get(i);
429 int object = rawStatements.get(i + 1);
430 long stmId = longStm(predicate, object);
431 if (!processed.add(stmId)) {
433 System.out.println(" " + stmId + " is already processed (" + (predicate & 0xffffffffL) + " "
434 + (object & 0xffffffffL) + ")");
438 System.out.println(" " + stmId + " is currently being processed (" + (predicate & 0xffffffffL) + " "
439 + (object & 0xffffffffL) + ")");
440 // if (partOf.resource == rawStatements.get(i))
442 if (consistsOf.resource == predicate) {
443 // if (!info.owned.isEmpty() && !info.name.startsWith("blank"))
446 System.out.println(" is consistsof " + predicate + " (" + consistsOf.resource + ")");
449 // // this will be inlined so lets indent
453 String predicateURI = rewritePredicateURI(predicate);
454 List<Integer> objects = predicateURIs.get(predicateURI);
455 if (objects == null) {
456 objects = new ArrayList<>();
457 predicateURIs.put(predicateURI, objects);
461 for (Entry<String, List<Integer>> entry : predicateURIs.entrySet()) {
462 String predicateURI = entry.getKey();
463 List<Integer> objects = entry.getValue();
464 for (int object : objects) {
465 ResourceInfo objectInfo = infos.get(object);
466 if (objectInfo == null) {
467 String objectURI = rewritePredicateURI(object);
469 System.out.println(" adding statement " + predicateURI + " " + objectURI);
470 addStatement(statements, predicateURI, objectURI);
471 } else if (objectInfo.ownedBy.size() == 1 && objectInfo.ownedBy.contains(info)) {
472 // inline printing with _
474 System.out.println(" adding inline statement " + predicateURI + " " + objectInfo.name);
475 addInlineStatement(statements, predicateURI, objectInfo, indent);
477 String objectName = objectInfo.name;
478 if (objectName.startsWith("blank")) {
479 objectName = getBlankRewrite(objectName);
482 System.out.println(" adding statement " + predicateURI + " " + objectName);
483 addStatement(statements, predicateURI, objectName);
490 "statements size for " + info.name + " : " + statements.size() + " " + statements.keySet());
492 StringBuilder output = new StringBuilder();
494 if (indent == 0 || inline) {
495 if ("ROOT".equals(info.name)) {
496 output.append("ROOT=<http:/>");
497 } else if (info.aliasURI != null) {
498 output.append(info.name + " = <" + info.aliasURI + ">");
500 String infoName = info.name;
501 if (infoName.startsWith("blank")) {
502 infoName = getBlankRewrite(infoName);
504 output.append(inline ? "_" : infoName);
506 Set<String> instanceOfs = statements.get("L0.InstanceOf");
507 if (instanceOfs != null) {
508 for (String instanceOf : instanceOfs) {
509 output.append(" : " + instanceOf);
512 Set<String> subrelationOfs = statements.get("L0.SubrelationOf");
513 if (subrelationOfs != null) {
514 for (String subrelationOf : subrelationOfs) {
515 output.append(" <R " + subrelationOf);
518 Set<String> inherits = statements.get("L0.Inherits");
519 if (inherits != null) {
520 for (String inherit : inherits) {
521 output.append(" <T " + inherit);
527 if (info.newResource)
528 output.append(" @L0.new\n");
530 for (Map.Entry<String, Set<String>> entry : statements.entrySet()) {
531 String predicate = entry.getKey();
532 if (ignoreIdentifiers) {
533 if (predicate.equals("L0.identifier")) {
537 if ("L0.InstanceOf".equals(predicate))
539 if ("L0.SubrelationOf".equals(predicate))
541 if ("L0.Inherits".equals(predicate))
543 if ("L0.PartOf".equals(predicate))
546 // predicates can be blank
547 if (predicate.startsWith("blan")) {
548 predicate = getBlankRewrite(predicate);
551 Set<String> objects = entry.getValue();
552 indent(output, indent + 1);
553 if (objects.size() == 1) {
554 output.append(predicate + " " + objects.iterator().next() + "\n");
556 output.append(predicate + "\n");
557 for (String object : objects) {
558 indent(output, indent + 1);
559 output.append(" " + object + "\n");
564 TreeMap<String, Set<Integer>> ownedOrdered = new TreeMap<>();
566 for (int i = 0; i < info.owned.size(); i += 2) {
567 String predicateURI = rewritePredicateURI(info.owned.get(i));
568 Set<Integer> owneds = ownedOrdered.get(predicateURI);
569 if (owneds == null) {
570 owneds = new TreeSet<>();
571 ownedOrdered.put(predicateURI, owneds);
573 owneds.add(info.owned.get(i + 1));
577 System.out.println(info.name + " : " + ownedOrdered.keySet());
579 for (Entry<String, Set<Integer>> entry : ownedOrdered.entrySet()) {
580 String predicateURI = entry.getKey();
581 Set<Integer> owneds = entry.getValue();
582 for (int owned : owneds) {
583 ResourceInfo ownedInfo = infos.get(owned);
585 String blank = printBlank(predicateURI, ownedInfo, indent + 1);
587 output.append(blank);
592 return output.toString();
595 static Map<String, String> knownOntologies = new HashMap<>();
598 knownOntologies.put("http://www.simantics.org/Layer0-1.1", "L0");
599 knownOntologies.put("http://www.simantics.org/Layer0X-1.1", "L0X");
600 knownOntologies.put("http://www.simantics.org/Modeling-1.2", "MOD");
601 knownOntologies.put("http://www.simantics.org/Diagram-2.2", "DIA");
602 knownOntologies.put("http://www.simantics.org/Structural-1.2", "STR");
603 knownOntologies.put("http://www.simantics.org/Document-1.2", "DOC");
604 knownOntologies.put("http://www.simantics.org/Documentation-1.2", "DOCU");
605 knownOntologies.put("http://www.simantics.org/G2D-1.1", "G2D");
606 knownOntologies.put("http://www.simantics.org/SelectionView-1.2", "SEL");
607 knownOntologies.put("http://www.simantics.org/Viewpoint-1.2", "VP");
608 knownOntologies.put("http://www.simantics.org/Image2-1.2", "IMAGE2");
609 knownOntologies.put("http://www.simantics.org/GraphFile-0.1", "GRAPHFILE");
610 knownOntologies.put("http://www.simantics.org/Project-1.2", "PROJECT");
611 knownOntologies.put("http://www.semantum.fi/Simupedia-1.0", "SIMUPEDIA");
612 knownOntologies.put("http://www.semantum.fi/SimupediaWorkbench-1.0", "SIMUPEDIA_WORKBENCH");
615 void prettyPrint() throws Exception {
616 log("Starting prettyPrint for TransferableGraph with {} resources, {} identities, {} statements and {} values",
617 query.getGraph().resourceCount, query.getGraph().identities, query.getGraph().statements.length, query.getGraph().values.length);
619 query.forIdentities(id -> {
620 int identityResource = id.resource;
621 if (id.definition instanceof Internal) {
622 Internal internal = (Internal) id.definition;
623 Identity parent = query.getIdentity(internal.parent);
624 if (parent.definition instanceof External || parent.definition instanceof Root) {
625 log("Resolving internal identity {}", id);
626 String name = "BASE";
627 ResourceInfo info = new ResourceInfo(true, name, identityResource, -1);
628 info.aliasURI = query.getURI(identityResource);
629 info.newResource = true;
630 orderedInfos.put(name, info);
631 // infos.put(id.resource, info);
632 log(" which parent is external {} and has an aliasURI {}", parent, info.aliasURI);
633 for (Identity child : query.getChildren(id))
634 recurseURI(orderedInfos, child, name, identityResource);
635 log(" and has {} children", infos.size());
637 } else if (id.definition instanceof External) {
638 External ext = (External) id.definition;
639 // Try to detect shared libraries
640 if (ext.name.contains("@")) {
642 log("Detected an external shared library {}", ext);
644 int index = ext.name.indexOf('@');
645 String prefix = ext.name.substring(0, index);
646 int index2 = ext.name.indexOf('/', index);
647 String ontology = index2 == -1 ? ext.name : ext.name.substring(0, index2);
648 String uri = query.getURI(identityResource);
650 log(" which was resolved as URI={} and prefix={}", uri, prefix);
652 ontologies.put(uri, prefix);
654 } else if (ext.name.contains("-")) {
655 log("Resolving possible ontology {}", ext);
656 String uri = query.getURI(identityResource);
657 Matcher m = versionExtractPattern.matcher(uri);
659 if (!ontologies.containsKey(uri)) {
660 int index = ext.name.indexOf('-');
661 String prefix = ext.name.substring(0, index);
662 log(" and it was resolved as URI={} and prefix {}", uri, prefix);
663 ontologies.put(uri, prefix);
671 // Discover other resources
672 log("Discovering other resources..");
674 TIntArrayList todo = new TIntArrayList();
675 for (ResourceInfo info : orderedInfos.values()) {
676 todo.add(info.resource);
678 // put orderedInfos to infos
679 infos.put(info.resource, info);
682 while (!todo.isEmpty()) {
683 int resource = todo.removeAt(todo.size() - 1);
684 discoverBlank(resource, todo);
686 for (ResourceInfo info : infos.valueCollection())
687 discoverOwners(info);
688 // for(ResourceInfo info : infos.valueCollection())
689 // fixInstanceOf(graph, info);
691 for (ResourceInfo info : infos.valueCollection()) {
692 // Old implementation
693 // if (info.owner >= 0) {
694 // ResourceInfo ownerInfo = infos.get(info.owner);
695 // System.out.println("originalOwner : " + info.owner + "
696 // originalPredicate: " + info.ownerPredicate);
697 // ownerInfo.owned.add(info.ownerPredicate);
698 // ownerInfo.owned.add(info.resource);
701 if (!info.ownedResourcesWithPredicates.isEmpty() && info.ownedResourcesWithPredicates.size() == 1) {
702 info.ownedResourcesWithPredicates.forEachEntry(new TIntIntProcedure() {
705 public boolean execute(int owner, int predicate) {
707 ResourceInfo ownerInfo = infos.get(owner);
708 ownerInfo.owned.add(predicate);
709 ownerInfo.owned.add(info.resource);
714 System.err.println("Here we are with " + info);
718 // Resolve inverses from ownedBy list
719 for (ResourceInfo info : infos.valueCollection()) {
720 for (int i = 0; i < info.owned.size(); i += 2) {
721 int object = info.owned.get(i + 1);
722 ResourceInfo inf = infos.get(object);
724 info.ownedBy.remove(inf);
729 Identity routeGraphConn = query.findExternalByURI("http://www.simantics.org/Diagram-2.2/RouteGraphConnection");
730 Identity instanceOf = query.findExternalByURI("http://www.simantics.org/Layer0-1.1/InstanceOf");
731 Identity diagramConnetionToConnection = query.findExternalByURI("http://www.simantics.org/Modeling-1.2/DiagramConnectionToConnection");
733 Identity elemTo = query.findExternalByURI("http://www.simantics.org/Modeling-1.2/ElementToComponent");
734 for (ResourceInfo infoo : infos.valueCollection()) {
735 if (elemTo != null) {
736 int elemToComponent = query.getPossibleObject(infoo.resource, elemTo);
737 if (elemToComponent != TransferableGraphUtils.NOT_FOUND) {
739 Identity component = query.getIdentity(elemToComponent);
740 Identity internal = query.getIdentity(infoo.resource);
741 if (internal.definition instanceof Internal && component.definition instanceof Internal) {
742 Internal iComponent = (Internal) component.definition;
743 infoo.name = infoo.name.substring(0, infoo.name.lastIndexOf(".") + 1) + iComponent.name;
748 if (instanceOf != null) {
749 int instOf = query.getPossibleObject( infoo.resource, instanceOf);
750 if (instOf != TransferableGraphUtils.NOT_FOUND && routeGraphConn != null) {
751 if (instOf == routeGraphConn.resource) {
752 // Found routegraphconnection, change name
753 // Lets go to configuration
755 int connection = query.getPossibleObject( infoo.resource,
756 diagramConnetionToConnection);
757 if (connection != TransferableGraphUtils.NOT_FOUND) {
758 // Gather all inverse statements to construct unique
760 List<String> nameParts = new ArrayList<>();
761 TIntArrayList statements = query.getStatements(connection);
762 for (int i = 0; i < statements.size(); i += 2) {
763 int predicate = statements.get(i);
764 Identity possibleInverse = query.getIdentity(predicate);
765 if (possibleInverse != null) {
766 int inverseRelation = TransferableGraphUtils.NOT_FOUND;
767 int parentId = TransferableGraphUtils.NOT_FOUND;
768 if (possibleInverse.definition instanceof Internal) {
769 Internal iPossibleInverse = (Internal) possibleInverse.definition;
770 if (iPossibleInverse.name.equals("Inverse")) {
771 inverseRelation = query.getPossibleObject(
772 connection, possibleInverse);
773 parentId = iPossibleInverse.parent;
775 log("Unsupported inverse relation found for {} {}", infoo, iPossibleInverse);
777 } else if (possibleInverse.definition instanceof External) {
778 External ePossibleInverse = (External) possibleInverse.definition;
779 if (ePossibleInverse.name.equals("Inverse")) {
780 inverseRelation = query.getPossibleObject(
781 connection, possibleInverse);
782 parentId = ePossibleInverse.parent;
784 log("This external inverse is unsupported for {} {}", infoo, ePossibleInverse);
787 log("This type of definition is not supported {}", infoo);
789 if (inverseRelation != TransferableGraphUtils.NOT_FOUND) {
790 // Ok found something
791 Identity object = query.getIdentity(inverseRelation);
792 Identity parent = query.getIdentity(parentId);
793 String objectName, parentName;
794 if (object.definition instanceof Internal) {
795 objectName = ((Internal) object.definition).name;
796 } else if (object.definition instanceof External) {
797 objectName = ((External) object.definition).name;
799 log("This type of definition is not supported {}", infoo);
800 throw new Error("UNSUPPORTED " + infoo);
802 if (parent.definition instanceof Internal) {
803 parentName = ((Internal) parent.definition).name;
804 } else if (parent.definition instanceof External) {
805 parentName = ((External) parent.definition).name;
807 log("This type of definition is not supported {}", infoo);
808 throw new Error("UNSUPPORTED " + infoo);
810 String fullName = parentName + "_" + objectName;
811 nameParts.add(fullName);
813 log("No inverse relation found for {}", infoo);
816 log("Did not find possible inverse relation for {}", infoo);
819 nameParts.sort((o1, o2) -> o1.compareTo(o2));
821 for (String namep : nameParts) {
824 infoo.name = infoo.name.substring(0, infoo.name.lastIndexOf(".") + 1) + name;
826 LOGGER.error("Could not find connection for " + infoo + ". Statements of graph below");
827 LOGGER.error("Subject -> Predicate : " + infoo.resource + " -> "
828 + diagramConnetionToConnection.resource);
834 for (ResourceInfo info : infos.valueCollection()) {
835 if (info.name.startsWith("blank")) {
836 info.name = "blank" + findHash(info);
840 TreeMap<String, ResourceInfo> order = new TreeMap<>();
841 for (ResourceInfo info : infos.valueCollection())
842 order.put(info.name, info);
844 for (ResourceInfo info : order.values()) {
846 System.out.print("info ");
847 String uri = printURI(info, true, 0, false);
852 TreeMap<String, ResourceInfo> rblanks = new TreeMap<>();
854 for (ResourceInfo info : order.values()) {
855 if (!info.hasURI && info.ownedResourcesWithPredicates.size() != 1) {
857 System.out.print("ownedResources ");
858 if (info.name.startsWith("blank")) {
859 // These will be printed later
860 rblanks.put(getBlankRewrite(info.name), info);
862 String uri = printURI(info, false, 0, false);
868 // Now print blanks in order
869 for (ResourceInfo info : rblanks.values()) {
870 if (!info.hasURI && info.ownedResourcesWithPredicates.size() != 1) {
872 System.out.print("ownedResources ");
873 String uri = printURI(info, false, 0, false);
879 // for(ResourceInfo info : order.values())
880 // if(!info.hasURI && info.owner < 0)
881 // printURI(graph, info, false, 0);
883 StringBuilder refs = new StringBuilder();
884 for (String ontology : referencedOntologies) {
885 String key = ontologies.get(ontology);
886 refs.append(key + " = <" + ontology + ">\n");
888 if (!referencedOntologies.isEmpty())
890 output.insert(0, refs.toString());
894 private String calculateHash(ResourceInfo info) {
895 StringBuilder statementHash = new StringBuilder();
896 TreeSet<String> parts = new TreeSet<>();
897 for (int i = 0; i < info.owned.size(); i += 2) {
898 int predicate = info.owned.get(i);
899 int object = info.owned.get(i + 1);
900 // Lets resolve a unique name for this based on the statements this
903 String predicatee = rewritePredicateURI(predicate);
904 ResourceInfo objInfo = infos.get(object);
905 parts.add(predicatee + "->" + objInfo.name + ";;;");
907 // Remove this from the list
908 List<ResourceInfo> filtered = info.ownedBy.stream().filter(ri -> !ri.name.startsWith("blank"))
909 .collect(Collectors.toList());
910 for (ResourceInfo ownedBy : filtered) {
911 parts.add(ownedBy.name);
914 ResourceInfo parentInfo = infos.get(info.parent);
915 if (parentInfo != null && !parentInfo.name.startsWith("blank")) {
916 parts.add("parent" + parentInfo.name);
918 // LOGGER.error("This should not happen");
920 for (String s : parts) {
921 statementHash.append(s);
923 String hash = makeHash(statementHash.toString().getBytes());
925 System.out.println(statementHash + " -> " + hash);
929 private String findHash(ResourceInfo info) {
930 if (info.name.startsWith("blank")) {
931 String hash = hashes.get(info.name);
933 String oldName = info.name;
935 System.out.print("calculating hash for " + oldName + " ");
936 hash = calculateHash(info);
937 if (hashes.put(oldName, hash) != null) {
938 System.err.println("!!!!A clash occured for " + info + " with hash " + hash);
947 private THashMap<String, String> hashes = new THashMap<>();
949 public static String print(TransferableGraph1 tg, boolean ignoreIdentifiers) throws Exception {
950 StringBuilder b = new StringBuilder();
951 new PrettyPrintTG(tg, b, ignoreIdentifiers).prettyPrint();
955 public static void main(String[] args) throws Exception {
956 if (args.length < 1) {
957 System.out.println("Required arguments: <input .sharedOntology file> [<output .tg file>]");
961 if (args.length < 2) {
962 input = Paths.get(args[0]);
963 output = input.getParent().resolve(input.getName(input.getNameCount() - 1) + ".fixed");
965 input = Paths.get(args[0]);
966 output = Paths.get(args[1]);
968 System.out.format("Converting exported shared ontology%n\t" + input.toString()
969 + "%nto bundle-compatible ontology%n\t" + output.toString());
970 try (InputStream is = new BufferedInputStream(Files.newInputStream(input), 128 * 1024)) {
971 DataInput dis = new DataInputStream(is);
972 org.simantics.databoard.container.DataContainer container = DataContainers.readFile(dis);
973 Binding binding = TransferableGraph1.BINDING;
974 TransferableGraph1 graph = (TransferableGraph1) container.content.getValue(binding);
975 new PrettyPrintTG(graph).prettyPrint();
979 private static void log(String string, Object... args) {
980 if (LOGGER.isDebugEnabled() && DEBUG)
981 LOGGER.debug(string, args);