1 package org.daisy.pipeline.nlp.lexing;
2
3 import java.util.Collection;
4 import java.util.List;
5 import java.util.Locale;
6 import java.util.Map;
7 import java.util.concurrent.ConcurrentHashMap;
8 import java.util.concurrent.CopyOnWriteArrayList;
9
10 import org.daisy.pipeline.nlp.lexing.LexService.LexerInitException;
11 import org.daisy.pipeline.nlp.lexing.LexService.LexerToken;
12
13 import org.osgi.service.component.annotations.Component;
14 import org.osgi.service.component.annotations.Reference;
15 import org.osgi.service.component.annotations.ReferenceCardinality;
16 import org.osgi.service.component.annotations.ReferencePolicy;
17
18 @Component(
19 name = "lexer-registry",
20 service = { LexServiceRegistry.class }
21 )
22 public class LexServiceRegistry {
23 private Map<LexService, List<LexerToken>> mLexerToTokens = new ConcurrentHashMap<LexService, List<LexerToken>>();
24
25
26
27
28 @Reference(
29 name = "LexService",
30 unbind = "-",
31 service = LexService.class,
32 cardinality = ReferenceCardinality.MULTIPLE,
33 policy = ReferencePolicy.STATIC
34 )
35 public void addLexService(LexService lexer) {
36 mLexerToTokens.put(lexer, new CopyOnWriteArrayList<LexService.LexerToken>());
37 }
38
39
40
41
42 public void removeLexService(LexService lexer) {
43 List<LexerToken> tokens = mLexerToTokens.get(lexer);
44 synchronized (this) {
45 if (tokens.size() > 0) {
46 lexer.globalRelease();
47 }
48 }
49 mLexerToTokens.remove(lexer);
50 }
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public LexerToken getTokenForLang(Locale lang, Collection<LexerToken> existingTokens)
69 throws LexerInitException {
70
71 int bestScore = -1;
72 LexerToken bestToken = null;
73 for (LexerToken token : existingTokens) {
74 int score = token.getLexService().getLexQuality(lang);
75 if (score > bestScore) {
76 bestScore = score;
77 bestToken = token;
78 }
79 }
80
81
82 Map.Entry<LexService, List<LexerToken>> best = null;
83 for (Map.Entry<LexService, List<LexerToken>> entry : mLexerToTokens.entrySet()) {
84 int score = entry.getKey().getLexQuality(lang);
85 if (score > bestScore) {
86 bestScore = score;
87 best = entry;
88 bestToken = null;
89 }
90 }
91
92 if (bestToken != null) {
93
94
95 for (LexerToken otherToken : mLexerToTokens.get(bestToken.getLexService())) {
96 bestToken.shareResourcesWith(otherToken, lang);
97 }
98 bestToken.addLang(lang);
99 return bestToken;
100 }
101
102
103 LexerToken result = best.getKey().newToken();
104 result.addLang(lang);
105 best.getValue().add(result);
106 synchronized (this) {
107 if (best.getValue().size() == 1) {
108 best.getKey().globalInit();
109 }
110 }
111
112 return result;
113 }
114
115
116
117
118
119 public LexerToken getFallbackToken(Collection<LexerToken> existingTokens)
120 throws LexerInitException {
121
122 int bestScore = 0;
123 LexerToken bestToken = null;
124 for (LexerToken token : existingTokens) {
125 int score = token.getLexService().getOverallQuality();
126 if (score > bestScore) {
127 bestScore = score;
128 bestToken = token;
129 }
130 }
131
132
133 Map.Entry<LexService, List<LexerToken>> best = null;
134 for (Map.Entry<LexService, List<LexerToken>> entry : mLexerToTokens.entrySet()) {
135 int score = entry.getKey().getOverallQuality();
136 if (score > bestScore) {
137 bestScore = score;
138 best = entry;
139 bestToken = null;
140 }
141 }
142
143 if (bestToken != null) {
144 return bestToken;
145 }
146
147 if (best == null) {
148 throw new LexerInitException("No generic lexing service available");
149 }
150
151
152 LexerToken result = best.getKey().newToken();
153 synchronized (this) {
154 if (best.getValue().size() == 1) {
155 best.getKey().globalInit();
156 }
157 }
158
159 return result;
160 }
161
162
163
164
165
166
167
168 public void releaseToken(LexerToken jobtoken) {
169 for (List<LexerToken> tokens : mLexerToTokens.values()) {
170 if (tokens.remove(jobtoken)) {
171 synchronized (this) {
172 if (tokens.size() == 0) {
173 jobtoken.getLexService().globalRelease();
174 }
175 }
176 return;
177 }
178 }
179
180 }
181
182 }