org.opendope.conditions.Xpathref Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of docx4j Show documentation
Show all versions of docx4j Show documentation
docx4j is a library which helps you to work with the Office Open
XML file format as used in docx
documents, pptx presentations, and xlsx spreadsheets.
The newest version!
package org.opendope.conditions;
import static org.docx4j.model.datastorage.XPathEnhancerParser.enhanceXPath;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.docx4j.XmlUtils;
import org.docx4j.model.datastorage.BindingHandler;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.CustomXmlPart;
import org.docx4j.openpackaging.parts.opendope.XPathsPart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Java class for anonymous complex type.
*
*
The following schema fragment specifies the expected content contained within this class.
*
*
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <attribute name="id" use="required" type="{http://www.w3.org/2001/XMLSchema}NCName" />
* </restriction>
* </complexContent>
* </complexType>
*
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
@XmlRootElement(name = "xpathref")
public class Xpathref implements Evaluable {
private static Logger log = LoggerFactory.getLogger(Xpathref.class);
@XmlAttribute(required = true)
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
@XmlSchemaType(name = "NCName")
protected String id;
/**
* Gets the value of the id property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getId() {
return id;
}
/**
* Sets the value of the id property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setId(String value) {
this.id = value;
}
public boolean evaluate(WordprocessingMLPackage pkg,
Map customXmlDataStorageParts,
Map conditionsMap,
Map xpathsMap) {
//org.opendope.xpaths.Xpaths.Xpath xpath = XPathsPart.getXPathById(xPaths, id);
org.opendope.xpaths.Xpaths.Xpath xpath = xpathsMap.get(id);
String val = BindingHandler.xpathGetString(pkg,
customXmlDataStorageParts, xpath.getDataBinding()
.getStoreItemID(), xpath.getDataBinding()
.getXpath(), xpath.getDataBinding()
.getPrefixMappings());
return Boolean.parseBoolean(val);
}
public void listXPaths( List theList,
Map conditionsMap,
Map xpathsMap) {
//org.opendope.xpaths.Xpaths.Xpath xpath = XPathsPart.getXPathById(xPaths, id);
org.opendope.xpaths.Xpaths.Xpath xpath = xpathsMap.get(id);
theList.add(xpath);
}
/**
* Map the IDs used in this condition to new values; useful for merging ConditionParts.
*
* @param xpathIdMap
* @param conditionIdMap
* @since 3.0.0
*/
public void mapIds(Map xpathIdMap, Map conditionIdMap) {
if (xpathIdMap==null) return;
String newId = xpathIdMap.get(getId());
if (newId!=null) {
setId(newId);
}
}
public String toString(Map conditionsMap,
Map xpathsMap) {
//org.opendope.xpaths.Xpaths.Xpath xpath = XPathsPart.getXPathById(xPaths, id);
org.opendope.xpaths.Xpaths.Xpath xpath = xpathsMap.get(id);
return xpath.getDataBinding().getXpath();
}
public Condition repeat(String xpathBase,
int index,
Map conditionsMap,
Map xpathsMap) {
// this Xpathref is a clone already,
// but it points to the original xpathObj
//org.opendope.xpaths.Xpaths.Xpath xpathObj = XPathsPart.getXPathById(xPaths, id);
org.opendope.xpaths.Xpaths.Xpath xpathObj = xpathsMap.get(id);
String thisXPath = xpathObj.getDataBinding().getXpath();
int xpathBaseIdx = thisXPath.indexOf(xpathBase);
if (xpathBaseIdx<0) {
// nothing to do
return null;
}
if (thisXPath.trim().startsWith("count") ) {
// we are trying to count rows of the repeat eg
// eg xpath="count(/oda:answers/oda:repeat[@qref='r1_OE']/oda:row[1]/oda:repeat[@qref='r2_d4']/oda:row)<=7"
// or xpath="count(/oda:answers/oda:repeat[@qref='r1_OE']/oda:row)=999"
// We want to enhance EXCEPT for the deepest repeat.
int pos = xpathBaseIdx + xpathBase.length();
String tail = thisXPath.substring(pos);
log.debug("the tail: " + tail);
if (tail.contains("oda:repeat") /* oda:answers XML case */ ) {
// There are deeper repeats in thisXPath than xpathBase, so enhance
log.debug("deeper repeats in count");
} else {
if (tail.contains("/")) {
// There are deeper bits to thisXPath than xpathBase, so enhance normally..
log.debug("deeper bits in count");
} else if (tail.startsWith("[")) {
log.debug("index needs enhancement"); // if you want to count the elements in a repeat, you won't have [1]; having that means something different.
} else if (tail.startsWith(")")) {
log.debug("retaining (repeat count): " + thisXPath); // we want to count elements in the repeat, so don't add an index!
return null;
} else {
log.info("fallback, enhance: " + thisXPath); // for example?
}
}
}
final String newPath = enhanceXPath(xpathBase, index + 1, thisXPath);
if (log.isDebugEnabled() ) {
if (thisXPath.equals(newPath)) {
log.debug("xpath base " + xpathBase + " enhanced NO CHANGE to " + newPath);
} else {
log.debug("xpath " + thisXPath + " enhanced to " + newPath + " using xpath base " + xpathBase);
}
}
// Clone the xpath
org.opendope.xpaths.Xpaths.Xpath newXPathObj = createNewXPathObject(xpathsMap,
newPath, xpathObj, index);
// point this at it
this.id = newXPathObj.getId();
return null;
}
private org.opendope.xpaths.Xpaths.Xpath createNewXPathObject(Map xpathsMap,
String newPath, org.opendope.xpaths.Xpaths.Xpath xpathObj, int index) {
// org.opendope.xpaths.Xpaths.Xpath newXPathObj = XmlUtils.deepCopy(xpathObj);
org.opendope.xpaths.Xpaths.Xpath newXPathObj = new org.opendope.xpaths.Xpaths.Xpath();
String newXPathId = xpathObj.getId() + "_" + index;
newXPathObj.setId(newXPathId);
org.opendope.xpaths.Xpaths.Xpath.DataBinding dataBinding = new org.opendope.xpaths.Xpaths.Xpath.DataBinding();
newXPathObj.setDataBinding(dataBinding);
dataBinding.setXpath(newPath);
dataBinding.setStoreItemID(
xpathObj.getDataBinding().getStoreItemID());
dataBinding.setPrefixMappings(
xpathObj.getDataBinding().getPrefixMappings());
//xPaths.getXpath().add(newXPathObj);
org.opendope.xpaths.Xpaths.Xpath preExistingSanity = xpathsMap.put(newXPathId, newXPathObj);
if (preExistingSanity!=null) {
if (preExistingSanity.getDataBinding().getXpath().equals(newXPathObj.getDataBinding().getXpath())) {
log.debug("Duplicate identical XPath being added: " + newXPathId);
} else {
log.error("Duplicate XPath " + newXPathId + ": "
+ "\n"+ newXPathObj.getDataBinding().getXpath() + " overwriting "
+ "\n"+ preExistingSanity.getDataBinding().getXpath());
}
}
return newXPathObj;
}
}