001/*
002  GRANITE DATA SERVICES
003  Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004
005  This file is part of Granite Data Services.
006
007  Granite Data Services is free software; you can redistribute it and/or modify
008  it under the terms of the GNU Library General Public License as published by
009  the Free Software Foundation; either version 2 of the License, or (at your
010  option) any later version.
011
012  Granite Data Services is distributed in the hope that it will be useful, but
013  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015  for more details.
016
017  You should have received a copy of the GNU Library General Public License
018  along with this library; if not, see <http://www.gnu.org/licenses/>.
019*/
020
021package org.granite.spring.data;
022
023import java.lang.reflect.Field;
024import java.lang.reflect.Type;
025import java.util.ArrayList;
026import java.util.List;
027
028import org.granite.messaging.amf.io.convert.Converter;
029import org.granite.messaging.amf.io.convert.Converters;
030import org.granite.messaging.amf.io.convert.Reverter;
031import org.granite.tide.data.model.PageInfo;
032import org.granite.tide.data.model.SortInfo;
033import org.springframework.data.domain.Page;
034import org.springframework.data.domain.Pageable;
035import org.springframework.data.domain.Sort;
036import org.springframework.data.domain.Sort.Direction;
037import org.springframework.data.domain.Sort.Order;
038
039
040public class PageableConverter extends Converter implements Reverter {
041        
042        public PageableConverter(Converters converters) {
043                super(converters);
044        }
045
046        @Override
047        protected boolean internalCanConvert(Object value, Type targetType) {
048                return (value instanceof PageInfo && targetType.equals(Pageable.class))
049                        || (value instanceof SortInfo && targetType.equals(Sort.class));
050        }
051
052        @Override
053        protected Object internalConvert(Object value, Type targetType) {
054                if (targetType.equals(Pageable.class)) {
055                        PageInfo pageInfo = (PageInfo)value;
056                        Sort sort = null;
057                        if (pageInfo.getSortInfo() != null && pageInfo.getSortInfo().getOrder() != null && pageInfo.getSortInfo().getOrder().length > 0) {
058                                List<Order> orders = new ArrayList<Order>(pageInfo.getSortInfo().getOrder().length);
059                                for (int i = 0; i < pageInfo.getSortInfo().getOrder().length; i++)
060                                        orders.add(new Order(pageInfo.getSortInfo().getDesc()[i] ? Direction.DESC : Direction.ASC, pageInfo.getSortInfo().getOrder()[i]));                      
061                                sort = new Sort(orders);                        
062                        }
063                        return new PageRequest(pageInfo.getFirstResult(), pageInfo.getMaxResults(), sort);
064                }
065                return null;
066        }
067
068        public boolean canRevert(Object value) {
069                return value instanceof Page;
070        }
071
072        public Object revert(Object value) {
073                @SuppressWarnings("unchecked")
074                Page<Object> page = (Page<Object>)value;
075                int offset = page.getNumber() * page.getSize();
076                try {
077                        Field f = page.getClass().getDeclaredField("pageable");
078                        f.setAccessible(true);
079                        Pageable pageable = (Pageable)f.get(page);
080                        offset = pageable.getOffset();
081                }
082                catch (Exception e) {
083                }
084                return new org.granite.tide.data.model.Page<Object>(offset, page.getSize(), Long.valueOf(page.getTotalElements()).intValue(), page.getContent());
085        }
086        
087        
088        public static class PageRequest implements Pageable {
089                
090                private int offset;
091                private int pageSize;
092                private Sort sort;
093                
094                public PageRequest(int offset, int pageSize, Sort sort) {
095                        this.offset = offset;
096                        this.pageSize = pageSize;
097                        this.sort = sort;
098                }
099
100                public int getOffset() {
101                        return offset;
102                }
103
104                public int getPageNumber() {
105                        return pageSize > 0 ? offset / pageSize : 0;
106                }
107
108                public int getPageSize() {
109                        return pageSize;
110                }
111
112                public Sort getSort() {
113                        return sort;
114                }
115        }
116}