adding license text to feature projects since these were removed from feature.xml
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / parser / ParseHandler.java
1 /**
2 *
3 */
4 package eu.etaxonomy.taxeditor.parser;
5
6 import java.util.ArrayList;
7 import java.util.List;
8
9 import eu.etaxonomy.cdm.api.service.ICommonService;
10 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
11 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
12 import eu.etaxonomy.cdm.model.name.NonViralName;
13 import eu.etaxonomy.cdm.model.name.Rank;
14 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
15 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
16 import eu.etaxonomy.cdm.model.reference.Reference;
17 import eu.etaxonomy.cdm.strategy.match.MatchException;
18 import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
19 import eu.etaxonomy.taxeditor.model.MessagingUtils;
20 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
21 import eu.etaxonomy.taxeditor.store.CdmStore;
22
23 /**
24 * <p>ParseHandler class.</p>
25 *
26 * @author n.hoffmann
27 * @version $Id: $
28 */
29 public class ParseHandler{
30
31 private TaxonNameBase taxonNameBase;
32
33 private class MatchMatrix {
34 List<TaxonNameBase> duplicateNames = new ArrayList<TaxonNameBase>();
35
36 List<INomenclaturalReference> duplicateReferences = new ArrayList<INomenclaturalReference>();
37 List<INomenclaturalReference> duplicateInReferences = new ArrayList<INomenclaturalReference>();
38
39 List<TeamOrPersonBase> duplicateCombinationAuthorTeams = new ArrayList<TeamOrPersonBase>();
40 List<TeamOrPersonBase> duplicateExCombinationAuthorTeams = new ArrayList<TeamOrPersonBase>();
41 List<TeamOrPersonBase> duplicateBasionymAuthorTeams = new ArrayList<TeamOrPersonBase>();
42 List<TeamOrPersonBase> duplicateExBasionymAuthorTeams = new ArrayList<TeamOrPersonBase>();
43 }
44
45 private static NonViralNameParserImpl nonViralNameParser = NonViralNameParserImpl.NewInstance();
46
47 /**
48 * The name that should get parsed
49 */
50 private NonViralName name;
51
52 private boolean doResolveInReferences;
53
54 /**
55 * Creates a new instance
56 *
57 * @param textWidget
58 * @param name
59 */
60 private ParseHandler(TaxonNameBase name){
61 if(name == null){
62 this.name = nonViralNameParser.getNonViralNameInstance("", PreferencesUtil.getPreferredNomenclaturalCode());
63 }else{
64 this.name = (NonViralName) HibernateProxyHelper.deproxy(name);
65 }
66 }
67
68 /**
69 * Factory method to create a new instance of the this class
70 *
71 * @param textWidget The text widget where the NonViralName may be entered into
72 * @param name An initial NonViralName or null when creating a new name
73 * @return An instance of this class
74 */
75 public static ParseHandler NewInstance(TaxonNameBase name){
76 return new ParseHandler(name);
77
78 }
79
80 /**
81 * Parses a given string and returns a <code>TaxonNameBase</code> instance with the
82 * results of the parsing.
83 *
84 * This method should be used to quickly create a new name from a string.
85 * Wherever the string will be parsed again in subsequent editing, an instance
86 * of <code>ParseHandler</code> should be attached to the text widget.
87 *
88 * @param unparsedNameString a {@link java.lang.String} object.
89 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
90 */
91 public static TaxonNameBase parseReferencedName(String unparsedNameString, Rank rank){
92 TaxonNameBase name = nonViralNameParser.parseReferencedName(unparsedNameString,
93 PreferencesUtil.getPreferredNomenclaturalCode(), rank);
94
95 // if (name.hasProblem()) {
96 // name.setFullTitleCache(unparsedNameString);
97 // }
98
99 return name;
100 }
101
102 public static TaxonNameBase parseName(String unparsedNameString, Rank rank){
103 TaxonNameBase name = nonViralNameParser.parseFullName(unparsedNameString,
104 PreferencesUtil.getPreferredNomenclaturalCode(), rank);
105
106 return name;
107 }
108
109 /**
110 * Creates an empty <code>TaxonNameBase</code> instance with the nomenclatural code
111 * currently set in preferences.
112 *
113 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
114 */
115 public static TaxonNameBase createEmptyName(){
116 return nonViralNameParser.getNonViralNameInstance("", PreferencesUtil.getPreferredNomenclaturalCode());
117 }
118
119 /**
120 * Parses the string that was entered into the text widget and returns a
121 * NonViralName object that resulted from the parsing process.
122 *
123 * @return The parsed NonViralName object
124 */
125 public NonViralName parse(String unparsedNameString){
126
127 // String unparsedNameString = "";
128 // try {
129 // Method getText;
130 // getText = textWidget.getClass().getDeclaredMethod("getText", null);
131 // unparsedNameString = (String) getText.invoke(textWidget, null);
132 // } catch (Exception e) {
133 // // we should never get here
134 // StoreUtil.error(this.getClass(), "Error trying to invoke getText method", e);
135 // }
136
137
138 nonViralNameParser.parseReferencedName(name, unparsedNameString,
139 name.getRank(), true);
140
141 // if (name.hasProblem()) {
142 // name.setFullTitleCache(unparsedNameString);
143 // }
144
145 return name;
146 }
147
148 /**
149 * Parses the string that was entered into the text widget and returns a
150 * NonViralName object that resulted from the parsing process.
151 *
152 * The atomized fields (scientific name, author and reference) will be matched
153 * against the database to find possible duplicates. If duplicates were found
154 * the respective parts of the NonViralName will be replaced with the found
155 * objects.
156 *
157 * @return The parsed NonViralName object
158 */
159 public NonViralName parseAndResolveDuplicates(String unparsedNameString){
160
161 NonViralName parsedName = parse(unparsedNameString);
162
163 MatchMatrix matchMatrix = findMatches(parsedName);
164
165 resolveDuplicates(parsedName, matchMatrix);
166
167 return parsedName;
168 }
169
170
171
172
173 /**
174 * @param name The name to resolve duplicates for.
175 */
176 private void resolveDuplicates(NonViralName name, MatchMatrix matchMatrix) {
177 resolveDuplicateNames(name, matchMatrix);
178
179 resolveAllDuplicateAuthors(name, matchMatrix);
180
181 resolveDuplicateReferences(name, matchMatrix);
182
183 if(matchMatrix.duplicateInReferences != null)
184 resolveDuplicateInReferences(name, matchMatrix);
185 }
186
187
188 /**
189 * @param name The name to resolve duplicates for.
190 */
191 private void resolveDuplicateNames(NonViralName name, MatchMatrix matchMatrix) {
192
193 if (matchMatrix.duplicateNames.size() == 1){
194 name = (NonViralName) matchMatrix.duplicateNames.iterator().next();
195 }else if(matchMatrix.duplicateNames.size() > 1){
196 // FIXME TODO resolve multiple duplications. Use first match for a start
197 name = (NonViralName) matchMatrix.duplicateNames.iterator().next();
198 }
199 }
200
201 /**
202 * @param name The name to resolve duplicates for.
203 */
204 private void resolveDuplicateReferences(NonViralName name, MatchMatrix matchMatrix) {
205 if(matchMatrix.duplicateReferences.size() == 1){
206 // exactly one match. We assume that the user wants this reference
207 INomenclaturalReference duplicate = matchMatrix.duplicateReferences.iterator().next();
208 name.setNomenclaturalReference(duplicate);
209 }else if(matchMatrix.duplicateReferences.size() > 1){
210 // FIXME TODO resolve multiple duplications. Use first match for a start
211 INomenclaturalReference duplicate = matchMatrix.duplicateReferences.iterator().next();
212 name.setNomenclaturalReference(duplicate);
213 }
214 }
215
216 /**
217 * @param name The name to resolve duplicates for.
218 */
219 private void resolveDuplicateInReferences(NonViralName name, MatchMatrix matchMatrix) {
220 Reference reference = (Reference) HibernateProxyHelper.deproxy(name.getNomenclaturalReference());
221
222 if(matchMatrix.duplicateInReferences.size() > 0){
223 Reference inReference = (Reference) matchMatrix.duplicateInReferences.iterator().next();
224 reference.setInReference(inReference);
225 MessagingUtils.warn(this.getClass(), reference.generateTitle());
226 // FIXME TODO resolve multiple duplications. We use first match for a start
227 MessagingUtils.warn(this.getClass(), reference.getTitleCache());
228 }
229 }
230
231
232 /**
233 * @param name The name to resolve duplicates for.
234 */
235 private void resolveAllDuplicateAuthors(NonViralName name, MatchMatrix matchMatrix) {
236
237 if(matchMatrix.duplicateCombinationAuthorTeams.size() > 0){
238 name.setCombinationAuthorTeam(matchMatrix.duplicateCombinationAuthorTeams.iterator().next());
239 Reference reference = (Reference) name.getNomenclaturalReference();
240 if(reference != null){
241 reference.setAuthorTeam(matchMatrix.duplicateCombinationAuthorTeams.iterator().next());
242 }
243 // FIXME TODO resolve multiple duplications. We use first match for a start.
244 }
245
246 if(matchMatrix.duplicateExCombinationAuthorTeams.size() > 0){
247 name.setExCombinationAuthorTeam(matchMatrix.duplicateExCombinationAuthorTeams.iterator().next());
248 // FIXME TODO resolve multiple duplications. We use first match for a start.
249 }
250
251 if(matchMatrix.duplicateBasionymAuthorTeams.size() > 0){
252 name.setBasionymAuthorTeam(matchMatrix.duplicateBasionymAuthorTeams.iterator().next());
253 // FIXME TODO resolve multiple duplications. We use first match for a start.
254 }
255
256 if(matchMatrix.duplicateExBasionymAuthorTeams.size() > 0){
257 name.setExBasionymAuthorTeam(matchMatrix.duplicateExBasionymAuthorTeams.iterator().next());
258 // FIXME TODO resolve multiple duplications. We use first match for a start.
259 }
260 }
261
262 /**
263 * Splits a NonViralName into its parts and calls methods to find matches for these
264 * parts in the database.
265 *
266 * @param name The NonViralName to find matches for.
267 */
268 private MatchMatrix findMatches(NonViralName name){
269
270 MatchMatrix matchMatrix = new MatchMatrix();
271
272 matchMatrix.duplicateNames = findMatchingLatinNames(name);
273
274 matchMatrix.duplicateCombinationAuthorTeams = findMatchingAuthors((TeamOrPersonBase) name.getCombinationAuthorTeam());
275 matchMatrix.duplicateExCombinationAuthorTeams = findMatchingAuthors((TeamOrPersonBase) name.getExCombinationAuthorTeam());
276 matchMatrix.duplicateBasionymAuthorTeams = findMatchingAuthors((TeamOrPersonBase) name.getBasionymAuthorTeam());
277 matchMatrix.duplicateExBasionymAuthorTeams = findMatchingAuthors((TeamOrPersonBase) name.getExBasionymAuthorTeam());
278
279 INomenclaturalReference nomenclaturalReference = name.getNomenclaturalReference();
280
281 // check if the reference has an inreference and also check if the inReference already exists
282 if(nomenclaturalReference != null){
283 Reference inReference = ((Reference)nomenclaturalReference).getInReference();
284 if(inReference != null){
285 doResolveInReferences = true;
286 matchMatrix.duplicateInReferences = findMatchingNomenclaturalReference(inReference);
287 }
288 }
289
290 matchMatrix.duplicateReferences = findMatchingNomenclaturalReference(nomenclaturalReference);
291
292 return matchMatrix;
293 }
294
295 /**
296 * @param nomenclaturalReference The NomenclaturalReference to find matches for.
297 * @return A <code>List</code> of possibly matching NomenclaturalReference's.
298 */
299 private List<INomenclaturalReference> findMatchingNomenclaturalReference(INomenclaturalReference nomenclaturalReference) {
300 if(nomenclaturalReference == null) return new ArrayList<INomenclaturalReference>();
301 try{
302 return CdmStore.getService(ICommonService.class).findMatching(nomenclaturalReference, MatchStrategyConfigurator.ReferenceMatchStrategy());
303 }catch (MatchException e) {
304 MessagingUtils.error(this.getClass(), "Error finding matching references", e);
305 }
306 return null;
307 }
308
309 /**
310 * @param authorTeam The TeamOrPersonBase to find matches for.
311 * @return A <code>List</code> of possibly matching TeamOrPersonBase's.
312 */
313 private List<TeamOrPersonBase> findMatchingAuthors(TeamOrPersonBase authorTeam) {
314
315 if(authorTeam == null){
316 return new ArrayList<TeamOrPersonBase>();
317 }
318
319 try{
320 return CdmStore.getService(ICommonService.class).findMatching(authorTeam, MatchStrategyConfigurator.TeamOrPersonMatchStrategy());
321 }catch (MatchException e) {
322 MessagingUtils.error(this.getClass(), "Error finding matching authors", e);
323 }
324 return null;
325 }
326
327 /**
328 * @param taxonNameBase The TaxonNameBase to find matches for.
329 * @return A <code>List</code> of possibly matching TaxonNameBase's.
330 */
331 private List<TaxonNameBase> findMatchingLatinNames(TaxonNameBase taxonNameBase) {
332
333 try {
334 return CdmStore.getService(ICommonService.class).findMatching(taxonNameBase, MatchStrategyConfigurator.NonViralNameMatchStrategy());
335
336 } catch (MatchException e) {
337 MessagingUtils.error(this.getClass(), "Error finding matching names", e);
338 }
339 return null;
340 }
341 }