Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post here questions and problems related to oXygen frameworks/document types.
Johann
Posts: 89
Joined: Wed Jun 17, 2015 12:46 pm

Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Johann » Tue Feb 21, 2017 6:54 pm

Hi everyone,

In the Author Component, I try to test
Configuring Proposed Values in the Context that the Content Completion was Invoked
from https://www.oxygenxml.com/doc/versions/ ... -proposals

An EE or PE version of SAXON is required to perform this configuration.

Is there a way to use another XSLT Processor in the Author Component instead of SAXON ?

Thank your for your response,

Johann

alex_jitianu
Posts: 704
Joined: Wed Nov 16, 2005 11:11 am

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by alex_jitianu » Thu Feb 23, 2017 4:53 pm

Hi Johann,

In theory the XSLT should run just fine with Saxon-HE (which is available in the Author Component) as long as the XSLT doesn't use any functionality available only in the PE/EE versions. If you would need access to the element for which the CC was invoked, you will run into this issue (because saxon:eval() is not available in the HE version).

Code: Select all

        <xsl:variable name="propertyElement" 
select="saxon:eval(saxon:expression($contextElementXPathExpression, ./*))"/>
Unfortunately there is no workaround for this other than using the Java API instead and implementing a SchemaManagerFilter.

Best regards,
Alex

Isabelle
Posts: 58
Joined: Fri Jan 20, 2017 1:11 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Isabelle » Fri Jul 19, 2019 7:21 pm

Hello Everyone,

I try to implement this solution in our ContentCompletionConfigurator java class with Saxon PE.
But when I execute this :

Code: Select all

ProfessionalTransformerFactory fac = new ProfessionalTransformerFactory();
I get this error :

Code: Select all

java.lang.SecurityException: class "net.sf.saxon.Configuration$ApiProvider"'s signer information does not match signer information of other classes in the same package
   at java.lang.ClassLoader.checkCerts(ClassLoader.java:898) ~[na:1.8.0_112]
   at java.lang.ClassLoader.preDefineClass(ClassLoader.java:668) ~[na:1.8.0_112]
   at java.lang.ClassLoader.defineClass(ClassLoader.java:761) ~[na:1.8.0_112]
   at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_112]
   at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[na:1.8.0_112]
   at java.net.URLClassLoader.access$100(URLClassLoader.java:73) ~[na:1.8.0_112]
   at java.net.URLClassLoader$1.run(URLClassLoader.java:368) ~[na:1.8.0_112]
   at java.net.URLClassLoader$1.run(URLClassLoader.java:362) ~[na:1.8.0_112]
   at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_112]
   at java.net.URLClassLoader.findClass(URLClassLoader.java:361) ~[na:1.8.0_112]
   at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_112]
   at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_112]
   at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_112]
   at com._4dconcept.adam.author.plugin.contentCompletion.ContentCompletionConfigurator.updateCCConfigurationFile(ContentCompletionConfigurator.java:84) ~[classes/:na]
   at com._4dconcept.adam.author.plugin.views.S1000DDownloaderOpenerWorker.doBeforeWork(S1000DDownloaderOpenerWorker.java:30) ~[classes/:na]
   at com._4dconcept.adam.author.plugin.views.AbstractDownloaderOpenerWorker.doInBackground(AbstractDownloaderOpenerWorker.java:66) ~[classes/:na]
   at javax.swing.SwingWorker$1.call(SwingWorker.java:295) [na:1.8.0_112]
   at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) [na:1.8.0_112]
   at java.util.concurrent.FutureTask.run(FutureTask.java) [na:1.8.0_112]
   at javax.swing.SwingWorker.run(SwingWorker.java:334) [na:1.8.0_112]
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_112]
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_112]
   at java.lang.Thread.run(Thread.java:745) [na:1.8.0_112]
It seems that it does not take the good net.sf.saxon.Configuration class.

I have checked with mvn dependency:tree, and I am sure only Saxon PE is called.
Would there be a conflict with oxygen jars?
Have you ever encountered this mistake ?
If yes, how did you solve it ?

Thanks for any help.
Regards,
Isabelle

Radu
Posts: 6552
Joined: Fri Jul 09, 2004 5:18 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Radu » Mon Jul 22, 2019 8:25 am

Hi Isabelle,

The Author Component SDK also comes with a Saxon HE JAR library called something like "oxygen-patched-saxon-9". So adding an extra Saxon 9 library directly to the classpath will not work.
You can either use our API to create a Saxon HE transformer:

Code: Select all

PluginWorkspaceProvider.getPluginWorkspace().getXMLUtilAccess().createXSLTTransformer(styleSource, new URL[0], XMLUtilAccess.TRANSFORMER_SAXON_HOME_EDITION)
or if you have a commercial license for Saxon PE and you explicitly want to use Saxon PE with our component you will probably need to load the Saxon PE libraries on a separate Java class loader using Java reflection so that they do not interfere with ours.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

Isabelle
Posts: 58
Joined: Fri Jan 20, 2017 1:11 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Isabelle » Mon Jul 22, 2019 11:34 am

Hello Radu,

As Alex said, we can not use Saxon HE to implement your solution because saxon:eval() is not available in the HE version.
It is not possible to "exclude" oxygen-patched-saxon-9 with Maven ?

Regards,
Isabelle

Radu
Posts: 6552
Joined: Fri Jul 09, 2004 5:18 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Radu » Mon Jul 22, 2019 12:22 pm

Hi Isabelle,

Our code absolutely needs the "oxygen-patched-saxon-9" in its current form, otherwise it might break in unexpected places.
Two possible workarounds for you:

1) XSLT 3.0 added the xsl element xsl:evaluate:

https://stackoverflow.com/questions/472 ... te-example

and using it should work even with Saxon HE.

2) Do not add your Saxon JAR library to the Maven class path, place it (and its commercial license) in another folder, create from the code an URLClassLoader which loads the JAR library and then license folder, then use that class loader to load the classes you are interested in and work with them using Java reflection.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

Isabelle
Posts: 58
Joined: Fri Jan 20, 2017 1:11 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Isabelle » Wed Jul 24, 2019 6:34 pm

Hi Radu,

I tried to create from the code an URLClassLoader which loads the JAR library, and then use that class loader to load classes I need and work with them using Java reflection.

Here is my code

Code: Select all

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SaxonPEUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(SaxonPEUtils.class);
    private static final String SAXON_PE_PATH = "C:/apps/saxon-pe/saxon9pe.jar";

    public static Object newSaxonPETransformer(Source xslt) {
        Object transformer = null;

        try {
            File externalJar = new File(SAXON_PE_PATH);
            if(externalJar.exists()) {
                URLClassLoader saxonClassLoader = new URLClassLoader(new URL[]{externalJar.toURI().toURL()}, ClassLoader.getSystemClassLoader());
                Class<?> classToLoad = saxonClassLoader.loadClass("com.saxonica.config.ProfessionalTransformerFactory");
                Constructor<?> conTest = classToLoad.getConstructor();
                Object proTransformerFactory = conTest.newInstance();
                Method method = proTransformerFactory.getClass().getMethod("newTransformer", Source.class);
                transformer = method.invoke(proTransformerFactory, xslt);
            } else {
                System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
                transformer = TransformerFactory.newInstance().newTransformer();
                LOGGER.error("Saxon PE not found in " + externalJar.getAbsolutePath() + ". Saxon HE TransformerFactory.newTransformer() provided instead.");
            }
        } catch (ClassNotFoundException | IllegalAccessException |InvocationTargetException | InstantiationException | NoSuchMethodException | MalformedURLException | TransformerException e) {
            LOGGER.error(e.getMessage(), e);
        }

        return transformer;
    }
}
Even if I specify an external class loader as parent ClassLoader.getSystemClassLoader(), it does not work because it still looking in oxygen-patched-saxon-9he-21.1.0.2.jar.
[SwingWorker-pool-8-thread-2] ERROR c._.a.a.plugin.utils.SaxonPEUtils - SYSTEM - null
java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_112]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_112]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_112]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_112]
at plugin.utils.SaxonPEUtils.newSaxonPETransformer(SaxonPEUtils.java:30) ~[classes/:na]
at plugin.contentCompletion.ContentCompletionConfigurator.updateCCConfigurationFile(ContentCompletionConfigurator.java:75) [classes/:na]
at plugin.views.OpenerWorker.doBeforeWork(OpenerWorker.java:30) [classes/:na]
at plugin.views.AbstractOpenerWorker.doInBackground(AbstractOpenerWorker.java:66) [classes/:na]
at javax.swing.SwingWorker$1.call(SwingWorker.java:295) [na:1.8.0_112]
at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) [na:1.8.0_112]
at java.util.concurrent.FutureTask.run(FutureTask.java) [na:1.8.0_112]
at javax.swing.SwingWorker.run(SwingWorker.java:334) [na:1.8.0_112]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_112]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_112]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_112]
Caused by: java.lang.NoSuchMethodError: com.saxonica.config.ProfessionalConfiguration.internalSetBooleanProperty(Lnet/sf/saxon/lib/Feature;Ljava/lang/Object;)V
at com.saxonica.config.ProfessionalConfiguration.setConfigurationProperty(ProfessionalConfiguration.java:265) ~[na:na]
at com.saxonica.config.ProfessionalConfiguration.setConfigurationProperty(ProfessionalConfiguration.java:254) ~[na:na]
at net.sf.saxon.Configuration.init(Configuration.java:651) ~[oxygen-patched-saxon-9he-21.1.0.2.jar:na]
at net.sf.saxon.Configuration.<init>(Configuration.java:432) ~[oxygen-patched-saxon-9he-21.1.0.2.jar:na]
at com.saxonica.config.ProfessionalConfiguration.<init>(ProfessionalConfiguration.java:133) ~[na:na]
at com.saxonica.config.ProfessionalTransformerFactory.<init>(ProfessionalTransformerFactory.java:25) ~[na:na]
... 15 common frames omitted
I do not understand what I miss, any idea ?

Regards,
Isabelle

Radu
Posts: 6552
Joined: Fri Jul 09, 2004 5:18 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Radu » Thu Jul 25, 2019 8:41 am

Hello Isabelle,

Problem with class loaders (your custom URLClassLoader in this case) is that they prefer to return the classes from the super class loader if they have already been loaded.
So in various places in Oxygen we use a class loader we call LateDelegationClassLoader which prefers to load classes from its JAR libraries instead of falling back on the parent class loader. I'm pasting below how the contents of our late delegation class loader look like:

Code: Select all

public class LateDelegationClassLoader extends URLClassLoader {

  public LateDelegationClassLoader(URL[] urls, ClassLoader parent) {
    super(urls, parent);
  }

  @Override
  public URL getResource(final String name) {
    return AccessController.doPrivileged(new PrivilegedAction<URL>() {
      /**
       * @see java.security.PrivilegedAction#run()
       */
      @Override
      public URL run() {
        
        // Try locally.
        URL url = findResource(name);
        if (url == null) {
          // Delegate to super.
          url = LateDelegationClassLoader.super.getResource(name);
        }
        
        return url;
      }
    });
  }

  @Override
  protected synchronized Class loadClass(String name, boolean resolve)
    throws ClassNotFoundException {

    // First, check if the class has already been loaded
    Class c = findLoadedClass(name);
    if (c == null) {
      if(delegateToParent(name)){
        // Delegate to super.
        c = super.loadClass(name, false);
      } else {
        // Try locally
        try {
          c = findClass(name);
        } catch (ClassNotFoundException e) {
          // Delegate to super.
          c = super.loadClass(name, false);
        }
      }
    }
    if (resolve) {
      resolveClass(c);
    }
    return c;
  }

  protected boolean delegateToParent(String className) {
    if(className.equals(getClass().getName())){
      //EXM-36639 Prefer having a single class loaded usually in the base class loader.
      //In this way we can use instanceof for example.
      return true;
    }
    return className.startsWith("java.") || className.startsWith("javax.swing.")
      // EXM-16043 XHive bootstrap needs xbean.jar which redefines the org.w3c.dom package.
        || className.startsWith("org.w3c.dom.")
        //EXM-24640 The unmarshalling in
        //ro.sync.xml.uriattributes.URIAttributesRepository.loadRepository(URL) 
        //fails if the xml-apis.jar is preferred to resolve these interfaces. 
        || className.startsWith("javax.xml.datatype.")
        || className.startsWith("javax.xml.parsers.")
        || className.startsWith("javax.xml.transform.")
        || className.startsWith("javax.xml.validation.")
        // EXM-24901 Documentum needs this package.
        || className.startsWith("javax.xml.namespace.")
        || className.startsWith("org.xml.sax.")
        // EXM-25938 XMLInputFactory requires com.ctc.wstx.stax.WstxInputFactory
        // so is best to use the interfaces from the JRE.
        || className.startsWith("javax.xml.stream.")
        // EXM-28502: JUnit needs the annotations to be loaded on the default 
        // classloader.
        || className.startsWith("org.junit.");
  }
  
  /**
   * @see java.net.URLClassLoader#getPermissions(java.security.CodeSource)
   */
  @Override
  protected PermissionCollection getPermissions(CodeSource codesource) {
    PermissionCollection perms = new java.security.Permissions();
    perms.add(new AllPermission());
    return perms;
  }
  
  @Override
  public Enumeration<URL> getResources(String name) throws IOException {
    Enumeration<URL> myResources = findResources(name);
    Enumeration<URL> superResources = super.getResources(name);
    if(myResources == null || !myResources.hasMoreElements()) {
      return superResources;
    } else {
      //Prefer to return my resources as the first ones.
      LinkedHashSet<URL> resources = new LinkedHashSet<URL>();
      while(myResources.hasMoreElements()) {
        resources.add(myResources.nextElement());
      }
      if(superResources != null) {
        while(superResources.hasMoreElements()) {
          URL url = superResources.nextElement();
          if(! resources.contains(url)) {
            resources.add(url);
          }
        }
      }
      return new Vector(resources).elements();
    }
  }
}
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

Isabelle
Posts: 58
Joined: Fri Jan 20, 2017 1:11 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Isabelle » Thu Jul 25, 2019 4:46 pm

Hi Radu,

Thanks for your feedback.
I did not know about that fact.

I have integrated your class and it works fine now.
Thanks again.

Regards,
Isabelle

Isabelle
Posts: 58
Joined: Fri Jan 20, 2017 1:11 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Isabelle » Fri Jul 26, 2019 3:11 pm

Hello,

Thanks to you, we can compile XSL with Saxon PE in java but we still have issue.

We try to implement
Configuring Proposed Values in the Context that the Content Completion was Invoked
that we find here https://www.oxygenxml.com/doc/versions/ ... -proposals.

But when we launch our application and call content completion on an xml element, we have these error :

Code: Select all

60045 ERROR [ AWT-EventQueue-0 ] ro.sync.contentcompletion.xml.extensibility.values.g - javax.xml.transform.TransformerConfigurationException: E Errors were reported during stylesheet compilation
F Cannot find a 2-argument function named {http://saxon.sf.net/}expression(). Saxon extension functions are not available under Saxon-HE at line 18 and column 83
javax.xml.transform.TransformerConfigurationException: E Errors were reported during stylesheet compilation
F Cannot find a 2-argument function named {http://saxon.sf.net/}expression(). Saxon extension functions are not available under Saxon-HE at line 18 and column 83
	at ro.sync.exml.workspace.b.b.d.d(Unknown Source)
	at ro.sync.exml.workspace.b.b.d.c(Unknown Source)
	at ro.sync.exml.workspace.b.b.d.createXSLTTransformer(Unknown Source)
	at ro.sync.exml.workspace.b.b.d.createXSLTTransformer(Unknown Source)
	at ro.sync.contentcompletion.xml.extensibility.values.g.getValues(Unknown Source)
	at ro.sync.contentcompletion.xml.extensibility.values.b.filterAttributeValues(Unknown Source)
	at ro.sync.contentcompletion.xml.gb.oyr(Unknown Source)
	at ro.sync.contentcompletion.xml.db.i(Unknown Source)
	at ro.sync.contentcompletion.xml.y.rgs(Unknown Source)
	at ro.sync.contentcompletion.t.rgs(Unknown Source)
	at ro.sync.contentcompletion.editor.k.vwl(Unknown Source)
	at ro.sync.contentcompletion.editor.k.processKeyEvent(Unknown Source)
	at ro.sync.contentcompletion.editor.s.processKeyEvent(Unknown Source)
	at java.awt.Component.processEvent(Component.java:6310)
	at java.awt.Container.processEvent(Container.java:2236)
	at java.awt.Component.dispatchEventImpl(Component.java:4889)
	at java.awt.Container.dispatchEventImpl(Container.java:2294)
	at java.awt.Component.dispatchEvent(Component.java:4711)
	at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1954)
	at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:806)
	at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1074)
	at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:945)
	at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:771)
	at java.awt.Component.dispatchEventImpl(Component.java:4760)
	at java.awt.Container.dispatchEventImpl(Container.java:2294)
	at java.awt.Window.dispatchEventImpl(Window.java:2746)
	at java.awt.Component.dispatchEvent(Component.java:4711)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
	at java.awt.EventQueue.access$500(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:709)
	at java.awt.EventQueue$3.run(EventQueue.java:703)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:90)
	at java.awt.EventQueue$4.run(EventQueue.java:731)
	at java.awt.EventQueue$4.run(EventQueue.java:729)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Even if we have compiled our content completion with saxon pe, it calls saxon HE when it executes

Code: Select all

    <match elementName="property" attributeName="value">
      <xslt href="get_values.xsl" useCache="false" action="replace"/>
    </match>
Any ideas how to correct it ?

Regards,
Isabelle

alex_jitianu
Posts: 704
Joined: Wed Nov 16, 2005 11:11 am

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by alex_jitianu » Tue Aug 06, 2019 1:14 pm

Dear Isabelle,

You should remove this block from within the content completion configuration file:

Code: Select all

<match elementName="property" attributeName="value">
  <xslt href="get_values.xsl" useCache="false" action="replace"/>
</match>
No matter what you do, this XSLT will be executed with the built-in Saxon HE. What you need to do is to implement your own SchemaManagerFilter. In its filterAttributeValues method you will execute the XSLT with your own Saxon-PE processor. The XSLT needs some external parameters that you can obtain and pass like this:

Code: Select all

  
  /**
   * @see ro.sync.contentcompletion.xml.SchemaManagerFilter#filterAttributeValues(java.util.List, ro.sync.contentcompletion.xml.WhatPossibleValuesHasAttributeContext)
   */
  @Override
  public List<CIValue> filterAttributeValues(List<CIValue> attributeValues,
      final WhatPossibleValuesHasAttributeContext context) {
    
    
    ((net.sf.saxon.jaxp.TransformerImpl) transformer).setInitialTemplate("start");

    // Give parameters. systemID and location path.
    transformer.setParameter("documentSystemID", context.getSystemID());
    String contextXPathExpression = context.computeContextXPathExpression();
    if (contextXPathExpression != null) {
      transformer.setParameter("contextElementXPathExpression", contextXPathExpression);
    }
    transformer.transform(null, outputTarget);
Once you have this class, you pack it into a Jar, you put the Jar inside the Classpath of the framework and you specify the Schema Manager in the Extensions tab.

Please let me know if you need any additional details.

Best regards,
Alex

Isabelle
Posts: 58
Joined: Fri Jan 20, 2017 1:11 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Isabelle » Thu Aug 08, 2019 7:51 pm

Hello Alex,

Thanks a lot for your help.
It finally works.

Regards,
Isabelle

Isabelle
Posts: 58
Joined: Fri Jan 20, 2017 1:11 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Isabelle » Thu Aug 08, 2019 8:38 pm

Hello Alex,

As I said earlier, it works fine, but only on saved document, not on in worked / unsaved document.

Each time I asked for content completion, it used previous saved value or don't find new values.

Do you have any workaround for that ?

Regards,
Isabelle

alex_jitianu
Posts: 704
Joined: Wed Nov 16, 2005 11:11 am

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by alex_jitianu » Fri Aug 09, 2019 3:16 pm

Hello Isabelle,

If I understand it correctly, the XSLT file processes the saved version of the file, instead of the unsaved snapshot from the editor, right? If that's the case, then the fix is to set an URIResolver that will get the content from the editor, like this:

Code: Select all

    
    URIResolver uriResolver = PluginWorkspaceProvider.getPluginWorkspace().getXMLUtilAccess().getURIResolver();
    transformer.setURIResolver(uriResolver);
Best regards,
Alex

Isabelle
Posts: 58
Joined: Fri Jan 20, 2017 1:11 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Isabelle » Fri Aug 09, 2019 4:03 pm

Hello Alex,

Thanks for your answer.

I tried to implement it this way:

Code: Select all

		    System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
                    Source quomXslt = new StreamSource(ccSpecificCCValueConfigXslFile);
                    URIResolver uriResolver = PluginWorkspaceProvider.getPluginWorkspace().getXMLUtilAccess().getURIResolver();
                    Transformer quomTransformer = (Transformer) SaxonPEManager.getInstance().newSaxonPETransformer(quomXslt, "start");
                    quomTransformer.setURIResolver(uriResolver);
                    quomTransformer.setParameter("documentSystemID", context.getSystemID());
                    String contextXPathExpression = context.computeContextXPathExpression();
                    if (contextXPathExpression != null) {
                        quomTransformer.setParameter("contextElementXPathExpression", contextXPathExpression);
                    }
                    quomTransformer.transform(null, new StreamResult(ccSpecificCCValueConfigXmlFile));
But it still does not work.
Did I miss something ?

Regards,
Isabelle

alex_jitianu
Posts: 704
Joined: Wed Nov 16, 2005 11:11 am

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by alex_jitianu » Fri Aug 09, 2019 4:12 pm

Hello Isabelle,

To make sure I understand the situation correctly, the XSLT file processes the saved version of the file, instead of the unsaved snapshot from the editor, right?

The code looks O.K. Can you send me the zipped plugin on support@oxygenxml.com so I can reproduce the issue myself and look for a fix? After I finish my investigation, I will remove it from my system.

Best regards,
Alex

Isabelle
Posts: 58
Joined: Fri Jan 20, 2017 1:11 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Isabelle » Fri Aug 09, 2019 4:18 pm

Hello Alex,

You understand the situation correctly.
It never process the unsaved snapshot from the editor.
I don't know if I can send to you the plugin like that.

I will ask to my colleague, and let you know as soon as possible.

Regards,
Isabelle

Isabelle
Posts: 58
Joined: Fri Jan 20, 2017 1:11 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Isabelle » Tue Sep 24, 2019 1:41 pm

Hi Everyone,

I have just send to support@oxygenxml.com all relevant files in order to have your help to solve our problem.
I can't send you our application, sorry, but I tried to send you all you need.

Here is a test case :

Code: Select all

<quantity quantityType="qty05">
   <quantityGroup quantityGroupType="minimum">
	  <quantityValue quantityUnitOfMeasure="um51">6.4</quantityValue>
	  <quantityValue quantityUnitOfMeasure="lbf.ft">47.2</quantityValue>
   </quantityGroup>
</quantity>
We want to filter quantityUnitOfMeasure attribute regarding the value of quantityType attribute.

Thanks,
Regards,
Isabelle

alex_jitianu
Posts: 704
Joined: Wed Nov 16, 2005 11:11 am

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by alex_jitianu » Thu Sep 26, 2019 8:35 am

Dear Isabelle,

Thank you for taking the time to send us all those resources. It turns out that the API URIResolver doesn't pass though the opened editors, like I initially expected. Sorry about that... Luckily there is enough API available so that you can extend this behavior. Something like this:

Code: Select all

	private URIResolver creteResolver(String editorSystemId) {
		final URIResolver uriResolver = PluginWorkspaceProvider.getPluginWorkspace().getXMLUtilAccess().getURIResolver();
		
		return new URIResolver() {
			@Override
			public Source resolve(String href, String base) throws TransformerException {
				if (editorSystemId.equals(href)) {
					// Check if the file is opened inside an editor.
					WSEditor editorAccess = PluginWorkspaceProvider.getPluginWorkspace().getEditorAccess(new URL(editorSystemId), PluginWorkspace.MAIN_EDITING_AREA);
					if (editorAccess != null) {
						Reader reader = editorAccess.createContentReader();
						return new StreamSource(reader, editorSystemId);
					}
				}
				return uriResolver.resolve(href, base);
			}
		}; 
	}
Let me know how it goes!

Best regards,
Alex

Isabelle
Posts: 58
Joined: Fri Jan 20, 2017 1:11 pm

Re: Configuring Proposed Values in the Context that the Content Completion was Invoked - SAXON

Post by Isabelle » Thu Sep 26, 2019 3:31 pm

Hello Alex,

It works fine now !
Thanks a lot.

Regards,
Isabelle

Post Reply