org.bidib.wizard.migration.labels.AbstractWizardLabelMigrator Maven / Gradle / Ivy
package org.bidib.wizard.migration.labels;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.XMLConstants;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.collections4.Predicate;
import org.bidib.jbidibc.core.schema.bidiblabels.LabelFactory;
import org.bidib.jbidibc.core.schema.bidiblabels.NodeLabels;
import org.bidib.jbidibc.core.schema.bidiblabels.PortLabels;
import org.bidib.wizard.api.context.ApplicationContext;
import org.bidib.wizard.migration.migrator.MigrationException;
import org.bidib.wizard.migration.schema.nodes.Nodes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.saxon.lib.FeatureKeys;
public abstract class AbstractWizardLabelMigrator {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractWizardLabelMigrator.class);
private static final String NAMESPACE_PREFIX = "{http://www.bidib.org/schema/labels}";
public static final String INPUT2_XSL = "/migration/labels-migration2.xsl";
public static final String INPUT2A_XSL = "/migration/labels-migration2a.xsl";
protected static final String KEY_MIGRATIONXSL = "migrationXSL";
/**
* Find all nodes in wizard labels.
*
* @param searchpath
* the search path
* @return the node labels with all nodes
*/
public abstract Nodes findAllNodesInWizardLabels(String searchpath);
/**
* Perform migration from wizard labels to new node labels.
*
* The old wizard labels of a node must be collected from multiple files, because each label type has it's own file.
*
*
* @param context
* the migration context
* @param uniqueId
* the uniqueId
* @param dataXML
* the data XML
* @return the nodeLabels that were migrated from dataXML
*/
public abstract NodeLabels performWizardLabelsMigration(
final ApplicationContext context, long uniqueId, String searchpath);
/**
* Search labels of one type.
*
* @param fileName
* the filename to search
* @param searchpath
* the search path
* @return the labels or {@code null} if no labels were found
*/
protected Nodes performFindAllNodesInWizardLabels(String fileName, String transformationXSL, String searchpath) {
LOGGER.info("Perform find all nodes in wizard label, fileName: {}, searchpath: {}", fileName, searchpath);
Nodes nodes = null;
FileInputStream dataXML = null;
try {
File searchFile = new File(searchpath, fileName);
LOGGER.info("Search for node file: {}", searchFile);
dataXML = new FileInputStream(searchFile);
LOGGER.info("Prepared dataXML: {}", dataXML);
nodes = performFindNodes(null, dataXML, transformationXSL);
}
catch (FileNotFoundException ex) {
LOGGER.warn("Perform find nodes failed because file is not available: {}", ex.getMessage());
}
// catch (Exception ex) {
// // TODO: handle exception
// LOGGER.warn("Perform find nodes failed.", ex);
// }
finally {
if (dataXML != null) {
try {
dataXML.close();
}
catch (IOException ex) {
LOGGER.warn("Close dataXML stream failed.", ex);
}
}
}
return nodes;
}
protected Nodes performFindNodes(Map params, InputStream dataXML, String migrationXSL) {
LOGGER.info("perform find nodes with migrationXSL: {}", migrationXSL);
InputStream inputXSL = null;
StringWriter outputXML = null;
InputStream is = null;
Nodes nodes = null;
try {
inputXSL = AbstractWizardLabelMigrator.class.getResourceAsStream(migrationXSL);
outputXML = new StringWriter();
LOGGER.info("Prepared inputXSL: {}", inputXSL);
// perform the transformation
doTransform(params, inputXSL, dataXML, outputXML);
LOGGER.info("The generated XML document is:\r\n{}", outputXML);
is = new ByteArrayInputStream(outputXML.getBuffer().toString().getBytes(StandardCharsets.UTF_8));
nodes = NodesFactory.loadNodes(is);
LOGGER.info("Prepared migrated nodes: {}", nodes);
}
catch (TransformerException ex) {
// TODO: handle exception
LOGGER.warn("Perform find nodes with transformation failed.", ex);
}
finally {
if (outputXML != null) {
try {
outputXML.close();
}
catch (IOException ex) {
LOGGER.warn("Close outputXML writer failed.", ex);
}
}
if (is != null) {
try {
is.close();
}
catch (IOException ex) {
LOGGER.warn("Close inputStream failed.", ex);
}
}
if (inputXSL != null) {
try {
inputXSL.close();
}
catch (IOException ex) {
LOGGER.warn("Close inputXSL stream failed.", ex);
}
}
}
return nodes;
}
protected void doTransform(
Map params, final InputStream inputXSL, final InputStream dataXML, final StringWriter outputXML)
throws TransformerException {
TransformerFactory factory = TransformerFactory.newInstance();
// disable warning in saxon
factory.setFeature(FeatureKeys.SUPPRESS_XSLT_NAMESPACE_CHECK, true);
// prevent XXE
try {
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
}
catch (IllegalArgumentException e) {
LOGGER.warn("XSL transformer implementation doesn't support {} feature", XMLConstants.ACCESS_EXTERNAL_DTD);
}
try {
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
}
catch (IllegalArgumentException e) {
LOGGER.warn("XSL transformer implementation doesn't support {} feature", XMLConstants.ACCESS_EXTERNAL_DTD);
}
StreamSource xslStream = new StreamSource(inputXSL);
Transformer transformer = factory.newTransformer(xslStream);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");
if (MapUtils.isNotEmpty(params)) {
for (Entry param : params.entrySet()) {
if (!KEY_MIGRATIONXSL.equals(param.getKey())) {
// set the transformation parameter
LOGGER.info("Set transformer parameter: {}", param);
transformer.setParameter(NAMESPACE_PREFIX + param.getKey(), param.getValue());
}
else {
LOGGER.info("Skip KEY_MIGRATIONXSL.");
}
}
}
StreamSource in = new StreamSource(dataXML);
StreamResult out = new StreamResult(outputXML);
transformer.transform(in, out);
outputXML.flush();
}
protected void appendNodeLabels(
final List exisiting,
final List toAdd) {
List toMerge =
ListUtils.select(toAdd, new Predicate() {
@Override
public boolean evaluate(org.bidib.wizard.migration.schema.nodes.NodeLabel nodeLabel) {
for (org.bidib.wizard.migration.schema.nodes.NodeLabel current : exisiting) {
if (current.getUniqueId() == nodeLabel.getUniqueId()) {
return false;
}
}
return true;
}
});
exisiting.addAll(toMerge);
}
protected NodeLabels performMigration(Map params, InputStream dataXML, String migrationXSL) {
LOGGER.info("perform migration with migrationXSL: {}", migrationXSL);
InputStream inputXSL = null;
StringWriter outputXML = null;
InputStream is = null;
NodeLabels nodeLabels = null;
try {
inputXSL = AbstractWizardLabelMigrator.class.getResourceAsStream(migrationXSL);
outputXML = new StringWriter();
LOGGER.info("Prepared inputXSL: {}", inputXSL);
// perform the transformation
doTransform(params, inputXSL, dataXML, outputXML);
LOGGER.info("The generated XML document is:\r\n{}", outputXML);
is = new ByteArrayInputStream(outputXML.getBuffer().toString().getBytes(StandardCharsets.UTF_8));
nodeLabels = new LabelFactory().loadLabels(is);
LOGGER.info("Prepared migrated nodeLabels: {}", nodeLabels);
}
catch (TransformerException ex) {
LOGGER.warn("Perform transformation of bidib2 migration failed.", ex);
throw new MigrationException("Perform transformation for label migration failed.", ex);
}
finally {
if (outputXML != null) {
try {
outputXML.close();
}
catch (IOException ex) {
LOGGER.warn("Close outputXML writer failed.", ex);
}
}
if (is != null) {
try {
is.close();
}
catch (IOException ex) {
LOGGER.warn("Close inputStream failed.", ex);
}
}
if (inputXSL != null) {
try {
inputXSL.close();
}
catch (IOException ex) {
LOGGER.warn("Close inputXSL stream failed.", ex);
}
}
}
return nodeLabels;
}
protected void migrateAndAppendWizardPortLabels(
final NodeLabels nodeLabels, final Map params, String searchpath, String fileName,
String migrationXSL, String portTypeIdentifier) {
LOGGER
.info("migrateAndAppendWizardPortLabels, portTypeIdentifier: {}, fileName: {}, migrationXSL: {}",
portTypeIdentifier, fileName, migrationXSL);
params.put("forced_porttype", portTypeIdentifier);
// search port labels
NodeLabels portNodeLabels = performWizardLabelsMigration(params, fileName, migrationXSL, searchpath);
if (portNodeLabels != null && portNodeLabels.getPortLabels() != null
&& CollectionUtils.isNotEmpty(portNodeLabels.getPortLabels().getPortLabel())) {
LOGGER.info("Merge {} port labels for params: {}", portTypeIdentifier, params);
// merge the port labels into the node labels
PortLabels portLabels = portNodeLabels.getPortLabels();
// make sure portLabels exist
if (nodeLabels.getPortLabels() == null) {
LOGGER.info("Create new PortLabels instance.");
nodeLabels.setPortLabels(new PortLabels());
}
nodeLabels.getPortLabels().getPortLabel().addAll(portLabels.getPortLabel());
}
else {
LOGGER.info("No migrated {} port labels found for params: {}", portTypeIdentifier, params);
}
}
/**
* Search labels of one type.
*
* @param params
* the params
* @param fileName
* the filename to search
* @param searchpath
* the search path
* @return the labels or {@code null} if no labels were found
*/
protected NodeLabels performWizardLabelsMigration(
final Map params, String fileName, String migrationXSL, String searchpath) {
LOGGER
.info("perform wizard label migration for params: {}, fileName: {}, migrationXSL: {}, searchpath: {}",
params, fileName, migrationXSL, searchpath);
NodeLabels nodeLabels = null;
FileInputStream dataXML = null;
try {
File searchFile = new File(searchpath, fileName);
LOGGER.info("Search for node file: {}", searchFile);
dataXML = new FileInputStream(searchFile);
LOGGER.info("Prepared dataXML: {}", dataXML);
nodeLabels = performMigration(params, dataXML, migrationXSL /* INPUT2_XSL */);
}
catch (MigrationException ex) {
LOGGER.warn("Perform transformation of label migration failed for fileName: {}", fileName, ex);
throw new MigrationException("Perform transformation for label migration failed for fileName: " + fileName,
ex.getCause());
}
catch (FileNotFoundException ex) {
// TODO: handle exception
LOGGER.warn("perform WizardLabelsMigration failed.", ex);
}
finally {
if (dataXML != null) {
try {
dataXML.close();
}
catch (IOException ex) {
LOGGER.warn("Close dataXML stream failed.", ex);
}
}
}
return nodeLabels;
}
}