package gwt.material.design.client.data;

/*
 * #%L
 * GwtMaterial
 * %%
 * Copyright (C) 2015 - 2016 GwtMaterialDesign
 * %%
 * 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.
 * #L%
 */

import gwt.material.design.client.data.loader.LoadCallback;
import gwt.material.design.client.data.loader.LoadConfig;
import gwt.material.design.client.data.loader.LoadResult;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Ben Dol
 */
public class ListDataSource<T> implements DataSource<T> {

    private Logger logger = Logger.getLogger(ListDataSource.class.getName());

    private List<T> data;

    public ListDataSource() {
        data = new ArrayList<>();
    }

    public ListDataSource(List<T> data) {
        this.data = data;
    }

    @Override
    public void load(LoadConfig<T> loadConfig, LoadCallback<T> callback) {
        try {
            final List<T> subList = data.subList(loadConfig.getOffset(),
                    (loadConfig.getOffset() + loadConfig.getLimit()));
            callback.onSuccess(new LoadResult<T>() {
                @Override
                public List<T> getData() {
                    return subList;
                }
                @Override
                public int getOffset() {
                    return loadConfig.getOffset();
                }
                @Override
                public int getTotalLength() {
                    return data.size();
                }
                @Override
                public boolean isCacheData() {
                    return cacheData();
                }
            });
        } catch (IndexOutOfBoundsException ex) {
            // Silently ignore index out of bounds exceptions
            logger.log(Level.FINE, "ListDataSource threw index out of bounds.", ex);
            callback.onFailure(ex);
        }
    }

    public void add(int startIndex, List<T> list) {
        data.addAll(startIndex, list);
    }

    public void remove(List<T> list) {
        data.removeAll(list);
    }

    public boolean cacheData() {
        return true;
    }

    @Override
    public boolean useRemoteSort() {
        return false;
    }
}

@@ -1440,68 +1440,138 @@
     
-f
 in
-al List%3CT%3E subList = data.subList(loadConfig.getOffset(),
+t size = loadConfig.getOffset() + loadConfig.getLimit();%0A            if(size %3E data.size())%7B%0A                size = data.size();
 %0A   
@@ -1579,24 +1579,26 @@
         
+%7D%0A
         
 (loadCon
@@ -1593,56 +1593,109 @@
     
-(loadConfig.getOffset() + loadConfig.getLimit())
+    final List%3CT%3E subList = size == 0 ? new ArrayList%3C%3E() : data.subList(loadConfig.getOffset(), size
 );%0A 

Apply fix for ListDataSource (thanks @reofake) Fix #34