1   package org.daisy.pipeline.braille.pef;
2   
3   import java.util.Collection;
4   import java.util.Collections;
5   import java.util.HashMap;
6   import java.util.Iterator;
7   import java.util.Map;
8   import java.util.NoSuchElementException;
9   
10  import com.google.common.base.Optional;
11  
12  import org.daisy.dotify.api.factory.FactoryProperties;
13  import org.daisy.dotify.api.table.Table;
14  import org.daisy.pipeline.braille.common.Query;
15  import org.daisy.pipeline.braille.common.Query.MutableQuery;
16  import static org.daisy.pipeline.braille.common.Query.util.mutableQuery;
17  
18  public abstract class AbstractTableProvider implements TableProvider {
19  	
20  	protected abstract Iterable<Table> _get(Query query);
21  	
22  	private final Map<String,Table> tablesFromId = new HashMap<String,Table>();
23  
24  	@Override
25  	public Collection<FactoryProperties> list() {
26  		// only list cached tables in preview-table option
27  		return Collections.unmodifiableCollection(tablesFromId.values());
28  	}
29  
30  	@Override
31  	public Table newFactory(String identifier) {
32  		MutableQuery q = mutableQuery();
33  		q.add("id", identifier);
34  		try {
35  			return get(q).iterator().next(); }
36  		catch (NoSuchElementException e) {
37  			return null; }
38  	}
39  
40  	@Override
41  	public final Iterable<Table> get(Query query) {
42  		MutableQuery q = mutableQuery(query);
43  		if (q.containsKey("id")) {
44  			String id = q.removeOnly("id").getValue().get();
45  			if (q.isEmpty()) {
46  				Table table = tablesFromId.get(id);
47  				if (table != null)
48  					return Collections.singleton(table); }
49  			else
50  				return empty; }
51  		return cache(_get(query));
52  	}
53  	
54  	private final static Iterable<Table> empty = Optional.<Table>absent().asSet();
55  	
56  	private Iterable<Table> cache(final Iterable<Table> tables) {
57  		return new Iterable<Table>() {
58  			public Iterator<Table> iterator() {
59  				return new Iterator<Table>() {
60  					Iterator<Table> i = null;
61  					public boolean hasNext() {
62  						if (i == null) i = tables.iterator();
63  						return i.hasNext();
64  					}
65  					public Table next() {
66  						Table t;
67  						if (i == null) i = tables.iterator();
68  						t = i.next();
69  						tablesFromId.put(t.getIdentifier(), t);
70  						return t;
71  					}
72  					public void remove() {
73  						if (i == null) i = tables.iterator();
74  						i.remove();
75  					}
76  				};
77  			}
78  		};
79  	}
80  }