Skip to content

Commit 4e7e10a

Browse files
bug fixes
1 parent 8e542c2 commit 4e7e10a

File tree

7 files changed

+161
-28
lines changed

7 files changed

+161
-28
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ hs_err_pid*
2828
simple-rdfs-editor-headless.sh
2929
deploy.sh
3030
nbactions.xml
31+
/nbproject/

pom.xml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>com.github.mschroeder.github</groupId>
55
<artifactId>simple-rdfs-editor</artifactId>
6-
<version>1.0.0</version>
6+
<version>1.0.0-SNAPSHOT</version>
77
<packaging>jar</packaging>
88
<name>Simple RDFS Editor</name>
99
<description>Editor to simply create RDFS based ontologies.</description>
@@ -48,7 +48,7 @@
4848
<dependency>
4949
<groupId>org.apache.jena</groupId>
5050
<artifactId>jena-core</artifactId>
51-
<version>3.12.0</version>
51+
<version>3.13.0</version>
5252
</dependency>
5353

5454
<!-- web -->
@@ -63,7 +63,13 @@
6363
<version>2.7.1</version>
6464
</dependency>
6565

66-
66+
<dependency>
67+
<groupId>junit</groupId>
68+
<artifactId>junit</artifactId>
69+
<version>4.13</version>
70+
<scope>test</scope>
71+
</dependency>
72+
6773
</dependencies>
6874

6975
<build>

src/main/java/com/github/mschroeder/github/srdfse/EditorPanel.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,9 @@ public Component getListCellRendererComponent(JList<?> list, Object value, int i
672672

673673
} else {
674674
String lbl = res.getLabel().get(getSelectedLanguage());
675+
if(lbl == null) {
676+
lbl = res.getLocalname();
677+
}
675678
label.setText(lbl);
676679
label.setIcon(instanceIcon);
677680
}
@@ -703,7 +706,13 @@ private void render(Ontology ontology, JLabel label) {
703706

704707
private void render(Resource resource, JLabel label, JTree jtree) {
705708
if (resource.getType() == Resource.Type.Class) {
706-
label.setText(resource.getLocalname(true));
709+
710+
String extra = "";
711+
if(!resource.getInstances().isEmpty()) {
712+
extra = " (" + resource.getInstances().size() + ")";
713+
}
714+
715+
label.setText(resource.getLocalname(true) + extra);
707716
label.setIcon(classIcon);
708717
} else if (resource.getType() == Resource.Type.Property) {
709718
StringBuilder sb = new StringBuilder();
@@ -737,6 +746,10 @@ private void render(Resource resource, JLabel label, JTree jtree) {
737746

738747
sb.append("</font>");
739748

749+
if(!resource.getLinks().isEmpty()) {
750+
sb.append(" (" + resource.getLinks().size() + ")");
751+
}
752+
740753
sb.append("</html>");
741754

742755
label.setText(sb.toString());

src/main/java/com/github/mschroeder/github/srdfse/Ontology.java

Lines changed: 126 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,17 @@
2020
import java.util.Queue;
2121
import java.util.Set;
2222
import org.apache.commons.io.FilenameUtils;
23+
import org.apache.jena.datatypes.RDFDatatype;
24+
import org.apache.jena.datatypes.TypeMapper;
2325
import org.apache.jena.rdf.model.Literal;
2426
import org.apache.jena.rdf.model.Model;
2527
import org.apache.jena.rdf.model.ModelFactory;
2628
import org.apache.jena.rdf.model.Property;
2729
import org.apache.jena.rdf.model.RDFNode;
2830
import org.apache.jena.rdf.model.ResourceFactory;
2931
import org.apache.jena.rdf.model.Statement;
32+
import org.apache.jena.shared.PrefixMapping;
33+
import org.apache.jena.shared.impl.PrefixMappingImpl;
3034
import org.apache.jena.vocabulary.OWL;
3135
import org.apache.jena.vocabulary.RDF;
3236
import org.apache.jena.vocabulary.RDFS;
@@ -52,6 +56,11 @@ public class Ontology {
5256

5357
private List<Link> inverseOf;
5458

59+
private PrefixMapping prefixMapping;
60+
61+
//filled by loadABox()
62+
//private List<Statement> skippedABox;
63+
5564
public Ontology() {
5665
this.prefix = "";
5766
this.uri = "";
@@ -63,8 +72,16 @@ public Ontology() {
6372
rootClasses = new ArrayList<>();
6473
rootProperties = new ArrayList<>();
6574
inverseOf = new ArrayList<>();
75+
76+
prefixMapping = new PrefixMappingImpl();
77+
78+
//skippedABox = new ArrayList<>();
6679
}
6780

81+
public PrefixMapping getPrefixMapping() {
82+
return prefixMapping;
83+
}
84+
6885
public void addInverseOf(Resource source, Resource target) {
6986
inverseOf.add(new Link(source, target));
7087
}
@@ -234,6 +251,9 @@ public static Ontology loadTTL(String filename, InputStream is) {
234251
//from model to onto
235252
public static void loadTBox(Ontology onto, Model m) {
236253
Map<String, String> prefixMap = m.getNsPrefixMap();
254+
255+
prefixMap.putAll(onto.prefixMapping.getNsPrefixMap());
256+
237257
//try find full uri in file
238258
String uri = prefixMap.get(onto.getPrefix());
239259
if (uri != null) {
@@ -275,9 +295,12 @@ public static void loadTBox(Ontology onto, Model m) {
275295
Set<Resource> rootClasses = new HashSet<>();
276296
Set<Resource> rootProps = new HashSet<>();
277297

278-
addResouces(m, RDFS.Class, Resource.Type.Class, onto, mapped, rootClasses, prefix2onto);
279-
addResouces(m, RDFS.Datatype, Resource.Type.Datatype, onto, mapped, rootClasses, prefix2onto);
280-
addResouces(m, RDF.Property, Resource.Type.Property, onto, mapped, rootProps, prefix2onto);
298+
Map<String, String> nsMap = new HashMap<>();
299+
prefixMap.forEach((a,b) -> nsMap.put(b,a));
300+
301+
addResouces(m, RDFS.Class, Resource.Type.Class, onto, mapped, rootClasses, prefix2onto, nsMap);
302+
addResouces(m, RDFS.Datatype, Resource.Type.Datatype, onto, mapped, rootClasses, prefix2onto, nsMap);
303+
addResouces(m, RDF.Property, Resource.Type.Property, onto, mapped, rootProps, prefix2onto, nsMap);
281304

282305
addRelations(m, RDFS.subClassOf, mapped, rootClasses, SpecialRelation.Sub);
283306
addRelations(m, RDFS.subPropertyOf, mapped, rootProps, SpecialRelation.Sub);
@@ -302,28 +325,35 @@ public static void loadABox(Ontology onto, Model m) {
302325

303326
Map<org.apache.jena.rdf.model.Resource, Resource> jena2res = new HashMap<>();
304327

305-
//types
328+
//instances which have no type are ignored here
306329
for(Statement stmt : m.listStatements(null, RDF.type, (RDFNode) null).toList()) {
307330
if(!stmt.getObject().isResource())
308331
continue;
309332

333+
if(stmt.getResource().equals(RDF.Property)) {
334+
continue;
335+
}
336+
310337
Resource clazz = uri2resource.get(stmt.getObject().asResource().getURI());
311338
if(clazz != null && clazz.getType() == Resource.Type.Class) {
312339

313-
String ns = stmt.getSubject().getNameSpace();
340+
String ns = getNameSpace(stmt.getSubject().getURI());
314341
String instPrefix = m.getNsURIPrefix(ns);
315342
if(instPrefix != null) {
316343
onto.setInstanceNamespace(ns);
317344
onto.setInstancePrefix(instPrefix);
318345
}
319346

320-
Resource inst = toResource(stmt.getSubject(), m, onto, Resource.Type.Instance, null);
347+
Resource inst = toResource(stmt.getSubject(), m, onto, Resource.Type.Instance, null, m.getNsPrefixMap()); //TODO m.getNsPrefixMap()
321348
clazz.addInstance(inst);
322349

323350
jena2res.put(stmt.getSubject(), inst);
324351
}
325352
}
326353

354+
onto.listClasses().forEach(clazz -> clazz.getInstances().sort((a, b) -> a.getLocalname().compareTo(b.getLocalname())));
355+
356+
//only the collected instances are iterated, without type is skipped
327357
//for all collected instances
328358
for(org.apache.jena.rdf.model.Resource jenaInstance : jena2res.keySet()) {
329359

@@ -332,13 +362,21 @@ public static void loadABox(Ontology onto, Model m) {
332362
for(Statement triple : m.listStatements(jenaInstance, null, (RDFNode) null).toList()) {
333363
Resource prop = uri2resource.get(triple.getPredicate().getURI());
334364

335-
if(prop == null)
365+
if(prop == null) {
366+
//onto.skippedABox.add(triple);
336367
continue;
368+
}
337369

338370
//literal case
339371
if(triple.getObject().isLiteral()) {
372+
Literal lit = triple.getObject().asLiteral();
373+
340374
Resource literal = new Resource(onto, Resource.Type.Literal);
341-
literal.getComment().put("", triple.getObject().asLiteral().getLexicalForm());
375+
376+
if(lit.getDatatypeURI() != null && !lit.getDatatypeURI().isEmpty() && !lit.getDatatypeURI().equals(XSD.xstring.getURI())) {
377+
literal.getComment().put("datatype", lit.getDatatypeURI());
378+
}
379+
literal.getComment().put("", lit.getLexicalForm());
342380

343381
prop.addLink(subj, literal);
344382
continue;
@@ -350,16 +388,21 @@ public static void loadABox(Ontology onto, Model m) {
350388

351389
Resource obj = jena2res.get(triple.getObject().asResource());
352390

353-
if(prop != null && obj != null) {
391+
if(obj != null) {
354392
prop.addLink(subj, obj);
355393
}
356394
}
357395
}
358396
}
359397

360-
private static void addResouces(Model m, org.apache.jena.rdf.model.Resource typeResource, Resource.Type type, Ontology onto, Map<org.apache.jena.rdf.model.Resource, Resource> mapped, Set<Resource> roots, Map<String, Ontology> prefix2onto) {
398+
private static void addResouces(Model m, org.apache.jena.rdf.model.Resource typeResource, Resource.Type type, Ontology onto, Map<org.apache.jena.rdf.model.Resource, Resource> mapped, Set<Resource> roots, Map<String, Ontology> prefix2onto, Map<String, String> nsMap) {
361399
for (org.apache.jena.rdf.model.Resource jena : m.listSubjectsWithProperty(RDF.type, typeResource).toList()) {
362-
Resource res = toResource(jena, m, onto, type, prefix2onto);
400+
//skip type
401+
if(typeResource.equals(RDF.Property) && jena.equals(RDF.type)) {
402+
continue;
403+
}
404+
405+
Resource res = toResource(jena, m, onto, type, prefix2onto, nsMap);
363406
roots.add(res);
364407
mapped.put(jena, res);
365408
}
@@ -382,9 +425,17 @@ private static void addRelations(Model m, Property p, Map<org.apache.jena.rdf.mo
382425
o.addChild(s);
383426
root.remove(s);
384427
} else if (special == SpecialRelation.Domain) {
385-
s.setDomain(o);
428+
if(s.hasDomain()) {
429+
s.getAdditionalDomainRangeStatements().add(stmt);
430+
} else {
431+
s.setDomain(o);
432+
}
386433
} else if (special == SpecialRelation.Range) {
387-
s.setRange(o);
434+
if(s.hasRange()) {
435+
s.getAdditionalDomainRangeStatements().add(stmt);
436+
} else {
437+
s.setRange(o);
438+
}
388439
}
389440
}
390441
}
@@ -395,9 +446,9 @@ private static enum SpecialRelation {
395446
Range
396447
}
397448

398-
private static Resource toResource(org.apache.jena.rdf.model.Resource jenaRes, Model model, Ontology onto, Resource.Type type, Map<String, Ontology> prefix2onto) {
399-
String prefix = model.getNsURIPrefix(jenaRes.getNameSpace());
400-
449+
private static Resource toResource(org.apache.jena.rdf.model.Resource jenaRes, Model model, Ontology onto, Resource.Type type, Map<String, Ontology> prefix2onto, Map<String, String> nsMap) {
450+
String prefix = nsMap.get(getNameSpace(jenaRes.getURI()));
451+
401452
Ontology trgOnto = prefix2onto == null ? null : prefix2onto.get(prefix);
402453
if (trgOnto == null) {
403454
trgOnto = onto;
@@ -406,10 +457,10 @@ private static Resource toResource(org.apache.jena.rdf.model.Resource jenaRes, M
406457
Resource res = new Resource(trgOnto, type);
407458
res.setImported(trgOnto != onto);
408459

409-
String localname = jenaRes.getLocalName();
460+
String localname = getLocalName(jenaRes.getURI());
410461
//sometimes getLocalName does not work; so fix it
411462
if (localname.isEmpty() && !trgOnto.getUri().isEmpty() && jenaRes.getURI().startsWith(trgOnto.getUri())) {
412-
localname = jenaRes.getURI().substring(trgOnto.getUri().length());
463+
localname = jenaRes.getURI().substring(trgOnto.getUriWithFragment().length());
413464
}
414465
res.setLocalname(localname);
415466

@@ -595,6 +646,10 @@ private List<org.apache.jena.rdf.model.Resource> createResources(Set<Resource> s
595646
if (r.hasRange()) {
596647
m.add(jenaRes, RDFS.range, ResourceFactory.createResource(r.getRange().getURI()));
597648
}
649+
650+
for(Statement stmt : r.getAdditionalDomainRangeStatements()) {
651+
m.add(jenaRes, stmt.getPredicate(), stmt.getObject());
652+
}
598653
}
599654

600655
l.add(jenaRes);
@@ -643,6 +698,8 @@ public Model getABoxModel() {
643698
m.setNsPrefix("rdf", RDF.getURI());
644699
m.setNsPrefix("rdfs", RDFS.getURI());
645700

701+
//m.add(skippedABox);
702+
646703
for (List<Resource> l : Arrays.asList(rootClasses)) {
647704
for (Resource r : l) {
648705
for (Resource clazz : r.descendants()) {
@@ -664,13 +721,24 @@ public Model getABoxModel() {
664721
org.apache.jena.rdf.model.Property jenaProperty = ResourceFactory.createProperty(property.getURI());
665722

666723
for(Link link : property.getLinks()) {
724+
667725
org.apache.jena.rdf.model.Resource jenaInstA = ResourceFactory.createResource(link.getSource().getURI());
668726

669727
if(link.getTarget().getType() == Resource.Type.Literal) {
670728

671-
//untyped literal
672729
String literalValue = link.getTarget().getLiteral().get("");
673-
m.add(jenaInstA, jenaProperty, literalValue);
730+
731+
if(link.getTarget().getLiteral().containsKey("datatype")) {
732+
733+
734+
String datatypeURI = link.getTarget().getLiteral().get("datatype");
735+
RDFDatatype dt = TypeMapper.getInstance().getSafeTypeByName(datatypeURI);
736+
m.addLiteral(jenaInstA, jenaProperty, ResourceFactory.createTypedLiteral(literalValue, dt));
737+
738+
} else {
739+
//untyped literal
740+
m.add(jenaInstA, jenaProperty, literalValue);
741+
}
674742

675743
} else {
676744
org.apache.jena.rdf.model.Resource jenaInstB = ResourceFactory.createResource(link.getTarget().getURI());
@@ -763,6 +831,19 @@ public Resource findClassByLocalname(String localname) {
763831
return null;
764832
}
765833

834+
public List<Resource> listClasses() {
835+
List<Resource> result = new ArrayList<>();
836+
837+
for (List<Resource> l : Arrays.asList(rootClasses)) {
838+
for (Resource r : l) {
839+
for (Resource desc : r.descendants()) {
840+
result.add(desc);
841+
}
842+
}
843+
}
844+
return result;
845+
}
846+
766847
public Resource findByUri(String uri) {
767848
for (List<Resource> l : Arrays.asList(rootClasses, rootProperties)) {
768849
for (Resource r : l) {
@@ -830,4 +911,29 @@ public void removeLinksHaving(Resource res) {
830911
}
831912
}
832913
}
914+
915+
/**
916+
* Returns http://.../[localname] or http://...#[localname] of URI.
917+
* @param uri
918+
* @return
919+
*/
920+
public static String getLocalName(String uri) {
921+
int a = uri.lastIndexOf("/");
922+
int b = uri.lastIndexOf("#");
923+
int m = Math.max(a, b);
924+
if(m == -1)
925+
return null;
926+
927+
return uri.substring(m+1, uri.length());
928+
}
929+
930+
public static String getNameSpace(String uri) {
931+
int a = uri.lastIndexOf("/");
932+
int b = uri.lastIndexOf("#");
933+
int m = Math.max(a, b);
934+
if(m == -1)
935+
return null;
936+
937+
return uri.substring(0, m+1);
938+
}
833939
}

0 commit comments

Comments
 (0)