Hi,

I've been waiting for several days for a response. 
Is there something wrong with my suggestions? Are they unacceptable? Should
I provide more info? Or did I submit them wrong? I can resubmit them in this
case. 

I'd appreciate to hear any response.

Thanks,
Dimitry

-----Original Message-----
From: Voytenko, Dimitry [mailto:[EMAIL PROTECTED]]
Sent: Monday, January 27, 2003 16:27
To: '[EMAIL PROTECTED]'
Cc: 'Gary L Peskin'; '[EMAIL PROTECTED]'
Subject: RE: xslt/xpath function extension mechanism


Hi,

I'm sorry for the length of the letter and some material that may look
excessive. But I thought that someone might want to comments on this.

Basically I'm looking for the answers to the following questions:
1. If any of these points have already been discussed and declined, I'd like
to know which ones, so I could find the reasons in the archives.
2. If anyone thinks that changes I made don't fit in the Xalan architecture
or common approaches, please post your comments.
3. If anyone believes that proposed changes are not usefull or difficult to
use, please post your comments.

Otherwise, if these changes seem reasonable enough, I can proceed with
further implementation. In this case, could anyone explain the system of
posting changes and how they'll be applied?

Here's what I've got so far.

I want to propose to adopt two level extension resolving system:
1. Global level -- extensions that can be used in any XPath expression
within any XPath client (xslt, XPathAPI, etc)
2. Local level -- extensions that can be used only with specific XPath
client (only xslt or XPathAPI, etc).

Extension functions will be resolved on the level 2 and then, if not found,
on level 1. This is what I call resolving stack.

I can name two approaches and their combination for extension mechanism. You
probably have already discussed them and decided to go with run-time
approach. But still, I'd like to present them here.
1. Compile-time extension resolving
Here all extensions are resolved during stylesheet calculation.
(+):
- All extensins resolved only once and then used in many transformers.
- This will remove all caches (today's ExtensionHandlerJavaClass.java, etc)
- No need in the XPath ExpressionVisitor (functions will be visited
automatically)

(-):
- Compilation and execution environments (in the extension part) must be
similar. 
- XSLT function function-available doesn't really fit into this system, b/c
it's runtime by definition, but it's still possible to do.
- Limitation will have to be put on all extension functions: thread-safety
and idempotent over many transformers of one stylesheet. This may be too big
a limitation.
- Too many changes will have to be done with the present code


2. Run-time extension resolving
All extensions are resolved in run-time (in one transformer, or shared).
(+):
- the least amount of changes will have to be done with the present code
- independent environments for compiling stylesheet and transformations.
Btw, present implementation has only one point where this is not true and I
believe this can be easily changed.
- possibility to change extensions for each transformer (if needed)

(-):
- multiple (and likely extensive) extension resolving. This can be avoided
by sharing ExtFunctionResolver's, but in the expence of extra
synchronizations.
- multiple (and likely extensive) extension lookups in the structures like
Hashtable and HashMap (caches).

3. Mixed approach
Here we can give up resolving stack and resolve all global extensions in the
compile-time and local in the run-time. In the case when global extensions
are primary used functions, this will significantly save resolving and
lookup time, as well as expences on caching.

I decided to go first with run-time approach, b/c compile-time imposes too
serious limitations on function implementation. But it's very easy to switch
to mixed approach, if we'd want to sacrifice resolving stack to benefit
performance.

Attached (in the following letter) are changes I propose for run-time
approach (only classes I've changed). These changes are not final, but
rather to show how the system will work. The classes and packages names are
not final too, b/c some of the classes will be obsolete, when these changes
are done and thus names can be reused.
The major things that haven't been implemented here, but definetely have to
be are:
- unified error processing for all extensions
- method caches
- code concerned with different class loaders (I haven't got a chance to
fully investigate the system adopted in the Xalan yet)

I'm also considering a way to register extension resolvers before
transformer is executed or stylesheet is compiled (similar to Xalan C++).
But even w/o this functionality big subset of possible users needs will be
covered.

I want to stop on the following new/changed classes:
1. org.apache.xpath.extensions.ExtCallContext
This is the analog of org.apache.xalan.extensions.ExpressionContext. I just
wanted it to be independent from the xalan package. XPath clients (like
Xalan) should provide implementation of this interface (or default can be
used). I'm still not sure which part of ExpressionContext should be defined
in this interface.

2. org.apache.xpath.extensions.ExtFunction
All extension functions should implement this interface. I stopped on this
model b/c:
 - it will be easier to organize unified cache for extension methods 
 - it's more coherent with compile-time and mixed approaches
 - easily organizable in C++

3. org.apache.xpath.extensions.ExtFunctionResolver
This is interface for resolving functions using namespace and function name
information. It is part of XPathContext class (getExtFunctionResolver) and
is provided by XPath clients. Functions resolved in this interface are
local, i.e. can be used only with specific xpath clients.

4. org.apache.xpath.extensions.ExtFunctionFactory
This is factory that manages/caches/lookups extension functions. Functions
resolved in this class are global, i.e. they can be used in any xpath
expression, any xpath client.
Functions are groupped into packages (ExtFunctionPackage interface).
Packages are referenced by namespace URI. 
Packages can be installed into the factory using installPackage method. 
If the referenced package is not found, an attempt to lookup it is made.
This mechanism in enclosed into lookupFunctionPackage method. I haven't
implemented it yet, but proposed behaviour in this case is:
a) check system properties for namespace uri as the property name
b) ".properties" file in this package, that will list
namespace-uri=java-class
c) jar's META-INF/services
(PkgString is installed in intializer of default factory only as an example.
Most probably it'll be refernced via ".properties" file).

5. org.apache.xpath.extensions.PkgString
This is just an example of global extension package for XPath. Most probably
it'll be moved into the package "org.apache.xpath.extensions.packages".
A number of such global (standard) packages can be defined: PkgString,
PkgNumber, PkgDate, PkgNodeSet, PkgHTML, etc. We can use sets of functions
defined by JavaScript, Java (java.lang), SQL 92 to define these standard
extensions. They are not too numerous, but sufficient for most users needs.
If this seams a good idea, I can post the proposed list of packages with
functions they incorporate (I already have one).

6. org.apache.xpath.functions.FuncExtFunction
I changed implementation. Now it resolves ExtFunction implementation and
executes it. For now I disabled existing code for caching methods (using
method key). I think, that probably it could be easier to organize it inside
of XPathContext or elsewhere, but outside of current ExtensionHandler - this
will make cache unified and it'll be possible to use extension resolvers
concurrently from several transformers in the future. But I haven't decided
on this feature yet.

7. org.apache.xpath.ExtensionsProvider
This class will be removed. This also means that FuncExtElementAvailable
will have to be moved to xalan package.

8. org.apache.xpath.XPathContext
This class now provides access to ExtFunctionResolver and ExtCallContext
implementations.

9. org.apache.xalan.transformer.TransformerImpl
Now it provides ExtFunctionResolver (ExtensionsTable) implementation for
XPathContext.
Methods functionAvailable and extFunction will be removed.

12. org.apache.xalan.extensions.ExtensionsTable
Now it's an implementation of ExtFunctionResolver. Thus methods
functionAvailable and extFunction will be removed

11. org.apache.xalan.extensions.ExtensionHandler
Now it's implementation of ExtFunctionPackage. Thus methods
isFunctionAvailable and callFunction will be removed.

12. org\apache\xalan\extensions\ExtensionNamespacesManager
Here I had to change code a little, so that not all namespaces are
instantiated as Java namespaces.

About extension elements and functions. 
I believe that these two can be unified. The same system of package/method
can be used for elements. Thus ExtensionHandler class will implement both
ExtFunctionPackage and ExtElementPackage interface. And ExtensionsTable will
implement both ExtFunctionResolver and ExtElementResolver.

About extensions in the Xalan C++.
If the same system will be adopted, then, at least, all XPath global
(standard) extensions can be fairly easily migrated from Java to C++ and
back. This might remove some problems, may be even most of them in case of
XPath.

Thanks,
Dimitry

P.S.
This is just an example of a stylesheet, that can be used for testing:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
        xmlns:x-str="http://xml.apache.org/xpath/string";
        xmlns:exslt-str="http://exslt.org/strings";
        xmlns:jstr="class:java.lang.String"

        exclude-result-prefixes="x-str exslt-str jstr"
>

<xsl:template match="/">
    <xsl:variable name="text">Hello World!</xsl:variable>
    <res>
                <r1>
                        <xsl:value-of select="$text"/>
                </r1>
                <r2>
                        <xsl:choose>
                                <xsl:when
test="function-available('x-str:upper')">
                                        <xsl:value-of
select="x-str:upper($text)"/>
                                </xsl:when>
                                <xsl:otherwise>function unavailable:
x-str:upper</xsl:otherwise>
                        </xsl:choose>
                </r2>
                <r3>
                        <xsl:choose>
                                <xsl:when
test="function-available('exslt-str:padding')">
                                        <xsl:value-of
select="exslt-str:padding(10, 'A')"/>
                                </xsl:when>
                                <xsl:otherwise>function unavailable:
exslt-str:padding</xsl:otherwise>
                        </xsl:choose>
                </r3>
                <r4>
                        <xsl:choose>
                                <xsl:when
test="function-available('jstr:valueOf')">
                                        <xsl:value-of
select="jstr:valueOf(10.2)"/>
                                </xsl:when>
                                <xsl:otherwise>function unavailable:
jstr:valueOf</xsl:otherwise>
                        </xsl:choose>
                </r4>
    </res>
</xsl:template>

</xsl:stylesheet>



_____________________________________________________
Sector Data, LLC, is not affiliated with Sector, Inc., or SIAC


_____________________________________________________
Sector Data, LLC, is not affiliated with Sector, Inc., or SIAC

Reply via email to