1   package org.daisy.pipeline.braille.libhyphen.impl;
2   
3   import java.io.File;
4   import java.net.URI;
5   import java.net.URL;
6   import java.util.Locale;
7   
8   import com.google.common.base.Predicate;
9   
10  import org.daisy.common.file.URLs;
11  import org.daisy.pipeline.braille.common.Provider;
12  import static org.daisy.pipeline.braille.common.Provider.util.dispatch;
13  import static org.daisy.pipeline.braille.common.Provider.util.memoize;
14  import static org.daisy.pipeline.braille.common.Provider.util.varyLocale;
15  import org.daisy.pipeline.braille.common.ResourcePath;
16  import org.daisy.pipeline.braille.common.ResourceRegistry;
17  import static org.daisy.pipeline.braille.common.util.Files.asFile;
18  import static org.daisy.pipeline.braille.common.util.Files.fileName;
19  import static org.daisy.pipeline.braille.common.util.Predicates.matchesGlobPattern;
20  import org.daisy.pipeline.braille.libhyphen.LibhyphenTablePath;
21  import org.daisy.pipeline.braille.libhyphen.LibhyphenTableProvider;
22  import org.daisy.pipeline.braille.libhyphen.LibhyphenTableResolver;
23  
24  import org.osgi.service.component.annotations.Component;
25  import org.osgi.service.component.annotations.Reference;
26  import org.osgi.service.component.annotations.ReferenceCardinality;
27  import org.osgi.service.component.annotations.ReferencePolicy;
28  
29  @Component(
30  	name = "org.daisy.pipeline.braille.libhyphen.impl.LibhyphenTableRegistry",
31  	service = {
32  		LibhyphenTableRegistry.class
33  	}
34  )
35  public class LibhyphenTableRegistry extends ResourceRegistry<LibhyphenTablePath>
36  	                                implements LibhyphenTableProvider, LibhyphenTableResolver {
37  	
38  	@Reference(
39  		name = "LibhyphenTablePath",
40  		unbind = "-",
41  		service = LibhyphenTablePath.class,
42  		cardinality = ReferenceCardinality.MULTIPLE,
43  		policy = ReferencePolicy.STATIC
44  	)
45  	protected void _register(LibhyphenTablePath path) {
46  		register(path);
47  		provider.invalidateCache();
48  	}
49  	
50  	protected void _unregister (LibhyphenTablePath path) {
51  		unregister(path);
52  		provider.invalidateCache();
53  	}
54  	
55  	/**
56  	 * Try to find a table based on the given locale.
57  	 * An automatic fallback mechanism is used: if nothing is found for
58  	 * language-COUNTRY-variant, then language-COUNTRY is searched, then language.
59  	 */
60  	public Iterable<URI> get(Locale locale) {
61  		return provider.get(locale);
62  	}
63  	
64  	private final Provider.util.MemoizingProvider<Locale,URI> provider
65  		= memoize(
66  			varyLocale(
67  				dispatch(paths.values())));
68  	
69  	@Override
70  	public URL resolve(URI resource) {
71  		URL resolved = super.resolve(resource);
72  		if (resolved == null)
73  			resolved = fileSystem.resolve(resource);
74  		return resolved;
75  	}
76  	
77  	private final ResourcePath fileSystem = new LibhyphenFileSystem();
78  	
79  	private static class LibhyphenFileSystem implements ResourcePath {
80  
81  		private static final URI identifier = URLs.asURI("file:/");
82  		
83  		private static final Predicate<String> isLibhyphenTable = matchesGlobPattern("hyph_*.dic");
84  		
85  		public URI getIdentifier() {
86  			return identifier;
87  		}
88  		
89  		public URL resolve(URI resource) {
90  			try {
91  				resource = resource.normalize();
92  				resource = URLs.resolve(identifier, resource);
93  				File file = asFile(resource);
94  				if (file.exists() && isLibhyphenTable.apply(fileName(file)))
95  					return URLs.asURL(resource); }
96  			catch (Exception e) {}
97  			return null;
98  		}
99  		
100 		public URI canonicalize(URI resource) {
101 			return URLs.asURI(resolve(resource));
102 		}
103 	}
104 }