diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/BundledNativePath.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/BundledNativePath.java index a65cba9f2..ef12c28a3 100755 --- a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/BundledNativePath.java +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/BundledNativePath.java @@ -10,7 +10,7 @@ import com.google.common.base.Optional; import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.find; import org.osgi.service.component.ComponentContext; @@ -67,7 +67,7 @@ private URI getExecutable(String name) { possiblePaths.add(asURI("x86/" + fileName)); possiblePaths.add(asURI(os + "/x86/" + fileName)); } try { - return Iterables.find( + return find( possiblePaths, new Predicate() { public boolean apply(URI p) { return resources.contains(p); }}); } catch (NoSuchElementException e) { return null; } @@ -81,7 +81,7 @@ private URI getSharedLibrary(String name) { possiblePaths.add(asURI(arch + "/" + fileName)); possiblePaths.add(asURI(os + "/" + arch + "/" + fileName)); try { - return Iterables.find( + return find( possiblePaths, new Predicate() { public boolean apply(URI p) { return resources.contains(p); }}); } catch (NoSuchElementException e) { return null; } diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/BundledResourcePath.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/BundledResourcePath.java index 7333ab1d9..642146418 100644 --- a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/BundledResourcePath.java +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/BundledResourcePath.java @@ -56,8 +56,8 @@ public URI getIdentifier() { return identifier; } - private final ResourceResolver resolver = new CachedResolver() { - public URL delegate(URI resource) { + private final ResourceResolver resolver = new MemoizingResolver() { + public URL _apply(URI resource) { logger.trace("Resolving " + resource + " within " + identifier + " (real path: " + path + "; unpack dir: " + unpackDir + ")"); resource = resource.normalize(); if (resource.equals(identifier) || resource.equals(path) || resource.equals(unpackDir)) diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Contextual.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Contextual.java new file mode 100644 index 000000000..86d762309 --- /dev/null +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Contextual.java @@ -0,0 +1,7 @@ +package org.daisy.pipeline.braille.common; + +public interface Contextual { + + public T withContext(C context); + +} diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/JobContext.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/JobContext.java new file mode 100644 index 000000000..c19e6c8a2 --- /dev/null +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/JobContext.java @@ -0,0 +1,160 @@ +package org.daisy.pipeline.braille.common; + +import org.slf4j.helpers.MarkerIgnoringBase; +import org.slf4j.helpers.MessageFormatter; +import org.slf4j.Logger; + +public interface JobContext extends Logger {; + + public abstract static class AbstractJobContext extends MarkerIgnoringBase implements JobContext { + + private static final long serialVersionUID = 1L; + + protected String format(String format, Object arg) { + return MessageFormatter.format(format, arg).getMessage(); + } + + protected String format(String format, Object arg1, Object arg2) { + return MessageFormatter.format(format, arg1, arg2).getMessage(); + } + + protected String format(String format, Object... args) { + return MessageFormatter.format(format, args).getMessage(); + } + + protected abstract void doTrace(String msg); + + protected abstract void doDebug(String msg); + + protected abstract void doInfo(String msg); + + protected abstract void doWarn(String msg); + + protected abstract void doError(String msg); + + public void trace(String msg) { + if (isTraceEnabled()) + doTrace(msg); + } + + public void trace(String format, Object arg) { + if (isTraceEnabled()) + doTrace(format(format, arg)); + } + + public void trace(String format, Object arg1, Object arg2) { + if (isTraceEnabled()) + doTrace(format(format, arg1, arg2)); + } + + public void trace(String format, Object... args) { + if (isTraceEnabled()) + doTrace(format(format, args)); + } + + public void trace(String msg, Throwable t) { + if (isTraceEnabled()) + doTrace(msg); + } + + public void debug(String msg) { + if (isDebugEnabled()) + doDebug(msg); + } + + public void debug(String format, Object arg) { + if (isDebugEnabled()) + doDebug(format(format, arg)); + } + + public void debug(String format, Object arg1, Object arg2) { + if (isDebugEnabled()) + doDebug(format(format, arg1, arg2)); + } + + public void debug(String format, Object... args) { + if (isDebugEnabled()) + doDebug(format(format, args)); + } + + public void debug(String msg, Throwable t) { + if (isDebugEnabled()) + doDebug(msg); + } + + public void info(String msg) { + if (isInfoEnabled()) + doInfo(msg); + } + + public void info(String format, Object arg) { + if (isInfoEnabled()) + doInfo(format(format, arg)); + } + + public void info(String format, Object arg1, Object arg2) { + if (isInfoEnabled()) + doInfo(format(format, arg1, arg2)); + } + + public void info(String format, Object... args) { + if (isInfoEnabled()) + doInfo(format(format, args)); + } + + public void info(String msg, Throwable t) { + if (isInfoEnabled()) + doInfo(msg); + } + + public void warn(String msg) { + if (isWarnEnabled()) + doWarn(msg); + } + + public void warn(String format, Object arg) { + if (isWarnEnabled()) + doWarn(format(format, arg)); + } + + public void warn(String format, Object arg1, Object arg2) { + if (isWarnEnabled()) + doWarn(format(format, arg1, arg2)); + } + + public void warn(String format, Object... args) { + if (isWarnEnabled()) + doWarn(format(format, args)); + } + + public void warn(String msg, Throwable t) { + if (isWarnEnabled()) + doWarn(msg); + } + + public void error(String msg) { + if (isErrorEnabled()) + doError(msg); + } + + public void error(String format, Object arg) { + if (isErrorEnabled()) + doError(format(format, arg)); + } + + public void error(String format, Object arg1, Object arg2) { + if (isErrorEnabled()) + doError(format(format, arg1, arg2)); + } + + public void error(String format, Object... args) { + if (isErrorEnabled()) + doError(format(format, args)); + } + + public void error(String msg, Throwable t) { + if (isErrorEnabled()) + doError(msg); + } + } +} diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/LazyValue.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/LazyValue.java index 00345fcd1..a9248f498 100644 --- a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/LazyValue.java +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/LazyValue.java @@ -7,12 +7,6 @@ public abstract class LazyValue implements Function0, Iterable { - public abstract V get(); - - public V apply() { - return get(); - } - public Iterator iterator() { return new Iterator() { boolean hasNext = true; @@ -23,7 +17,7 @@ public V next() { if (!hasNext()) throw new NoSuchElementException(); hasNext = false; - return get(); + return apply(); } public void remove() { throw new UnsupportedOperationException(); @@ -31,10 +25,10 @@ public void remove() { }; } - public static LazyValue from(final Function0 get) { + public static LazyValue from(final Function0 value) { return new LazyValue() { - public V get() { - return get.apply(); + public V apply() { + return value.apply(); } }; } @@ -44,34 +38,19 @@ public static abstract class ImmutableLazyValue extends LazyValue { private V value = null; protected boolean computed = false; - public V get() { + public final V apply() { if (!computed) { - value = delegate(); + value = _apply(); computed = true; } return value; } - protected abstract V delegate(); + protected abstract V _apply(); - public static LazyValue from(final Function0 get) { + public static LazyValue from(final Function0 value) { return new ImmutableLazyValue() { - public V delegate() { - return get.apply(); - } - }; - } - } - - public static abstract class CachedLazyValue extends ImmutableLazyValue { - - public void invalidateCache() { - computed = false; - } - - public static CachedLazyValue from(final Function0 get) { - return new CachedLazyValue() { - public V delegate() { - return get.apply(); + public V _apply() { + return value.apply(); } }; } diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Cached.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Memoizing.java similarity index 66% rename from pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Cached.java rename to pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Memoizing.java index d009b30a6..2f12b4ec8 100644 --- a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Cached.java +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Memoizing.java @@ -3,19 +3,21 @@ import java.util.HashMap; import java.util.Map; -public abstract class Cached { +import com.google.common.base.Function; + +public abstract class Memoizing implements Function { private final Map cache = new HashMap(); /** * @param key must not be mutated. */ - public abstract V delegate(K key); + protected abstract V _apply(K key); - public V get(K key) { + public final V apply(K key) { if (cache.containsKey(key)) return cache.get(key); - V value = delegate(key); + V value = _apply(key); if (value != null) { cache.put(key, value); return value; } diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Provider.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Provider.java index 282bb9d61..7e1759414 100644 --- a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Provider.java +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Provider.java @@ -12,7 +12,8 @@ import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.concat; +import static com.google.common.collect.Iterables.transform; import org.daisy.pipeline.braille.common.util.Function2; @@ -31,17 +32,13 @@ public Iterable get(Q query) { } } - public static abstract class CachedProvider extends Cached> implements Provider { - - /** - * delegate.get(query) must not mutate query - */ - public static CachedProvider newInstance(final Provider delegate) { - return new CachedProvider() { - public Iterable delegate(Q query) { - return delegate.get(query); - } - }; + public static abstract class MemoizingProvider extends Memoizing> implements Provider { + protected abstract Iterable _get(Q query); + public final Iterable get(Q query) { + return _get(query); + } + protected final Iterable _apply(Q query) { + return _get(query); } } @@ -74,46 +71,21 @@ private Map readProperties(URL url) { catch (Exception e) { throw new RuntimeException("Could not read properties file " + url, e); } } - public static SimpleMappingProvider newInstance(URL properties, - final Function parseKey, - final Function parseValue) { - return new SimpleMappingProvider(properties) { - public Q parseKey(String key) { - return parseKey.apply(key); - } - public X parseValue(String value) { - return parseValue.apply(value); - } - }; - } } public static abstract class DispatchingProvider implements Provider { public abstract Iterable> dispatch(); public Iterable get(final Q query) { - return Iterables.concat(Iterables.transform( + return concat(transform( dispatch(), new Function,Iterable>() { public Iterable apply(Provider provider) { - return provider.get(query); - } - } - )); - } - public static DispatchingProvider newInstance(final Iterable> dispatch) { - return new DispatchingProvider() { - @SuppressWarnings( - "unchecked" // safe cast to Iterable> - ) - public Iterable> dispatch() { - return (Iterable>)dispatch; - } - }; + return provider.get(query); }})); } } public static abstract class LocaleBasedProvider implements Provider { - public abstract Iterable delegate(Q query); + public abstract Iterable _get(Q query); public abstract Locale getLocale(Q query); /** * @param query must not be mutated @@ -127,7 +99,7 @@ public Locale getLocale(Locale query) { public Locale assocLocale(Locale query, Locale locale) { return locale; } - public Iterable get(final Q query) { + public final Iterable get(final Q query) { return new Iterable() { public Iterator iterator() { return new Iterator() { @@ -139,19 +111,19 @@ public boolean hasNext() { switch (tryNext) { case 1: tryNext++; - next = delegate(query).iterator(); + next = _get(query).iterator(); if (locale == null || "".equals(locale.toString())) tryNext = 4; break; case 2: tryNext++; if (!"".equals(locale.getVariant())) - next = delegate(assocLocale(query, new Locale(locale.getLanguage(), locale.getCountry()))).iterator(); + next = _get(assocLocale(query, new Locale(locale.getLanguage(), locale.getCountry()))).iterator(); break; case 3: tryNext++; if (!"".equals(locale.getCountry())) - next = delegate(assocLocale(query, new Locale(locale.getLanguage()))).iterator(); + next = _get(assocLocale(query, new Locale(locale.getLanguage()))).iterator(); break; case 4: tryNext++; @@ -175,11 +147,37 @@ public void remove() { public Iterable fallback(Q query) { return Optional.absent().asSet(); } - public static LocaleBasedProvider newInstance(final Provider delegate, - final Function getLocale, - final Function2 assocLocale) { + } + + public static abstract class util { + + /** + * provider.get(query) must not mutate query + */ + public static MemoizingProvider memoize(final Provider provider) { + return new MemoizingProvider() { + protected Iterable _get(Q query) { + return provider.get(query); + } + }; + } + + public static DispatchingProvider dispatch(final Iterable> dispatch) { + return new DispatchingProvider() { + @SuppressWarnings( + "unchecked" // safe cast to Iterable> + ) + public Iterable> dispatch() { + return (Iterable>)dispatch; + } + }; + } + + public static LocaleBasedProvider varyLocale(final Provider delegate, + final Function getLocale, + final Function2 assocLocale) { return new LocaleBasedProvider() { - public Iterable delegate(Q query) { + public Iterable _get(Q query) { return delegate.get(query); } public Locale getLocale(Q query) { @@ -190,9 +188,10 @@ public Q assocLocale(Q query, Locale locale) { } }; } - public static LocaleBasedProvider newInstance(final Provider delegate) { + + public static LocaleBasedProvider varyLocale(final Provider delegate) { return new LocaleBasedProvider() { - public Iterable delegate(Locale locale) { + public Iterable _get(Locale locale) { return delegate.get(locale); } }; diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/ResourceRegistry.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/ResourceRegistry.java index d77c912dc..09b1c227b 100644 --- a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/ResourceRegistry.java +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/ResourceRegistry.java @@ -30,8 +30,8 @@ protected void unregister(T path) { * Iterate over all registered resource paths and return as soon as one * path can resolve the resource. */ - protected final CachedResolver resolver = new CachedResolver() { - public URL delegate(URI resource) { + protected final MemoizingResolver resolver = new MemoizingResolver() { + public URL _apply(URI resource) { for (T path : paths.values()) { URL resolved = path.resolve(resource); if (resolved != null) diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/ResourceResolver.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/ResourceResolver.java index 602eacc7d..ee24c1348 100755 --- a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/ResourceResolver.java +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/ResourceResolver.java @@ -12,9 +12,9 @@ public interface ResourceResolver { */ public URL resolve(URI resource); - public static abstract class CachedResolver extends Cached implements ResourceResolver { + public static abstract class MemoizingResolver extends Memoizing implements ResourceResolver { public URL resolve(URI resource) { - return get(resource); + return apply(resource); } } } diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Transform.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Transform.java index 4e1be177a..9e203eb24 100644 --- a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Transform.java +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/Transform.java @@ -1,6 +1,17 @@ package org.daisy.pipeline.braille.common; -import com.google.common.collect.Iterables; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; + +import com.google.common.base.Function; +import com.google.common.collect.AbstractIterator; +import static com.google.common.collect.Iterables.transform; + +import org.daisy.pipeline.braille.common.WithSideEffect; + +import org.slf4j.Logger; /** * Tag interface for anything that can transform a node. @@ -10,20 +21,196 @@ */ public interface Transform { - public interface Provider extends org.daisy.pipeline.braille.common.Provider { + public interface Provider extends org.daisy.pipeline.braille.common.Provider, + Contextual> { + + public static abstract class MemoizingProvider + extends org.daisy.pipeline.braille.common.Provider.MemoizingProvider + implements Transform.Provider { + protected final Logger context; + private Map> providerCache; + protected MemoizingProvider(Logger context) { + this.context = context; + } + private void setProviderCache(Map> cache) { + providerCache = cache; + } + protected abstract Transform.Provider.MemoizingProvider _withContext(Logger context); + public final Transform.Provider withContext(Logger context) { + if (providerCache == null) { + providerCache = new HashMap>(); + providerCache.put(this.context, this); } + if (providerCache.containsKey(context)) + return providerCache.get(context); + Transform.Provider.MemoizingProvider provider = _withContext(context); + providerCache.put(context, provider); + provider.setProviderCache(providerCache); + return provider; + } + private static class _ extends Transform.Provider.MemoizingProvider { + private final Transform.Provider provider; + private _(Transform.Provider provider, Logger context) { + super(context); + this.provider = provider; + } + protected Iterable _get(String query) { + return provider.get(query); + } + protected Transform.Provider.MemoizingProvider _withContext(Logger context) { + return new _(provider.withContext(context), context); + } + } + } - public static class DispatchingProvider + public static abstract class DispatchingProvider extends org.daisy.pipeline.braille.common.Provider.DispatchingProvider - implements Provider { - private final Iterable> dispatch; - public DispatchingProvider(Iterable> dispatch) { - this.dispatch = dispatch; + implements Transform.Provider { + private final Logger context; + public DispatchingProvider(Logger context) { + this.context = context; } + protected abstract Iterable> _dispatch(); + public final Iterable> dispatch() { + return transform( + _dispatch(), + new Function,org.daisy.pipeline.braille.common.Provider>() { + public org.daisy.pipeline.braille.common.Provider apply(Transform.Provider provider) { + return provider.withContext(context); }}); + } + private static class _ extends Transform.Provider.DispatchingProvider { + private final Iterable> dispatch; + private _(Iterable> dispatch, Logger context) { + super(context); + this.dispatch = dispatch; + } + protected Iterable> _dispatch() { + return dispatch; + } + public Transform.Provider withContext(Logger context) { + return new _(dispatch, context); + } + } + + } + + public static abstract class AbstractProvider extends Transform.Provider.MemoizingProvider { + private final Function,T> applyContext; + protected AbstractProvider(Logger context) { + super(context); + applyContext = new Function,T>() { + public T apply(WithSideEffect value) { + return value.apply(AbstractProvider.this.context); + } + }; + } + protected abstract Iterable> __get(String query); + protected final Iterable _get(String query) { + return filterOutThrowsWithSideEffectException( + transform( + __get(query), + applyContext)); + } + private static Iterable filterOutThrowsWithSideEffectException(final Iterable iterable) { + return new Iterable() { + public Iteratoriterator() { + return new AbstractIterator() { + private Iterator i; + protected T computeNext() { + if (i == null) + i = iterable.iterator(); + while (true) { + try { + return i.next(); } + catch (WithSideEffect.Exception e) { + continue; } + catch (NoSuchElementException e) { + return endOfData(); }} + } + }; + } + }; + } + } + + public static abstract class util { + + public static Transform.Provider.MemoizingProvider memoize(Transform.Provider provider) { + return new Transform.Provider.MemoizingProvider._(provider, null); + } + @SuppressWarnings( - "unchecked" // safe cast to Provider + "unchecked" // safe cast to Iterable> ) - public Iterable> dispatch() { - return Iterables.>concat(dispatch); + public static Transform.Provider dispatch(Iterable> dispatch) { + return new Transform.Provider.DispatchingProvider._((Iterable>)dispatch, null); + } + + public static WithSideEffect logCreate(final T t) { + return new WithSideEffect() { + public T _apply() { + applyWithSideEffect(debug("Created " + t)); + return t; }}; + } + + public static Iterable> logSelect(final String query, + final Iterable iterable) { + return new Iterable>() { + public Iterator> iterator() { + return new Iterator>() { + Iterator i = null; + public boolean hasNext() { + if (i == null) + return true; + return i.hasNext(); + } + public WithSideEffect next() { + final T t; + if (i == null) { + i = iterable.iterator(); + try { t = i.next(); } + catch (final NoSuchElementException e) { + return new WithSideEffect() { + public T _apply() { + applyWithSideEffect(debug("No match for query " + query)); + throw e; + } + }; + } + } else + t = i.next(); + return new WithSideEffect() { + public T _apply() { + applyWithSideEffect(info("Selected " + t + " for query " + query)); + return t; + } + }; + } + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } + + private static Function debug(final String message) { + return new Function() { + public Void apply(Logger logger) { + if (logger != null) + logger.debug(message); + return null; + } + }; + } + + private static Function info(final String message) { + return new Function() { + public Void apply(Logger logger) { + if (logger != null) + logger.info(message); + return null; + } + }; } } } diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/WithSideEffect.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/WithSideEffect.java new file mode 100644 index 000000000..ad41a0b51 --- /dev/null +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/WithSideEffect.java @@ -0,0 +1,73 @@ +package org.daisy.pipeline.braille.common; + +import java.util.List; +import java.util.NoSuchElementException; + +import com.google.common.collect.ImmutableList; + +public abstract class WithSideEffect implements com.google.common.base.Function { + + private T value = null; + private boolean computed = false; + + public final T apply(W world) throws Exception { + if (!computed) { + sideEffectsBuilder = new ImmutableList.Builder>(); + firstWorld = world; + try { + value = _apply(); + sideEffects = sideEffectsBuilder.build(); + computed = true; } + catch (Throwable t) { + throw new Exception(t); } + finally { + sideEffectsBuilder = null; + firstWorld = null; }} + else + for (com.google.common.base.Function sideEffect : sideEffects) + try { sideEffect.apply(world); } catch(Throwable t) {} + return value; + } + + protected abstract T _apply() throws Throwable; + + private List> sideEffects; + private ImmutableList.Builder> sideEffectsBuilder; + private W firstWorld; + + protected final V applyWithSideEffect(final com.google.common.base.Function withSideEffect) { + sideEffectsBuilder.add(withSideEffect); + return withSideEffect.apply(firstWorld); + } + + @SuppressWarnings("serial") + public static class Exception extends NoSuchElementException { + private final Throwable cause; + private Exception(Throwable cause) { + this.cause = cause; + } + @Override + public Throwable getCause() { + return cause; + } + } + + public static abstract class Function implements com.google.common.base.Function,WithSideEffect> { + public abstract T _apply(F input); + public final WithSideEffect apply(final WithSideEffect input) { + return new WithSideEffect() { + public T _apply() { + current = this; + try { + return Function.this._apply(applyWithSideEffect(input)); } + finally { + current = null; } + } + }; + } + private WithSideEffect current; + protected final V applyWithSideEffect(final com.google.common.base.Function withSideEffect) { + return current.applyWithSideEffect(withSideEffect); + } + } +} diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/calabash/JobContextImpl.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/calabash/JobContextImpl.java new file mode 100644 index 000000000..b9cf591e7 --- /dev/null +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/calabash/JobContextImpl.java @@ -0,0 +1,67 @@ +package org.daisy.pipeline.braille.common.calabash; + +import com.xmlcalabash.core.XProcMessageListener; +import com.xmlcalabash.core.XProcRunnable; + +import net.sf.saxon.s9api.XdmNode; + +import org.daisy.pipeline.braille.common.JobContext.AbstractJobContext; + +public class JobContextImpl extends AbstractJobContext { + + private static final long serialVersionUID = 1L; + + private final XProcMessageListener listener; + private final XProcRunnable step; + private final XdmNode node; + + public JobContextImpl(XProcMessageListener listener) { + this(listener, null, null); + } + + public JobContextImpl(XProcMessageListener listener, XProcRunnable step, XdmNode node) { + this.listener = listener; + this.step = step; + this.node = node; + } + + public boolean isTraceEnabled() { + return true; + } + + public boolean isDebugEnabled() { + return true; + } + + public boolean isInfoEnabled() { + return true; + } + + public boolean isWarnEnabled() { + return true; + } + + public boolean isErrorEnabled() { + return true; + } + + protected void doTrace(String msg) { + listener.finer(step, node, msg); + } + + protected void doDebug(String msg) { + listener.fine(step, node, msg); + } + + protected void doInfo(String msg) { + listener.info(step, node, msg); + } + + protected void doWarn(String msg) { + listener.warning(step, node, msg); + } + + protected void doError(String msg) { + listener.error(step, node, msg, null); + } +} diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/calabash/PxTransformStep.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/calabash/PxTransformStep.java index 681a7e667..262a04fcc 100644 --- a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/calabash/PxTransformStep.java +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/calabash/PxTransformStep.java @@ -11,7 +11,7 @@ import static com.google.common.base.Predicates.alwaysFalse; import static com.google.common.base.Predicates.alwaysTrue; import static com.google.common.base.Predicates.instanceOf; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.filter; import com.xmlcalabash.core.XProcException; import com.xmlcalabash.core.XProcRuntime; @@ -27,9 +27,10 @@ import org.daisy.common.xproc.calabash.XProcStepProvider; import org.daisy.pipeline.braille.common.CSSBlockTransform; import org.daisy.pipeline.braille.common.CSSStyledDocumentTransform; +import org.daisy.pipeline.braille.common.JobContext; import org.daisy.pipeline.braille.common.MathMLTransform; import org.daisy.pipeline.braille.common.Transform; -import org.daisy.pipeline.braille.common.Transform.Provider.DispatchingProvider; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.dispatch; import org.daisy.pipeline.braille.common.util.Tuple3; import org.daisy.pipeline.braille.common.XProcTransform; @@ -43,6 +44,7 @@ public class PxTransformStep extends Eval { + private final JobContext context; private final Iterable> providers; private final ReadableDocument pipeline; @@ -56,6 +58,7 @@ public class PxTransformStep extends Eval { private PxTransformStep(XProcRuntime runtime, XAtomicStep step, Iterable> providers) { super(runtime, step); + this.context = new JobContextImpl(runtime.getMessageListener()); this.providers = providers; pipeline = new ReadableDocument(runtime); setInput("pipeline", pipeline); @@ -97,7 +100,7 @@ else if (type.equals("#any")) filter = alwaysFalse(); XProcTransform transform = null; try { - transform = new DispatchingProvider(Iterables.filter(providers, filter)).get(query).iterator().next(); } + transform = dispatch(filter(providers, filter)).withContext(context).get(query).iterator().next(); } catch (NoSuchElementException e) { throw new RuntimeException("Could not find an XProcTransform for query: " + query + " and type: " + type); } RuntimeValue tempDir = getOption(_temp_dir); diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/saxon/TextTransformDefinition.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/saxon/TextTransformDefinition.java index 6eb7c7ba6..fbd84d49d 100644 --- a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/saxon/TextTransformDefinition.java +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/saxon/TextTransformDefinition.java @@ -13,11 +13,11 @@ import net.sf.saxon.value.SequenceType; import net.sf.saxon.value.StringValue; -import org.daisy.pipeline.braille.common.Provider.CachedProvider; +import org.daisy.pipeline.braille.common.Provider; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; import org.daisy.pipeline.braille.common.TextTransform; import org.daisy.pipeline.braille.common.Transform; -import org.daisy.pipeline.braille.common.Transform.Provider.DispatchingProvider; - +import static org.daisy.pipeline.braille.common.Transform.Provider.util.dispatch; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ReferenceCardinality; @@ -59,8 +59,8 @@ protected void unbindTextTransformProvider(TextTransform.Provider provider) { private List> providers = new ArrayList>(); - private CachedProvider translators - = CachedProvider.newInstance(new DispatchingProvider(providers)); + private Provider.MemoizingProvider translators + = memoize(dispatch(providers)); public StructuredQName getFunctionQName() { return funcname; diff --git a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/util.java b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/util.java index 11fd34efb..f81119bc9 100755 --- a/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/util.java +++ b/pipeline-braille-utils/common-utils/src/main/java/org/daisy/pipeline/braille/common/util.java @@ -124,7 +124,27 @@ public boolean equals(Object obj) { public static abstract class Functions { public static Function0 noOp = new Function0 () { - public Void apply() { return null; }}; + public Void apply() { return null; } + }; + + public static Function sideEffect(final Function function) { + return new Function() { + public Void apply(F input) { + function.apply(input); + return null; + } + }; + } + + public static Function doAll(final Iterable> functions) { + return new Function() { + public Void apply(F input) { + for (Function f : functions) + f.apply(input); + return null; + } + }; + } } public static abstract class Predicates { diff --git a/pipeline-braille-utils/common-utils/src/test/java/CommonUtilsTest.java b/pipeline-braille-utils/common-utils/src/test/java/CommonUtilsTest.java index 2d15134d3..b07f0d510 100644 --- a/pipeline-braille-utils/common-utils/src/test/java/CommonUtilsTest.java +++ b/pipeline-braille-utils/common-utils/src/test/java/CommonUtilsTest.java @@ -14,6 +14,7 @@ import org.daisy.pipeline.braille.common.TextTransform; import org.daisy.pipeline.braille.common.TextTransform.ContextUnawareTextTransform; +import org.daisy.pipeline.braille.common.Transform; import static org.daisy.pipeline.braille.common.util.Strings.extractHyphens; import static org.daisy.pipeline.braille.common.util.Tuple3; import static org.daisy.pipeline.braille.common.util.URIs.asURI; @@ -46,6 +47,8 @@ import org.osgi.framework.BundleContext; +import org.slf4j.Logger; + @RunWith(PaxExam.class) @ExamReactorStrategy(PerClass.class) public class CommonUtilsTest { @@ -69,12 +72,7 @@ public Option[] config() { @Before public void registerUppercaseTransformProvider() { - final UppercaseTransform transform = new UppercaseTransform(); - UppercaseTransform.Provider provider - = new UppercaseTransform.Provider() { - public Iterable get(String query) { - return Optional.fromNullable( - query.equals("(uppercase)") ? transform : null).asSet(); }}; + UppercaseTransform.Provider provider = new UppercaseTransform.Provider(); Hashtable properties = new Hashtable(); context.registerService(TextTransform.Provider.class.getName(), provider, properties); context.registerService(XProcTransform.Provider.class.getName(), provider, properties); @@ -88,7 +86,25 @@ public String transform(String text) { public Tuple3> asXProc() { return new Tuple3>(href, null, null); } - public interface Provider extends TextTransform.Provider, XProcTransform.Provider {} + private static final UppercaseTransform instance = new UppercaseTransform(); + public static class Provider implements TextTransform.Provider, XProcTransform.Provider { + private Logger logger; + public Provider() {} + private Provider(Logger context) { + logger = context; + } + public Iterable get(String query) { + if (query.equals("(uppercase)")) { + if (logger != null) + logger.info("Selecting " + instance); + return Optional.fromNullable(instance).asSet(); } + else + return Optional.fromNullable(null).asSet(); + } + public Transform.Provider withContext(Logger context) { + return new Provider(context); + } + } } @Test diff --git a/pipeline-braille-utils/css-utils/css-calabash/src/main/java/org/daisy/pipeline/braille/css/calabash/CSSInlineStep.java b/pipeline-braille-utils/css-utils/css-calabash/src/main/java/org/daisy/pipeline/braille/css/calabash/CSSInlineStep.java index 0b120b5fe..ea21b0c61 100755 --- a/pipeline-braille-utils/css-utils/css-calabash/src/main/java/org/daisy/pipeline/braille/css/calabash/CSSInlineStep.java +++ b/pipeline-braille-utils/css-utils/css-calabash/src/main/java/org/daisy/pipeline/braille/css/calabash/CSSInlineStep.java @@ -14,8 +14,9 @@ import com.google.common.base.Function; import static com.google.common.base.Strings.emptyToNull; import com.google.common.base.Objects; -import com.google.common.collect.Iterables; -import com.google.common.collect.Iterators; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.toArray; +import static com.google.common.collect.Iterators.addAll; import com.xmlcalabash.core.XProcException; import com.xmlcalabash.core.XProcRuntime; @@ -194,7 +195,7 @@ public InlineCSSWriter(Document document, printStylemap = new Analyzer(printStyle).evaluateDOM(document, "print", false); pages = new HashMap(); - for (RulePage page : Iterables.filter(brailleStyle, RulePage.class)) + for (RulePage page : filter(brailleStyle, RulePage.class)) pages.put(Objects.firstNonNull(page.getName(), "auto"), page); startDocument(baseURI); @@ -267,8 +268,8 @@ public void addStartElement(Element element) { inscopeNS = inode.getDeclaredNamespaces(null); else { List namespaces = new ArrayList(); - Iterators.addAll(namespaces, NamespaceIterator.iterateNamespaces(inode)); - inscopeNS = Iterables.toArray(namespaces, NamespaceBinding.class); + addAll(namespaces, NamespaceIterator.iterateNamespaces(inode)); + inscopeNS = toArray(namespaces, NamespaceBinding.class); seenRoot = true; } receiver.setSystemId(element.getBaseURI()); addStartElement(new NameOfNode(inode), inode.getSchemaType(), inscopeNS); @@ -318,19 +319,19 @@ private static void insertPageStyle(StringBuilder builder, RulePage rulePage, Ru builder.append(":").append(pseudo).append(" "); builder.append("{ "); List seen = new ArrayList(); - for (Declaration decl : Iterables.filter(rulePage, Declaration.class)) { + for (Declaration decl : filter(rulePage, Declaration.class)) { seen.add(decl.getProperty()); insertDeclaration(builder, decl); } if (inheritFrom != null) - for (Declaration decl : Iterables.filter(inheritFrom, Declaration.class)) + for (Declaration decl : filter(inheritFrom, Declaration.class)) if (!seen.contains(decl.getProperty())) insertDeclaration(builder, decl); seen.clear(); - for (RuleMargin margin : Iterables.filter(rulePage, RuleMargin.class)) { + for (RuleMargin margin : filter(rulePage, RuleMargin.class)) { seen.add(margin.getMarginArea().value); insertMarginStyle(builder, margin); } if (inheritFrom != null) - for (RuleMargin margin : Iterables.filter(inheritFrom, RuleMargin.class)) + for (RuleMargin margin : filter(inheritFrom, RuleMargin.class)) if (!seen.contains(margin.getMarginArea().value)) insertMarginStyle(builder, margin); builder.append("} "); diff --git a/pipeline-braille-utils/css-utils/css-utils/src/test/java/CssUtilsTest.java b/pipeline-braille-utils/css-utils/css-utils/src/test/java/CssUtilsTest.java index 020c67e9d..daba5092f 100644 --- a/pipeline-braille-utils/css-utils/css-utils/src/test/java/CssUtilsTest.java +++ b/pipeline-braille-utils/css-utils/css-utils/src/test/java/CssUtilsTest.java @@ -10,6 +10,7 @@ import org.daisy.maven.xspec.XSpecRunner; import org.daisy.pipeline.braille.common.TextTransform; import org.daisy.pipeline.braille.common.TextTransform.ContextUnawareTextTransform; +import org.daisy.pipeline.braille.common.Transform; import static org.daisy.pipeline.pax.exam.Options.brailleModule; import static org.daisy.pipeline.pax.exam.Options.domTraversalPackage; @@ -39,6 +40,8 @@ import org.osgi.framework.BundleContext; +import org.slf4j.Logger; + @RunWith(PaxExam.class) @ExamReactorStrategy(PerClass.class) public class CssUtilsTest { @@ -76,7 +79,12 @@ public Iterable get(String query) { ? new ContextUnawareTextTransform() { public String transform(String text) { return text.toUpperCase(); }} - : null).asSet(); }}, + : null).asSet(); + } + public Transform.Provider withContext(Logger context) { + return this; + } + }, new Hashtable()); } diff --git a/pipeline-braille-utils/dotify-utils/dotify-core/src/main/java/org/daisy/pipeline/braille/dotify/DotifyHyphenator.java b/pipeline-braille-utils/dotify-utils/dotify-core/src/main/java/org/daisy/pipeline/braille/dotify/DotifyHyphenator.java index 8cd634004..20a442494 100644 --- a/pipeline-braille-utils/dotify-utils/dotify-core/src/main/java/org/daisy/pipeline/braille/dotify/DotifyHyphenator.java +++ b/pipeline-braille-utils/dotify-utils/dotify-core/src/main/java/org/daisy/pipeline/braille/dotify/DotifyHyphenator.java @@ -13,7 +13,9 @@ import org.daisy.dotify.api.hyphenator.HyphenatorInterface; import org.daisy.dotify.api.hyphenator.HyphenatorFactoryService; import org.daisy.pipeline.braille.common.Hyphenator; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; import org.daisy.pipeline.braille.common.TextTransform; +import org.daisy.pipeline.braille.common.Transform; import org.daisy.pipeline.braille.common.util.Locales; import static org.daisy.pipeline.braille.common.util.Locales.parseLocale; @@ -55,6 +57,10 @@ public HyphenatorInterface asHyphenatorInterface() { ) public static class Provider implements Hyphenator.Provider { + public Transform.Provider withContext(Logger context) { + return this; + } + /** * Try to find a translator based on the given locale. * An automatic fallback mechanism is used: if nothing is found for @@ -114,10 +120,10 @@ private HyphenatorInterface newHyphenator(String locale) throws HyphenatorConfig throw new RuntimeException("Cannot locate a factory for " + locale.toLowerCase()); } - private final CachedProvider hyphenators - = CachedProvider.newInstance( + private final org.daisy.pipeline.braille.common.Provider.MemoizingProvider hyphenators + = memoize( new LocaleBasedProvider() { - public Iterable delegate(Locale locale) { + public Iterable _get(Locale locale) { try { HyphenatorInterface hyphenator = newHyphenator(Locales.toString(locale, '-')); return Optional.of(new DotifyHyphenator(hyphenator)).asSet(); } diff --git a/pipeline-braille-utils/dotify-utils/dotify-core/src/main/java/org/daisy/pipeline/braille/dotify/DotifyTranslator.java b/pipeline-braille-utils/dotify-utils/dotify-core/src/main/java/org/daisy/pipeline/braille/dotify/DotifyTranslator.java index f96978a9f..babeb0e4b 100644 --- a/pipeline-braille-utils/dotify-utils/dotify-core/src/main/java/org/daisy/pipeline/braille/dotify/DotifyTranslator.java +++ b/pipeline-braille-utils/dotify-utils/dotify-core/src/main/java/org/daisy/pipeline/braille/dotify/DotifyTranslator.java @@ -13,7 +13,9 @@ import org.daisy.dotify.api.translator.BrailleTranslatorFactory; import org.daisy.dotify.api.translator.BrailleTranslatorFactoryService; import org.daisy.dotify.api.translator.TranslatorConfigurationException; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; import org.daisy.pipeline.braille.common.TextTransform; +import org.daisy.pipeline.braille.common.Transform; import org.daisy.pipeline.braille.common.util.Locales; import static org.daisy.pipeline.braille.common.util.Locales.parseLocale; @@ -54,6 +56,10 @@ public BrailleTranslator asBrailleTranslator() { ) public static class Provider implements TextTransform.Provider { + public Transform.Provider withContext(Logger context) { + return this; + } + /** * Try to find a translator based on the given locale. * An automatic fallback mechanism is used: if nothing is found for @@ -114,10 +120,10 @@ private BrailleTranslator newTranslator(String locale, String grade) throws Tran + locale.toLowerCase() + "(" + grade.toUpperCase() + ")"); } - private final CachedProvider translators - = CachedProvider.newInstance( + private final org.daisy.pipeline.braille.common.Provider.MemoizingProvider translators + = memoize( new LocaleBasedProvider() { - public Iterable delegate(Locale locale) { + public Iterable _get(Locale locale) { try { BrailleTranslator translator = newTranslator( Locales.toString(locale, '-'), BrailleTranslatorFactory.MODE_UNCONTRACTED); diff --git a/pipeline-braille-utils/dotify-utils/dotify-utils/src/main/java/org/daisy/pipeline/braille/dotify/transform/DotifyCSSBlockTransform.java b/pipeline-braille-utils/dotify-utils/dotify-utils/src/main/java/org/daisy/pipeline/braille/dotify/transform/DotifyCSSBlockTransform.java index dbf5d7904..b0ae420db 100644 --- a/pipeline-braille-utils/dotify-utils/dotify-utils/src/main/java/org/daisy/pipeline/braille/dotify/transform/DotifyCSSBlockTransform.java +++ b/pipeline-braille-utils/dotify-utils/dotify-utils/src/main/java/org/daisy/pipeline/braille/dotify/transform/DotifyCSSBlockTransform.java @@ -10,13 +10,15 @@ import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; +import org.daisy.pipeline.braille.common.Memoizing; import static org.daisy.pipeline.braille.css.Query.parseQuery; import static org.daisy.pipeline.braille.css.Query.serializeQuery; -import org.daisy.pipeline.braille.common.Cached; import static org.daisy.pipeline.braille.common.util.Tuple3; import static org.daisy.pipeline.braille.common.util.URIs.asURI; import org.daisy.pipeline.braille.common.CSSBlockTransform; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; import org.daisy.pipeline.braille.common.Transform; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.dispatch; import org.daisy.pipeline.braille.common.XProcTransform; import org.daisy.pipeline.braille.dotify.DotifyTranslator; @@ -27,6 +29,8 @@ import org.osgi.service.component.annotations.ReferencePolicy; import org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; + public interface DotifyCSSBlockTransform extends XProcTransform, CSSBlockTransform { @Component( @@ -45,6 +49,10 @@ private void activate(ComponentContext context, final Map properties) { href = asURI(context.getBundleContext().getBundle().getEntry("xml/transform/dotify-block-translate.xpl")); } + public Transform.Provider withContext(Logger context) { + return this; + } + /** * Recognized features: * @@ -54,12 +62,12 @@ private void activate(ComponentContext context, final Map properties) { * Other features are used for finding sub-transformers of type DotifyTranslator. */ public Iterable get(String query) { - return Optional.fromNullable(transforms.get(query)).asSet(); + return Optional.fromNullable(transforms.apply(query)).asSet(); } - private Cached transforms - = new Cached() { - public DotifyCSSBlockTransform delegate(String query) { + private Memoizing transforms + = new Memoizing() { + public DotifyCSSBlockTransform _apply(String query) { final URI href = Provider.this.href; Map> q = new HashMap>(parseQuery(query)); Optional o; @@ -94,8 +102,9 @@ protected void unbindDotifyTranslatorProvider(DotifyTranslator.Provider provider private List> dotifyTranslatorProviders = new ArrayList>(); - private CachedProvider dotifyTranslatorProvider - = CachedProvider.newInstance(new DispatchingProvider(dotifyTranslatorProviders)); + + private org.daisy.pipeline.braille.common.Provider.MemoizingProvider dotifyTranslatorProvider + = memoize(dispatch(dotifyTranslatorProviders)); } } diff --git a/pipeline-braille-utils/dotify-utils/dotify-utils/src/main/java/org/daisy/pipeline/braille/dotify/transform/DotifyCSSStyledDocumentTransform.java b/pipeline-braille-utils/dotify-utils/dotify-utils/src/main/java/org/daisy/pipeline/braille/dotify/transform/DotifyCSSStyledDocumentTransform.java index 0ee6eb9fc..300ab81ae 100644 --- a/pipeline-braille-utils/dotify-utils/dotify-utils/src/main/java/org/daisy/pipeline/braille/dotify/transform/DotifyCSSStyledDocumentTransform.java +++ b/pipeline-braille-utils/dotify-utils/dotify-utils/src/main/java/org/daisy/pipeline/braille/dotify/transform/DotifyCSSStyledDocumentTransform.java @@ -10,14 +10,16 @@ import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; +import org.daisy.pipeline.braille.common.Memoizing; import static org.daisy.pipeline.braille.css.Query.parseQuery; import static org.daisy.pipeline.braille.css.Query.serializeQuery; -import org.daisy.pipeline.braille.common.Cached; import static org.daisy.pipeline.braille.common.util.Tuple3; import static org.daisy.pipeline.braille.common.util.URIs.asURI; import org.daisy.pipeline.braille.common.CSSBlockTransform; import org.daisy.pipeline.braille.common.CSSStyledDocumentTransform; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; import org.daisy.pipeline.braille.common.Transform; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.dispatch; import org.daisy.pipeline.braille.common.XProcTransform; import org.osgi.service.component.annotations.Activate; @@ -27,6 +29,8 @@ import org.osgi.service.component.annotations.ReferencePolicy; import org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; + public interface DotifyCSSStyledDocumentTransform extends XProcTransform, CSSStyledDocumentTransform { @Component( @@ -46,6 +50,10 @@ private void activate(ComponentContext context, final Map properties) { href = asURI(context.getBundleContext().getBundle().getEntry("xml/transform/dotify-transform.xpl")); } + public Transform.Provider withContext(Logger context) { + return this; + } + /** * Recognized features: * @@ -54,12 +62,12 @@ private void activate(ComponentContext context, final Map properties) { * Other features are used for finding sub-transformers of type CSSBlockTransform. */ public Iterable get(String query) { - return Optional.fromNullable(transforms.get(query)).asSet(); + return Optional.fromNullable(transforms.apply(query)).asSet(); } - private Cached transforms - = new Cached() { - public DotifyCSSStyledDocumentTransform delegate(String query) { + private Memoizing transforms + = new Memoizing() { + public DotifyCSSStyledDocumentTransform _apply(String query) { final URI href = Provider.this.href; Map> q = new HashMap>(parseQuery(query)); Optional o; @@ -99,8 +107,8 @@ public void unbindCSSBlockTransformProvider(CSSBlockTransform.Provider provid private List> cssBlockTransformProviders = new ArrayList>(); - private CachedProvider cssBlockTransformProvider - = CachedProvider.newInstance(new DispatchingProvider(cssBlockTransformProviders)); + private org.daisy.pipeline.braille.common.Provider.MemoizingProvider cssBlockTransformProvider + = memoize(dispatch(cssBlockTransformProviders)); } } diff --git a/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/LibhyphenTablePath.java b/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/LibhyphenTablePath.java index a3d9686f9..9fd92d158 100644 --- a/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/LibhyphenTablePath.java +++ b/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/LibhyphenTablePath.java @@ -8,7 +8,7 @@ import static com.google.common.base.Functions.toStringFunction; import com.google.common.base.Optional; import com.google.common.base.Predicates; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.filter; import org.daisy.pipeline.braille.common.BundledResourcePath; import org.daisy.pipeline.braille.common.Provider; @@ -37,7 +37,7 @@ public Iterable get(Locale locale) { } private Provider provider = new LocaleBasedProvider() { - public Iterable delegate(Locale locale) { + public Iterable _get(Locale locale) { String language = locale.getLanguage().toLowerCase(); String country = locale.getCountry().toUpperCase(); String variant = locale.getVariant().toLowerCase(); @@ -54,7 +54,7 @@ else if (!"".equals(country)) } @Override public Iterable fallback(Locale locale) { - return Iterables.filter( + return filter( resources, Predicates.compose( matchesGlobPattern(String.format("hyph_%s_*.dic", locale.getLanguage().toLowerCase())), diff --git a/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/LibhyphenTableRegistry.java b/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/LibhyphenTableRegistry.java index b4635608a..5f56b497f 100644 --- a/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/LibhyphenTableRegistry.java +++ b/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/LibhyphenTableRegistry.java @@ -7,6 +7,10 @@ import com.google.common.base.Predicate; +import org.daisy.pipeline.braille.common.Provider; +import static org.daisy.pipeline.braille.common.Provider.util.dispatch; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; +import static org.daisy.pipeline.braille.common.Provider.util.varyLocale; import org.daisy.pipeline.braille.common.ResourcePath; import org.daisy.pipeline.braille.common.ResourceRegistry; @@ -40,10 +44,10 @@ public Iterable get(Locale locale) { return provider.get(locale); } - private final CachedProvider provider - = CachedProvider.newInstance( - LocaleBasedProvider.newInstance( - DispatchingProvider.newInstance(paths.values()))); + private final Provider.MemoizingProvider provider + = memoize( + varyLocale( + dispatch(paths.values()))); @Override public URL resolve(URI resource) { diff --git a/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/impl/LibhyphenJnaImpl.java b/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/impl/LibhyphenJnaImpl.java index bfd04fed6..30b742012 100644 --- a/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/impl/LibhyphenJnaImpl.java +++ b/pipeline-braille-utils/libhyphen-utils/libhyphen-core/src/main/java/org/daisy/pipeline/braille/libhyphen/impl/LibhyphenJnaImpl.java @@ -12,14 +12,19 @@ import com.google.common.base.Function; import com.google.common.base.Optional; -import com.google.common.base.Predicates; +import static com.google.common.base.Predicates.notNull; import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.getFirst; +import static com.google.common.collect.Iterables.toArray; +import static com.google.common.collect.Iterables.transform; import static org.daisy.pipeline.braille.css.Query.parseQuery; import org.daisy.pipeline.braille.common.BundledNativePath; +import org.daisy.pipeline.braille.common.Provider; import org.daisy.pipeline.braille.common.ResourceResolver; import org.daisy.pipeline.braille.common.TextTransform; +import org.daisy.pipeline.braille.common.Transform; import static org.daisy.pipeline.braille.common.util.Files.asFile; import static org.daisy.pipeline.braille.common.util.Files.isAbsoluteFile; import static org.daisy.pipeline.braille.common.util.Locales.parseLocale; @@ -79,7 +84,7 @@ protected void deactivate() { ) protected void bindLibrary(BundledNativePath path) { if (nativePath == null) { - URI libraryPath = Iterables.getFirst(path.get("libhyphen"), null); + URI libraryPath = getFirst(path.get("libhyphen"), null); if (libraryPath != null) { Hyphen.setLibraryPath(asFile(path.resolve(libraryPath))); nativePath = path; @@ -132,9 +137,9 @@ private LibhyphenHyphenator get(URI table) { private final static Iterable empty = Optional.absent().asSet(); - private CachedProvider provider - = new CachedProvider() { - public Iterable delegate(String query) { + private Provider.MemoizingProvider provider + = new Provider.MemoizingProvider() { + public Iterable _get(String query) { Map> q = parseQuery(query); if (q.containsKey("hyphenator")) if (!"hyphen".equals(q.get("hyphenator").get())) @@ -148,19 +153,23 @@ public Iterable delegate(String query) { else locale = parseLocale("und"); if (tableProvider != null) { - return Iterables.filter( - Iterables.transform( + return filter( + transform( tableProvider.get(locale), new Function() { public LibhyphenHyphenator apply(URI table) { return LibhyphenJnaImpl.this.get(table); }}), - Predicates.notNull()); } + notNull()); } return empty; }}; public Iterable get(String query) { return provider.get(query); } + public Transform.Provider withContext(Logger context) { + return this; + } + private final static char US = '\u001F'; private final static Splitter SEGMENT_SPLITTER = Splitter.on(US); @@ -192,7 +201,7 @@ public String[] transform(String[] text) { // positions but also the segment boundaries. byte[] positions; Tuple2 t = extractHyphens(join(text, US), SHY, ZWSP); - String[] unhyphenated = Iterables.toArray(SEGMENT_SPLITTER.split(t._1), String.class); + String[] unhyphenated = toArray(SEGMENT_SPLITTER.split(t._1), String.class); t = extractHyphens(t._2, t._1, null, null, US); String _text = t._1; if (t._2 != null) diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTable.java b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTable.java index eff3e4af9..9e97d9dba 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTable.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTable.java @@ -3,7 +3,8 @@ import java.net.URI; import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.toArray; +import static com.google.common.collect.Iterables.transform; import static org.daisy.pipeline.braille.common.util.Strings.join; import static org.daisy.pipeline.braille.common.util.URIs.asURI; @@ -29,8 +30,8 @@ public String toString() { } public static URI[] tokenizeTable(String table) { - return Iterables.toArray( - Iterables.transform( + return toArray( + transform( Splitter.on(',').split(table), asURI), URI.class); diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTablePath.java b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTablePath.java index 85a3487c0..04950e916 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTablePath.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTablePath.java @@ -4,7 +4,7 @@ import java.util.Map; import com.google.common.base.Function; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.transform; import org.daisy.pipeline.braille.common.BundledResourcePath; @@ -25,7 +25,7 @@ protected void activate(ComponentContext context, Map properties) throws Ex } public Iterable listTableFiles() { - return Iterables.transform( + return transform( resources, new Function() { public URI apply(URI resource) { diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTableRegistry.java b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTableRegistry.java index 5ea45bd59..025bccc9f 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTableRegistry.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTableRegistry.java @@ -9,7 +9,8 @@ import com.google.common.base.Function; import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.concat; +import static com.google.common.collect.Iterables.transform; import org.daisy.pipeline.braille.common.ResourcePath; import org.daisy.pipeline.braille.common.ResourceRegistry; @@ -133,8 +134,8 @@ public Iterable apply(LiblouisTablePath path) { }; public Iterable listAllTableFiles() { - return Iterables.concat( - Iterables.>transform( + return concat( + transform( paths.values(), listTableFiles)); } diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTranslator.java b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTranslator.java index 8b00cb828..f1138d182 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTranslator.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/LiblouisTranslator.java @@ -2,7 +2,6 @@ import org.daisy.pipeline.braille.common.BrailleTranslator; import org.daisy.pipeline.braille.common.CSSStyledTextTransform; -import org.daisy.pipeline.braille.common.TextTransform; public abstract class LiblouisTranslator implements CSSStyledTextTransform, BrailleTranslator { diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisHyphenatorJnaImpl.java b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisHyphenatorJnaImpl.java index f7b78378b..8cdd9a28e 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisHyphenatorJnaImpl.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisHyphenatorJnaImpl.java @@ -6,12 +6,15 @@ import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.toArray; +import static com.google.common.collect.Iterables.transform; import static org.daisy.pipeline.braille.css.Query.parseQuery; import static org.daisy.pipeline.braille.css.Query.serializeQuery; import org.daisy.pipeline.braille.common.Hyphenator; +import org.daisy.pipeline.braille.common.Provider; import org.daisy.pipeline.braille.common.TextTransform; +import org.daisy.pipeline.braille.common.Transform; import org.daisy.pipeline.braille.common.util.Locales; import static org.daisy.pipeline.braille.common.util.Locales.parseLocale; import static org.daisy.pipeline.braille.common.util.Strings.extractHyphens; @@ -60,6 +63,10 @@ protected void unbindLiblouisJnaImpl(LiblouisJnaImpl provider) { tableProvider = null; } + public Transform.Provider withContext(Logger context) { + return this; + } + /** * Recognized features: * @@ -81,8 +88,9 @@ public Iterable get(String query) { private final static Iterable empty = Optional.absent().asSet(); - private CachedProvider provider = new CachedProvider() { - public Iterable delegate(String query) { + private Provider.MemoizingProvider provider + = new Provider.MemoizingProvider() { + public Iterable _get(String query) { final Map> q = new HashMap>(parseQuery(query)); Optional o; if ((o = q.remove("hyphenator")) != null) @@ -111,7 +119,7 @@ public Iterable delegate(String query) { if (locale != null) q.put("locale", Optional.of(Locales.toString(parseLocale(locale), '_'))); Iterable tables = tableProvider.get(serializeQuery(q)); - return Iterables.transform( + return transform( tables, new Function() { public LiblouisHyphenator apply(Translator table) { @@ -147,7 +155,7 @@ public String[] transform(String text[]) { // positions but also the segment boundaries. byte[] positions; Tuple2 t = extractHyphens(join(text, US), SHY, ZWSP); - String[] unhyphenated = Iterables.toArray(SEGMENT_SPLITTER.split(t._1), String.class); + String[] unhyphenated = toArray(SEGMENT_SPLITTER.split(t._1), String.class); t = extractHyphens(t._2, t._1, null, null, US); String _text = t._1; if (t._2 != null) diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImpl.java b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImpl.java index e53e5ff3c..acc0ab303 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImpl.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImpl.java @@ -1,7 +1,6 @@ package org.daisy.pipeline.braille.liblouis.impl; import java.io.File; -import java.net.URI; import java.net.URL; import java.util.HashMap; import java.util.Locale; @@ -10,8 +9,11 @@ import com.google.common.base.Function; import static com.google.common.base.Functions.toStringFunction; import com.google.common.base.Optional; -import com.google.common.base.Predicates; -import com.google.common.collect.Iterables; +import static com.google.common.base.Predicates.notNull; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.getFirst; +import static com.google.common.collect.Iterables.toArray; +import static com.google.common.collect.Iterables.transform; import static org.daisy.pipeline.braille.css.Query.parseQuery; import org.daisy.pipeline.braille.common.BundledNativePath; @@ -132,8 +134,8 @@ private void lazyIndex() { return; logger.debug("Indexing tables"); Louis.getLibrary().lou_indexTables( - Iterables.toArray( - Iterables.transform( + toArray( + transform( tableRegistry.listAllTableFiles(), toStringFunction()), String.class)); @@ -154,7 +156,7 @@ protected void deactivate() { ) protected void bindLibrary(BundledNativePath path) { if (!LIBLOUIS_EXTERNAL && nativePath == null) { - URL libraryPath = path.resolve(Iterables.getFirst(path.get("liblouis"), null)); + URL libraryPath = path.resolve(getFirst(path.get("liblouis"), null)); if (libraryPath != null) { Louis.setLibraryPath(asFile(libraryPath)); nativePath = path; @@ -186,22 +188,22 @@ public Iterable get(String query) { return provider.get(query); } - private CachedProvider provider - = new CachedProvider() { - public Iterable delegate(final String query) { - return provider_.get(parseQuery(query)); + private Provider.MemoizingProvider provider + = new Provider.MemoizingProvider() { + public Iterable _get(final String query) { + return _provider.get(parseQuery(query)); } @Override public void invalidateCache() { super.invalidateCache(); - provider__.invalidateCache(); + __provider.invalidateCache(); } }; - private Provider>,Translator> provider_ + private Provider>,Translator> _provider = new LocaleBasedProvider>,Translator>() { - public Iterable delegate(final Map> query) { - return provider__.get(query); + public Iterable _get(final Map> query) { + return __provider.get(query); } public Locale getLocale(Map> query) { Optional o; @@ -217,13 +219,13 @@ public Map> assocLocale(Map> que } }; - private CachedProvider>,Translator> provider__ - = new CachedProvider>,Translator>() { - public Iterable delegate(final Map> query) { + private Provider.MemoizingProvider>,Translator> __provider + = new Provider.MemoizingProvider>,Translator>() { + public Iterable _get(final Map> query) { final Map> q = new HashMap>(query); - return Iterables.filter( + return filter( new ImmutableLazyValue() { - public Translator delegate() { + public Translator _apply() { String table = null; boolean unicode = false; Optional o; @@ -256,7 +258,7 @@ else if (q.size() > 0) { catch (CompilationException e) { logger.warn("Could not compile translator", e); }} return null; }}, - Predicates.notNull()); + notNull()); } }; diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisTranslatorJnaImpl.java b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisTranslatorJnaImpl.java index 51971b7ca..00bfc213c 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisTranslatorJnaImpl.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisTranslatorJnaImpl.java @@ -10,15 +10,21 @@ import com.google.common.base.Function; import static com.google.common.base.Objects.toStringHelper; import com.google.common.base.Optional; -import com.google.common.base.Predicates; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.concat; +import static com.google.common.collect.Iterables.toArray; +import static com.google.common.collect.Iterables.transform; import static org.daisy.pipeline.braille.css.Query.parseQuery; import static org.daisy.pipeline.braille.css.Query.serializeQuery; import org.daisy.pipeline.braille.common.Hyphenator; +import org.daisy.pipeline.braille.common.Provider; import org.daisy.pipeline.braille.common.Transform; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.memoize; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.dispatch; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.logCreate; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.logSelect; import org.daisy.pipeline.braille.common.TextTransform; import org.daisy.pipeline.braille.common.util.Locales; import static org.daisy.pipeline.braille.common.util.Locales.parseLocale; @@ -26,6 +32,7 @@ import static org.daisy.pipeline.braille.common.util.Strings.insertHyphens; import static org.daisy.pipeline.braille.common.util.Strings.join; import static org.daisy.pipeline.braille.common.util.Tuple2; +import org.daisy.pipeline.braille.common.WithSideEffect; import org.daisy.pipeline.braille.liblouis.LiblouisTable; import static org.daisy.pipeline.braille.liblouis.LiblouisTable.tokenizeTable; @@ -103,8 +110,8 @@ protected void unbindHyphenatorProvider(Hyphenator.Provider provider) { private List> hyphenatorProviders = new ArrayList>(); - private CachedProvider hyphenatorProvider - = CachedProvider.newInstance(new DispatchingProvider(hyphenatorProviders)); + private Provider.MemoizingProvider hyphenatorProvider + = memoize(dispatch(hyphenatorProviders)); /** * Recognized features: @@ -131,13 +138,29 @@ protected void unbindHyphenatorProvider(Hyphenator.Provider provider) { * A translator will only use external hyphenators with the same locale as the translator itself. */ public Iterable get(String query) { - return provider.get(query); + return impl.get(query); } - private final static Iterable empty = Optional.absent().asSet(); + public Transform.Provider withContext(Logger context) { + return impl.withContext(context); + } + + private Transform.Provider.MemoizingProvider impl = new ProviderImpl(null); - private CachedProvider provider = new CachedProvider() { - public Iterable delegate(String query) { + private final static Iterable> empty + = Optional.>absent().asSet(); + + private class ProviderImpl extends AbstractProvider { + + private ProviderImpl(Logger context) { + super(context); + } + + protected Transform.Provider.MemoizingProvider _withContext(Logger context) { + return new ProviderImpl(context); + } + + protected final Iterable> __get(String query) { final Map> q = new HashMap>(parseQuery(query)); Optional o; if ((o = q.remove("translator")) != null) @@ -172,18 +195,19 @@ public Iterable delegate(String query) { q.put("locale", Optional.of(Locales.toString(parseLocale(locale), '_'))); q.put("unicode", Optional.absent()); Iterable tables = tableProvider.get(serializeQuery(q)); - return Iterables.concat( - Iterables.>transform( + return concat( + transform( tables, - new Function>() { - public Iterable apply(final Translator table) { - Iterable translators = empty; + new Function>>() { + public Iterable> apply(final Translator table) { + Iterable> translators = empty; if (!"none".equals(hyphenator)) { if ("liblouis".equals(hyphenator) || "auto".equals(hyphenator)) for (URI t : tokenizeTable(table.getTable())) if (t.toString().endsWith(".dic")) { - translators = Optional.of( - new LiblouisTranslatorHyphenatorImpl(table)).asSet(); + translators = Optional.of( + logCreate((LiblouisTranslator)new LiblouisTranslatorHyphenatorImpl(table)) + ).asSet(); break; } if (!"liblouis".equals("hyphenator")) { if (locale == null) { @@ -196,27 +220,32 @@ public Iterable apply(final Translator table) { if (!"auto".equals(hyphenator)) hyphenatorQuery.put("hyphenator", Optional.of(hyphenator)); hyphenatorQuery.put("locale", Optional.of(locale)); - Iterable hyphenators = hyphenatorProvider.get(serializeQuery(hyphenatorQuery.build())); - translators = Iterables.concat( + String hyphenatorQueryString = serializeQuery(hyphenatorQuery.build()); + Iterable> hyphenators + = logSelect(hyphenatorQueryString, hyphenatorProvider.get(hyphenatorQueryString)); + translators = concat( translators, - Iterables.filter( - Iterables.transform( - hyphenators, - new Function() { - public LiblouisTranslator apply(Hyphenator hyphenator) { - return new LiblouisTranslatorImpl(table, hyphenator); }}), - Predicates.notNull())); }}} + transform( + hyphenators, + new WithSideEffect.Function() { + public LiblouisTranslator _apply(Hyphenator hyphenator) { + return applyWithSideEffect( + logCreate( + (LiblouisTranslator)new LiblouisTranslatorImpl(table, hyphenator))); }})); + }}} if ("none".equals(hyphenator) || "auto".equals(hyphenator)) - translators = Iterables.concat( + translators = concat( translators, - Optional.of(new LiblouisTranslatorImpl(table)).asSet()); + Optional.of( + logCreate((LiblouisTranslator)new LiblouisTranslatorImpl(table)) + ).asSet()); return translators; } } ) ); } - }; + } private static class LiblouisTranslatorImpl extends LiblouisTranslator { @@ -288,7 +317,7 @@ public String[] transform(String[] text, byte[] typeform, boolean[] hyphenate) { // array. byte[] positions; Tuple2 t = extractHyphens(join(text, US), SHY, ZWSP); - String[] unhyphenated = Iterables.toArray(SEGMENT_SPLITTER.split(t._1), String.class); + String[] unhyphenated = toArray(SEGMENT_SPLITTER.split(t._1), String.class); t = extractHyphens(t._2, t._1, null, null, US); String _text = t._1; if (_text.length() == 0) @@ -357,7 +386,7 @@ public String[] transform(String[] text, byte[] typeform, boolean[] hyphenate) { + "Input segments: " + Arrays.toString(text) + "\n" + "Typeform: " + Arrays.toString(typeform) + "\n" + "Output segments: " + Arrays.toString( - Iterables.toArray(SEGMENT_SPLITTER.split(braille), String.class))); + toArray(SEGMENT_SPLITTER.split(braille), String.class))); // If some segment breaks were discarded, fall // back on a fuzzy split method. First number the @@ -457,6 +486,11 @@ protected byte[] doHyphenate(String text) { catch (TranslationException e) { throw new RuntimeException(e); } } + + @Override + public String toString() { + return toStringHelper(this).add("translator", translator).add("hyphenator", "self").toString(); + } } private final static Splitter.MapSplitter CSS_PARSER diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisutdmlProcessBuilderImpl.java b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisutdmlProcessBuilderImpl.java index f4e07bc46..4fdb0c900 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisutdmlProcessBuilderImpl.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisutdmlProcessBuilderImpl.java @@ -14,7 +14,7 @@ import java.util.Map; import com.google.common.base.Function; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.getFirst; import org.daisy.pipeline.braille.common.BundledNativePath; import org.daisy.pipeline.braille.common.ResourceResolver; @@ -53,7 +53,7 @@ protected void deactivate() { protected void bindExecutable(BundledNativePath nativePath) { if (!LIBLOUISUTDML_EXTERNAL && this.nativePath == null) { - URI executablePath = Iterables.getFirst(nativePath.get("file2brl"), null); + URI executablePath = getFirst(nativePath.get("file2brl"), null); if (executablePath != null) { file2brl = asFile(nativePath.resolve(executablePath)); this.nativePath = nativePath; diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/pef/impl/LiblouisDisplayTableProvider.java b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/pef/impl/LiblouisDisplayTableProvider.java index 4f74469e9..28112e5f1 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/pef/impl/LiblouisDisplayTableProvider.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/pef/impl/LiblouisDisplayTableProvider.java @@ -6,9 +6,10 @@ import com.google.common.base.Function; import com.google.common.base.Optional; -import com.google.common.base.Predicates; +import static com.google.common.base.Predicates.notNull; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.transform; import org.daisy.braille.api.factory.AbstractFactory; import org.daisy.braille.api.table.BrailleConverter; @@ -73,8 +74,8 @@ protected Iterable get(Map> query) { for (String feature : query.keySet()) if (!supportedFeatures.contains(feature)) return empty; - return Iterables.
filter( - Iterables.transform( + return filter( + transform( tableProvider.get(serializeQuery(query)), new Function() { public Table apply(Translator table) { @@ -83,7 +84,7 @@ public Table apply(Translator table) { if (subTables[0].toString().endsWith(".dis")) return new LiblouisDisplayTable(table); return null; }}), - Predicates.notNull()); + notNull()); } private final static Iterable
empty = Optional.
absent().asSet(); diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/test/java/org/daisy/pipeline/braille/liblouis/LiblouisCoreTest.java b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/test/java/org/daisy/pipeline/braille/liblouis/LiblouisCoreTest.java index ff414143c..25bd09315 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/test/java/org/daisy/pipeline/braille/liblouis/LiblouisCoreTest.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/test/java/org/daisy/pipeline/braille/liblouis/LiblouisCoreTest.java @@ -10,7 +10,7 @@ import org.daisy.braille.api.table.TableCatalogService; import org.daisy.pipeline.braille.common.Provider; -import org.daisy.pipeline.braille.common.Provider.DispatchingProvider; +import static org.daisy.pipeline.braille.common.Provider.util.dispatch; import static org.daisy.pipeline.braille.common.util.Files.asFile; import static org.daisy.pipeline.braille.common.util.URIs.asURI; import org.daisy.pipeline.braille.liblouis.LiblouisTranslator.Typeform; @@ -46,6 +46,9 @@ import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + @RunWith(PaxExam.class) @ExamReactorStrategy(PerClass.class) public class LiblouisCoreTest { @@ -62,6 +65,8 @@ public class LiblouisCoreTest { @Inject private TableCatalogService tableCatalog; + private static final Logger messageBus = LoggerFactory.getLogger("JOB_MESSAGES"); + @Configuration public Option[] config() { return options( @@ -99,39 +104,39 @@ public void testResolveTable() { @Test public void testGetTranslatorFromQuery1() { - provider.get("(locale:foo)").iterator().next(); + provider.withContext(messageBus).get("(locale:foo)").iterator().next(); } @Test public void testGetTranslatorFromQuery2() { - provider.get("(table:'foobar.cti')").iterator().next(); + provider.withContext(messageBus).get("(table:'foobar.cti')").iterator().next(); } @Test public void testGetTranslatorFromQuery3() { - provider.get("(locale:foo_BAR)").iterator().next(); + provider.withContext(messageBus).get("(locale:foo_BAR)").iterator().next(); } @Test public void testTranslate() { - assertEquals("⠋⠕⠕⠃⠁⠗", provider.get("(table:'foobar.cti')").iterator().next().transform("foobar")); + assertEquals("⠋⠕⠕⠃⠁⠗", provider.withContext(messageBus).get("(table:'foobar.cti')").iterator().next().transform("foobar")); } @Test public void testTranslateStyled() { - assertEquals("⠋⠕⠕⠃⠁⠗", provider.get("(table:'foobar.cti')").iterator().next().transform("foobar", Typeform.ITALIC)); + assertEquals("⠋⠕⠕⠃⠁⠗", provider.withContext(messageBus).get("(table:'foobar.cti')").iterator().next().transform("foobar", Typeform.ITALIC)); } @Test public void testTranslateSegments() { - LiblouisTranslator translator = provider.get("(table:'foobar.cti')").iterator().next(); + LiblouisTranslator translator = provider.withContext(messageBus).get("(table:'foobar.cti')").iterator().next(); assertEquals(new String[]{"⠋⠕⠕","⠃⠁⠗"}, translator.transform(new String[]{"foo","bar"})); assertEquals(new String[]{"⠋⠕⠕","","⠃⠁⠗"}, translator.transform(new String[]{"foo","","bar"})); } @Test public void testTranslateSegmentsFuzzy() { - LiblouisTranslator translator = provider.get("(table:'foobar.ctb')").iterator().next(); + LiblouisTranslator translator = provider.withContext(messageBus).get("(table:'foobar.ctb')").iterator().next(); assertEquals(new String[]{"⠋⠥","⠃⠁⠗"}, translator.transform(new String[]{"foo","bar"})); assertEquals(new String[]{"⠋⠥","⠃⠁⠗"}, translator.transform(new String[]{"fo","obar"})); assertEquals(new String[]{"⠋⠥","","⠃⠁⠗"}, translator.transform(new String[]{"fo","","obar"})); @@ -144,17 +149,17 @@ public void testTranslateSegmentsFuzzy() { @Test public void testHyphenate() { - assertEquals("foo\u00ADbar", (hyphenatorProvider.get("(table:'foobar.cti,foobar.dic')").iterator().next()).transform("foobar")); + assertEquals("foo\u00ADbar", (hyphenatorProvider.withContext(messageBus).get("(table:'foobar.cti,foobar.dic')").iterator().next()).transform("foobar")); } @Test public void testHyphenateCompoundWord() { - assertEquals("foo-\u200Bbar", (hyphenatorProvider.get("(table:'foobar.cti,foobar.dic')").iterator().next()).transform("foo-bar")); + assertEquals("foo-\u200Bbar", (hyphenatorProvider.withContext(messageBus).get("(table:'foobar.cti,foobar.dic')").iterator().next()).transform("foo-bar")); } @Test public void testTranslateAndHyphenateSomeSegments() { - LiblouisTranslator translator = provider.get("(table:'foobar.cti,foobar.dic')").iterator().next(); + LiblouisTranslator translator = provider.withContext(messageBus).get("(table:'foobar.cti,foobar.dic')").iterator().next(); assertEquals(new String[]{"⠋⠕⠕\u00AD⠃⠁⠗ ","⠋⠕⠕⠃⠁⠗"}, translator.transform(new String[]{"foobar ","foobar"}, new String[]{"hyphens:auto","hyphens:none"})); } @@ -162,7 +167,7 @@ public void testTranslateAndHyphenateSomeSegments() { @Test public void testDisplayTableProvider() { Iterable tableProviders = getServices(TableProvider.class); - Provider tableProvider = DispatchingProvider.newInstance(tableProviders); + Provider tableProvider = dispatch(tableProviders); Table table = tableProvider.get("(liblouis-table:'foobar.dis')").iterator().next(); BrailleConverter converter = table.newBrailleConverter(); assertEquals("⠋⠕⠕⠀⠃⠁⠗", converter.toBraille("foo bar")); diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/test/resources/logback.xml b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/test/resources/logback.xml index b6e362a72..34b3f679a 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-core/src/test/resources/logback.xml +++ b/pipeline-braille-utils/liblouis-utils/liblouis-core/src/test/resources/logback.xml @@ -3,7 +3,7 @@ - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + [ %-5level] %msg%n @@ -19,5 +19,9 @@ - + + + + + diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-mathml/src/main/java/org/daisy/pipeline/braille/liblouis/math/LiblouisMathMLTransform.java b/pipeline-braille-utils/liblouis-utils/liblouis-mathml/src/main/java/org/daisy/pipeline/braille/liblouis/math/LiblouisMathMLTransform.java index cbdcc94f1..5a7173e98 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-mathml/src/main/java/org/daisy/pipeline/braille/liblouis/math/LiblouisMathMLTransform.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-mathml/src/main/java/org/daisy/pipeline/braille/liblouis/math/LiblouisMathMLTransform.java @@ -5,12 +5,15 @@ import java.net.URI; import javax.xml.namespace.QName; +import static com.google.common.base.Objects.toStringHelper; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; import static org.daisy.pipeline.braille.css.Query.parseQuery; -import org.daisy.pipeline.braille.common.Cached; +import org.daisy.pipeline.braille.common.Memoizing; import org.daisy.pipeline.braille.common.MathMLTransform; +import org.daisy.pipeline.braille.common.Transform; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.logCreate; import static org.daisy.pipeline.braille.common.util.Locales.parseLocale; import static org.daisy.pipeline.braille.common.util.Tuple3; import static org.daisy.pipeline.braille.common.util.URIs.asURI; @@ -20,6 +23,9 @@ import org.osgi.service.component.annotations.Component; import org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public interface LiblouisMathMLTransform extends MathMLTransform, XProcTransform { public enum MathCode { @@ -43,17 +49,26 @@ private void activate(ComponentContext context, final Map properties) { } public LiblouisMathMLTransform get(MathCode code) { - return translators.get(code); + return translators.apply(code); } - private Cached translators - = new Cached() { - public LiblouisMathMLTransform delegate(final MathCode code) { + private Memoizing translators + = new Memoizing() { + public LiblouisMathMLTransform _apply(final MathCode code) { final URI href = Provider.this.href; - return new LiblouisMathMLTransform() { - private final Map options = ImmutableMap.of("math-code", code.name()); - public Tuple3> asXProc() { - return new Tuple3>(href, null, options); }}; }}; + return logCreate( + new LiblouisMathMLTransform() { + private final Map options = ImmutableMap.of("math-code", code.name()); + public Tuple3> asXProc() { + return new Tuple3>(href, null, options); + } + @Override + public String toString() { + return toStringHelper(LiblouisMathMLTransform.class.getSimpleName()).add("mathCode", code).toString(); + } + }).apply(logger); + } + }; public Iterable get(String query) { Map> q = parseQuery(query); @@ -64,6 +79,10 @@ public Iterable get(String query) { return Optional.absent().asSet(); } + public Transform.Provider withContext(Logger context) { + return this; + } + private static MathCode mathCodeFromLocale(Locale locale) { String language = locale.getLanguage().toLowerCase(); String country = locale.getCountry().toUpperCase(); @@ -79,5 +98,8 @@ else if (language.equals("nl")) else return null; } + + private static final Logger logger = LoggerFactory.getLogger(Provider.class); + } } diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-saxon/src/main/java/org/daisy/pipeline/braille/liblouis/saxon/HyphenateDefinition.java b/pipeline-braille-utils/liblouis-utils/liblouis-saxon/src/main/java/org/daisy/pipeline/braille/liblouis/saxon/HyphenateDefinition.java index 349c92b81..9f794cc27 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-saxon/src/main/java/org/daisy/pipeline/braille/liblouis/saxon/HyphenateDefinition.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-saxon/src/main/java/org/daisy/pipeline/braille/liblouis/saxon/HyphenateDefinition.java @@ -15,9 +15,10 @@ import net.sf.saxon.value.StringValue; import org.daisy.pipeline.braille.common.Hyphenator; +import org.daisy.pipeline.braille.common.Provider; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; import org.daisy.pipeline.braille.common.Transform; -import org.daisy.pipeline.braille.common.Provider.CachedProvider; -import org.daisy.pipeline.braille.common.Transform.Provider.DispatchingProvider; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.dispatch; import org.daisy.pipeline.braille.liblouis.LiblouisHyphenator; import org.osgi.service.component.annotations.Component; @@ -58,8 +59,8 @@ protected void unbindLiblouisHyphenatorProvider(LiblouisHyphenator.Provider prov private List> providers = new ArrayList>(); - private CachedProvider hyphenators - = CachedProvider.newInstance(new DispatchingProvider(providers)); + private Provider.MemoizingProvider hyphenators + = memoize(dispatch(providers)); public StructuredQName getFunctionQName() { return funcname; diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-saxon/src/main/java/org/daisy/pipeline/braille/liblouis/saxon/TranslateDefinition.java b/pipeline-braille-utils/liblouis-utils/liblouis-saxon/src/main/java/org/daisy/pipeline/braille/liblouis/saxon/TranslateDefinition.java index 14beb6986..0bfa360dd 100755 --- a/pipeline-braille-utils/liblouis-utils/liblouis-saxon/src/main/java/org/daisy/pipeline/braille/liblouis/saxon/TranslateDefinition.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-saxon/src/main/java/org/daisy/pipeline/braille/liblouis/saxon/TranslateDefinition.java @@ -15,9 +15,10 @@ import net.sf.saxon.value.SequenceType; import net.sf.saxon.value.StringValue; +import org.daisy.pipeline.braille.common.Provider; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; import org.daisy.pipeline.braille.common.Transform; -import org.daisy.pipeline.braille.common.Provider.CachedProvider; -import org.daisy.pipeline.braille.common.Transform.Provider.DispatchingProvider; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.dispatch; import org.daisy.pipeline.braille.liblouis.LiblouisTranslator; import org.osgi.service.component.annotations.Component; @@ -58,8 +59,8 @@ protected void unbindLiblouisTranslatorProvider(LiblouisTranslator.Provider prov private List> providers = new ArrayList>(); - private CachedProvider translators - = CachedProvider.newInstance(new DispatchingProvider(providers)); + private Provider.MemoizingProvider translators + = memoize(dispatch(providers)); public StructuredQName getFunctionQName() { return funcname; diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-utils/src/main/java/org/daisy/pipeline/braille/liblouis/transform/LiblouisCSSBlockTransform.java b/pipeline-braille-utils/liblouis-utils/liblouis-utils/src/main/java/org/daisy/pipeline/braille/liblouis/transform/LiblouisCSSBlockTransform.java index e9b0cf84e..29d290bf2 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-utils/src/main/java/org/daisy/pipeline/braille/liblouis/transform/LiblouisCSSBlockTransform.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-utils/src/main/java/org/daisy/pipeline/braille/liblouis/transform/LiblouisCSSBlockTransform.java @@ -4,19 +4,26 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.net.URI; import javax.xml.namespace.QName; +import static com.google.common.base.Objects.toStringHelper; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; import static org.daisy.pipeline.braille.css.Query.parseQuery; import static org.daisy.pipeline.braille.css.Query.serializeQuery; -import org.daisy.pipeline.braille.common.Cached; import static org.daisy.pipeline.braille.common.util.Tuple3; import static org.daisy.pipeline.braille.common.util.URIs.asURI; import org.daisy.pipeline.braille.common.CSSBlockTransform; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; +import org.daisy.pipeline.braille.common.LazyValue.ImmutableLazyValue; import org.daisy.pipeline.braille.common.Transform; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.dispatch; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.logCreate; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.logSelect; +import org.daisy.pipeline.braille.common.WithSideEffect; import org.daisy.pipeline.braille.common.XProcTransform; import org.daisy.pipeline.braille.liblouis.LiblouisTranslator; @@ -27,6 +34,9 @@ import org.osgi.service.component.annotations.ReferencePolicy; import org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public interface LiblouisCSSBlockTransform extends CSSBlockTransform, XProcTransform { @Component( @@ -54,27 +64,75 @@ private void activate(ComponentContext context, final Map properties) { * Other features are used for finding sub-transformers of type LiblouisTranslator. */ public Iterable get(String query) { - return Optional.fromNullable(transforms.get(query)).asSet(); + return impl.get(query); + } + + public Transform.Provider withContext(Logger context) { + return impl.withContext(context); } - private Cached transforms - = new Cached() { - public LiblouisCSSBlockTransform delegate(String query) { - final URI href = Provider.this.href; - Map> q = new HashMap>(parseQuery(query)); - Optional o; - if ((o = q.remove("translator")) != null) - if (!o.get().equals("liblouis")) - return null; - String newQuery = serializeQuery(q); - if (!liblouisTranslatorProvider.get(newQuery).iterator().hasNext()) - return null; - final Map options = ImmutableMap.of("query", newQuery); - return new LiblouisCSSBlockTransform() { - public Tuple3> asXProc() { - return new Tuple3>(href, null, options); }}; + private Transform.Provider impl = new ProviderImpl(null); + + private class ProviderImpl extends AbstractProvider { + + private ProviderImpl(Logger context) { + super(context); } - }; + + protected Transform.Provider.MemoizingProvider _withContext(Logger context) { + return new ProviderImpl(context); + } + + protected Iterable> __get(final String query) { + return new ImmutableLazyValue>() { + public WithSideEffect _apply() { + return new WithSideEffect() { + public LiblouisCSSBlockTransform _apply() { + Map> q = new HashMap>(parseQuery(query)); + Optional o; + if ((o = q.remove("translator")) != null) + if (!o.get().equals("liblouis")) + return null; + String translatorQuery = serializeQuery(q); + Iterable> translators + = logSelect(translatorQuery, liblouisTranslatorProvider.get(translatorQuery)); + LiblouisTranslator translator; + try { + translator = applyWithSideEffect( translators.iterator().next() ); } + catch (NoSuchElementException e) { + throw new NoSuchElementException(); } + return applyWithSideEffect( + logCreate(new TransformImpl(translatorQuery, translator)) + ); + } + }; + } + }; + } + } + + private class TransformImpl implements LiblouisCSSBlockTransform { + + private final LiblouisTranslator translator; + private final Tuple3> xproc; + + private TransformImpl(String translatorQuery, LiblouisTranslator translator) { + Map options = ImmutableMap.of("query", translatorQuery); + xproc = new Tuple3>(href, null, options); + this.translator = translator; + } + + public Tuple3> asXProc() { + return xproc; + } + + @Override + public String toString() { + return toStringHelper(LiblouisCSSBlockTransform.class.getSimpleName()) + .add("translator", translator) + .toString(); + } + } @Reference( name = "LiblouisTranslatorProvider", @@ -94,8 +152,10 @@ protected void unbindLiblouisTranslatorProvider(LiblouisTranslator.Provider prov private List> liblouisTranslatorProviders = new ArrayList>(); - private CachedProvider liblouisTranslatorProvider - = CachedProvider.newInstance(new DispatchingProvider(liblouisTranslatorProviders)); + private org.daisy.pipeline.braille.common.Provider.MemoizingProvider liblouisTranslatorProvider + = memoize(dispatch(liblouisTranslatorProviders)); + + private static final Logger logger = LoggerFactory.getLogger(Provider.class); } } diff --git a/pipeline-braille-utils/liblouis-utils/liblouis-utils/src/main/java/org/daisy/pipeline/braille/liblouis/transform/LiblouisCSSStyledDocumentTransform.java b/pipeline-braille-utils/liblouis-utils/liblouis-utils/src/main/java/org/daisy/pipeline/braille/liblouis/transform/LiblouisCSSStyledDocumentTransform.java index 6b5f0ba1c..9c9553842 100644 --- a/pipeline-braille-utils/liblouis-utils/liblouis-utils/src/main/java/org/daisy/pipeline/braille/liblouis/transform/LiblouisCSSStyledDocumentTransform.java +++ b/pipeline-braille-utils/liblouis-utils/liblouis-utils/src/main/java/org/daisy/pipeline/braille/liblouis/transform/LiblouisCSSStyledDocumentTransform.java @@ -4,21 +4,28 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.net.URI; import javax.xml.namespace.QName; +import static com.google.common.base.Objects.toStringHelper; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; import static org.daisy.pipeline.braille.css.Query.parseQuery; import static org.daisy.pipeline.braille.css.Query.serializeQuery; -import org.daisy.pipeline.braille.common.Cached; import static org.daisy.pipeline.braille.common.util.Tuple3; import static org.daisy.pipeline.braille.common.util.URIs.asURI; import org.daisy.pipeline.braille.common.CSSBlockTransform; import org.daisy.pipeline.braille.common.CSSStyledDocumentTransform; +import org.daisy.pipeline.braille.common.LazyValue.ImmutableLazyValue; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; import org.daisy.pipeline.braille.common.Transform; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.dispatch; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.logCreate; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.logSelect; +import org.daisy.pipeline.braille.common.WithSideEffect; import org.daisy.pipeline.braille.common.XProcTransform; import org.osgi.service.component.annotations.Activate; @@ -28,6 +35,9 @@ import org.osgi.service.component.annotations.ReferencePolicy; import org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public interface LiblouisCSSStyledDocumentTransform extends XProcTransform, CSSStyledDocumentTransform { @Component( @@ -55,27 +65,75 @@ private void activate(ComponentContext context, final Map properties) { * Other features are used for finding sub-transformers of type CSSBlockTransform. */ public Iterable get(String query) { - return Optional.fromNullable(transforms.get(query)).asSet(); + return impl.get(query); + } + + public Transform.Provider withContext(Logger context) { + return impl.withContext(context); + } + + private Transform.Provider impl = new ProviderImpl(null); + + private class ProviderImpl extends AbstractProvider { + + private ProviderImpl(Logger context) { + super(context); + } + + protected Transform.Provider.MemoizingProvider _withContext(Logger context) { + return new ProviderImpl(context); + } + + protected Iterable> __get(final String query) { + return new ImmutableLazyValue>() { + public WithSideEffect _apply() { + return new WithSideEffect() { + public LiblouisCSSStyledDocumentTransform _apply() { + Map> q = new HashMap>(parseQuery(query)); + Optional o; + if ((o = q.remove("formatter")) != null) + if (!o.get().equals("liblouis")) + return null; + String cssBlockTransformQuery = serializeQuery(q); + Iterable> cssBlockTransforms + = logSelect(cssBlockTransformQuery, cssBlockTransformProvider.get(cssBlockTransformQuery)); + CSSBlockTransform cssBlockTransform; + try { + cssBlockTransform = applyWithSideEffect( cssBlockTransforms.iterator().next() ); } + catch (NoSuchElementException e) { + throw new NoSuchElementException(); } + return applyWithSideEffect( + logCreate(new TransformImpl(cssBlockTransformQuery, cssBlockTransform)) + ); + } + }; + } + }; + } } - private Cached transforms - = new Cached() { - public LiblouisCSSStyledDocumentTransform delegate(final String query) { - final URI href = Provider.this.href; - Map> q = new HashMap>(parseQuery(query)); - Optional o; - if ((o = q.remove("formatter")) != null) - if (!o.get().equals("liblouis")) - return null; - String newQuery = serializeQuery(q); - if (!cssBlockTransformProvider.get(newQuery).iterator().hasNext()) - return null; - final Map options = ImmutableMap.of("query", newQuery); - return new LiblouisCSSStyledDocumentTransform() { - public Tuple3> asXProc() { - return new Tuple3>(href, null, options); }}; + private class TransformImpl implements LiblouisCSSStyledDocumentTransform { + + private final CSSBlockTransform cssBlockTransform; + private final Tuple3> xproc; + + private TransformImpl(String cssBlockTransformQuery, CSSBlockTransform cssBlockTransform) { + Map options = ImmutableMap.of("query", cssBlockTransformQuery); + xproc = new Tuple3>(href, null, options); + this.cssBlockTransform = cssBlockTransform; + } + + public Tuple3> asXProc() { + return xproc; + } + + @Override + public String toString() { + return toStringHelper(LiblouisCSSStyledDocumentTransform.class.getSimpleName()) + .add("blockTransform", cssBlockTransform) + .toString(); } - }; + } @Reference( name = "CSSBlockTransformProvider", @@ -100,8 +158,10 @@ public void unbindCSSBlockTransformProvider(CSSBlockTransform.Provider provid private List> cssBlockTransformProviders = new ArrayList>(); - private CachedProvider cssBlockTransformProvider - = CachedProvider.newInstance(new DispatchingProvider(cssBlockTransformProviders)); + private org.daisy.pipeline.braille.common.Provider.MemoizingProvider cssBlockTransformProvider + = memoize(dispatch(cssBlockTransformProviders)); + + private static final Logger logger = LoggerFactory.getLogger(Provider.class); } } diff --git a/pipeline-braille-utils/pef-utils/pef-calabash/src/main/java/org/daisy/pipeline/braille/pef/calabash/PEF2TextStep.java b/pipeline-braille-utils/pef-utils/pef-calabash/src/main/java/org/daisy/pipeline/braille/pef/calabash/PEF2TextStep.java index be8e5a5fe..4ca92bf33 100755 --- a/pipeline-braille-utils/pef-utils/pef-calabash/src/main/java/org/daisy/pipeline/braille/pef/calabash/PEF2TextStep.java +++ b/pipeline-braille-utils/pef-utils/pef-calabash/src/main/java/org/daisy/pipeline/braille/pef/calabash/PEF2TextStep.java @@ -28,8 +28,8 @@ import org.daisy.braille.pef.PEFHandler.Alignment; import org.daisy.braille.pef.UnsupportedWidthException; import org.daisy.common.xproc.calabash.XProcStepProvider; -import org.daisy.pipeline.braille.common.Provider.CachedProvider; -import org.daisy.pipeline.braille.common.Provider.DispatchingProvider; +import static org.daisy.pipeline.braille.common.Provider.util.dispatch; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; import org.daisy.pipeline.braille.pef.TableProvider; import org.xml.sax.SAXException; @@ -161,8 +161,8 @@ protected void unbindTableProvider(TableProvider provider) { } private List tableProviders = new ArrayList(); - private CachedProvider tableProvider - = CachedProvider.newInstance(DispatchingProvider.newInstance(tableProviders)); + private org.daisy.pipeline.braille.common.Provider.MemoizingProvider tableProvider + = memoize(dispatch(tableProviders)); } diff --git a/pipeline-braille-utils/pef-utils/pef-calabash/src/main/java/org/daisy/pipeline/braille/pef/calabash/Text2PEFStep.java b/pipeline-braille-utils/pef-utils/pef-calabash/src/main/java/org/daisy/pipeline/braille/pef/calabash/Text2PEFStep.java index 29bf90b5e..17d803f4d 100644 --- a/pipeline-braille-utils/pef-utils/pef-calabash/src/main/java/org/daisy/pipeline/braille/pef/calabash/Text2PEFStep.java +++ b/pipeline-braille-utils/pef-utils/pef-calabash/src/main/java/org/daisy/pipeline/braille/pef/calabash/Text2PEFStep.java @@ -17,8 +17,8 @@ import org.daisy.braille.api.table.TableCatalogService; import org.daisy.braille.pef.TextHandler; import org.daisy.common.xproc.calabash.XProcStepProvider; -import org.daisy.pipeline.braille.common.Provider.CachedProvider; -import org.daisy.pipeline.braille.common.Provider.DispatchingProvider; +import static org.daisy.pipeline.braille.common.Provider.util.dispatch; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; import org.daisy.pipeline.braille.pef.TableProvider; import com.xmlcalabash.core.XProcException; @@ -161,8 +161,8 @@ protected void unbindTableProvider(TableProvider provider) { } private List tableProviders = new ArrayList(); - private CachedProvider tableProvider - = CachedProvider.newInstance(DispatchingProvider.newInstance(tableProviders)); + private org.daisy.pipeline.braille.common.Provider.MemoizingProvider tableProvider + = memoize(dispatch(tableProviders)); } diff --git a/pipeline-braille-utils/pef-utils/pef-saxon/src/main/java/org/daisy/pipeline/braille/pef/saxon/EncodeDefinition.java b/pipeline-braille-utils/pef-utils/pef-saxon/src/main/java/org/daisy/pipeline/braille/pef/saxon/EncodeDefinition.java index e20585ebe..55e4ae682 100755 --- a/pipeline-braille-utils/pef-utils/pef-saxon/src/main/java/org/daisy/pipeline/braille/pef/saxon/EncodeDefinition.java +++ b/pipeline-braille-utils/pef-utils/pef-saxon/src/main/java/org/daisy/pipeline/braille/pef/saxon/EncodeDefinition.java @@ -15,8 +15,9 @@ import net.sf.saxon.value.StringValue; import org.daisy.braille.api.table.Table; -import org.daisy.pipeline.braille.common.Provider.CachedProvider; -import org.daisy.pipeline.braille.common.Provider.DispatchingProvider; +import org.daisy.pipeline.braille.common.Provider; +import static org.daisy.pipeline.braille.common.Provider.util.dispatch; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; import org.daisy.pipeline.braille.pef.TableProvider; import org.osgi.service.component.annotations.Component; @@ -54,8 +55,8 @@ protected void unbindTableProvider(TableProvider provider) { } private List tableProviders = new ArrayList(); - private CachedProvider tableProvider - = CachedProvider.newInstance(DispatchingProvider.newInstance(tableProviders)); + private Provider.MemoizingProvider tableProvider + = memoize(dispatch(tableProviders)); @Override public StructuredQName getFunctionQName() { diff --git a/pipeline-braille-utils/pef-utils/pom.xml b/pipeline-braille-utils/pef-utils/pom.xml index 0f520dfbe..9586b923b 100644 --- a/pipeline-braille-utils/pef-utils/pom.xml +++ b/pipeline-braille-utils/pef-utils/pom.xml @@ -19,7 +19,6 @@ pef-calabash - pef-core pef-saxon pef-utils diff --git a/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/TexHyphenatorTableRegistry.java b/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/TexHyphenatorTableRegistry.java index ec24ab39b..4c1076aff 100644 --- a/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/TexHyphenatorTableRegistry.java +++ b/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/TexHyphenatorTableRegistry.java @@ -4,6 +4,9 @@ import java.util.Locale; import org.daisy.pipeline.braille.common.Provider; +import static org.daisy.pipeline.braille.common.Provider.util.dispatch; +import static org.daisy.pipeline.braille.common.Provider.util.memoize; +import static org.daisy.pipeline.braille.common.Provider.util.varyLocale; import org.daisy.pipeline.braille.common.ResourceRegistry; import org.osgi.service.component.annotations.Component; @@ -46,9 +49,9 @@ public Iterable get(Locale locale) { return provider.get(locale); } - private final CachedProvider provider - = CachedProvider.newInstance( - LocaleBasedProvider.newInstance( - DispatchingProvider.newInstance(paths.values()))); + private final Provider.MemoizingProvider provider + = memoize( + varyLocale( + dispatch(paths.values()))); } diff --git a/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/impl/TexHyphenatorDotifyImpl.java b/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/impl/TexHyphenatorDotifyImpl.java index 4116b3ff8..a7cf32989 100644 --- a/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/impl/TexHyphenatorDotifyImpl.java +++ b/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/impl/TexHyphenatorDotifyImpl.java @@ -13,14 +13,17 @@ import com.google.common.base.Function; import com.google.common.base.Optional; -import com.google.common.base.Predicates; -import com.google.common.collect.Iterables; +import static com.google.common.base.Predicates.notNull; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.transform; import net.davidashen.text.Utf8TexParser.TexParserException; import static org.daisy.pipeline.braille.css.Query.parseQuery; import org.daisy.pipeline.braille.common.Hyphenator; +import org.daisy.pipeline.braille.common.Provider; import org.daisy.pipeline.braille.common.TextTransform; +import org.daisy.pipeline.braille.common.Transform; import static org.daisy.pipeline.braille.common.util.Files.isAbsoluteFile; import static org.daisy.pipeline.braille.common.util.Locales.parseLocale; import static org.daisy.pipeline.braille.common.util.URIs.asURI; @@ -77,6 +80,10 @@ protected void unbindTableRegistry(TexHyphenatorTableRegistry registry) { tableRegistry = null; } + public Transform.Provider withContext(Logger context) { + return this; + } + /** * Recognized features: * @@ -134,9 +141,9 @@ private URL resolveTable(URI table) { private final static Iterable empty = Optional.absent().asSet(); - private CachedProvider provider - = new CachedProvider() { - public Iterable delegate(String query) { + private Provider.MemoizingProvider provider + = new Provider.MemoizingProvider() { + public Iterable _get(String query) { Map> q = new HashMap>(parseQuery(query)); Optional o; if ((o = q.remove("hyphenator")) != null) @@ -157,13 +164,13 @@ public Iterable delegate(String query) { logger.warn("A query with '" + q.keySet().iterator().next() + "' never matches anything"); return empty; } if (tableRegistry != null) { - return Iterables.filter( - Iterables.transform( + return filter( + transform( tableRegistry.get(locale), new Function() { public TexHyphenator apply(URI table) { return TexHyphenatorDotifyImpl.this.get(table); }}), - Predicates.notNull()); } + notNull()); } return empty; }}; /* diff --git a/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/impl/TexHyphenatorSimpleImpl.java b/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/impl/TexHyphenatorSimpleImpl.java index 961724b95..0d68d2a0d 100644 --- a/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/impl/TexHyphenatorSimpleImpl.java +++ b/pipeline-braille-utils/texhyph-utils/texhyph-core/src/main/java/org/daisy/pipeline/braille/tex/impl/TexHyphenatorSimpleImpl.java @@ -10,12 +10,15 @@ import com.google.common.base.Function; import com.google.common.base.Optional; -import com.google.common.base.Predicates; -import com.google.common.collect.Iterables; +import static com.google.common.base.Predicates.notNull; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.transform; import static org.daisy.pipeline.braille.css.Query.parseQuery; import org.daisy.pipeline.braille.common.Hyphenator; +import org.daisy.pipeline.braille.common.Provider; import org.daisy.pipeline.braille.common.TextTransform; +import org.daisy.pipeline.braille.common.Transform; import static org.daisy.pipeline.braille.common.util.Files.isAbsoluteFile; import static org.daisy.pipeline.braille.common.util.Locales.parseLocale; import static org.daisy.pipeline.braille.common.util.URIs.asURI; @@ -71,6 +74,10 @@ protected void unbindTableRegistry(TexHyphenatorTableRegistry registry) { tableRegistry = null; } + public Transform.Provider withContext(Logger context) { + return this; + } + /** * Recognized features: * @@ -99,9 +106,9 @@ private TexHyphenator get(URI table) { private final static Iterable empty = Optional.absent().asSet(); - private CachedProvider provider - = new CachedProvider() { - public Iterable delegate(String query) { + private Provider.MemoizingProvider provider + = new Provider.MemoizingProvider() { + public Iterable _get(String query) { Map> q = new HashMap>(parseQuery(query)); Optional o; if ((o = q.remove("hyphenator")) != null) @@ -122,13 +129,13 @@ public Iterable delegate(String query) { logger.warn("A query with '" + q.keySet().iterator().next() + "' never matches anything"); return empty; } if (tableRegistry != null) { - return Iterables.filter( - Iterables.transform( + return filter( + transform( tableRegistry.get(locale), new Function() { public TexHyphenator apply(URI table) { return TexHyphenatorSimpleImpl.this.get(table); }}), - Predicates.notNull()); } + notNull()); } return empty; }}; private class TexHyphenatorImpl implements TexHyphenator { diff --git a/pipeline-braille-utils/texhyph-utils/texhyph-core/src/test/java/org/daisy/pipeline/braille/tex/TexHyphenatorCoreTest.java b/pipeline-braille-utils/texhyph-utils/texhyph-core/src/test/java/org/daisy/pipeline/braille/tex/TexHyphenatorCoreTest.java index 9ed154e6f..36512a0e8 100644 --- a/pipeline-braille-utils/texhyph-utils/texhyph-core/src/test/java/org/daisy/pipeline/braille/tex/TexHyphenatorCoreTest.java +++ b/pipeline-braille-utils/texhyph-utils/texhyph-core/src/test/java/org/daisy/pipeline/braille/tex/TexHyphenatorCoreTest.java @@ -5,7 +5,7 @@ import javax.inject.Inject; import org.daisy.pipeline.braille.common.Transform; -import org.daisy.pipeline.braille.common.Transform.Provider.DispatchingProvider; +import static org.daisy.pipeline.braille.common.Transform.Provider.util.dispatch; import static org.daisy.pipeline.pax.exam.Options.brailleModule; import static org.daisy.pipeline.pax.exam.Options.bundlesAndDependencies; @@ -80,6 +80,6 @@ private Transform.Provider getProvider(Class transfo providers.add(context.getService(ref)); } catch (InvalidSyntaxException e) { throw new RuntimeException(e); } - return new DispatchingProvider(providers); + return dispatch(providers); } }