blob: 7bde736fbfdd7f68442e1af2dc0b66b5bd7812ab [file] [log] [blame]
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
// * with the License. You may obtain a copy of the License at *
// * *
// * http://www.apache.org/licenses/LICENSE-2.0 *
// * *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
// * specific language governing permissions and limitations under the License. *
// ***************************************************************************************************************************
package org.apache.juneau.jena;
import static org.apache.juneau.TestUtils.*;
import static org.apache.juneau.jena.RdfCommonContext.*;
import static org.junit.Assert.*;
import java.net.*;
import java.net.URI;
import java.util.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.jena.annotation.*;
import org.apache.juneau.testbeans.*;
import org.apache.juneau.utils.*;
import org.junit.*;
@SuppressWarnings({"serial","javadoc"})
public class CommonTest {
private RdfSerializerBuilder getBasicSerializer() {
return new RdfSerializerBuilder()
.sq()
.useWhitespace(false)
.property(RDF_rdfxml_allowBadUris, true)
.property(RDF_rdfxml_showDoctypeDeclaration, false)
.property(RDF_rdfxml_showXmlDeclaration, false);
}
private String strip(String s) {
return s.replaceFirst("<rdf:RDF[^>]+>\\s*", "").replaceAll("</rdf:RDF>$", "").trim().replaceAll("[\\r\\n]", "");
}
//====================================================================================================
// Trim nulls from beans
//====================================================================================================
@Test
public void testTrimNullsFromBeans() throws Exception {
RdfSerializerBuilder s = getBasicSerializer();
RdfParser p = RdfParser.DEFAULT_XML;
A t1 = A.create(), t2;
s.trimNullProperties(false);
String r = s.build().serialize(t1);
assertEquals("<rdf:Description><jp:s1 rdf:resource='http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'/><jp:s2>s2</jp:s2></rdf:Description>", strip(r));
t2 = p.parse(r, A.class);
assertEqualObjects(t1, t2);
s.trimNullProperties(true);
r = s.build().serialize(t1);
assertEquals("<rdf:Description><jp:s2>s2</jp:s2></rdf:Description>", strip(r));
t2 = p.parse(r, A.class);
assertEqualObjects(t1, t2);
}
public static class A {
public String s1, s2;
public static A create() {
A t = new A();
t.s2 = "s2";
return t;
}
}
//====================================================================================================
// Trim empty maps
//====================================================================================================
@Test
public void testTrimEmptyMaps() throws Exception {
RdfSerializerBuilder s = getBasicSerializer();
RdfParser p = RdfParser.DEFAULT_XML;
B t1 = B.create(), t2;
String r;
s.trimEmptyMaps(false);
r = s.build().serialize(t1);
assertEquals("<rdf:Description><jp:f1 rdf:parseType='Resource'></jp:f1><jp:f2 rdf:parseType='Resource'><jp:f2a rdf:resource='http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'/><jp:f2b rdf:parseType='Resource'><jp:s2>s2</jp:s2></jp:f2b></jp:f2></rdf:Description>", strip(r));
t2 = p.parse(r, B.class);
assertEqualObjects(t1, t2);
s.trimEmptyMaps(true);
r = s.build().serialize(t1);
assertEquals("<rdf:Description><jp:f2 rdf:parseType='Resource'><jp:f2a rdf:resource='http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'/><jp:f2b rdf:parseType='Resource'><jp:s2>s2</jp:s2></jp:f2b></jp:f2></rdf:Description>", strip(r));
t2 = p.parse(r, B.class);
assertNull(t2.f1);
}
public static class B {
public TreeMap<String,A> f1, f2;
public static B create() {
B t = new B();
t.f1 = new TreeMap<String,A>();
t.f2 = new TreeMap<String,A>(){{put("f2a",null);put("f2b",A.create());}};
return t;
}
}
//====================================================================================================
// Trim empty lists
//====================================================================================================
@Test
public void testTrimEmptyLists() throws Exception {
RdfSerializerBuilder s = getBasicSerializer();
RdfParser p = RdfParser.DEFAULT_XML;
C t1 = C.create(), t2;
String r;
s.trimEmptyCollections(false);
r = s.build().serialize(t1);
assertEquals("<rdf:Description><jp:f1><rdf:Seq/></jp:f1><jp:f2><rdf:Seq><rdf:li rdf:resource='http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'/><rdf:li rdf:parseType='Resource'><jp:s2>s2</jp:s2></rdf:li></rdf:Seq></jp:f2></rdf:Description>", strip(r));
t2 = p.parse(r, C.class);
assertEqualObjects(t1, t2);
s.trimEmptyCollections(true);
r = s.build().serialize(t1);
assertEquals("<rdf:Description><jp:f2><rdf:Seq><rdf:li rdf:resource='http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'/><rdf:li rdf:parseType='Resource'><jp:s2>s2</jp:s2></rdf:li></rdf:Seq></jp:f2></rdf:Description>", strip(r));
t2 = p.parse(r, C.class);
assertNull(t2.f1);
t2 = p.parse(r, C.class);
}
public static class C {
public List<A> f1, f2;
public static C create() {
C t = new C();
t.f1 = new AList<A>();
t.f2 = new AList<A>().append(null).append(A.create());
return t;
}
}
//====================================================================================================
// Trim empty arrays
//====================================================================================================
@Test
public void testTrimEmptyArrays() throws Exception {
RdfSerializerBuilder s = getBasicSerializer();
RdfParser p = RdfParser.DEFAULT_XML;
D t1 = D.create(), t2;
String r;
s.trimEmptyCollections(false);
r = s.build().serialize(t1);
assertEquals("<rdf:Description><jp:f1><rdf:Seq/></jp:f1><jp:f2><rdf:Seq><rdf:li rdf:resource='http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'/><rdf:li rdf:parseType='Resource'><jp:s2>s2</jp:s2></rdf:li></rdf:Seq></jp:f2></rdf:Description>", strip(r));
t2 = p.parse(r, D.class);
assertEqualObjects(t1, t2);
s.trimEmptyCollections(true);
r = s.build().serialize(t1);
assertEquals("<rdf:Description><jp:f2><rdf:Seq><rdf:li rdf:resource='http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'/><rdf:li rdf:parseType='Resource'><jp:s2>s2</jp:s2></rdf:li></rdf:Seq></jp:f2></rdf:Description>", strip(r));
t2 = p.parse(r, D.class);
assertNull(t2.f1);
}
public static class D {
public A[] f1, f2;
public static D create() {
D t = new D();
t.f1 = new A[]{};
t.f2 = new A[]{null, A.create()};
return t;
}
}
//====================================================================================================
// @BeanProperty.properties annotation.
//====================================================================================================
@Test
public void testBeanPropertyProperties() throws Exception {
RdfSerializerBuilder s = getBasicSerializer();
RdfParser p = RdfParser.DEFAULT_XML;
E1 t1 = E1.create(), t2;
String r;
r = s.build().serialize(t1);
assertEquals("<rdf:Description><jp:x1 rdf:parseType='Resource'><jp:f1>1</jp:f1></jp:x1><jp:x2 rdf:parseType='Resource'><jp:f1>1</jp:f1></jp:x2><jp:x3><rdf:Seq><rdf:li rdf:parseType='Resource'><jp:f1>1</jp:f1></rdf:li></rdf:Seq></jp:x3><jp:x4><rdf:Seq><rdf:li rdf:parseType='Resource'><jp:f1>1</jp:f1></rdf:li></rdf:Seq></jp:x4><jp:x5><rdf:Seq><rdf:li rdf:parseType='Resource'><jp:f1>1</jp:f1></rdf:li></rdf:Seq></jp:x5><jp:x6><rdf:Seq><rdf:li rdf:parseType='Resource'><jp:f1>1</jp:f1></rdf:li></rdf:Seq></jp:x6></rdf:Description>", strip(r));
t2 = p.parse(r, E1.class);
assertEqualObjects(t1, t2);
}
public static class E1 {
@BeanProperty(properties="f1") public E2 x1;
@BeanProperty(properties="f1") public Map<String,Integer> x2;
@BeanProperty(properties="f1") public E2[] x3;
@BeanProperty(properties="f1") public List<E2> x4;
@BeanProperty(properties="f1") public ObjectMap[] x5;
@BeanProperty(properties="f1") public List<ObjectMap> x6;
public static E1 create() {
E1 t = new E1();
t.x1 = new E2();
t.x2 = new AMap<String,Integer>().append("f1",1).append("f2",2);
t.x3 = new E2[] {new E2()};
t.x4 = new AList<E2>().append(new E2());
t.x5 = new ObjectMap[] {new ObjectMap().append("f1","1").append("f2","2")};
t.x6 = new AList<ObjectMap>().append(new ObjectMap().append("f1","1").append("f2","2"));
return t;
}
}
public static class E2 {
public int f1 = 1;
public int f2 = 2;
}
//====================================================================================================
// @BeanProperty.properties annotation on list of beans.
//====================================================================================================
@Test
public void testBeanPropertyProperiesOnListOfBeans() throws Exception {
RdfSerializerBuilder s = getBasicSerializer();
RdfParser p = RdfParser.DEFAULT_XML;
List<F> l1 = new LinkedList<F>(), l2;
F t = F.create();
t.x1.add(F.create());
l1.add(t);
String r = s.build().serialize(l1);
assertEquals("<rdf:Seq><rdf:li rdf:parseType='Resource'><jp:x1><rdf:Seq><rdf:li rdf:parseType='Resource'><jp:x2>2</jp:x2></rdf:li></rdf:Seq></jp:x1><jp:x2>2</jp:x2></rdf:li></rdf:Seq>", strip(r));
l2 = p.parse(r, LinkedList.class, F.class);
assertEqualObjects(l1, l2);
}
public static class F {
@BeanProperty(properties="x2") public List<F> x1;
public int x2;
public static F create() {
F t = new F();
t.x1 = new LinkedList<F>();
t.x2 = 2;
return t;
}
}
//====================================================================================================
// Test URIAttr - Test that URLs and URIs are serialized and parsed correctly.
//====================================================================================================
@Test
public void testURIAttr() throws Exception {
RdfSerializerBuilder s = getBasicSerializer();
RdfParser p = RdfParser.DEFAULT_XML;
G t = new G();
t.uri = new URI("http://uri");
t.f1 = new URI("http://f1");
t.f2 = new URL("http://f2");
String xml = s.build().serialize(t);
t = p.parse(xml, G.class);
assertEquals("http://uri", t.uri.toString());
assertEquals("http://f1", t.f1.toString());
assertEquals("http://f2", t.f2.toString());
}
public static class G {
@Rdf(beanUri=true) public URI uri;
public URI f1;
public URL f2;
}
//====================================================================================================
// Test URIs with URI_CONTEXT and URI_AUTHORITY
//====================================================================================================
@Test
public void testUris() throws Exception {
RdfSerializerBuilder s = getBasicSerializer();
TestURI t = new TestURI();
String r;
String expected = "";
s.relativeUriBase(null);
r = stripAndSort(s.build().serialize(t));
expected = ""
+"</rdf:Description>>"
+"\n<<rdf:Description rdf:about='f0/x0'>"
+"\n<jp:f1 rdf:resource='f1/x1'/>"
+"\n<jp:f2 rdf:resource='/f2/x2'/>"
+"\n<jp:f3 rdf:resource='http://www.apache.org/f3/x3'/>"
+"\n<jp:f4 rdf:resource='f4/x4'/>"
+"\n<jp:f5 rdf:resource='/f5/x5'/>"
+"\n<jp:f6 rdf:resource='http://www.apache.org/f6/x6'/>"
+"\n<jp:f7 rdf:resource='http://www.apache.org/f7/x7'/>"
+"\n<jp:f8 rdf:resource='f8/x8'/>"
+"\n<jp:f9 rdf:resource='f9/x9'/>"
+"\n<jp:fa>http://www.apache.org/fa/xa#MY_LABEL</jp:fa>"
+"\n<jp:fb>http://www.apache.org/fb/xb?label=MY_LABEL&amp;foo=bar</jp:fb>"
+"\n<jp:fc>http://www.apache.org/fc/xc?foo=bar&amp;label=MY_LABEL</jp:fc>"
+"\n<jp:fd>http://www.apache.org/fd/xd?label2=MY_LABEL&amp;foo=bar</jp:fd>"
+"\n<jp:fe>http://www.apache.org/fe/xe?foo=bar&amp;label2=MY_LABEL</jp:fe>"
;
assertEquals(expected, r);
s.relativeUriBase(""); // Same as null.
r = stripAndSort(s.build().serialize(t));
assertEquals(expected, r);
s.relativeUriBase("/cr");
r = stripAndSort(s.build().serialize(t));
expected = ""
+"</rdf:Description>>"
+"\n<<rdf:Description rdf:about='/cr/f0/x0'>"
+"\n<jp:f1 rdf:resource='/cr/f1/x1'/>"
+"\n<jp:f2 rdf:resource='/f2/x2'/>"
+"\n<jp:f3 rdf:resource='http://www.apache.org/f3/x3'/>"
+"\n<jp:f4 rdf:resource='/cr/f4/x4'/>"
+"\n<jp:f5 rdf:resource='/f5/x5'/>"
+"\n<jp:f6 rdf:resource='http://www.apache.org/f6/x6'/>"
+"\n<jp:f7 rdf:resource='http://www.apache.org/f7/x7'/>"
+"\n<jp:f8 rdf:resource='/cr/f8/x8'/>"
+"\n<jp:f9 rdf:resource='/cr/f9/x9'/>"
+"\n<jp:fa>http://www.apache.org/fa/xa#MY_LABEL</jp:fa>"
+"\n<jp:fb>http://www.apache.org/fb/xb?label=MY_LABEL&amp;foo=bar</jp:fb>"
+"\n<jp:fc>http://www.apache.org/fc/xc?foo=bar&amp;label=MY_LABEL</jp:fc>"
+"\n<jp:fd>http://www.apache.org/fd/xd?label2=MY_LABEL&amp;foo=bar</jp:fd>"
+"\n<jp:fe>http://www.apache.org/fe/xe?foo=bar&amp;label2=MY_LABEL</jp:fe>"
;
assertEquals(expected, r);
s.relativeUriBase("/cr/"); // Same as above
r = stripAndSort(s.build().serialize(t));
assertEquals(expected, r);
s.relativeUriBase("/");
r = stripAndSort(s.build().serialize(t));
expected = ""
+"</rdf:Description>>"
+"\n<<rdf:Description rdf:about='/f0/x0'>"
+"\n<jp:f1 rdf:resource='/f1/x1'/>"
+"\n<jp:f2 rdf:resource='/f2/x2'/>"
+"\n<jp:f3 rdf:resource='http://www.apache.org/f3/x3'/>"
+"\n<jp:f4 rdf:resource='/f4/x4'/>"
+"\n<jp:f5 rdf:resource='/f5/x5'/>"
+"\n<jp:f6 rdf:resource='http://www.apache.org/f6/x6'/>"
+"\n<jp:f7 rdf:resource='http://www.apache.org/f7/x7'/>"
+"\n<jp:f8 rdf:resource='/f8/x8'/>"
+"\n<jp:f9 rdf:resource='/f9/x9'/>"
+"\n<jp:fa>http://www.apache.org/fa/xa#MY_LABEL</jp:fa>"
+"\n<jp:fb>http://www.apache.org/fb/xb?label=MY_LABEL&amp;foo=bar</jp:fb>"
+"\n<jp:fc>http://www.apache.org/fc/xc?foo=bar&amp;label=MY_LABEL</jp:fc>"
+"\n<jp:fd>http://www.apache.org/fd/xd?label2=MY_LABEL&amp;foo=bar</jp:fd>"
+"\n<jp:fe>http://www.apache.org/fe/xe?foo=bar&amp;label2=MY_LABEL</jp:fe>"
;
assertEquals(expected, r);
s.relativeUriBase(null);
s.absolutePathUriBase("http://foo");
r = stripAndSort(s.build().serialize(t));
expected = ""
+"</rdf:Description>>"
+"\n<<rdf:Description rdf:about='f0/x0'>"
+"\n<jp:f1 rdf:resource='f1/x1'/>"
+"\n<jp:f2 rdf:resource='http://foo/f2/x2'/>"
+"\n<jp:f3 rdf:resource='http://www.apache.org/f3/x3'/>"
+"\n<jp:f4 rdf:resource='f4/x4'/>"
+"\n<jp:f5 rdf:resource='http://foo/f5/x5'/>"
+"\n<jp:f6 rdf:resource='http://www.apache.org/f6/x6'/>"
+"\n<jp:f7 rdf:resource='http://www.apache.org/f7/x7'/>"
+"\n<jp:f8 rdf:resource='f8/x8'/>"
+"\n<jp:f9 rdf:resource='f9/x9'/>"
+"\n<jp:fa>http://www.apache.org/fa/xa#MY_LABEL</jp:fa>"
+"\n<jp:fb>http://www.apache.org/fb/xb?label=MY_LABEL&amp;foo=bar</jp:fb>"
+"\n<jp:fc>http://www.apache.org/fc/xc?foo=bar&amp;label=MY_LABEL</jp:fc>"
+"\n<jp:fd>http://www.apache.org/fd/xd?label2=MY_LABEL&amp;foo=bar</jp:fd>"
+"\n<jp:fe>http://www.apache.org/fe/xe?foo=bar&amp;label2=MY_LABEL</jp:fe>"
;
assertEquals(expected, r);
s.absolutePathUriBase("http://foo/");
r = stripAndSort(s.build().serialize(t));
assertEquals(expected, r);
s.absolutePathUriBase(""); // Same as null.
r = stripAndSort(s.build().serialize(t));
expected = ""
+"</rdf:Description>>"
+"\n<<rdf:Description rdf:about='f0/x0'>"
+"\n<jp:f1 rdf:resource='f1/x1'/>"
+"\n<jp:f2 rdf:resource='/f2/x2'/>"
+"\n<jp:f3 rdf:resource='http://www.apache.org/f3/x3'/>"
+"\n<jp:f4 rdf:resource='f4/x4'/>"
+"\n<jp:f5 rdf:resource='/f5/x5'/>"
+"\n<jp:f6 rdf:resource='http://www.apache.org/f6/x6'/>"
+"\n<jp:f7 rdf:resource='http://www.apache.org/f7/x7'/>"
+"\n<jp:f8 rdf:resource='f8/x8'/>"
+"\n<jp:f9 rdf:resource='f9/x9'/>"
+"\n<jp:fa>http://www.apache.org/fa/xa#MY_LABEL</jp:fa>"
+"\n<jp:fb>http://www.apache.org/fb/xb?label=MY_LABEL&amp;foo=bar</jp:fb>"
+"\n<jp:fc>http://www.apache.org/fc/xc?foo=bar&amp;label=MY_LABEL</jp:fc>"
+"\n<jp:fd>http://www.apache.org/fd/xd?label2=MY_LABEL&amp;foo=bar</jp:fd>"
+"\n<jp:fe>http://www.apache.org/fe/xe?foo=bar&amp;label2=MY_LABEL</jp:fe>"
;
assertEquals(expected, r);
}
private String stripAndSort(String s) {
s = strip(s);
Set<String> set = new TreeSet<String>();
for (String s2 : s.split("><"))
set.add('<' + s2 + '>');
return StringUtils.join(set, "\n");
}
//====================================================================================================
// Recursion
//====================================================================================================
@Test
public void testRecursion() throws Exception {
RdfSerializerBuilder s = new RdfSerializerBuilder().xmlabbrev().sq();
R1 r1 = new R1();
R2 r2 = new R2();
R3 r3 = new R3();
r1.r2 = r2;
r2.r3 = r3;
r3.r1 = r1;
// No recursion detection
try {
s.build().serialize(r1);
fail("Exception expected!");
} catch (Exception e) {
String msg = e.getLocalizedMessage();
assertTrue(msg.contains("It's recommended you use the SerializerContext.SERIALIZER_detectRecursions setting to help locate the loop."));
}
// Recursion detection, no ignore
s.detectRecursions(true);
try {
s.build().serialize(r1);
fail("Exception expected!");
} catch (Exception e) {
String msg = e.getLocalizedMessage();
assertTrue(msg.contains("[0]root:org.apache.juneau.jena.CommonTest$R1"));
assertTrue(msg.contains("->[1]r2:org.apache.juneau.jena.CommonTest$R2"));
assertTrue(msg.contains("->[2]r3:org.apache.juneau.jena.CommonTest$R3"));
assertTrue(msg.contains("->[3]r1:org.apache.juneau.jena.CommonTest$R1"));
}
s.ignoreRecursions(true);
String r = s.build().serialize(r1).replace("\r", "");
// Note...the order of the namespaces is not always the same depending on the JVM.
// The Jena libraries appear to use a hashmap for these.
assertTrue(r.contains(
"<rdf:Description>\n"+
"<jp:name>foo</jp:name>\n"+
"<jp:r2 rdf:parseType='Resource'>\n"+
"<jp:name>bar</jp:name>\n"+
"<jp:r3 rdf:parseType='Resource'>\n"+
"<jp:name>baz</jp:name>\n"+
"</jp:r3>\n"+
"</jp:r2>\n"+
"</rdf:Description>\n"+
"</rdf:RDF>\n"
));
assertTrue(r.contains("xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#"));
assertTrue(r.contains("xmlns:j='http://www.apache.org/juneau/"));
assertTrue(r.contains("xmlns:jp='http://www.apache.org/juneaubp/"));
}
public static class R1 {
public String name = "foo";
public R2 r2;
}
public static class R2 {
public String name = "bar";
public R3 r3;
}
public static class R3 {
public String name = "baz";
public R1 r1;
}
}