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.Arrays;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.List;
19 import java.util.Map.Entry;
21 import java.util.TreeMap;
22 import java.util.TreeSet;
23 import java.util.regex.Matcher;
24 import java.util.regex.Pattern;
25 import java.util.stream.Collectors;
27 import org.simantics.databoard.Bindings;
28 import org.simantics.databoard.binding.Binding;
29 import org.simantics.databoard.binding.mutable.Variant;
30 import org.simantics.databoard.container.DataContainers;
31 import org.simantics.databoard.parser.DataValuePrinter;
32 import org.simantics.databoard.parser.PrintFormat;
33 import org.simantics.databoard.parser.repository.DataValueRepository;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 import gnu.trove.list.array.TIntArrayList;
38 import gnu.trove.map.hash.THashMap;
39 import gnu.trove.map.hash.TIntIntHashMap;
40 import gnu.trove.map.hash.TIntObjectHashMap;
41 import gnu.trove.procedure.TIntIntProcedure;
42 import gnu.trove.set.hash.TLongHashSet;
45 * @author Antti Villberg
48 public class PrettyPrintTG {
50 private static final Logger LOGGER = LoggerFactory.getLogger(PrettyPrintTG.class);
52 private static final boolean DEBUG = false;
55 int newBlankCounter = 0;
56 Map<String, String> blankRewrites = new HashMap<>();
59 private final Pattern versionExtractPattern = Pattern.compile("^.*-(\\d+\\.\\d+)");
61 final StringBuilder output;
62 final Map<String, String> ontologies = new HashMap<>(knownOntologies);
63 final Set<String> referencedOntologies = new TreeSet<>();
65 private boolean ignoreIdentifiers;
67 static class ResourceInfo {
71 boolean newResource = false;
75 boolean inlined = false;
77 // -1 = no owner, -2 = multiple owners
79 // Set<ResourceInfo> ownedBy
80 Set<ResourceInfo> ownedBy = new HashSet<>();
82 // A Map<Integer, Integer> containing information about resource that
83 // this resource owns and what are the predicates for forming this
85 TIntIntHashMap ownedResourcesWithPredicates = new TIntIntHashMap();
88 // int ownerPredicate = 0;
89 String aliasURI = null;
90 TIntArrayList owned = new TIntArrayList();
92 // TIntObjectHashMap<TIntHashSet> statements = new
93 // TIntObjectHashMap<TIntHashSet>();
94 public ResourceInfo(boolean hasURI, String name, int resource, int parent) {
97 this.resource = resource;
102 public String toString() {
103 return name + (aliasURI != null ? " = <" + aliasURI + ">" : "");
107 public PrettyPrintTG(StringBuilder b, boolean ignoreIdentifiers) throws NoSuchAlgorithmException {
109 m = MessageDigest.getInstance("SHA-256");
110 this.ignoreIdentifiers = ignoreIdentifiers;
113 public PrettyPrintTG() throws NoSuchAlgorithmException {
114 this(new StringBuilder(), false);
117 TreeMap<String, ResourceInfo> orderedInfos = new TreeMap<>();
118 TIntObjectHashMap<ResourceInfo> infos = new TIntObjectHashMap<>();
120 String tgNodeName(String name) {
121 if (name.contains(" "))
122 return "\"" + name + "\"";
127 ResourceInfo recurseURI(TransferableGraph1 graph, Identity parent, String parentName, int parentId) {
128 String name = parentName + "." + tgNodeName(TransferableGraphUtils.getName(parent));
129 ResourceInfo info = new ResourceInfo(true, name, parent.resource, parentId);
130 orderedInfos.put(name, info);
131 // infos.put(parent.resource, info);
132 for (Identity child : TransferableGraphUtils.getChildren(graph, parent)) {
133 recurseURI(graph, child, name, info.resource);
138 private TreeMap<String, TreeSet<Integer>> sortByPredicateUniqueStatements(TransferableGraph1 graph, int resource) {
139 TreeMap<String, TreeSet<Integer>> results = new TreeMap<>();
140 TIntArrayList statements = TransferableGraphUtils.getStatements(graph, resource);
141 for (int i = 0; i < statements.size(); i += 2) {
142 int predicate = statements.get(i);
143 String predicateURI = TransferableGraphUtils.getURI(graph, predicate);
144 TreeSet<Integer> objects = results.get(predicateURI);
145 if (objects == null) {
146 objects = new TreeSet<>();
148 objects.add(statements.get(i + 1));
149 results.put(predicateURI, objects);
154 void discoverBlank(TransferableGraph1 graph, int resource, TIntArrayList todo) throws Exception {
155 // TIntArrayList statements =
156 // TransferableGraphUtils.getStatements(graph, resource);
157 // for(int i=0;i<statements.size();i+=2) {
158 for (TreeSet<Integer> objects : sortByPredicateUniqueStatements(graph, resource).values()) {
159 for (int object : objects) {
160 // int object = statements.get(i+1);
161 Identity objectId = TransferableGraphUtils.getIdentity(graph, object);
162 if (objectId != null) {
163 if (objectId.definition instanceof External)
166 Value value = TransferableGraphUtils.findValue(graph, object);
168 infos.put(object, new ResourceInfo(false, printValue(value), object, resource));
171 ResourceInfo existing = infos.get(object);
172 if (existing == null) {
174 existing = new ResourceInfo(false, "blank" + blankCounter++, object, resource);
176 // System.out.println("created blank" + blankCounter + "
177 // with object " + object + " resource " + resource);
178 infos.put(object, existing);
185 private String makeHash(byte[] data) {
187 m.update(data, 0, data.length);
188 return new BigInteger(1, m.digest()).toString(16);
191 void discoverOwners(TransferableGraph1 graph, ResourceInfo info) {
192 log("Discovering owners for {}", info);
193 int resource = info.resource;
194 TIntArrayList statements = TransferableGraphUtils.getStatements(graph, resource);
195 for (int i = 0; i < statements.size(); i += 2) {
196 int predicate = statements.get(i);
197 int object = statements.get(i + 1);
198 ResourceInfo existing = infos.get(object);
199 if (existing != null) {
200 // Add all owners here for now and resolve the best owner later
202 // Check if predicate is inverse, this just resolves all
203 // predicates to be inverse with ending "Inverse"..
204 String predicateUri = rewritePredicateURI(graph, predicate);
205 if (!predicateUri.endsWith("Inverse") && !predicateUri.endsWith("Of")) {
206 existing.ownedResourcesWithPredicates.put(resource, predicate);
207 // if (predicateUri.endsWith("Of")) {
208 // System.out.println("asd");
210 existing.ownedBy.add(info);
211 log(" {} owns {} with {}", existing, info, predicateUri);
214 // System.out.println("asd");
220 DataValueRepository repo = new DataValueRepository();
221 DataValuePrinter printer = new DataValuePrinter(null, repo);
223 String printValue(Value value) throws Exception {
224 StringBuilder sb = new StringBuilder();
225 printer.setFormat(PrintFormat.SINGLE_LINE);
226 printer.setOutput(sb);
228 Variant variant = value.value;
229 printer.print(variant.getBinding(), variant.getValue());
230 String formattedOutput = sb.toString();
231 if (formattedOutput.length() > 100) {
232 // Ok, value too long, lets calculate a hash for it and store first
233 // 100 chars as comment
234 byte[] data = Bindings.getSerializerUnchecked(variant.getBinding()).serialize(variant.getValue());
236 m.update(data, 0, data.length);
237 String hash = "\"" + new BigInteger(1, m.digest()).toString(16) + "\"";
238 return hash + " // " + formattedOutput.substring(0, 100) + "..";
240 return formattedOutput;
243 // Variant variant = value.value;
244 // Datatype dt = variant.getBinding().type();
245 // if (Datatypes.STRING.equals(dt)) {
246 // String s = (String) variant.getValue(Bindings.STRING);
247 // if (s.contains("\n")) {
248 // return "\"\"\"" + s + "\"\"\"";
250 // return "\"" + s + "\"";
252 // } else if (Datatypes.BOOLEAN.equals(dt)) {
253 // Boolean i = (Boolean) variant.getValue(Bindings.BOOLEAN);
254 // return i ? "true" : "false";
255 // } else if (Datatypes.INTEGER.equals(dt)) {
256 // Integer i = (Integer) variant.getValue(Bindings.INTEGER);
257 // return i.toString();
258 // } else if (Datatypes.LONG.equals(dt)) {
259 // Long i = (Long) variant.getValue(Bindings.LONG);
260 // return i.toString();
261 // } else if (Datatypes.DOUBLE.equals(dt)) {
262 // Double d = (Double) variant.getValue();
263 // return d.toString();
264 // } else if (Datatypes.FLOAT.equals(dt)) {
265 // Float f = (Float) variant.getValue();
266 // return f.toString();
267 // } else if (Datatypes.STRING_ARRAY.equals(dt)) {
268 // return Arrays.toString((String []) variant.getValue());
269 // } else if (Datatypes.BOOLEAN_ARRAY.equals(dt)) {
270 // return Arrays.toString((boolean []) variant.getValue());
271 // } else if (Datatypes.INTEGER_ARRAY.equals(dt)) {
272 // return Arrays.toString((int []) variant.getValue());
273 // } else if (Datatypes.LONG_ARRAY.equals(dt)) {
274 // return Arrays.toString((long []) variant.getValue());
275 // } else if (Datatypes.DOUBLE_ARRAY.equals(dt)) {
276 // return Arrays.toString((double []) variant.getValue());
277 // } else if (Datatypes.FLOAT_ARRAY.equals(dt)) {
278 // return Arrays.toString((float []) variant.getValue());
279 // } else if (Datatypes.BYTE_ARRAY.equals(dt)) {
280 // return Arrays.toString((byte []) variant.getValue());
281 //// } else if (dt instanceof ArrayType) {
282 //// return Arrays.toString((Object []) variant.getValue());
285 // Bindings.getSerializerUnchecked(variant.getBinding()).serialize(variant.getValue());
287 // m.update(data, 0, data.length);
288 // return "\"" + new BigInteger(1, m.digest()).toString(16) + "\"";
293 // void fixInstanceOf(TransferableGraph1 graph, ResourceInfo info) {
294 // Identity id = getIdentity(graph, info.resource);
295 // if(id == null) return;
296 // if(id.definition instanceof Internal) {
297 // Identity instanceOf = findExternal(graph,
298 // "http://www.simantics.org/Layer0-1.1/InstanceOf");
299 // Identity library = findExternal(graph,
300 // "http://www.simantics.org/Layer0-1.1/Library");
301 // info.statements.add(instanceOf.resource);
302 // info.statements.add(library.resource);
306 public static String getExternalURI(TransferableGraph1 tg, External ext) {
307 String name = ext.name;
308 if (name.contains(" "))
309 name = name.replace(" ", "_").replaceAll("@", "_");// name = "\"" +
311 int parentId = ext.parent;
312 // if(parentId == 0) return ext.name;
314 Identity id = TransferableGraphUtils.getIdentity(tg, parentId);
315 if (id.definition instanceof External) {
316 return getExternalURI(tg, (External) id.definition) + "/" + name;
317 } else if (id.definition instanceof Root) {
318 Root root = (Root) id.definition;
319 return "http:/" + root.name + "/" + name;
326 public static String getExternalURI(TransferableGraph1 tg, int resource) {
327 Identity id = TransferableGraphUtils.getIdentity(tg, resource);
330 if (id.definition instanceof External) {
331 External ext = (External) id.definition;
332 return getExternalURI(tg, ext);
337 String rewritePredicateURI(TransferableGraph1 graph, int predicate) {
339 String uri = getExternalURI(graph, predicate);
341 ResourceInfo info = infos.get(predicate);
347 for (String ontology : ontologies.keySet()) {
348 if (uri.contains(ontology)) {
349 String key = ontologies.get(ontology);
350 uri = uri.replace(ontology, key);
351 referencedOntologies.add(ontology);
355 uri = uri.replace("/", ".");
361 static void indent(StringBuilder output, int indent) {
362 for (int i = 0; i < indent; i++)
366 String printBlank(TransferableGraph1 graph, String predicateURI2, ResourceInfo info, int indent) {
371 StringBuilder output = new StringBuilder();
373 String infoName = info.name;
374 if (infoName.startsWith("blank")) {
375 infoName = getBlankRewrite(infoName);
378 if (ignoreIdentifiers) {
379 if (predicateURI2.contains("L0.identifier")) {
382 indent(output, indent);
383 output.append(predicateURI2 + " " + infoName + "\n");
386 indent(output, indent);
387 output.append(predicateURI2 + " " + infoName + "\n");
390 if (info.ownedResourcesWithPredicates.isEmpty()) {
392 System.out.print("printBlank");
393 String uri = printURI(graph, info, false, indent, false);
397 // if(info.owner < 0) {
398 // printURI(graph, info, false, indent);
400 return output.toString();
403 private String getBlankRewrite(String infoName) {
404 String rewrite = blankRewrites.get(infoName);
405 if (rewrite == null) {
406 rewrite = "rblank" + newBlankCounter++;
408 System.out.println("rewrote " + infoName + " to " + rewrite);
409 blankRewrites.put(infoName, rewrite);
415 static long longStm(int predicate, int object) {
416 return ((predicate & 0xffffffffL) << 32) | (object & 0xffffffffL);
419 private void addInlineStatement(TransferableGraph1 graph, Map<String, Set<String>> statements, String predicate,
420 ResourceInfo objectInfo, int indent) {
421 Set<String> objects = statements.get(predicate);
422 if (objects == null) {
423 objects = new TreeSet<>();
424 statements.put(predicate, objects);
426 String uri = printURI(graph, objectInfo, false, indent + 1, true);
428 // TODO: this is not the right place to remove trailing newline
429 uri = uri.endsWith("\n") ? uri.substring(0, uri.length() - 2) : uri;
432 objectInfo.inlined = true;
435 void addStatement(Map<String, Set<String>> statements, String predicate, String object) {
437 if (predicate.endsWith("Inverse"))
439 Set<String> objects = statements.get(predicate);
440 if (objects == null) {
441 objects = new TreeSet<>();
442 statements.put(predicate, objects);
447 String printURI(TransferableGraph1 graph, ResourceInfo info, boolean requireURI, int indent, boolean inline) {
449 if (requireURI && !info.hasURI)
452 // Check if this ResourceInfo is already inlined with some other
457 Map<String, Set<String>> statements = new TreeMap<>();
458 Identity consistsOf = TransferableGraphUtils.findExternal(graph,
459 "http://www.simantics.org/Layer0-1.1/ConsistsOf");
460 // Identity partOf = TransferableGraphUtils.findExternal(graph,
461 // "http://www.simantics.org/Layer0-1.1/PartOf");
462 TLongHashSet processed = new TLongHashSet();
464 System.out.println("info.owned.size " + info.owned.size() + info.owned);
465 for (int i = 0; i < info.owned.size(); i += 2) {
466 int predicate = info.owned.get(i);
467 int object = info.owned.get(i + 1);
468 long stmId = longStm(predicate, object);
471 " " + stmId + " is already processed as it is owned (" + predicate + " " + object + ")");
472 processed.add(stmId);
475 TreeMap<String, Integer> predicateURIs = new TreeMap<>();
477 TIntArrayList rawStatements = TransferableGraphUtils.getStatements(graph, info.resource);
480 "rawStatements size for " + info.name + " : " + rawStatements.size() + " " + rawStatements);
481 for (int i = 0; i < rawStatements.size(); i += 2) {
482 int predicate = rawStatements.get(i);
483 int object = rawStatements.get(i + 1);
484 long stmId = longStm(predicate, object);
485 if (!processed.add(stmId)) {
487 System.out.println(" " + stmId + " is already processed (" + (predicate & 0xffffffffL) + " "
488 + (object & 0xffffffffL) + ")");
492 System.out.println(" " + stmId + " is currently being processed (" + (predicate & 0xffffffffL) + " "
493 + (object & 0xffffffffL) + ")");
494 // if (partOf.resource == rawStatements.get(i))
496 if (consistsOf.resource == predicate) {
497 // if (!info.owned.isEmpty() && !info.name.startsWith("blank"))
500 System.out.println(" is consistsof " + predicate + " (" + consistsOf.resource + ")");
503 // // this will be inlined so lets indent
507 String predicateURI = rewritePredicateURI(graph, predicate);
508 predicateURIs.put(predicateURI, object);
510 for (Entry<String, Integer> entry : predicateURIs.entrySet()) {
511 String predicateURI = entry.getKey();
512 int object = entry.getValue();
514 ResourceInfo objectInfo = infos.get(object);
515 if (objectInfo == null) {
516 String objectURI = rewritePredicateURI(graph, object);
518 System.out.println(" adding statement " + predicateURI + " " + objectURI);
519 addStatement(statements, predicateURI, objectURI);
520 } else if (objectInfo.ownedBy.size() == 1 && objectInfo.ownedBy.contains(info)) {
521 // inline printing with _
523 System.out.println(" adding inline statement " + predicateURI + " " + objectInfo.name);
524 addInlineStatement(graph, statements, predicateURI, objectInfo, indent);
526 String objectName = objectInfo.name;
527 if (objectName.startsWith("blank")) {
528 objectName = getBlankRewrite(objectName);
531 System.out.println(" adding statement " + predicateURI + " " + objectName);
532 addStatement(statements, predicateURI, objectName);
538 "statements size for " + info.name + " : " + statements.size() + " " + statements.keySet());
540 StringBuilder output = new StringBuilder();
542 if (indent == 0 || inline) {
543 if ("ROOT".equals(info.name)) {
544 output.append("ROOT=<http:/>");
545 } else if (info.aliasURI != null) {
546 output.append(info.name + " = <" + info.aliasURI + ">");
548 String infoName = info.name;
549 if (infoName.startsWith("blank")) {
550 infoName = getBlankRewrite(infoName);
552 output.append(inline ? "_" : infoName);
554 Set<String> instanceOfs = statements.get("L0.InstanceOf");
555 if (instanceOfs != null) {
556 for (String instanceOf : instanceOfs) {
557 output.append(" : " + instanceOf);
560 Set<String> subrelationOfs = statements.get("L0.SubrelationOf");
561 if (subrelationOfs != null) {
562 for (String subrelationOf : subrelationOfs) {
563 output.append(" <R " + subrelationOf);
566 Set<String> inherits = statements.get("L0.Inherits");
567 if (inherits != null) {
568 for (String inherit : inherits) {
569 output.append(" <T " + inherit);
575 if (info.newResource)
576 output.append(" @L0.new\n");
578 for (Map.Entry<String, Set<String>> entry : statements.entrySet()) {
579 String predicate = entry.getKey();
580 if (ignoreIdentifiers) {
581 if (predicate.equals("L0.identifier")) {
585 if ("L0.InstanceOf".equals(predicate))
587 if ("L0.SubrelationOf".equals(predicate))
589 if ("L0.Inherits".equals(predicate))
591 if ("L0.PartOf".equals(predicate))
594 // predicates can be blank
595 if (predicate.startsWith("blan")) {
596 predicate = getBlankRewrite(predicate);
599 Set<String> objects = entry.getValue();
600 indent(output, indent + 1);
601 if (objects.size() == 1) {
602 output.append(predicate + " " + objects.iterator().next() + "\n");
604 output.append(predicate + "\n");
605 for (String object : objects) {
606 indent(output, indent + 1);
607 output.append(" " + object + "\n");
612 TreeMap<String, Integer> ownedOrdered = new TreeMap<>();
614 for (int i = 0; i < info.owned.size(); i += 2) {
615 String predicateURI = rewritePredicateURI(graph, info.owned.get(i));
616 ownedOrdered.put(predicateURI, info.owned.get(i + 1));
620 System.out.println(info.name + " : " + ownedOrdered.keySet());
622 for (Entry<String, Integer> entry : ownedOrdered.entrySet()) {
623 String predicateURI = entry.getKey();
624 int owned = entry.getValue();
625 ResourceInfo ownedInfo = infos.get(owned);
627 String blank = printBlank(graph, predicateURI, ownedInfo, indent + 1);
629 output.append(blank);
633 return output.toString();
636 void prettyPrint(Path input, Path output) throws Exception {
638 System.out.format("Converting exported shared ontology%n\t" + input.toString()
639 + "%nto bundle-compatible ontology%n\t" + output.toString());
640 try (InputStream is = new BufferedInputStream(Files.newInputStream(input), 128 * 1024)) {
641 DataInput dis = new DataInputStream(is);
642 org.simantics.databoard.container.DataContainer container = DataContainers.readFile(dis);
643 Binding binding = TransferableGraph1.BINDING;
644 TransferableGraph1 graph = (TransferableGraph1) container.content.getValue(binding);
646 Files.write(output, this.output.toString().getBytes());
652 static Map<String, String> knownOntologies = new HashMap<>();
655 knownOntologies.put("http://www.simantics.org/Layer0-1.1", "L0");
656 knownOntologies.put("http://www.simantics.org/Layer0X-1.1", "L0X");
657 knownOntologies.put("http://www.simantics.org/Modeling-1.2", "MOD");
658 knownOntologies.put("http://www.simantics.org/Diagram-2.2", "DIA");
659 knownOntologies.put("http://www.simantics.org/Structural-1.2", "STR");
660 knownOntologies.put("http://www.simantics.org/Document-1.2", "DOC");
661 knownOntologies.put("http://www.simantics.org/Documentation-1.2", "DOCU");
662 knownOntologies.put("http://www.simantics.org/G2D-1.1", "G2D");
663 knownOntologies.put("http://www.simantics.org/SelectionView-1.2", "SEL");
664 knownOntologies.put("http://www.simantics.org/Viewpoint-1.2", "VP");
665 knownOntologies.put("http://www.simantics.org/Image2-1.2", "IMAGE2");
666 knownOntologies.put("http://www.simantics.org/GraphFile-0.1", "GRAPHFILE");
667 knownOntologies.put("http://www.simantics.org/Project-1.2", "PROJECT");
668 knownOntologies.put("http://www.semantum.fi/Simupedia-1.0", "SIMUPEDIA");
669 knownOntologies.put("http://www.semantum.fi/SimupediaWorkbench-1.0", "SIMUPEDIA_WORKBENCH");
672 void prettyPrint(TransferableGraph1 graph) throws Exception {
673 log("Starting prettyPrint for TransferableGraph with {} resources, {} identities, {} statements and {} values",
674 graph.resourceCount, graph.identities, graph.statements.length, graph.values.length);
676 for (Identity id : graph.identities) {
677 if (id.definition instanceof Internal) {
678 Internal internal = (Internal) id.definition;
679 Identity parent = TransferableGraphUtils.getIdentity(graph, internal.parent);
680 if (parent.definition instanceof External) {
681 log("Resolving internal identity {}", id);
682 String name = "BASE";
683 ResourceInfo info = new ResourceInfo(true, name, id.resource, -1);
684 info.aliasURI = TransferableGraphUtils.getURI(graph, id.resource);
685 info.newResource = true;
686 orderedInfos.put(name, info);
687 // infos.put(id.resource, info);
688 log(" which parent is external {} and has an aliasURI {}", parent, info.aliasURI);
689 for (Identity child : TransferableGraphUtils.getChildren(graph, id)) {
690 recurseURI(graph, child, name, info.resource);
692 log(" and has {} children", infos.size());
694 } else if (id.definition instanceof External) {
695 External ext = (External) id.definition;
696 // Try to detect shared libraries
697 if (ext.name.contains("@")) {
699 log("Detected an external shared library {}", ext);
701 int index = ext.name.indexOf('@');
702 String prefix = ext.name.substring(0, index);
703 int index2 = ext.name.indexOf('/', index);
704 String ontology = index2 == -1 ? ext.name : ext.name.substring(0, index2);
705 String uri = TransferableGraphUtils.getURI(graph, id.resource);
707 log(" which was resolved as URI={} and prefix={}", uri, prefix);
709 ontologies.put(uri, prefix);
711 } else if (ext.name.contains("-")) {
712 log("Resolving possible ontology {}", ext);
713 String uri = TransferableGraphUtils.getURI(graph, id.resource);
714 Matcher m = versionExtractPattern.matcher(uri);
716 if (!ontologies.containsKey(uri)) {
717 int index = ext.name.indexOf('-');
718 String prefix = ext.name.substring(0, index);
719 log(" and it was resolved as URI={} and prefix {}", uri, prefix);
720 ontologies.put(uri, prefix);
727 // Discover other resources
728 log("Discovering other resources..");
730 TIntArrayList todo = new TIntArrayList();
731 for (ResourceInfo info : orderedInfos.values()) {
732 todo.add(info.resource);
734 // put orderedInfos to infos
735 infos.put(info.resource, info);
738 while (!todo.isEmpty()) {
739 int resource = todo.removeAt(todo.size() - 1);
740 discoverBlank(graph, resource, todo);
742 for (ResourceInfo info : infos.valueCollection())
743 discoverOwners(graph, info);
744 // for(ResourceInfo info : infos.valueCollection())
745 // fixInstanceOf(graph, info);
747 for (ResourceInfo info : infos.valueCollection()) {
748 // Old implementation
749 // if (info.owner >= 0) {
750 // ResourceInfo ownerInfo = infos.get(info.owner);
751 // System.out.println("originalOwner : " + info.owner + "
752 // originalPredicate: " + info.ownerPredicate);
753 // ownerInfo.owned.add(info.ownerPredicate);
754 // ownerInfo.owned.add(info.resource);
757 if (!info.ownedResourcesWithPredicates.isEmpty() && info.ownedResourcesWithPredicates.size() == 1) {
758 info.ownedResourcesWithPredicates.forEachEntry(new TIntIntProcedure() {
761 public boolean execute(int owner, int predicate) {
762 ResourceInfo ownerInfo = infos.get(owner);
763 ownerInfo.owned.add(predicate);
764 ownerInfo.owned.add(info.resource);
771 // Resolve inverses from ownedBy list
772 for (ResourceInfo info : infos.valueCollection()) {
773 for (int i = 0; i < info.owned.size(); i += 2) {
774 int object = info.owned.get(i + 1);
775 ResourceInfo inf = infos.get(object);
777 info.ownedBy.remove(inf);
782 Identity routeGraphConn = TransferableGraphUtils.findExternal(graph,
783 "http://www.simantics.org/Diagram-2.2/RouteGraphConnection");
784 Identity instanceOf = TransferableGraphUtils.findExternal(graph,
785 "http://www.simantics.org/Layer0-1.1/InstanceOf");
786 Identity diagramConnetionToConnection = TransferableGraphUtils.findExternal(graph,
787 "http://www.simantics.org/Modeling-1.2/DiagramConnectionToConnection");
789 for (ResourceInfo infoo : infos.valueCollection()) {
790 Identity elemTo = TransferableGraphUtils.findExternal(graph,
791 "http://www.simantics.org/Modeling-1.2/ElementToComponent");
792 if (elemTo != null) {
793 int elemToComponent = TransferableGraphUtils.getPossibleObject2(graph, infoo.resource, elemTo);
794 if (elemToComponent != TransferableGraphUtils.NOT_FOUND) {
796 Identity component = TransferableGraphUtils.getIdentity(graph, elemToComponent);
797 Identity internal = TransferableGraphUtils.getIdentity(graph, infoo.resource);
798 if (internal.definition instanceof Internal && component.definition instanceof Internal) {
799 Internal iCOmponent = (Internal) component.definition;
800 infoo.name = infoo.name.substring(0, infoo.name.lastIndexOf(".") + 1) + iCOmponent.name;
805 if (instanceOf != null) {
806 int instOf = TransferableGraphUtils.getPossibleObject2(graph, infoo.resource, instanceOf);
807 if (instOf != TransferableGraphUtils.NOT_FOUND && routeGraphConn != null) {
808 if (instOf == routeGraphConn.resource) {
809 // Found routegraphconnection, change name
810 // Lets go to configuration
812 int connection = TransferableGraphUtils.getPossibleObject2(graph, infoo.resource,
813 diagramConnetionToConnection);
814 if (connection != TransferableGraphUtils.NOT_FOUND) {
815 // Gather all inverse statements to construct unique
817 List<String> nameParts = new ArrayList<>();
818 TIntArrayList statements = TransferableGraphUtils.getStatements(graph, connection);
819 for (int i = 0; i < statements.size(); i += 2) {
820 int predicate = statements.get(i);
821 Identity possibleInverse = TransferableGraphUtils.getIdentity(graph, predicate);
822 if (possibleInverse != null) {
823 int inverseRelation = TransferableGraphUtils.NOT_FOUND;
824 int parentId = TransferableGraphUtils.NOT_FOUND;
825 if (possibleInverse.definition instanceof Internal) {
826 Internal iPossibleInverse = (Internal) possibleInverse.definition;
827 if (iPossibleInverse.name.equals("Inverse")) {
828 inverseRelation = TransferableGraphUtils.getPossibleObject2(graph,
829 connection, possibleInverse);
830 parentId = iPossibleInverse.parent;
832 LOGGER.error("THIS UNSUPPORTED for " + infoo + " " + iPossibleInverse);
834 } else if (possibleInverse.definition instanceof External) {
835 External ePossibleInverse = (External) possibleInverse.definition;
836 if (ePossibleInverse.name.equals("Inverse")) {
837 inverseRelation = TransferableGraphUtils.getPossibleObject2(graph,
838 connection, possibleInverse);
839 parentId = ePossibleInverse.parent;
841 // This is not an inverse
842 // LOGGER.error("THIS UNSUPPORTED
846 LOGGER.error("UNSUPPORTED for " + infoo + " ");
848 if (inverseRelation != TransferableGraphUtils.NOT_FOUND) {
849 // Ok found something
850 Identity object = TransferableGraphUtils.getIdentity(graph, inverseRelation);
851 Identity parent = TransferableGraphUtils.getIdentity(graph, parentId);
852 String objectName, parentName;
853 if (object.definition instanceof Internal) {
854 objectName = ((Internal) object.definition).name;
855 } else if (object.definition instanceof External) {
856 objectName = ((External) object.definition).name;
858 LOGGER.error("UNSUPPORTED " + infoo);
859 throw new Error("UNSUPPORTED " + infoo);
861 if (parent.definition instanceof Internal) {
862 parentName = ((Internal) parent.definition).name;
863 } else if (parent.definition instanceof External) {
864 parentName = ((External) parent.definition).name;
866 LOGGER.error("UNSUPPORTED " + infoo);
867 throw new Error("UNSUPPORTED " + infoo);
869 String fullName = parentName + "_" + objectName;
870 nameParts.add(fullName);
872 LOGGER.error("THIS IS ALSO UNSupported");
875 LOGGER.error("HERE");
878 nameParts.sort((o1, o2) -> o1.compareTo(o2));
880 for (String namep : nameParts) {
883 infoo.name = infoo.name.substring(0, infoo.name.lastIndexOf(".") + 1) + name;
885 LOGGER.error("Could not find connection for " + infoo + ". Statements of graph below");
886 LOGGER.error(Arrays.toString(graph.statements));
887 LOGGER.error("Subject -> Predicate : " + infoo.resource + " -> "
888 + diagramConnetionToConnection.resource);
894 for (ResourceInfo info : infos.valueCollection()) {
895 if (info.name.startsWith("blank")) {
896 info.name = "blank" + findHash(graph, info);
900 TreeMap<String, ResourceInfo> order = new TreeMap<>();
901 for (ResourceInfo info : infos.valueCollection())
902 order.put(info.name, info);
904 for (ResourceInfo info : order.values()) {
906 System.out.print("info ");
907 String uri = printURI(graph, info, true, 0, false);
912 TreeMap<String, ResourceInfo> rblanks = new TreeMap<>();
914 for (ResourceInfo info : order.values()) {
915 if (!info.hasURI && info.ownedResourcesWithPredicates.size() != 1) {
917 System.out.print("ownedResources ");
918 if (info.name.startsWith("blank")) {
919 // These will be printed later
920 rblanks.put(getBlankRewrite(info.name), info);
922 String uri = printURI(graph, info, false, 0, false);
928 // Now print blanks in order
929 for (ResourceInfo info : rblanks.values()) {
930 if (!info.hasURI && info.ownedResourcesWithPredicates.size() != 1) {
932 System.out.print("ownedResources ");
933 String uri = printURI(graph, info, false, 0, false);
939 // for(ResourceInfo info : order.values())
940 // if(!info.hasURI && info.owner < 0)
941 // printURI(graph, info, false, 0);
943 StringBuilder refs = new StringBuilder();
944 for (String ontology : referencedOntologies) {
945 String key = ontologies.get(ontology);
946 refs.append(key + " = <" + ontology + ">\n");
948 if (!referencedOntologies.isEmpty())
950 output.insert(0, refs.toString());
954 private String calculateHash(TransferableGraph1 graph, ResourceInfo info) {
955 StringBuilder statementHash = new StringBuilder();
956 TreeSet<String> parts = new TreeSet<>();
957 for (int i = 0; i < info.owned.size(); i += 2) {
958 int predicate = info.owned.get(i);
959 int object = info.owned.get(i + 1);
960 // Lets resolve a unique name for this based on the statements this
963 String predicatee = rewritePredicateURI(graph, predicate);
964 ResourceInfo objInfo = infos.get(object);
965 parts.add(predicatee + "->" + objInfo.name + ";;;");
967 // Remove this from the list
968 List<ResourceInfo> filtered = info.ownedBy.stream().filter(ri -> !ri.name.startsWith("blank"))
969 .collect(Collectors.toList());
970 for (ResourceInfo ownedBy : filtered) {
971 parts.add(ownedBy.name);
974 ResourceInfo parentInfo = infos.get(info.parent);
975 if (parentInfo != null && !parentInfo.name.startsWith("blank")) {
976 parts.add("parent" + parentInfo.name);
978 // LOGGER.error("This should not happen");
980 for (String s : parts) {
981 statementHash.append(s);
983 String hash = makeHash(statementHash.toString().getBytes());
985 System.out.println(statementHash + " -> " + hash);
989 private String findHash(TransferableGraph1 graph, ResourceInfo info) {
990 if (info.name.startsWith("blank")) {
991 String hash = hashes.get(info.name);
993 String oldName = info.name;
995 System.out.print("calculating hash for " + oldName + " ");
996 hash = calculateHash(graph, info);
997 if (hashes.put(oldName, hash) != null) {
998 System.err.println("!!!!A clash occured for " + info + " with hash " + hash);
1007 private THashMap<String, String> hashes = new THashMap<>();
1009 public static String print(TransferableGraph1 tg, boolean ignoreIdentifiers) throws Exception {
1010 StringBuilder b = new StringBuilder();
1011 new PrettyPrintTG(b, ignoreIdentifiers).prettyPrint(tg);
1012 return b.toString();
1015 public static void main(String[] args) throws Exception {
1016 if (args.length < 1) {
1017 System.out.println("Required arguments: <input .sharedOntology file> [<output .tg file>]");
1018 } else if (args.length < 2) {
1019 Path input = Paths.get(args[0]);
1020 Path output = input.getParent().resolve(input.getName(input.getNameCount() - 1) + ".fixed");
1021 new PrettyPrintTG().prettyPrint(input, output);
1023 new PrettyPrintTG().prettyPrint(Paths.get(args[0]), Paths.get(args[1]));
1027 private static void log(String string, Object... args) {
1028 if (LOGGER.isDebugEnabled() && DEBUG)
1029 LOGGER.debug(string, args);