1313import java .io .InputStream ;
1414import java .io .InputStreamReader ;
1515import java .io .OutputStreamWriter ;
16+ import java .io .StringReader ;
1617import java .net .URISyntaxException ;
1718import java .text .SimpleDateFormat ;
1819import java .util .ArrayList ;
1920import java .util .Arrays ;
2021import java .util .Collection ;
2122import java .util .Collections ;
23+ import java .util .Comparator ;
2224import java .util .Date ;
2325import java .util .Iterator ;
2426import java .util .LinkedHashMap ;
2527import java .util .List ;
2628import java .util .Map ;
29+ import java .util .Set ;
30+ import java .util .TreeSet ;
2731
2832import org .junit .AfterClass ;
2933import org .junit .BeforeClass ;
3034import org .junit .Test ;
3135import org .junit .runner .RunWith ;
3236import org .junit .runners .Parameterized ;
3337import org .junit .runners .Parameterized .Parameters ;
38+ import org .openrdf .model .BNode ;
39+ import org .openrdf .model .Literal ;
40+ import org .openrdf .model .Statement ;
41+ import org .openrdf .model .URI ;
42+ import org .openrdf .model .Value ;
43+ import org .openrdf .model .impl .ValueFactoryImpl ;
44+ import org .openrdf .model .util .ModelUtil ;
45+ import org .openrdf .rio .ParserConfig ;
46+ import org .openrdf .rio .RDFFormat ;
47+ import org .openrdf .rio .RDFParseException ;
48+ import org .openrdf .rio .Rio ;
49+ import org .openrdf .rio .helpers .BasicParserSettings ;
50+ import org .openrdf .rio .helpers .ParseErrorCollector ;
3451
3552import com .fasterxml .jackson .core .JsonGenerationException ;
3653import com .fasterxml .jackson .databind .JsonMappingException ;
@@ -421,8 +438,8 @@ public void runTest() throws URISyntaxException, IOException, JSONLDProcessingEr
421438 .get ("useRdfType" );
422439 }
423440 if (((Map <String , Object >) test .get ("option" )).containsKey ("useNativeTypes" )) {
424- options .useNativeTypes = (Boolean ) ((Map <String , Object >) test . get ( "option" ))
425- .get ("useNativeTypes" );
441+ options .useNativeTypes = (Boolean ) ((Map <String , Object >) test
442+ .get ("option" )). get ( " useNativeTypes" );
426443 }
427444 }
428445 result = JSONLD .fromRDF (input , options );
@@ -437,9 +454,42 @@ public void runTest() throws URISyntaxException, IOException, JSONLDProcessingEr
437454
438455 Boolean testpassed = false ;
439456 try {
440- // TODO: for tests that are supposed to fail, a more detailed check
441- // that it failed in the right way is needed
442- testpassed = Obj .equals (expect , result ) || failure_expected ;
457+ if (options .format != null && options .format .equals ("application/nquads" )) {
458+ if (expect instanceof String && result instanceof String ) {
459+ ParseErrorCollector expectedErrors = new ParseErrorCollector ();
460+ ParseErrorCollector resultErrors = new ParseErrorCollector ();
461+ ParserConfig parserConfig = new ParserConfig ();
462+ parserConfig .addNonFatalError (BasicParserSettings .VERIFY_DATATYPE_VALUES );
463+ parserConfig .addNonFatalError (BasicParserSettings .VERIFY_LANGUAGE_TAGS );
464+ Set <Statement > expectedModel = new TreeSet <Statement >(
465+ new ContextInsensitiveStatementComparator ());
466+ Set <Statement > resultModel = new TreeSet <Statement >(
467+ new ContextInsensitiveStatementComparator ());
468+ try {
469+ expectedModel .addAll (Rio .parse (new StringReader ((String ) expect ),
470+ options .base , RDFFormat .NQUADS , parserConfig ,
471+ ValueFactoryImpl .getInstance (), expectedErrors ));
472+ resultModel .addAll (Rio .parse (new StringReader ((String ) result ),
473+ options .base , RDFFormat .NQUADS , parserConfig ,
474+ ValueFactoryImpl .getInstance (), resultErrors ));
475+ testpassed = ModelUtil .equals (expectedModel , resultModel );
476+ } catch (RDFParseException e ) {
477+ // Sesame cannot handle blank node predicates, so try to
478+ // do a check using our N-Quads parser that can
479+ testpassed = Obj .equals (expect , result ) || failure_expected ;
480+ if (!testpassed ) {
481+ e .printStackTrace ();
482+ }
483+ }
484+ } else {
485+ testpassed = Obj .equals (expect , result ) || failure_expected ;
486+ }
487+ } else {
488+ // TODO: for tests that are supposed to fail, a more detailed
489+ // check
490+ // that it failed in the right way is needed
491+ testpassed = Obj .equals (expect , result ) || failure_expected ;
492+ }
443493 if (testpassed == false ) {
444494 // System.out.println("failed test!!! details:");
445495 // jsonDiff("/", expect, result);
@@ -563,4 +613,132 @@ else if (expect instanceof List && result instanceof List) {
563613 }
564614 }
565615 }
616+
617+ private static class ContextInsensitiveStatementComparator implements Comparator <Statement > {
618+ public final static int BEFORE = -1 ;
619+ public final static int EQUALS = 0 ;
620+ public final static int AFTER = 1 ;
621+
622+ @ Override
623+ public int compare (Statement first , Statement second ) {
624+ if (first == second ) {
625+ return EQUALS ;
626+ }
627+
628+ if (first .getSubject ().equals (second .getSubject ())) {
629+ if (first .getPredicate ().equals (second .getPredicate ())) {
630+ if (first .getObject ().equals (second .getObject ())) {
631+ return EQUALS ;
632+ } else {
633+ return new ValueComparator ().compare (first .getObject (), second .getObject ());
634+ }
635+ } else {
636+ return new ValueComparator ().compare (first .getPredicate (),
637+ second .getPredicate ());
638+ }
639+ } else {
640+ return new ValueComparator ().compare (first .getSubject (), second .getSubject ());
641+ }
642+ }
643+
644+ }
645+
646+ private static class ValueComparator implements Comparator <Value > {
647+ public final static int BEFORE = -1 ;
648+ public final static int EQUALS = 0 ;
649+ public final static int AFTER = 1 ;
650+
651+ /**
652+ * Sorts in the order nulls>BNodes>URIs>Literals
653+ * <p/>
654+ * This is due to the fact that nulls are only applicable to contexts,
655+ * and according to the OpenRDF documentation, the type of the null
656+ * cannot be sufficiently distinguished from any other Value to make an
657+ * intelligent comparison to other Values
658+ * <p/>
659+ * http://www.openrdf.org/doc/sesame2/api/org/openrdf/OpenRDFUtil.html#
660+ * verifyContextNotNull(org.openrdf.model.Resource...)
661+ * <p/>
662+ * BNodes are sorted according to the lexical compare of their
663+ * identifiers, which provides a way to sort statements with the same
664+ * BNodes in the same positions, near each other
665+ * <p/>
666+ * BNode sorting is not specified across sessions
667+ */
668+ @ Override
669+ public int compare (Value first , Value second ) {
670+ if (first == null ) {
671+ if (second == null ) {
672+ return EQUALS ;
673+ } else {
674+ return BEFORE ;
675+ }
676+ } else if (second == null ) {
677+ // always sort null Values before others, so if the second is
678+ // null, but the first wasn't, sort the first after the second
679+ return AFTER ;
680+ }
681+
682+ if (first == second || first .equals (second )) {
683+ return EQUALS ;
684+ }
685+
686+ if (first instanceof BNode ) {
687+ if (second instanceof BNode ) {
688+ // if both are BNodes, sort based on the lexical value of
689+ // the internal ID
690+ // Although this sorting is not guaranteed to be consistent
691+ // across sessions,
692+ // it provides a consistent sorting of statements in every
693+ // case
694+ // so that statements with the same BNode are sorted near
695+ // each other
696+ return ((BNode ) first ).getID ().compareTo (((BNode ) second ).getID ());
697+ } else {
698+ return BEFORE ;
699+ }
700+ } else if (second instanceof BNode ) {
701+ // sort BNodes before other things, and first was not a BNode
702+ return AFTER ;
703+ } else if (first instanceof URI ) {
704+ if (second instanceof URI ) {
705+ return ((URI ) first ).stringValue ().compareTo (((URI ) second ).stringValue ());
706+ } else {
707+ return BEFORE ;
708+ }
709+ } else if (second instanceof URI ) {
710+ // sort URIs before Literals
711+ return AFTER ;
712+ }
713+ // they must both be Literal's, so sort based on the lexical value
714+ // of the Literal
715+ else {
716+ int cmp = first .stringValue ().compareTo (second .stringValue ());
717+
718+ if (EQUALS == cmp ) {
719+ URI firstType = ((Literal ) first ).getDatatype ();
720+ URI secondType = ((Literal ) second ).getDatatype ();
721+ if (null == firstType ) {
722+ if (null == secondType ) {
723+ String firstLang = ((Literal ) first ).getLanguage ();
724+ String secondLang = ((Literal ) second ).getLanguage ();
725+
726+ return null == firstLang ? (null == secondLang ? EQUALS : BEFORE )
727+ : (null == secondLang ? AFTER : firstLang .compareTo (secondLang ));
728+ } else {
729+ return BEFORE ;
730+ }
731+ } else {
732+ if (null == secondType ) {
733+ return AFTER ;
734+ } else {
735+ return firstType .stringValue ().compareTo (secondType .stringValue ());
736+ }
737+ }
738+ } else {
739+ return cmp ;
740+ }
741+ }
742+ }
743+ }
566744}
0 commit comments