Created
November 29, 2008 02:00
-
-
Save loganj/30152 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
Bijective function interface and transform collections based thereupon. |
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
/** | |
* Copyright (C) 2008 Logan Johnson | |
* | |
* 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. | |
*/ | |
package loganj.structures; | |
import com.google.common.base.Function; | |
public interface Bijective<F, T> extends Function<F,T> { | |
Bijective<T,F> inverse(); | |
} |
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
/** | |
* Copyright (C) 2008 Logan Johnson | |
* | |
* 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. | |
*/ | |
package loganj.structures; | |
import com.google.common.base.Function; | |
import java.util.Iterator; | |
import java.util.Collection; | |
class BijectiveCollection<F,T> implements Collection<T> { | |
final private Collection<F> backingCollection; | |
final private Bijective<F,T> bijective; | |
BijectiveCollection(Collection<F> backingCollection, Bijective<F,T> bijective) { | |
this.backingCollection = backingCollection; | |
this.bijective = bijective; | |
} | |
@Override | |
public int size() { | |
return backingCollection.size(); | |
} | |
@Override | |
public boolean isEmpty() { | |
return backingCollection.isEmpty(); | |
} | |
@Override | |
public boolean contains(Object o) { | |
if ( o == null ) { | |
return false; | |
} | |
T to = null; | |
try { | |
to = (T)o; | |
} catch ( ClassCastException e ) { | |
return false; | |
} | |
return backingCollection.contains(bijective.inverse().apply(to)); | |
} | |
private static class OntoIterator<F,T> implements Iterator<T> { | |
final private Iterator<F> it; | |
final private Function<F,T> from; | |
OntoIterator(Iterator<F> it, Function<F,T> from) { | |
this.it = it; | |
this.from = from; | |
} | |
@Override | |
public boolean hasNext() { | |
return it.hasNext(); | |
} | |
@Override | |
public T next() { | |
return from.apply(it.next()); | |
} | |
@Override | |
public void remove() { | |
it.remove(); | |
} | |
} | |
@Override | |
public Iterator<T> iterator() { | |
return new OntoIterator<F,T>(backingCollection.iterator(), bijective); | |
} | |
@Override | |
public Object[] toArray() { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public <T> T[] toArray(T[] ts) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public boolean add(T t) { | |
return backingCollection.add(bijective.inverse().apply(t)); | |
} | |
@Override | |
public boolean remove(Object o) { | |
if ( o == null) { | |
return false; | |
} | |
T cast; | |
try { | |
cast = (T)o; | |
} catch ( ClassCastException e ) { | |
return false; | |
} | |
return backingCollection.remove(bijective.inverse().apply(cast)); | |
} | |
@Override | |
public boolean containsAll(Collection<?> objects) { | |
for ( Object o : objects ) { | |
if ( !contains(o) ) { | |
return false; | |
} | |
} | |
return true; | |
} | |
@Override | |
public boolean addAll(Collection<? extends T> ts) { | |
boolean changed = false; | |
for ( T t : ts) { | |
changed |= add(t); | |
} | |
return changed; | |
} | |
@Override | |
public boolean retainAll(Collection<?> objects) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public boolean removeAll(Collection<?> objects) { | |
boolean changed = false; | |
for ( Object o : objects ) { | |
changed |= remove(o); | |
} | |
return changed; | |
} | |
@Override | |
public void clear() { | |
backingCollection.clear(); | |
} | |
} |
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
/** | |
* Copyright (C) 2008 Logan Johnson | |
* | |
* 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. | |
*/ | |
package loganj.structures; | |
import com.google.common.base.Function; | |
import com.google.common.base.Nullable; | |
import java.util.Map; | |
import java.util.Set; | |
import java.util.Collection; | |
final public class BijectiveMap<FK,K,FV,V> implements Map<K,V> { | |
final private class InverseEntry implements Map.Entry<FK,FV> { | |
final private Map.Entry<K,V> entry; | |
InverseEntry(Entry<K, V> entry) { | |
this.entry = entry; | |
} | |
@Override | |
public FK getKey() { | |
return keyBijective.inverse().apply(entry.getKey()); | |
} | |
@Override | |
public FV getValue() { | |
return valueBijective.inverse().apply(entry.getValue()); | |
} | |
@Override | |
public FV setValue(FV fv) { | |
return valueBijective.inverse().apply(entry.setValue(valueBijective.apply(fv))); | |
} | |
} | |
final private class ForwardEntry implements Map.Entry<K,V> { | |
final private Map.Entry<FK,FV> entry; | |
ForwardEntry(Entry<FK, FV> entry) { | |
this.entry = entry; | |
} | |
@Override | |
public K getKey() { | |
return keyBijective.apply(entry.getKey()); | |
} | |
@Override | |
public V getValue() { | |
return valueBijective.apply(entry.getValue()); | |
} | |
@Override | |
public V setValue(V v) { | |
return valueBijective.apply(entry.setValue(valueBijective.inverse().apply(v))); | |
} | |
@Override | |
public String toString() { | |
StringBuilder b = new StringBuilder(); | |
b.append(keyBijective.apply(entry.getKey())); | |
b.append("="); | |
b.append(valueBijective.apply(entry.getValue())); | |
return b.toString(); | |
} | |
} | |
final private Map<FK,FV> backingMap; | |
final private Bijective<FK,K> keyBijective; | |
final private Bijective<FV,V> valueBijective; | |
final private Set<K> keySet; | |
final private Set<Entry<K,V>> entrySet; | |
final private Collection<V> values; | |
public BijectiveMap(Map<FK, FV> backingMap, Bijective<FK,K> keyBijective, Bijective<FV,V> valueBijective) { | |
this.backingMap = backingMap; | |
this.keyBijective = keyBijective; | |
this.valueBijective = valueBijective; | |
keySet = new BijectiveSet<FK,K>(backingMap.keySet(), keyBijective ); | |
values = new BijectiveCollection<FV,V>(backingMap.values(), valueBijective); | |
entrySet = new BijectiveSet<Entry<FK,FV>,Entry<K,V>>(backingMap.entrySet(), | |
Bijectives.newBijective( | |
new Function<Entry<FK,FV>,Entry<K,V>>() { | |
@Override | |
public Entry<K, V> apply(@Nullable Entry<FK, FV> from) { | |
return new ForwardEntry(from); | |
} | |
}, | |
new Function<Entry<K,V>,Entry<FK,FV>>() { | |
@Override | |
public Entry<FK, FV> apply(@Nullable Entry<K, V> from) { | |
return new InverseEntry(from); | |
} | |
}) | |
); | |
} | |
@Override | |
public int size() { | |
return backingMap.size(); | |
} | |
@Override | |
public boolean isEmpty() { | |
return backingMap.isEmpty(); | |
} | |
@Override | |
public boolean containsKey(Object o) { | |
return keySet.contains(o); | |
} | |
@Override | |
public boolean containsValue(Object o) { | |
return values.contains(o); | |
} | |
@Override | |
public V get(Object o) { | |
if ( !containsKey(o) ) { | |
return null; | |
} | |
K cast; | |
try { | |
cast = (K)o; | |
} catch ( ClassCastException e ) { | |
return null; | |
} | |
return valueBijective.apply(backingMap.get(keyBijective.inverse().apply(cast))); | |
} | |
@Override | |
public V put(K k, V v) { | |
return valueBijective.apply(backingMap.put(keyBijective.inverse().apply(k), valueBijective.inverse().apply(v))); | |
} | |
@Override | |
public V remove(Object o) { | |
if ( o == null ) { | |
return null; | |
} | |
K cast; | |
try { | |
cast = (K)o; | |
} catch ( ClassCastException e ) { | |
return null; | |
} | |
return valueBijective.apply(backingMap.remove(keyBijective.inverse().apply(cast))); | |
} | |
@Override | |
public void putAll(Map<? extends K, ? extends V> map) { | |
for ( Map.Entry<? extends K, ? extends V> entry : map.entrySet() ) { | |
backingMap.put( keyBijective.inverse().apply(entry.getKey()), | |
valueBijective.inverse().apply(entry.getValue())); | |
} | |
} | |
@Override | |
public void clear() { | |
backingMap.clear(); | |
} | |
@Override | |
public Set<K> keySet() { | |
return keySet; | |
} | |
@Override | |
public Collection<V> values() { | |
return values; | |
} | |
@Override | |
public Set<Entry<K, V>> entrySet() { | |
return entrySet; | |
} | |
} |
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
/** | |
* Copyright (C) 2008 Logan Johnson | |
* | |
* 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. | |
*/ | |
package loganj.structures; | |
import com.google.common.base.Function; | |
import com.google.common.base.Nullable; | |
import com.google.common.base.Functions; | |
import com.google.common.base.Join; | |
import com.google.common.collect.Maps; | |
import java.util.Map; | |
import java.util.Calendar; | |
import java.awt.*; | |
final public class Bijectives { | |
private Bijectives() {} | |
public static <F,T> Bijective<F,T> newBijective(Function<F,T> forward, Function<T,F> inverse) { | |
return new BijectiveImpl<F,T>(forward,inverse); | |
} | |
private static final class BijectiveImpl<F,T> implements Bijective<F,T> { | |
final private Function<F,T> forward; | |
final private Function<T,F> inverse; | |
BijectiveImpl(Function<F, T> forward, Function<T, F> inverse) { | |
this.forward = forward; | |
this.inverse = inverse; | |
} | |
@Override | |
public Bijective<T, F> inverse() { | |
return new Bijective<T,F>() { | |
@Override | |
public Bijective<F, T> inverse() { | |
return BijectiveImpl.this; | |
} | |
@Override | |
public F apply(@Nullable T from) { | |
return inverse.apply(from); | |
} | |
}; | |
} | |
@Override | |
public T apply(@Nullable F from) { | |
return forward.apply(from); | |
} | |
} | |
} |
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
/** | |
* Copyright (C) 2008 Logan Johnson | |
* | |
* 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. | |
*/ | |
package loganj.structures; | |
import java.util.Set; | |
final public class BijectiveSet<F,T> extends BijectiveCollection<F,T> implements Set<T> { | |
public BijectiveSet(Set<F> backingSet, Bijective<F,T> bijective) { | |
super(backingSet, bijective); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment