final AQualifiedSourceAndTargetType elementTypes = new AQualifiedSourceAndTargetType(h.elementType(types.sourceType), types.sourceQualifier, h.elementType(types.targetType), types.targetQualifier);
if(targetColl.isEmpty()) {
// this is an optimization for the common case that the target collection is initially empty
for(Object s: sourceColl) {
final APath elPath = ACollectionMappingTools.elementPath(path, worker.getIdentifierExtractor().uniqueIdentifier(s, types));
final AOption<Object> optT = worker.map(elPath, s, null, elementTypes, context);
if(optT.isDefined()) {
targetColl.add(optT.get());
}
}
return h.fromJuCollection(targetColl, types.target());
}
final Equiv equiv = new Equiv(sourceColl, targetColl, types, worker.getIdentifierExtractor());
// now apply the changes to the target collection
targetColl.removeAll(equiv.targetWithoutSource);
for (Object s: equiv.sourceWithoutTarget) {
final APath elPath = ACollectionMappingTools.elementPath(path, worker.getIdentifierExtractor().uniqueIdentifier(s, types));
final AOption<Object> tc = worker.map(elPath, s, null, elementTypes, context);
if(tc.isDefined()) {
targetColl.add(tc.get());
}
}
for (Map.Entry<Object, Object> e: equiv.equiv.entrySet()) {
final APath elPath = ACollectionMappingTools.elementPath(path, worker.getIdentifierExtractor().uniqueIdentifier(e.getKey(), types));
final AOption<Object> tc = worker.map(elPath, e.getKey(), e.getValue(), elementTypes, context);
if(tc.isEmpty()) {
targetColl.remove(e.getValue());
}