
org.daisy.pipeline.braille.common.AbstractTransformProvider Maven / Gradle / Ivy
package org.daisy.pipeline.braille.common;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Optional;
import com.google.common.collect.AbstractIterator;
import org.daisy.pipeline.braille.common.Query.Feature;
import org.daisy.pipeline.braille.common.Query.MutableQuery;
import static org.daisy.pipeline.braille.common.Query.util.mutableQuery;
import org.slf4j.Logger;
public abstract class AbstractTransformProvider implements TransformProvider {
private Map> transformCache = new HashMap>();
private Map> providerCache = new HashMap>();
protected abstract Iterable _get(Query query);
private final java.lang.Iterable get(Query query, Logger context) {
MutableQuery q = mutableQuery(query);
if (q.containsKey("id")) {
Feature f = q.removeOnly("id");
if (q.isEmpty())
return Optional.fromNullable(fromId(f.getValue().get())).asSet(); }
Iterable i;
if (transformCache.containsKey(query))
i = transformCache.get(query);
else {
// memoize() doesn't make sense
i = util.Iterables.memoize(_get(query));
transformCache.put(query, i); }
return rememberId(i.apply(context));
}
public java.lang.Iterable get(Query query) {
return get(query, null);
}
public final TransformProvider withContext(Logger context) {
if (providerCache.containsKey(context))
return providerCache.get(context);
TransformProvider provider = new DerivativeProvider(context);
providerCache.put(context, provider);
return provider;
}
public void invalidateCache() {
transformCache.clear();
}
public ToStringHelper toStringHelper() {
return Objects.toStringHelper(this);
}
@Override
public String toString() {
return toStringHelper().add("context", null).toString();
}
private class DerivativeProvider implements TransformProvider {
private final Logger context;
private DerivativeProvider(final Logger context) {
this.context = context;
}
public java.lang.Iterable get(Query query) {
return AbstractTransformProvider.this.get(query, context);
}
public TransformProvider withContext(Logger context) {
return AbstractTransformProvider.this.withContext(context);
}
@Override
public String toString() {
return AbstractTransformProvider.this.toStringHelper().add("context", context).toString();
}
}
private Map fromId = new HashMap();
protected T fromId(String id) {
return fromId.get(id);
}
private java.lang.Iterable rememberId(final java.lang.Iterable iterable) {
final Map fromId = this.fromId;
return new java.lang.Iterable() {
public Iterator iterator() {
return new Iterator() {
Iterator i = iterable.iterator();
public boolean hasNext() {
return i.hasNext();
}
public T next() {
T t = i.next();
fromId.put(t.getIdentifier(), t);
return t;
}
public void remove() {
i.remove();
}
};
}
};
}
/* -------- */
/* Iterable */
/* -------- */
protected interface Iterable extends WithSideEffect.util.Iterable,
java.lang.Iterable> {}
/* ================== */
/* UTILS */
/* ================== */
public static abstract class util {
/* ------------------------ */
/* logCreate(), logSelect() */
/* ------------------------ */
public static WithSideEffect logCreate(final T t) {
return new WithSideEffect() {
public T _apply() {
__apply(debug("Created " + t));
return t; }};
}
public static Iterable logSelect(final Query query,
final TransformProvider provider) {
// not using provider.withContext() because memoizing only makes sense if sub-providers
// have no side-effects and provided transformers have no context
return logSelect(query, provider.withContext(null).get(query));
}
public static Iterable logSelect(final Query query,
final java.lang.Iterable iterable) {
return Iterables.of(
new java.lang.Iterable>() {
public Iterator> iterator() {
return new Iterator>() {
Iterator i = iterable.iterator();
boolean first = true;
public boolean hasNext() {
if (i == null)
return true;
return i.hasNext();
}
public WithSideEffect next() {
final T t;
if (first) {
first = false;
try { t = i.next(); }
catch (final NoSuchElementException e) {
return new WithSideEffect() {
public T _apply() {
__apply(debug("No match for query " + query));
throw e;
}
};
}
} else
t = i.next();
return new WithSideEffect() {
public T _apply() {
__apply(info("Selected " + t + " for query " + query));
return t;
}
};
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
);
}
public static com.google.common.base.Function debug(final String message) {
return new com.google.common.base.Function() {
public Void apply(Logger logger) {
if (logger != null)
logger.debug(message);
return null;
}
};
}
public static com.google.common.base.Function info(final String message) {
return new com.google.common.base.Function() {
public Void apply(Logger logger) {
if (logger != null)
logger.info(message);
return null;
}
};
}
public static com.google.common.base.Function warn(final String message) {
return new com.google.common.base.Function() {
public Void apply(Logger logger) {
if (logger != null)
logger.warn(message);
return null;
}
};
}
/* -------- */
/* Function */
/* -------- */
public static abstract class Function extends WithSideEffect.util.Function {}
/* --------- */
/* Iterables */
/* --------- */
public static abstract class Iterables {
/* memoize() */
public static Iterable memoize(Iterable iterable) {
return of(org.daisy.pipeline.braille.common.util.Iterables.memoize(iterable));
}
/* empty() */
public static Iterable empty() {
return of(Optional.>absent().asSet());
}
/* fromNullable() */
public static Iterable fromNullable(T element) {
return of(WithSideEffect.fromNullable(element));
}
/* of() */
public static Iterable of(T element) {
return of(WithSideEffect.of(element));
}
public static Iterable of(WithSideEffect element) {
return of(Optional.of(element).asSet());
}
public static Iterable of(final java.lang.Iterable> iterable) {
return new Of(iterable);
}
private static class Of extends WithSideEffect.util.Iterables.Of implements Iterable {
protected Of(java.lang.Iterable> iterable) {
super(iterable);
}
public Iterator> iterator() {
return iterable.iterator();
}
}
/* transform() */
public static Iterable transform(Iterable from,
final com.google.common.base.Function function) {
return transform(
from,
new Function() {
public T _apply(F from) {
return function.apply(from);
}
}
);
}
public static Iterable transform(Iterable from, final Function function) {
return of(
com.google.common.collect.Iterables.transform(
from,
new Function,T>() {
public T _apply(WithSideEffect from) {
return __apply(function.apply(__apply(from)));
}
}
)
);
}
public static Iterable transform(final java.lang.Iterable from, final Function function) {
return of(
com.google.common.collect.Iterables.transform(from, function)
);
}
/* concat() */
public static Iterable concat(Iterable a, T b) {
return of(
com.google.common.collect.Iterables.concat(a, of(b))
);
}
public static Iterable concat(Iterable a, WithSideEffect b) {
return of(
com.google.common.collect.Iterables.concat(a, of(b))
);
}
public static Iterable concat(Iterable a, Iterable b) {
return of(
com.google.common.collect.Iterables.concat(a, b)
);
}
public static Iterable concat(final java.lang.Iterable extends Iterable> inputs) {
return of(
com.google.common.collect.Iterables.concat(inputs)
);
}
public static Iterable concat(final Iterable extends Iterable> inputs) {
return new Concat() {
protected Iterator extends Iterable> iterator(Logger context) {
return inputs.apply(context).iterator();
}
public Iterator> iterator() {
return new AbstractIterator>() {
Iterator extends WithSideEffect extends Iterable,Logger>> iterableIterator = inputs.iterator();
Iterator> current;
WithSideEffect nextEvaluate;
boolean evaluated = true;
protected WithSideEffect computeNext() {
if (!evaluated)
throw new RuntimeException("Previous element must be evaluated first");
if (current != null && current.hasNext())
return current.next();
else if (!iterableIterator.hasNext())
return endOfData();
nextEvaluate = new WithSideEffect() {
public T _apply() throws Throwable {
if (nextEvaluate == this)
evaluated = true;
while (current == null || !current.hasNext()) {
try {
current = __apply(iterableIterator.next()).iterator();
break; }
catch (WithSideEffect.Exception e) {
continue; }}
try {
return __apply(current.next()); }
catch (WithSideEffect.Exception e) {
throw e.getCause(); }
}
};
evaluated = false;
return nextEvaluate;
}
};
}
};
}
protected static abstract class Concat extends WithSideEffect.util.Iterables.Concat
implements Iterable {}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy