Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright 2013, Plutext Pty Ltd.
*
* This file is part of docx4j.
docx4j is licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
**/
package org.docx4j.model.datastorage;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBElement;
import org.docx4j.TraversalUtil;
import org.docx4j.TraversalUtil.CallbackImpl;
import org.docx4j.XmlUtils;
import org.docx4j.jaxb.Context;
import org.docx4j.model.sdt.QueryString;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.FooterPart;
import org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart;
import org.docx4j.openpackaging.parts.opendope.XPathsPart;
import org.docx4j.openpackaging.parts.relationships.Namespaces;
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.CTDataBinding;
import org.docx4j.wml.CTSdtText;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.SdtElement;
import org.docx4j.wml.SdtPr;
import org.docx4j.wml.Tag;
import org.jvnet.jaxb2_commons.ppp.Child;
import org.opendope.xpaths.Xpaths.Xpath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Reverse the action of OpenDoPEHandler.
*
* Useful where a user has edited an instance docx,
* but you want to regenerate with fresh XML data.
*
* This won't work if RemovalHandler has been used to
* removed the content controls.
*
* Note that any edits made by hand within a condition
* or repeat will be lost, so it is recommended
* that after regenerating from this reverted template,
* you do a document compare (eg in Word) against your
* previous instance to pick up any edits in a condition
* or repeat which this process will have dropped).
*
* This class modifies the instance, so you'll need
* to clone or copy it first if that's a problem.
*
* @author jharrop
*
*/
public class OpenDoPEReverter {
private static Logger log = LoggerFactory.getLogger(OpenDoPEReverter.class);
private WordprocessingMLPackage openDopePkg;
private WordprocessingMLPackage instancePkg;
public OpenDoPEReverter(WordprocessingMLPackage openDopePkg, WordprocessingMLPackage instancePkg) {
this.openDopePkg = openDopePkg;
this.instancePkg = instancePkg;
}
/*
Algorithm:
- find top level repeat/condition controls in template docx
part by part:-
- traverse instance, making 2 lists
+ sdt to be replaced (first encounter)
+ sdt to be deleted
then do the replacement
What about the case where the one repeat is used twice? That's ok, as long as there is some
other object between the two lots of repeats.
Limitation: The user could screw this up, by manually inserting a paragraph between 2 instances of
a repeat. Result would be that an instance is kept, and converted back into an extra repeat!
So have a sanity check that count of repeats and conditions in result matches what we
have in the original template.
A user could also delete a condition/repeat sdt entirely, in which case it won't get reverted.
Add option to lock it to prevent this from happening?
*/
Map templateConditionSdtsByID = new HashMap();
Map templateRepeatSdtsByID = new HashMap();
public boolean revert() throws Docx4JException {
// template docx:- find top level repeat/condition controls
TopLevelSdtTemplateFinder sdtPrFinder = new TopLevelSdtTemplateFinder(false);
findSdtsInTemplate(openDopePkg, sdtPrFinder);
templateConditionSdtsByID = sdtPrFinder.conditionSdtsByID;
templateRepeatSdtsByID = sdtPrFinder.repeatSdtsByID;
// instance docx:-
handleSdtsInInstance();
return sanityCheck();
}
/**
What about the case where the one repeat is used twice? That's ok, as long as there is some
other object between the two lots of repeats.
Limitation: The user could screw this up, by manually inserting a paragraph between 2 instances of
a repeat. Result would be that an instance is kept, and converted back into an extra repeat!
So have a sanity check that count of repeats and conditions in result matches what we
have in the original template.
*/
private boolean sanityCheck() throws Docx4JException {
int expectedConditions = templateConditionSdtsByID.size();
int expectedRepeats = templateRepeatSdtsByID.size();
TopLevelSdtTemplateFinder sdtPrFinder = new TopLevelSdtTemplateFinder(true);
findSdtsInTemplate(instancePkg, sdtPrFinder); // feed the instance through here to count (not bothering to count plain binds)
boolean resultC = sdtPrFinder.conditionSdtsByID.size() == expectedConditions;
if (!resultC) {
log.error("Restored " + sdtPrFinder.conditionSdtsByID.size() + " condition SDTs but expected " + expectedConditions);
}
boolean resultR = sdtPrFinder.repeatSdtsByID.size() == expectedRepeats;
if (!resultR) {
log.error("Restored " + sdtPrFinder.repeatSdtsByID.size() + " repeat SDTs but expected " + expectedRepeats);
}
return (resultC && resultR);
}
// ======================================================================================
// ====== openDopePkg template stuff
private void findSdtsInTemplate(WordprocessingMLPackage pkg, TopLevelSdtTemplateFinder sdtPrFinder) throws Docx4JException {
findSdtsInTemplatePart(pkg.getMainDocumentPart(), sdtPrFinder);
// Add headers/footers
RelationshipsPart rp = pkg.getMainDocumentPart()
.getRelationshipsPart();
for (Relationship r : rp.getRelationships().getRelationship()) {
if (r.getType().equals(Namespaces.HEADER)) {
findSdtsInTemplatePart((HeaderPart) rp.getPart(r), sdtPrFinder);
} else if (r.getType().equals(Namespaces.FOOTER)) {
findSdtsInTemplatePart((FooterPart) rp.getPart(r), sdtPrFinder);
}
}
}
private void findSdtsInTemplatePart(ContentAccessor content, TopLevelSdtTemplateFinder sdtPrFinder) throws Docx4JException {
new TraversalUtil(content.getContent(), sdtPrFinder);
}
private static class TopLevelSdtTemplateFinder extends CallbackImpl {
private boolean instanceCountOnly;
TopLevelSdtTemplateFinder(boolean instanceCountOnly) {
this.instanceCountOnly = instanceCountOnly;
}
// Separate map for each
// Maps are by SDT ID, since 2 distinct SDT could use the one condition or repeat
Map conditionSdtsByID = new HashMap();
Map repeatSdtsByID = new HashMap();
@Override
public List