Make prettyPrintTG available via SCL from Simantics/DB-module
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / refactoring / GraphRefactoringUtils.java
1 package org.simantics.graph.refactoring;
2
3 import java.util.Arrays;
4
5 import org.simantics.databoard.util.URIStringUtils;
6 import org.simantics.graph.query.Path;
7 import org.simantics.graph.query.PathChild;
8 import org.simantics.graph.query.TransferableGraphConversion;
9 import org.simantics.graph.query.UriUtils;
10 import org.simantics.graph.refactoring.MappingSpecification.MappingRule;
11 import org.simantics.graph.representation.External;
12 import org.simantics.graph.representation.Identity;
13 import org.simantics.graph.representation.Internal;
14 import org.simantics.graph.representation.Root;
15 import org.simantics.graph.representation.TransferableGraph1;
16 import org.simantics.graph.representation.TransferableGraphUtils;
17 import org.simantics.graph.store.GraphStore;
18 import org.simantics.graph.store.IdentityStore;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 import gnu.trove.set.hash.TIntHashSet;
23
24 public class GraphRefactoringUtils {
25     private static final Logger LOGGER = LoggerFactory.getLogger(GraphRefactoringUtils.class);
26     /**
27      * Moves an external resource. Returns true if did something.
28      * @param parentsAffected 
29      */
30     public static boolean moveExternal(TransferableGraph1 tg, IdentityStore ids, Path from, PathChild to, TIntHashSet parentsAffected) throws GraphRefactoringException {
31         // Find from id
32         int fromId = ids.pathToId(from);
33         if(fromId < 0)
34             return false;
35         if(ids.isNewResource(fromId))
36             throw new GraphRefactoringException("Cannot move internal resource " + from + ".");
37
38         // Remove old identity
39         int parentId = ids.removeIdentity(fromId);
40         if(parentId >= 0)
41             parentsAffected.add(parentId);
42
43         // Find parent id
44         int toParentId = ids.createPathToId(to.parent);
45         if(ids.hasChild(toParentId, to.name)) {
46             LOGGER.info("refactor statements from " + from + " to " + to);
47             //throw new GraphRefactoringException("External reference to " + to + " already exists.");
48                 int toId = ids.pathToId(to);
49             int[] statements = tg.statements;
50             for(int i=0;i<tg.statements.length;++i) {
51                 if(statements[i] == fromId) statements[i] = toId;
52             }
53             return true;
54         }
55         
56         // Set new identity
57         ids.setIdentity(fromId, toParentId, to.name);
58         return true;
59     }
60     
61     public static void refactor(TransferableGraph1 tg, IdentityStore ids, MappingSpecification spec, TIntHashSet parentsAffected) throws GraphRefactoringException {
62         for(MappingRule rule : spec.getRules()) {
63             if(!(rule.to instanceof PathChild))
64                 throw new GraphRefactoringException("Invalid target URI " + rule.to);
65             if(!moveExternal(tg, ids, rule.from, (PathChild)rule.to, parentsAffected))
66                 LOGGER.warn("Didn't find " + rule.from);
67         }
68     }
69
70     public static boolean fixIncorrectRoot(Identity[] ids) {
71         for(int i=0;i<ids.length;++i) {
72             Identity id = ids[i];
73             if(id.definition instanceof External) {
74                 External ext = (External)id.definition;
75                 if(ext.parent == -1 && (ext.name.equals("http:/") || ext.name.equals(""))) {
76                     id.definition = new Root("", "");
77                     return true;
78                 }
79             }
80         }
81         return false;
82     }
83
84     public static void fixOntologyExport(TransferableGraph1 tg) {
85         
86         fixIncorrectRoot(tg.identities);
87         fixOntologyRoot(tg, true);
88         
89     }
90     
91     private static Identity recursePath(TransferableGraph1 tg, String path) {
92         
93         Identity extId = TransferableGraphUtils.findExternal(tg, path);
94         if(extId != null) return extId;
95         if("http://".equals(path)) return TransferableGraphUtils.findRootWithName(tg, "");
96         String[] parts = URIStringUtils.splitURI(path);
97         Identity parentId = recursePath(tg, parts[0]);
98         tg.identities = Arrays.copyOf(tg.identities, tg.identities.length+1);
99         Identity childIdentity = new Identity(tg.resourceCount++, new External(parentId.resource, parts[1]));
100                 tg.identities[tg.identities.length-1] = childIdentity;
101                 return childIdentity;
102         
103     }
104     
105     public static void fixOntologyRoot(TransferableGraph1 tg, boolean tryToFix) {
106
107         Identity[] ids = tg.identities;
108         for(int i=0;i<ids.length;++i) {
109             Identity id = ids[i];
110             if(id.definition instanceof Root) {
111                 Root ext = (Root)id.definition;
112                 if(ext.name.startsWith("http://")) {
113                         
114                         String[] parts = URIStringUtils.splitURI(ext.name);
115                         Identity path = recursePath(tg, parts[0]);
116                         id.definition = new Internal(path.resource, parts[1]);
117                         
118                         GraphStore store = TransferableGraphConversion.convert(tg);
119                         int rootId = store.identities.createPathToId(UriUtils.uriToPath(ext.name));
120                         propagateNewMarks(store.identities, rootId);
121
122                         TransferableGraph1 tgNew = TransferableGraphConversion.convert(store);
123                                 
124                         tg.resourceCount = tgNew.resourceCount;
125                         tg.identities = tgNew.identities;
126                         tg.values = tgNew.values;
127                         tg.statements = tgNew.statements;
128                                 
129                         return;
130                         
131                 } else if (ext.type.startsWith("http://")) {
132                     String first = "http://Projects/Development Project";
133                     Identity path = recursePath(tg, first);
134                     id.definition = new Internal(path.resource, ext.name);
135                     
136                     GraphStore store = TransferableGraphConversion.convert(tg);
137                     int rootId = store.identities.createPathToId(UriUtils.uriToPath(first + "/" + ext.name));
138                     propagateNewMarks(store.identities, rootId);
139
140                     TransferableGraph1 tgNew = TransferableGraphConversion.convert(store);
141                         
142                     tg.resourceCount = tgNew.resourceCount;
143                     tg.identities = tgNew.identities;
144                     tg.values = tgNew.values;
145                     tg.statements = tgNew.statements;
146
147                 }
148             }
149         }
150         
151     }
152     
153         private static void propagateNewMarks(IdentityStore identities, int resource) {
154                 if(identities.markNew(resource)) {
155                         for(int child : identities.getChildren(resource))
156                                 propagateNewMarks(identities, child);
157                 }
158         }
159
160     public static void unfixIncorrectRoot(Identity[] ids) {
161         for(int i=0;i<ids.length;++i) {
162             Identity id = ids[i];
163             if(id.definition instanceof Root) {
164                 Root root = (Root)id.definition;
165                 if(root.name.equals("") && root.type.equals("")) {
166                     id.definition = new External(-1, "http:/");
167                     return;
168                 }
169             }
170         }
171     }
172
173 }