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

nu.nota.pipeline.braille.impl.NotaTranslator Maven / Gradle / Ivy

The newest version!
package nu.nota.pipeline.braille.impl;

import java.util.ArrayList;
import java.util.Arrays;
import static java.util.Arrays.copyOfRange;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.net.URI;

import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import static com.google.common.collect.Iterables.size;
import static com.google.common.collect.Lists.newArrayList;

import cz.vutbr.web.css.CSSProperty;
import cz.vutbr.web.css.Term;
import cz.vutbr.web.css.TermIdent;
import cz.vutbr.web.css.TermList;

import org.daisy.braille.css.BrailleCSSProperty.TextTransform;
import org.daisy.braille.css.SimpleInlineStyle;

import org.daisy.pipeline.braille.common.AbstractBrailleTranslator;
import org.daisy.pipeline.braille.common.AbstractTransformProvider;
import org.daisy.pipeline.braille.common.AbstractTransformProvider.util.Function;
import org.daisy.pipeline.braille.common.AbstractTransformProvider.util.Iterables;
import static org.daisy.pipeline.braille.common.AbstractTransformProvider.util.Iterables.concat;
import static org.daisy.pipeline.braille.common.AbstractTransformProvider.util.Iterables.transform;
import static org.daisy.pipeline.braille.common.AbstractTransformProvider.util.logCreate;
import static org.daisy.pipeline.braille.common.AbstractTransformProvider.util.logSelect;
import org.daisy.pipeline.braille.common.BrailleTranslator;
import org.daisy.pipeline.braille.common.BrailleTranslatorProvider;
import org.daisy.pipeline.braille.common.CSSStyledText;
import org.daisy.pipeline.braille.common.Query;
import org.daisy.pipeline.braille.common.Query.Feature;
import org.daisy.pipeline.braille.common.Query.MutableQuery;
import static org.daisy.pipeline.braille.common.Query.util.mutableQuery;
import org.daisy.pipeline.braille.common.TransformProvider;
import static org.daisy.pipeline.braille.common.TransformProvider.util.dispatch;
import static org.daisy.pipeline.braille.common.TransformProvider.util.memoize;
import static org.daisy.pipeline.braille.common.util.Locales.parseLocale;
import static org.daisy.pipeline.braille.common.util.Strings.join;
import static org.daisy.pipeline.braille.common.util.URIs.asURI;
import org.daisy.pipeline.braille.libhyphen.LibhyphenHyphenator;
import org.daisy.pipeline.braille.liblouis.LiblouisTranslator;

import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.ComponentContext;

public interface NotaTranslator {
	
	@Component(
		name = "nu.nota.pipeline.braille.impl.NotaTranslatorProvider",
		service = {
			TransformProvider.class,
			BrailleTranslatorProvider.class
		}
	)
	public class Provider extends AbstractTransformProvider implements BrailleTranslatorProvider {
		
		private URI href;
		
		@Activate
		private void activate(ComponentContext context, final Map properties) {
			href = asURI(context.getBundleContext().getBundle().getEntry("xml/block-translate.xpl"));
		}
		
		private final static Query uncontractedTable = mutableQuery().add("liblouis-table", "http://www.liblouis.org/tables/da-dk-g16.utb");
		private final static Query contractedTable = mutableQuery().add("liblouis-table", "http://www.liblouis.org/tables/da-dk-g26.ctb");
		private final static Query hyphenTable = mutableQuery().add("libhyphen-table",
		                                                            "http://www.libreoffice.org/dictionaries/hyphen/hyph_da_DK.dic");
		
		private final static Iterable empty = Iterables.empty();
		
		private final static List supportedInput = ImmutableList.of("css","text-css","dtbook","html");
		private final static List supportedOutput = ImmutableList.of("css","braille");
		
		/**
		 * Recognized features:
		 *
		 * - translator: Will only match if the value is `nota'.
		 * - locale: Will only match if the language subtag is 'da'.
		 * - grade: `0' or `2'.
		 *
		 */
		protected final Iterable _get(Query query) {
			final MutableQuery q = mutableQuery(query);
			for (Feature f : q.removeAll("input"))
				if (!supportedInput.contains(f.getValue().get()))
					return empty;
			for (Feature f : q.removeAll("output"))
				if (!supportedOutput.contains(f.getValue().get()))
					return empty;
			if (q.containsKey("locale"))
				if (!"da".equals(parseLocale(q.removeOnly("locale").getValue().get()).getLanguage()))
					return empty;
			if (q.containsKey("translator"))
				if ("nota".equals(q.removeOnly("translator").getValue().get()))
					if (q.containsKey("grade")) {
						String v = q.removeOnly("grade").getValue().get();
						final int grade;
						if (v.equals("0"))
							grade = 0;
						else if (v.equals("2"))
							grade = 2;
						else
							return empty;
						if (q.isEmpty()) {
							Iterable hyphenators = logSelect(hyphenTable, libhyphenHyphenatorProvider);
							final Query liblouisTable = grade == 0 ? uncontractedTable : contractedTable;
							return concat(
								transform(
									hyphenators,
									new Function>() {
										public Iterable _apply(final LibhyphenHyphenator h) {
											return concat(
												transform(
													logSelect(mutableQuery(liblouisTable).add("hyphenator", h.getIdentifier()),
													          liblouisTranslatorProvider),
													new Function>() {
														public Iterable _apply(final LiblouisTranslator translator) {
															return transform(
																logSelect(mutableQuery(uncontractedTable).add("hyphenator", h.getIdentifier()),
																          liblouisTranslatorProvider),
																new Function() {
																	public BrailleTranslator _apply(LiblouisTranslator uncontractedTranslator) {
																		return __apply(
																			logCreate(
																				new TransformImpl(grade, translator, uncontractedTranslator)));
																	}}); }})); }})); }}
			return empty;
		}
		
		private class TransformImpl extends AbstractBrailleTranslator {
			
			private final FromStyledTextToBraille translator;
			private final FromStyledTextToBraille uncontractedTranslator;
			private final XProc xproc;
			private final int grade;
			
			private TransformImpl(int grade, LiblouisTranslator translator, LiblouisTranslator uncontractedTranslator) {
				Map options = ImmutableMap.of(
					"text-transform", mutableQuery().add("id", this.getIdentifier()).toString());
				xproc = new XProc(href, null, options);
				this.grade = grade;
				this.translator = translator.fromStyledTextToBraille();
				this.uncontractedTranslator = uncontractedTranslator.fromStyledTextToBraille();
			}
			
			@Override
			public XProc asXProc() {
				return xproc;
			}
			
			@Override
			public FromStyledTextToBraille fromStyledTextToBraille() {
				return fromStyledTextToBraille;
			}
			
			private final FromStyledTextToBraille fromStyledTextToBraille = new FromStyledTextToBraille() {
				public java.lang.Iterable transform(java.lang.Iterable styledText) {
					int size = size(styledText);
					String[] text = new String[size];
					SimpleInlineStyle[] style = new SimpleInlineStyle[size];
					int i = 0;
					for (CSSStyledText t : styledText) {
						text[i] = t.getText();
						style[i] = t.getStyle();
						i++; }
					return Arrays.asList(TransformImpl.this.transform(text, style));
				}
			};
			
			private String[] transform(String[] text, SimpleInlineStyle[] cssStyle) {
				if (text.length == 0)
					return new String[]{};
				String[] result = new String[text.length];
				boolean uncont = false;
				int j = 0;
				List uncontStyle = null;
				for (int i = 0; i < text.length; i++) {
					SimpleInlineStyle style = cssStyle[i];
					boolean thisUncont; {
						thisUncont = false;
						if (style != null) {
							CSSProperty val = style.getProperty("text-transform");
							if (val != null) {
								if (val == TextTransform.list_values) {
									TermList values = style.getValue(TermList.class, "text-transform");
									Iterator> it = values.iterator();
									while (it.hasNext()) {
										String tt = ((TermIdent)it.next()).getValue();
										if (tt.equals("uncontracted")) {
											thisUncont = true;
											it.remove();
											break; }}
									if (values.isEmpty())
										style.removeProperty("text-transform"); }}}}
					if (thisUncont) {
						if (i > 0 && !uncont)
							for (String s : transformArray(translator,
							                               copyOfRange(text, j, i),
							                               copyOfRange(cssStyle, j, i)))
								result[j++] = s;
						if (uncontStyle == null)
							uncontStyle = new ArrayList();
						uncontStyle.add(style);
						uncont = true; }
					else {
						if (i > 0 && uncont) {
							for (String s : transformArray(uncontractedTranslator,
							                               copyOfRange(text, j, i),
							                               uncontStyle.toArray(new SimpleInlineStyle[i - j])))
								result[j++] = s;
							uncontStyle = null; }
						uncont = false; }}
				if (uncont)
					for (String s : transformArray(uncontractedTranslator,
					                               copyOfRange(text, j, text.length),
					                               uncontStyle.toArray(new SimpleInlineStyle[text.length - j])))
						result[j++] = s;
				else
					for (String s : transformArray(translator,
					                               copyOfRange(text, j, text.length),
					                               copyOfRange(cssStyle, j, text.length)))
						result[j++] = s;
				return result;
			}
			
			private String[] transformArray(FromStyledTextToBraille translator, String[] text, SimpleInlineStyle[] style) {
				List styledText = new ArrayList();
				for (int i = 0; i < text.length; i++)
					styledText.add(new CSSStyledText(text[i], style[i]));
				String[] result = new String[text.length];
				int i = 0;
				for (String s : translator.transform(styledText))
					result[i++] = s;
				return result;
			}
			
			@Override
			public String toString() {
				return Objects.toStringHelper(NotaTranslator.class.getSimpleName())
					.add("grade", grade)
					.add("id", getIdentifier())
					.toString();
			}
		}
		
		@Reference(
			name = "LiblouisTranslatorProvider",
			unbind = "unbindLiblouisTranslatorProvider",
			service = LiblouisTranslator.Provider.class,
			cardinality = ReferenceCardinality.MULTIPLE,
			policy = ReferencePolicy.DYNAMIC
		)
		protected void bindLiblouisTranslatorProvider(LiblouisTranslator.Provider provider) {
			liblouisTranslatorProviders.add(provider);
		}
	
		protected void unbindLiblouisTranslatorProvider(LiblouisTranslator.Provider provider) {
			liblouisTranslatorProviders.remove(provider);
			liblouisTranslatorProvider.invalidateCache();
		}
	
		private List> liblouisTranslatorProviders
		= new ArrayList>();
		private TransformProvider.util.MemoizingProvider liblouisTranslatorProvider
		= memoize(dispatch(liblouisTranslatorProviders));
		
		@Reference(
			name = "LibhyphenHyphenatorProvider",
			unbind = "unbindLibhyphenHyphenatorProvider",
			service = LibhyphenHyphenator.Provider.class,
			cardinality = ReferenceCardinality.MULTIPLE,
			policy = ReferencePolicy.DYNAMIC
		)
		protected void bindLibhyphenHyphenatorProvider(LibhyphenHyphenator.Provider provider) {
			libhyphenHyphenatorProviders.add(provider);
		}
	
		protected void unbindLibhyphenHyphenatorProvider(LibhyphenHyphenator.Provider provider) {
			libhyphenHyphenatorProviders.remove(provider);
			libhyphenHyphenatorProvider.invalidateCache();
		}
	
		private List> libhyphenHyphenatorProviders
		= new ArrayList>();
		private TransformProvider.util.MemoizingProvider libhyphenHyphenatorProvider
		= memoize(dispatch(libhyphenHyphenatorProviders));
		
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy