public List < Map < String , List < EventId > > > extractPatterns ( final NodeId nodeId , final DeweyNumber version ) { List < Map < String , List < EventId > > > result = new ArrayList <> ( ) ; // stack to remember the current extraction states Stack < SharedBufferAccessor . ExtractionState > extractionStates = new Stack <> ( ) ; // get the starting shared buffer entry for the previous relation Lockable < SharedBufferNode > entryLock = sharedBuffer . getEntry ( nodeId ) ; if ( entryLock != null ) { SharedBufferNode entry = entryLock . getElement ( ) ; extractionStates . add ( new SharedBufferAccessor . ExtractionState ( Tuple2 . of ( nodeId , entry ) , version , new Stack <> ( ) ) ) ; // use a depth first search to reconstruct the previous relations while ( ! extractionStates . isEmpty ( ) ) { final SharedBufferAccessor . ExtractionState extractionState = extractionStates . pop ( ) ; // current path of the depth first search final Stack < Tuple2 < NodeId , SharedBufferNode > > currentPath = extractionState . getPath ( ) ; final Tuple2 < NodeId , SharedBufferNode > currentEntry = extractionState . getEntry ( ) ; // termination criterion if ( currentEntry == null ) { final Map < String , List < EventId > > completePath = new LinkedHashMap <> ( ) ; while ( ! currentPath . isEmpty ( ) ) { final NodeId currentPathEntry = currentPath . pop ( ) . f0 ; String page = currentPathEntry . getPageName ( ) ; List < EventId > values = completePath . computeIfAbsent ( page , k -> new ArrayList <> ( ) ) ; values . add ( currentPathEntry . getEventId ( ) ) ; } result . add ( completePath ) ; } else { // append state to the path currentPath . push ( currentEntry ) ; boolean firstMatch = true ; for ( SharedBufferEdge edge : currentEntry . f1 . getEdges ( ) ) { // we can only proceed if the current version is compatible to the version // of this previous relation final DeweyNumber currentVersion = extractionState . getVersion ( ) ; if ( currentVersion . isCompatibleWith ( edge . getDeweyNumber ( ) ) ) { final NodeId target = edge . getTarget ( ) ; Stack < Tuple2 < NodeId , SharedBufferNode > > newPath ; if ( firstMatch ) { // for the first match we don't have to copy the current path newPath = currentPath ; firstMatch = false ; } else { newPath = new Stack <> ( ) ; newPath . addAll ( currentPath ) ; } extractionStates . push ( new SharedBufferAccessor . ExtractionState ( target != null ? Tuple2 . of ( target , sharedBuffer . getEntry ( target ) . getElement ( ) ) : null , edge . getDeweyNumber ( ) , newPath ) ) ; } } } } } return result ; }
Returns all elements from the previous relation starting at the given entry .