Project

General

Profile

Download (11.8 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.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
}
(2-2/2)