question: @ Override public final synchronized void addRemoveStatements ( Collection < Statement > added , Collection < Statement > removed ) throws IOException { MapOfListMaps < Resource , String , Statement > rsAdded = new MapOfListMaps < Resource , String , Statement > ( ) ; MapOfListMaps < Resource , String , Statement > rsRemoved = new MapOfListMaps < Resource , String , Statement > ( ) ; HashSet < Resource > resources = new HashSet < Resource > ( ) ; for ( Statement s : added ) { rsAdded . add ( s . getSubject ( ) , SearchFields . getContextID ( s . getContext ( ) ) , s ) ; resources . add ( s . getSubject ( ) ) ; } for ( Statement s : removed ) { rsRemoved . add ( s . getSubject ( ) , SearchFields . getContextID ( s . getContext ( ) ) , s ) ; resources . add ( s . getSubject ( ) ) ; } logger . debug ( "Removing " + removed . size ( ) + " statements, adding " + added . size ( ) + " statements" ) ; BulkUpdater updater = newBulkUpdate ( ) ; for ( Resource resource : resources ) { Map < String , List < Statement > > stmtsToRemove = rsRemoved . get ( resource ) ; Map < String , List < Statement > > stmtsToAdd = rsAdded . get ( resource ) ; Set < String > contextsToUpdate = new HashSet < String > ( stmtsToAdd . keySet ( ) ) ; contextsToUpdate . addAll ( stmtsToRemove . keySet ( ) ) ; Map < String , SearchDocument > docsByContext = new HashMap < String , SearchDocument > ( ) ; String resourceId = SearchFields . getResourceID ( resource ) ; Iterable < ? extends SearchDocument > documents = getDocuments ( resourceId ) ; for ( SearchDocument doc : documents ) { docsByContext . put ( doc . getContext ( ) , doc ) ; } for ( String contextId : contextsToUpdate ) { String id = SearchFields . formIdString ( resourceId , contextId ) ; SearchDocument document = docsByContext . get ( contextId ) ; if ( document == null ) { document = newDocument ( id , resourceId , contextId ) ; List < Statement > list = stmtsToAdd . get ( contextId ) ; if ( list != null ) { for ( Statement s : list ) { addProperty ( s , document ) ; } } updater . add ( document ) ; if ( stmtsToRemove . containsKey ( contextId ) ) logger . info ( "Statements are marked to be removed that should not be in the store, for resource {} and context {}. Nothing done." , resource , contextId ) ; } else { Map < String , Set < String > > removedOfResource = null ; { List < Statement > removedStatements = stmtsToRemove . get ( contextId ) ; if ( removedStatements != null && ! removedStatements . isEmpty ( ) ) { removedOfResource = new HashMap < String , Set < String > > ( ) ; for ( Statement r : removedStatements ) { String val = SearchFields . getLiteralPropertyValueAsString ( r ) ; if ( val != null ) { String field = SearchFields . getPropertyField ( r . getPredicate ( ) ) ; Set < String > removedValues = removedOfResource . get ( field ) ; if ( removedValues == null ) { removedValues = new HashSet < String > ( ) ; removedOfResource . put ( field , removedValues ) ; } removedValues . add ( val ) ; } } } } SearchDocument newDocument = newDocument ( id , resourceId , contextId ) ; boolean mutated = copyDocument ( newDocument , document , removedOfResource ) ; { List < Statement > addedToResource = stmtsToAdd . get ( contextId ) ; String val ; if ( addedToResource != null && ! addedToResource . isEmpty ( ) ) { PropertyCache propertyCache = new PropertyCache ( newDocument ) ; for ( Statement s : addedToResource ) { val = SearchFields . getLiteralPropertyValueAsString ( s ) ; if ( val != null ) { String field = SearchFields . getPropertyField ( s . getPredicate ( ) ) ; if ( ! propertyCache . hasProperty ( field , val ) ) { addProperty ( s , newDocument ) ; mutated = true ; } } } } } int nrProperties = countPropertyValues ( newDocument ) ; if ( nrProperties > 0 ) { if ( mutated ) { updater . update ( newDocument ) ; } } else { updater . delete ( document ) ; } } } } updater . end ( ) ; }
target:  Add many statements at the same time, remove many statements at the same time. Ordering by resource has to be done inside this method. The passed added/removed sets are disjunct, no statement can be in both