1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package cz.zcu.mre.sparkle.data;
21
22 import cz.zcu.mre.sparkle.gui.query.helpers.PrefixesUser;
23 import cz.zcu.mre.sparkle.tools.*;
24 import cz.zcu.mre.sparkle.tools.SparqlParser;
25 import javafx.beans.InvalidationListener;
26 import javafx.collections.FXCollections;
27 import javafx.collections.MapChangeListener;
28 import javafx.collections.ObservableMap;
29 import org.apache.jena.shared.PrefixMapping;
30 import org.w3c.dom.Document;
31 import org.w3c.dom.Element;
32 import org.w3c.dom.NodeList;
33 import java.io.IOException;
34 import java.io.ObjectInputStream;
35 import java.io.ObjectOutputStream;
36 import java.io.Serializable;
37 import java.util.HashMap;
38 import java.util.HashSet;
39 import java.util.Map;
40 import java.util.Map.Entry;
41 import java.util.Set;
42 import java.util.regex.Matcher;
43 import static cz.zcu.mre.sparkle.tools.sparqlParser.SparqlParserUtils.IRI_PATTERN;
44 import static cz.zcu.mre.sparkle.tools.sparqlParser.SparqlParserUtils.PREFIX_PATTERN;
45
46
47
48
49
50
51
52
53 public final class PrefixesStorage
54 implements Serializable, PrefixesUser, PrefixMapping, Saveable, Changeable {
55
56 private static final long serialVersionUID = -5472647693723537955L;
57 private static final String XML_ELEMENT_NAME = "Prefixes";
58 private static final String XML_ENTRY_ELEMENT_NAME = "Entry";
59 private static final String XML_ENTRY_NAMESPACE = "ns";
60 private static final String XML_ENTRY_ALT_NAMESPACE = "altNs";
61 private static final String XML_ENTRY_PREFIX = "prefix";
62
63 private transient ObservableMap<String, String> prefixToIri;
64 private transient ObservableMap<String, String> iriToPrefix;
65 private transient ObservableMap<String, String> iriToPrefixReadOnly;
66 private transient ObservableMap<String, String> iriToAlternativeIri;
67 private transient Set<InvalidationListener> observers;
68
69 public PrefixesStorage() {
70 init();
71 }
72
73
74
75
76 public static final PrefixesStorage getBuiltIn() {
77 final PrefixesStorage prefixesStorage = new PrefixesStorage();
78
79 BuiltInVocabulary builtInNamespaces = new BuiltInVocabulary();
80
81 builtInNamespaces.getBuiltInNamespaces().forEach((entry) -> {
82 registerPrefix(prefixesStorage, entry.getUri(), entry.getPrefix(), entry.getAlternativeUri());
83 });
84
85 return prefixesStorage;
86 }
87
88
89
90
91
92 private void init() {
93 observers = new HashSet<>();
94 prefixToIri = FXCollections.observableHashMap();
95 iriToPrefix = FXCollections.observableHashMap();
96 iriToPrefixReadOnly = FXCollections.unmodifiableObservableMap(iriToPrefix);
97 iriToAlternativeIri = FXCollections.observableHashMap();
98 prefixToIriMapper();
99 }
100
101
102
103
104
105
106
107
108 public void addPrefix(String prefix, String iri, String alternativeIri) {
109 iriToAlternativeIri.put(iri, alternativeIri);
110 prefixToIri.put(prefix, iri);
111
112 }
113
114 private void removePrefix(String prefix, String iri) {
115 iriToAlternativeIri.remove(iri);
116 prefixToIri.remove(prefix);
117
118 }
119
120
121
122
123 private void prefixToIriMapper() {
124
125
126
127 prefixToIri.addListener((final MapChangeListener.Change<? extends String, ? extends String> change) -> {
128
129 final String valueAdded = change.getValueAdded();
130 final String valueRemoved = change.getValueRemoved();
131
132 if (valueRemoved != null) {
133 iriToPrefix.remove(valueRemoved);
134 }
135
136 if (valueAdded != null) {
137 iriToPrefix.put(valueAdded, change.getKey());
138 }
139
140 notifyChanged();
141 });
142 }
143
144
145
146
147
148
149
150
151 private static void registerPrefix(final PrefixesStorage prefixesStorage, final String iri, final String prefix,
152 String alternativeIri) {
153
154 final String prefixToRemove = prefixesStorage.iriToPrefix.get(iri);
155
156 if (prefixToRemove != null && alternativeIri == null) {
157
158 return;
159 }
160
161 if (prefixToRemove != null) {
162 prefixesStorage.removePrefix(prefixToRemove, iri);
163 }
164
165 prefixesStorage.addPrefix(prefix, iri, alternativeIri);
166 }
167
168
169
170
171
172
173 public final void add(final PrefixesStorage prefixesStorage) {
174 iriToAlternativeIri.putAll(prefixesStorage.getIriToAlternativeIri());
175 setNsPrefixes(prefixesStorage);
176
177 }
178
179 @Override
180 public final PrefixMapping removeNsPrefix(final String prefix) {
181 iriToAlternativeIri.remove(getPrefixToIri().get(prefix));
182 getPrefixToIri().remove(prefix);
183
184 return this;
185 }
186
187
188
189
190
191
192
193 public final void renamePrefix(final String oldPrefix, final String newPrefix) {
194 final String iri = prefixToIri.get(oldPrefix);
195 iriToPrefix.put(iri, newPrefix);
196 prefixToIri.put(newPrefix, iri);
197 prefixToIri.remove(oldPrefix);
198 }
199
200 @Override
201 public final PrefixMapping setNsPrefix(final String prefix, final String iri) {
202 String oldIri = prefixToIri.get(prefix);
203 String altIri = iriToAlternativeIri.remove(oldIri);
204
205 return setNsPrefix(prefix, iri, altIri);
206 }
207
208 public final PrefixMapping setNsPrefix(final String prefix, final String iri, String alternativeIri) {
209 iriToAlternativeIri.put(iri, alternativeIri);
210 prefixToIri.put(prefix, iri);
211 return this;
212 }
213
214
215
216
217
218
219
220
221 private void writeObject(final ObjectOutputStream out) throws IOException {
222 out.defaultWriteObject();
223
224 final Set<Entry<String, String>> entrySet = prefixToIri.entrySet();
225 out.writeInt(entrySet.size());
226
227 for (final Entry<String, String> entry : entrySet) {
228 out.writeUTF(entry.getKey());
229 String altIri = iriToAlternativeIri.get(entry.getValue());
230 out.writeUTF(entry.getValue());
231 out.writeUTF(altIri);
232 }
233 }
234
235
236
237
238
239
240
241
242
243 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
244 in.defaultReadObject();
245
246 init();
247
248 final int size = in.readInt();
249 for (int index = 0; index < size; index++) {
250 final String key = in.readUTF();
251 final String iri = in.readUTF();
252 final String alternativeIri = in.readUTF();
253
254 registerPrefix(this, iri, key, alternativeIri);
255 }
256 }
257
258
259
260
261 public final ObservableMap<String, String> getPrefixToIri() {
262 return prefixToIri;
263 }
264
265
266
267
268 public final ObservableMap<String, String> getIriToPrefixReadOnly() {
269 return iriToPrefixReadOnly;
270 }
271
272 @Override
273 public final Set<String> getPrefixesUsed(final boolean appendDelimiter) {
274 final Set<String> result = new HashSet<>();
275 prefixToIri.keySet().forEach((prefix) -> result.add(appendDelimiter ? prefix + Definitions.PREFIXED_NAME_PREFIX_DELIMITER : prefix));
276
277 return result;
278 }
279
280 @Override
281 public final PrefixMapping setNsPrefixes(final PrefixMapping other) {
282 return setNsPrefixes(other.getNsPrefixMap());
283 }
284
285 @Override
286 public final PrefixMapping setNsPrefixes(final Map<String, String> map) {
287 prefixToIri.putAll(map);
288 return this;
289 }
290
291 public void setAlternativeIri(String iri, String alternatiteIri) {
292 iriToAlternativeIri.put(iri, alternatiteIri);
293 }
294
295 @Override
296 public final PrefixMapping withDefaultMappings(final PrefixMapping map) {
297 map.getNsPrefixMap().forEach((key, value) -> prefixToIri.putIfAbsent(key, value));
298 return this;
299 }
300
301 @Override
302 public final String getNsPrefixURI(final String prefix) {
303 return prefixToIri.get(prefix);
304 }
305
306 @Override
307 public final String getNsURIPrefix(final String iri) {
308 return iriToPrefix.get(iri);
309 }
310
311 @Override
312 public final Map<String, String> getNsPrefixMap() {
313 return new HashMap<>(prefixToIri);
314 }
315
316 @Override
317 public final String expandPrefix(final String prefixed) {
318 final String prefix = Utils.extractPrefix(prefixed);
319 if (prefix != null) {
320 final String iri = prefixToIri.get(prefix);
321 if (iri == null) {
322 return prefixed;
323 }
324 return Utils.tryReplacePrefixForIRI(prefix, iri, prefixed);
325 }
326 return prefixed;
327 }
328
329 @Override
330 public final String shortForm(final String iri) {
331
332 for (Map.Entry<String, String> storedIriMapEntry : iriToPrefix.entrySet()) {
333 final String storedIriKey = storedIriMapEntry.getKey();
334
335 if (iri.startsWith(storedIriKey)) {
336 return iriToPrefix.get(storedIriKey) + Definitions.PREFIXED_NAME_PREFIX_DELIMITER
337 + iri.substring(storedIriKey.length());
338 }
339 }
340
341 return iri;
342 }
343
344 @Override
345 public final String qnameFor(final String iri) {
346 String longestStoredIri = null;
347 int longestLength = 0;
348 for (final String storedIri : iriToPrefix.keySet()) {
349 final int length = storedIri.length();
350 if (length <= longestLength) {
351 continue;
352 }
353 if (iri.startsWith(storedIri)) {
354 longestStoredIri = storedIri;
355 longestLength = length;
356 }
357 }
358 if (longestStoredIri == null) {
359 return null;
360 }
361 return iriToPrefix.get(longestStoredIri) + Definitions.PREFIXED_NAME_PREFIX_DELIMITER
362 + iri.substring(longestLength);
363 }
364
365 @Override
366 public final PrefixMapping lock() {
367
368 return this;
369 }
370
371 @Override
372 public final boolean samePrefixMappingAs(final PrefixMapping other) {
373 if (other == null) {
374 return false;
375 }
376 if (other instanceof PrefixesStorage) {
377 return prefixToIri.equals(((PrefixesStorage) other).prefixToIri);
378 }
379 return prefixToIri.equals(other.getNsPrefixMap());
380 }
381
382 @Override
383 public final void save(final Element e) {
384 final Document doc = e.getOwnerDocument();
385 prefixToIri.entrySet().stream().map((entry) -> {
386 final Element entryElement = doc.createElement(XML_ENTRY_ELEMENT_NAME);
387 entryElement.setAttribute(XML_ENTRY_NAMESPACE, entry.getValue());
388
389 String altUri = iriToAlternativeIri.get(entry.getValue());
390 entryElement.setAttribute(XML_ENTRY_ALT_NAMESPACE, altUri);
391
392 entryElement.setAttribute(XML_ENTRY_PREFIX, entry.getKey());
393
394 return entryElement;
395 }).forEachOrdered(e::appendChild);
396 }
397
398 @Override
399 public final void load(final Object e) throws LoadException {
400 if (e instanceof Element) {
401
402 final NodeList list = ((Element) e).getElementsByTagName(XML_ENTRY_ELEMENT_NAME);
403 final int nodesCount = list.getLength();
404 for (int index = 0; index < nodesCount; index++) {
405 final Element entryElement = (Element) list.item(index);
406
407 registerPrefix(this, entryElement.getAttribute(XML_ENTRY_NAMESPACE),
408 entryElement.getAttribute(XML_ENTRY_PREFIX),
409 entryElement.getAttribute(XML_ENTRY_ALT_NAMESPACE));
410 }
411
412 } else if (e instanceof SparqlParser.PrefixDeclContext) {
413
414 SparqlParser.PrefixDeclContext root = (SparqlParser.PrefixDeclContext) e;
415
416 Matcher prefixMatcher = PREFIX_PATTERN.matcher(root.PNAME_NS().getText());
417 Matcher iriMatcher = IRI_PATTERN.matcher(root.IRIREF().getText());
418
419 if (prefixMatcher.matches() && iriMatcher.matches()) {
420 registerPrefix(this, iriMatcher.group(1), prefixMatcher.group(1), null);
421 }
422 }
423 }
424
425 @Override
426 public final String getXMLElementName() {
427 return XML_ELEMENT_NAME;
428 }
429
430 @Override
431 public final Set<InvalidationListener> getObservers() {
432 return observers;
433 }
434
435 @Override
436 public int numPrefixes() {
437 return prefixToIri.size();
438 }
439
440 @Override
441 public PrefixMapping clearNsPrefixMap() {
442 this.prefixToIri.clear();
443 this.iriToPrefix.clear();
444 this.iriToAlternativeIri.clear();
445
446 return this;
447 }
448
449 public ObservableMap<String, String> getIriToAlternativeIri() {
450 return iriToAlternativeIri;
451 }
452
453 }