4 package eu
.etaxonomy
.taxeditor
.parser
;
6 import java
.util
.ArrayList
;
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
.parser
.NonViralNameParserImpl
;
19 import eu
.etaxonomy
.taxeditor
.preference
.PreferencesUtil
;
20 import eu
.etaxonomy
.taxeditor
.store
.CdmStore
;
21 import eu
.etaxonomy
.taxeditor
.store
.StoreUtil
;
24 * <p>ParseHandler class.</p>
29 public class ParseHandler
{
31 private TaxonNameBase taxonNameBase
;
33 private class MatchMatrix
{
34 List
<TaxonNameBase
> duplicateNames
= new ArrayList
<TaxonNameBase
>();
36 List
<INomenclaturalReference
> duplicateReferences
= new ArrayList
<INomenclaturalReference
>();
37 List
<INomenclaturalReference
> duplicateInReferences
= new ArrayList
<INomenclaturalReference
>();
39 List
<TeamOrPersonBase
> duplicateCombinationAuthorTeams
= new ArrayList
<TeamOrPersonBase
>();
40 List
<TeamOrPersonBase
> duplicateExCombinationAuthorTeams
= new ArrayList
<TeamOrPersonBase
>();
41 List
<TeamOrPersonBase
> duplicateBasionymAuthorTeams
= new ArrayList
<TeamOrPersonBase
>();
42 List
<TeamOrPersonBase
> duplicateExBasionymAuthorTeams
= new ArrayList
<TeamOrPersonBase
>();
45 private static NonViralNameParserImpl nonViralNameParser
= NonViralNameParserImpl
.NewInstance();
48 * The name that should get parsed
50 private NonViralName name
;
52 private boolean doResolveInReferences
;
55 * Creates a new instance
60 private ParseHandler(TaxonNameBase name
){
62 this.name
= nonViralNameParser
.getNonViralNameInstance("", PreferencesUtil
.getPreferredNomenclaturalCode());
64 this.name
= (NonViralName
) HibernateProxyHelper
.deproxy(name
);
69 * Factory method to create a new instance of the this class
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
75 public static ParseHandler
NewInstance(TaxonNameBase name
){
76 return new ParseHandler(name
);
81 * Parses a given string and returns a <code>TaxonNameBase</code> instance with the
82 * results of the parsing.
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.
88 * @param unparsedNameString a {@link java.lang.String} object.
89 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
91 public static TaxonNameBase
parseReferencedName(String unparsedNameString
, Rank rank
){
92 TaxonNameBase name
= nonViralNameParser
.parseReferencedName(unparsedNameString
,
93 PreferencesUtil
.getPreferredNomenclaturalCode(), rank
);
95 // if (name.hasProblem()) {
96 // name.setFullTitleCache(unparsedNameString);
102 public static TaxonNameBase
parseName(String unparsedNameString
, Rank rank
){
103 TaxonNameBase name
= nonViralNameParser
.parseFullName(unparsedNameString
,
104 PreferencesUtil
.getPreferredNomenclaturalCode(), rank
);
110 * Creates an empty <code>TaxonNameBase</code> instance with the nomenclatural code
111 * currently set in preferences.
113 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
115 public static TaxonNameBase
createEmptyName(){
116 return nonViralNameParser
.getNonViralNameInstance("", PreferencesUtil
.getPreferredNomenclaturalCode());
120 * Parses the string that was entered into the text widget and returns a
121 * NonViralName object that resulted from the parsing process.
123 * @return The parsed NonViralName object
125 public NonViralName
parse(String unparsedNameString
){
127 // String unparsedNameString = "";
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);
138 nonViralNameParser
.parseReferencedName(name
, unparsedNameString
,
139 name
.getRank(), true);
141 // if (name.hasProblem()) {
142 // name.setFullTitleCache(unparsedNameString);
149 * Parses the string that was entered into the text widget and returns a
150 * NonViralName object that resulted from the parsing process.
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
157 * @return The parsed NonViralName object
159 public NonViralName
parseAndResolveDuplicates(String unparsedNameString
){
161 NonViralName parsedName
= parse(unparsedNameString
);
163 MatchMatrix matchMatrix
= findMatches(parsedName
);
165 resolveDuplicates(parsedName
, matchMatrix
);
174 * @param name The name to resolve duplicates for.
176 private void resolveDuplicates(NonViralName name
, MatchMatrix matchMatrix
) {
177 resolveDuplicateNames(name
, matchMatrix
);
179 resolveAllDuplicateAuthors(name
, matchMatrix
);
181 resolveDuplicateReferences(name
, matchMatrix
);
183 if(matchMatrix
.duplicateInReferences
!= null)
184 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 StoreUtil
.warn(this.getClass(), reference
.generateTitle());
226 // FIXME TODO resolve multiple duplications. We use first match for a start
227 StoreUtil
.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
.setAuthorTeam(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((TeamOrPersonBase
) name
.getCombinationAuthorTeam());
275 matchMatrix
.duplicateExCombinationAuthorTeams
= findMatchingAuthors((TeamOrPersonBase
) name
.getExCombinationAuthorTeam());
276 matchMatrix
.duplicateBasionymAuthorTeams
= findMatchingAuthors((TeamOrPersonBase
) name
.getBasionymAuthorTeam());
277 matchMatrix
.duplicateExBasionymAuthorTeams
= findMatchingAuthors((TeamOrPersonBase
) 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) return new ArrayList
<INomenclaturalReference
>();
302 return CdmStore
.getService(ICommonService
.class).findMatching(nomenclaturalReference
, MatchStrategyConfigurator
.ReferenceMatchStrategy());
303 }catch (MatchException e
) {
304 StoreUtil
.error(this.getClass(), "Error finding matching references", e
);
310 * @param authorTeam The TeamOrPersonBase to find matches for.
311 * @return A <code>List</code> of possibly matching TeamOrPersonBase's.
313 private List
<TeamOrPersonBase
> findMatchingAuthors(TeamOrPersonBase authorTeam
) {
315 if(authorTeam
== null){
316 return new ArrayList
<TeamOrPersonBase
>();
320 return CdmStore
.getService(ICommonService
.class).findMatching(authorTeam
, MatchStrategyConfigurator
.TeamOrPersonMatchStrategy());
321 }catch (MatchException e
) {
322 StoreUtil
.error(this.getClass(), "Error finding matching authors", e
);
328 * @param taxonNameBase The TaxonNameBase to find matches for.
329 * @return A <code>List</code> of possibly matching TaxonNameBase's.
331 private List
<TaxonNameBase
> findMatchingLatinNames(TaxonNameBase taxonNameBase
) {
334 return CdmStore
.getService(ICommonService
.class).findMatching(taxonNameBase
, MatchStrategyConfigurator
.NonViralNameMatchStrategy());
336 } catch (MatchException e
) {
337 StoreUtil
.error(this.getClass(), "Error finding matching names", e
);