You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mu...@apache.org on 2023/07/09 16:39:50 UTC

[xalan-java] branch xalan-j_xslt3.0 updated: committing improvements to implementation of, xpath 3.1 dynamic function calls. also committing a related working test case as well.

This is an automated email from the ASF dual-hosted git repository.

mukulg pushed a commit to branch xalan-j_xslt3.0
in repository https://gitbox.apache.org/repos/asf/xalan-java.git


The following commit(s) were added to refs/heads/xalan-j_xslt3.0 by this push:
     new 9d87cd23 committing improvements to implementation of, xpath 3.1 dynamic function calls. also committing a related working test case as well.
     new 6cf8008f Merge pull request #23 from mukulga/xalan-j_xslt3.0_mukul
9d87cd23 is described below

commit 9d87cd2343a3ad7ebeb9414261c7619e03257d1a
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Sun Jul 9 22:00:15 2023 +0530

    committing improvements to implementation of, xpath 3.1 dynamic function calls. also committing a related working test case as well.
---
 src/org/apache/xpath/compiler/XPathParser.java     | 76 +++++++++++++++++++---
 .../xpath/functions/DynamicFunctionCall.java       | 21 +++---
 tests/dynamic_function_call/gold/test8.out         |  5 ++
 tests/dynamic_function_call/test1_d.xml            | 16 +++++
 tests/dynamic_function_call/test8.xsl              | 45 +++++++++++++
 .../xalan/xpath3/DynamicFunctionCallTests.java     | 10 +++
 6 files changed, 155 insertions(+), 18 deletions(-)

diff --git a/src/org/apache/xpath/compiler/XPathParser.java b/src/org/apache/xpath/compiler/XPathParser.java
index c5493cf6..3fdbfd37 100644
--- a/src/org/apache/xpath/compiler/XPathParser.java
+++ b/src/org/apache/xpath/compiler/XPathParser.java
@@ -90,14 +90,16 @@ public class XPathParser
   
   private List<String> fXpathOpArrTokensList = null;
   
+  private boolean fDynamicFunctionCallArgumentMarker = false;
+  
+  private boolean fIsXpathPredicateParsingActive = false;
+  
   static InlineFunction fInlineFunction = null;
   
   static DynamicFunctionCall fDynamicFunctionCall = null;
   
   static IfExpr fIfExpr = null;
   
-  private boolean fIsXpathPredicateParsingActive = false;
-
   /**
    * The parser constructor.
    */
@@ -622,6 +624,52 @@ public class XPathParser
       
       return (funcBodyXPathExprStrBuff.toString()).trim();
   }
+  
+  private boolean isXpathDynamicFuncCallParseAhead(List<String> argDetailsStrPartsList, 
+                                                                                  String delim) {
+      boolean isXpathDynamicFuncCallParseAhead = false;
+
+      if (lookahead('(', 1)) {
+         // handles the case, where the function call argument
+         // is itself another function call.
+         fDynamicFunctionCallArgumentMarker = true;
+         argDetailsStrPartsList.add(m_token);
+         nextToken();
+         isXpathDynamicFuncCallParseAhead = true;
+      }
+      else if (tokenIs(')') && lookahead(',', 1)) {
+         argDetailsStrPartsList.add(m_token);          
+         nextToken();
+         argDetailsStrPartsList.add(delim);
+         nextToken();
+         fDynamicFunctionCallArgumentMarker = false;
+         isXpathDynamicFuncCallParseAhead = true;
+      }
+      else if (lookahead(',', 1)) {
+         argDetailsStrPartsList.add(m_token);
+         nextToken();
+         if (!fDynamicFunctionCallArgumentMarker) {
+            argDetailsStrPartsList.add(delim);
+            nextToken();
+         }
+         else {
+            argDetailsStrPartsList.add(m_token);
+            nextToken();
+         }
+         isXpathDynamicFuncCallParseAhead = true; 
+      }
+      else if (!tokenIs(')')) {
+         argDetailsStrPartsList.add(m_token);
+         nextToken();
+         isXpathDynamicFuncCallParseAhead = true; 
+      }
+      else if (fDynamicFunctionCallArgumentMarker) {
+         argDetailsStrPartsList.add(m_token);
+         nextToken();
+      }
+
+      return isXpathDynamicFuncCallParseAhead; 
+  }
 
   /**
    * Notify the user of an assertion error, and probably throw an
@@ -1670,23 +1718,31 @@ public class XPathParser
        
        List<String> argDetailsStrPartsList = new ArrayList<String>();
        
-       while (!tokenIs(')') && m_token != null)
+       // we create here a temporary function call argument delimiter 
+       // string, for this processing.
+       long currentTimeMills = System.currentTimeMillis();
+       String delimSuffix = (Long.valueOf(currentTimeMills)).toString();
+       String delim = "t0_" + delimSuffix;
+       
+       while (m_token != null && isXpathDynamicFuncCallParseAhead(
+                                                      argDetailsStrPartsList, delim))
        {
-          argDetailsStrPartsList.add(m_token);
-          nextToken();
+          // no op here
        }
        
+       fDynamicFunctionCallArgumentMarker = false;
+       
        int startIdx = 0;
-       int idxComma;       
-       while (argDetailsStrPartsList.contains(",") && 
-                         (idxComma = argDetailsStrPartsList.indexOf(",")) != -1) {
-          List<String> lst1 = argDetailsStrPartsList.subList(startIdx, idxComma);
+       int idxDelim;       
+       while (argDetailsStrPartsList.contains(delim) && 
+                         (idxDelim = argDetailsStrPartsList.indexOf(delim)) != -1) {
+          List<String> lst1 = argDetailsStrPartsList.subList(startIdx, idxDelim);
           
           String xpathStr = getXPathStrFromComponentParts(lst1);
           
           argList.add(xpathStr);
           
-          List<String> lst2 = argDetailsStrPartsList.subList(idxComma + 1, 
+          List<String> lst2 = argDetailsStrPartsList.subList(idxDelim + 1, 
                                                                            argDetailsStrPartsList.size());
           
           argDetailsStrPartsList = lst2; 
diff --git a/src/org/apache/xpath/functions/DynamicFunctionCall.java b/src/org/apache/xpath/functions/DynamicFunctionCall.java
index 5c97cf64..6ebc6451 100644
--- a/src/org/apache/xpath/functions/DynamicFunctionCall.java
+++ b/src/org/apache/xpath/functions/DynamicFunctionCall.java
@@ -51,6 +51,12 @@ public class DynamicFunctionCall extends Expression {
     private String funcRefVarName;
     
     private List<String> argList;
+    
+    // the following two fields of this class, are used during 
+    // XPath.fixupVariables(..) action as performed within object of 
+    // this class.    
+    private Vector fVars;    
+    private int fGlobalsSize;
 
     public String getFuncRefVarName() {
         return funcRefVarName;
@@ -104,14 +110,12 @@ public class DynamicFunctionCall extends Expression {
               String funcParamName = funcParamNameList.get(idx);
               
               String argXPathStr = argList.get(idx);
-              XObject argValue = null;
-              if (argXPathStr.startsWith("$")) {
-                 argValue = exprContext.getVariableOrParam(new QName(argXPathStr.substring(1)));
-              }
-              else {
-                 XPath argXpath = new XPath(argXPathStr, srcLocator, null, XPath.SELECT, null);
-                 argValue = argXpath.execute(xctxt, contextNode, null);
+              
+              XPath argXpath = new XPath(argXPathStr, srcLocator, null, XPath.SELECT, null);
+              if (fVars != null) {
+                 argXpath.fixupVariables(fVars, fGlobalsSize);
               }
+              XObject argValue = argXpath.execute(xctxt, contextNode, null);
               
               inlineFunctionVarMap.put(new QName(funcParamName), argValue);
            }
@@ -127,7 +131,8 @@ public class DynamicFunctionCall extends Expression {
 
     @Override
     public void fixupVariables(Vector vars, int globalsSize) {
-       // no op
+        fVars = (Vector)(vars.clone());
+        fGlobalsSize = globalsSize; 
     }
 
     @Override
diff --git a/tests/dynamic_function_call/gold/test8.out b/tests/dynamic_function_call/gold/test8.out
new file mode 100644
index 00000000..6719da81
--- /dev/null
+++ b/tests/dynamic_function_call/gold/test8.out
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?><list>
+  <person>Id : 1, Name : Gary Gregory</person>
+  <person>Id : 2, Name : Joseph Kesselman</person>
+  <person>Id : 3, Name : Leonhard Euler</person>
+</list>
diff --git a/tests/dynamic_function_call/test1_d.xml b/tests/dynamic_function_call/test1_d.xml
new file mode 100644
index 00000000..79c2432c
--- /dev/null
+++ b/tests/dynamic_function_call/test1_d.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<list>
+   <person>
+     <fName>Gary</fName>
+     <lName>Gregory</lName>
+   </person>
+   <person>
+     <fName>Joseph</fName>
+     <lName>Kesselman</lName>  
+   </person>
+   <person>
+     <fName>Leonhard</fName>
+     <lName>Euler</lName>
+   </person>
+</list>
+ 
\ No newline at end of file
diff --git a/tests/dynamic_function_call/test8.xsl b/tests/dynamic_function_call/test8.xsl
new file mode 100644
index 00000000..db819564
--- /dev/null
+++ b/tests/dynamic_function_call/test8.xsl
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- use with test1_d.xml -->
+   
+   <!-- Test case description : Specifying complex valued arguments to 
+        XPath dynamic function call (for e.g, within this XSLT stylesheet, 
+        dynamic function call arguments are themselves function calls. -->                 
+
+   <xsl:output method="xml" indent="yes"/>
+   
+   <xsl:variable name="trfNameStr" select="function($pos, $str) { concat('Id : ', $pos, ', Name : ', $str) }"/>
+
+   <xsl:template match="/list">
+      <list>
+         <xsl:for-each select="person">
+           <person>
+              <xsl:copy-of select="$trfNameStr(position(), concat(fName, ' ', lName))"/>
+           </person>
+         </xsl:for-each>
+      </list>
+   </xsl:template>
+   
+   <!--
+      * Licensed to the Apache Software Foundation (ASF) under one
+      * or more contributor license agreements. See the NOTICE file
+      * distributed with this work for additional information
+      * regarding copyright ownership. The ASF licenses this file
+      * to you under the Apache License, Version 2.0 (the  "License");
+      * you may not use this file except in compliance with the License.
+      * You may obtain a copy of the License at
+      *
+      *     http://www.apache.org/licenses/LICENSE-2.0
+      *
+      * Unless required by applicable law or agreed to in writing, software
+      * distributed under the License is distributed on an "AS IS" BASIS,
+      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      * See the License for the specific language governing permissions and
+      * limitations under the License.
+   -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/org/apache/xalan/xpath3/DynamicFunctionCallTests.java b/tests/org/apache/xalan/xpath3/DynamicFunctionCallTests.java
index e7d2bb3c..3a12aa06 100644
--- a/tests/org/apache/xalan/xpath3/DynamicFunctionCallTests.java
+++ b/tests/org/apache/xalan/xpath3/DynamicFunctionCallTests.java
@@ -116,5 +116,15 @@ public class DynamicFunctionCallTests extends XslTransformTestsUtil {
         
         runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
     }
+    
+    @Test
+    public void xslDynamicFunctionCallTest8() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_d.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test8.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test8.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
 
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org