package org.simantics.graph.representation; import java.io.BufferedInputStream; import java.io.DataInput; import java.io.DataInputStream; import java.io.InputStream; import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import org.simantics.databoard.Bindings; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.mutable.Variant; import org.simantics.databoard.container.DataContainers; import org.simantics.databoard.parser.DataValuePrinter; import org.simantics.databoard.parser.PrintFormat; import org.simantics.databoard.parser.repository.DataValueRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import gnu.trove.list.array.TIntArrayList; import gnu.trove.map.hash.THashMap; import gnu.trove.map.hash.TIntIntHashMap; import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.procedure.TIntIntProcedure; import gnu.trove.set.hash.TLongHashSet; /** * @author Antti Villberg * @since 1.24.0 */ public class PrettyPrintTG { private static final Logger LOGGER = LoggerFactory.getLogger(PrettyPrintTG.class); private static final boolean DEBUG = false; int blankCounter = 0; int newBlankCounter = 0; Map blankRewrites = new HashMap<>(); MessageDigest m; private final Pattern versionExtractPattern = Pattern.compile("^.*-(\\d+\\.\\d+)"); final StringBuilder output; final Map ontologies = new HashMap<>(knownOntologies); final Set referencedOntologies = new TreeSet<>(); private boolean ignoreIdentifiers; static class ResourceInfo { final boolean hasURI; String name; final int resource; boolean newResource = false; int parent; boolean inlined = false; // -1 = no owner, -2 = multiple owners // Set ownedBy Set ownedBy = new HashSet<>(); // A Map containing information about resource that // this resource owns and what are the predicates for forming this // ownership TIntIntHashMap ownedResourcesWithPredicates = new TIntIntHashMap(); // int owner = -1; // int ownerPredicate = 0; String aliasURI = null; TIntArrayList owned = new TIntArrayList(); // TIntObjectHashMap statements = new // TIntObjectHashMap(); public ResourceInfo(boolean hasURI, String name, int resource, int parent) { this.hasURI = hasURI; this.name = name; this.resource = resource; this.parent = parent; } @Override public String toString() { return name + (aliasURI != null ? " = <" + aliasURI + ">" : ""); } } public PrettyPrintTG(StringBuilder b, boolean ignoreIdentifiers) throws NoSuchAlgorithmException { output = b; m = MessageDigest.getInstance("SHA-256"); this.ignoreIdentifiers = ignoreIdentifiers; } public PrettyPrintTG() throws NoSuchAlgorithmException { this(new StringBuilder(), false); } TreeMap orderedInfos = new TreeMap<>(); TIntObjectHashMap infos = new TIntObjectHashMap<>(); String tgNodeName(String name) { if (name.contains(" ")) return "\"" + name + "\""; else return name; } ResourceInfo recurseURI(TransferableGraph1 graph, Identity parent, String parentName, int parentId) { String name = parentName + "." + tgNodeName(TransferableGraphUtils.getName(parent)); ResourceInfo info = new ResourceInfo(true, name, parent.resource, parentId); orderedInfos.put(name, info); // infos.put(parent.resource, info); for (Identity child : TransferableGraphUtils.getChildren(graph, parent)) { recurseURI(graph, child, name, info.resource); } return info; } private TreeMap> sortByPredicateUniqueStatements(TransferableGraph1 graph, int resource) { TreeMap> results = new TreeMap<>(); TIntArrayList statements = TransferableGraphUtils.getStatements(graph, resource); for (int i = 0; i < statements.size(); i += 2) { int predicate = statements.get(i); String predicateURI = TransferableGraphUtils.getURI(graph, predicate); TreeSet objects = results.get(predicateURI); if (objects == null) { objects = new TreeSet<>(); } objects.add(statements.get(i + 1)); results.put(predicateURI, objects); } return results; } void discoverBlank(TransferableGraph1 graph, int resource, TIntArrayList todo) throws Exception { // TIntArrayList statements = // TransferableGraphUtils.getStatements(graph, resource); // for(int i=0;i objects : sortByPredicateUniqueStatements(graph, resource).values()) { for (int object : objects) { // int object = statements.get(i+1); Identity objectId = TransferableGraphUtils.getIdentity(graph, object); if (objectId != null) { if (objectId.definition instanceof External) continue; } Value value = TransferableGraphUtils.findValue(graph, object); if (value != null) { infos.put(object, new ResourceInfo(false, printValue(value), object, resource)); continue; } ResourceInfo existing = infos.get(object); if (existing == null) { existing = new ResourceInfo(false, "blank" + blankCounter++, object, resource); // System.out.println("created blank" + blankCounter + " // with object " + object + " resource " + resource); infos.put(object, existing); todo.add(object); } } } } private String makeHash(byte[] data) { m.reset(); m.update(data, 0, data.length); return new BigInteger(1, m.digest()).toString(16); } void discoverOwners(TransferableGraph1 graph, ResourceInfo info) { log("Discovering owners for {}", info); int resource = info.resource; TIntArrayList statements = TransferableGraphUtils.getStatements(graph, resource); for (int i = 0; i < statements.size(); i += 2) { int predicate = statements.get(i); int object = statements.get(i + 1); ResourceInfo existing = infos.get(object); if (existing != null) { // Add all owners here for now and resolve the best owner later // Check if predicate is inverse, this just resolves all // predicates to be inverse with ending "Inverse".. String predicateUri = rewritePredicateURI(graph, predicate); if (!predicateUri.endsWith("Inverse") && !predicateUri.endsWith("Of")) { existing.ownedResourcesWithPredicates.put(resource, predicate); // if (predicateUri.endsWith("Of")) { // System.out.println("asd"); // } else { existing.ownedBy.add(info); log(" {} owns {} with {}", existing, info, predicateUri); // } } else { // System.out.println("asd"); } } } } DataValueRepository repo = new DataValueRepository(); DataValuePrinter printer = new DataValuePrinter(null, repo); String printValue(Value value) throws Exception { StringBuilder sb = new StringBuilder(); printer.setFormat(PrintFormat.SINGLE_LINE); printer.setOutput(sb); Variant variant = value.value; printer.print(variant.getBinding(), variant.getValue()); String formattedOutput = sb.toString(); if (formattedOutput.length() > 100) { // Ok, value too long, lets calculate a hash for it and store first // 100 chars as comment byte[] data = Bindings.getSerializerUnchecked(variant.getBinding()).serialize(variant.getValue()); m.reset(); m.update(data, 0, data.length); String hash = "\"" + new BigInteger(1, m.digest()).toString(16) + "\""; return hash + " // " + formattedOutput.substring(0, 100) + ".."; } else { return formattedOutput; } // // Variant variant = value.value; // Datatype dt = variant.getBinding().type(); // if (Datatypes.STRING.equals(dt)) { // String s = (String) variant.getValue(Bindings.STRING); // if (s.contains("\n")) { // return "\"\"\"" + s + "\"\"\""; // } else { // return "\"" + s + "\""; // } // } else if (Datatypes.BOOLEAN.equals(dt)) { // Boolean i = (Boolean) variant.getValue(Bindings.BOOLEAN); // return i ? "true" : "false"; // } else if (Datatypes.INTEGER.equals(dt)) { // Integer i = (Integer) variant.getValue(Bindings.INTEGER); // return i.toString(); // } else if (Datatypes.LONG.equals(dt)) { // Long i = (Long) variant.getValue(Bindings.LONG); // return i.toString(); // } else if (Datatypes.DOUBLE.equals(dt)) { // Double d = (Double) variant.getValue(); // return d.toString(); // } else if (Datatypes.FLOAT.equals(dt)) { // Float f = (Float) variant.getValue(); // return f.toString(); // } else if (Datatypes.STRING_ARRAY.equals(dt)) { // return Arrays.toString((String []) variant.getValue()); // } else if (Datatypes.BOOLEAN_ARRAY.equals(dt)) { // return Arrays.toString((boolean []) variant.getValue()); // } else if (Datatypes.INTEGER_ARRAY.equals(dt)) { // return Arrays.toString((int []) variant.getValue()); // } else if (Datatypes.LONG_ARRAY.equals(dt)) { // return Arrays.toString((long []) variant.getValue()); // } else if (Datatypes.DOUBLE_ARRAY.equals(dt)) { // return Arrays.toString((double []) variant.getValue()); // } else if (Datatypes.FLOAT_ARRAY.equals(dt)) { // return Arrays.toString((float []) variant.getValue()); // } else if (Datatypes.BYTE_ARRAY.equals(dt)) { // return Arrays.toString((byte []) variant.getValue()); //// } else if (dt instanceof ArrayType) { //// return Arrays.toString((Object []) variant.getValue()); // } else { // byte[] data = // Bindings.getSerializerUnchecked(variant.getBinding()).serialize(variant.getValue()); // m.reset(); // m.update(data, 0, data.length); // return "\"" + new BigInteger(1, m.digest()).toString(16) + "\""; // } } // void fixInstanceOf(TransferableGraph1 graph, ResourceInfo info) { // Identity id = getIdentity(graph, info.resource); // if(id == null) return; // if(id.definition instanceof Internal) { // Identity instanceOf = findExternal(graph, // "http://www.simantics.org/Layer0-1.1/InstanceOf"); // Identity library = findExternal(graph, // "http://www.simantics.org/Layer0-1.1/Library"); // info.statements.add(instanceOf.resource); // info.statements.add(library.resource); // } // } public static String getExternalURI(TransferableGraph1 tg, External ext) { String name = ext.name; if (name.contains(" ")) name = name.replace(" ", "_").replaceAll("@", "_");// name = "\"" + // name + "\""; int parentId = ext.parent; // if(parentId == 0) return ext.name; // else { Identity id = TransferableGraphUtils.getIdentity(tg, parentId); if (id.definition instanceof External) { return getExternalURI(tg, (External) id.definition) + "/" + name; } else if (id.definition instanceof Root) { Root root = (Root) id.definition; return "http:/" + root.name + "/" + name; } else { return null; } // } } public static String getExternalURI(TransferableGraph1 tg, int resource) { Identity id = TransferableGraphUtils.getIdentity(tg, resource); if (id == null) return null; if (id.definition instanceof External) { External ext = (External) id.definition; return getExternalURI(tg, ext); } return null; } String rewritePredicateURI(TransferableGraph1 graph, int predicate) { String uri = getExternalURI(graph, predicate); if (uri == null) { ResourceInfo info = infos.get(predicate); if (info != null) return info.name; return "_"; } for (String ontology : ontologies.keySet()) { if (uri.contains(ontology)) { String key = ontologies.get(ontology); uri = uri.replace(ontology, key); referencedOntologies.add(ontology); } } uri = uri.replace("/", "."); return uri; } static void indent(StringBuilder output, int indent) { for (int i = 0; i < indent; i++) output.append(" "); } String printBlank(TransferableGraph1 graph, String predicateURI2, ResourceInfo info, int indent) { if (info.hasURI) return null; StringBuilder output = new StringBuilder(); String infoName = info.name; if (infoName.startsWith("blank")) { infoName = getBlankRewrite(infoName); } if (ignoreIdentifiers) { if (predicateURI2.contains("L0.identifier")) { // Do nothing } else { indent(output, indent); output.append(predicateURI2 + " " + infoName + "\n"); } } else { indent(output, indent); output.append(predicateURI2 + " " + infoName + "\n"); } if (info.ownedResourcesWithPredicates.isEmpty()) { if (DEBUG) System.out.print("printBlank"); String uri = printURI(graph, info, false, indent, false); if (uri != null) output.append(uri); } // if(info.owner < 0) { // printURI(graph, info, false, indent); // } return output.toString(); } private String getBlankRewrite(String infoName) { String rewrite = blankRewrites.get(infoName); if (rewrite == null) { rewrite = "rblank" + newBlankCounter++; if (DEBUG) System.out.println("rewrote " + infoName + " to " + rewrite); blankRewrites.put(infoName, rewrite); } return rewrite; // return infoName; } static long longStm(int predicate, int object) { return ((predicate & 0xffffffffL) << 32) | (object & 0xffffffffL); } private void addInlineStatement(TransferableGraph1 graph, Map> statements, String predicate, ResourceInfo objectInfo, int indent) { Set objects = statements.get(predicate); if (objects == null) { objects = new TreeSet<>(); statements.put(predicate, objects); } String uri = printURI(graph, objectInfo, false, indent + 1, true); if (uri != null) { // TODO: this is not the right place to remove trailing newline uri = uri.endsWith("\n") ? uri.substring(0, uri.length() - 2) : uri; objects.add(uri); } objectInfo.inlined = true; } void addStatement(Map> statements, String predicate, String object) { // TODO: fix this if (predicate.endsWith("Inverse")) return; Set objects = statements.get(predicate); if (objects == null) { objects = new TreeSet<>(); statements.put(predicate, objects); } objects.add(object); } String printURI(TransferableGraph1 graph, ResourceInfo info, boolean requireURI, int indent, boolean inline) { if (requireURI && !info.hasURI) return null; // Check if this ResourceInfo is already inlined with some other // ResourceInfo if (info.inlined) return null; Map> statements = new TreeMap<>(); Identity consistsOf = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Layer0-1.1/ConsistsOf"); // Identity partOf = TransferableGraphUtils.findExternal(graph, // "http://www.simantics.org/Layer0-1.1/PartOf"); TLongHashSet processed = new TLongHashSet(); if (DEBUG) System.out.println("info.owned.size " + info.owned.size() + info.owned); for (int i = 0; i < info.owned.size(); i += 2) { int predicate = info.owned.get(i); int object = info.owned.get(i + 1); long stmId = longStm(predicate, object); if (DEBUG) System.out.println( " " + stmId + " is already processed as it is owned (" + predicate + " " + object + ")"); processed.add(stmId); } TreeMap predicateURIs = new TreeMap<>(); TIntArrayList rawStatements = TransferableGraphUtils.getStatements(graph, info.resource); if (DEBUG) System.out.println( "rawStatements size for " + info.name + " : " + rawStatements.size() + " " + rawStatements); for (int i = 0; i < rawStatements.size(); i += 2) { int predicate = rawStatements.get(i); int object = rawStatements.get(i + 1); long stmId = longStm(predicate, object); if (!processed.add(stmId)) { if (DEBUG) System.out.println(" " + stmId + " is already processed (" + (predicate & 0xffffffffL) + " " + (object & 0xffffffffL) + ")"); continue; } if (DEBUG) System.out.println(" " + stmId + " is currently being processed (" + (predicate & 0xffffffffL) + " " + (object & 0xffffffffL) + ")"); // if (partOf.resource == rawStatements.get(i)) // continue; if (consistsOf.resource == predicate) { // if (!info.owned.isEmpty() && !info.name.startsWith("blank")) // { if (DEBUG) System.out.println(" is consistsof " + predicate + " (" + consistsOf.resource + ")"); continue; // } else { // // this will be inlined so lets indent // indent++; // } } String predicateURI = rewritePredicateURI(graph, predicate); predicateURIs.put(predicateURI, object); } for (Entry entry : predicateURIs.entrySet()) { String predicateURI = entry.getKey(); int object = entry.getValue(); ResourceInfo objectInfo = infos.get(object); if (objectInfo == null) { String objectURI = rewritePredicateURI(graph, object); if (DEBUG) System.out.println(" adding statement " + predicateURI + " " + objectURI); addStatement(statements, predicateURI, objectURI); } else if (objectInfo.ownedBy.size() == 1 && objectInfo.ownedBy.contains(info)) { // inline printing with _ if (DEBUG) System.out.println(" adding inline statement " + predicateURI + " " + objectInfo.name); addInlineStatement(graph, statements, predicateURI, objectInfo, indent); } else { String objectName = objectInfo.name; if (objectName.startsWith("blank")) { objectName = getBlankRewrite(objectName); } if (DEBUG) System.out.println(" adding statement " + predicateURI + " " + objectName); addStatement(statements, predicateURI, objectName); } } if (DEBUG) System.out.println( "statements size for " + info.name + " : " + statements.size() + " " + statements.keySet()); StringBuilder output = new StringBuilder(); if (indent == 0 || inline) { if ("ROOT".equals(info.name)) { output.append("ROOT="); } else if (info.aliasURI != null) { output.append(info.name + " = <" + info.aliasURI + ">"); } else { String infoName = info.name; if (infoName.startsWith("blank")) { infoName = getBlankRewrite(infoName); } output.append(inline ? "_" : infoName); } Set instanceOfs = statements.get("L0.InstanceOf"); if (instanceOfs != null) { for (String instanceOf : instanceOfs) { output.append(" : " + instanceOf); } } Set subrelationOfs = statements.get("L0.SubrelationOf"); if (subrelationOfs != null) { for (String subrelationOf : subrelationOfs) { output.append(" inherits = statements.get("L0.Inherits"); if (inherits != null) { for (String inherit : inherits) { output.append(" > entry : statements.entrySet()) { String predicate = entry.getKey(); if (ignoreIdentifiers) { if (predicate.equals("L0.identifier")) { continue; } } if ("L0.InstanceOf".equals(predicate)) continue; if ("L0.SubrelationOf".equals(predicate)) continue; if ("L0.Inherits".equals(predicate)) continue; if ("L0.PartOf".equals(predicate)) continue; // predicates can be blank if (predicate.startsWith("blan")) { predicate = getBlankRewrite(predicate); } Set objects = entry.getValue(); indent(output, indent + 1); if (objects.size() == 1) { output.append(predicate + " " + objects.iterator().next() + "\n"); } else { output.append(predicate + "\n"); for (String object : objects) { indent(output, indent + 1); output.append(" " + object + "\n"); } } } TreeMap ownedOrdered = new TreeMap<>(); for (int i = 0; i < info.owned.size(); i += 2) { String predicateURI = rewritePredicateURI(graph, info.owned.get(i)); ownedOrdered.put(predicateURI, info.owned.get(i + 1)); } if (DEBUG) System.out.println(info.name + " : " + ownedOrdered.keySet()); for (Entry entry : ownedOrdered.entrySet()) { String predicateURI = entry.getKey(); int owned = entry.getValue(); ResourceInfo ownedInfo = infos.get(owned); String blank = printBlank(graph, predicateURI, ownedInfo, indent + 1); if (blank != null) { output.append(blank); } } return output.toString(); } void prettyPrint(Path input, Path output) throws Exception { System.out.format("Converting exported shared ontology%n\t" + input.toString() + "%nto bundle-compatible ontology%n\t" + output.toString()); try (InputStream is = new BufferedInputStream(Files.newInputStream(input), 128 * 1024)) { DataInput dis = new DataInputStream(is); org.simantics.databoard.container.DataContainer container = DataContainers.readFile(dis); Binding binding = TransferableGraph1.BINDING; TransferableGraph1 graph = (TransferableGraph1) container.content.getValue(binding); prettyPrint(graph); Files.write(output, this.output.toString().getBytes()); } } static Map knownOntologies = new HashMap<>(); static { knownOntologies.put("http://www.simantics.org/Layer0-1.1", "L0"); knownOntologies.put("http://www.simantics.org/Layer0X-1.1", "L0X"); knownOntologies.put("http://www.simantics.org/Modeling-1.2", "MOD"); knownOntologies.put("http://www.simantics.org/Diagram-2.2", "DIA"); knownOntologies.put("http://www.simantics.org/Structural-1.2", "STR"); knownOntologies.put("http://www.simantics.org/Document-1.2", "DOC"); knownOntologies.put("http://www.simantics.org/Documentation-1.2", "DOCU"); knownOntologies.put("http://www.simantics.org/G2D-1.1", "G2D"); knownOntologies.put("http://www.simantics.org/SelectionView-1.2", "SEL"); knownOntologies.put("http://www.simantics.org/Viewpoint-1.2", "VP"); knownOntologies.put("http://www.simantics.org/Image2-1.2", "IMAGE2"); knownOntologies.put("http://www.simantics.org/GraphFile-0.1", "GRAPHFILE"); knownOntologies.put("http://www.simantics.org/Project-1.2", "PROJECT"); knownOntologies.put("http://www.semantum.fi/Simupedia-1.0", "SIMUPEDIA"); knownOntologies.put("http://www.semantum.fi/SimupediaWorkbench-1.0", "SIMUPEDIA_WORKBENCH"); } void prettyPrint(TransferableGraph1 graph) throws Exception { log("Starting prettyPrint for TransferableGraph with {} resources, {} identities, {} statements and {} values", graph.resourceCount, graph.identities, graph.statements.length, graph.values.length); for (Identity id : graph.identities) { if (id.definition instanceof Internal) { Internal internal = (Internal) id.definition; Identity parent = TransferableGraphUtils.getIdentity(graph, internal.parent); if (parent.definition instanceof External) { log("Resolving internal identity {}", id); String name = "BASE"; ResourceInfo info = new ResourceInfo(true, name, id.resource, -1); info.aliasURI = TransferableGraphUtils.getURI(graph, id.resource); info.newResource = true; orderedInfos.put(name, info); // infos.put(id.resource, info); log(" which parent is external {} and has an aliasURI {}", parent, info.aliasURI); for (Identity child : TransferableGraphUtils.getChildren(graph, id)) { recurseURI(graph, child, name, info.resource); } log(" and has {} children", infos.size()); } } else if (id.definition instanceof External) { External ext = (External) id.definition; // Try to detect shared libraries if (ext.name.contains("@")) { log("Detected an external shared library {}", ext); int index = ext.name.indexOf('@'); String prefix = ext.name.substring(0, index); int index2 = ext.name.indexOf('/', index); String ontology = index2 == -1 ? ext.name : ext.name.substring(0, index2); String uri = TransferableGraphUtils.getURI(graph, id.resource); log(" which was resolved as URI={} and prefix={}", uri, prefix); ontologies.put(uri, prefix); } else if (ext.name.contains("-")) { log("Resolving possible ontology {}", ext); String uri = TransferableGraphUtils.getURI(graph, id.resource); Matcher m = versionExtractPattern.matcher(uri); if (m.matches()) { if (!ontologies.containsKey(uri)) { int index = ext.name.indexOf('-'); String prefix = ext.name.substring(0, index); log(" and it was resolved as URI={} and prefix {}", uri, prefix); ontologies.put(uri, prefix); } } } } } // Discover other resources log("Discovering other resources.."); TIntArrayList todo = new TIntArrayList(); for (ResourceInfo info : orderedInfos.values()) { todo.add(info.resource); // put orderedInfos to infos infos.put(info.resource, info); } while (!todo.isEmpty()) { int resource = todo.removeAt(todo.size() - 1); discoverBlank(graph, resource, todo); } for (ResourceInfo info : infos.valueCollection()) discoverOwners(graph, info); // for(ResourceInfo info : infos.valueCollection()) // fixInstanceOf(graph, info); for (ResourceInfo info : infos.valueCollection()) { // Old implementation // if (info.owner >= 0) { // ResourceInfo ownerInfo = infos.get(info.owner); // System.out.println("originalOwner : " + info.owner + " // originalPredicate: " + info.ownerPredicate); // ownerInfo.owned.add(info.ownerPredicate); // ownerInfo.owned.add(info.resource); // } if (!info.ownedResourcesWithPredicates.isEmpty() && info.ownedResourcesWithPredicates.size() == 1) { info.ownedResourcesWithPredicates.forEachEntry(new TIntIntProcedure() { @Override public boolean execute(int owner, int predicate) { ResourceInfo ownerInfo = infos.get(owner); ownerInfo.owned.add(predicate); ownerInfo.owned.add(info.resource); return false; } }); } } // Resolve inverses from ownedBy list for (ResourceInfo info : infos.valueCollection()) { for (int i = 0; i < info.owned.size(); i += 2) { int object = info.owned.get(i + 1); ResourceInfo inf = infos.get(object); if (inf != null) { info.ownedBy.remove(inf); } } } Identity routeGraphConn = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Diagram-2.2/RouteGraphConnection"); Identity instanceOf = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Layer0-1.1/InstanceOf"); Identity diagramConnetionToConnection = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Modeling-1.2/DiagramConnectionToConnection"); for (ResourceInfo infoo : infos.valueCollection()) { Identity elemTo = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Modeling-1.2/ElementToComponent"); if (elemTo != null) { int elemToComponent = TransferableGraphUtils.getPossibleObject2(graph, infoo.resource, elemTo); if (elemToComponent != TransferableGraphUtils.NOT_FOUND) { Identity component = TransferableGraphUtils.getIdentity(graph, elemToComponent); Identity internal = TransferableGraphUtils.getIdentity(graph, infoo.resource); if (internal.definition instanceof Internal && component.definition instanceof Internal) { Internal iCOmponent = (Internal) component.definition; infoo.name = infoo.name.substring(0, infoo.name.lastIndexOf(".") + 1) + iCOmponent.name; } } } if (instanceOf != null) { int instOf = TransferableGraphUtils.getPossibleObject2(graph, infoo.resource, instanceOf); if (instOf != TransferableGraphUtils.NOT_FOUND && routeGraphConn != null) { if (instOf == routeGraphConn.resource) { // Found routegraphconnection, change name // Lets go to configuration int connection = TransferableGraphUtils.getPossibleObject2(graph, infoo.resource, diagramConnetionToConnection); if (connection != TransferableGraphUtils.NOT_FOUND) { // Gather all inverse statements to construct unique // name List nameParts = new ArrayList<>(); TIntArrayList statements = TransferableGraphUtils.getStatements(graph, connection); for (int i = 0; i < statements.size(); i += 2) { int predicate = statements.get(i); Identity possibleInverse = TransferableGraphUtils.getIdentity(graph, predicate); if (possibleInverse != null) { int inverseRelation = TransferableGraphUtils.NOT_FOUND; int parentId = TransferableGraphUtils.NOT_FOUND; if (possibleInverse.definition instanceof Internal) { Internal iPossibleInverse = (Internal) possibleInverse.definition; if (iPossibleInverse.name.equals("Inverse")) { inverseRelation = TransferableGraphUtils.getPossibleObject2(graph, connection, possibleInverse); parentId = iPossibleInverse.parent; } else { LOGGER.error("THIS UNSUPPORTED for " + infoo + " " + iPossibleInverse); } } else if (possibleInverse.definition instanceof External) { External ePossibleInverse = (External) possibleInverse.definition; if (ePossibleInverse.name.equals("Inverse")) { inverseRelation = TransferableGraphUtils.getPossibleObject2(graph, connection, possibleInverse); parentId = ePossibleInverse.parent; } else { // This is not an inverse // LOGGER.error("THIS UNSUPPORTED // TOO"); } } else { LOGGER.error("UNSUPPORTED for " + infoo + " "); } if (inverseRelation != TransferableGraphUtils.NOT_FOUND) { // Ok found something Identity object = TransferableGraphUtils.getIdentity(graph, inverseRelation); Identity parent = TransferableGraphUtils.getIdentity(graph, parentId); String objectName, parentName; if (object.definition instanceof Internal) { objectName = ((Internal) object.definition).name; } else if (object.definition instanceof External) { objectName = ((External) object.definition).name; } else { LOGGER.error("UNSUPPORTED " + infoo); throw new Error("UNSUPPORTED " + infoo); } if (parent.definition instanceof Internal) { parentName = ((Internal) parent.definition).name; } else if (parent.definition instanceof External) { parentName = ((External) parent.definition).name; } else { LOGGER.error("UNSUPPORTED " + infoo); throw new Error("UNSUPPORTED " + infoo); } String fullName = parentName + "_" + objectName; nameParts.add(fullName); } else { LOGGER.error("THIS IS ALSO UNSupported"); } } else { LOGGER.error("HERE"); } } nameParts.sort((o1, o2) -> o1.compareTo(o2)); String name = ""; for (String namep : nameParts) { name += namep; } infoo.name = infoo.name.substring(0, infoo.name.lastIndexOf(".") + 1) + name; } else { LOGGER.error("Could not find connection for " + infoo + ". Statements of graph below"); LOGGER.error(Arrays.toString(graph.statements)); LOGGER.error("Subject -> Predicate : " + infoo.resource + " -> " + diagramConnetionToConnection.resource); } } } } } for (ResourceInfo info : infos.valueCollection()) { if (info.name.startsWith("blank")) { info.name = "blank" + findHash(graph, info); } } TreeMap order = new TreeMap<>(); for (ResourceInfo info : infos.valueCollection()) order.put(info.name, info); for (ResourceInfo info : order.values()) { if (DEBUG) System.out.print("info "); String uri = printURI(graph, info, true, 0, false); if (uri != null) output.append(uri); } TreeMap rblanks = new TreeMap<>(); for (ResourceInfo info : order.values()) { if (!info.hasURI && info.ownedResourcesWithPredicates.size() != 1) { if (DEBUG) System.out.print("ownedResources "); if (info.name.startsWith("blank")) { // These will be printed later rblanks.put(getBlankRewrite(info.name), info); } else { String uri = printURI(graph, info, false, 0, false); if (uri != null) output.append(uri); } } } // Now print blanks in order for (ResourceInfo info : rblanks.values()) { if (!info.hasURI && info.ownedResourcesWithPredicates.size() != 1) { if (DEBUG) System.out.print("ownedResources "); String uri = printURI(graph, info, false, 0, false); if (uri != null) output.append(uri); } } // for(ResourceInfo info : order.values()) // if(!info.hasURI && info.owner < 0) // printURI(graph, info, false, 0); StringBuilder refs = new StringBuilder(); for (String ontology : referencedOntologies) { String key = ontologies.get(ontology); refs.append(key + " = <" + ontology + ">\n"); } if (!referencedOntologies.isEmpty()) refs.append("\n"); output.insert(0, refs.toString()); } private String calculateHash(TransferableGraph1 graph, ResourceInfo info) { StringBuilder statementHash = new StringBuilder(); TreeSet parts = new TreeSet<>(); for (int i = 0; i < info.owned.size(); i += 2) { int predicate = info.owned.get(i); int object = info.owned.get(i + 1); // Lets resolve a unique name for this based on the statements this // one has String predicatee = rewritePredicateURI(graph, predicate); ResourceInfo objInfo = infos.get(object); parts.add(predicatee + "->" + objInfo.name + ";;;"); } // Remove this from the list List filtered = info.ownedBy.stream().filter(ri -> !ri.name.startsWith("blank")) .collect(Collectors.toList()); for (ResourceInfo ownedBy : filtered) { parts.add(ownedBy.name); } // check parent ResourceInfo parentInfo = infos.get(info.parent); if (parentInfo != null && !parentInfo.name.startsWith("blank")) { parts.add("parent" + parentInfo.name); } else { // LOGGER.error("This should not happen"); } for (String s : parts) { statementHash.append(s); } String hash = makeHash(statementHash.toString().getBytes()); if (DEBUG) System.out.println(statementHash + " -> " + hash); return hash; } private String findHash(TransferableGraph1 graph, ResourceInfo info) { if (info.name.startsWith("blank")) { String hash = hashes.get(info.name); if (hash == null) { String oldName = info.name; if (DEBUG) System.out.print("calculating hash for " + oldName + " "); hash = calculateHash(graph, info); if (hashes.put(oldName, hash) != null) { System.err.println("!!!!A clash occured for " + info + " with hash " + hash); } } return hash; } else { return info.name; } } private THashMap hashes = new THashMap<>(); public static String print(TransferableGraph1 tg, boolean ignoreIdentifiers) throws Exception { StringBuilder b = new StringBuilder(); new PrettyPrintTG(b, ignoreIdentifiers).prettyPrint(tg); return b.toString(); } public static void main(String[] args) throws Exception { if (args.length < 1) { System.out.println("Required arguments: []"); } else if (args.length < 2) { Path input = Paths.get(args[0]); Path output = input.getParent().resolve(input.getName(input.getNameCount() - 1) + ".fixed"); new PrettyPrintTG().prettyPrint(input, output); } else { new PrettyPrintTG().prettyPrint(Paths.get(args[0]), Paths.get(args[1])); } } private static void log(String string, Object... args) { if (LOGGER.isDebugEnabled() && DEBUG) LOGGER.debug(string, args); } }