All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.daisy.pipeline.braille.common.Provider Maven / Gradle / Ivy

There is a newer version: 5.0.2
Show newest version
package org.daisy.pipeline.braille.common;

import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.transform;

import org.daisy.pipeline.braille.common.util.Function2;
import org.daisy.pipeline.braille.common.util.Iterables;

public interface Provider {
	
	/**
	 * Get a collection of objects based on a query.
	 * @param query is assumed to be immutable
	 * @return The objects for the query, in order of best match.
	 */
	public Iterable get(Q query);
	
	/* ================== */
	/*       UTILS        */
	/* ================== */
	
	public static abstract class util {
		
		/* ------- */
		/* empty() */
		/* ------- */
		
		public static  Provider empty() {
			return new Provider() {
				public Iterable get(Q query) {
					return Optional.absent().asSet();
				}
			};
		}
		
		/* --------- */
		/* memoize() */
		/* --------- */
		
		public interface MemoizingProvider extends Memoizing>, Provider {}
		
		/**
		 * provider.get(query) must not mutate query
		 */
		public static  MemoizingProvider memoize(final Provider provider) {
			return new Memoize() {
				protected Iterable _get(Q query) {
					return Iterables.memoize(provider.get(query));
				}
			};
		}
		
		public static abstract class Memoize extends Memoizing.util.AbstractMemoizing> implements MemoizingProvider {
			protected Memoize() {
				super();
			}
			protected Memoize(Memoize shareCacheWith) {
				super(shareCacheWith);
			}
			protected abstract Iterable _get(Q query);
			public Iterable get(Q query) {
				return apply(query);
			}
			protected final Iterable _apply(Q query) {
				return _get(query);
			}
		}
		
		/* --------------------- */
		/* SimpleMappingProvider */
		/* --------------------- */
		
		public static abstract class SimpleMappingProvider implements Provider {
			private Map map;
			public abstract Q parseKey(String key);
			public abstract X parseValue(String value);
			public SimpleMappingProvider(URL properties) {
				map = readProperties(properties);
			}
			public Iterable get(Q query) {
				String value = map.get(query);
				if (value != null)
					return Optional.fromNullable(parseValue(value)).asSet();
				return Optional.absent().asSet();
			}
			private Map readProperties(URL url) {
				Map map = new HashMap();
				try {
					url.openConnection();
					InputStream reader = url.openStream();
					Properties properties = new Properties();
					properties.loadFromXML(reader);
					for (String key : properties.stringPropertyNames()) {
						Q query = parseKey(key);
						if (!map.containsKey(query))
							map.put(query, properties.getProperty(key)); }
					reader.close();
					return new ImmutableMap.Builder().putAll(map).build(); }
				catch (Exception e) {
					throw new RuntimeException("Could not read properties file " + url, e); }
			}
		}
		
		/* ---------- */
		/* dispatch() */
		/* ---------- */
		
		public static  Provider dispatch(final Iterable> dispatch) {
			return new Dispatch() {
				@SuppressWarnings(
					"unchecked" // safe cast to Iterable>
				)
				public Iterable> dispatch() {
					return (Iterable>)dispatch;
				}
			};
		}
		
		public static abstract class Dispatch implements Provider {
			public abstract Iterable> dispatch();
			public Iterable get(final Q query) {
				return concat(transform(
					dispatch(),
					new Function,Iterable>() {
						public Iterable apply(Provider provider) {
							return provider.get(query); }}));
			}
		}
		
		/* ------------ */
		/* varyLocale() */
		/* ------------ */
		
		public static  Provider varyLocale(final Provider delegate) {
			return new VaryLocale() {
				public Iterable _get(Locale locale) {
					return delegate.get(locale);
				}
			};
		}
		
		public static  Provider varyLocale(final Provider delegate,
		                                             final Function getLocale,
		                                             final Function2 assocLocale) {
			return new VaryLocale() {
				public Iterable _get(Q query) {
					return delegate.get(query);
				}
				public Locale getLocale(Q query) {
					return getLocale.apply(query);
				}
				public Q assocLocale(Q query, Locale locale) {
					return assocLocale.apply(query, locale);
				}
			};
		}
		
		public static abstract class VaryLocale implements Provider {
			public abstract Iterable _get(Q query);
			public abstract Locale getLocale(Q query);
			/**
			 * @param query must not be mutated
			 * @param locale
			 * @return a new query with the locale feature "added"
			 */
			public abstract Q assocLocale(Q query, Locale locale);
			public Locale getLocale(Locale query) {
				return query;
			}
			public Locale assocLocale(Locale query, Locale locale) {
				return locale;
			}
			public final Iterable get(final Q query) {
				return new Iterable() {
					public Iterator iterator() {
						return new Iterator() {
							Iterator next = null;
							int tryNext = 1;
							Locale locale = getLocale(query);
							public boolean hasNext() {
								while (next == null || !next.hasNext()) {
									switch (tryNext) {
									case 1:
										tryNext++;
										next = _get(query).iterator();
										if (locale == null || "".equals(locale.toString()))
											tryNext = 4;
										break;
									case 2:
										tryNext++;
										if (!"".equals(locale.getVariant()))
											next = _get(assocLocale(query, new Locale(locale.getLanguage(), locale.getCountry()))).iterator();
										break;
									case 3:
										tryNext++;
										if (!"".equals(locale.getCountry()))
											next = _get(assocLocale(query, new Locale(locale.getLanguage()))).iterator();
										break;
									case 4:
										tryNext++;
										next = fallback(query).iterator();
										break;
									default:
										return false; }}
								return true;
							}
							public X next() {
								if (!hasNext()) throw new NoSuchElementException();
								return next.next();
							}
							public void remove() {
								throw new UnsupportedOperationException();
							}
						};
					}
				};
			}
			public Iterable fallback(Q query) {
				return Optional.absent().asSet();
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy