Skip to content

Commit

Permalink
Post process schema (#206)
Browse files Browse the repository at this point in the history
* remove anyAttribute from default and generated xsds if no extraProperties

* Update cached schema
  • Loading branch information
cherylking authored Aug 25, 2023
1 parent 96cea15 commit e116770
Show file tree
Hide file tree
Showing 7 changed files with 41,714 additions and 42,078 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import io.openliberty.tools.langserver.lemminx.services.DockerService;
import io.openliberty.tools.langserver.lemminx.services.LibertyProjectsManager;
import io.openliberty.tools.langserver.lemminx.services.LibertyWorkspace;
import io.openliberty.tools.langserver.lemminx.util.DocumentUtil;
import io.openliberty.tools.langserver.lemminx.util.LibertyUtils;

public class LibertyXSDURIResolver implements URIResolverExtension, IExternalGrammarLocationProvider {
Expand Down Expand Up @@ -159,6 +160,11 @@ private String generateServerSchemaXsd(LibertyWorkspace libertyWorkspace, Path s
return null;
}

if (xsdDestFile.exists()) {
// do some post processing to remove the anyAttribute element from parent element if there is no extraProperties sibling
DocumentUtil.removeExtraneousAnyAttributeElements(xsdDestFile);
}

LOGGER.info("Caching schema file with URI: " + xsdDestFile.toURI().toString());
} catch (Exception e) {
LOGGER.warning(e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import io.openliberty.tools.langserver.lemminx.util.DocumentUtil;
import io.openliberty.tools.langserver.lemminx.util.LibertyUtils;

public class DockerService {
Expand Down Expand Up @@ -124,6 +125,10 @@ public String generateServerSchemaXsdFromContainer(LibertyWorkspace libertyWorks
if (!xsdFile.exists()) {
return null;
}

// do some post processing to remove the anyAttribute element from parent element if there is no extraProperties sibling
DocumentUtil.removeExtraneousAnyAttributeElements(xsdFile);

LOGGER.info("Using schema file at: " + xsdFile.toURI().toString());
return xsdFile.toURI().toString();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*******************************************************************************
* Copyright (c) 2023 IBM Corporation and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/

package io.openliberty.tools.langserver.lemminx.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class DocumentUtil {
private static final Logger LOGGER = Logger.getLogger(DocumentUtil.class.getName());

public static Document getDocument(File inputFile) throws Exception {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
docFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
docFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
docFactory.setNamespaceAware(true);
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
return docBuilder.parse(inputFile);
} catch (Exception e) {
LOGGER.warning("Error creating document from xml file: " + inputFile.getAbsolutePath() +" exception: "+e.getMessage());
throw e;
}
}

public static void writeDocToXmlFile(Document doc, File inputFile) throws Exception {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
// Need to use this xsl to prevent extra lines in the updated xsd file. It is a known issue in Java 9 and up that is not going to be fixed.
// It was a design decision. Ref link: https://bugs.openjdk.org/browse/JDK-8262285?attachmentViewMode=list
InputStream is = DocumentUtil.class.getClassLoader().getResourceAsStream("formatxsd.xsl");
Transformer transformer = transformerFactory.newTransformer(new StreamSource(is));
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes");

doc.setXmlStandalone(true);
DOMSource source = new DOMSource(doc);
StreamResult file = new StreamResult(new OutputStreamWriter(new FileOutputStream(inputFile), "UTF-8"));
transformer.transform(source, file);
}

public static void removeExtraneousAnyAttributeElements(File schemaFile) {
try {
Document doc = getDocument(schemaFile);
boolean updated = false;

List<Element> anyAttrElements = getElementsByName(doc,"anyAttribute");
for (Element anyAttr : anyAttrElements) {
Node anyAttrParent = anyAttr.getParentNode();
// if the parent node does not contain a <annotation><appinfo><extraProperties> element, remove the anyAttribute element
if (anyAttrParent != null && anyAttrParent.getNodeType() == Node.ELEMENT_NODE) {
Element anyAttrParentElement = (Element) anyAttrParent;
NodeList extraPropertiesList = anyAttrParentElement.getElementsByTagNameNS("*", "extraProperties");
if (extraPropertiesList == null || extraPropertiesList.getLength() == 0) {
if (anyAttrParent.removeChild(anyAttr) != null) {
updated = true;
}
}
}
}

if (updated) {
writeDocToXmlFile(doc, schemaFile);
LOGGER.info("Finished post processing of schema file: "+schemaFile.getCanonicalPath());
}
} catch (Exception e) {
LOGGER.warning("Received exception during post processing of schema file "+schemaFile.getAbsolutePath()+" : "+e.getMessage());
}
}

public static List<Element> getElementsByName(Document doc, String name) {
List<Element> elements = new ArrayList<Element>();
try {
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagNameNS("*", name);
if (nList != null) {
for (int temp = 0; temp < nList.getLength(); temp++) {

Node nNode = nList.item(temp);

if (nNode.getNodeType() == Node.ELEMENT_NODE) {

Element elem = (Element) nNode;
elements.add(elem);
}
}
}
} catch (Exception e) {
LOGGER.warning("Exception received while parsing "+ doc.getDocumentURI() +": "+e.getMessage());
}
return elements;
}
}
11 changes: 11 additions & 0 deletions lemminx-liberty/src/main/resources/formatxsd.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" encoding="UTF-8"/>

<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>
Loading

0 comments on commit e116770

Please sign in to comment.