/*
* Joinery -- Data frames for Java
* Copyright (c) 2014, 2015 IBM Corp.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package joinery.impl;
import java.util.AbstractList;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import joinery.DataFrame;
import joinery.DataFrame.Function;
public class Views {
public static class ListView<V>
extends AbstractList<List<V>> {
private final DataFrame<V> df;
private final boolean transpose;
public ListView(final DataFrame<V> df, final boolean transpose) {
this.df = df;
this.transpose = transpose;
}
@Override
public List<V> get(final int index) {
return new SeriesListView<>(df, index, !transpose);
}
@Override
public int size() {
return transpose ? df.length() : df.size();
}
}
public static class SeriesListView<V>
extends AbstractList<V> {
private final DataFrame<V> df;
private final int index;
private final boolean transpose;
public SeriesListView(final DataFrame<V> df, final int index, final boolean transpose) {
this.df = df;
this.index = index;
this.transpose = transpose;
}
@Override
public V get(final int index) {
return transpose ? df.get(index, this.index) : df.get(this.index, index);
}
@Override
public int size() {
return transpose ? df.length() : df.size();
}
}
public static class MapView<V>
extends AbstractList<Map<Object, V>> {
private final DataFrame<V> df;
private final boolean transpose;
public MapView(final DataFrame<V> df, final boolean transpose) {
this.df = df;
this.transpose = transpose;
}
@Override
public Map<Object, V> get(final int index) {
return new SeriesMapView<>(df, index, !transpose);
}
@Override
public int size() {
return transpose ? df.length() : df.size();
}
}
public static class SeriesMapView<V>
extends AbstractMap<Object, V> {
private final DataFrame<V> df;
private final int index;
private final boolean transpose;
public SeriesMapView(final DataFrame<V> df, final int index, final boolean transpose) {
this.df = df;
this.index = index;
this.transpose = transpose;
}
@Override
public Set<Map.Entry<Object, V>> entrySet() {
return new AbstractSet<Map.Entry<Object, V>>() {
@Override
public Iterator<Map.Entry<Object, V>> iterator() {
final Set<Object> names = transpose ? df.index() : df.columns();
final Iterator<Object> it = names.iterator();
return new Iterator<Map.Entry<Object, V>>() {
int value = 0;
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public Map.Entry<Object, V> next() {
final Object key = it.next();
final int value = this.value++;
return new Map.Entry<Object, V>() {
@Override
public Object getKey() {
return key;
}
@Override
public V getValue() {
return transpose ?
df.get(value, index) :
df.get(index, value);
}
@Override
public V setValue(final V value) {
throw new UnsupportedOperationException();
}
};
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public int size() {
return transpose ? df.length() : df.size();
}
};
}
}
public static class TransformedView<V, U>
extends AbstractList<List<U>> {
protected final DataFrame<V> df;
protected final Function<V, U> transform;
protected final boolean transpose;
public TransformedView(final DataFrame<V> df, final Function<V, U> transform, final boolean transpose) {
this.df = df;
this.transform = transform;
this.transpose = transpose;
}
@Override
public List<U> get(final int index) {
return new TransformedSeriesView<>(df, transform, index, !transpose);
}
@Override
public int size() {
return transpose ? df.length() : df.size();
}
}
public static class TransformedSeriesView<V, U>
extends AbstractList<U> {
protected final DataFrame<V> df;
protected final int index;
protected final boolean transpose;
protected final Function<V, U> transform;
public TransformedSeriesView(final DataFrame<V> df, final Function<V, U> transform, final int index, final boolean transpose) {
this.df = df;
this.transform = transform;
this.index = index;
this.transpose = transpose;
}
@Override
public U get(final int index) {
final V value = transpose ? df.get(index, this.index) : df.get(this.index, index);
return transform.apply(value);
}
@Override
public int size() {
return transpose ? df.length() : df.size();
}
}
public static class FlatView<V>
extends AbstractList<V> {
private final DataFrame<V> df;
public FlatView(final DataFrame<V> df) {
this.df = df;
}
@Override
public V get(final int index) {
return df.get(index % df.length(), index / df.length());
}
@Override
public int size() {
return df.size() * df.length();
}
}
public static class FillNaFunction<V>
implements Function<V, V> {
private final V fill;
public FillNaFunction(final V fill) {
this.fill = fill;
}
@Override
public V apply(final V value) {
return value == null ? fill : value;
}
}
}