From c64f01414f8babf8f583dc9fcd56d078926f1f0f Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 2 May 2012 13:48:50 +0200 Subject: [PATCH] DATACMNS-164 - Added support for XML/JSON marshaling of Page, Pageable and Sort. Added XmlTypeAdapter implementations that convert the PageImpl, PageRequest and Sort value objects into a JAXB marshalable object. --- spring-data-commons-core/pom.xml | 14 + .../data/domain/PageRequest.java | 2 +- .../data/domain/jaxb/OrderAdapter.java | 57 +++++ .../data/domain/jaxb/PageAdapter.java | 70 +++++ .../data/domain/jaxb/PageableAdapter.java | 70 +++++ .../data/domain/jaxb/SortAdapter.java | 42 +++ .../data/domain/jaxb/SpringDataJaxb.java | 153 +++++++++++ .../data/domain/jaxb/package-info.java | 21 ++ .../springframework/data/domain/jaxb/atom.xsd | 240 ++++++++++++++++++ .../data/domain/jaxb/spring-data-jaxb.xsd | 52 ++++ .../domain/jaxb/SpringDataJaxbUnitTests.java | 160 ++++++++++++ .../data/domain/jaxb/jaxb.index | 3 + .../data/domain/jaxb/pageable.xml | 13 + spring-data-commons-core/template.mf | 2 + spring-data-commons-parent/pom.xml | 1 + 15 files changed, 899 insertions(+), 1 deletion(-) create mode 100644 spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/OrderAdapter.java create mode 100644 spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/PageAdapter.java create mode 100644 spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/PageableAdapter.java create mode 100644 spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/SortAdapter.java create mode 100644 spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/SpringDataJaxb.java create mode 100644 spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/package-info.java create mode 100644 spring-data-commons-core/src/main/resources/org/springframework/data/domain/jaxb/atom.xsd create mode 100644 spring-data-commons-core/src/main/resources/org/springframework/data/domain/jaxb/spring-data-jaxb.xsd create mode 100644 spring-data-commons-core/src/test/java/org/springframework/data/domain/jaxb/SpringDataJaxbUnitTests.java create mode 100644 spring-data-commons-core/src/test/resources/org/springframework/data/domain/jaxb/jaxb.index create mode 100644 spring-data-commons-core/src/test/resources/org/springframework/data/domain/jaxb/pageable.xml diff --git a/spring-data-commons-core/pom.xml b/spring-data-commons-core/pom.xml index cfc37809b..306818520 100644 --- a/spring-data-commons-core/pom.xml +++ b/spring-data-commons-core/pom.xml @@ -130,6 +130,20 @@ ${webbeans.version} test + + + org.springframework.hateoas + spring-hateoas + ${org.springframework.hateoas.version} + true + + + + com.sun.xml.bind + jaxb-impl + 2.2.3U1 + test + diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/domain/PageRequest.java b/spring-data-commons-core/src/main/java/org/springframework/data/domain/PageRequest.java index 507d36327..621937e88 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/domain/PageRequest.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/domain/PageRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2010 the original author or authors. + * Copyright 2008-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/OrderAdapter.java b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/OrderAdapter.java new file mode 100644 index 000000000..254ead4a7 --- /dev/null +++ b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/OrderAdapter.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed 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.springframework.data.domain.jaxb; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +import org.springframework.data.domain.Sort.Order; +import org.springframework.data.domain.jaxb.SpringDataJaxb.OrderDto; + +/** + * XmlAdapter to convert {@link Order} instances into {@link OrderDto}s and vice versa. + * + * @author Oliver Gierke + */ +public class OrderAdapter extends XmlAdapter { + + public static final OrderAdapter INSTANCE = new OrderAdapter(); + + /* + * (non-Javadoc) + * @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object) + */ + @Override + public OrderDto marshal(Order order) throws Exception { + + if (order == null) { + return null; + } + + OrderDto dto = new OrderDto(); + dto.direction = order.getDirection(); + dto.property = order.getProperty(); + return dto; + } + + /* + * (non-Javadoc) + * @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object) + */ + @Override + public Order unmarshal(OrderDto source) throws Exception { + return source == null ? null : new Order(source.direction, source.property); + } +} diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/PageAdapter.java b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/PageAdapter.java new file mode 100644 index 000000000..82847a202 --- /dev/null +++ b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/PageAdapter.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed 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.springframework.data.domain.jaxb; + +import java.util.Collections; +import java.util.List; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.jaxb.SpringDataJaxb.PageDto; +import org.springframework.hateoas.Link; + +/** + * {@link XmlAdapter} to convert {@link Page} instances into {@link PageDto} instances and vice versa. + * + * @author Oliver Gierke + */ +public class PageAdapter extends XmlAdapter> { + + /* + * (non-Javadoc) + * @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object) + */ + @Override + public PageDto marshal(Page source) throws Exception { + + if (source == null) { + return null; + } + + PageDto dto = new PageDto(); + dto.content = source.getContent(); + dto.add(getLinks(source)); + + return dto; + } + + /* + * (non-Javadoc) + * @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object) + */ + @Override + public Page unmarshal(PageDto v) throws Exception { + return null; + } + + /** + * Return additional links that shall be added to the {@link PageDto}. + * + * @param source the source {@link Page}. + * @return + */ + protected List getLinks(Page source) { + return Collections.emptyList(); + } +} diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/PageableAdapter.java b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/PageableAdapter.java new file mode 100644 index 000000000..1a205bf11 --- /dev/null +++ b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/PageableAdapter.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed 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.springframework.data.domain.jaxb; + +import java.util.Collections; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.jaxb.SpringDataJaxb.OrderDto; +import org.springframework.data.domain.jaxb.SpringDataJaxb.PageRequestDto; +import org.springframework.data.domain.jaxb.SpringDataJaxb.SortDto; + +/** + * {@link XmlAdapter} to convert {@link Pageable} instances int a {@link PageRequestDto} and vice versa. + * + * @author Oliver Gierke + */ +class PageableAdapter extends XmlAdapter { + + /* + * (non-Javadoc) + * @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object) + */ + @Override + public PageRequestDto marshal(Pageable request) throws Exception { + + SortDto sortDto = SortAdapter.INSTANCE.marshal(request.getSort()); + + PageRequestDto dto = new PageRequestDto(); + dto.orders = sortDto == null ? Collections. emptyList() : sortDto.orders; + dto.page = request.getPageNumber(); + dto.size = request.getPageSize(); + + return dto; + } + + /* + * (non-Javadoc) + * @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object) + */ + @Override + public Pageable unmarshal(PageRequestDto v) throws Exception { + + if (v.orders.isEmpty()) { + return new PageRequest(v.page, v.size); + } + + SortDto sortDto = new SortDto(); + sortDto.orders = v.orders; + Sort sort = SortAdapter.INSTANCE.unmarshal(sortDto); + + return new PageRequest(v.page, v.size, sort); + } +} diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/SortAdapter.java b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/SortAdapter.java new file mode 100644 index 000000000..3113bc6f7 --- /dev/null +++ b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/SortAdapter.java @@ -0,0 +1,42 @@ +package org.springframework.data.domain.jaxb; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.jaxb.SpringDataJaxb.SortDto; + +/** + * {@link XmlAdapter} to convert {@link Sort} instances into {@link SortDto} instances and vice versa. + * + * @author Oliver Gierke + */ +public class SortAdapter extends XmlAdapter { + + public static final SortAdapter INSTANCE = new SortAdapter(); + + /* + * (non-Javadoc) + * @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object) + */ + @Override + public SortDto marshal(Sort source) throws Exception { + + if (source == null) { + return null; + } + + SortDto dto = new SortDto(); + dto.orders = SpringDataJaxb.marshal(source, OrderAdapter.INSTANCE); + + return dto; + } + + /* + * (non-Javadoc) + * @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object) + */ + @Override + public Sort unmarshal(SortDto source) throws Exception { + return source == null ? null : new Sort(SpringDataJaxb.unmarshal(source.orders, OrderAdapter.INSTANCE)); + } +} diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/SpringDataJaxb.java b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/SpringDataJaxb.java new file mode 100644 index 000000000..c529aeb9d --- /dev/null +++ b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/SpringDataJaxb.java @@ -0,0 +1,153 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed 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.springframework.data.domain.jaxb; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAnyElement; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.adapters.XmlAdapter; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Sort.Direction; +import org.springframework.data.domain.Sort.Order; +import org.springframework.hateoas.ResourceSupport; +import org.springframework.util.Assert; + +/** + * Helper class containing utility methods to implement JAXB {@link XmlAdapter}s as well as the DTO types to be + * marshalled by JAXB. + * + * @author Oliver Gierke + */ +public class SpringDataJaxb { + + public static final String NAMESPACE = "http://www.springframework.org/schema/data/jaxb"; + + /** + * The DTO for {@link Pageable}s/{@link PageRequest}s. + * + * @author Oliver Gierke + */ + @XmlRootElement(name = "page-request", namespace = NAMESPACE) + @XmlAccessorType(XmlAccessType.FIELD) + public static class PageRequestDto { + + @XmlAttribute + int page, size; + @XmlElement(name = "order", namespace = NAMESPACE) + List orders = new ArrayList(); + } + + /** + * The DTO for {@link Sort}. + * + * @author Oliver Gierke + */ + @XmlRootElement(name = "sort", namespace = NAMESPACE) + @XmlAccessorType(XmlAccessType.FIELD) + public static class SortDto { + + @XmlElement(name = "order", namespace = SpringDataJaxb.NAMESPACE) + List orders = new ArrayList(); + } + + /** + * The DTO for {@link Order}. + * + * @author Oliver Gierke + */ + @XmlRootElement(name = "order", namespace = NAMESPACE) + @XmlAccessorType(XmlAccessType.FIELD) + public static class OrderDto { + + @XmlAttribute + String property; + @XmlAttribute + Direction direction; + } + + /** + * The DTO for {@link Page}. + * + * @author Oliver Gierke + */ + @XmlRootElement(name = "page", namespace = NAMESPACE) + @XmlAccessorType(XmlAccessType.FIELD) + public static class PageDto extends ResourceSupport { + + @XmlAnyElement + @XmlElementWrapper(name = "content") + List content; + } + + /** + * Unmarshals each element of the given {@link Collection} using the given {@link XmlAdapter}. + * + * @param source + * @param adapter must not be {@literal null}. + * @return + * @throws Exception + */ + public static List unmarshal(Collection source, XmlAdapter adapter) throws Exception { + + Assert.notNull(adapter); + + if (source == null || source.isEmpty()) { + return Collections.emptyList(); + } + + List result = new ArrayList(source.size()); + for (S element : source) { + result.add(adapter.unmarshal(element)); + } + return result; + } + + /** + * Marshals each of the elements of the given {@link Iterable} using the given {@link XmlAdapter}. + * + * @param source + * @param adapter must not be {@literal null}. + * @return + * @throws Exception + */ + public static List marshal(Iterable source, XmlAdapter adapter) throws Exception { + + Assert.notNull(adapter); + + if (source == null) { + return Collections.emptyList(); + } + + List result = new ArrayList(); + for (T element : source) { + result.add(adapter.marshal(element)); + } + return result; + } +} diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/package-info.java b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/package-info.java new file mode 100644 index 000000000..2a74e51bc --- /dev/null +++ b/spring-data-commons-core/src/main/java/org/springframework/data/domain/jaxb/package-info.java @@ -0,0 +1,21 @@ +/** + * Central domain abstractions especially to be used in combination with the {@link org.springframework.data.repository.Repository} abstraction. + * + * @see org.springframework.data.repository.Repository + */ +@XmlSchema(xmlns = { @XmlNs(prefix = "sd", namespaceURI = org.springframework.data.domain.jaxb.SpringDataJaxb.NAMESPACE) }) +@XmlJavaTypeAdapters({ + @XmlJavaTypeAdapter(value = org.springframework.data.domain.jaxb.PageableAdapter.class, type = Pageable.class), + @XmlJavaTypeAdapter(value = org.springframework.data.domain.jaxb.SortAdapter.class, type = Sort.class), + @XmlJavaTypeAdapter(value = org.springframework.data.domain.jaxb.PageAdapter.class, type = Page.class) }) +package org.springframework.data.domain.jaxb; + +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + diff --git a/spring-data-commons-core/src/main/resources/org/springframework/data/domain/jaxb/atom.xsd b/spring-data-commons-core/src/main/resources/org/springframework/data/domain/jaxb/atom.xsd new file mode 100644 index 000000000..fc606ba37 --- /dev/null +++ b/spring-data-commons-core/src/main/resources/org/springframework/data/domain/jaxb/atom.xsd @@ -0,0 +1,240 @@ + + + + + This version of the Atom schema is based on version 1.0 of the format specifications, + found here http://www.atomenabled.org/developers/syndication/atom-format-spec.php. + + + + + + An Atom document may have two root elements, feed and entry, as defined in section 2. + + + + + + + + The Atom text construct is defined in section 3.1 of the format spec. + + + + + + + + + + + + + + + + + + + + The Atom person construct is defined in section 3.2 of the format spec. + + + + + + + + + + + + + + Schema definition for an email address. + + + + + + + + + + The Atom feed construct is defined in section 4.1.1 of the format spec. + + + + + + + + + + + + + + + + + + + + + + + + The Atom entry construct is defined in section 4.1.2 of the format spec. + + + + + + + + + + + + + + + + + + + + + + + The Atom content construct is defined in section 4.1.3 of the format spec. + + + + + + + + + + + + + The Atom cagegory construct is defined in section 4.2.2 of the format spec. + + + + + + + + + + + The Atom generator element is defined in section 4.2.4 of the format spec. + + + + + + + + + + + + + + The Atom icon construct is defined in section 4.2.5 of the format spec. + + + + + + + + + + + + The Atom id construct is defined in section 4.2.6 of the format spec. + + + + + + + + + + + + The Atom link construct is defined in section 3.4 of the format spec. + + + + + + + + + + + + + + The Atom logo construct is defined in section 4.2.8 of the format spec. + + + + + + + + + + + + The Atom source construct is defined in section 4.2.11 of the format spec. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-commons-core/src/main/resources/org/springframework/data/domain/jaxb/spring-data-jaxb.xsd b/spring-data-commons-core/src/main/resources/org/springframework/data/domain/jaxb/spring-data-jaxb.xsd new file mode 100644 index 000000000..968261742 --- /dev/null +++ b/spring-data-commons-core/src/main/resources/org/springframework/data/domain/jaxb/spring-data-jaxb.xsd @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/domain/jaxb/SpringDataJaxbUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/domain/jaxb/SpringDataJaxbUnitTests.java new file mode 100644 index 000000000..05bcadbfe --- /dev/null +++ b/spring-data-commons-core/src/test/java/org/springframework/data/domain/jaxb/SpringDataJaxbUnitTests.java @@ -0,0 +1,160 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed 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.springframework.data.domain.jaxb; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import java.io.StringWriter; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Sort.Direction; +import org.springframework.hateoas.Link; + +/** + * Unit test for custom JAXB conversions for Spring Data value objects. + * + * @author Oliver Gierke + */ +public class SpringDataJaxbUnitTests { + + Marshaller marshaller; + Unmarshaller unmarshaller; + + Sort sort = new Sort(Direction.ASC, "firstname", "lastname"); + Pageable reference = new PageRequest(2, 15, sort); + Resource resource = new ClassPathResource("pageable.xml", this.getClass()); + Resource schemaFile = new ClassPathResource("spring-data-jaxb.xsd", this.getClass()); + + Scanner scanner; + + @Before + public void setUp() throws Exception { + + JAXBContext context = JAXBContext.newInstance("org.springframework.data.domain.jaxb"); + + marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + + unmarshaller = context.createUnmarshaller(); + + scanner = new Scanner(resource.getFile()); + } + + @After + public void tearDown() { + scanner.close(); + } + + @Test + public void usesCustomTypeAdapterForPageRequests() throws Exception { + + StringWriter writer = new StringWriter(); + Wrapper wrapper = new Wrapper(); + wrapper.pageable = reference; + wrapper.sort = sort; + wrapper.pageableWithoutSort = new PageRequest(10, 20); + marshaller.marshal(wrapper, writer); + + for (String line : writer.toString().split("\n")) { + assertThat(scanner.hasNextLine(), is(true)); + assertThat(line, is(scanner.nextLine())); + } + } + + @Test + public void readsPageRequest() throws Exception { + + Object result = unmarshaller.unmarshal(resource.getFile()); + + assertThat(result, is(instanceOf(Wrapper.class))); + assertThat(((Wrapper) result).pageable, is(reference)); + assertThat(((Wrapper) result).sort, is(sort)); + } + + @Test + public void writesPlainPage() throws Exception { + + PageWrapper wrapper = new PageWrapper(); + Content content = new Content(); + content.name = "Foo"; + wrapper.page = new PageImpl(Arrays.asList(content)); + wrapper.pageWithLinks = new PageImpl(Arrays.asList(content)); + + marshaller.marshal(wrapper, new StringWriter()); + } + + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + static class Wrapper { + + @XmlElement(name = "page-request", namespace = SpringDataJaxb.NAMESPACE) + Pageable pageable; + + @XmlElement(name = "page-request-without-sort", namespace = SpringDataJaxb.NAMESPACE) + Pageable pageableWithoutSort; + + @XmlElement(name = "sort", namespace = SpringDataJaxb.NAMESPACE) + Sort sort; + } + + @XmlRootElement(name = "wrapper", namespace = SpringDataJaxb.NAMESPACE) + static class PageWrapper { + + Page page; + + @XmlElement(name = "page-with-links") + @XmlJavaTypeAdapter(LinkedPageAdapter.class) + Page pageWithLinks; + } + + @XmlRootElement + static class Content { + + @XmlAttribute + String name; + } + + static class LinkedPageAdapter extends PageAdapter { + + @Override + protected List getLinks(Page source) { + return Arrays.asList(new Link(Link.REL_NEXT, "next"), new Link(Link.REL_PREVIOUS, "previous")); + } + } +} diff --git a/spring-data-commons-core/src/test/resources/org/springframework/data/domain/jaxb/jaxb.index b/spring-data-commons-core/src/test/resources/org/springframework/data/domain/jaxb/jaxb.index new file mode 100644 index 000000000..7c9665663 --- /dev/null +++ b/spring-data-commons-core/src/test/resources/org/springframework/data/domain/jaxb/jaxb.index @@ -0,0 +1,3 @@ +SpringDataJaxbUnitTests$Wrapper +SpringDataJaxbUnitTests$PageWrapper +SpringDataJaxbUnitTests$Content \ No newline at end of file diff --git a/spring-data-commons-core/src/test/resources/org/springframework/data/domain/jaxb/pageable.xml b/spring-data-commons-core/src/test/resources/org/springframework/data/domain/jaxb/pageable.xml new file mode 100644 index 000000000..b08245c50 --- /dev/null +++ b/spring-data-commons-core/src/test/resources/org/springframework/data/domain/jaxb/pageable.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/spring-data-commons-core/template.mf b/spring-data-commons-core/template.mf index 166033ad7..1bbf7e4d3 100644 --- a/spring-data-commons-core/template.mf +++ b/spring-data-commons-core/template.mf @@ -8,6 +8,7 @@ Import-Template: com.mysema.query.*;version="[2.2.0,3.0.0)";resolution:=optional, javax.enterprise.*;version="${cdi.version:[=.=.=,+1.0.0)}";resolution:=optional, javax.inject.*;version="[1.0.0,2.0.0)";resolution:=optional, + javax.xml.bind.*;version="0";resolution:=optional, javax.xml.transform.*;version="0";resolution:=optional, org.codehaus.jackson.*;version="${jackson.version:[=.=.=,+1.0.0)}";resolution:=optional, org.springframework.aop.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional, @@ -18,6 +19,7 @@ Import-Template: org.springframework.expression.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional, org.springframework.expression.spel.standard.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional, org.springframework.expression.spel.support.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional, + org.springframework.hateoas.*;version="${org.springframework.hateoas.version:[=.=.=,+1.0.0)}";resolution:=optional, org.springframework.oxm.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional, org.springframework.transaction.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional, org.springframework.util.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}", diff --git a/spring-data-commons-parent/pom.xml b/spring-data-commons-parent/pom.xml index 754812afc..9708d3b23 100644 --- a/spring-data-commons-parent/pom.xml +++ b/spring-data-commons-parent/pom.xml @@ -17,6 +17,7 @@ 3.0.7.RELEASE 4.0.0.RELEASE [${org.springframework.version.30}, ${org.springframework.version.40}) + 0.1.0.RELEASE 1.2.1 true