blob: 2ddbcb3311318c88dd7121a16db7c1730e5dc7ac [file] [log] [blame]
package org.eclipse.basyx.components.aasx;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.io.IOUtils;
import org.eclipse.basyx.components.configuration.BaSyxConfiguration;
import org.eclipse.basyx.components.xml.XMLAASBundleFactory;
import org.eclipse.basyx.support.bundle.AASBundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* The AASX package converter converts a aasx package into a list of aas, a list
* of submodels a list of assets, a list of Concept descriptions
*
* The aas provides the references to the submodels and assets
*
* @author zhangzai
*
*/
public class AASXPackageManager {
/**
* Input stream of the aasx package
*/
private ZipInputStream stream;
/**
* Path to the AASX package
*/
private String aasxPath;
/**
* AAS bundle factory
*/
private XMLAASBundleFactory bundleFactory;
/**
* Logger
*/
private static Logger logger = LoggerFactory.getLogger(AASXPackageManager.class);
/**
* Constructor
*/
public AASXPackageManager(String path) {
aasxPath = path;
}
public Set<AASBundle> retrieveAASBundles() throws IOException, ParserConfigurationException, SAXException {
bundleFactory = new XMLAASBundleFactory(getXMLResourceString(aasxPath));
return bundleFactory.create();
}
/**
* Find the path of the aas-xml file
*
* @param stream - Stream of the aasx package
* @return Path of the aas xml file, empty string if not found
* @throws IOException
* @throws ParserConfigurationException
* @throws SAXException
*/
private String findAASXml(ZipInputStream stream) throws IOException, ParserConfigurationException, SAXException {
String path = "";
// find the entry of the aasx
for (ZipEntry entry; (entry = stream.getNextEntry()) != null;) {
// get name of the entry
String name = entry.getName();
// find the relationship file in the directory /aasx/_rels/aas_origin.rels
if (!entry.isDirectory() && name.startsWith("aasx/_rels")) {
// find the file aasx-origin.rels
if (name.endsWith("aasx-origin.rels")) {
// Get path of the aas xml
String aasXmlPath = findAASXMLAddress(stream);
if (!aasXmlPath.isEmpty()) {
path = aasXmlPath;
break;
}
}
}
}
return path;
}
/**
* Get entry of a file
*
* @param filename - name of a file with path
* @return a file entry
* @throws IOException
*/
private ZipInputStream returnFileEntryStream(String filename) throws IOException {
ZipInputStream str = null;
if (filename.startsWith("/")) {
filename = filename.substring(1);
}
// get all entries of the aasx
for (ZipEntry e; (e = stream.getNextEntry()) != null;) {
// get name of the entry
String name = e.getName();
if (name.equals(filename)) {
str = stream;
break;
}
}
return str;
}
/**
* Parse the relationship file and find the path of the aas-XML file describing
* the aas
*
* @param ins - input stream of this relationship file
* @return path of the aas-xml file
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
private String findAASXMLAddress(InputStream ins) throws ParserConfigurationException, SAXException, IOException {
String path = "";
// create the XML document parser
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(ins);
doc.getDocumentElement().normalize();
// Get the tag with "Relationships"
logger.info("Root element :" + doc.getDocumentElement().getNodeName());
NodeList relList = doc.getElementsByTagName("Relationship");
// If there is only 1 relationship pointing to the aas-xml file, this should be
// the case
if (relList.getLength() == 1) {
Node first = relList.item(0);
if (first.getNodeType() == Node.ELEMENT_NODE) {
logger.info("\nCurrent Element :" + first.getNodeName());
// get the target file path
String targetFile = ((Element) first).getAttribute("Target");
String type = ((Element) first).getAttribute("Type");
// validate the relationship type
if (type.endsWith("aas-spec")) {
logger.info("target file name : " + targetFile);
path = targetFile;
}
}
}
return path;
}
/**
* Return the Content of the xml file in the aasx-package as String
*
* @param filePath - path to the aasx package
* @return Content of XML as String
* @throws IOException
* @throws ParserConfigurationException
* @throws SAXException
*/
private String getXMLResourceString(String filePath) throws IOException, ParserConfigurationException, SAXException {
String aasXmlPath;
// Create the zip input stream
try (ZipInputStream stream = new ZipInputStream(BaSyxConfiguration.getResourceStream(filePath))) {
// find the path of the aas xml
aasXmlPath = this.findAASXml(stream);
}
try (ZipInputStream stream = new ZipInputStream(BaSyxConfiguration.getResourceStream(filePath))) {
this.stream = stream;
// Find the entry of the aas xml
ZipInputStream streamPointingToEntry = this.returnFileEntryStream(aasXmlPath);
// create the xml-converter with the input stream
String text = IOUtils.toString(streamPointingToEntry, StandardCharsets.UTF_8.name());
return text;
}
}
}