corrected visibility check for edit authorities editor
[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.hibernate.HibernateProxyHelper;
10 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
11 import eu.etaxonomy.cdm.model.name.NonViralName;
12 import eu.etaxonomy.cdm.model.name.Rank;
13 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
14 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
15 import eu.etaxonomy.cdm.model.reference.Reference;
16 import eu.etaxonomy.cdm.strategy.match.MatchException;
17 import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
18 import eu.etaxonomy.taxeditor.model.MessagingUtils;
19 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
20 import eu.etaxonomy.taxeditor.store.CdmStore;
21
22 /**
23 * <p>ParseHandler class.</p>
24 *
25 * @author n.hoffmann
26 * @version $Id: $
27 */
28 public class ParseHandler{
29
30 private TaxonNameBase taxonNameBase;
31
32 private class MatchMatrix {
33 List<TaxonNameBase> duplicateNames = new ArrayList<TaxonNameBase>();
34
35 List<INomenclaturalReference> duplicateReferences = new ArrayList<INomenclaturalReference>();
36 List<INomenclaturalReference> duplicateInReferences = new ArrayList<INomenclaturalReference>();
37
38 List<TeamOrPersonBase> duplicateCombinationAuthorTeams = new ArrayList<TeamOrPersonBase>();
39 List<TeamOrPersonBase> duplicateExCombinationAuthorTeams = new ArrayList<TeamOrPersonBase>();
40 List<TeamOrPersonBase> duplicateBasionymAuthorTeams = new ArrayList<TeamOrPersonBase>();
41 List<TeamOrPersonBase> duplicateExBasionymAuthorTeams = new ArrayList<TeamOrPersonBase>();
42 }
43
44 private static NonViralNameParserImpl nonViralNameParser = NonViralNameParserImpl.NewInstance();
45
46 /**
47 * The name that should get parsed
48 */
49 private NonViralName name;
50
51 private boolean doResolveInReferences;
52
53 /**
54 * Creates a new instance
55 *
56 * @param textWidget
57 * @param name
58 */
59 private ParseHandler(TaxonNameBase name){
60 if(name == null){
61 this.name = nonViralNameParser.getNonViralNameInstance("", PreferencesUtil.getPreferredNomenclaturalCode());
62 }else{
63 this.name = (NonViralName) HibernateProxyHelper.deproxy(name);
64 }
65 }
66
67 /**
68 * Factory method to create a new instance of the this class
69 *
70 * @param textWidget The text widget where the NonViralName may be entered into
71 * @param name An initial NonViralName or null when creating a new name
72 * @return An instance of this class
73 */
74 public static ParseHandler NewInstance(TaxonNameBase name){
75 return new ParseHandler(name);
76
77 }
78
79 /**
80 * Parses a given string and returns a <code>TaxonNameBase</code> instance with the
81 * results of the parsing.
82 *
83 * This method should be used to quickly create a new name from a string.
84 * Wherever the string will be parsed again in subsequent editing, an instance
85 * of <code>ParseHandler</code> should be attached to the text widget.
86 *
87 * @param unparsedNameString a {@link java.lang.String} object.
88 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
89 */
90 public static TaxonNameBase parseReferencedName(String unparsedNameString, Rank rank){
91 TaxonNameBase name = nonViralNameParser.parseReferencedName(unparsedNameString,
92 PreferencesUtil.getPreferredNomenclaturalCode(), rank);
93
94 // if (name.hasProblem()) {
95 // name.setFullTitleCache(unparsedNameString);
96 // }
97
98 return name;
99 }
100
101 public static TaxonNameBase parseName(String unparsedNameString, Rank rank){
102 TaxonNameBase name = nonViralNameParser.parseFullName(unparsedNameString,
103 PreferencesUtil.getPreferredNomenclaturalCode(), rank);
104
105 return name;
106 }
107
108 /**
109 * Creates an empty <code>TaxonNameBase</code> instance with the nomenclatural code
110 * currently set in preferences.
111 *
112 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
113 */
114 public static TaxonNameBase createEmptyName(){
115 return nonViralNameParser.getNonViralNameInstance("", PreferencesUtil.getPreferredNomenclaturalCode());
116 }
117
118 /**
119 * Parses the string that was entered into the text widget and returns a
120 * NonViralName object that resulted from the parsing process.
121 *
122 * @return The parsed NonViralName object
123 */
124 public NonViralName parse(String unparsedNameString){
125
126 // String unparsedNameString = "";
127 // try {
128 // Method getText;
129 // getText = textWidget.getClass().getDeclaredMethod("getText", null);
130 // unparsedNameString = (String) getText.invoke(textWidget, null);
131 // } catch (Exception e) {
132 // // we should never get here
133 // StoreUtil.error(this.getClass(), "Error trying to invoke getText method", e);
134 // }
135
136
137 nonViralNameParser.parseReferencedName(name, unparsedNameString,
138 name.getRank(), true);
139
140 // if (name.hasProblem()) {
141 // name.setFullTitleCache(unparsedNameString);
142 // }
143
144 return name;
145 }
146
147 /**
148 * Parses the string that was entered into the text widget and returns a
149 * NonViralName object that resulted from the parsing process.
150 *
151 * The atomized fields (scientific name, author and reference) will be matched
152 * against the database to find possible duplicates. If duplicates were found
153 * the respective parts of the NonViralName will be replaced with the found
154 * objects.
155 *
156 * @return The parsed NonViralName object
157 */
158 public NonViralName parseAndResolveDuplicates(String unparsedNameString){
159
160 NonViralName parsedName = parse(unparsedNameString);
161
162 MatchMatrix matchMatrix = findMatches(parsedName);
163
164 resolveDuplicates(parsedName, matchMatrix);
165
166 return parsedName;
167 }
168
169
170
171
172 /**
173 * @param name The name to resolve duplicates for.
174 */
175 private void resolveDuplicates(NonViralName name, MatchMatrix matchMatrix) {
176 resolveDuplicateNames(name, matchMatrix);
177
178 resolveAllDuplicateAuthors(name, matchMatrix);
179
180 resolveDuplicateReferences(name, matchMatrix);
181
182 if(matchMatrix.duplicateInReferences != null) {
183 resolveDuplicateInReferences(name, matchMatrix);
184 }
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.setAuthorship(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(name.getCombinationAuthorTeam());
275 matchMatrix.duplicateExCombinationAuthorTeams = findMatchingAuthors(name.getExCombinationAuthorTeam());
276 matchMatrix.duplicateBasionymAuthorTeams = findMatchingAuthors(name.getBasionymAuthorTeam());
277 matchMatrix.duplicateExBasionymAuthorTeams = findMatchingAuthors(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) {
301 return new ArrayList<INomenclaturalReference>();
302 }
303 try{
304 return CdmStore.getCommonService().findMatching(nomenclaturalReference, MatchStrategyConfigurator.ReferenceMatchStrategy());
305 }catch (MatchException e) {
306 MessagingUtils.error(this.getClass(), "Error finding matching references", e);
307 }
308 return null;
309 }
310
311 /**
312 * @param authorTeam The TeamOrPersonBase to find matches for.
313 * @return A <code>List</code> of possibly matching TeamOrPersonBase's.
314 */
315 private List<TeamOrPersonBase> findMatchingAuthors(TeamOrPersonBase authorTeam) {
316
317 if(authorTeam == null){
318 return new ArrayList<TeamOrPersonBase>();
319 }
320
321 try{
322 return CdmStore.getCommonService().findMatching(authorTeam, MatchStrategyConfigurator.TeamOrPersonMatchStrategy());
323 }catch (MatchException e) {
324 MessagingUtils.error(this.getClass(), "Error finding matching authors", e);
325 }
326 return null;
327 }
328
329 /**
330 * @param taxonNameBase The TaxonNameBase to find matches for.
331 * @return A <code>List</code> of possibly matching TaxonNameBase's.
332 */
333 private List<TaxonNameBase> findMatchingLatinNames(TaxonNameBase taxonNameBase) {
334
335 try {
336 return CdmStore.getCommonService().findMatching(taxonNameBase, MatchStrategyConfigurator.NonViralNameMatchStrategy());
337
338 } catch (MatchException e) {
339 MessagingUtils.error(this.getClass(), "Error finding matching names", e);
340 }
341 return null;
342 }
343 }