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.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.match.MatchStrategyConfigurator.MatchStrategy;
19
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
20
import eu.etaxonomy.taxeditor.model.MessagingUtils;
21
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
22
import eu.etaxonomy.taxeditor.store.CdmStore;
23

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

    
32
	private TaxonNameBase taxonNameBase;
33

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

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

    
40
		List<TeamOrPersonBase> duplicateCombinationAuthorTeams = new ArrayList<TeamOrPersonBase>();
41
		List<TeamOrPersonBase> duplicateExCombinationAuthorTeams = new ArrayList<TeamOrPersonBase>();
42
		List<TeamOrPersonBase> duplicateBasionymAuthorTeams = new ArrayList<TeamOrPersonBase>();
43
		List<TeamOrPersonBase> duplicateExBasionymAuthorTeams = new ArrayList<TeamOrPersonBase>();
44
	}
45

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

    
48
	/**
49
	 * The name that should get parsed
50
	 */
51
	private NonViralName name;
52

    
53
	private boolean doResolveInReferences;
54

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

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

    
79
	}
80

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

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

    
100
		return name;
101
	}
102

    
103
	public static NonViralName parseName(String unparsedNameString, Rank rank){
104
		NonViralName name = nonViralNameParser.parseFullName(unparsedNameString,
105
				PreferencesUtil.getPreferredNomenclaturalCode(), rank);
106

    
107
		return name;
108
	}
109

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

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

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

    
138

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

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

    
146
		return name;
147
	}
148

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

    
162
		NonViralName parsedName = parse(unparsedNameString);
163

    
164
		MatchMatrix matchMatrix = findMatches(parsedName);
165

    
166
		resolveDuplicates(parsedName, matchMatrix);
167

    
168
		return parsedName;
169
	}
170

    
171

    
172

    
173

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

    
180
		resolveAllDuplicateAuthors(name, matchMatrix);
181

    
182
		resolveDuplicateReferences(name, matchMatrix);
183

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

    
189

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

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

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

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

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

    
233

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

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

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

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

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

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

    
272
		MatchMatrix matchMatrix = new MatchMatrix();
273

    
274
		matchMatrix.duplicateNames = findMatchingLatinNames(name);
275

    
276
		matchMatrix.duplicateCombinationAuthorTeams = findMatchingAuthors(name.getCombinationAuthorTeam());
277
		matchMatrix.duplicateExCombinationAuthorTeams = findMatchingAuthors(name.getExCombinationAuthorTeam());
278
		matchMatrix.duplicateBasionymAuthorTeams = findMatchingAuthors(name.getBasionymAuthorTeam());
279
		matchMatrix.duplicateExBasionymAuthorTeams = findMatchingAuthors(name.getExBasionymAuthorTeam());
280

    
281
		INomenclaturalReference nomenclaturalReference = name.getNomenclaturalReference();
282

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

    
292
		matchMatrix.duplicateReferences = findMatchingNomenclaturalReference(nomenclaturalReference);
293

    
294
		return matchMatrix;
295
	}
296

    
297
	/**
298
	 * @param nomenclaturalReference	The NomenclaturalReference to find matches for.
299
	 * @return	A <code>List</code> of possibly matching NomenclaturalReference's.
300
	 */
301
	private List<INomenclaturalReference> findMatchingNomenclaturalReference(INomenclaturalReference nomenclaturalReference) {
302
		if(nomenclaturalReference == null) {
303
            return new ArrayList<INomenclaturalReference>();
304
        }
305
		try{
306
			return CdmStore.getService(ICommonService.class).findMatching(nomenclaturalReference, MatchStrategy.Reference);
307
		}catch (MatchException e) {
308
			MessagingUtils.error(this.getClass(), "Error finding matching references", e);
309
		}
310
		return null;
311
	}
312

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

    
319
		if(authorTeam == null){
320
			return new ArrayList<TeamOrPersonBase>();
321
		}
322

    
323
		try{
324
			return CdmStore.getService(ICommonService.class).findMatching(authorTeam, MatchStrategy.TeamOrPerson);
325
		}catch (MatchException e) {
326
			MessagingUtils.error(this.getClass(), "Error finding matching authors", e);
327
		}
328
		return null;
329
	}
330

    
331
	/**
332
	 * @param taxonNameBase	The TaxonNameBase to find matches for.
333
	 * @return	A <code>List</code> of possibly matching TaxonNameBase's.
334
	 */
335
	private List<TaxonNameBase> findMatchingLatinNames(TaxonNameBase taxonNameBase) {
336

    
337
		try {
338
			return CdmStore.getService(ICommonService.class).findMatching(taxonNameBase, MatchStrategy.NonViralName);
339

    
340
		} catch (MatchException e) {
341
			MessagingUtils.error(this.getClass(), "Error finding matching names", e);
342
		}
343
		return null;
344
	}
345
}
    (1-1/1)