Select history using matched entry positions
This commit is contained in:
@@ -26,21 +26,43 @@ type historySensitivityCandidate struct {
|
||||
classify bool
|
||||
}
|
||||
|
||||
type historyQueryCoordinates struct {
|
||||
final Path
|
||||
entry Path
|
||||
hasEntry bool
|
||||
}
|
||||
|
||||
func (model *historyModel) queryCoordinates(path Path) historyQueryCoordinates {
|
||||
coordinate := historyQueryCoordinates{final: path.clone(), entry: path.clone(), hasEntry: true}
|
||||
if model != nil && model.resolutionPayload != nil {
|
||||
coordinate.entry, coordinate.hasEntry = model.resolutionPayload.correspondence.entryPath(path)
|
||||
}
|
||||
return coordinate
|
||||
}
|
||||
|
||||
func (model *historyModel) selectHistory(path Path) []historySelection {
|
||||
if model == nil || !path.valid() || !model.hasObservedShape(path) {
|
||||
if model == nil || !path.valid() {
|
||||
return nil
|
||||
}
|
||||
coordinate := model.queryCoordinates(path)
|
||||
if !model.hasObservedShape(path) && (!coordinate.hasEntry || !model.hasObservedShape(coordinate.entry)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
candidateSet := make(map[int]struct{})
|
||||
for _, observationID := range model.observationsByPointer[path.String()] {
|
||||
candidateSet[observationID] = struct{}{}
|
||||
collect := func(query Path) {
|
||||
for _, observationID := range model.observationsByPointer[query.String()] {
|
||||
candidateSet[observationID] = struct{}{}
|
||||
}
|
||||
model.affectedPathIndex.visitDescendants(query.String(), func(observationID int) { candidateSet[observationID] = struct{}{} })
|
||||
}
|
||||
collect(path)
|
||||
if coordinate.hasEntry {
|
||||
collect(coordinate.entry)
|
||||
}
|
||||
// Producers register all affected before/after paths. Exact facts cover
|
||||
// ancestor replacements; descendants cover operations within an enclosing
|
||||
// query. Logical operations are still deduplicated by payload below.
|
||||
model.affectedPathIndex.visitDescendants(path.String(), func(observationID int) {
|
||||
candidateSet[observationID] = struct{}{}
|
||||
})
|
||||
candidates := make([]int, 0, len(candidateSet))
|
||||
for observationID := range candidateSet {
|
||||
candidates = append(candidates, observationID)
|
||||
@@ -54,18 +76,30 @@ func (model *historyModel) selectHistory(path Path) []historySelection {
|
||||
if observation.role == historyRoleInventory {
|
||||
continue
|
||||
}
|
||||
query := path
|
||||
if observation.phase != historyPhaseResolution {
|
||||
if !coordinate.hasEntry {
|
||||
continue
|
||||
}
|
||||
query = coordinate.entry
|
||||
} else if observation.beforePresent && !observation.afterPresent {
|
||||
if !coordinate.hasEntry {
|
||||
continue
|
||||
}
|
||||
query = coordinate.entry
|
||||
}
|
||||
reportedPath := observation.reportedPath
|
||||
attributionRef := observation.attributionRef
|
||||
if observation.role == historyRoleContribution {
|
||||
if !historyObservationMatchesQuery(path, observation.path) {
|
||||
if !historyObservationMatchesQuery(query, observation.path) {
|
||||
continue
|
||||
}
|
||||
application, found := model.applicationPayload(observation.payload)
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
if pathContains(observation.path, path) && len(observation.path.segments) < len(path.segments) {
|
||||
local, ok := historyApplicationLocalPath(application, path)
|
||||
if pathContains(observation.path, query) && len(observation.path.segments) < len(query.segments) {
|
||||
local, ok := historyApplicationLocalPath(application, query)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
@@ -73,12 +107,18 @@ func (model *historyModel) selectHistory(path Path) []historySelection {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if operationPath, relevant := applicationOperationPath(application, path, model.documentLookup); relevant {
|
||||
if operationPath, relevant := applicationOperationPath(application, query, model.documentLookup); relevant {
|
||||
reportedPath = operationPath
|
||||
}
|
||||
} else if !historyObservationMatchesQuery(path, observation.path) {
|
||||
} else if !historyObservationMatchesQuery(query, observation.path) {
|
||||
continue
|
||||
}
|
||||
if query.String() != path.String() && pathContains(query, reportedPath) {
|
||||
suffix := reportedPath.segments[len(query.segments):]
|
||||
reportedPath = Path{segments: append(clonePathSegments(path.segments, len(suffix)), suffix...)}
|
||||
} else if query.String() != path.String() && pathContains(reportedPath, query) && len(reportedPath.segments) >= len(query.segments)-1 {
|
||||
reportedPath = path.clone()
|
||||
}
|
||||
selectionIndex, found := selectionByPayload[observation.payload]
|
||||
if !found {
|
||||
selectionIndex = len(selections)
|
||||
|
||||
Reference in New Issue
Block a user