Xproc search and replace
Added custom extension for calabash to handle search and replace functionality. Added xproc pipeline/step to pick pom filename configuration and call calabash extension java code. Linked xproc and calabash extension using the configuration.xml
This commit is contained in:
@@ -147,6 +147,13 @@ public abstract class PDFMojo extends AbstractFoMojo {
|
||||
* default-value=""
|
||||
*/
|
||||
private String canonicalUrlBase;
|
||||
|
||||
/**
|
||||
* @parameter
|
||||
* expression="${generate-pdf.replacementsFile}"
|
||||
* default-value=""
|
||||
*/
|
||||
private String replacementsFile;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -380,7 +387,10 @@ public abstract class PDFMojo extends AbstractFoMojo {
|
||||
}
|
||||
transformer.setParameter("branding", branding);
|
||||
|
||||
transformer.setParameter("docbook.infile",sourceDocBook.getAbsolutePath());
|
||||
//transformer.setParameter("docbook.infile",sourceDocBook.getAbsolutePath());
|
||||
String srcFilename = sourceDocBook.getName();
|
||||
getLog().info("SOURCE FOR COVER PAGE: "+this.projectBuildDirectory+"/docbkx/"+srcFilename);
|
||||
transformer.setParameter("docbook.infile", this.projectBuildDirectory+"/docbkx/"+srcFilename);
|
||||
transformer.transform (new StreamSource(coverImageTemplate), new StreamResult(coverImage));
|
||||
}
|
||||
catch (TransformerConfigurationException e)
|
||||
@@ -406,8 +416,10 @@ public abstract class PDFMojo extends AbstractFoMojo {
|
||||
|
||||
map.put("security", security);
|
||||
map.put("canonicalUrlBase", canonicalUrlBase);
|
||||
map.put("replacementsFile", replacementsFile);
|
||||
map.put("failOnValidationError", failOnValidationError);
|
||||
map.put("project.build.directory", this.projectBuildDirectory);
|
||||
map.put("inputSrcFile", inputFilename);
|
||||
//String outputDir=System.getProperty("project.build.outputDirectory ");
|
||||
return CalabashHelper.createSource(source, pathToPipelineFile, map);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
package com.rackspace.cloud.api.docs;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.sf.saxon.s9api.QName;
|
||||
import net.sf.saxon.s9api.SaxonApiException;
|
||||
import net.sf.saxon.s9api.XdmNode;
|
||||
|
||||
import org.apache.maven.plugin.logging.Log;
|
||||
import org.apache.maven.plugin.logging.SystemStreamLog;
|
||||
|
||||
import com.xmlcalabash.core.XProcRuntime;
|
||||
import com.xmlcalabash.io.ReadablePipe;
|
||||
import com.xmlcalabash.io.WritablePipe;
|
||||
import com.xmlcalabash.library.DefaultStep;
|
||||
import com.xmlcalabash.model.RuntimeValue;
|
||||
import com.xmlcalabash.runtime.XAtomicStep;
|
||||
import com.xmlcalabash.util.ProcessMatch;
|
||||
import com.xmlcalabash.util.ProcessMatchingNodes;
|
||||
|
||||
public class ReplaceTextXProcStep extends DefaultStep {
|
||||
private static final QName _replacements_file = new QName("", "replacements.file");
|
||||
private static Pattern XPATH_LINE = Pattern.compile("^XPATH=(.+)$");
|
||||
private static Pattern COMMENT_LINE = Pattern.compile("^#(.+)$");
|
||||
private static Pattern REPLACEMENT_LINE = Pattern.compile("(.+)->(.*)");
|
||||
|
||||
private ReadablePipe source = null;
|
||||
private WritablePipe result = null;
|
||||
private ProcessMatch matcher = null;
|
||||
|
||||
private Log log = null;
|
||||
|
||||
public Log getLog()
|
||||
{
|
||||
if ( log == null )
|
||||
{
|
||||
log = new SystemStreamLog();
|
||||
}
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
|
||||
public ReplaceTextXProcStep(XProcRuntime runtime, XAtomicStep step) {
|
||||
super(runtime,step);
|
||||
}
|
||||
|
||||
public void setInput(String port, ReadablePipe pipe) {
|
||||
source = pipe;
|
||||
}
|
||||
|
||||
public void setOutput(String port, WritablePipe pipe) {
|
||||
result = pipe;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
source.resetReader();
|
||||
result.resetWriter();
|
||||
}
|
||||
|
||||
public void run() throws SaxonApiException {
|
||||
super.run();
|
||||
|
||||
List<XPathReplacement> replacements = readReplacementsFile(getOption(_replacements_file, "replacements.config"));
|
||||
XdmNode updatedDoc = makeReplacements (source.read(), replacements);
|
||||
|
||||
result.write(updatedDoc);
|
||||
}
|
||||
|
||||
private List<XPathReplacement> readReplacementsFile(String fileName) {
|
||||
List<XPathReplacement> xpathReplacements = new ArrayList<XPathReplacement>();
|
||||
XPathReplacement currentXPath = new XPathReplacement("//text()");
|
||||
|
||||
File replacementsFile = new File(fileName);
|
||||
long fileLength = replacementsFile.length();
|
||||
if(fileLength>0){
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
getLog().info("REPLACEMENTS FILE = " + replacementsFile.getAbsolutePath());
|
||||
br = new BufferedReader(new FileReader(replacementsFile));
|
||||
|
||||
String line;
|
||||
while((line = br.readLine()) != null) {
|
||||
Matcher xpathLine = XPATH_LINE.matcher(line);
|
||||
Matcher commentLine = COMMENT_LINE.matcher(line);
|
||||
Matcher replacementLine = REPLACEMENT_LINE.matcher(line);
|
||||
if (xpathLine.matches()) {
|
||||
currentXPath = new XPathReplacement(xpathLine.group(1).trim());
|
||||
xpathReplacements.add(currentXPath);
|
||||
} else if (commentLine.matches()) {
|
||||
/*ignore comment line.
|
||||
* Although this could have been handled in the default else below.
|
||||
* Had to create an explicit case here so that any reference to the token separator "->"
|
||||
* in comments does not cause any issues.
|
||||
*/
|
||||
} else if (replacementLine.matches()) {
|
||||
currentXPath.add(replacementLine.group(1).trim(), replacementLine.group(2).trim());
|
||||
} else {
|
||||
//ignore input line
|
||||
}
|
||||
}
|
||||
|
||||
if (xpathReplacements.size()==0) {
|
||||
getLog().info("SKIPPING REPLACEMENTS: Replacements file is empty or was not found at specified location '"+fileName+ "'.");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
getLog().error("Unable to process replacements config file", e);
|
||||
} finally {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
getLog().error("Unable to release/close replacements config file", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getLog().info("SKIPPING REPLACEMENTS: Replacements file is empty or was not found at specified location '"+fileName+ "'.");
|
||||
}
|
||||
|
||||
return xpathReplacements;
|
||||
}
|
||||
|
||||
private XdmNode makeReplacements(XdmNode doc, List<XPathReplacement> replacements) {
|
||||
for (XPathReplacement xpathRepl : replacements) {
|
||||
matcher = new ProcessMatch(runtime, xpathRepl);
|
||||
xpathRepl.setMatcher(matcher);
|
||||
|
||||
matcher.match(doc, new RuntimeValue(xpathRepl.getXPath()));
|
||||
doc = matcher.getResult();
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
||||
class XPathReplacement implements Iterable<Replacement>, ProcessMatchingNodes {
|
||||
String xpath;
|
||||
List<Replacement> replacements;
|
||||
ProcessMatch matcher;
|
||||
|
||||
public XPathReplacement(String _xpath) {
|
||||
this.xpath = _xpath;
|
||||
replacements = new ArrayList<Replacement>();
|
||||
}
|
||||
|
||||
public String getXPath() {
|
||||
return xpath;
|
||||
}
|
||||
|
||||
public void setMatcher (ProcessMatch matcher) {
|
||||
this.matcher = matcher;
|
||||
}
|
||||
|
||||
public void add(String oldVal, String newVal) {
|
||||
replacements.add(new Replacement(oldVal, newVal));
|
||||
}
|
||||
|
||||
private String computeReplacement(XdmNode node) {
|
||||
String newValue = node.getStringValue();
|
||||
for (Replacement repl : this.replacements) {
|
||||
if(repl.oldValue.startsWith("\"") && repl.oldValue.endsWith("\"")) {
|
||||
newValue = (newValue.replace(repl.oldValue.substring(1,repl.oldValue.length()-1), repl.newValue));
|
||||
} else {
|
||||
newValue = (newValue.replaceAll(repl.oldValue, repl.newValue));
|
||||
}
|
||||
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Replacement> iterator() {
|
||||
return replacements.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processStartDocument(XdmNode node) throws SaxonApiException {
|
||||
return true;//process children
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processEndDocument(XdmNode node) throws SaxonApiException {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processStartElement(XdmNode node) throws SaxonApiException {
|
||||
return true;//process children
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processAttribute(XdmNode node) throws SaxonApiException {
|
||||
String newValue = computeReplacement(node);
|
||||
matcher.addAttribute(node, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processEndElement(XdmNode node) throws SaxonApiException { }
|
||||
|
||||
@Override
|
||||
public void processText(XdmNode node) throws SaxonApiException {
|
||||
String newValue = computeReplacement(node);
|
||||
matcher.addText(newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processComment(XdmNode node) throws SaxonApiException {
|
||||
String newValue = computeReplacement(node);
|
||||
matcher.addText(newValue);}
|
||||
|
||||
@Override
|
||||
public void processPI(XdmNode node) throws SaxonApiException {
|
||||
String newValue = computeReplacement(node);
|
||||
matcher.addText(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
class Replacement {
|
||||
public String oldValue;
|
||||
public String newValue;
|
||||
|
||||
public Replacement(String _oldVal, String _newVal) {
|
||||
this.oldValue = _oldVal;
|
||||
this.newValue = _newVal;
|
||||
}
|
||||
}
|
||||
@@ -158,6 +158,13 @@ public abstract class WebHelpMojo extends AbstractWebhelpMojo {
|
||||
*/
|
||||
private String canonicalUrlBase;
|
||||
|
||||
/**
|
||||
* @parameter
|
||||
* expression="${generate-webhelp.replacementsFile}"
|
||||
* default-value=""
|
||||
*/
|
||||
private String replacementsFile;
|
||||
|
||||
/**
|
||||
*
|
||||
* @parameter
|
||||
@@ -405,8 +412,10 @@ public abstract class WebHelpMojo extends AbstractWebhelpMojo {
|
||||
|
||||
map.put("security", this.security);
|
||||
map.put("canonicalUrlBase", this.canonicalUrlBase);
|
||||
map.put("replacementsFile", this.replacementsFile);
|
||||
map.put("failOnValidationError", this.failOnValidationError);
|
||||
map.put("project.build.directory", this.projectBuildDirectory);
|
||||
map.put("inputSrcFile", inputFilename);
|
||||
|
||||
int lastSlash=inputFilename.lastIndexOf("/");
|
||||
|
||||
|
||||
@@ -254,5 +254,9 @@
|
||||
|
||||
<implementation type="cxu:compare"
|
||||
class-name="com.xmlcalabash.extensions.xmlunit.Compare" />
|
||||
|
||||
<!-- Rackspace Extensions -->
|
||||
<implementation type="cx:replace-text"
|
||||
class-name="com.rackspace.cloud.api.docs.ReplaceTextXProcStep" />
|
||||
|
||||
</xproc-config>
|
||||
|
||||
@@ -406,6 +406,59 @@
|
||||
</p:group>
|
||||
</p:declare-step>
|
||||
|
||||
<p:declare-step
|
||||
xmlns:l="http://xproc.org/library"
|
||||
xml:id="search-and-replace"
|
||||
xmlns:c="http://www.w3.org/ns/xproc-step"
|
||||
type="l:search-and-replace"
|
||||
name="search-and-replace-step">
|
||||
<p:input port="source" primary="true" sequence="true"/>
|
||||
<p:output port="result" sequence="true">
|
||||
<p:pipe step="group" port="result"/>
|
||||
</p:output>
|
||||
|
||||
<p:input port="parameters" kind="parameter"/>
|
||||
<ut:parameters name="params"/>
|
||||
<p:sink/>
|
||||
|
||||
<p:group name="group">
|
||||
<p:output port="result" primary="true">
|
||||
<p:pipe step="replace" port="result"/>
|
||||
</p:output>
|
||||
|
||||
<p:variable name="inputSrcFile" select="//c:param[@name = 'inputSrcFile']/@value">
|
||||
<p:pipe step="params" port="parameters"/>
|
||||
</p:variable>
|
||||
<p:variable name="project.build.directory" select="//c:param[@name = 'project.build.directory']/@value">
|
||||
<p:pipe step="params" port="parameters"/>
|
||||
</p:variable>
|
||||
<p:variable name="replacementsFile" select="//c:param[@name = 'replacementsFile']/@value">
|
||||
<p:pipe step="params" port="parameters"/>
|
||||
</p:variable>
|
||||
<cx:replace-text name="replace">
|
||||
<p:input port="source">
|
||||
<p:pipe step="search-and-replace-step" port="source"/>
|
||||
</p:input>
|
||||
<p:with-option name="replacements.file" select="$replacementsFile">
|
||||
</p:with-option>
|
||||
</cx:replace-text>
|
||||
<p:store encoding="utf-8" indent="true" omit-xml-declaration="false">
|
||||
<p:with-option name="href"
|
||||
select="concat('file://',$project.build.directory,'/docbkx/',$inputSrcFile)"
|
||||
/>
|
||||
</p:store>
|
||||
</p:group>
|
||||
</p:declare-step>
|
||||
|
||||
<!-- Search and replace calabash extension -->
|
||||
<p:declare-step
|
||||
type="cx:replace-text"
|
||||
xml:id="replace-text">
|
||||
<p:input port="source" primary="true" sequence="true"/>
|
||||
<p:output port="result" primary="true" sequence="true"/>
|
||||
<p:option name="replacements.file" cx:type="xsd:string"/>
|
||||
</p:declare-step>
|
||||
|
||||
<!--+========================================================+
|
||||
| Step parameters
|
||||
|
|
||||
@@ -430,5 +483,4 @@
|
||||
</p:input>
|
||||
</p:parameters>
|
||||
</p:declare-step>
|
||||
|
||||
</p:library>
|
||||
@@ -48,6 +48,11 @@
|
||||
|
||||
<l:extensions-info/>
|
||||
|
||||
<cx:message>
|
||||
<p:with-option name="message" select="'Making replacements'"/>
|
||||
</cx:message>
|
||||
<l:search-and-replace/>
|
||||
|
||||
<cx:message>
|
||||
<p:with-option name="message" select="'Normalize wadls'"/>
|
||||
</cx:message>
|
||||
|
||||
Reference in New Issue
Block a user