package org.docx4j.model.fields; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.docx4j.TraversalUtil.CallbackImpl; import org.docx4j.XmlUtils; import org.docx4j.wml.FldChar; import org.docx4j.wml.P; import org.docx4j.wml.STFldCharType; import org.docx4j.wml.SdtBlock; import org.jvnet.jaxb2_commons.ppp.Child; public class ComplexFieldLocator extends CallbackImpl { /** * A list of paragraphs containing field begins. * * If the paragraph contains 2 fields or nested fields, * it will still be listed just once */ List<P> starts = new ArrayList<P>(); public List<P> getStarts() { return starts; } // P currentP; int depth=0; @Override public List<Object> apply(Object o) { // System.out.println(o.getClass().getName()); // if (o instanceof P) { // currentP = (P)o; // } if (o instanceof org.docx4j.wml.FldChar) { FldChar fldChar = (FldChar)o; if (fldChar.getFldCharType().equals(STFldCharType.BEGIN) ) { //System.out.println("Found a BEGIN"); depth++; P currentP = pStack.peek(); if (depth==1 && !starts.contains(currentP)) { starts.add(currentP); // System.out.println("Adding " + XmlUtils.marshaltoString(currentP)); } } if (fldChar.getFldCharType().equals(STFldCharType.END) ) { depth--; } } return null; } /* * Need a paragraph stack, to accommodate: * * <w:p > <w:r> <w:pict> <v:shape stroked="f" o:spid="_x0000_s1026" id="Text Box 2" style="position:absolute;left:0;text-align:left;margin-left:383.8pt;margin-top:-19.9pt;width:117.35pt;height:25.25pt;z-index:251658240;visibility:visible;mso-wrap-style:square;mso-width-percent:0;mso-height-percent:0;mso-wrap-distance-left:9pt;mso-wrap-distance-top:0;mso-wrap-distance-right:9pt;mso-wrap-distance-bottom:0;mso-position-horizontal:absolute;mso-position-horizontal-relative:text;mso-position-vertical:absolute;mso-position-vertical-relative:text;mso-width-percent:0;mso-height-percent:0;mso-width-relative:page;mso-height-relative:page;v-text-anchor:top" type="#_x0000_t202" o:gfxdata="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"> <v:textbox> <w:txbxContent> <w:p> * */ private LinkedList<P> pStack = new LinkedList<P>(); @Override // so we can manage the stack public void walkJAXBElements(Object parent) { if (parent instanceof P) { pStack.push((P)parent); } // Same as superclass: List children = getChildren(parent); if (children != null) { for (Object o : children) { // if its wrapped in javax.xml.bind.JAXBElement, get its // value; this is ok, provided the results of the Callback // won't be marshalled o = XmlUtils.unwrap(o); // workaround for broken getParent (since 3.0.0) if (o instanceof Child) { if (parent instanceof SdtBlock) { ((Child)o).setParent( ((SdtBlock)parent).getSdtContent() ); } else { ((Child)o).setParent(parent); } } this.apply(o); if (this.shouldTraverse(o)) { walkJAXBElements(o); } } } if (parent instanceof P) { pStack.pop(); } } }