org.daisy.pipeline.braille.common.TransformProvider Maven / Gradle / Ivy
package org.daisy.pipeline.braille.common;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import com.google.common.base.Function;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Iterables;
import org.daisy.pipeline.braille.common.Provider;
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 static org.daisy.pipeline.braille.common.util.Locales.parseLocale;
import static org.daisy.pipeline.braille.common.util.Strings.join;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public interface TransformProvider extends Provider, Contextual> {
/* ================== */
/* UTILS */
/* ================== */
public static abstract class util {
/* ------ */
/* cast() */
/* ------ */
@SuppressWarnings(
"unchecked" // safe cast
)
public static TransformProvider cast(TransformProvider extends T> provider) {
return (TransformProvider)provider;
}
/* --------- */
/* memoize() */
/* --------- */
public interface MemoizingProvider
extends Provider.util.MemoizingProvider, TransformProvider {}
public static MemoizingProvider memoize(TransformProvider provider) {
return new MemoizeFromProvider(provider);
}
public static abstract class Memoize
extends Provider.util.Memoize implements MemoizingProvider {
private final Map> providerCache;
private final boolean idOnly;
public Memoize() {
this(false);
}
/**
* @param idOnly whether to memoize {@code (id:...)} lookups only.
*/
public Memoize(boolean idOnly) {
providerCache = new HashMap>();
providerCache.put(null, this);
this.idOnly = idOnly;
}
/**
* Create a new {@link Memoize} object that is based on the same underlying caches.
*/
protected Memoize(Memoize shareCacheWith) {
super(shareCacheWith);
this.providerCache = shareCacheWith.providerCache;
this.idOnly = shareCacheWith.idOnly;
}
protected boolean skip(Query query) {
return !idOnly || !(query.containsKey("id") && Iterables.size(query) == 1);
}
@Override
public Iterable get(Query query) {
MutableQuery q = mutableQuery(query);
if (q.containsKey("id")) {
Feature f = q.removeOnly("id");
if (q.isEmpty()) {
T t = fromId(f.getValue().get());
if (t != null)
return Collections.singleton(t); }}
return rememberId(super.get(query));
}
private final Map fromId = new HashMap<>();
private T fromId(String id) {
return fromId.get(id);
}
private T rememberId(T t) {
fromId.put(t.getIdentifier(), t);
return t;
}
private Iterable rememberId(final Iterable iterable) {
return new java.lang.Iterable() {
public Iterator iterator() {
return new Iterator() {
Iterator i = iterable.iterator();
public boolean hasNext() {
return i.hasNext();
}
public T next() {
return rememberId(i.next());
}
public void remove() {
i.remove();
}
};
}
};
}
/**
* Create a new {@link TransformProvider} with the given context that is also memoizing
* and is based on the same underlying caches.
*/
protected abstract TransformProvider _withContext(Logger context);
public TransformProvider withContext(Logger context) {
if (providerCache.containsKey(context))
return providerCache.get(context);
TransformProvider provider = _withContext(context);
providerCache.put(context, provider);
return provider;
}
}
private static class MemoizeFromProvider extends Memoize {
private final TransformProvider provider;
private MemoizeFromProvider(TransformProvider provider) {
this.provider = provider;
}
private MemoizeFromProvider(MemoizeFromProvider provider) {
super(provider);
this.provider = provider.provider;
}
protected Iterable _get(Query query) {
return provider.get(query);
}
protected TransformProvider _withContext(Logger context) {
return new MemoizeFromProvider(provider.withContext(context));
}
@Override
public String toString() {
return "memoize( " + provider + " )";
}
}
/* ---------- */
/* dispatch() */
/* ---------- */
public static abstract class Dispatch
extends Provider.util.Dispatch implements TransformProvider {
private final Logger context;
public Dispatch(Logger context) {
this.context = context;
}
protected abstract Iterable> _dispatch();
public final Iterable> dispatch() {
return Iterables.transform(
_dispatch(),
new Function,Provider>() {
public Provider apply(TransformProvider provider) {
return provider.withContext(context); }});
}
}
@SuppressWarnings(
"unchecked" // safe cast to Iterable>
)
public static TransformProvider dispatch(Iterable extends TransformProvider> dispatch) {
return new DispatchFromProviderIterable((Iterable>)dispatch, null);
}
private static class DispatchFromProviderIterable extends Dispatch {
private final Iterable> dispatch;
private DispatchFromProviderIterable(Iterable> dispatch, Logger context) {
super(context);
this.dispatch = dispatch;
}
protected Iterable> _dispatch() {
return dispatch;
}
public TransformProvider withContext(Logger context) {
return new DispatchFromProviderIterable(dispatch, context);
}
@Override
public String toString() {
return "dispatch( " + join(_dispatch(), ", ") + " )";
}
}
/* --------- */
/* partial() */
/* --------- */
public static TransformProvider partial(Query query, TransformProvider provider) {
return new Partial(query, provider);
}
private static class Partial implements TransformProvider {
private final Query partialQuery;
private final TransformProvider provider;
public Partial(Query partialQuery, TransformProvider provider) {
this.partialQuery = partialQuery;
this.provider = provider;
}
public final Iterable get(Query query) {
return provider.get(mutableQuery().addAll(partialQuery).addAll(query));
}
public TransformProvider withContext(Logger context) {
return new Partial(partialQuery, provider.withContext(context));
}
@Override
public String toString() {
return "partial( " + partialQuery + ", " + provider + " )";
}
}
/* ------------------------ */
/* logCreate(), logSelect() */
/* ------------------------ */
public static T logCreate(T t, Logger context) {
context.debug("Created " + t);
return t;
}
public static Iterable logSelect(final Query query,
final TransformProvider provider,
final Logger context) {
return new Iterable() {
public Iterator iterator() {
return new AbstractIterator() {
Iterator i = provider.get(query).iterator();
boolean first = true;
public T computeNext() {
if (!i.hasNext()) {
if (first)
context.trace("No match for query " + query);
return endOfData(); }
T t = i.next();
context.debug("Selected " + t + " for query " + query);
first = false;
return t;
}
};
}
};
}
/* ------------ */
/* varyLocale() */
/* ------------ */
public static TransformProvider varyLocale(TransformProvider delegate) {
return new VaryLocale(delegate, null);
}
private static class VaryLocale
extends Provider.util.VaryLocale implements TransformProvider {
private final TransformProvider delegate;
private final Logger context;
private VaryLocale(TransformProvider delegate, Logger context) {
this.delegate = delegate;
this.context = context;
}
public Iterable _get(Query query) {
return delegate.withContext(context).get(query);
}
public Locale getLocale(Query query) {
if (query.containsKey("document-locale"))
try {
return parseLocale(query.getOnly("document-locale").getValue().get()); }
catch (IllegalArgumentException e) {
logger.warn("Invalid locale", e);
return null; }
else
return null;
}
public Query assocLocale(Query query, Locale locale) {
MutableQuery q = mutableQuery(query);
q.removeAll("document-locale");
q.add("document-locale", locale.toLanguageTag());
return q.asImmutable();
}
public TransformProvider withContext(Logger context) {
return new VaryLocale(delegate, context);
}
@Override
public String toString() {
return "varyLocale( " + delegate + " )";
}
}
private static final Logger logger = LoggerFactory.getLogger(TransformProvider.class);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy