4 package eu
.etaxonomy
.taxeditor
.parser
;
6 import java
.util
.ArrayList
;
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
;
23 * <p>ParseHandler class.</p>
28 public class ParseHandler
{
30 private TaxonNameBase taxonNameBase
;
32 private class MatchMatrix
{
33 List
<TaxonNameBase
> duplicateNames
= new ArrayList
<TaxonNameBase
>();
35 List
<INomenclaturalReference
> duplicateReferences
= new ArrayList
<INomenclaturalReference
>();
36 List
<INomenclaturalReference
> duplicateInReferences
= new ArrayList
<INomenclaturalReference
>();
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
>();
44 private static NonViralNameParserImpl nonViralNameParser
= NonViralNameParserImpl
.NewInstance();
47 * The name that should get parsed
49 private NonViralName name
;
51 private boolean doResolveInReferences
;
54 * Creates a new instance
59 private ParseHandler(TaxonNameBase name
){
61 this.name
= nonViralNameParser
.getNonViralNameInstance("", PreferencesUtil
.getPreferredNomenclaturalCode());
63 this.name
= (NonViralName
) HibernateProxyHelper
.deproxy(name
);
68 * Factory method to create a new instance of the this class
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
74 public static ParseHandler
NewInstance(TaxonNameBase name
){
75 return new ParseHandler(name
);
80 * Parses a given string and returns a <code>TaxonNameBase</code> instance with the
81 * results of the parsing.
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.
87 * @param unparsedNameString a {@link java.lang.String} object.
88 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
90 public static TaxonNameBase
parseReferencedName(String unparsedNameString
, Rank rank
){
91 TaxonNameBase name
= nonViralNameParser
.parseReferencedName(unparsedNameString
,
92 PreferencesUtil
.getPreferredNomenclaturalCode(), rank
);
94 // if (name.hasProblem()) {
95 // name.setFullTitleCache(unparsedNameString);
101 public static TaxonNameBase
parseName(String unparsedNameString
, Rank rank
){
102 TaxonNameBase name
= nonViralNameParser
.parseFullName(unparsedNameString
,
103 PreferencesUtil
.getPreferredNomenclaturalCode(), rank
);
109 * Creates an empty <code>TaxonNameBase</code> instance with the nomenclatural code
110 * currently set in preferences.
112 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
114 public static TaxonNameBase
createEmptyName(){
115 return nonViralNameParser
.getNonViralNameInstance("", PreferencesUtil
.getPreferredNomenclaturalCode());
119 * Parses the string that was entered into the text widget and returns a
120 * NonViralName object that resulted from the parsing process.
122 * @return The parsed NonViralName object
124 public NonViralName
parse(String unparsedNameString
){
126 // String unparsedNameString = "";
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);
137 nonViralNameParser
.parseReferencedName(name
, unparsedNameString
,
138 name
.getRank(), true);
140 // if (name.hasProblem()) {
141 // name.setFullTitleCache(unparsedNameString);
148 * Parses the string that was entered into the text widget and returns a
149 * NonViralName object that resulted from the parsing process.
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
156 * @return The parsed NonViralName object
158 public NonViralName
parseAndResolveDuplicates(String unparsedNameString
){
160 NonViralName parsedName
= parse(unparsedNameString
);
162 MatchMatrix matchMatrix
= findMatches(parsedName
);
164 resolveDuplicates(parsedName
, matchMatrix
);
173 * @param name The name to resolve duplicates for.
175 private void resolveDuplicates(NonViralName name
, MatchMatrix matchMatrix
) {
176 resolveDuplicateNames(name
, matchMatrix
);
178 resolveAllDuplicateAuthors(name
, matchMatrix
);
180 resolveDuplicateReferences(name
, matchMatrix
);
182 if(matchMatrix
.duplicateInReferences
!= null) {
183 resolveDuplicateInReferences(name
, matchMatrix
);
189 * @param name The name to resolve duplicates for.
191 private void resolveDuplicateNames(NonViralName name
, MatchMatrix matchMatrix
) {
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();
202 * @param name The name to resolve duplicates for.
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
);
217 * @param name The name to resolve duplicates for.
219 private void resolveDuplicateInReferences(NonViralName name
, MatchMatrix matchMatrix
) {
220 Reference reference
= (Reference
) HibernateProxyHelper
.deproxy(name
.getNomenclaturalReference());
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());
233 * @param name The name to resolve duplicates for.
235 private void resolveAllDuplicateAuthors(NonViralName name
, MatchMatrix matchMatrix
) {
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());
243 // FIXME TODO resolve multiple duplications. We use first match for a start.
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.
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.
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.
263 * Splits a NonViralName into its parts and calls methods to find matches for these
264 * parts in the database.
266 * @param name The NonViralName to find matches for.
268 private MatchMatrix
findMatches(NonViralName name
){
270 MatchMatrix matchMatrix
= new MatchMatrix();
272 matchMatrix
.duplicateNames
= findMatchingLatinNames(name
);
274 matchMatrix
.duplicateCombinationAuthorTeams
= findMatchingAuthors(name
.getCombinationAuthorTeam());
275 matchMatrix
.duplicateExCombinationAuthorTeams
= findMatchingAuthors(name
.getExCombinationAuthorTeam());
276 matchMatrix
.duplicateBasionymAuthorTeams
= findMatchingAuthors(name
.getBasionymAuthorTeam());
277 matchMatrix
.duplicateExBasionymAuthorTeams
= findMatchingAuthors(name
.getExBasionymAuthorTeam());
279 INomenclaturalReference nomenclaturalReference
= name
.getNomenclaturalReference();
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
);
290 matchMatrix
.duplicateReferences
= findMatchingNomenclaturalReference(nomenclaturalReference
);
296 * @param nomenclaturalReference The NomenclaturalReference to find matches for.
297 * @return A <code>List</code> of possibly matching NomenclaturalReference's.
299 private List
<INomenclaturalReference
> findMatchingNomenclaturalReference(INomenclaturalReference nomenclaturalReference
) {
300 if(nomenclaturalReference
== null) {
301 return new ArrayList
<INomenclaturalReference
>();
304 return CdmStore
.getCommonService().findMatching(nomenclaturalReference
, MatchStrategyConfigurator
.ReferenceMatchStrategy());
305 }catch (MatchException e
) {
306 MessagingUtils
.error(this.getClass(), "Error finding matching references", e
);
312 * @param authorTeam The TeamOrPersonBase to find matches for.
313 * @return A <code>List</code> of possibly matching TeamOrPersonBase's.
315 private List
<TeamOrPersonBase
> findMatchingAuthors(TeamOrPersonBase authorTeam
) {
317 if(authorTeam
== null){
318 return new ArrayList
<TeamOrPersonBase
>();
322 return CdmStore
.getCommonService().findMatching(authorTeam
, MatchStrategyConfigurator
.TeamOrPersonMatchStrategy());
323 }catch (MatchException e
) {
324 MessagingUtils
.error(this.getClass(), "Error finding matching authors", e
);
330 * @param taxonNameBase The TaxonNameBase to find matches for.
331 * @return A <code>List</code> of possibly matching TaxonNameBase's.
333 private List
<TaxonNameBase
> findMatchingLatinNames(TaxonNameBase taxonNameBase
) {
336 return CdmStore
.getCommonService().findMatching(taxonNameBase
, MatchStrategyConfigurator
.NonViralNameMatchStrategy());
338 } catch (MatchException e
) {
339 MessagingUtils
.error(this.getClass(), "Error finding matching names", e
);