Support for creating shared ontology dump to git
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / utils / DumpOntologyStructure.java
1 package org.simantics.modeling.utils;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.nio.charset.StandardCharsets;
6 import java.util.Collection;
7 import java.util.HashMap;
8 import java.util.Map;
9 import java.util.TreeMap;
10
11 import org.simantics.Simantics;
12 import org.simantics.db.ReadGraph;
13 import org.simantics.db.Resource;
14 import org.simantics.db.common.utils.CommonDBUtils;
15 import org.simantics.db.common.utils.NameUtils;
16 import org.simantics.db.exception.DatabaseException;
17 import org.simantics.db.layer0.variable.Variable;
18 import org.simantics.db.layer0.variable.Variables;
19 import org.simantics.layer0.Layer0;
20 import org.simantics.modeling.ModelingResources;
21 import org.simantics.scl.runtime.function.Function;
22 import org.simantics.utils.FileUtils;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 import gnu.trove.list.array.TByteArrayList;
27
28 public class DumpOntologyStructure {
29
30     private static final Logger LOGGER = LoggerFactory.getLogger(DumpOntologyStructure.class);
31
32     private Resource ontology;
33     
34     private Map<Resource, String> names = new HashMap<>();
35     private Map<Resource,Resource> parents = new HashMap<>();
36     private Map<Resource, File> libraryFolders = new HashMap<>();
37     private Map<Resource, byte[]> contentDumps = new HashMap<>();
38
39     private void readNameAndParent(ReadGraph graph, Resource container, Resource r) throws DatabaseException {
40         parents.put(r, container);
41         names.put(r, NameUtils.getSafeName(graph, r));
42     }
43     
44     private Collection<Resource> containers() {
45         return parents.values();
46     }
47     
48     private void readHierarchy(ReadGraph graph, Resource container) throws DatabaseException {
49         Layer0 L0 = Layer0.getInstance(graph);
50         for(Resource r : CommonDBUtils.objectsWithType(graph, container, L0.ConsistsOf, L0.Entity)) {
51             try {
52                 readNameAndParent(graph, container, r);
53                 readHierarchy(graph, r);
54             } catch (DatabaseException e) {
55                 LOGGER.error("Error while reading content dump hierarchy for " + r, e);
56             }
57         }
58     }
59
60     private void readGeneric(ReadGraph graph) throws DatabaseException {
61         ModelingResources MOD = ModelingResources.getInstance(graph);
62         for(Resource r : parents.keySet()) {
63             if(contentDumps.containsKey(r))
64                 continue;
65             TByteArrayList result = new TByteArrayList();
66             try {
67                 TreeMap<String,Resource> sortedTypes = new TreeMap<>();
68                 for(Resource type : graph.getTypes(r)) {
69                     String uri = graph.getPossibleURI(type);
70                     if(uri != null)
71                         sortedTypes.put(uri, type);
72                 }
73                 for(Resource type : sortedTypes.values()) {
74                     try {
75                         Variable typeVariable = Variables.getVariable(graph, type);
76                         @SuppressWarnings("rawtypes")
77                         Function f = typeVariable.getPossiblePropertyValue(graph, MOD.contentDumpFunction);
78                         if(f != null) {
79                             @SuppressWarnings("unchecked")
80                             byte[] dump = (byte[])Simantics.applySCLRead(graph, f, r);
81                             if(dump != null) {
82                                 result.add(dump);
83                             }
84                         }
85                     } catch (DatabaseException e) {
86                         LOGGER.error("Error while computing content dump for " + r, e);
87                     }
88                 }
89                 if(result.size() > 0)
90                     contentDumps.put(r, result.toArray());
91             } catch (DatabaseException e) {
92                 LOGGER.error("Error while computing content dump for " + r, e);
93             }
94         }
95     }
96
97     public void read(ReadGraph graph, Resource ontology) throws DatabaseException {
98         this.ontology = ontology;
99         readHierarchy(graph, ontology);
100         readGeneric(graph);
101     }
102     
103     private File escapeFile(File file) {
104
105         if(file.exists())
106             return file;
107         
108         return new File(escapeFile(file.getParentFile()), FileUtils.escapeFileName(file.getName()));
109         
110     }
111     
112     public void write(File unsafeFolder) throws IOException {
113         File folder = escapeFile(unsafeFolder);
114         if(folder.exists())
115             FileUtils.deleteAll(folder);
116         folder.mkdirs();
117         writeDirectories(folder);
118         writeResources(folder);
119     }
120     
121     private File getFolder(File root, Resource library) {
122         if(ontology.equals(library))
123             return root;
124         Resource parent = parents.get(library);
125         if(parent == null)
126             throw new IllegalStateException("null parent for " + library);
127         File parentFolder = getFolder(root, parent);
128         return new File(parentFolder, FileUtils.escapeFileName(names.get(library))); 
129     }
130
131     private File getFile(File rootFolder, Resource r) {
132         Resource parent = parents.get(r);
133         File folder = getFolder(rootFolder, parent);
134         return new File(folder, FileUtils.escapeFileName(names.get(r)));
135     }
136
137     private void writeDirectories(File rootFolder) {
138         for(Resource library : containers()) {
139             File folder = getFolder(rootFolder, library);
140             folder.mkdirs();
141             libraryFolders.put(library, folder);
142         }
143     }
144
145     private void writeResources(File rootFolder) throws IOException {
146         for(Resource r : parents.keySet()) {
147             writeResource(rootFolder, r);
148         }
149     }
150     
151     private boolean isParent(Resource r) {
152         return parents.values().contains(r);
153     }
154     
155     private void writeResource(File rootFolder, Resource resource) throws IOException {
156         byte[] dump = contentDumps.get(resource);
157         if(dump == null)
158             dump = "".getBytes(StandardCharsets.UTF_8);
159         if(isParent(resource)) {
160             if(dump.length > 0)
161                 FileUtils.writeFile(new File(getFolder(rootFolder, resource), "__contents__"), dump);
162         } else {
163             write(rootFolder, resource, dump);
164         }
165     }
166
167     private void write(File rootFolder, Resource resource, byte[] bytes) throws IOException {
168         FileUtils.writeFile(getFile(rootFolder, resource), bytes);
169     }
170
171 }