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.nio.file.Files;
8 import java.nio.file.Path;
9 import java.nio.file.Paths;
10 import java.util.ArrayList;
11 import java.util.HashMap;
12 import java.util.List;
14 import java.util.TreeMap;
16 import org.simantics.databoard.binding.Binding;
17 import org.simantics.databoard.binding.mutable.Variant;
18 import org.simantics.databoard.container.DataContainers;
19 import org.simantics.databoard.type.Datatype;
21 import gnu.trove.list.array.TIntArrayList;
22 import gnu.trove.map.hash.TIntObjectHashMap;
23 import gnu.trove.set.hash.TLongHashSet;
26 * @author Antti Villberg
29 public class PrettyPrintTG extends TransferableGraphUtils {
33 final StringBuilder output;
35 static class ResourceInfo {
39 boolean newResource = false;
41 int ownerPredicate = 0;
42 String aliasURI = null;
43 TIntArrayList owned = new TIntArrayList();
44 TIntArrayList statements = new TIntArrayList();
45 public ResourceInfo(boolean hasURI, String name, int resource) {
48 this.resource = resource;
52 public PrettyPrintTG(StringBuilder b) {
56 public PrettyPrintTG() {
57 this(new StringBuilder());
60 TIntObjectHashMap<ResourceInfo> infos = new TIntObjectHashMap<>();
62 String tgNodeName(String name) {
63 if(name.contains(" ")) return "\"" + name + "\"";
67 ResourceInfo recurseURI(TransferableGraph1 graph, Identity parent, String parentName) {
68 String name = parentName + "." + tgNodeName(getName(parent));
69 ResourceInfo info = new ResourceInfo(true, name, parent.resource);
70 infos.put(parent.resource, info);
71 for(Identity child : getChildren(graph, parent)) {
72 recurseURI(graph, child, name);
77 void discoverBlank(TransferableGraph1 graph, int resource, TIntArrayList todo) {
78 TIntArrayList statements = getStatements(graph, resource);
79 for(int i=0;i<statements.size();i+=2) {
80 int object = statements.get(i+1);
81 Identity objectId = getIdentity(graph, object);
82 if(objectId != null) {
83 if(objectId.definition instanceof External) continue;
85 Value value = TransferableGraphUtils.findValue(graph, object);
87 infos.put(object, new ResourceInfo(false, printValue(value), object));
91 ResourceInfo existing = infos.get(object);
92 if(existing == null) {
93 existing = new ResourceInfo(false, "blank" + blankCounter++, object);
94 infos.put(object, existing);
100 void discoverOwners(TransferableGraph1 graph, ResourceInfo info) {
101 int resource = info.resource;
102 TIntArrayList statements = getStatements(graph, resource);
103 for(int i=0;i<statements.size();i+=2) {
104 int predicate = statements.get(i);
105 int object = statements.get(i+1);
106 ResourceInfo existing = infos.get(object);
107 if(existing == null) continue;
108 if(existing.owner == 0) {
109 existing.owner = resource;
110 existing.ownerPredicate = predicate;
111 //System.err.println("First owner " + info.name + " => " + predicateURI + " " + existing.name);
114 //System.err.println("Multiple owners " + info.name + " => " + predicateURI + " " + existing.name);
117 info.statements = statements;
120 String printValue(Value value) {
121 Variant variant = value.value;
122 Datatype dt = variant.getBinding().type();
123 return "\"" + variant.getValue() + "\"";
126 void fixInstanceOf(TransferableGraph1 graph, ResourceInfo info) {
127 Identity id = getIdentity(graph, info.resource);
128 if(id == null) return;
129 if(id.definition instanceof Internal) {
130 Identity instanceOf = findExternal(graph, "http://www.simantics.org/Layer0-1.1/InstanceOf");
131 Identity library = findExternal(graph, "http://www.simantics.org/Layer0-1.1/Library");
132 info.statements.add(instanceOf.resource);
133 info.statements.add(library.resource);
137 public static String getExternalURI(TransferableGraph1 tg, External ext) {
138 String name = ext.name;
139 if(name.contains(" ")) name = name.replace(" ", "_").replaceAll("@", "_");//name = "\"" + name + "\"";
140 int parentId = ext.parent;
141 //if(parentId == 0) return ext.name;
143 Identity id = getIdentity(tg, parentId);
144 if(id.definition instanceof External) {
145 return getExternalURI(tg, (External)id.definition) + "/" + name;
146 } else if(id.definition instanceof Root) {
147 Root root = (Root)id.definition;
148 return "http:/" + root.name + "/" + name;
155 public static String getExternalURI(TransferableGraph1 tg, int resource) {
156 Identity id = getIdentity(tg, resource);
157 if(id == null) return null;
158 if(id.definition instanceof External) {
159 External ext = (External)id.definition;
160 return getExternalURI(tg, ext);
165 String rewritePredicateURI(TransferableGraph1 graph, int predicate) {
166 String uri = getExternalURI(graph, predicate);
167 if(uri == null) return null;
168 uri = uri.replace("http://www.simantics.org/Modeling-1.2", "MOD");
169 uri = uri.replace("http://www.simantics.org/Layer0-1.1", "L0");
170 uri = uri.replace("http://www.simantics.org/Layer0X-1.1", "L0X");
171 uri = uri.replace("http://www.simantics.org/Diagram-2.2", "DIA");
172 uri = uri.replace("http://www.simantics.org/Structural-1.2", "STR");
173 uri = uri.replace("http://www.simantics.org/Documentation-1.2", "DOCU");
174 uri = uri.replace("http://www.simantics.org/Document-1.2", "DOC");
175 uri = uri.replace("http://www.simantics.org/G2D-1.1", "G2D");
176 uri = uri.replace("http://www.simantics.org/Image2-1.2", "IMAGE2");
177 uri = uri.replace("http://www.simantics.org/SelectionView-1.2", "SEL");
178 uri = uri.replace("http://www.simantics.org/Viewpoint-1.2", "VP");
179 uri = uri.replace("http://www.simantics.org/GraphFile-0.1", "GRAPHFILE");
180 uri = uri.replace("http://www.semantum.fi/Simupedia-1.0", "SIMUPEDIA");
181 uri = uri.replace("http://www.semantum.fi/SimupediaWorkbench-1.0", "SIMUPEDIA_WB");
182 uri = uri.replace("http://www.apros.fi/OperationUI-6.6", "APROS_OPER");
183 uri = uri.replace("http://semantum.fi/SimupediaStandardLibrary@1.3-trunk", "SIMUPEDIA_STD");
184 uri = uri.replace("/", ".");
188 void printBlank(TransferableGraph1 graph, String predicateURI2, ResourceInfo info) {
190 if(info.hasURI) return;
191 output.append(" " + predicateURI2 + " " + info.name + "\n");
193 Value value = findValue(graph, info.resource);
198 // for(int i=0;i<info.owned.size();i+=2) {
199 // String predicateURI = rewritePredicateURI(graph, info.owned.get(i));
200 // ResourceInfo ownedInfo = infos.get(info.owned.get(i+1));
201 // if(ownedInfo == null) {
202 // System.err.println("null owned");
205 // printBlank(graph, predicateURI, ownedInfo);
210 long longStm(int predicate, int object) {
211 return (predicate<<32) | (object & 0xffffffffL);
214 void addStatement(Map<String,List<String>> statements, String predicate, String object) {
215 List<String> objects = statements.get(predicate);
216 if(objects == null) {
217 objects = new ArrayList<String>();
218 statements.put(predicate, objects);
223 void printURI(TransferableGraph1 graph, ResourceInfo info) {
225 if(!info.hasURI) return;
227 Map<String,List<String>> statements = new HashMap<>();
228 Identity consistsOf = findExternal(graph, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
229 TLongHashSet processed = new TLongHashSet();
230 for(int i=0;i<info.owned.size();i+=2) {
231 String predicateURI = rewritePredicateURI(graph, info.owned.get(i));
232 ResourceInfo ownedInfo = infos.get(info.owned.get(i+1));
233 if(ownedInfo == null) {
234 System.err.println("null owned");
237 long stmId = longStm(info.owned.get(i), info.owned.get(i+1));
238 processed.add(stmId);
239 printBlank(graph, predicateURI, ownedInfo);
241 for(int i=0;i<info.statements.size();i+=2) {
242 long stmId = longStm(info.statements.get(i), info.statements.get(i+1));
243 if(processed.contains(stmId)) continue;
244 if(consistsOf.resource == info.statements.get(i)) continue;
245 String predicateURI = rewritePredicateURI(graph, info.statements.get(i));
246 ResourceInfo objectInfo = infos.get(info.statements.get(i+1));
247 if(objectInfo == null) {
248 String objectURI = rewritePredicateURI(graph, info.statements.get(i+1));
249 //output.append(" " + predicateURI + " " + objectURI + "\n");
250 addStatement(statements, predicateURI, objectURI);
252 //output.append(" " + predicateURI + " " + objectInfo.name + "\n");
253 addStatement(statements, predicateURI, objectInfo.name);
257 if("ROOT".equals(info.name)) {
258 output.append("ROOT=<http:/>");
259 } else if (info.aliasURI != null) {
260 output.append(info.name + " = <" + info.aliasURI + ">");
262 output.append(info.name);
265 List<String> instanceOfs = statements.get("L0.InstanceOf");
266 if(instanceOfs != null) {
267 for(String instanceOf : instanceOfs) {
268 output.append(" : " + instanceOf);
272 List<String> subrelationOfs = statements.get("L0.SubrelationOf");
273 if(subrelationOfs != null) {
274 for(String subrelationOf : subrelationOfs) {
275 output.append(" <R " + subrelationOf);
279 List<String> inherits = statements.get("L0.Inherits");
280 if(inherits != null) {
281 for(String inherit : inherits) {
282 output.append(" <T " + inherit);
289 output.append(" @L0.new\n");
291 for(Map.Entry<String, List<String>> entry : statements.entrySet()) {
292 String predicate = entry.getKey();
293 if("L0.InstanceOf".equals(predicate)) continue;
294 if("L0.SubrelationOf".equals(predicate)) continue;
295 if("L0.Inherits".equals(predicate)) continue;
296 List<String> objects = entry.getValue();
297 if(objects.size() == 1) {
298 output.append(" " + predicate + " " + objects.iterator().next() + "\n");
300 output.append(" " + predicate + "\n");
301 for(String object : objects) {
302 output.append(" " + object + "\n");
309 void prettyPrint(Path input, Path output) throws Exception {
311 System.out.format("Converting exported shared ontology%n\t" + input.toString() + "%nto bundle-compatible ontology%n\t" + output.toString());
312 try (InputStream is = new BufferedInputStream(Files.newInputStream(input), 128*1024)) {
314 DataInput dis = new DataInputStream(is);
315 org.simantics.databoard.container.DataContainer container =
316 DataContainers.readFile(dis);
317 Binding binding = TransferableGraph1.BINDING;
318 TransferableGraph1 graph = (TransferableGraph1)container.content.getValue(binding);
320 Files.write(output, this.output.toString().getBytes());
326 void prettyPrint(TransferableGraph1 graph) {
328 // Discover resources with URI
329 // for(Identity id : TransferableGraphUtils.getRoots(graph)) {
330 // String name = "ROOT";
331 // ResourceInfo info = new ResourceInfo(true, name, id.resource);
332 // infos.put(id.resource, info);
333 // for(Identity child : getChildren(graph, id)) {
334 // ResourceInfo childInfo = recurseURI(graph, child, name);
335 // childInfo.newResource = true;
338 for(Identity id : graph.identities) {
339 if(id.definition instanceof Internal) {
340 Internal internal = (Internal)id.definition;
341 Identity parent = TransferableGraphUtils.getIdentity(graph, internal.parent);
342 if(parent.definition instanceof External) {
343 String name = "BASE";
344 ResourceInfo info = new ResourceInfo(true, name, id.resource);
345 info.aliasURI = TransferableGraphUtils.getURI(graph, id.resource);
346 info.newResource = true;
347 infos.put(id.resource, info);
348 for(Identity child : getChildren(graph, id)) {
349 recurseURI(graph, child, name);
354 // Discover other resources
355 TIntArrayList todo = new TIntArrayList();
356 for(ResourceInfo info : infos.valueCollection())
357 todo.add(info.resource);
358 while(!todo.isEmpty()) {
359 int resource = todo.removeAt(todo.size()-1);
360 discoverBlank(graph, resource, todo);
362 for(ResourceInfo info : infos.valueCollection())
363 discoverOwners(graph, info);
364 for(ResourceInfo info : infos.valueCollection())
365 fixInstanceOf(graph, info);
366 for(ResourceInfo info : infos.valueCollection())
368 ResourceInfo ownerInfo = infos.get(info.owner);
369 ownerInfo.owned.add(info.ownerPredicate);
370 ownerInfo.owned.add(info.resource);
371 } else if (info.owner == 0) {
372 //System.err.println("faf1");
373 } else if (info.owner == -1) {
374 //System.err.println("faf2");
377 TreeMap<String,ResourceInfo> order = new TreeMap<>();
378 for(ResourceInfo info : infos.valueCollection())
379 order.put(info.name, info);
381 this.output.append("MOD = <http://www.simantics.org/Modeling-1.2>\n");
382 this.output.append("L0 = <http://www.simantics.org/Layer0-1.1>\n");
383 this.output.append("L0X = <http://www.simantics.org/Layer0X-1.1>\n");
384 this.output.append("DIA = <http://www.simantics.org/Diagram-2.2>\n");
385 this.output.append("STR = <http://www.simantics.org/Structural-1.2>\n");
386 this.output.append("DOCU = <http://www.simantics.org/Documentation-1.2>\n");
387 this.output.append("DOC = <http://www.simantics.org/Document-1.2>\n");
388 this.output.append("G2D = <http://www.simantics.org/G2D-1.1>\n");
389 this.output.append("SEL = <http://www.simantics.org/SelectionView-1.2>\n");
390 this.output.append("VP = <http://www.simantics.org.Viewpoint-1.2>\n");
391 this.output.append("IMAGE2 = <http://www.simantics.org/Image2-1.2>\n");
392 this.output.append("GRAPHFILE = <http://www.simantics.org/GraphFile-0.1>\n");
393 this.output.append("APROS_OPER = <http://www.apros.fi/OperationUI-6.6>\n");
394 this.output.append("SIMUPEDIA = <http://www.semantum.fi/Simupedia-1.0>\n");
395 this.output.append("SIMUPEDIA_WB = <http://www.semantum.fi/SimupediaWorkbench-1.0>\n");
396 this.output.append("SIMUPEDIA_STD = <http://semantum.fi/SimupediaStandardLibrary@1.3-trunk>\n");
398 for(ResourceInfo info : order.values())
399 printURI(graph, info);
403 public static String print(TransferableGraph1 tg) {
404 StringBuilder b = new StringBuilder();
405 new PrettyPrintTG(b).prettyPrint(tg);
409 public static void main(String[] args) throws Exception {
410 if (args.length < 1) {
411 System.out.println("Required arguments: <input .sharedOntology file> [<output .tg file>]");
412 } else if (args.length < 2) {
413 Path input = Paths.get(args[0]);
414 Path output = input.getParent().resolve(input.getName(input.getNameCount()-1) + ".fixed");
415 new PrettyPrintTG().prettyPrint(input, output);
417 new PrettyPrintTG().prettyPrint(Paths.get(args[0]), Paths.get(args[1]));