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 this resource owns and what are the predicates for forming this ownership
83 TIntIntHashMap ownedResourcesWithPredicates = new TIntIntHashMap();
86 // int ownerPredicate = 0;
87 String aliasURI = null;
88 TIntArrayList owned = new TIntArrayList();
89 //TIntObjectHashMap<TIntHashSet> statements = new TIntObjectHashMap<TIntHashSet>();
90 public ResourceInfo(boolean hasURI, String name, int resource, int parent) {
93 this.resource = resource;
98 public String toString() {
99 return name + (aliasURI != null ? " = <" + aliasURI + ">" : "");
103 public PrettyPrintTG(StringBuilder b, boolean ignoreIdentifiers) throws NoSuchAlgorithmException {
105 m = MessageDigest.getInstance("SHA-256");
106 this.ignoreIdentifiers = ignoreIdentifiers;
109 public PrettyPrintTG() throws NoSuchAlgorithmException {
110 this(new StringBuilder(), false);
113 TreeMap<String, ResourceInfo> orderedInfos = new TreeMap<>();
114 TIntObjectHashMap<ResourceInfo> infos = new TIntObjectHashMap<>();
116 String tgNodeName(String name) {
117 if(name.contains(" ")) return "\"" + name + "\"";
121 ResourceInfo recurseURI(TransferableGraph1 graph, Identity parent, String parentName, int parentId) {
122 String name = parentName + "." + tgNodeName(TransferableGraphUtils.getName(parent));
123 ResourceInfo info = new ResourceInfo(true, name, parent.resource, parentId);
124 orderedInfos.put(name, info);
125 // infos.put(parent.resource, info);
126 for(Identity child : TransferableGraphUtils.getChildren(graph, parent)) {
127 recurseURI(graph, child, name, info.resource);
132 private TreeMap<String, TreeSet<Integer>> sortByPredicateUniqueStatements(TransferableGraph1 graph, int resource) {
133 TreeMap<String, TreeSet<Integer>> results = new TreeMap<>();
134 TIntArrayList statements = TransferableGraphUtils.getStatements(graph, resource);
135 for (int i = 0; i < statements.size(); i += 2) {
136 int predicate = statements.get(i);
137 String predicateURI = TransferableGraphUtils.getURI(graph, predicate);
138 TreeSet<Integer> objects = results.get(predicateURI);
139 if (objects == null) {
140 objects = new TreeSet<>();
142 objects.add(statements.get(i+1));
143 results.put(predicateURI, objects);
148 void discoverBlank(TransferableGraph1 graph, int resource, TIntArrayList todo) throws Exception {
149 // TIntArrayList statements = TransferableGraphUtils.getStatements(graph, resource);
150 // for(int i=0;i<statements.size();i+=2) {
151 for (TreeSet<Integer> objects : sortByPredicateUniqueStatements(graph, resource).values()) {
152 for (int object : objects) {
153 // int object = statements.get(i+1);
154 Identity objectId = TransferableGraphUtils.getIdentity(graph, object);
155 if(objectId != null) {
156 if(objectId.definition instanceof External) continue;
158 Value value = TransferableGraphUtils.findValue(graph, object);
160 infos.put(object, new ResourceInfo(false, printValue(value), object, resource));
163 ResourceInfo existing = infos.get(object);
164 if(existing == null) {
166 existing = new ResourceInfo(false, "blank" + blankCounter++, object, resource);
167 // existing = new ResourceInfo(false, "blank" + makeHash(statementHash.toString().getBytes()), object, resource);
169 String resourceURI = TransferableGraphUtils.getURI(graph, resource);
170 String objectURI = TransferableGraphUtils.getURI(graph, object);
172 // System.out.println("created blank" + blankCounter + " with object " + object + " resource " + resource);
173 infos.put(object, existing);
180 private String makeHash(byte[] data) {
182 m.update(data, 0, data.length);
183 return new BigInteger(1, m.digest()).toString(16);
186 void discoverOwners(TransferableGraph1 graph, ResourceInfo info) {
187 log("Discovering owners for " + info);
188 int resource = info.resource;
189 TIntArrayList statements = TransferableGraphUtils.getStatements(graph, resource);
190 for(int i=0;i<statements.size();i+=2) {
191 int predicate = statements.get(i);
192 int object = statements.get(i+1);
193 ResourceInfo existing = infos.get(object);
194 if(existing != null) {
195 // Add all owners here for now and resolve the best owner later
197 // Check if predicate is inverse, this just resolves all predicates to be inverse with ending "Inverse"..
198 String predicateUri = rewritePredicateURI(graph, predicate);
199 if (!predicateUri.endsWith("Inverse") && !predicateUri.endsWith("Of")) {
200 existing.ownedResourcesWithPredicates.put(resource, predicate);
201 // if (predicateUri.endsWith("Of")) {
202 // System.out.println("asd");
204 existing.ownedBy.add(info);
205 log(" " + existing + " owns " + info + " with " + predicateUri);
208 // System.out.println("asd");
214 DataValueRepository repo = new DataValueRepository();
215 DataValuePrinter printer = new DataValuePrinter(null, repo);
217 String printValue(Value value) throws Exception {
218 StringBuilder sb = new StringBuilder();
219 printer.setFormat(PrintFormat.SINGLE_LINE);
220 printer.setOutput(sb);
222 Variant variant = value.value;
223 printer.print(variant.getBinding(), variant.getValue());
224 String formattedOutput = sb.toString();
225 if (formattedOutput.length() > 100) {
226 // Ok, value too long, lets calculate a hash for it and store first 100 chars as comment
227 byte[] data = Bindings.getSerializerUnchecked(variant.getBinding()).serialize(variant.getValue());
229 m.update(data, 0, data.length);
230 String hash = "\"" + new BigInteger(1, m.digest()).toString(16) + "\"";
231 return hash + " // " + formattedOutput.substring(0, 100) + "..";
233 return formattedOutput;
236 // Variant variant = value.value;
237 // Datatype dt = variant.getBinding().type();
238 // if (Datatypes.STRING.equals(dt)) {
239 // String s = (String) variant.getValue(Bindings.STRING);
240 // if (s.contains("\n")) {
241 // return "\"\"\"" + s + "\"\"\"";
243 // return "\"" + s + "\"";
245 // } else if (Datatypes.BOOLEAN.equals(dt)) {
246 // Boolean i = (Boolean) variant.getValue(Bindings.BOOLEAN);
247 // return i ? "true" : "false";
248 // } else if (Datatypes.INTEGER.equals(dt)) {
249 // Integer i = (Integer) variant.getValue(Bindings.INTEGER);
250 // return i.toString();
251 // } else if (Datatypes.LONG.equals(dt)) {
252 // Long i = (Long) variant.getValue(Bindings.LONG);
253 // return i.toString();
254 // } else if (Datatypes.DOUBLE.equals(dt)) {
255 // Double d = (Double) variant.getValue();
256 // return d.toString();
257 // } else if (Datatypes.FLOAT.equals(dt)) {
258 // Float f = (Float) variant.getValue();
259 // return f.toString();
260 // } else if (Datatypes.STRING_ARRAY.equals(dt)) {
261 // return Arrays.toString((String []) variant.getValue());
262 // } else if (Datatypes.BOOLEAN_ARRAY.equals(dt)) {
263 // return Arrays.toString((boolean []) variant.getValue());
264 // } else if (Datatypes.INTEGER_ARRAY.equals(dt)) {
265 // return Arrays.toString((int []) variant.getValue());
266 // } else if (Datatypes.LONG_ARRAY.equals(dt)) {
267 // return Arrays.toString((long []) variant.getValue());
268 // } else if (Datatypes.DOUBLE_ARRAY.equals(dt)) {
269 // return Arrays.toString((double []) variant.getValue());
270 // } else if (Datatypes.FLOAT_ARRAY.equals(dt)) {
271 // return Arrays.toString((float []) variant.getValue());
272 // } else if (Datatypes.BYTE_ARRAY.equals(dt)) {
273 // return Arrays.toString((byte []) variant.getValue());
274 //// } else if (dt instanceof ArrayType) {
275 //// return Arrays.toString((Object []) variant.getValue());
277 // byte[] data = Bindings.getSerializerUnchecked(variant.getBinding()).serialize(variant.getValue());
279 // m.update(data, 0, data.length);
280 // return "\"" + new BigInteger(1, m.digest()).toString(16) + "\"";
285 // void fixInstanceOf(TransferableGraph1 graph, ResourceInfo info) {
286 // Identity id = getIdentity(graph, info.resource);
287 // if(id == null) return;
288 // if(id.definition instanceof Internal) {
289 // Identity instanceOf = findExternal(graph, "http://www.simantics.org/Layer0-1.1/InstanceOf");
290 // Identity library = findExternal(graph, "http://www.simantics.org/Layer0-1.1/Library");
291 // info.statements.add(instanceOf.resource);
292 // info.statements.add(library.resource);
296 public static String getExternalURI(TransferableGraph1 tg, External ext) {
297 String name = ext.name;
298 if(name.contains(" ")) name = name.replace(" ", "_").replaceAll("@", "_");//name = "\"" + name + "\"";
299 int parentId = ext.parent;
300 //if(parentId == 0) return ext.name;
302 Identity id = TransferableGraphUtils.getIdentity(tg, parentId);
303 if(id.definition instanceof External) {
304 return getExternalURI(tg, (External)id.definition) + "/" + name;
305 } else if(id.definition instanceof Root) {
306 Root root = (Root)id.definition;
307 return "http:/" + root.name + "/" + name;
314 public static String getExternalURI(TransferableGraph1 tg, int resource) {
315 Identity id = TransferableGraphUtils.getIdentity(tg, resource);
316 if(id == null) return null;
317 if(id.definition instanceof External) {
318 External ext = (External)id.definition;
319 return getExternalURI(tg, ext);
324 String rewritePredicateURI(TransferableGraph1 graph, int predicate) {
326 String uri = getExternalURI(graph, predicate);
328 ResourceInfo info = infos.get(predicate);
329 if(info != null) return info.name;
333 for(String ontology : ontologies.keySet()) {
334 if(uri.contains(ontology)) {
335 String key = ontologies.get(ontology);
336 uri = uri.replace(ontology, key);
337 referencedOntologies.add(ontology);
341 uri = uri.replace("/", ".");
347 static void indent(StringBuilder output, int indent) {
348 for(int i=0;i<indent;i++)
352 String printBlank(TransferableGraph1 graph, String predicateURI2, ResourceInfo info, int indent) {
357 StringBuilder output = new StringBuilder();
359 String infoName = info.name;
360 if (infoName.startsWith("blank")) {
361 infoName = getBlankRewrite(infoName);
364 if (ignoreIdentifiers) {
365 if (predicateURI2.contains("L0.identifier")) {
368 indent(output, indent);
369 output.append(predicateURI2 + " " + infoName + "\n");
372 indent(output, indent);
373 output.append(predicateURI2 + " " + infoName + "\n");
376 if (info.ownedResourcesWithPredicates.isEmpty()) {
378 System.out.print("printBlank");
379 String uri = printURI(graph, info, false, indent, false);
383 // if(info.owner < 0) {
384 // printURI(graph, info, false, indent);
386 return output.toString();
389 private String getBlankRewrite(String infoName) {
390 String rewrite = blankRewrites.get(infoName);
391 if (rewrite == null) {
392 rewrite = "rblank" + newBlankCounter++;
394 System.out.println("rewrote " + infoName + " to " + rewrite);
395 blankRewrites.put(infoName, rewrite);
401 static long longStm(int predicate, int object) {
402 return ((predicate & 0xffffffffL)<<32) | (object & 0xffffffffL);
405 private void addInlineStatement(TransferableGraph1 graph, Map<String, Set<String>> statements, String predicate, ResourceInfo objectInfo, int indent) {
406 Set<String> objects = statements.get(predicate);
407 if(objects == null) {
408 objects = new TreeSet<>();
409 statements.put(predicate, objects);
411 String uri = printURI(graph, objectInfo, false, indent + 1, true);
413 // TODO: this is not the right place to remove trailing newline
414 uri = uri.endsWith("\n") ? uri.substring(0, uri.length() - 2) : uri;
417 objectInfo.inlined = true;
421 void addStatement(Map<String,Set<String>> statements, String predicate, String object) {
423 if (predicate.endsWith("Inverse"))
425 Set<String> objects = statements.get(predicate);
426 if(objects == null) {
427 objects = new TreeSet<>();
428 statements.put(predicate, objects);
433 String printURI(TransferableGraph1 graph, ResourceInfo info, boolean requireURI, int indent, boolean inline) {
435 if(requireURI && !info.hasURI)
438 // Check if this ResourceInfo is already inlined with some other ResourceInfo
442 Map<String,Set<String>> statements = new TreeMap<>();
443 Identity consistsOf = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
444 // Identity partOf = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Layer0-1.1/PartOf");
445 TLongHashSet processed = new TLongHashSet();
447 System.out.println("info.owned.size " + info.owned.size() + info.owned);
448 for(int i=0;i<info.owned.size();i+=2) {
449 int predicate = info.owned.get(i);
450 int object = info.owned.get(i+1);
451 long stmId = longStm(predicate, object);
453 System.out.println(" " + stmId + " is already processed as it is owned (" + predicate + " " + object + ")");
454 processed.add(stmId);
457 TreeMap<String, Integer> predicateURIs = new TreeMap<>();
459 TIntArrayList rawStatements = TransferableGraphUtils.getStatements(graph, info.resource);
461 System.out.println("rawStatements size for " + info.name + " : " + rawStatements.size() + " " + rawStatements);
462 for(int i=0;i<rawStatements.size();i+=2) {
463 int predicate = rawStatements.get(i);
464 int object = rawStatements.get(i+1);
465 long stmId = longStm(predicate, object);
466 if(!processed.add(stmId)) {
468 System.out.println(" " + stmId + " is already processed (" + (predicate & 0xffffffffL) + " " + (object & 0xffffffffL) + ")");
472 System.out.println(" " + stmId + " is currently being processed (" + (predicate & 0xffffffffL) + " " + (object & 0xffffffffL) + ")");
473 // if (partOf.resource == rawStatements.get(i))
475 if(consistsOf.resource == predicate) {
476 // if (!info.owned.isEmpty() && !info.name.startsWith("blank")) {
478 System.out.println(" is consistsof " + predicate + " (" + consistsOf.resource + ")");
481 // // this will be inlined so lets indent
485 String predicateURI = rewritePredicateURI(graph, predicate);
486 predicateURIs.put(predicateURI, object);
488 for (Entry<String, Integer> entry : predicateURIs.entrySet()) {
489 String predicateURI = entry.getKey();
490 int object = entry.getValue();
492 ResourceInfo objectInfo = infos.get(object);
493 if(objectInfo == null) {
494 String objectURI = rewritePredicateURI(graph, object);
496 System.out.println(" adding statement " + predicateURI + " " + objectURI);
497 addStatement(statements, predicateURI, objectURI);
498 } else if (objectInfo.ownedBy.size() == 1 && objectInfo.ownedBy.contains(info)) {
499 // inline printing with _
501 System.out.println(" adding inline statement " + predicateURI + " " + objectInfo.name);
502 addInlineStatement(graph, statements, predicateURI, objectInfo, indent);
504 String objectName = objectInfo.name;
505 if (objectName.startsWith("blank")) {
506 objectName = getBlankRewrite(objectName);
509 System.out.println(" adding statement " + predicateURI + " " + objectName);
510 addStatement(statements, predicateURI, objectName);
515 System.out.println("statements size for " + info.name + " : " + statements.size() + " " + statements.keySet());
517 StringBuilder output = new StringBuilder();
519 if(indent == 0 || inline) {
520 if("ROOT".equals(info.name)) {
521 output.append("ROOT=<http:/>");
522 } else if (info.aliasURI != null) {
523 output.append(info.name + " = <" + info.aliasURI + ">");
525 String infoName = info.name;
526 if (infoName.startsWith("blank")) {
527 infoName = getBlankRewrite(infoName);
529 output.append(inline ? "_" : infoName);
531 Set<String> instanceOfs = statements.get("L0.InstanceOf");
532 if(instanceOfs != null) {
533 for(String instanceOf : instanceOfs) {
534 output.append(" : " + instanceOf);
537 Set<String> subrelationOfs = statements.get("L0.SubrelationOf");
538 if(subrelationOfs != null) {
539 for(String subrelationOf : subrelationOfs) {
540 output.append(" <R " + subrelationOf);
543 Set<String> inherits = statements.get("L0.Inherits");
544 if(inherits != null) {
545 for(String inherit : inherits) {
546 output.append(" <T " + inherit);
553 output.append(" @L0.new\n");
555 for(Map.Entry<String, Set<String>> entry : statements.entrySet()) {
556 String predicate = entry.getKey();
557 if (ignoreIdentifiers) {
558 if (predicate.equals("L0.identifier")) {
562 if("L0.InstanceOf".equals(predicate)) continue;
563 if("L0.SubrelationOf".equals(predicate)) continue;
564 if("L0.Inherits".equals(predicate)) continue;
565 if("L0.PartOf".equals(predicate)) continue;
567 // predicates can be blank
568 if (predicate.startsWith("blan")) {
569 predicate = getBlankRewrite(predicate);
572 Set<String> objects = entry.getValue();
573 indent(output, indent+1);
574 if(objects.size() == 1) {
575 output.append(predicate + " " + objects.iterator().next() + "\n");
577 output.append(predicate + "\n");
578 for(String object : objects) {
579 indent(output, indent+1);
580 output.append(" " + object + "\n");
585 TreeMap<String, Integer> ownedOrdered = new TreeMap<>();
587 for(int i=0;i<info.owned.size();i+=2) {
588 String predicateURI = rewritePredicateURI(graph, info.owned.get(i));
589 ownedOrdered.put(predicateURI, info.owned.get(i+1));
593 System.out.println(info.name + " : " + ownedOrdered.keySet());
596 for (Entry<String, Integer> entry : ownedOrdered.entrySet()) {
597 String predicateURI = entry.getKey();
598 int owned = entry.getValue();
599 ResourceInfo ownedInfo = infos.get(owned);
601 String blank = printBlank(graph, predicateURI, ownedInfo, indent+1);
603 output.append(blank);
607 return output.toString();
610 void prettyPrint(Path input, Path output) throws Exception {
612 System.out.format("Converting exported shared ontology%n\t" + input.toString() + "%nto bundle-compatible ontology%n\t" + output.toString());
613 try (InputStream is = new BufferedInputStream(Files.newInputStream(input), 128*1024)) {
614 DataInput dis = new DataInputStream(is);
615 org.simantics.databoard.container.DataContainer container =
616 DataContainers.readFile(dis);
617 Binding binding = TransferableGraph1.BINDING;
618 TransferableGraph1 graph = (TransferableGraph1)container.content.getValue(binding);
620 Files.write(output, this.output.toString().getBytes());
626 static Map<String,String> knownOntologies = new HashMap<>();
629 knownOntologies.put("http://www.simantics.org/Layer0-1.1", "L0");
630 knownOntologies.put("http://www.simantics.org/Layer0X-1.1", "L0X");
631 knownOntologies.put("http://www.simantics.org/Modeling-1.2", "MOD");
632 knownOntologies.put("http://www.simantics.org/Diagram-2.2", "DIA");
633 knownOntologies.put("http://www.simantics.org/Structural-1.2", "STR");
634 knownOntologies.put("http://www.simantics.org/Document-1.2", "DOC");
635 knownOntologies.put("http://www.simantics.org/Documentation-1.2", "DOCU");
636 knownOntologies.put("http://www.simantics.org/G2D-1.1", "G2D");
637 knownOntologies.put("http://www.simantics.org/SelectionView-1.2", "SEL");
638 knownOntologies.put("http://www.simantics.org/Viewpoint-1.2", "VP");
639 knownOntologies.put("http://www.simantics.org/Image2-1.2", "IMAGE2");
640 knownOntologies.put("http://www.simantics.org/GraphFile-0.1", "GRAPHFILE");
641 knownOntologies.put("http://www.simantics.org/Project-1.2", "PROJECT");
642 knownOntologies.put("http://www.semantum.fi/Simupedia-1.0", "SIMUPEDIA");
643 knownOntologies.put("http://www.semantum.fi/SimupediaWorkbench-1.0", "SIMUPEDIA_WORKBENCH");
647 void prettyPrint(TransferableGraph1 graph) throws Exception {
648 log("Starting prettyPrint for TransferableGraph with " + graph.resourceCount + " resources, " + graph.identities + " identities, " + graph.statements.length + " statements and " + graph.values.length + " values");
650 for(Identity id : graph.identities) {
651 if(id.definition instanceof Internal) {
652 Internal internal = (Internal)id.definition;
653 Identity parent = TransferableGraphUtils.getIdentity(graph, internal.parent);
654 if(parent.definition instanceof External) {
655 log("Resolving internal identity " + id);
656 String name = "BASE";
657 ResourceInfo info = new ResourceInfo(true, name, id.resource, -1);
658 info.aliasURI = TransferableGraphUtils.getURI(graph, id.resource);
659 info.newResource = true;
660 orderedInfos.put(name, info);
661 // infos.put(id.resource, info);
662 log(" which parent is external " + parent + " and has an aliasURI " + info.aliasURI);
663 for(Identity child : TransferableGraphUtils.getChildren(graph, id)) {
664 recurseURI(graph, child, name, info.resource);
666 log(" and has " + (infos.size() - 1) + " children");
668 } else if (id.definition instanceof External) {
669 External ext = (External)id.definition;
670 // Try to detect shared libraries
671 if(ext.name.contains("@")) {
673 log("Detected an external shared library " + ext);
675 int index = ext.name.indexOf('@');
676 String prefix = ext.name.substring(0, index);
677 int index2 = ext.name.indexOf('/', index);
678 String ontology = index2 == -1 ? ext.name : ext.name.substring(0, index2);
679 String uri = TransferableGraphUtils.getURI(graph, id.resource);
681 log(" which was resolved as URI=" + uri + " and prefix " + prefix);
683 ontologies.put(uri, prefix);
685 } else if (ext.name.contains("-")) {
686 log("Resolving possible ontology " + ext);
687 String uri = TransferableGraphUtils.getURI(graph, id.resource);
688 Matcher m = versionExtractPattern.matcher(uri);
690 if(!ontologies.containsKey(uri)) {
691 int index = ext.name.indexOf('-');
692 String prefix = ext.name.substring(0, index);
693 log(" and it was resolved as URI=" + uri + " and prefix " + prefix);
694 ontologies.put(uri, prefix);
701 // Discover other resources
702 log("Discovering other resources..");
704 TIntArrayList todo = new TIntArrayList();
705 for(ResourceInfo info : orderedInfos.values()) {
706 todo.add(info.resource);
708 // put orderedInfos to infos
709 infos.put(info.resource, info);
712 while(!todo.isEmpty()) {
713 int resource = todo.removeAt(todo.size()-1);
714 discoverBlank(graph, resource, todo);
716 for(ResourceInfo info : infos.valueCollection())
717 discoverOwners(graph, info);
718 // for(ResourceInfo info : infos.valueCollection())
719 // fixInstanceOf(graph, info);
721 for (ResourceInfo info : infos.valueCollection()) {
722 // Old implementation
723 // if (info.owner >= 0) {
724 // ResourceInfo ownerInfo = infos.get(info.owner);
725 // System.out.println("originalOwner : " + info.owner + " originalPredicate: " + info.ownerPredicate);
726 // ownerInfo.owned.add(info.ownerPredicate);
727 // ownerInfo.owned.add(info.resource);
730 if (!info.ownedResourcesWithPredicates.isEmpty() && info.ownedResourcesWithPredicates.size() == 1) {
731 info.ownedResourcesWithPredicates.forEachEntry(new TIntIntProcedure() {
734 public boolean execute(int owner, int predicate) {
735 ResourceInfo ownerInfo = infos.get(owner);
736 ownerInfo.owned.add(predicate);
737 ownerInfo.owned.add(info.resource);
744 // Resolve inverses from ownedBy list
745 for (ResourceInfo info : infos.valueCollection()) {
746 for (int i = 0; i < info.owned.size(); i+=2) {
747 int object = info.owned.get(i+1);
748 ResourceInfo inf = infos.get(object);
750 info.ownedBy.remove(inf);
755 Identity routeGraphConn = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Diagram-2.2/RouteGraphConnection");
756 Identity instanceOf = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Layer0-1.1/InstanceOf");
757 Identity diagramConnetionToConnection = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Modeling-1.2/DiagramConnectionToConnection");
759 for (ResourceInfo infoo : infos.valueCollection()) {
760 Identity elemTo = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Modeling-1.2/ElementToComponent");
761 if (elemTo != null) {
762 int elemToComponent = TransferableGraphUtils.getPossibleObject2(graph, infoo.resource, elemTo);
763 if (elemToComponent != TransferableGraphUtils.NOT_FOUND) {
765 Identity component = TransferableGraphUtils.getIdentity(graph, elemToComponent);
766 Identity internal = TransferableGraphUtils.getIdentity(graph, infoo.resource);
767 if (internal.definition instanceof Internal && component.definition instanceof Internal) {
768 Internal iCOmponent = (Internal) component.definition;
769 infoo.name = infoo.name.substring(0, infoo.name.lastIndexOf(".")+1) + iCOmponent.name;
774 if (instanceOf != null) {
775 int instOf = TransferableGraphUtils.getPossibleObject2(graph, infoo.resource, instanceOf);
776 if (instOf != TransferableGraphUtils.NOT_FOUND && routeGraphConn != null) {
777 if (instOf == routeGraphConn.resource) {
778 // Found routegraphconnection, change name
779 // Lets go to configuration
781 int connection = TransferableGraphUtils.getPossibleObject2(graph, infoo.resource, diagramConnetionToConnection);
782 if (connection != TransferableGraphUtils.NOT_FOUND) {
783 // Gather all inverse statements to construct unique name
784 List<String> nameParts = new ArrayList<>();
785 TIntArrayList statements = TransferableGraphUtils.getStatements(graph, connection);
786 for (int i = 0; i < statements.size(); i+=2) {
787 int predicate = statements.get(i);
788 Identity possibleInverse = TransferableGraphUtils.getIdentity(graph, predicate);
789 if (possibleInverse != null) {
790 int inverseRelation = TransferableGraphUtils.NOT_FOUND;
791 int parentId = TransferableGraphUtils.NOT_FOUND;
792 if (possibleInverse.definition instanceof Internal) {
793 Internal iPossibleInverse = (Internal) possibleInverse.definition;
794 if (iPossibleInverse.name.equals("Inverse")) {
795 inverseRelation = TransferableGraphUtils.getPossibleObject2(graph, connection, possibleInverse);
796 parentId = iPossibleInverse.parent;
798 LOGGER.error("THIS UNSUPPORTED for " + infoo + " " + iPossibleInverse);
800 } else if (possibleInverse.definition instanceof External) {
801 External ePossibleInverse = (External) possibleInverse.definition;
802 if (ePossibleInverse.name.equals("Inverse")) {
803 inverseRelation = TransferableGraphUtils.getPossibleObject2(graph, connection, possibleInverse);
804 parentId = ePossibleInverse.parent;
806 // This is not an inverse
807 // LOGGER.error("THIS UNSUPPORTED TOO");
810 LOGGER.error("UNSUPPORTED for " + infoo + " " );
812 if (inverseRelation != TransferableGraphUtils.NOT_FOUND) {
813 // Ok found something
814 Identity object = TransferableGraphUtils.getIdentity(graph, inverseRelation);
815 Identity parent = TransferableGraphUtils.getIdentity(graph, parentId);
816 String objectName, parentName;
817 if (object.definition instanceof Internal) {
818 objectName = ((Internal) object.definition).name;
819 } else if (object.definition instanceof External) {
820 objectName = ((External) object.definition).name;
822 LOGGER.error("UNSUPPORTED " + infoo);
823 throw new Error("UNSUPPORTED " + infoo);
825 if (parent.definition instanceof Internal) {
826 parentName = ((Internal) parent.definition).name;
827 } else if (parent.definition instanceof External) {
828 parentName = ((External) parent.definition).name;
830 LOGGER.error("UNSUPPORTED " + infoo);
831 throw new Error("UNSUPPORTED " + infoo);
833 String fullName = parentName + "_" + objectName;
834 nameParts.add(fullName);
836 LOGGER.error("THIS IS ALSO UNSupported");
839 LOGGER.error("HERE");
842 nameParts.sort((o1, o2) -> o1.compareTo(o2));
844 for (String namep : nameParts) {
847 infoo.name = infoo.name.substring(0, infoo.name.lastIndexOf(".") + 1) + name;
849 LOGGER.error("Could not find connection for " + infoo + ". Statements of graph below");
850 LOGGER.error(Arrays.toString(graph.statements));
851 LOGGER.error("Subject -> Predicate : " + infoo.resource + " -> " + diagramConnetionToConnection.resource);
857 for (ResourceInfo info : infos.valueCollection()) {
858 if (info.name.startsWith("blank")) {
859 info.name = "blank" + findHash(graph, info);
863 TreeMap<String,ResourceInfo> order = new TreeMap<>();
864 for(ResourceInfo info : infos.valueCollection())
865 order.put(info.name, info);
867 for(ResourceInfo info : order.values()) {
869 System.out.print("info ");
870 String uri = printURI(graph, info, true, 0, false);
875 TreeMap<String, ResourceInfo> rblanks = new TreeMap<>();
877 for (ResourceInfo info : order.values()) {
878 if (!info.hasURI && info.ownedResourcesWithPredicates.size() != 1) {
880 System.out.print("ownedResources ");
881 if (info.name.startsWith("blank")) {
882 // These will be printed later
883 rblanks.put(getBlankRewrite(info.name), info);
885 String uri = printURI(graph, info, false, 0, false);
891 // Now print blanks in order
892 for (ResourceInfo info : rblanks.values()) {
893 if (!info.hasURI && info.ownedResourcesWithPredicates.size() != 1) {
895 System.out.print("ownedResources ");
896 String uri = printURI(graph, info, false, 0, false);
902 // for(ResourceInfo info : order.values())
903 // if(!info.hasURI && info.owner < 0)
904 // printURI(graph, info, false, 0);
906 StringBuilder refs = new StringBuilder();
907 for(String ontology : referencedOntologies) {
908 String key = ontologies.get(ontology);
909 refs.append(key + " = <" + ontology + ">\n");
911 if (!referencedOntologies.isEmpty())
913 output.insert(0, refs.toString());
917 private String calculateHash(TransferableGraph1 graph, ResourceInfo info) {
918 StringBuilder statementHash = new StringBuilder();
919 TreeSet<String> parts = new TreeSet<>();
920 for (int i = 0; i < info.owned.size(); i+=2) {
921 int predicate = info.owned.get(i);
922 int object = info.owned.get(i+1);
923 // Lets resolve a unique name for this based on the statements this
926 String predicatee = rewritePredicateURI(graph, predicate);
927 ResourceInfo objInfo = infos.get(object);
928 parts.add(predicatee + "->" + objInfo.name + ";;;");
930 // Remove this from the list
931 List<ResourceInfo> filtered = info.ownedBy.stream().filter(ri -> !ri.name.startsWith("blank")).collect(Collectors.toList());
932 for (ResourceInfo ownedBy : filtered) {
933 parts.add(ownedBy.name);
936 ResourceInfo parentInfo = infos.get(info.parent);
937 if (parentInfo != null && !parentInfo.name.startsWith("blank")) {
938 parts.add("parent" + parentInfo.name);
940 // LOGGER.error("This should not happen");
942 for (String s : parts) {
943 statementHash.append(s);
945 String hash = makeHash(statementHash.toString().getBytes());
947 System.out.println(statementHash + " -> " + hash);
951 private String findHash(TransferableGraph1 graph, ResourceInfo info) {
952 if (info.name.startsWith("blank")) {
953 String hash = hashes.get(info.name);
955 String oldName = info.name;
957 System.out.print("calculating hash for " + oldName + " ");
958 hash = calculateHash(graph, info);
959 if (hashes.put(oldName, hash) != null) {
960 System.err.println("!!!!A clash occured for " + info + " with hash " + hash);
969 private THashMap<String, String> hashes = new THashMap<>();
971 public static String print(TransferableGraph1 tg, boolean ignoreIdentifiers) throws Exception {
972 StringBuilder b = new StringBuilder();
973 new PrettyPrintTG(b, ignoreIdentifiers).prettyPrint(tg);
977 public static void main(String[] args) throws Exception {
978 if (args.length < 1) {
979 System.out.println("Required arguments: <input .sharedOntology file> [<output .tg file>]");
980 } else if (args.length < 2) {
981 Path input = Paths.get(args[0]);
982 Path output = input.getParent().resolve(input.getName(input.getNameCount()-1) + ".fixed");
983 new PrettyPrintTG().prettyPrint(input, output);
985 new PrettyPrintTG().prettyPrint(Paths.get(args[0]), Paths.get(args[1]));
989 private static void log(String string) {
990 if (LOGGER.isDebugEnabled() && DEBUG)
991 LOGGER.debug(string);