Skip to content

Instantly share code, notes, and snippets.

@mathieuancelin
Created July 13, 2012 10:40
Show Gist options
  • Save mathieuancelin/3104192 to your computer and use it in GitHub Desktop.
Save mathieuancelin/3104192 to your computer and use it in GitHub Desktop.
A Java Cagette implementation based on Guava
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
public class Recipient {
public static enum Unit { INST }
public static interface Identifiable<ID> {
ID getId();
}
public static interface Identifier<A, ID> {
public ID of(A obj);
}
public static interface Pagination {}
public static abstract class Page implements Pagination {
private final int page;
private final int size;
public Page(int page) {
this.page = page;
this.size = 25;
}
public Page(int page, int size) {
this.page = page;
this.size = size;
}
public int getPage() { return page; }
public int getSize() { return size; }
}
public static class Full extends Page {
public Full() { super(-1); }
}
public static final Pagination FULL = new Full();
public static class Bocal<A, ID> {
private final Identifier<A, ID> identifier;
private final List<A> store = Lists.newArrayList();
public static <ID, T extends Identifiable<ID>> Bocal<T, ID> identifiableBocal(final Class<T> clazz) {
return new Bocal<T, ID>(clazz);
}
public static <A, ID> Bocal<A, ID> identifiableBocal(Identifier<A, ID> identifier) {
return new Bocal<A, ID>(identifier);
}
public Bocal() {
// SO UGLY !!!!
this.identifier = new Identifier<A, ID>() {
private Class clazz;
private Field f;
@Override
public ID of(A obj) {
try {
if (clazz == null && f == null) {
clazz = obj.getClass();
f = clazz.getDeclaredField("id");
f.setAccessible(true);
}
return (ID) f.get(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
Bocal(final Class<? extends Identifiable<ID>> clazz) {
this.identifier = new Identifier<A, ID>() {
public ID of(A obj) {
return clazz.cast(obj).getId();
}
};
}
public Bocal(Identifier<A, ID> identifier) {
this.identifier = identifier;
}
public Optional<A> findById(final ID id) {
return Optional.fromNullable(Iterables.getFirst(
Collections2.filter(store, new Predicate<A>() {
public boolean apply(A item) {
return identifier.of(item).equals(id);
}
}), null));
}
public Collection<A> findAll(Pagination pagination) {
return paginate(store, pagination);
}
public Collection<A> findAll() { return paginate(store, FULL); }
public Collection<A> findBy(Predicate<A> p, Pagination pagination) {
return paginate(Collections2.filter(store, p), pagination);
}
public Collection<A> findBy(Predicate<A> p) {
return paginate(Collections2.filter(store, p), FULL);
}
public Optional<A> findOneBy(Predicate<A> p) {
return Optional.fromNullable(Iterables.getFirst(findBy(p), null));
}
public void delete(ID id) {
findById(id).transform(new Function<A, Unit>() {
public Unit apply(A item) {
store.remove(item);
return Unit.INST;
}
});
}
public void delete(List<ID> ids) {
for (ID id : ids) {
delete(id);
}
}
public void delete(final Predicate<A> p) {
for (A item : findBy(p)) {
delete(identifier.of(item));
}
}
public A save(A item) {
delete(identifier.of(item));
store.add(item);
return item;
}
public void save(List<A> items) {
for (A item : items) {
save(item);
}
}
public long count(Predicate<A> p) { return (long) findBy(p).size(); }
public void clear() { store.clear(); }
public void reset() { reset(Collections.<A>emptyList()); }
public void reset(Collection<A> withItems) {
clear();
counter.set(0);
store.addAll(withItems);
}
public long size() { return store.size(); }
private Collection<A> paginate(Collection<A> items, Pagination pagination) {
for (Full full : caseClassOf(Full.class, pagination)) {
return items;
}
for (Page page : caseClassOf(Page.class, pagination)) {
return Lists.newArrayList(
Iterables.limit(
Iterables.skip(items, (page.getPage() - 1)
* page.getSize()), page.getSize()));
}
throw new RuntimeException("Should not happen !!!");
}
private AtomicLong counter = new AtomicLong(0);
public Long autoIncrement() { return counter.getAndIncrement(); }
public String UUID() { return Long.toString(autoIncrement(), 24); }
}
private static <K> Iterable<K> caseClassOf(final Class<K> clazz, Object o) {
if (clazz.isInstance(o)) { return Collections.singleton(clazz.cast(o));}
return Collections.emptyList();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment