Last active
August 29, 2015 14:01
-
-
Save dha-lo-jd/1f83ee3e05a259519837 to your computer and use it in GitHub Desktop.
リファクタリング切望
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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