Project

General

Profile

Download (16.8 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2018 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.strategy.match;
10

    
11
import eu.etaxonomy.cdm.model.agent.Person;
12
import eu.etaxonomy.cdm.model.agent.Team;
13
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
14
import eu.etaxonomy.cdm.model.reference.Reference;
15
import eu.etaxonomy.cdm.model.reference.ReferenceType;
16

    
17
/**
18
 * @author a.mueller
19
 * @since 17.10.2018
20
 */
21
public class MatchStrategyFactory {
22

    
23
    public static IMatchStrategyEqual NewDefaultInstance(Class<? extends IMatchable> matchClass){
24
        return new DefaultMatchStrategy(matchClass);
25
    }
26

    
27
    public static IParsedMatchStrategy NewParsedInstance(Class<? extends IMatchable> matchClass){
28
        IParsedMatchStrategy parsedMatchStrategy = new ParsedBaseMatchStrategy(matchClass);
29
        return parsedMatchStrategy;
30
    }
31

    
32
    public static IParsedMatchStrategy NewParsedPersonInstance(){
33
        try {
34
            IParsedMatchStrategy parsedPersonMatchStrategy = NewParsedInstance(Person.class);
35

    
36
            addParsedAgentBaseMatchModes(parsedPersonMatchStrategy);
37

    
38
            //FIXME adapt for inRef authors
39
            parsedPersonMatchStrategy.setMatchMode("familyName", MatchMode.EQUAL_OR_FIRST_NULL);
40

    
41
            //TODO lifespan may implement MATCH_OR_ONE_NULL
42
            String[] equalOrNullParams = new String[]{"collectorTitle","givenName","initials",
43
                    "lifespan","orcid","prefix","suffix"};
44
            for(String param : equalOrNullParams){
45
                parsedPersonMatchStrategy.setMatchMode(param, MatchMode.EQUAL_OR_FIRST_NULL);
46
            }
47

    
48
            String[] ignoreParams = new String[]{"institutionalMemberships"};
49
            for(String param : ignoreParams){
50
                parsedPersonMatchStrategy.setMatchMode(param, MatchMode.IGNORE);
51
            }
52

    
53
            return parsedPersonMatchStrategy;
54
        } catch (MatchException e) {
55
            throw new RuntimeException("Exception when creating parsed person match strategy.", e);
56
        }
57
    }
58

    
59
    public static IParsedMatchStrategy NewParsedTeamInstance(){
60
        IParsedMatchStrategy parsedTeamMatchStrategy = NewParsedInstance(Team.class);
61
        try {
62
            addParsedAgentBaseMatchModes(parsedTeamMatchStrategy);
63

    
64
            parsedTeamMatchStrategy.setMatchMode("teamMembers", MatchMode.MATCH, NewParsedPersonInstance());
65

    
66
            parsedTeamMatchStrategy.setMatchMode("hasMoreMembers", MatchMode.EQUAL);
67

    
68
            //TODO is this correct?
69
            parsedTeamMatchStrategy.setMatchMode("protectedCollectorTitleCache", MatchMode.EQUAL_OR_FIRST_NULL);
70
            parsedTeamMatchStrategy.setMatchMode("protectedNomenclaturalTitleCache", MatchMode.EQUAL);
71

    
72
            String[] equalOrNullParams = new String[]{"collectorTitle"};
73
            for(String param : equalOrNullParams){
74
                parsedTeamMatchStrategy.setMatchMode(param, MatchMode.EQUAL_OR_FIRST_NULL);
75
            }
76

    
77
            String[] ignoreParams = new String[]{};
78
            for(String param : ignoreParams){
79
                parsedTeamMatchStrategy.setMatchMode(param, MatchMode.IGNORE);
80
            }
81

    
82
            return parsedTeamMatchStrategy;
83
        } catch (MatchException e) {
84
            throw new RuntimeException("Exception when creating parsed team match strategy.", e);
85
        }
86
    }
87

    
88
    public static IParsedMatchStrategy NewParsedTeamOrPersonInstance(){
89
        @SuppressWarnings("rawtypes")
90
        SubClassMatchStrategy<TeamOrPersonBase> parsedAuthorMatchStrategy = SubClassMatchStrategy.NewInstance(TeamOrPersonBase.class);
91
        try {
92
            parsedAuthorMatchStrategy.putStrategy(Person.class, NewParsedPersonInstance());
93
            parsedAuthorMatchStrategy.putStrategy(Team.class, NewParsedTeamInstance());
94
            return parsedAuthorMatchStrategy;
95
        } catch (MatchException e) {
96
            throw new RuntimeException("Exception when creating parsed author match strategy.", e);
97
        }
98
    }
99

    
100
    public static IParsedMatchStrategy NewParsedBookInstance(){
101
        try {
102
            IParsedMatchStrategy parsedBookMatchStrategy = NewParsedInstance(Reference.class);
103

    
104
            addParsedReferenceMatchModes(parsedBookMatchStrategy);
105

    
106
            //author (as it should always be known for a parsed book)
107
            parsedBookMatchStrategy.setMatchMode("authorship", MatchMode.MATCH_REQUIRED, NewParsedTeamOrPersonInstance());
108
            //in-reference , parsed book has no in-Reference
109
            parsedBookMatchStrategy.setMatchMode("inReference", MatchMode.EQUAL_OR_FIRST_NULL);
110
            parsedBookMatchStrategy.setMatchMode("title", MatchMode.EQUAL_OR_FIRST_NULL);  //not available in parsed book
111
            parsedBookMatchStrategy.setMatchMode("abbrevTitle", MatchMode.EQUAL_REQUIRED);
112

    
113
            //TODO caches
114

    
115
            return parsedBookMatchStrategy;
116
        } catch (MatchException e) {
117
            throw new RuntimeException("Exception when creating parsed team match strategy.", e);
118
        }
119
    }
120

    
121
    /**
122
     * As the book section is not clearly defined if parsed (usually only the author and publication date is known),
123
     * it can only match exactly. If pages, title, abbrevTitle are known for the more complete references
124
     * it will match only if they are also known for the parsed instance.
125
     */
126
    public static IParsedMatchStrategy NewParsedBookSectionInstance(){
127
        try {
128
            IParsedMatchStrategy parsedBookSectionMatchStrategy = (IParsedMatchStrategy)NewDefaultInstance(Reference.class);
129

    
130
            addParsedSectionReferenceMatchModes(parsedBookSectionMatchStrategy);
131

    
132
            //author (or either title or authorship match, but usually only authorship is known for parsed instances)
133
            parsedBookSectionMatchStrategy.setMatchMode("authorship", MatchMode.MATCH_REQUIRED, NewParsedTeamOrPersonInstance());
134
            //in-reference
135
            parsedBookSectionMatchStrategy.setMatchMode("inReference", MatchMode.MATCH_REQUIRED, NewParsedBookInstance());
136
            //see comment on title and abbrevTitle in #NewParsedArticleInstance
137
            parsedBookSectionMatchStrategy.setMatchMode("title", MatchMode.EQUAL);
138
            parsedBookSectionMatchStrategy.setMatchMode("abbrevTitle", MatchMode.EQUAL);
139

    
140
            //TODO caches
141

    
142
            return parsedBookSectionMatchStrategy;
143

    
144
        } catch (MatchException e) {
145
            throw new RuntimeException("Exception when creating parsed team match strategy.", e);
146
        }
147
    }
148

    
149
    public static IParsedMatchStrategy NewParsedArticleInstance(){ //or should it better be Section (in Journal)
150
        try {
151
            IParsedMatchStrategy articleMatchStrategy = (IParsedMatchStrategy)NewDefaultInstance(Reference.class);
152

    
153
            addParsedSectionReferenceMatchModes(articleMatchStrategy);
154

    
155
            //if a title or abbrevTitle exists for the existing (first) article
156
            //we can not guarantee that the article is really the one that is
157
            //meant in the context, there could be other articles with the same
158
            //author.
159
            //Having a soft matching for possible candidates may solve this issue.
160
            //Also comparing the detail (page) with a filled field "pages" may solve
161
            //it in many cases.
162
            //However, we need to accept that articles as nomenclatural references are not
163
            //clearly enough defined so exact matching with rich data is not possible at
164
            //this point
165
            //TODO improvement, check page number
166
            articleMatchStrategy.setMatchMode("title", MatchMode.EQUAL);
167
            articleMatchStrategy.setMatchMode("abbrevTitle", MatchMode.EQUAL);
168

    
169
            articleMatchStrategy.setMatchMode("authorship", MatchMode.MATCH_REQUIRED, NewParsedTeamOrPersonInstance());
170
            articleMatchStrategy.setMatchMode("inReference", MatchMode.MATCH, NewParsedJournalInstance());
171

    
172
            //TODO caches
173

    
174
            return articleMatchStrategy;
175
        } catch (MatchException e) {
176
            throw new RuntimeException("Problems when creating parsed article match strategy.");
177
        }
178
    }
179

    
180
    /**
181
     * Adds all typical parsed reference match modes which are equal for non section references
182
     * (journal, book, (generic(?))).
183
     * The following fields need to be handled explicitly by each calling method:<BR>
184
     *
185
     * <LI>authorship</LI>
186
     * <LI>title</LI>
187
     * <LI>abbrevTitle</LI>
188
     * <LI>titleCache</LI>
189
     * <LI>abbrevTitleCache</LI>
190
     * <LI>protectedTitleCache</LI>
191
     * <LI>protectedAbbrevTitleCache</LI>
192
     * <LI>inReference</LI>
193
     *
194
     * @see #addParsedSectionReferenceMatchModes(IParsedMatchStrategy)
195
     * @param referenceMatchStrategy the strategy to fill
196
     * @throws MatchException
197
     */
198
    private static void addParsedReferenceMatchModes(IParsedMatchStrategy referenceMatchStrategy) throws MatchException {
199

    
200
        //"placePublished" should be MatchMode.EQUAL if parser parses place published
201
        //TODO datePublished could also be more detailed in first then in second, e.g. Apr 2008 <-> 2008,
202
        //something like MatchMode.IncludedIn is needed here
203

    
204
        //TODO externally managed
205

    
206
        addParsedIdentifiableEntityModes(referenceMatchStrategy);
207

    
208
        String[] equalOrNullParams = new String[]{"accessed","doi",
209
                "institution","isbn","issn","organization",
210
                "pages","publisher","placePublished",
211
                "referenceAbstract","school","uri"};
212
        for(String param : equalOrNullParams){
213
            referenceMatchStrategy.setMatchMode(param, MatchMode.EQUAL_OR_FIRST_NULL);
214
        }
215

    
216
        String[] equalParams = new String[]{"datePublished","edition",
217
                "editor","seriesPart","volume"};
218
        for(String param : equalParams){
219
            referenceMatchStrategy.setMatchMode(param, MatchMode.EQUAL);
220
        }
221
        String[] matchOrNullParams = new String[]{"institution"};
222
        for(String param : matchOrNullParams){
223
            referenceMatchStrategy.setMatchMode(param, MatchMode.MATCH_OR_FIRST_NULL);
224
        }
225
    }
226

    
227
    /**
228
     * Adds all typical parsed reference match modes which are equal for section references
229
     * (article, book section).
230
     * The following fields need to be handled explicitly by each calling method:<BR>
231
     *
232
     * For further information see: #9157
233
     *
234
     * <LI>authorship</LI>
235
     * <LI>title</LI>
236
     * <LI>abbrevTitle</LI>
237
     * <LI>titleCache</LI>
238
     * <LI>abbrevTitleCache</LI>
239
     * <LI>protectedTitleCache</LI>
240
     * <LI>protectedAbbrevTitleCache</LI>
241
     * <LI>inReference</LI>
242
     *
243
     * @see #addParsedReferenceMatchModes(IParsedMatchStrategy)
244
     * @param referenceMatchStrategy the strategy to fill
245
     * @throws MatchException
246
     */
247
    private static void addParsedSectionReferenceMatchModes(IParsedMatchStrategy referenceMatchStrategy) throws MatchException {
248

    
249
        //"placePublished" should be MatchMode.EQUAL if parser parses place published
250
        //TODO datePublished could also be more detailed in first then in second, e.g. Apr 2008 <-> 2008,
251
        //something like MatchMode.IncludedIn is needed here
252
        //TODO pages if a page number is given the parsed reference may not be unidentified anymore
253

    
254
        //TODO externally managed
255

    
256
        addParsedIdentifiableEntityModes(referenceMatchStrategy);
257

    
258
        //here the result differs from addParsedReferenceMatchModes
259
        String[] equalOrNullParams = new String[]{"accessed","doi",
260
                "institution","isbn","issn","organization",
261
                "pages","publisher","placePublished",
262
                "referenceAbstract","school","uri"};
263
        for(String param : equalOrNullParams){
264
            referenceMatchStrategy.setMatchMode(param, MatchMode.EQUAL); //EQUAL !!
265
        }
266

    
267
        String[] equalParams = new String[]{"datePublished","edition",
268
                "editor","seriesPart","volume"};
269
        for(String param : equalParams){
270
            referenceMatchStrategy.setMatchMode(param, MatchMode.EQUAL);
271
        }
272
        String[] matchOrNullParams = new String[]{"institution"};
273
        for(String param : matchOrNullParams){
274
            referenceMatchStrategy.setMatchMode(param, MatchMode.MATCH); //MATCH!!
275
        }
276
    }
277

    
278
    private static void addParsedAgentBaseMatchModes(IParsedMatchStrategy matchStrategy) throws MatchException {
279

    
280
        //FIXME adapt for inRef authors
281
        //TODO how to initialize this cache field in a generic way
282
        matchStrategy.setMatchMode("nomenclaturalTitle", MatchMode.EQUAL_REQUIRED);
283

    
284
        addParsedIdentifiableEntityModes(matchStrategy);
285

    
286
        //TODO contact does not yet works, also not with EQUAL_OR_ONE_NULL, leads to agent.id=? or agent.id is null query
287
        //better should be even handled with MATCH.Equal_OR_ONE_NULL
288
        String[] equalOrNullParams = new String[]{"collectorTitle"};
289
        for(String param : equalOrNullParams){
290
            matchStrategy.setMatchMode(param, MatchMode.EQUAL_OR_FIRST_NULL);
291
        }
292
        String[] ignoreCollectionParams = new String[]{"media"};
293
        for(String param : ignoreCollectionParams){
294
            matchStrategy.setMatchMode(param, MatchMode.IGNORE);
295
        }
296
    }
297

    
298
    private static void addParsedIdentifiableEntityModes(IParsedMatchStrategy matchStrategy) throws MatchException {
299

    
300
        addAnnotatableEntityModes(matchStrategy);
301

    
302
        //TODO titleCache and protectedTitleCache
303

    
304
        //TODO lsid should be handled with MATCH
305
        String[] equalOrNullParams = new String[]{"lsid"};
306
        for(String param : equalOrNullParams){
307
            matchStrategy.setMatchMode(param, MatchMode.EQUAL_OR_FIRST_NULL);
308
        }
309
        String[] ignoreCollectionParams = new String[]{"credits","extensions","identifiers","links","rights"};
310
        for(String param : ignoreCollectionParams){
311
            matchStrategy.setMatchMode(param, MatchMode.IGNORE);
312
        }
313
    }
314

    
315
    private static void addAnnotatableEntityModes(IParsedMatchStrategy matchStrategy) throws MatchException {
316

    
317
//        //TODO titleCache and protectedTitleCache
318
//
319
//        //TODO lsid should be handled with MATCH
320
//        String[] equalOrNullParams = new String[]{"lsid"};
321
//        for(String param : equalOrNullParams){
322
//            matchStrategy.setMatchMode(param, MatchMode.EQUAL_OR_ONE_NULL);
323
//        }
324
        String[] ignoreCollectionParams = new String[]{"sources","annotations","markers"};
325
        for(String param : ignoreCollectionParams){
326
            matchStrategy.setMatchMode(param, MatchMode.IGNORE);
327
        }
328
    }
329

    
330
    public static IParsedMatchStrategy NewParsedJournalInstance(){
331

    
332
        try {
333
            IParsedMatchStrategy parsedJournalMatchStrategy = NewParsedInstance(Reference.class);
334
            addParsedReferenceMatchModes(parsedJournalMatchStrategy);
335

    
336
            //journals must not have an author, better MatchMode would be MatchMode.NULL
337
            parsedJournalMatchStrategy.setMatchMode("authorship", MatchMode.MATCH, NewParsedTeamOrPersonInstance());
338
            //in-reference, parsed journal has no in-reference
339
            parsedJournalMatchStrategy.setMatchMode("inReference", MatchMode.EQUAL_OR_FIRST_NULL);
340
            parsedJournalMatchStrategy.setMatchMode("title", MatchMode.EQUAL_OR_FIRST_NULL);  //full title not available in parsed journal
341
            parsedJournalMatchStrategy.setMatchMode("abbrevTitle", MatchMode.EQUAL_REQUIRED);
342

    
343
            //TODO caches
344

    
345
            return parsedJournalMatchStrategy;
346
        } catch (MatchException e) {
347
            throw new RuntimeException("Exception when creating parsed journal match strategy.", e);
348
        }
349
    }
350

    
351
    public static IParsedMatchStrategy NewParsedReferenceInstance(){
352
        IParsedMatchStrategy refStrat = ParsedReferenceMatchStrategy.INSTANCE();
353
        return refStrat;
354
    }
355

    
356
    /**
357
     * Returns the best matching strategy for a given reference
358
     * with a given reference type
359
     * @return the matching strategy
360
     * @throws NullPointerException if ref is <code>null</code>
361
     */
362
    public static IMatchStrategy NewParsedReferenceInstance(Reference ref) {
363
        ReferenceType type = ref.getType();
364
        if (type.equals(ReferenceType.Article)){
365
            return NewParsedArticleInstance();
366
        }else if (type.equals(ReferenceType.Book)){
367
            return NewParsedBookInstance();
368
        }else if (type.equals(ReferenceType.BookSection)){
369
            return NewParsedBookSectionInstance();
370
        }else if (type.equals(ReferenceType.Journal)){
371
            return NewParsedJournalInstance();
372
        }else if (type.equals(ReferenceType.Generic)){
373
            //TODO
374
            return NewDefaultInstance(Reference.class);
375
        }else{
376
            //TODO
377
            return NewDefaultInstance(Reference.class);
378
        }
379
    }
380

    
381
    //  public static IMatchStrategy NewParsedNameInstance(){
382
    //      IMatchStrategy result = new DefaultMatchStrategy(TaxonName.class);
383
    //      return result;
384
    //  }
385
}
(14-14/18)