2020import java .util .Queue ;
2121import java .util .Set ;
2222import org .apache .commons .io .FilenameUtils ;
23+ import org .apache .jena .datatypes .RDFDatatype ;
24+ import org .apache .jena .datatypes .TypeMapper ;
2325import org .apache .jena .rdf .model .Literal ;
2426import org .apache .jena .rdf .model .Model ;
2527import org .apache .jena .rdf .model .ModelFactory ;
2628import org .apache .jena .rdf .model .Property ;
2729import org .apache .jena .rdf .model .RDFNode ;
2830import org .apache .jena .rdf .model .ResourceFactory ;
2931import org .apache .jena .rdf .model .Statement ;
32+ import org .apache .jena .shared .PrefixMapping ;
33+ import org .apache .jena .shared .impl .PrefixMappingImpl ;
3034import org .apache .jena .vocabulary .OWL ;
3135import org .apache .jena .vocabulary .RDF ;
3236import 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