1 package nl.dedicon.pipeline.braille.impl;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Map;
6 import java.net.URI;
7
8 import com.google.common.base.MoreObjects;
9 import com.google.common.collect.ImmutableList;
10 import com.google.common.collect.ImmutableMap;
11
12 import org.daisy.common.file.URIs;
13 import org.daisy.common.file.URLs;
14 import org.daisy.pipeline.braille.common.AbstractBrailleTranslator;
15 import org.daisy.pipeline.braille.common.AbstractTransformProvider;
16 import org.daisy.pipeline.braille.common.AbstractTransformProvider.util.Function;
17 import org.daisy.pipeline.braille.common.AbstractTransformProvider.util.Iterables;
18 import static org.daisy.pipeline.braille.common.AbstractTransformProvider.util.Iterables.concat;
19 import static org.daisy.pipeline.braille.common.AbstractTransformProvider.util.Iterables.transform;
20 import static org.daisy.pipeline.braille.common.AbstractTransformProvider.util.logCreate;
21 import static org.daisy.pipeline.braille.common.AbstractTransformProvider.util.logSelect;
22 import org.daisy.pipeline.braille.common.BrailleTranslator;
23 import org.daisy.pipeline.braille.common.BrailleTranslatorProvider;
24 import org.daisy.pipeline.braille.common.CSSStyledText;
25 import org.daisy.pipeline.braille.common.Hyphenator;
26 import org.daisy.pipeline.braille.common.HyphenatorProvider;
27 import org.daisy.pipeline.braille.common.Query;
28 import org.daisy.pipeline.braille.common.Query.Feature;
29 import org.daisy.pipeline.braille.common.Query.MutableQuery;
30 import static org.daisy.pipeline.braille.common.Query.util.mutableQuery;
31 import static org.daisy.pipeline.braille.common.Query.util.query;
32 import org.daisy.pipeline.braille.common.TransformProvider;
33 import static org.daisy.pipeline.braille.common.TransformProvider.util.dispatch;
34 import static org.daisy.pipeline.braille.common.TransformProvider.util.memoize;
35 import org.daisy.pipeline.braille.liblouis.LiblouisTranslator;
36
37 import org.osgi.service.component.annotations.Activate;
38 import org.osgi.service.component.annotations.Component;
39 import org.osgi.service.component.annotations.Reference;
40 import org.osgi.service.component.annotations.ReferenceCardinality;
41 import org.osgi.service.component.annotations.ReferencePolicy;
42
43 public interface DediconTranslator {
44
45 @Component(
46 name = "nl.dedicon.pipeline.braille.impl.DediconTranslator.Provider",
47 service = {
48 TransformProvider.class,
49 BrailleTranslatorProvider.class
50 }
51 )
52 public class Provider extends AbstractTransformProvider<BrailleTranslator> implements BrailleTranslatorProvider<BrailleTranslator> {
53
54 private URI href;
55
56 @Activate
57 void activate(final Map<?, ?> properties) {
58 href = URIs.asURI(URLs.getResourceFromJAR("/xml/xproc/block-translate.xpl", DediconTranslator.class));
59 }
60
61 private final static Iterable<BrailleTranslator> empty = Iterables.<BrailleTranslator>empty();
62
63 private final static List<String> supportedInput = ImmutableList.of("css", "text-css", "dtbook", "html");
64 private final static List<String> supportedOutput = ImmutableList.of("css", "braille");
65
66
67
68
69
70
71
72
73 @Override
74 protected final Iterable<BrailleTranslator> _get(Query query) {
75
76
77 final Query liblouisTable = query("(locale:nl_NL)(type:literary)");
78 Query hyphenationLocale = null;
79
80 final MutableQuery q = mutableQuery(query);
81 for (Feature f : q.removeAll("input")) {
82 if (!supportedInput.contains(f.getValue().get())) {
83 return empty;
84 }
85 }
86 for (Feature f : q.removeAll("output")) {
87 if (!supportedOutput.contains(f.getValue().get())) {
88 return empty;
89 }
90 }
91 if (q.containsKey("locale")) {
92 hyphenationLocale = mutableQuery().addAll(q.removeAll("locale"));
93 }
94 if (hyphenationLocale == null) {
95 return empty;
96 }
97 if (q.containsKey("translator")) {
98 if ("dedicon".equals(q.removeOnly("translator").getValue().get())) {
99 if (q.isEmpty()) {
100
101 Query hyphenTable = mutableQuery(hyphenationLocale).add("hyphenator", "hyphen");
102 Query fallbackHyphenationTable = mutableQuery(hyphenationLocale).add("hyphenator", "tex");
103
104 Iterable<Hyphenator> hyphenators = concat(
105 logSelect(hyphenTable, hyphenatorProvider),
106 logSelect(fallbackHyphenationTable, hyphenatorProvider)
107 );
108 return concat(
109 transform(
110 concat(
111 transform(
112 hyphenators,
113 new Function<Hyphenator, String>() {
114 @Override
115 public String _apply(Hyphenator h) {
116 return h.getIdentifier();
117 }
118 }
119 ),
120 "liblouis"
121 ),
122 new Function<String, Iterable<BrailleTranslator>>() {
123 @Override
124 public Iterable<BrailleTranslator> _apply(String hyphenator) {
125 final Query translatorQuery = mutableQuery(liblouisTable).add("hyphenator", hyphenator);
126 return transform(
127 logSelect(translatorQuery, liblouisTranslatorProvider),
128 new Function<LiblouisTranslator, BrailleTranslator>() {
129 @Override
130 public BrailleTranslator _apply(LiblouisTranslator translator) {
131 return __apply(logCreate(new TransformImpl(translatorQuery.toString(), translator)));
132 }
133 }
134 );
135 }
136 }
137 )
138 );
139 }
140 }
141 }
142 return empty;
143 }
144
145 private class TransformImpl extends AbstractBrailleTranslator {
146
147 private final FromStyledTextToBraille translator;
148 private final XProc xproc;
149
150 private TransformImpl(String translatorQuery, LiblouisTranslator translator) {
151 Map<String, String> options = ImmutableMap.of("text-transform", mutableQuery().add("id", this.getIdentifier()).toString());
152 xproc = new XProc(href, null, options);
153 this.translator = translator.fromStyledTextToBraille();
154 }
155
156 @Override
157 public XProc asXProc() {
158 return xproc;
159 }
160
161 @Override
162 public FromStyledTextToBraille fromStyledTextToBraille() {
163 return fromStyledTextToBraille;
164 }
165
166 private final FromStyledTextToBraille fromStyledTextToBraille = new FromStyledTextToBraille() {
167 @Override
168 public java.lang.Iterable<String> transform(java.lang.Iterable<CSSStyledText> styledText, int from, int to) {
169 return translator.transform(styledText, from, to);
170 }
171 };
172
173 @Override
174 public String toString() {
175 return MoreObjects.toStringHelper(DediconTranslator.class.getSimpleName())
176 .add("id", getIdentifier())
177 .add("liblouisTranslator", translator)
178 .toString();
179 }
180 }
181
182 @Reference(
183 name = "LiblouisTranslatorProvider",
184 unbind = "unbindLiblouisTranslatorProvider",
185 service = LiblouisTranslator.Provider.class,
186 cardinality = ReferenceCardinality.MULTIPLE,
187 policy = ReferencePolicy.DYNAMIC
188 )
189 protected void bindLiblouisTranslatorProvider(LiblouisTranslator.Provider provider) {
190 liblouisTranslatorProviders.add(provider);
191 }
192
193 protected void unbindLiblouisTranslatorProvider(LiblouisTranslator.Provider provider) {
194 liblouisTranslatorProviders.remove(provider);
195 liblouisTranslatorProvider.invalidateCache();
196 }
197
198 private final List<TransformProvider<LiblouisTranslator>> liblouisTranslatorProviders
199 = new ArrayList<>();
200 private final TransformProvider.util.MemoizingProvider<LiblouisTranslator> liblouisTranslatorProvider
201 = memoize(dispatch(liblouisTranslatorProviders));
202
203 @Reference(
204 name = "HyphenatorProvider",
205 unbind = "unbindHyphenatorProvider",
206 service = HyphenatorProvider.class,
207 cardinality = ReferenceCardinality.MULTIPLE,
208 policy = ReferencePolicy.DYNAMIC
209 )
210 @SuppressWarnings(
211 "unchecked"
212 )
213 protected void bindHyphenatorProvider(HyphenatorProvider<?> provider) {
214 hyphenatorProviders.add((TransformProvider<Hyphenator>) provider);
215 }
216
217 protected void unbindHyphenatorProvider(HyphenatorProvider<?> provider) {
218 hyphenatorProviders.remove((HyphenatorProvider)provider);
219 hyphenatorProvider.invalidateCache();
220 }
221
222 private final List<TransformProvider<Hyphenator>> hyphenatorProviders
223 = new ArrayList<>();
224 private final TransformProvider.util.MemoizingProvider<Hyphenator> hyphenatorProvider
225 = memoize(dispatch(hyphenatorProviders));
226
227 }
228 }