Project

General

Profile

Download (11.9 KB) Statistics
| Branch: | Tag: | Revision:
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.INonViralName;
12
import eu.etaxonomy.cdm.model.name.ITaxonNameBase;
13
import eu.etaxonomy.cdm.model.name.NonViralName;
14
import eu.etaxonomy.cdm.model.name.Rank;
15
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
16
import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
17
import eu.etaxonomy.cdm.model.reference.Reference;
18
import eu.etaxonomy.cdm.strategy.match.MatchException;
19
import eu.etaxonomy.cdm.strategy.match.MatchStrategyConfigurator.MatchStrategy;
20
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
21
import eu.etaxonomy.taxeditor.model.MessagingUtils;
22
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
23
import eu.etaxonomy.taxeditor.store.CdmStore;
24

    
25
/**
26
 * <p>ParseHandler class.</p>
27
 *
28
 * @author n.hoffmann
29
 * @version $Id: $
30
 */
31
public class ParseHandler{
32

    
33
	private TaxonNameBase taxonNameBase;
34

    
35
	private class MatchMatrix {
36
		List<TaxonNameBase> duplicateNames = new ArrayList<TaxonNameBase>();
37

    
38
		List<INomenclaturalReference> duplicateReferences = new ArrayList<INomenclaturalReference>();
39
		List<INomenclaturalReference> duplicateInReferences = new ArrayList<INomenclaturalReference>();
40

    
41
		List<TeamOrPersonBase> duplicateCombinationAuthorships = new ArrayList<TeamOrPersonBase>();
42
		List<TeamOrPersonBase> duplicateExCombinationAuthorships = new ArrayList<TeamOrPersonBase>();
43
		List<TeamOrPersonBase> duplicateBasionymAuthorships = new ArrayList<TeamOrPersonBase>();
44
		List<TeamOrPersonBase> duplicateExBasionymAuthorships = new ArrayList<TeamOrPersonBase>();
45
	}
46

    
47
	private static NonViralNameParserImpl nonViralNameParser = NonViralNameParserImpl.NewInstance();
48

    
49
	/**
50
	 * The name that should get parsed
51
	 */
52
	private INonViralName name;
53

    
54
	private boolean doResolveInReferences;
55

    
56
	/**
57
	 * Creates a new instance
58
	 *
59
	 * @param textWidget
60
	 * @param name
61
	 */
62
	private ParseHandler(TaxonNameBase name){
63
		if(name == null){
64
			this.name = nonViralNameParser.getNonViralNameInstance("", PreferencesUtil.getPreferredNomenclaturalCode());
65
		}else{
66
			this.name = (NonViralName) HibernateProxyHelper.deproxy(name);
67
		}
68
	}
69

    
70
	/**
71
	 * Factory method to create a new instance of the this class
72
	 *
73
	 * @param textWidget	The text widget where the NonViralName may be entered into
74
	 * @param name			An initial NonViralName or null when creating a new name
75
	 * @return				An instance of this class
76
	 */
77
	public static ParseHandler NewInstance(TaxonNameBase name){
78
		return new ParseHandler(name);
79

    
80
	}
81

    
82
	/**
83
	 * Parses a given string and returns a <code>TaxonNameBase</code> instance with the
84
	 * results of the parsing.
85
	 *
86
	 * This method should be used to quickly create a new name from a string.
87
	 * Wherever the string will be parsed again in subsequent editing, an instance
88
	 * of <code>ParseHandler</code> should be attached to the text widget.
89
	 *
90
	 * @param unparsedNameString a {@link java.lang.String} object.
91
	 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
92
	 */
93
	public static NonViralName parseReferencedName(String unparsedNameString, Rank rank){
94
	    NonViralName name = nonViralNameParser.parseReferencedName(unparsedNameString,
95
				PreferencesUtil.getPreferredNomenclaturalCode(), rank);
96

    
97
//		if (name.hasProblem()) {
98
//			name.setFullTitleCache(unparsedNameString);
99
//		}
100

    
101
		return name;
102
	}
103

    
104
	public static TaxonNameBase<?,?> parseName(String unparsedNameString, Rank rank){
105
		INonViralName name = nonViralNameParser.parseFullName(unparsedNameString,
106
				PreferencesUtil.getPreferredNomenclaturalCode(), rank);
107
		
108
		return (TaxonNameBase<?,?>)name;
109
	}
110

    
111
	/**
112
	 * Creates an empty <code>TaxonNameBase</code> instance with the nomenclatural code
113
	 * currently set in preferences.
114
	 *
115
	 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
116
	 */
117
	public static TaxonNameBase<?,?> createEmptyName(){
118
		return (TaxonNameBase<?,?>)nonViralNameParser.getNonViralNameInstance("", PreferencesUtil.getPreferredNomenclaturalCode());
119
	}
120

    
121
	/**
122
	 * Parses the string that was entered into the text widget and returns a
123
	 * NonViralName object that resulted from the parsing process.
124
	 *
125
	 * @return	The parsed NonViralName object
126
	 */
127
	public INonViralName parse(String unparsedNameString){
128

    
129
//		String unparsedNameString = "";
130
//		try {
131
//			Method getText;
132
//			getText = textWidget.getClass().getDeclaredMethod("getText", null);
133
//			unparsedNameString = (String) getText.invoke(textWidget, null);
134
//		} catch (Exception e) {
135
//			// we should never get here
136
//			StoreUtil.error(this.getClass(), "Error trying to invoke getText method", e);
137
//		}
138

    
139

    
140
		nonViralNameParser.parseReferencedName(name, unparsedNameString,
141
				name.getRank(), true);
142

    
143
//		if (name.hasProblem()) {
144
//			name.setFullTitleCache(unparsedNameString);
145
//		}
146

    
147
		return name;
148
	}
149

    
150
	/**
151
	 * Parses the string that was entered into the text widget and returns a
152
	 * NonViralName object that resulted from the parsing process.
153
	 *
154
	 * The atomized fields (scientific name, author and reference) will be matched
155
	 * against the database to find possible duplicates. If duplicates were found
156
	 * the respective parts of the NonViralName will be replaced with the found
157
	 * objects.
158
	 *
159
	 * @return	The parsed NonViralName object
160
	 */
161
	public INonViralName parseAndResolveDuplicates(String unparsedNameString){
162

    
163
		INonViralName parsedName = parse(unparsedNameString);
164

    
165
		MatchMatrix matchMatrix = findMatches(parsedName);
166

    
167
		resolveDuplicates(parsedName, matchMatrix);
168

    
169
		return parsedName;
170
	}
171

    
172

    
173

    
174

    
175
	/**
176
	 * @param name The name to resolve duplicates for.
177
	 */
178
	private void resolveDuplicates(INonViralName name, MatchMatrix matchMatrix) {
179
		resolveDuplicateNames(name, matchMatrix);
180

    
181
		resolveAllDuplicateAuthors(name, matchMatrix);
182

    
183
		resolveDuplicateReferences(name, matchMatrix);
184

    
185
		if(matchMatrix.duplicateInReferences != null) {
186
            resolveDuplicateInReferences(name, matchMatrix);
187
        }
188
	}
189

    
190

    
191
	/**
192
	 * @param name The name to resolve duplicates for.
193
	 */
194
	private void resolveDuplicateNames(INonViralName name, MatchMatrix matchMatrix) {
195

    
196
		if (matchMatrix.duplicateNames.size() == 1){
197
			name = matchMatrix.duplicateNames.iterator().next();
198
		}else if(matchMatrix.duplicateNames.size() > 1){
199
			// FIXME TODO resolve multiple duplications. Use first match for a start
200
			name = matchMatrix.duplicateNames.iterator().next();
201
		}
202
	}
203

    
204
	/**
205
	 * @param name The name to resolve duplicates for.
206
	 */
207
	private void resolveDuplicateReferences(INonViralName name, MatchMatrix matchMatrix) {
208
		if(matchMatrix.duplicateReferences.size() == 1){
209
			// exactly one match. We assume that the user wants this reference
210
			INomenclaturalReference duplicate = matchMatrix.duplicateReferences.iterator().next();
211
			name.setNomenclaturalReference(duplicate);
212
		}else if(matchMatrix.duplicateReferences.size() > 1){
213
			// FIXME TODO resolve multiple duplications. Use first match for a start
214
			INomenclaturalReference duplicate = matchMatrix.duplicateReferences.iterator().next();
215
			name.setNomenclaturalReference(duplicate);
216
		}
217
	}
218

    
219
	/**
220
	 * @param name The name to resolve duplicates for.
221
	 */
222
	private void resolveDuplicateInReferences(INonViralName name, MatchMatrix matchMatrix) {
223
		Reference reference = (Reference) HibernateProxyHelper.deproxy(name.getNomenclaturalReference());
224

    
225
		if(matchMatrix.duplicateInReferences.size() > 0){
226
			Reference inReference = (Reference) matchMatrix.duplicateInReferences.iterator().next();
227
			reference.setInReference(inReference);
228
			MessagingUtils.warn(this.getClass(), reference.generateTitle());
229
			// FIXME TODO resolve multiple duplications. We use first match for a start
230
			MessagingUtils.warn(this.getClass(), reference.getTitleCache());
231
		}
232
	}
233

    
234

    
235
	/**
236
	 * @param name The name to resolve duplicates for.
237
	 */
238
	private void resolveAllDuplicateAuthors(INonViralName name, MatchMatrix matchMatrix) {
239

    
240
		if(matchMatrix.duplicateCombinationAuthorships.size() > 0){
241
			name.setCombinationAuthorship(matchMatrix.duplicateCombinationAuthorships.iterator().next());
242
			Reference reference = (Reference) name.getNomenclaturalReference();
243
			if(reference != null){
244
				reference.setAuthorship(matchMatrix.duplicateCombinationAuthorships.iterator().next());
245
			}
246
			// FIXME TODO resolve multiple duplications. We use first match for a start.
247
		}
248

    
249
		if(matchMatrix.duplicateExCombinationAuthorships.size() > 0){
250
			name.setExCombinationAuthorship(matchMatrix.duplicateExCombinationAuthorships.iterator().next());
251
			// FIXME TODO resolve multiple duplications. We use first match for a start.
252
		}
253

    
254
		if(matchMatrix.duplicateBasionymAuthorships.size() > 0){
255
			name.setBasionymAuthorship(matchMatrix.duplicateBasionymAuthorships.iterator().next());
256
			// FIXME TODO resolve multiple duplications. We use first match for a start.
257
		}
258

    
259
		if(matchMatrix.duplicateExBasionymAuthorships.size() > 0){
260
			name.setExBasionymAuthorship(matchMatrix.duplicateExBasionymAuthorships.iterator().next());
261
			// FIXME TODO resolve multiple duplications. We use first match for a start.
262
		}
263
	}
264

    
265
	/**
266
	 * Splits a NonViralName into its parts and calls methods to find matches for these
267
	 * parts in the database.
268
	 *
269
	 * @param name	The NonViralName to find matches for.
270
	 */
271
	private MatchMatrix findMatches(INonViralName name){
272

    
273
		MatchMatrix matchMatrix = new MatchMatrix();
274

    
275
		matchMatrix.duplicateNames = findMatchingLatinNames(name);
276

    
277
		matchMatrix.duplicateCombinationAuthorships = findMatchingAuthors(name.getCombinationAuthorship());
278
		matchMatrix.duplicateExCombinationAuthorships = findMatchingAuthors(name.getExCombinationAuthorship());
279
		matchMatrix.duplicateBasionymAuthorships = findMatchingAuthors(name.getBasionymAuthorship());
280
		matchMatrix.duplicateExBasionymAuthorships = findMatchingAuthors(name.getExBasionymAuthorship());
281

    
282
		INomenclaturalReference nomenclaturalReference = name.getNomenclaturalReference();
283

    
284
		// check if the reference has an inreference and also check if the inReference already exists
285
		if(nomenclaturalReference != null){
286
			Reference inReference = ((Reference)nomenclaturalReference).getInReference();
287
			if(inReference != null){
288
				doResolveInReferences = true;
289
				matchMatrix.duplicateInReferences = findMatchingNomenclaturalReference(inReference);
290
			}
291
		}
292

    
293
		matchMatrix.duplicateReferences = findMatchingNomenclaturalReference(nomenclaturalReference);
294

    
295
		return matchMatrix;
296
	}
297

    
298
	/**
299
	 * @param nomenclaturalReference	The NomenclaturalReference to find matches for.
300
	 * @return	A <code>List</code> of possibly matching NomenclaturalReference's.
301
	 */
302
	private List<INomenclaturalReference> findMatchingNomenclaturalReference(INomenclaturalReference nomenclaturalReference) {
303
		if(nomenclaturalReference == null) {
304
            return new ArrayList<INomenclaturalReference>();
305
        }
306
		try{
307

    
308
			return CdmStore.getCommonService().findMatching(nomenclaturalReference, MatchStrategy.Reference);
309

    
310
		}catch (MatchException e) {
311
			MessagingUtils.error(this.getClass(), "Error finding matching references", e);
312
		}
313
		return null;
314
	}
315

    
316
	/**
317
	 * @param authorTeam	The TeamOrPersonBase to find matches for.
318
	 * @return	A <code>List</code> of possibly matching TeamOrPersonBase's.
319
	 */
320
	private List<TeamOrPersonBase> findMatchingAuthors(TeamOrPersonBase authorTeam) {
321

    
322
		if(authorTeam == null){
323
			return new ArrayList<TeamOrPersonBase>();
324
		}
325

    
326
		try{
327

    
328
			return CdmStore.getCommonService().findMatching(authorTeam, MatchStrategy.TeamOrPerson);
329

    
330
		}catch (MatchException e) {
331
			MessagingUtils.error(this.getClass(), "Error finding matching authors", e);
332
		}
333
		return null;
334
	}
335

    
336
	/**
337
	 * @param taxonNameBase	The TaxonNameBase to find matches for.
338
	 * @return	A <code>List</code> of possibly matching TaxonNameBase's.
339
	 */
340
	private List<TaxonNameBase> findMatchingLatinNames(ITaxonNameBase taxonNameBase) {
341

    
342
		try {
343

    
344
			return CdmStore.getCommonService().findMatching(TaxonNameBase.castAndDeproxy(taxonNameBase), MatchStrategy.NonViralName);
345

    
346

    
347
		} catch (MatchException e) {
348
			MessagingUtils.error(this.getClass(), "Error finding matching names", e);
349
		}
350
		return null;
351
	}
352
}
(2-2/2)