Skip to content

Instantly share code, notes, and snippets.

@dha-lo-jd
Last active August 29, 2015 14:01
Show Gist options
  • Save dha-lo-jd/1f83ee3e05a259519837 to your computer and use it in GitHub Desktop.
Save dha-lo-jd/1f83ee3e05a259519837 to your computer and use it in GitHub Desktop.
リファクタリング切望
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import lombok.Data;
public abstract class AbstractMatrix<KA, KB, V> implements Matrix<KA, KB, V> {
public static abstract class AbstractCell<K, V> implements Cell<K, V> {
protected final K key;
public AbstractCell(K key) {
this.key = key;
}
@Override
public K getKey() {
return key;
}
}
public interface Cell<K, V> {
public K getKey();
public V getValue();
}
public static class ReferenceCell<K, KA, KB, V> extends AbstractCell<K, V> {
protected final KA keyA;
protected final KB keyB;
protected final Matrix<KA, KB, V> matrix;
public ReferenceCell(K key, KA keyA, KB keyB, Matrix<KA, KB, V> matrix) {
super(key);
this.keyA = keyA;
this.keyB = keyB;
this.matrix = matrix;
}
@Override
public V getValue() {
return matrix.get(keyA, keyB);
}
}
public interface Row<KF, KS, V> extends Iterable<Cell<KS, V>>, Cell<KF, Iterable<Cell<KS, V>>> {
V get(KS colKey);
}
public class RowImpl<KF, KS> extends AbstractCell<KF, Iterable<Cell<KS, V>>> implements Row<KF, KS, V> {
protected final Iterable<Cell<KS, V>> value;
protected final Matrix<KA, KB, V> matrix;
protected final MatrixAccessor<KA, KB, KF, KS, V> matrixAccessor;
public RowImpl(KF key, Iterable<Cell<KS, V>> value, Matrix<KA, KB, V> matrix, MatrixAccessor<KA, KB, KF, KS, V> matrixAccessor) {
super(key);
this.value = value;
this.matrix = matrix;
this.matrixAccessor = matrixAccessor;
}
@Override
public V get(KS colKey) {
return matrixAccessor.get(matrix, key, colKey).getValue();
}
@Override
public Iterable<Cell<KS, V>> getValue() {
return value;
}
@Override
public Iterator<Cell<KS, V>> iterator() {
return value.iterator();
}
}
public static class SimpleCell<K, V> extends AbstractCell<K, V> {
private final V value;
public SimpleCell(K key, V value) {
super(key);
this.value = value;
}
@Override
public V getValue() {
return value;
}
}
protected interface Keys<K> extends Iterable<K> {
void addKey(K key);
boolean hasKey(K key);
int size();
}
protected static class SimpleKeys<K> implements Keys<K> {
Set<K> set = new LinkedHashSet<>();
@Override
public void addKey(K key) {
set.add(key);
}
@Override
public boolean hasKey(K key) {
return set.contains(key);
}
@Override
public Iterator<K> iterator() {
return set.iterator();
}
@Override
public int size() {
return set.size();
}
}
@Data
private static class Key<KA, KB> {
private final KA keyA;
private final KB keyB;
private Key(KA keyA, KB keyB) {
this.keyA = keyA;
this.keyB = keyB;
}
}
private interface MatrixAccessor<KA, KB, F, S, V> {
Cell<S, V> get(Matrix<KA, KB, V> matrix, F f, S s);
}
private class RowAAccessor implements MatrixAccessor<KA, KB, KA, KB, V> {
@Override
public Cell<KB, V> get(Matrix<KA, KB, V> matrix, KA f, KB s) {
return new ReferenceCell<KB, KA, KB, V>(s, f, s, matrix);
}
}
private class RowBAccessor implements MatrixAccessor<KA, KB, KB, KA, V> {
@Override
public Cell<KA, V> get(Matrix<KA, KB, V> matrix, KB f, KA s) {
return new ReferenceCell<KA, KA, KB, V>(s, s, f, matrix);
}
}
protected final Map<Key<KA, KB>, V> map = new HashMap<>();
protected final Keys<KA> keyAKeys;
protected final Keys<KB> keyBKeys;
private final RowAAccessor rowAAccessor = new RowAAccessor();
private final RowBAccessor rowBAccessor = new RowBAccessor();
private Iterable<Row<KA, KB, V>> cacheRowByAs = null;
private Iterable<Row<KB, KA, V>> cacheRowByBs = null;
protected AbstractMatrix() {
this(new SimpleKeys<KA>());
}
protected AbstractMatrix(Keys<KA> keyAKeys) {
this(keyAKeys, new SimpleKeys<KB>());
}
protected AbstractMatrix(Keys<KA> keyAKeys, Keys<KB> keyBKeys) {
this.keyAKeys = keyAKeys;
this.keyBKeys = keyBKeys;
}
@Override
public V get(KA rowKey, KB colKey) {
Key<KA, KB> k = new Key<>(rowKey, colKey);
V v;
if (map.containsKey(k)) {
v = map.get(k);
} else {
v = getDefaultValue(rowKey, colKey);
}
return v;
}
/*
* (非 Javadoc)
*
* @see jp.co.afs.commons.calender.Matrix#matrixRowByAs()
*/
@Override
public Iterable<Row<KA, KB, V>> matrixRowByAs() {
if (cacheRowByAs == null) {
cacheRowByAs = matrix(keyAKeys, keyBKeys, rowAAccessor);
}
return cacheRowByAs;
}
/*
* (非 Javadoc)
*
* @see jp.co.afs.commons.calender.Matrix#matrixRowByBs()
*/
@Override
public Iterable<Row<KB, KA, V>> matrixRowByBs() {
if (cacheRowByBs == null) {
cacheRowByBs = matrix(keyBKeys, keyAKeys, rowBAccessor);
}
return cacheRowByBs;
}
@Override
public V put(KA keyA, KB keyB, V value) {
putKey(keyAKeys, keyA);
putKey(keyBKeys, keyB);
return map.put(new Key<>(keyA, keyB), value);
}
protected void clearCache() {
cacheRowByAs = null;
cacheRowByBs = null;
}
protected V getDefaultValue(KA keyA, KB keyB) {
return null;
}
protected Iterable<KA> getKeyAKeys() {
return keyAKeys;
}
protected Iterable<KB> getKeyBKeys() {
return keyBKeys;
}
protected void putARow(KA keyA, Map<KB, V> map) {
for (Entry<KB, V> entry : map.entrySet()) {
put(keyA, entry.getKey(), entry.getValue());
}
}
protected void putBRow(KB keyB, Map<KA, V> map) {
for (Entry<KA, V> entry : map.entrySet()) {
put(entry.getKey(), keyB, entry.getValue());
}
}
protected int sizeKeyAKeys() {
return keyAKeys.size();
}
protected int sizeKeyBKeys() {
return keyBKeys.size();
}
private <F, S> Iterable<Row<F, S, V>> matrix(Keys<F> keyFs, Keys<S> keySs, MatrixAccessor<KA, KB, F, S, V> accessor) {
List<Row<F, S, V>> rowList = new ArrayList<>();
for (F keyF : keyFs) {
rowList.add(values(keyF, keySs, accessor));
}
return rowList;
}
private <K> void putKey(Keys<K> keys, K key) {
if (!keys.hasKey(key)) {
keys.addKey(key);
clearCache();
}
}
private <F, S> Row<F, S, V> values(F keyF, Keys<S> keys, MatrixAccessor<KA, KB, F, S, V> accessor) {
List<Cell<S, V>> list = new ArrayList<>();
for (S key : keys) {
list.add(accessor.get(this, keyF, key));
}
return new RowImpl<F, S>(keyF, list, this, accessor);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment