]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graph.compiler/src/org/simantics/graph/compiler/GraphUnparser.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.graph.compiler / src / org / simantics / graph / compiler / GraphUnparser.java
1 package org.simantics.graph.compiler;
2
3 import gnu.trove.list.array.TIntArrayList;
4 import gnu.trove.map.hash.TIntIntHashMap;
5 import gnu.trove.map.hash.TIntObjectHashMap;
6 import gnu.trove.set.hash.TIntHashSet;
7
8 import java.util.ArrayList;
9 import java.util.Collection;
10
11 import org.simantics.databoard.Bindings;
12 import org.simantics.databoard.binding.Binding;
13 import org.simantics.databoard.parser.unparsing.DataTypePrinter;
14 import org.simantics.databoard.type.Datatype;
15 import org.simantics.graph.query.CompositeGraph;
16 import org.simantics.graph.query.IGraph;
17 import org.simantics.graph.query.Path;
18 import org.simantics.graph.query.Paths;
19 import org.simantics.graph.query.Res;
20 import org.simantics.graph.query.TransferableGraphConversion;
21 import org.simantics.graph.query.UriUtils;
22 import org.simantics.graph.representation.External;
23 import org.simantics.graph.representation.Identity;
24 import org.simantics.graph.representation.Internal;
25 import org.simantics.graph.representation.LocalStatement;
26 import org.simantics.graph.representation.Optional;
27 import org.simantics.graph.representation.TransferableGraph1;
28 import org.simantics.graph.representation.Value;
29 import org.simantics.graph.store.GraphStore;
30 import org.simantics.graph.store.IStatementProcedure;
31
32 public class GraphUnparser {
33         IGraph graph;
34         GraphStore store;
35         StringBuilder b = new StringBuilder();  
36         
37         GraphUnparser(IGraph graph, GraphStore store) {
38                 this.graph = graph;
39                 this.store = store;
40         }
41         
42         ArrayList<Identity> uriRes = new ArrayList<Identity>();
43         TIntHashSet blankResources = new TIntHashSet(); 
44         TIntObjectHashMap<String> refNames = new TIntObjectHashMap<String>();
45         TIntHashSet parentNameUsed = new TIntHashSet();
46         TIntObjectHashMap<String> parentNames = new TIntObjectHashMap<String>();
47         
48         TIntHashSet activeResources = new TIntHashSet(); // Resources that have statements      
49         TIntObjectHashMap<ArrayList<LocalStatement>> localStatements = 
50                 new TIntObjectHashMap<ArrayList<LocalStatement>>();
51         TIntObjectHashMap<String> uris = new TIntObjectHashMap<String>();               
52         TIntObjectHashMap<String> literals = new TIntObjectHashMap<String>();
53         
54         int SimanticsDomain;
55         int Layer0;
56         int Inherits;
57         int InstanceOf;
58         int DataType;
59         int SubrelationOf;
60         
61         void handleIdentity(Identity id) {
62                 int resource = id.resource;
63                 int parent;
64                 String name;
65                 if(id.definition instanceof External) {
66                         External def = (External)id.definition;
67                         parent = def.parent;
68                         name = def.name;
69                 }
70                 else if(id.definition instanceof Internal) {
71                         Internal def = (Internal)id.definition;
72                         parent = def.parent;
73                         name = def.name;
74                 }
75                 else if(id.definition instanceof Optional) {
76                         Optional def = (Optional)id.definition;
77                         parent = def.parent;
78                         name = def.name;
79                 }
80                 else
81                         return;
82                 
83                 uris.put(id.resource, uris.get(parent) + "/" + name);           
84                 if(isIdentifier(name)) {
85                         if(parentNames.containsKey(parent)) {
86                                 refNames.put(resource, parentNames.get(parent) + "." + name);
87                                 parentNameUsed.add(parent);
88                         }
89                         else
90                                 refNames.put(resource, "<" + uris.get(resource) + ">");
91                         parentNames.put(resource, name);
92                 }
93                 else {
94                         refNames.put(resource, "<" + uris.get(resource) + ">");
95                         String[] parts = name.split("-");
96                         if(isIdentifier(parts[0]))
97                                 parentNames.put(resource, parts[0]);
98                 }
99                 if(activeResources.remove(resource)) {  
100                         uriRes.add(id);         
101                 }
102                 if(parent == 0) {
103                         if(name.equals("www.simantics.org"))
104                                 SimanticsDomain = resource;
105                 }
106                 else if(parent == SimanticsDomain) {
107                         if(name.equals("Layer0-1.0")) {
108                                 Layer0 = resource;
109                                 parentNames.put(resource, "L0");
110                         }
111                 }
112                 else if(parent == Layer0) {
113                         if(name.equals("InstanceOf"))
114                                 InstanceOf = resource;
115                         else if(name.equals("Inherits"))
116                                 Inherits = resource;
117                         else if(name.equals("SubrelationOf"))
118                                 SubrelationOf = resource;
119                         else if(name.equals("DataType"))
120                                 DataType = resource;
121                 }
122         }
123         
124         void run() {
125                 final TIntIntHashMap refCount = new TIntIntHashMap(); 
126                 store.statements.forStatements(new IStatementProcedure() {                      
127                         @Override
128                         public void execute(int s, int p, int o) {
129                                 ArrayList<LocalStatement> localStatement;
130                                 if(activeResources.add(s)) {
131                                         localStatement = new ArrayList<LocalStatement>(2);
132                                         localStatements.put(s, localStatement);
133                                 }
134                                 else
135                                         localStatement = localStatements.get(s);
136                                 refCount.adjustOrPutValue(p, 1, 1);
137                                 refCount.adjustOrPutValue(o, 1, 1);
138                                 localStatement.add(new LocalStatement(p, o));   
139                         }
140                 });     
141                 
142                 Paths paths = new Paths("1.0");
143                                 
144                 // Uris
145                 uris.put(0, "http:/");
146                 for(Identity id : store.identities.toArray())
147                         handleIdentity(id);
148                 /*Collections.sort(uriRes, new Comparator<Identity>() {
149                         @Override
150                         public int compare(Identity arg0, Identity arg1) {
151                                 int diff = arg0.parent - arg1.parent;
152                                 if(diff != 0)
153                                         return diff;
154                                 return arg0.name.compareTo(arg1.name);                          
155                         }                       
156                 });*/
157                 
158                 // Literals             
159                 Path dataTypeRes = UriUtils.uriToPath("http://www.simantics.org/Layer0-1.0/DataType");
160                 for(Value value : store.values.toArray()) {
161                         if(graph != null) {
162                                 Res res = store.idToRes(value.resource);
163                                 if(graph.rawGetObjects(res, paths.InstanceOf).contains(dataTypeRes)) {
164                                         Binding b = Bindings.getBindingUnchecked(Datatype.class);
165                                         try {
166                                                 Datatype dt = (Datatype)value.value.getValue(b);
167                                                 literals.put(value.resource, "@" + DataTypePrinter.toString(dt, false));
168                                                 continue;
169                                         } catch (Exception e) {
170                                                 // TODO Auto-generated catch block
171                                                 e.printStackTrace();
172                                         }                                       
173                                 }
174                                 else {
175                                         Datatype dt = graph.getDatatype(res);
176                                         if(dt != null) {
177                                                 Binding b = Bindings.getBinding(dt);
178                                                 try {
179                                                         Object obj = value.value.getValue(b);                           
180                                                         literals.put(value.resource, b.toString(obj));
181                                                         continue;
182                                                 } catch (Exception e) {
183                                                         // TODO Auto-generated catch block
184                                                         e.printStackTrace();
185                                                 }                                       
186                                         }
187                                         else {
188                                                 literals.put(value.resource, "<" + value.value + ">");
189                                         }
190                                                 
191                                 }
192                         }
193                 }       
194                 
195                 // Blank resources
196                 for(int id : activeResources.toArray())
197                         if(refCount.get(id) == 1) {
198                                 activeResources.remove(id);
199                                 blankResources.add(id);
200                         }       
201                 
202                 int tempId = 0;
203                 TIntArrayList otherResources = new TIntArrayList(); 
204                 for(int id : activeResources.toArray()) {
205                         refNames.put(id, "r" + (++tempId));
206                         otherResources.add(id);
207                 }
208                 
209                 for(Identity uriRe : uriRes)
210                         describeResource(0, uriRe.resource);
211                 for(int id : otherResources.toArray())
212                         describeResource(0, id);
213         }
214         
215         private void indent(int indentation) {
216                 for(int i=0;i<indentation;++i)
217                         b.append("    ");
218         }
219         
220         private void describeResource(int indentation, int resource) {
221                 if(parentNameUsed.contains(resource)) {
222                         b.append(parentNames.get(resource));
223                         b.append(" = ");
224                 }               
225                 if(literals.containsKey(resource)) {                    
226                         if(refNames.get(resource) != null) {
227                                 refResource(resource);                  
228                                 b.append(" = ");
229                         }
230                         b.append(literals.get(resource));
231                 }
232                 else
233                         refResource(resource);
234                 ArrayList<LocalStatement> others = new ArrayList<LocalStatement>();
235                 for(LocalStatement stat : localStatements.get(resource)) {
236                         if(!blankResources.contains(stat.object) &&
237                                         (stat.predicate == InstanceOf ||
238                                                         stat.predicate == Inherits ||
239                                                         stat.predicate == SubrelationOf)) {
240                                 b.append(' ');
241                                 refPredicate(stat.predicate);
242                                 b.append(' ');
243                                 refResource(stat.object);
244                         }
245                         else
246                                 others.add(stat);
247                 }
248                 b.append('\n');
249                 
250                 for(LocalStatement stat : others) {
251                         indent(indentation+1);
252                         refPredicate(stat.predicate);
253                         b.append(" ");
254                         describeObject(indentation+1, stat.object);
255                 }
256         }
257         
258         private void describeObject(int indentation, int resource) {
259                 if(blankResources.contains(resource))
260                         describeResource(indentation, resource);
261                 else {
262                         refResource(resource);
263                         b.append('\n');
264                 }
265         }
266         
267         private void refPredicate(int resource) {
268                 if(resource == InstanceOf)
269                         b.append(":");
270                 else if(resource == Inherits)
271                         b.append("<T");
272                 else if(resource == SubrelationOf)
273                         b.append("<R");
274                 else
275                         refResource(resource);
276         }
277         
278         private void refResource(int resource) {
279                 String name = refNames.get(resource);
280                 if(name == null)
281                         b.append("_");
282                 else
283                         b.append(name);
284         }
285         
286         @Override
287         public String toString() {
288                 return b.toString();
289         }
290         
291         static boolean isIdentifier(String name) {
292                 if(name.isEmpty())
293                         return false;
294                 if(!Character.isJavaIdentifierStart(name.charAt(0)))
295                         return false;
296                 for(int i=1;i<name.length();++i)
297                         if(!Character.isJavaIdentifierPart(name.charAt(i)))
298                                 return false;
299                 return true;
300         }
301         
302         public static String unparse(Paths paths, TransferableGraph1 tg, Collection<TransferableGraph1> dependencies) {
303                 CompositeGraph cg = TransferableGraphConversion.convert(paths, dependencies);                   
304                 GraphStore store = TransferableGraphConversion.convert(tg);
305                 cg.addFragment(store);  
306                 
307                 GraphUnparser gu = new GraphUnparser(cg, store);
308                 gu.run();
309                 
310                 return gu.toString();
311         }
312 }