Project

General

Profile

Revision 4cab2fd1

ID4cab2fd1c02b7ccf6fd892d90b2389947d9416f5
Parent 943941be
Child 269cc178

Added by Andreas Müller almost 2 years ago

Add series parsing with letters (test)

View differences:

cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/berlinModel/BerlinModelTransformer.java
282 282
	public static final UUID uuidMclCode = UUID.fromString("aa27083a-6a96-42aa-a2f8-5541cf057067");
283 283
	public static final UUID PARENTAL_SPECIES_EXT_UUID = UUID.fromString("fee3138a-0084-4571-8e32-56bd14a4b0a8");
284 284

  
285
	//Identifier Type
286
	public static final UUID uuidEMReferenceSourceNumber = UUID.fromString("06b02bbd-bf22-485c-9fd1-fad9175f0d53");
287

  
285 288
	//Area Level
286 289
	public static final UUID uuidEuroMedAreaLevelTop = UUID.fromString("190d5758-4b96-4016-9412-6dc9c36ef5fd");
287 290
	public static final UUID uuidEuroMedAreaLevelFirst = UUID.fromString("d21503e3-875e-4abc-82ec-f812e3cfea84");
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/common/utils/ImportDeduplicationHelper.java
41 41
import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
42 42
import eu.etaxonomy.cdm.model.reference.Reference;
43 43
import eu.etaxonomy.cdm.strategy.match.DefaultMatchStrategy;
44
import eu.etaxonomy.cdm.strategy.match.IMatchStrategy;
44
import eu.etaxonomy.cdm.strategy.match.IMatchStrategyEqual;
45 45
import eu.etaxonomy.cdm.strategy.match.MatchException;
46 46
import eu.etaxonomy.cdm.strategy.match.MatchMode;
47 47

  
......
74 74
    private Map<String, Set<Collection>> collectionMap = new HashMap<>();
75 75

  
76 76

  
77
    private IMatchStrategy referenceMatcher = DefaultMatchStrategy.NewInstance(Reference.class);
77
    private IMatchStrategyEqual referenceMatcher = DefaultMatchStrategy.NewInstance(Reference.class);
78 78
//    private IMatchStrategy collectionMatcher = DefaultMatchStrategy.NewInstance(Collection.class);
79
    private IMatchStrategy nameMatcher = DefaultMatchStrategy.NewInstance(TaxonName.class);
80
    private IMatchStrategy personMatcher = DefaultMatchStrategy.NewInstance(Person.class);
81
    private IMatchStrategy teamMatcher = DefaultMatchStrategy.NewInstance(Team.class);
79
    private IMatchStrategyEqual nameMatcher = DefaultMatchStrategy.NewInstance(TaxonName.class);
80
    private IMatchStrategyEqual personMatcher = DefaultMatchStrategy.NewInstance(Person.class);
81
    private IMatchStrategyEqual teamMatcher = DefaultMatchStrategy.NewInstance(Team.class);
82 82

  
83 83

  
84 84
 // ************************** FACTORY *******************************/
......
229 229
    private Optional<Reference> getMatchingReference(Reference newReference){
230 230
        Predicate<Reference> matchFilter = reference ->{
231 231
            try {
232
                return referenceMatcher.invoke(reference, newReference);
232
                return referenceMatcher.invoke(reference, newReference).isSuccessful();
233 233
            } catch (MatchException e) {
234 234
                throw new RuntimeException(e);
235 235
            }
......
266 266
        Person newPersonDeproxy = CdmBase.deproxy(newPerson);
267 267
        Predicate<Person> matchFilter = (person) ->{
268 268
            try {
269
                return personMatcher.invoke(person, newPersonDeproxy);
269
                return personMatcher.invoke(person, newPersonDeproxy).isSuccessful();
270 270
            } catch (MatchException e) {
271 271
                throw new RuntimeException(e);
272 272
            }
......
292 292
        Team newTeamDeproxy = CdmBase.deproxy(newTeam);
293 293
        Predicate<Team> matchFilter = (team) ->{
294 294
            try {
295
                return teamMatcher.invoke(team, newTeamDeproxy);
295
                return teamMatcher.invoke(team, newTeamDeproxy).isSuccessful();
296 296
            } catch (MatchException e) {
297 297
                throw new RuntimeException(e);
298 298
            }
......
328 328
    private Optional<INonViralName> getMatchingName(INonViralName existing){
329 329
        Predicate<INonViralName> matchFilter = name ->{
330 330
            try {
331
                return nameMatcher.invoke(name, existing);
331
                return nameMatcher.invoke(name, existing).isSuccessful();
332 332
            } catch (MatchException e) {
333 333
                throw new RuntimeException(e);
334 334
            }
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/media/in/MediaExcelImport.java
93 93
        //description
94 94
        String description = record.get(COL_DESCRIPTION);
95 95
        if (isNotBlank(description)){
96
            Language descriptionLanguage = state.getConfig().getDescriptionLanguage();
96
            Language descriptionLanguage = Language.ENGLISH();  //  state.getConfig().getDescriptionLanguage();
97 97
            descriptionLanguage = descriptionLanguage == null? Language.UNKNOWN_LANGUAGE(): descriptionLanguage;
98 98
            media.putDescription(descriptionLanguage, description);
99 99
        }
......
104 104
            title = makeTitle(state, taxon, line);
105 105
        }
106 106
        if (isNotBlank(title)){
107
            Language titleLanguage = state.getConfig().getTitleLanguage();
107
            Language titleLanguage = Language.LATIN(); // state.getConfig().getTitleLanguage();
108 108
            titleLanguage = titleLanguage == null? Language.UNKNOWN_LANGUAGE(): titleLanguage;
109 109
            media.putTitle(titleLanguage, title);
110 110
        }
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/common/CdmBase.java
59 59
import eu.etaxonomy.cdm.jaxb.DateTimeAdapter;
60 60
import eu.etaxonomy.cdm.jaxb.UUIDAdapter;
61 61
import eu.etaxonomy.cdm.model.NewEntityListener;
62
import eu.etaxonomy.cdm.strategy.match.IMatchStrategy;
62
import eu.etaxonomy.cdm.strategy.match.IMatchStrategyEqual;
63 63
import eu.etaxonomy.cdm.strategy.match.IMatchable;
64 64
import eu.etaxonomy.cdm.strategy.match.Match;
65 65
import eu.etaxonomy.cdm.strategy.match.MatchMode;
......
353 353
     * <BR><BR>
354 354
     *
355 355
     * If one wants to compare 2 CdmBase entities content wise you may use e.g. a
356
     * {@link IMatchStrategy match strategy} and make sure
356
     * {@link IMatchStrategyEqual match strategy} and make sure
357 357
     * {@link IMatchable matching} is implemented for the respective CdmBase subclass.
358 358
     * You may adapt your match strategy to your own needs.
359 359
     *
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/reference/IJournal.java
16 16
 * This class corresponds, according to the TDWG ontology, to the publication type
17 17
 * term (from PublicationTypeTerm): "Journal".
18 18
 */
19
//TODO inheriting getAuthorship() and datePublished() from IReference is not correct
19 20
public interface IJournal extends IPublicationBase{
20 21

  
21 22
	/**
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/match/CacheMatcher.java
43 43
	}
44 44

  
45 45
	public Field getProtectedField(Matching matching){
46
		String protectedPropertyName = getProtectedPropertyName();
47
		FieldMatcher fieldMatcher = matching.getFieldMatcher(protectedPropertyName);
46
		FieldMatcher fieldMatcher = getProtectedFieldMatcher(matching);
48 47
		return fieldMatcher.getField();
49 48
	}
49
    public FieldMatcher getProtectedFieldMatcher(Matching matching){
50
        String protectedPropertyName = getProtectedPropertyName();
51
        return matching.getFieldMatcher(protectedPropertyName);
52
    }
50 53

  
51 54
	/**
52 55
	 * @return
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/match/DefaultMatchStrategy.java
44 44
 * @author a.mueller
45 45
 * @since 06.08.2009
46 46
 */
47
public class DefaultMatchStrategy extends StrategyBase implements IMatchStrategy {
47
public class DefaultMatchStrategy extends StrategyBase implements IMatchStrategyEqual, IParsedMatchStrategy {
48 48
	private static final long serialVersionUID = 5045874493910155162L;
49 49
	private static final Logger logger = Logger.getLogger(DefaultMatchStrategy.class);
50 50

  
......
54 54
		return new DefaultMatchStrategy(matchClazz);
55 55
	}
56 56

  
57
	protected MatchMode defaultMatchMode = MatchMode.EQUAL;
58
	protected MatchMode defaultCollectionMatchMode = MatchMode.IGNORE;
59
	protected MatchMode defaultMatchMatchMode = MatchMode.MATCH;
57
    protected MatchMode defaultMatchMode = IMatchStrategyEqual.DEFAULT_MATCH_MODE;
58
    protected MatchMode defaultCollectionMatchMode = IMatchStrategyEqual.DEFAULT_COLLECTION_MATCH_MODE;
59
    protected MatchMode defaultMatchMatchMode = IMatchStrategyEqual.DEFAULT_MATCH_MATCH_MODE;
60

  
61

  
62
	//for some reason this does not work, always has null
63
//    private MatchMode defaultMatchMode = IMatchStrategy.defaultMatchMode;
64
//    private MatchMode defaultCollectionMatchMode = IMatchStrategy.defaultCollectionMatchMode;
65
//    private MatchMode defaultMatchMatchMode = IMatchStrategy.defaultMatchMatchMode;
60 66

  
61 67
	protected Class<? extends IMatchable> matchClass;
62 68
	protected Map<String, Field> matchFields;
......
74 80
	/**
75 81
	 * @return the merge class
76 82
	 */
77
	@Override
78 83
    public Class<? extends IMatchable> getMatchClass() {
79 84
		return matchClass;
80 85
	}
......
106 111
        }
107 112
    }
108 113

  
109
	@Override
110
    public MatchMode getMatchMode(String propertyName) {
111
		FieldMatcher fieldMatcher = matching.getFieldMatcher(propertyName);
112
		return fieldMatcher == null ? defaultMatchMode : fieldMatcher.getMatchMode();
113
	}
114
//    public MatchMode getMatchMode(String propertyName) {
115
//		FieldMatcher fieldMatcher = matching.getFieldMatcher(propertyName);
116
//		return fieldMatcher == null ? getDefaultMatchMode() : fieldMatcher.getMatchMode();
117
//	}
118

  
119
    @Override
120
    public <T extends IMatchable> MatchResult invoke(T matchFirst, T matchSecond)
121
            throws MatchException {
122
        return invoke(matchFirst, matchSecond, false);
123
    }
124

  
125
    @Override
126
    public <T extends IMatchable> MatchResult invoke(T matchFirst, T matchSecond,
127
            boolean failAll) throws MatchException {
128
        MatchResult matchResult = new MatchResult();
129
        invoke(matchFirst, matchSecond, matchResult, failAll);
130
        return matchResult;
131
    }
114 132

  
115 133
	@Override
116
    public <T extends IMatchable> boolean invoke(T matchFirst, T matchSecond)
117
			throws MatchException {
118
		boolean result = true;
134
    public <T extends IMatchable> void invoke(T matchFirst, T matchSecond,
135
            MatchResult matchResult, boolean failAll) throws MatchException {
119 136
		if (matchFirst == null || matchSecond == null){
120
			return false;
137
			matchResult.addNullMatching(matchFirst, matchSecond);
138
		    return;
121 139
		}else if (matchFirst == matchSecond){
122
			return true;
140
			return;
123 141
		}else if (matchFirst.getClass() != matchSecond.getClass()){
124 142
			matchFirst = HibernateProxyHelper.deproxy(matchFirst);
125 143
			matchSecond = HibernateProxyHelper.deproxy(matchSecond);
126 144
			if (matchFirst.getClass() != matchSecond.getClass()){
127
				return false;
145
				matchResult.addNoClassMatching(matchFirst.getClass(), matchSecond.getClass());
146
			    return;
128 147
			}
129 148
		}
130 149
		matching.deleteTemporaryMatchers(); //just in case they are not yet deleted during last invoke
......
134 153
			initializeSubclass(matchFirst.getClass());
135 154
		}
136 155
		try {
137
			result = invokeChecked(matchFirst, matchSecond, result);
156
			invokeChecked(matchFirst, matchSecond, matchResult, failAll);
138 157
		}catch (MatchException e) {
139 158
			throw e;
140 159
		}finally{
141 160
			matching.deleteTemporaryMatchers();
142 161
		}
143
		return result;
162
		return;
144 163
	}
145 164

  
146 165
	/**
......
161 180
	 * @return
162 181
	 * @throws MatchException
163 182
	 */
164
	private <T extends IMatchable> boolean invokeChecked(T matchFirst, T matchSecond,
165
			boolean result) throws MatchException {
183
	private <T extends IMatchable> void invokeChecked(T matchFirst, T matchSecond,
184
			MatchResult result, boolean failAll) throws MatchException {
166 185
		//matchFirst != matchSecond != null
167 186
		try {
168 187
			Map<String, List<MatchMode>> replaceMatchers = new HashMap<>();
169 188
			for (CacheMatcher cacheMatcher: matching.getCacheMatchers()){
170
				result = matchSingleCache(matchFirst, matchSecond, result, replaceMatchers, cacheMatcher);
171
				if (result == false){
172
				    return false;
189
				matchSingleCache(matchFirst, matchSecond, result, replaceMatchers, cacheMatcher, failAll);
190
				if (result.isFailed() && !failAll){
191
				    return;
173 192
				}
174 193
			}
175 194
			for (FieldMatcher fieldMatcher : matching.getFieldMatchers(true)){
176
				result = matchSingleField(matchFirst, matchSecond, result, replaceMatchers, fieldMatcher);
177
				if (result == false){
195
				matchSingleField(matchFirst, matchSecond, result,
196
				        replaceMatchers, fieldMatcher, failAll);
197
				if (result.isFailed() && !failAll){
178 198
				    break;
179 199
				}
180 200
			}
181 201
		} catch (Exception e) {
182 202
			throw new MatchException("Match Exception in invoke", e);
183 203
		}
184
		return result;
204
		return;
185 205
	}
186 206

  
187 207
    /**
......
194 214
     * @throws IllegalAccessException
195 215
     * @throws MatchException
196 216
     */
197
    protected <T extends IMatchable> boolean matchSingleCache(T matchFirst, T matchSecond, boolean result,
198
            Map<String, List<MatchMode>> replaceMatchers, CacheMatcher cacheMatcher)
217
    protected <T extends IMatchable> void matchSingleCache(T matchFirst, T matchSecond,
218
            MatchResult result,
219
            Map<String, List<MatchMode>> replaceMatchers, CacheMatcher cacheMatcher, boolean failAll)
199 220
            throws IllegalAccessException, MatchException {
200
        Field protectedField = cacheMatcher.getProtectedField(matching);
221

  
222
        FieldMatcher protectedFieldMatcher = cacheMatcher.getProtectedFieldMatcher(matching);
223
        Field protectedField = protectedFieldMatcher.getField();
201 224
        boolean protected1 = protectedField.getBoolean(matchFirst);
202 225
        boolean protected2 = protectedField.getBoolean(matchFirst);
203 226
        if (protected1 != protected2){
204
        	return false;
227
        	result.addNonMatching(protectedFieldMatcher, protected1, protected2);
228
            return;
205 229
        }else if (protected1 == false){
206 230
        	//ignore
207 231
        }else{
208 232
        	String cache1 = (String)cacheMatcher.getField().get(matchFirst);
209 233
        	String cache2 = (String)cacheMatcher.getField().get(matchSecond);
210
        	result &= cacheMatcher.getMatchMode().matches(cache1, cache2, null);
211
			if (result == false){
212
				return false;
234
        	MatchResult matches = cacheMatcher.getMatchMode().matches(cache1, cache2, null, cacheMatcher.getPropertyName(), failAll);
235
			if (matches.isFailed()){
236
			    result.addSubResult(cacheMatcher.getPropertyName(), matches);
237
			    //addNonMatching(cacheMatcher);
238
				return;
213 239
			}
214 240
        	List<DoubleResult<String, MatchMode>> replacementModes = cacheMatcher.getReplaceMatchModes(matching);
215 241
        	for (DoubleResult<String, MatchMode> replacementMode: replacementModes ){
......
222 248
        		replaceMatcherList.add(replacementMode.getSecondResult());
223 249
        	}
224 250
        }
225
        return result;
251
        return;
226 252
    }
227 253

  
228 254
    /**
......
234 260
     * @return
235 261
     * @throws Exception
236 262
     */
237
    protected <T extends IMatchable> boolean matchSingleField(T matchFirst, T matchSecond, boolean result,
238
            Map<String, List<MatchMode>> replaceMatchers, FieldMatcher fieldMatcher) throws Exception {
263
    protected <T extends IMatchable> void matchSingleField(T matchFirst, T matchSecond,
264
            MatchResult matchResult,
265
            Map<String, List<MatchMode>> replaceMatchers, FieldMatcher fieldMatcher,
266
            boolean failAll) throws Exception {
267
        MatchResult fieldResult;
239 268
        Field field = fieldMatcher.getField();
240 269
        List<MatchMode> replaceModeList = replaceMatchers.get(fieldMatcher.getPropertyName());
241 270
        if (replaceModeList == null){
......
244 273
        Class<?> fieldType = field.getType();
245 274
        logger.debug(field.getName() + ": ");
246 275
        if (isPrimitive(fieldType)){
247
        	result &= matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList);
276
            fieldResult = matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList, failAll);
248 277
        }else if (fieldType == String.class ){
249
        	result &= matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList);
278
            fieldResult = matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList, failAll);
250 279
        }else if (fieldType == Integer.class ){
251
        	result &= matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList);
280
            fieldResult = matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList, failAll);
252 281
        }else if(isUserType(fieldType)){
253
        	result &= matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList);
282
            fieldResult = matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList, failAll);
254 283
        }else if(fieldType == UUID.class){
284
            fieldResult = MatchResult.SUCCESS();
255 285
        	//result &= matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList);
256 286
        }else if(fieldType == URI.class){
257
        	result &= matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList);
287
            fieldResult = matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList, failAll);
258 288
        }else if(fieldType == DOI.class){
259
        	result &= matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList);
289
            fieldResult = matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList, failAll);
260 290
        }else if(isSingleCdmBaseObject(fieldType)){
261
        	result &= matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList);
291
            matchResult.addPath(fieldMatcher.getPropertyName());
292
            fieldResult = matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList, failAll);
293
            matchResult.removePath();
262 294
        }else if (isCollection(fieldType)){
263
        	result &= matchCollectionField(matchFirst, matchSecond, fieldMatcher, replaceModeList);
295
            fieldResult = matchCollectionField(matchFirst, matchSecond, fieldMatcher, replaceModeList, failAll);
264 296
        }else if(fieldType.isInterface()){
265
        	result &= matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList);
297
            fieldResult = matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList, failAll);
266 298
        }else if(fieldType.isEnum()){
267
        	result &= matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList);
299
            fieldResult = matchPrimitiveField(matchFirst, matchSecond, fieldMatcher, replaceModeList, failAll);
268 300
        }else{
269 301
        	throw new RuntimeException("Unknown Object type for matching: " + fieldType);
270 302
        }
271
        if (result == false){
303
        if (fieldResult.isFailed()){
272 304
//					System.out.println(field.getName());
273
        	return result;
274
//				    return result;
305
            matchResult.addSubResult(fieldResult);
306
            return;
275 307
        }
276
        return result;
308
        return;
277 309
    }
278 310

  
279 311

  
......
281 313
	 * @throws Exception
282 314
	 *
283 315
	 */
284
	private <T extends IMatchable> boolean matchPrimitiveField(T matchFirst, T matchSecond, FieldMatcher fieldMatcher, List<MatchMode> replaceModeList) throws Exception {
316
	private <T extends IMatchable> MatchResult matchPrimitiveField(T matchFirst, T matchSecond,
317
	        FieldMatcher fieldMatcher, List<MatchMode> replaceModeList, boolean failAll) throws Exception {
285 318
		Field field = fieldMatcher.getField();
286 319
		Object value1 = checkEmpty(field.get(matchFirst));
287 320
		Object value2 = checkEmpty(field.get(matchSecond));
288 321
		IMatchStrategy matchStrategy = fieldMatcher.getMatchStrategy();
289
		boolean result = fieldMatcher.getMatchMode().matches(value1, value2, matchStrategy);
290
		for (MatchMode replaceMode : replaceModeList){
291
			if (result == true){
292
				break;
293
			}
294
			result |= replaceMode.matches(value1, value2, null);
322
		MatchMode matchMode = fieldMatcher.getMatchMode();
323
		MatchResult fieldResult = matchMode.matches(value1, value2, matchStrategy, fieldMatcher.getPropertyName(), failAll);
324
		fieldResult = makeReplaceModeMatching(fieldResult, replaceModeList, value1, value2, fieldMatcher, failAll);
325
		if (fieldResult.isFailed()){
326
		    if (logger.isDebugEnabled()){logger.debug(fieldMatcher.getMatchMode() + ", " + field.getType().getName()+ ": " + fieldResult.isSuccessful());}
295 327
		}
296
		if (logger.isDebugEnabled()){logger.debug(fieldMatcher.getMatchMode() + ", " + field.getType().getName()+ ": " + result);}
297
		return result;
328
		return fieldResult;
298 329
	}
299 330

  
300 331
	/**
301 332
	 * @throws Exception
302 333
	 *
303 334
	 */
304
	private <T extends IMatchable> boolean matchCollectionField(T matchFirst, T matchSecond, FieldMatcher fieldMatcher, List<MatchMode> replaceModeList) throws Exception {
305
		boolean result;
335
	private <T extends IMatchable> MatchResult matchCollectionField(T matchFirst, T matchSecond,
336
	        FieldMatcher fieldMatcher, List<MatchMode> replaceModeList, boolean failAll) throws Exception {
337

  
338
	    MatchResult fieldResult = new MatchResult();
306 339
		Field field = fieldMatcher.getField();
307 340
		Collection<?> value1 = (Collection)field.get(matchFirst);
308 341
		Collection<?> value2 = (Collection)field.get(matchSecond);
......
313 346
			Class collectionType = getTypeOfSet(field);
314 347
			if (! IMatchable.class.isAssignableFrom(collectionType)){
315 348
				//TODO
316
				return fieldMatcher.getMatchMode().matches(value1, value2, matchStrategy);
349
			    return fieldMatcher.getMatchMode().matches(value1, value2, matchStrategy, fieldMatcher.getPropertyName(), failAll);
317 350
			}
318 351
			if (matchStrategy == null){
319 352
				matchStrategy = DefaultMatchStrategy.NewInstance(collectionType);
320 353
			}
321 354
			if (Set.class.isAssignableFrom(fieldType)){
322
				result = matchSet(value1, value2, matchStrategy);
355
				matchSet(value1, value2, matchStrategy, fieldResult, fieldMatcher, failAll);
323 356
			}else if (List.class.isAssignableFrom(fieldType)){
324
				result = matchList(value1, value2, matchStrategy);
357
				matchList(value1, value2, matchStrategy, fieldResult, fieldMatcher, failAll);
325 358
			}else{
326 359
				throw new MatchException("Collection type not yet supported: " + fieldType);
327 360
			}
328 361
		}else{
329
			result = fieldMatcher.getMatchMode().matches(value1, value2, matchStrategy);
330
		}
331
		//cache replace modes
332
		for (MatchMode replaceMode : replaceModeList){
333
			if (result == true){
334
				break;
335
			}
336
			result |= replaceMode.matches(value1, value2, null);
362
			fieldResult = fieldMatcher.getMatchMode().matches(value1, value2, matchStrategy, fieldMatcher.getPropertyName(), failAll);
337 363
		}
338
		logger.debug(fieldMatcher.getMatchMode() + ", " + field.getType().getName()+ ": " + result);
339
		return result;
364
		fieldResult = makeReplaceModeMatching(fieldResult, replaceModeList, value1, value2, fieldMatcher, failAll);
365

  
366
		if (logger.isDebugEnabled()){logger.debug(fieldMatcher.getMatchMode() + ", " + field.getType().getName()+ ": " + fieldResult.isSuccessful());}
367
		return fieldResult;
340 368
	}
341 369

  
342 370

  
343 371
	/**
372
     * @param fieldResult
373
     * @param replaceModeList
374
	 * @param fieldMatcher
375
	 * @param value2
376
	 * @param value1
377
     * @return
378
	 * @throws MatchException
379
     */
380
    private MatchResult makeReplaceModeMatching(MatchResult fieldResult,
381
            List<MatchMode> replaceModeList, Object value1, Object value2, FieldMatcher fieldMatcher, boolean failAll) throws MatchException {
382
        if (fieldResult.isFailed()){
383
            for (MatchMode replaceMode : replaceModeList){
384
                //TODO is the property name correct here?
385
                MatchResult replaceResult = replaceMode.matches(value1, value2, null, fieldMatcher.getPropertyName(), failAll);
386
                if(replaceResult.isSuccessful()){
387
                    fieldResult = replaceResult;
388
                    break;
389
                }
390
            }
391
        }
392
        return fieldResult;
393
    }
394

  
395
    /**
344 396
	 * @param object
345 397
	 * @return
346 398
	 */
......
376 428
	/**
377 429
	 * @param value1
378 430
	 * @param matchStrategy
431
	 * @param fieldMatcher
379 432
	 * @return
380 433
	 * @throws MatchException
381 434
	 */
382
	private boolean matchSet(Collection value1, Collection value2, IMatchStrategy matchStrategy)
383
			throws MatchException {
384
		boolean result;
385
		Set<IMatchable> set1 = (Set<IMatchable>)value1;
435
	private void matchSet(Collection value1, Collection value2,
436
	        IMatchStrategy matchStrategy, MatchResult matchResult,
437
	        FieldMatcher fieldMatcher, boolean failAll)
438
            throws MatchException {
439

  
440
	    Set<IMatchable> set1 = (Set<IMatchable>)value1;
386 441
		Set<IMatchable> set2 = (Set<IMatchable>)value2;
387 442
		if (set1.size()!= set2.size()){
388
			return false;
443
			matchResult.addNonMatching(fieldMatcher, set1.size(), set2.size());
444
		    return;
389 445
		}
390
		result = true;
391 446
		for (IMatchable setItem1: set1){
392 447
			boolean matches = false;
393 448
			for (IMatchable setItem2: set2){
394
				matches |= matchStrategy.invoke(setItem1, setItem2);
449
			    MatchResult collectionResult = new MatchResult();
450
			    matchStrategy.invoke(setItem1, setItem2, collectionResult, failAll);
451
                matches |= collectionResult.isSuccessful();
395 452
			}
396 453
			if (matches == false){
397
				return false;
454
				matchResult.addNonMatching(fieldMatcher, setItem1, "No match");
455
			    return;
398 456
			}
399 457
		}
400
		return result;
458
		return;
401 459
	}
402 460

  
403 461
	/**
404 462
	 * @param value1
405 463
	 * @param matchStrategy
464
	 * @param fieldMatcher
406 465
	 * @return
407 466
	 * @throws MatchException
408 467
	 */
409
	private boolean matchList(Collection value1, Collection value2, IMatchStrategy matchStrategy)
410
			throws MatchException {
411
		boolean result;
468
	private void matchList(Collection value1, Collection value2,
469
	        IMatchStrategy matchStrategy, MatchResult matchResult,
470
	        FieldMatcher fieldMatcher, boolean failAll)
471
	        throws MatchException {
472

  
412 473
		List<IMatchable> list1 = (List<IMatchable>)value1;
413 474
		List<IMatchable> list2 = (List<IMatchable>)value2;
414 475
		if(list1 == null && list2 == null) {
415
			return true;
476
			return;
416 477
		}
417 478

  
418 479
		if ((list1 != null && list2 == null) || (list1 == null && list2 != null) || (list1.size()!= list2.size())){
419
			return false;
480
		    matchResult.addNonMatching(fieldMatcher, listSize(list1), listSize(list2));
481
		    return;
420 482
		}
421 483

  
422
		result = true;
484
		matchResult.addPath(fieldMatcher.getPropertyName());
423 485
		for (int i = 0; i < list1.size(); i++){
424 486
			IMatchable listObject1 = list1.get(i);
425 487
			IMatchable listObject2 = list2.get(i);
426
			if (! matchStrategy.invoke(listObject1, listObject2)){
427
				return false;
488
			matchStrategy.invoke(listObject1, listObject2, matchResult, failAll);
489
			if (matchResult.isFailed()&& !failAll){
490
			    break;
428 491
			}
429 492
		}
430
		return result;
493
		matchResult.removePath();
494
		return;
431 495
	}
432 496

  
433
	private Class<?> getTypeOfSet(Field field) throws MatchException{
497
	/**
498
     * @param list1
499
     * @return
500
     */
501
    private Object listSize(List<IMatchable> list) {
502
        return list == null? 0 :list.size();
503
    }
504

  
505
    private Class<?> getTypeOfSet(Field field) throws MatchException{
434 506
		Type genericType = field.getGenericType();
435 507
		if (genericType instanceof ParameterizedType/*Impl*/){
436 508
			ParameterizedType paraType = (ParameterizedType)genericType;
......
468 540
	 *
469 541
	 */
470 542
	private void initMapping() {
543
	    preInitMapping();
471 544
		boolean includeStatic = false;
472 545
		boolean includeTransient = false;
473 546
		boolean makeAccessible = true;
474
		matchFields = CdmUtils.getAllFields(matchClass, CdmBase.class, includeStatic, includeTransient, makeAccessible, true);
547
		matchFields = CdmUtils.getAllFields(matchClass, CdmBase.class, includeStatic,
548
		        includeTransient, makeAccessible, true);
475 549
		for (Field field: matchFields.values()){
476 550
			initField(field, false);
477 551
		}
478 552
	}
479 553

  
480 554
	/**
555
     *
556
     */
557
    protected void preInitMapping() {}
558

  
559
    /**
481 560
	 * Initializes the matching for a single field
482 561
	 * @param field
483 562
	 */
484 563
	private void initField(Field field, boolean temporary) {
485 564
		MatchMode matchMode = null;
486
		IMatchStrategy matchStrategy = null;
565
		IMatchStrategyEqual matchStrategy = null;
487 566
		for (Annotation annotation : field.getAnnotations()){
488 567
			if (annotation.annotationType() == Match.class){
489 568
				Match match = ((Match)annotation);
......
499 578
				}
500 579
			}
501 580
		}
502
		Class fieldType = field.getType();
503 581
		if (matchMode == null){
582
		    Class fieldType = field.getType();
504 583
			if (isCollection(fieldType)){
505
				matchMode = defaultCollectionMatchMode;
584
				matchMode = getDefaultCollectionMatchMode();
506 585
				matching.addFieldMatcher(FieldMatcher.NewInstance(field, matchMode), temporary);
507 586
			}else if (fieldType.isInterface()){
508 587
				//TODO could be handled more sophisticated
509
				matchMode = defaultMatchMatchMode;
588
				matchMode = getDefaultMatchMatchMode();
510 589
				matching.addFieldMatcher(FieldMatcher.NewInstance(field, matchMode, matchStrategy), temporary);
511 590
			}else if (isSingleCdmBaseObject(fieldType)){
512 591
				if (IMatchable.class.isAssignableFrom(fieldType)){
513
					matchMode = defaultMatchMatchMode;
592
					matchMode = getDefaultMatchMatchMode();
514 593
					if (matchStrategy == null){
515 594
						if (fieldType == this.matchClass){
516 595
							matchStrategy = this;
......
520 599
					}
521 600
					matching.addFieldMatcher(FieldMatcher.NewInstance(field, matchMode, matchStrategy), temporary);
522 601
				}else{
523
					matchMode = defaultMatchMode;
602
					matchMode = getDefaultMatchMode();
524 603
					matching.addFieldMatcher(FieldMatcher.NewInstance(field, matchMode), temporary);
525 604
				}
526 605
			}else{
527
				matchMode = defaultMatchMode;
606
				matchMode = getDefaultMatchMode();
528 607
				matching.addFieldMatcher(FieldMatcher.NewInstance(field, matchMode), temporary);
529 608
			}
530 609
		}
531 610
	}
532 611

  
612
//
613
//	@Override
614
//	public Set<String> getMatchFieldPropertyNames() {
615
//		return matchFields.keySet();
616
//	}
617
//
618
//	@Override
619
//    public void setDefaultMatchMode(MatchMode defaultMatchMode){
620
//	    this.defaultMatchMatchMode = defaultMatchMode;
621
//	}
622
//
623
//	@Override
624
//    public void setDefaultCollectionMatchMode(MatchMode defaultCollectionMatchMode){
625
//        this.defaultCollectionMatchMode = defaultCollectionMatchMode;
626
//    }
627
//
628
//	@Override
629
//    public void setDefaultMatchMatchMode(MatchMode defaultMatchMatchMode){
630
//        this.defaultMatchMatchMode = defaultMatchMatchMode;
631
//    }
632

  
633
    protected MatchMode getDefaultMatchMode(){
634
        return this.defaultMatchMode;
635
    }
533 636

  
534
	@Override
535
	public Set<String> getMatchFieldPropertyNames() {
536
		return matchFields.keySet();
537
	}
637
    protected MatchMode getDefaultCollectionMatchMode(){
638
        return this.defaultCollectionMatchMode;
639
    }
538 640

  
641
    protected MatchMode getDefaultMatchMatchMode(){
642
        return this.defaultMatchMatchMode;
643
    }
539 644

  
540 645
}
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/match/FieldMatcher.java
46 46
	/**
47 47
	 * @param matchStrategy the matchStrategy to set
48 48
	 */
49
	public void setMatchStrategy(IMatchStrategy matchStrategy) {
49
	public void setMatchStrategy(IMatchStrategyEqual matchStrategy) {
50 50
		this.matchStrategy = matchStrategy;
51 51
	}
52 52

  
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/match/IMatchStrategy.java
1
/**
2
 * Copyright (C) 2007 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

  
10
package eu.etaxonomy.cdm.strategy.match;
11

  
12
import java.util.Set;
13

  
14

  
15
/**
16
 * @author a.mueller
17
 * @since 31.07.2009
18
 */
19
public interface IMatchStrategy {
20

  
21
	public static MatchMode defaultMatchMode = MatchMode.EQUAL;
22
	public static MatchMode defaultCollectionMatchMode = MatchMode.IGNORE;
23
	public static MatchMode defaultMatchMatchMode = MatchMode.MATCH;
24

  
25
	public MatchMode getMatchMode(String propertyName);
26

  
27
	/**
28
	 * Sets the match mode for property propertyName
29
	 * @param propertyName
30
	 * @param mergeMode
31
	 * @throws MatchException
32
	 * @see {@link #setMatchMode(String, MatchMode, IMatchStrategy)}
33
	 */
34
	public void setMatchMode(String propertyName, MatchMode matchMode) throws MatchException;
35

  
36

  
37
    /**
38
     * Sets the match mode for property propertyName using the given match strategy.
39
     * The match strategy has no effect if {@link MatchMode match mode} is none of
40
     * the 4 MATCH* match modes like {@link MatchMode#MATCH} or {@link MatchMode#MATCH_REQUIRED}.
41
     * @param propertyName
42
     * @param matchStrategy
43
     * @throws MatchException
44
     * @see {@link #setMatchMode(String, MatchMode)}
45
     */
46
    void setMatchMode(String propertyName, MatchMode matchMode, IMatchStrategy matchStrategy) throws MatchException;
47

  
48
	/**
49
	 * Invokes the match check.
50
	 * If two objects match this method returns true, false otherwise
51
	 * @param <T>
52
	 * @param mergeFirst
53
	 * @param mergeSecond
54
	 * @throws MatchException
55
	 */
56
	public <T extends IMatchable> boolean invoke(T matchFirst, T matchSecond) throws MatchException;
57

  
58

  
59
	/**
60
	 * Returns the Matching of this match strategy
61
	 * @return
62
	 */
63
	public Matching getMatching();
64

  
65
	/**
66
	 * Returns the class this match strategy matches for
67
	 * @return
68
	 */
69
	public Class getMatchClass();
70

  
71
	/**
72
	 * Returns a map containing all fields this match strategy defines match modes for
73
	 * @return
74
	 */
75
	public Set<String> getMatchFieldPropertyNames();
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
/**
12
 * @author a.mueller
13
 * @since 20.10.2018
14
 *
15
 */
16
public interface IMatchStrategy {
17

  
18
    public static MatchMode DEFAULT_MATCH_MODE = MatchMode.EQUAL;
19
    public static MatchMode DEFAULT_COLLECTION_MATCH_MODE = MatchMode.IGNORE;
20
    public static MatchMode DEFAULT_MATCH_MATCH_MODE = MatchMode.MATCH;
21

  
22
    /**
23
     * Sets the match mode for property propertyName
24
     * @param propertyName
25
     * @param mergeMode
26
     * @throws MatchException
27
     * @see {@link #setMatchMode(String, MatchMode, IMatchStrategy)}
28
     */
29
    public void setMatchMode(String propertyName, MatchMode matchMode) throws MatchException;
30

  
31

  
32
    /**
33
     * Sets the match mode for property propertyName using the given match strategy.
34
     * The match strategy has no effect if {@link MatchMode match mode} is none of
35
     * the 4 MATCH* match modes like {@link MatchMode#MATCH} or {@link MatchMode#MATCH_REQUIRED}.
36
     * @param propertyName
37
     * @param matchStrategy
38
     * @throws MatchException
39
     * @see {@link #setMatchMode(String, MatchMode)}
40
     */
41
    void setMatchMode(String propertyName, MatchMode matchMode, IMatchStrategy matchStrategy) throws MatchException;
42

  
43
    /**
44
     * Invokes the match check.
45
     * If two objects match this method returns true, false otherwise
46
     * @param <T>
47
     * @param mergeFirst
48
     * @param mergeSecond
49
     * @throws MatchException
50
     */
51
    public <T extends IMatchable> MatchResult invoke(T matchFirst, T matchSecond) throws MatchException;
52

  
53
    public  <T extends IMatchable> MatchResult invoke(T matchFirst, T matchSecond, boolean failAll) throws MatchException;
54

  
55

  
56
    /**
57
     * @param matchFirst
58
     * @param matchSecond
59
     * @param matchResult
60
     * @param failAll
61
     * @throws MatchException
62
     */
63
    <T extends IMatchable> void invoke(T matchFirst, T matchSecond, MatchResult matchResult, boolean failAll) throws MatchException;
64

  
65
    /**
66
     * Returns the Matching of this match strategy
67
     * @return
68
     */
69
    public Matching getMatching();
70

  
76 71
}
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/match/IMatchStrategyEqual.java
1
/**
2
 * Copyright (C) 2007 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

  
10
package eu.etaxonomy.cdm.strategy.match;
11

  
12
/**
13
 * @author a.mueller
14
 * @since 31.07.2009
15
 */
16
public interface IMatchStrategyEqual extends IMatchStrategy{
17

  
18

  
19
//	public MatchMode getMatchMode(String propertyName);
20

  
21
	/**
22
	 * Sets the match mode for property propertyName
23
	 * @param propertyName
24
	 * @param mergeMode
25
	 * @throws MatchException
26
	 * @see {@link #setMatchMode(String, MatchMode, IMatchStrategy)}
27
	 */
28
	@Override
29
    public void setMatchMode(String propertyName, MatchMode matchMode) throws MatchException;
30

  
31

  
32
    /**
33
     * Sets the match mode for property propertyName using the given match strategy.
34
     * The match strategy has no effect if {@link MatchMode match mode} is none of
35
     * the 4 MATCH* match modes like {@link MatchMode#MATCH} or {@link MatchMode#MATCH_REQUIRED}.
36
     * @param propertyName
37
     * @param matchStrategy
38
     * @throws MatchException
39
     * @see {@link #setMatchMode(String, MatchMode)}
40
     */
41
    @Override
42
    void setMatchMode(String propertyName, MatchMode matchMode, IMatchStrategy matchStrategy) throws MatchException;
43

  
44
	/**
45
	 * Invokes the match check.
46
	 * If two objects match this method returns true, false otherwise
47
	 * @param <T>
48
	 * @param mergeFirst
49
	 * @param mergeSecond
50
	 * @throws MatchException
51
	 */
52
	@Override
53
    public <T extends IMatchable> MatchResult invoke(T matchFirst, T matchSecond) throws MatchException;
54

  
55

  
56
	/**
57
	 * Returns the Matching of this match strategy
58
	 * @return
59
	 */
60
	@Override
61
    public Matching getMatching();
62
//
63
//	/**
64
//	 * Returns the class this match strategy matches for
65
//	 * @return
66
//	 */
67
//	public Class getMatchClass();
68
//
69
//	/**
70
//	 * Returns a map containing all fields this match strategy defines match modes for
71
//	 * @return
72
//	 */
73
//	@Override
74
//    public Set<String> getMatchFieldPropertyNames();
75
//
76
//    /**
77
//     * Sets the default match mode
78
//     * @param defaultMatchMode
79
//     */
80
//    void setDefaultMatchMode(MatchMode defaultMatchMode);
81
//
82
//    /**
83
//     * Sets the default match mode for collection attributes.
84
//     * @param defaultCollectionMatchMode
85
//     */
86
//    void setDefaultCollectionMatchMode (MatchMode defaultCollectionMatchMode);
87
//
88
//    /**
89
//     * Sets the default match mode for all attributes that again need matching.
90
//     * @param defaultMatchMatchMode
91
//     */
92
//    void setDefaultMatchMatchMode(MatchMode defaultMatchMatchMode);
93
//
94
//    /**
95
//     * @return the default match mode
96
//     */
97
//    public MatchMode getDefaultMatchMode();
98
//
99
//    /**
100
//     * @return the default match mode for collections
101
//     */
102
//    public MatchMode getDefaultCollectionMatchMode();
103
//
104
//    /**
105
//     * @return the default match mode for other matchable objects
106
//     */
107
//    public MatchMode getDefaultMatchMatchMode();
108
}
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/match/IParsedMatchStrategy.java
1
/**
2
 * Copyright (C) 2007 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

  
10
package eu.etaxonomy.cdm.strategy.match;
11

  
12

  
13

  
14
/**
15
 * @author a.mueller
16
 * @since 31.07.2009
17
 */
18
public interface IParsedMatchStrategy extends IMatchStrategy{
19

  
20
    public static MatchMode DEFAULT_PARSED_MATCH_MODE = MatchMode.EQUAL_OR_SECOND_NULL;
21
    public static MatchMode DEFAULT_PARSED_COLLECTION_MATCH_MODE = MatchMode.IGNORE;
22
    public static MatchMode DEFAULT_PARSED_MATCH_MATCH_MODE = MatchMode.MATCH_OR_SECOND_NULL;
23

  
24

  
25

  
26
	/**
27
	 * {@inheritDoc} Invokes the match check.
28
	 *
29
	 * @param <T>
30
	 * @param fullInstance The more complete instance
31
	 * @param parsedInstance The parsed instance having only few attributes defined
32
	 * @throws MatchException
33
	 */
34
	@Override
35
    public <T extends IMatchable> MatchResult invoke(T fullInstance, T parsedInstance) throws MatchException;
36

  
37
}
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/match/MatchMode.java
30 30
	MATCH,//matches if parameter match (parameters must implement IMatchable)
31 31
	CACHE
32 32
	;
33
    //a possible further MatchMode could be NULL, saying that all instances of the given type should have a null
34
    //value, otherwise dirty data which should not be matched
35
    //e.g. NewParsedJournalInstance-authorship
36

  
33 37
	private static final Logger logger = Logger.getLogger(MatchMode.class);
34 38

  
35
	public boolean matches(Object obj1, Object obj2, IMatchStrategy matchStrategy) throws MatchException{
39
	public MatchResult matches(Object obj1, Object obj2, IMatchStrategy matchStrategy, String fieldName, boolean failAll) throws MatchException{
36 40
		if (this == EQUAL_REQUIRED){
37
			return matchesEqualRequired(obj1, obj2);
41
			return matchesEqualRequired(obj1, obj2, fieldName);
38 42
		}else if(this == EQUAL){
39
			return matchesEqual(obj1, obj2);
43
			return matchesEqual(obj1, obj2, fieldName);
40 44
		}else if (this == EQUAL_OR_ONE_NULL){
41
			return matchesEqualOrOneNull(obj1, obj2);
45
			return matchesEqualOrOneNull(obj1, obj2, fieldName);
42 46
		}else if (this == EQUAL_OR_SECOND_NULL){
43
			return matchesEqualOrSecondNull(obj1, obj2);
47
			return matchesEqualOrSecondNull(obj1, obj2, fieldName);
44 48
		}else if(this == IGNORE){
45 49
			return matchesIgnore(obj1, obj2);
46 50
		}else if(this == MATCH){
47
			return matchesMatch(obj1, obj2, matchStrategy);
51
			return matchesMatch(obj1, obj2, matchStrategy, fieldName, failAll);
48 52
		}else if(this == MATCH_REQUIRED){
49
			return matchesMatchRequired(obj1, obj2, matchStrategy);
53
			return matchesMatchRequired(obj1, obj2, matchStrategy, fieldName, failAll);
50 54
		}else if(this == MATCH_OR_ONE_NULL){
51
			return matchesMatchOrOneNull(obj1, obj2, matchStrategy);
55
			return matchesMatchOrOneNull(obj1, obj2, matchStrategy, fieldName, failAll);
52 56
		}else if(this == MATCH_OR_SECOND_NULL){
53
			return matchesMatchOrSecondNull(obj1, obj2, matchStrategy);
57
			return matchesMatchOrSecondNull(obj1, obj2, matchStrategy, fieldName, failAll);
54 58
		}else if(this == CACHE){
55
			return matchesEqualRequired(obj1, obj2) && StringUtils.isNotBlank((String)obj1);
59
			return matchCache(obj1, obj2, fieldName);
56 60
		}else {
57 61
			throw new MatchException("Match mode not handled yet: " + this);
58 62
		}
......
61 65

  
62 66

  
63 67
	/**
68
     * @param obj1
69
     * @param obj2
70
     * @return
71
     */
72
    private MatchResult matchCache(Object obj1, Object obj2, String fieldName) {
73
        if (StringUtils.isBlank((String)obj1)){
74
            return MatchResult.NewInstance(fieldName, this,obj1, obj2);
75
        }else{
76
            return matchesEqualRequired(obj1, obj2, fieldName);
77
        }
78
    }
79

  
80

  
81

  
82
    /**
64 83
	 * @param obj1
65 84
	 * @param obj2
66 85
	 * @param matchStrategy
67 86
	 * @return
68 87
	 * @throws MatchException
69 88
	 */
70
	private boolean matchesMatchRequired(Object obj1, Object obj2, IMatchStrategy matchStrategy) throws MatchException {
89
	private MatchResult matchesMatchRequired(Object obj1, Object obj2, IMatchStrategy matchStrategy, String fieldName, boolean failAll) throws MatchException {
71 90
		if (obj1 == null || obj2 == null ){
72
			return false;
91
			return MatchResult.NewInstance(fieldName, this, obj1, obj2);
73 92
		}else if (! (obj1 instanceof IMatchable  && obj2 instanceof IMatchable) ){
74 93
			logger.warn("Match objects are not of type IMatchable");
75
			return matchesEqualRequired(obj1, obj2);
94
			return matchesEqualRequired(obj1, obj2, fieldName);
76 95
		}else{
77 96
			if (matchStrategy == null){
78 97
				matchStrategy = DefaultMatchStrategy.NewInstance((Class<? extends IMatchable>) obj1.getClass());
79 98
			}
80
			return matchStrategy.invoke((IMatchable)obj1, (IMatchable)obj2);
99
			return matchStrategy.invoke((IMatchable)obj1, (IMatchable)obj2, failAll);
81 100
		}
82 101
	}
83 102

  
......
88 107
	 * @return
89 108
	 * @throws MatchException
90 109
	 */
91
	private boolean matchesMatchOrOneNull(Object obj1, Object obj2, IMatchStrategy matchStrategy) throws MatchException {
110
	private MatchResult matchesMatchOrOneNull(Object obj1, Object obj2,
111
	        IMatchStrategy matchStrategy, String fieldName, boolean failAll) throws MatchException {
92 112
		if (obj1 == null || obj2 == null ){
93
			return true;
113
			return MatchResult.SUCCESS();
94 114
		}else {
95
			return matchesMatchRequired(obj1, obj2, matchStrategy);
115
			return matchesMatchRequired(obj1, obj2, matchStrategy, fieldName, failAll);
96 116
		}
97 117
	}
98 118

  
......
102 122
	 * @return
103 123
	 * @throws MatchException
104 124
	 */
105
	private boolean matchesMatchOrSecondNull(Object obj1, Object obj2, IMatchStrategy matchStrategy) throws MatchException {
106
		if (obj1 == null ){
107
			return true;
125
	private MatchResult matchesMatchOrSecondNull(Object obj1, Object obj2,
126
	        IMatchStrategy matchStrategy, String fieldName, boolean failAll) throws MatchException {
127
		if (obj2 == null ){
128
		    return MatchResult.SUCCESS();
108 129
		}else {
109
			return matchesMatchRequired(obj1, obj2, matchStrategy);
130
			return matchesMatchRequired(obj1, obj2, matchStrategy, fieldName, failAll);
110 131
		}
111 132
	}
112 133

  
......
118 139
	 * @return
119 140
	 * @throws MatchException
120 141
	 */
121
	private boolean matchesMatch(Object obj1, Object obj2, IMatchStrategy matchStrategy) throws MatchException {
142
	private MatchResult matchesMatch(Object obj1, Object obj2,
143
	        IMatchStrategy matchStrategy, String fieldName, boolean failAll) throws MatchException {
122 144
		if (obj1 == null && obj2 == null ){
123
			return true;
145
			return MatchResult.SUCCESS();
124 146
		}else {
125
			return matchesMatchRequired(obj1, obj2, matchStrategy);
147
			return matchesMatchRequired(obj1, obj2, matchStrategy, fieldName, failAll);
126 148
		}
127 149
	}
128 150

  
......
131 153
	 * @param obj2
132 154
	 * @return
133 155
	 */
134
	private boolean matchesIgnore(Object obj1, Object obj2) {
135
		return true;
156
	private MatchResult matchesIgnore(Object obj1, Object obj2) {
157
		return MatchResult.SUCCESS();
136 158
	}
137 159

  
138 160

  
......
141 163
	 * @param obj2
142 164
	 * @return
143 165
	 */
144
	private boolean matchesEqualRequired(Object obj1, Object obj2) {
145
		if (obj1 == null || obj2 == null || ! obj1.equals(obj2)){
146
			return false;
166
	private MatchResult matchesEqualRequired(Object obj1, Object obj2, String fieldName) {
167
		if (obj1 == null || obj2 == null){
168
		    return MatchResult.NewInstance(fieldName, this, obj1, obj2);
169
		}else if (! obj1.equals(obj2)) {
170
		    return MatchResult.NewInstance(fieldName, this, obj1, obj2);
147 171
		}else{
148
			return true;
172
			return MatchResult.SUCCESS();
149 173
		}
150 174
	}
151 175

  
......
155 179
	 * @param obj2
156 180
	 * @return
157 181
	 */
158
	private boolean matchesEqualOrOneNull(Object obj1, Object obj2) {
182
	private MatchResult matchesEqualOrOneNull(Object obj1, Object obj2, String fieldName) {
159 183
		if (obj1 == null || obj2 == null){
160
			return true;
184
			return MatchResult.SUCCESS();
161 185
		}else{
162
			return matchesEqualRequired(obj1, obj2);
186
			return matchesEqualRequired(obj1, obj2, fieldName);
163 187
		}
164 188
	}
165 189

  
......
169 193
	 * @param obj2
170 194
	 * @return
171 195
	 */
172
	private boolean matchesEqualOrSecondNull(Object obj1, Object obj2) {
196
	private MatchResult matchesEqualOrSecondNull(Object obj1, Object obj2, String fieldName) {
173 197
		if (obj2 == null){
174
			return true;
198
			return MatchResult.SUCCESS();
175 199
		}else{
176
			return matchesEqual(obj1, obj2);
200
			return matchesEqual(obj1, obj2, fieldName);
177 201
		}
178 202
	}
179 203

  
......
183 207
	 * @param obj2
184 208
	 * @return
185 209
	 */
186
	private boolean matchesEqual(Object obj1, Object obj2) {
210
	private MatchResult matchesEqual(Object obj1, Object obj2, String fieldName) {
187 211
		if (obj1 == null && obj2 == null){
188
			return true;
212
			return MatchResult.SUCCESS();
189 213
		}else {
190
			return matchesEqualRequired(obj1, obj2);
214
			return matchesEqualRequired(obj1, obj2, fieldName);
191 215
		}
192 216
	}
193 217

  
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/match/MatchResult.java
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 java.util.ArrayList;
12
import java.util.List;
13

  
14
/**
15
 * @author a.mueller
16
 * @since 21.10.2018
17
 *
18
 */
19
public class MatchResult {
20

  
21
    private static final String NULL = "null";
22
    private static final String CLAZZ = "clazz";
23
    private static final String TYPE = "type";
24

  
25
    public static MatchResult SUCCESS(){
26
        return new MatchResult();
27
    }
28
//    public static MatchResult NULL(String fieldName) {
29
//        MatchResult result = new MatchResult();
30
//        result.addNonMatching(fieldName, null);
31
//        return result;
32
//    }
33
//    public static MatchResult EQUAL(String fieldName) {
34
//        MatchResult result = new MatchResult();
35
//        result.addNonMatching(fieldName, MatchMode.EQUAL);;
36
//        return result;
37
//    }
38
    public static MatchResult NewInstance(String fieldName, MatchMode matchMode, Object value1, Object value2) {
39
        MatchResult result = new MatchResult();
40
        result.addNonMatching(fieldName, matchMode, value1, value2);
41
        return result;
42
    }
43
    public static MatchResult NewNoTypeInstance(Enum<?> type1, Enum<?> type2) {
44
        MatchResult result = new MatchResult();
45
        result.addNoTypeMatching(type1, type2);
46
        return result;
47
    }
48

  
49
    private class NonMatching{
50
        private NonMatching(String path, MatchMode matchMode, Object value1, Object value2) {
51
            this.path = path;
52
            this.matchMode = matchMode;
53
            this.value1 = value1;
54
            this.value2 = value2;
55
        }
56
        String path;
57
        MatchMode matchMode;
58
        Object value1;
59
        Object value2;
60
        @Override
61
        public String toString() {
62
            return "NonMatching [path=" + path + ", matchMode=" + matchMode + "]";
63
        }
64

  
65
    }
66

  
67
    private String currentPath = "";
68
    private List<NonMatching> nonMatchings = new ArrayList<>();
69
//    private List<String> nonMatchingPasses = new ArrayList<>();
70
//    private List<MatchMode> nonMatchingMatchModes = new ArrayList<>();
71

  
72

  
73
    public boolean isSuccessful(){
74
        return nonMatchings.isEmpty();
75
    }
76

  
77
    private void addNonMatching(String fieldName, MatchMode matchMode, Object value1, Object value2){
78
        nonMatchings.add(new NonMatching(fieldName, matchMode, value1, value2));
79
//        nonMatchingPasses.add(currentPath + "." + fieldName);
80
//        nonMatchingMatchModes.add(matchMode);
81
    }
82

  
83
    /**
84
     * @param fieldMatcher
85
     */
86
    public void addNonMatching(FieldMatcher fieldMatcher, Object value1, Object value2) {
87
        addNonMatching(fieldMatcher.getPropertyName(), fieldMatcher.getMatchMode(), value1, value2);
88
    }
89

  
90
    public void addNullMatching(Object value1, Object value2) {
91
        addNonMatching(NULL, null, value1, value2);
92
    }
93

  
94
    public void addNoClassMatching(Class<?> clazz1, Class<?> clazz2) {
95
        addNonMatching(CLAZZ, MatchMode.EQUAL_REQUIRED, clazz1, clazz2);
96
    }
97

  
98
    public void addNoTypeMatching(Enum<?> type1, Enum<?> type2) {
99
        addNonMatching(TYPE, MatchMode.EQUAL_REQUIRED, type1, type2);
100
    }
101

  
102
    /**
103
     * @param clazz
104
     */
105
    public void addClass(Class<? extends IMatchable> clazz) {
106
        currentPath += "[" +  clazz.getSimpleName()+"]";
107
    }
108

  
109
    /**
110
     * @return
111
     */
112
    public boolean isFailed() {
113
        return !isSuccessful();
114
    }
115

  
116
    /**
117
     * @param string
118
     */
119
    public void addPath(String path) {
120
        currentPath += "." + path;
121
    }
122

  
123
    /**
124
     *
125
     */
126
    public void removePath() {
127
        if (currentPath.equals("")){
128
            throw new IllegalStateException("Path can not be removed. Is already empty");
129
        }
130
        int index = currentPath.lastIndexOf(".");
131
        if (index == -1){
132
            currentPath = "";
133
        }else{
134
            currentPath = currentPath.substring(0, index);
135
        }
136
    }
137
    /**
138
     * @param fieldResult
139
     */
140
    public void addSubResult(MatchResult subResult) {
141
        for (int i = 0; i < subResult.nonMatchings.size(); i++ ){
142
            NonMatching subNonMatching = subResult.nonMatchings.get(i);
143
            subNonMatching.path = currentPath + (subNonMatching.path.startsWith(".")? "":".")+ subNonMatching.path;
144
            nonMatchings.add(subNonMatching);
145
//            nonMatchingPasses.add((currentPath + "" + subResult.nonMatchingPasses.get(i)));
146
//            nonMatchingMatchModes.add(subResult.nonMatchingMatchModes.get(i));
147
        }
148
    }
149

  
150
    public void addSubResult(String fieldName, MatchResult subResult) {
151
        addPath(fieldName);
152
        addSubResult(subResult);
153
        removePath();
154
    }
155

  
156
    @Override
157
    public String toString() {
158
        String result = isSuccessful()? "SUCCESS" : "FAIL [";
159
        for (int i = 0; i < nonMatchings.size(); i++ ){
160
            if (i > 0){
161
                result += "\n      ";
162
            }
163
            NonMatching nonMatch = nonMatchings.get(i);
164
            result += nonMatch.path;
165
            String matchMode = nonMatch.matchMode == null? "NULL" : nonMatch.matchMode.toString();
166
            result += "(" + matchMode + "): ";
167
            result += nonMatch.value1 == null ? "null": nonMatch.value1.toString();
168
            result += " <-> ";
169
            result += nonMatch.value2 == null ? "null": nonMatch.value2.toString();
170

  
171
        }
172
        if (isFailed()){
173
            result += "]";
174
        }
175
        return result;
176
    }
177

  
178
}
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/match/MatchStrategyConfigurator.java
28 28
        Reference
29 29
    }
30 30

  
31
    public static IMatchStrategy getMatchStrategy(MatchStrategy strategy) throws MatchException {
31
    public static IMatchStrategyEqual getMatchStrategy(MatchStrategy strategy) throws MatchException {
32 32
        switch(strategy) {
33 33
        case NonViralName :
34 34
            return NonViralNameMatchStrategy();
......
44 44
	 * <p>NonViralNameMatchStrategy</p>
45 45
	 *
46 46
	 * @throws eu.etaxonomy.cdm.strategy.match.MatchException if any.
47
	 * @return a {@link eu.etaxonomy.cdm.strategy.match.IMatchStrategy} object.
47
	 * @return a {@link eu.etaxonomy.cdm.strategy.match.IMatchStrategyEqual} object.
48 48
	 */
49
	public static IMatchStrategy NonViralNameMatchStrategy() throws MatchException{
49
	public static IMatchStrategyEqual NonViralNameMatchStrategy() throws MatchException{
50 50
		return getDefaultNonViralNameMatchStrategy();// PreferencesUtil.getMatchStrategy(NonViralName.class);
51 51
	}
52 52

  
......
54 54
	 * <p>TeamOrPersonMatchStrategy</p>
55 55
	 *
56 56
	 * @throws eu.etaxonomy.cdm.strategy.match.MatchException if any.
57
	 * @return a {@link eu.etaxonomy.cdm.strategy.match.IMatchStrategy} object.
57
	 * @return a {@link eu.etaxonomy.cdm.strategy.match.IMatchStrategyEqual} object.
58 58
	 */
59
	public static IMatchStrategy TeamOrPersonMatchStrategy() throws MatchException{
59
	public static IMatchStrategyEqual TeamOrPersonMatchStrategy() throws MatchException{
60 60
		return getDefaultTeamOrPersonMatchStrategy();// PreferencesUtil.getMatchStrategy(TeamOrPersonBase.class);
61 61
	}
62 62

  
......
64 64
	 * <p>ReferenceMatchStrategy</p>
65 65
	 *
66 66
	 * @throws eu.etaxonomy.cdm.strategy.match.MatchException if any.
67
	 * @return a {@link eu.etaxonomy.cdm.strategy.match.IMatchStrategy} object.
67
	 * @return a {@link eu.etaxonomy.cdm.strategy.match.IMatchStrategyEqual} object.
68 68
	 */
69
	public static IMatchStrategy ReferenceMatchStrategy() throws MatchException{
69
	public static IMatchStrategyEqual ReferenceMatchStrategy() throws MatchException{
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff

Add picture from clipboard (Maximum size: 40 MB)