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.Rank;
14
import eu.etaxonomy.cdm.model.name.TaxonName;
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
 */
29
public class ParseHandler{
30

    
31
	private TaxonName taxonName;
32

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

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

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

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

    
47
	/**
48
	 * The name that should get parsed
49
	 */
50
	private INonViralName name;
51

    
52
	private boolean doResolveInReferences;
53

    
54
	/**
55
	 * Creates a new instance
56
	 *
57
	 * @param textWidget
58
	 * @param name
59
	 */
60
	private ParseHandler(TaxonName name){
61
		if(name == null){
62
			this.name = nonViralNameParser.getNonViralNameInstance("", PreferencesUtil.getPreferredNomenclaturalCode());
63
		}else{
64
			this.name = 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(TaxonName 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 INonViralName parseReferencedName(String unparsedNameString, Rank rank){
92
	    INonViralName 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 TaxonName parseName(String unparsedNameString, Rank rank){
103
		INonViralName name = nonViralNameParser.parseFullName(unparsedNameString,
104
				PreferencesUtil.getPreferredNomenclaturalCode(), rank);
105

    
106
		return (TaxonName)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 TaxonName createEmptyName(){
116
		return (TaxonName)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 INonViralName 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 INonViralName parseAndResolveDuplicates(String unparsedNameString){
160

    
161
		INonViralName 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(INonViralName 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
	/**
190
	 * @param name The name to resolve duplicates for.
191
	 */
192
	private void resolveDuplicateNames(INonViralName name, MatchMatrix matchMatrix) {
193

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

    
202
	/**
203
	 * @param name The name to resolve duplicates for.
204
	 */
205
	private void resolveDuplicateReferences(INonViralName name, MatchMatrix matchMatrix) {
206
		if(matchMatrix.duplicateReferences.size() == 1){
207
			// exactly one match. We assume that the user wants this reference
208
			INomenclaturalReference duplicate = matchMatrix.duplicateReferences.iterator().next();
209
			name.setNomenclaturalReference(duplicate);
210
		}else if(matchMatrix.duplicateReferences.size() > 1){
211
			// FIXME TODO resolve multiple duplications. Use first match for a start
212
			INomenclaturalReference duplicate = matchMatrix.duplicateReferences.iterator().next();
213
			name.setNomenclaturalReference(duplicate);
214
		}
215
		//if reference is new but the in reference is already in db
216
		if (matchMatrix.duplicateReferences.size() == 0 && name.getNomenclaturalReference().getInReference() != null && matchMatrix.duplicateInReferences.size() > 0){
217
		    resolveDuplicateInReferences(name, matchMatrix);
218
		}
219
	}
220

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

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

    
236

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

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

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

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

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

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

    
275
		MatchMatrix matchMatrix = new MatchMatrix();
276

    
277
		matchMatrix.duplicateNames = findMatchingLatinNames(name);
278

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

    
284
		INomenclaturalReference nomenclaturalReference = name.getNomenclaturalReference();
285

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

    
295
		matchMatrix.duplicateReferences = findMatchingNomenclaturalReference(nomenclaturalReference);
296

    
297
		return matchMatrix;
298
	}
299

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

    
310
			return CdmStore.getCommonService().findMatching(nomenclaturalReference, MatchStrategy.Reference);
311

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

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

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

    
328
		try{
329

    
330
			return CdmStore.getCommonService().findMatching(authorTeam, MatchStrategy.TeamOrPerson);
331

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

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

    
344
		try {
345

    
346
			return CdmStore.getCommonService().findMatching(TaxonName.castAndDeproxy(taxonName), MatchStrategy.NonViralName);
347

    
348

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