github.com/searKing/golang/go@v1.2.74/container/stream/op/find/task.go (about) 1 // Copyright 2020 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package find 6 7 import ( 8 "context" 9 10 "github.com/searKing/golang/go/container/stream/op/terminal" 11 "github.com/searKing/golang/go/util/spliterator" 12 ) 13 14 type FindTask struct { 15 terminal.TODOShortCircuitTask 16 17 op FindOp 18 // true if find first 19 // false if find any 20 mustFindFirst bool 21 } 22 23 /** 24 * Constructor for root tasks. 25 * 26 * @param helper the {@code PipelineHelper} describing the stream pipeline 27 * up to this operation 28 * @param spliterator the {@code Spliterator} describing the source for this 29 * pipeline 30 */ 31 func (task *FindTask) WithSpliterator(op FindOp, spliterator spliterator.Spliterator) *FindTask { 32 task.TODOShortCircuitTask.WithSpliterator(spliterator) 33 task.op = op 34 task.mustFindFirst = op.mustFindFirst 35 task.SetDerived(task) 36 return task 37 } 38 39 /** 40 * Constructor for non-root nodes. 41 * 42 * @param parent parent task in the computation tree 43 * @param spliterator the {@code Spliterator} for the portion of the 44 * computation tree described by this task 45 */ 46 func (task *FindTask) WithParent(parent *FindTask, spliterator spliterator.Spliterator) *FindTask { 47 task.TODOShortCircuitTask.WithParent(parent, spliterator) 48 task.op = parent.op 49 task.mustFindFirst = parent.mustFindFirst 50 task.SetDerived(task) 51 return task 52 } 53 54 func (task *FindTask) MakeChild(spliterator spliterator.Spliterator) terminal.Task { 55 child := &FindTask{} 56 return child.WithParent(task, spliterator) 57 } 58 59 func (task *FindTask) foundResult(answer terminal.Sink) { 60 if task.IsLeftmostNode() { 61 task.ShortCircuit(answer) 62 return 63 } 64 task.CancelLaterNodes() 65 } 66 67 func (task *FindTask) DoLeaf(ctx context.Context) terminal.Sink { 68 result := terminal.WrapAndCopyInto(ctx, task.op.MakeSink(), task.GetSpliterator()) 69 if !task.mustFindFirst { 70 if result != nil && result.Get().IsPresent() { 71 task.ShortCircuit(result) 72 } 73 return nil 74 } 75 if result != nil && result.Get().IsPresent() { 76 task.foundResult(result) 77 return result 78 } 79 return nil 80 } 81 82 func (task *FindTask) OnCompletion(caller terminal.Task) { 83 if task.mustFindFirst { 84 child := task.LeftChild() 85 var p terminal.Task 86 for child != p { 87 result := child.GetLocalResult() 88 if result != nil && task.op.presentPredicate.Test(result.Get().Get()) { 89 task.SetLocalResult(result) 90 task.foundResult(result) 91 break 92 } 93 94 p = child 95 child = task.RightChild() 96 } 97 } 98 // GC spliterator, left and right child 99 task.TODOShortCircuitTask.OnCompletion(caller) 100 }