99 * Licensed under the Apache License, Version 2.0 (the "License");
1010 * you may not use this file except in compliance with the License.
1111 * You may obtain a copy of the License at
12- *
12+ *
1313 * http://www.apache.org/licenses/LICENSE-2.0
14- *
14+ *
1515 * Unless required by applicable law or agreed to in writing, software
1616 * distributed under the License is distributed on an "AS IS" BASIS,
1717 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2121 */
2222
2323
24-
2524import com .yangdb .fuse .asg .strategy .AsgStrategy ;
2625import com .yangdb .fuse .model .Range ;
2726import com .yangdb .fuse .model .Tagged ;
3635import com .yangdb .fuse .model .query .entity .EndPattern ;
3736import com .yangdb .fuse .model .query .properties .BaseProp ;
3837import com .yangdb .fuse .model .query .properties .BasePropGroup ;
38+ import com .yangdb .fuse .model .query .properties .EPropGroup ;
3939import com .yangdb .fuse .model .query .quant .Quant1 ;
4040import com .yangdb .fuse .model .query .quant .QuantBase ;
4141import com .yangdb .fuse .model .query .quant .QuantType ;
@@ -94,7 +94,7 @@ public void apply(AsgQuery query, AsgStrategyContext context) {
9494 quant .get ().addNext (quantAsg );
9595 } else {
9696 // quant of type some exist -> add the inner or patterns after the quant
97- addRelPattern (counter , query , quant .get (), relPattern ,endPattern .get ());
97+ addRelPattern (counter , query , quant .get (), relPattern , endPattern .get ());
9898 //remove pattern
9999 parent .get ().removeNextChild (relPattern );
100100 }
@@ -103,8 +103,47 @@ public void apply(AsgQuery query, AsgStrategyContext context) {
103103
104104 //replace all EndPatterns with its internal real entity
105105 AsgQueryUtil .elements (query , EndPattern .class )
106- .forEach (p -> ((AsgEBase ) p ).seteBase (p .geteBase ().getEndEntity ()));
106+ .forEach (p -> replaceEndPattern (counter , p ));
107+
108+ }
109+
110+ /**
111+ * replace end pattern with the actual type - including its possible filters
112+ *
113+ * @param counter
114+ * @param p
115+ */
116+ public void replaceEndPattern (AtomicInteger counter , AsgEBase <EndPattern > p ) {
117+ if (!p .geteBase ().getFilter ().isEmpty ()) {
118+ //if end pattern is last in query - add quant for the purpose of the end-pattern filters
119+ if (!p .hasNext ()) {
120+ addEndPatternFilters (counter , p );
121+ } else {
122+ //if end pattern is not last in query - search for a quant right after
123+ Optional <AsgEBase <QuantBase >> quantOp = AsgQueryUtil .nextAdjacentDescendant (p , QuantBase .class , 1 );
124+ // if quant not present - add one and chain all childs to that quant
125+ if (!quantOp .isPresent ()) {
126+ AsgEBase <QuantBase > quantAsg = new AsgEBase <>(new Quant1 (counter .incrementAndGet (), QuantType .all ));
127+ AsgQueryUtil .replaceParents (quantAsg ,p );
128+ p .addNext (quantAsg );
129+ }
130+ // quant present - add end-pattern filter to quant
131+ quantOp = AsgQueryUtil .nextAdjacentDescendant (p , QuantBase .class , 1 );
132+ EPropGroup ePropGroup = new EPropGroup (p .geteBase ().getFilter ()).clone (counter .incrementAndGet ());
133+ quantOp .get ().addNext (new AsgEBase <>(ePropGroup ));
134+ }
135+ }
136+ //change endPattern type to actual type
137+ ((AsgEBase ) p ).seteBase (p .geteBase ().getEndEntity ());
138+ }
107139
140+ public QuantBase addEndPatternFilters (AtomicInteger counter , AsgEBase <EndPattern > p ) {
141+ QuantBase newQuant = new Quant1 (counter .incrementAndGet (), QuantType .all );
142+ AsgEBase <QuantBase > quantAsg = new AsgEBase <>(newQuant );
143+ EPropGroup ePropGroup = new EPropGroup (p .geteBase ().getFilter ()).clone (counter .incrementAndGet ());
144+ quantAsg .addNext (new AsgEBase <>(ePropGroup ));
145+ p .addNext (quantAsg );
146+ return newQuant ;
108147 }
109148
110149 /**
@@ -117,11 +156,11 @@ public void apply(AsgQuery query, AsgStrategyContext context) {
117156 private void addRelPattern (AtomicInteger counter , AsgQuery query , AsgEBase <Quant1 > quantAsg , AsgEBase <RelPattern > relPattern , AsgEBase <EndPattern > endPattern ) {
118157 Range range = relPattern .geteBase ().getLength ();
119158 //duplicate the rel pattern according to the range, range should already be validated by the validator
120- LongStream .rangeClosed (range .getLower () , range .getUpper ())
159+ LongStream .rangeClosed (range .getLower (), range .getUpper ())
121160 //this is the Root some quant all pattern premutations will be added to...
122161 .forEach (value -> {
123162 //if value == 0 remove the RelPattern entirely
124- if (value == 0 ) {
163+ if (value == 0 ) {
125164 //take the path after the end pattern section (if exists) & add it as no hop pattern to the Quant
126165 if (endPattern .hasNext ()) {
127166 final AsgEBase <? extends EBase > nextAfterEndPattern = endPattern .getNext ().get (0 );
@@ -145,28 +184,29 @@ private void addRelPattern(AtomicInteger counter, AsgQuery query, AsgEBase<Quant
145184
146185 /**
147186 * rel pattern premutation generator
187+ *
148188 * @param value
149189 * @param relPattern
150190 * @param endPattern
151191 * @return
152192 */
153- private AsgEBase <? extends EBase > addPath (AtomicInteger counter ,long value , AsgEBase <RelPattern > relPattern , AsgEBase <EndPattern > endPattern ) {
193+ private AsgEBase <? extends EBase > addPath (AtomicInteger counter , long value , AsgEBase <RelPattern > relPattern , AsgEBase <EndPattern > endPattern ) {
154194 final AtomicReference <AsgEBase <? extends EBase >> current = new AtomicReference <>();
155195 LongStream .rangeClosed (1 , value )
156196 .forEach (step -> {
157- AsgEBase <? extends EBase > node = buildStep (counter ,relPattern , endPattern );
197+ AsgEBase <? extends EBase > node = buildStep (counter , relPattern , endPattern );
158198 if (current .get () == null ) {
159199 current .set (node );
160200 } else {
161201 //the build step returns a cloned pattern of [rel:Rel]-....->(endPattern:Entity)->...
162202 //
163- if (!(current .get ().geteBase () instanceof QuantBase )) {
203+ if (!(current .get ().geteBase () instanceof QuantBase )) {
164204 final AsgEBase <Quant1 > quant = new AsgEBase <>(new Quant1 (counter .incrementAndGet (), QuantType .all ));
165- AsgQueryUtil .addAsNext (quant ,current .get ());
205+ AsgQueryUtil .addAsNext (quant , current .get ());
166206 current .set (quant );
167207 } else {
168208 //knowing that the rel pattern has a shape of a line not a tree get the last Descendant
169- current .set (AsgQueryUtil .nextDescendant (current .get (),EndPattern .class ).get ());
209+ current .set (AsgQueryUtil .nextDescendant (current .get (), EndPattern .class ).get ());
170210 }
171211 current .get ().addNext (AsgQueryUtil .ancestorRoot (node ).get ());
172212 current .set (node );
@@ -179,11 +219,12 @@ private AsgEBase<? extends EBase> addPath(AtomicInteger counter,long value, AsgE
179219
180220 /**
181221 * build a new complete rel->pattern step cloned from existing step
222+ *
182223 * @param relPattern
183224 * @param endPattern
184225 * @return
185226 */
186- private AsgEBase <? extends EBase > buildStep (AtomicInteger counter ,AsgEBase <RelPattern > relPattern , AsgEBase <EndPattern > endPattern ) {
227+ private AsgEBase <? extends EBase > buildStep (AtomicInteger counter , AsgEBase <RelPattern > relPattern , AsgEBase <EndPattern > endPattern ) {
187228
188229 RelPattern pattern = relPattern .geteBase ();
189230 List <AsgEBase <? extends EBase >> belowList = new ArrayList <>(relPattern .getB ());
0 commit comments