]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graph/src/org/simantics/graph/refactoring/GraphRefactoringUtils.java
Merge branch 'feature/funcwrite'
[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.ArrayList;
4 import java.util.Arrays;
5
6 import org.simantics.databoard.util.URIStringUtils;
7 import org.simantics.graph.query.Path;
8 import org.simantics.graph.query.PathChild;
9 import org.simantics.graph.query.TransferableGraphConversion;
10 import org.simantics.graph.query.UriUtils;
11 import org.simantics.graph.refactoring.MappingSpecification.MappingRule;
12 import org.simantics.graph.representation.External;
13 import org.simantics.graph.representation.Identity;
14 import org.simantics.graph.representation.IdentityDefinition;
15 import org.simantics.graph.representation.Internal;
16 import org.simantics.graph.representation.Optional;
17 import org.simantics.graph.representation.Root;
18 import org.simantics.graph.representation.TransferableGraph1;
19 import org.simantics.graph.representation.TransferableGraphUtils;
20 import org.simantics.graph.representation.old.OldTransferableGraph1;
21 import org.simantics.graph.representation.old.OldValue1;
22 import org.simantics.graph.store.GraphStore;
23 import org.simantics.graph.store.IdentityStore;
24
25 import gnu.trove.list.array.TIntArrayList;
26 import gnu.trove.map.hash.TIntIntHashMap;
27 import gnu.trove.set.hash.TIntHashSet;
28
29 public class GraphRefactoringUtils {
30
31     /**
32      * Moves an external resource. Returns true if did something.
33      * @param parentsAffected 
34      */
35     public static boolean moveExternal(TransferableGraph1 tg, IdentityStore ids, Path from, PathChild to, TIntHashSet parentsAffected) throws GraphRefactoringException {
36         // Find from id
37         int fromId = ids.pathToId(from);
38         if(fromId < 0)
39             return false;
40         if(ids.isNewResource(fromId))
41             throw new GraphRefactoringException("Cannot move internal resource " + from + ".");
42
43         // Remove old identity
44         int parentId = ids.removeIdentity(fromId);
45         if(parentId >= 0)
46             parentsAffected.add(parentId);
47
48         // Find parent id
49         int toParentId = ids.createPathToId(to.parent);
50         if(ids.hasChild(toParentId, to.name)) {
51                 System.err.println("refactor statements from " + from + " to " + to);
52             //throw new GraphRefactoringException("External reference to " + to + " already exists.");
53                 int toId = ids.pathToId(to);
54             int[] statements = tg.statements;
55             for(int i=0;i<tg.statements.length;++i) {
56                 if(statements[i] == fromId) statements[i] = toId;
57             }
58             return true;
59         }
60         
61         // Set new identity
62         ids.setIdentity(fromId, toParentId, to.name);
63         return true;
64     }
65     
66     public static void refactor(TransferableGraph1 tg, IdentityStore ids, MappingSpecification spec, TIntHashSet parentsAffected) throws GraphRefactoringException {
67         for(MappingRule rule : spec.getRules()) {
68             if(!(rule.to instanceof PathChild))
69                 throw new GraphRefactoringException("Invalid target URI " + rule.to);
70             if(!moveExternal(tg, ids, rule.from, (PathChild)rule.to, parentsAffected))
71                 System.err.println("Didn't find " + rule.from);
72         }
73     }
74
75     public static boolean fixIncorrectRoot(Identity[] ids) {
76         for(int i=0;i<ids.length;++i) {
77             Identity id = ids[i];
78             if(id.definition instanceof External) {
79                 External ext = (External)id.definition;
80                 if(ext.parent == -1 && (ext.name.equals("http:/") || ext.name.equals(""))) {
81                     id.definition = new Root("", "");
82                     return true;
83                 }
84             }
85         }
86         return false;
87     }
88
89     public static void fixOntologyExport(TransferableGraph1 tg) {
90         
91         fixIncorrectRoot(tg.identities);
92         fixOntologyRoot(tg, true);
93         
94     }
95     
96     private static Identity recursePath(TransferableGraph1 tg, String path) {
97         
98         Identity extId = TransferableGraphUtils.findExternal(tg, path);
99         if(extId != null) return extId;
100         if("http://".equals(path)) return TransferableGraphUtils.findRootWithName(tg, "");
101         String[] parts = URIStringUtils.splitURI(path);
102         Identity parentId = recursePath(tg, parts[0]);
103         tg.identities = Arrays.copyOf(tg.identities, tg.identities.length+1);
104         Identity childIdentity = new Identity(tg.resourceCount++, new External(parentId.resource, parts[1]));
105                 tg.identities[tg.identities.length-1] = childIdentity;
106                 return childIdentity;
107         
108     }
109     
110     public static void fixOntologyRoot(TransferableGraph1 tg, boolean tryToFix) {
111
112         Identity[] ids = tg.identities;
113         for(int i=0;i<ids.length;++i) {
114             Identity id = ids[i];
115             if(id.definition instanceof Root) {
116                 Root ext = (Root)id.definition;
117                 if(ext.name.startsWith("http://")) {
118                         
119                         String[] parts = URIStringUtils.splitURI(ext.name);
120                         Identity path = recursePath(tg, parts[0]);
121                         id.definition = new Internal(path.resource, parts[1]);
122                         
123                         GraphStore store = TransferableGraphConversion.convert(tg);
124                         int rootId = store.identities.createPathToId(UriUtils.uriToPath(ext.name));
125                         propagateNewMarks(store.identities, rootId);
126
127                         TransferableGraph1 tgNew = TransferableGraphConversion.convert(store);
128                                 
129                         tg.resourceCount = tgNew.resourceCount;
130                         tg.identities = tgNew.identities;
131                         tg.values = tgNew.values;
132                         tg.statements = tgNew.statements;
133                                 
134                         return;
135                         
136                 }
137             }
138         }
139         
140     }
141     
142         private static void propagateNewMarks(IdentityStore identities, int resource) {
143                 if(identities.markNew(resource)) {
144                         for(int child : identities.getChildren(resource))
145                                 propagateNewMarks(identities, child);
146                 }
147         }
148
149     public static void unfixIncorrectRoot(Identity[] ids) {
150         for(int i=0;i<ids.length;++i) {
151             Identity id = ids[i];
152             if(id.definition instanceof Root) {
153                 Root root = (Root)id.definition;
154                 if(root.name.equals("") && root.type.equals("")) {
155                     id.definition = new External(-1, "http:/");
156                     return;
157                 }
158             }
159         }
160     }
161
162     public static void compactify(OldTransferableGraph1 tg,
163             TIntHashSet removed) {
164         // Filter removed set
165         for(Identity id : tg.identities) {
166             IdentityDefinition def = id.definition;
167             if(def instanceof Root)
168                 removed.remove(id.resource);
169             else if(def instanceof External)
170                 removed.remove(((External)def).parent);
171             else if(def instanceof Internal)
172                 removed.remove(((Internal)def).parent);
173             else if(def instanceof Optional)
174                 removed.remove(((Optional)def).parent);
175         }
176         for(int r : tg.statements)
177             removed.remove(r);
178         for(OldValue1 value : tg.values)
179             removed.remove(value.resource);
180         
181         // Compactify
182         if(!removed.isEmpty()) {
183             // create map
184             int resourceCount = tg.resourceCount;
185             int[] map = new int[resourceCount];
186             for(int i=0;i<resourceCount;++i)
187                 map[i] = i;
188             for(int r : removed.toArray()) {
189                 map[--resourceCount] = map[r];
190             }
191             
192             // map
193             ArrayList<Identity> newIdentities = new ArrayList<Identity>(tg.identities.length);
194             for(Identity id : tg.identities) {
195                 if(removed.contains(id.resource))
196                     continue;
197                 else
198                     newIdentities.add(id);                
199                 id.resource = map[id.resource];
200                 IdentityDefinition def = id.definition;
201                 if(def instanceof External) {
202                     External d = (External)def;
203                     d.parent = map[d.parent];
204                 }
205                 else if(def instanceof Internal) {
206                     External d = (External)def;
207                     d.parent = map[d.parent];
208                 }
209                 else if(def instanceof Optional) {
210                     External d = (External)def;
211                     d.parent = map[d.parent];
212                 }
213             }
214             tg.identities = newIdentities.toArray(new Identity[newIdentities.size()]);
215             int[] statements = tg.statements;
216             for(int i=0;i<statements.length;++i) {
217                 int r = statements[i];                        
218                 if(r >= 0)
219                     statements[i] = map[r];
220             }
221             for(OldValue1 value : tg.values)
222                 value.resource = map[value.resource];
223             tg.resourceCount = resourceCount;
224         }
225     }
226
227 }