/* recursively (i) create new Parts for each thing listed in the relationships (ii) add the new Part to the package (iii) cross the PartName off unusedZipEntries */ private void addPartsFromRelationships(Base source, RelationshipsPart rp, ContentTypeManager ctm) throws Docx4JException { OpcPackage pkg = source.getPackage(); for (Relationship r : rp.getRelationships().getRelationship()) { log.debug( "\n For Relationship Id=" + r.getId() + " Source is " + rp.getSourceP().getPartName() + ", Target is " + r.getTarget() + ", type: " + r.getType()); // This is usually the first logged comment for // a part, so start with a line break. try { getPart(pkg, rp, r, ctm); } catch (Exception e) { throw new Docx4JException("Failed to add parts from relationships", e); } } }
/** * Creates document header including process name * * @param doc WordprocessingMLPackage for the document. * @throws InvalidFormatException */ private void createHeader(WordprocessingMLPackage doc) throws InvalidFormatException { MainDocumentPart content = doc.getMainDocumentPart(); // Create header HeaderPart header = new HeaderPart(); Relationship rel = content.addTargetPart(header); Hdr hdr = objectFactory.createHdr(); P headerParagraph = content.createParagraphOfText(p.getTitle()); hdr.getContent().add(headerParagraph); header.setJaxbElement(hdr); setStyle(headerParagraph, "Header"); alignParagraph(headerParagraph, JcEnumeration.CENTER); // Relate to document List<SectionWrapper> sections = doc.getDocumentModel().getSections(); SectPr sectPr = sections.get(sections.size() - 1).getSectPr(); if (null == sectPr) { sectPr = objectFactory.createSectPr(); content.addObject(sectPr); sections.get(sections.size() - 1).setSectPr(sectPr); } HeaderReference headerReference = objectFactory.createHeaderReference(); headerReference.setId(rel.getId()); headerReference.setType(HdrFtrRef.DEFAULT); sectPr.getEGHdrFtrReferences().add(headerReference); }
/** * Nastaví záhlaví dokumentu. Úprava předchozí funkce. * * @param irPackage * @throws InvalidFormatException */ private Ftr SetupFooter(WordprocessingMLPackage irPackage) throws InvalidFormatException { ObjectFactory lrFactory = Context.getWmlObjectFactory(); /* create header part */ FooterPart lrFooterPart = new FooterPart(); lrFooterPart.setPackage(irPackage); Ftr lrFooter = lrFactory.createFtr(); lrFooterPart.setJaxbElement(lrFooter); Relationship lrRelationship = irPackage.getMainDocumentPart().addTargetPart(lrFooterPart); /* end create header part */ /* create header reference */ List<SectionWrapper> lrSections = irPackage.getDocumentModel().getSections(); SectPr lrSectionPr = lrSections.get(lrSections.size() - 1).getSectPr(); // There is always a section wrapper, but it might not contain a sectPr if (lrSectionPr == null) { lrSectionPr = lrFactory.createSectPr(); irPackage.getMainDocumentPart().addObject(lrSectionPr); lrSections.get(lrSections.size() - 1).setSectPr(lrSectionPr); } FooterReference lrFooterReference = lrFactory.createFooterReference(); lrFooterReference.setId(lrRelationship.getId()); lrFooterReference.setType(HdrFtrRef.DEFAULT); lrSectionPr.getEGHdrFtrReferences().add(lrFooterReference); // add header or footer references /* end create header reference */ return lrFooter; }
/** * Creates document footer including page number * * @param doc WordprocessingMLPackage for the document. * @throws InvalidFormatException */ private void createFooter(WordprocessingMLPackage doc) throws InvalidFormatException { MainDocumentPart content = doc.getMainDocumentPart(); // Create footer FooterPart footer = new FooterPart(); Ftr ftr = objectFactory.createFtr(); P footerParagraph = objectFactory.createP(); setStyle(footerParagraph, "footer"); PPr parProps = objectFactory.createPPr(); Jc al = objectFactory.createJc(); al.setVal(JcEnumeration.RIGHT); parProps.setJc(al); footerParagraph.setPPr(parProps); // Add field start R run = objectFactory.createR(); FldChar fldChar = objectFactory.createFldChar(); fldChar.setFldCharType(STFldCharType.BEGIN); run.getContent().add(fldChar); footerParagraph.getContent().add(run); // Add pageNumber field run = objectFactory.createR(); Text txt = objectFactory.createText(); txt.setSpace("preserve"); txt.setValue(" PAGE \\* MERGEFORMAT "); run.getContent().add(objectFactory.createRInstrText(txt)); footerParagraph.getContent().add(run); // Add field end run = objectFactory.createR(); fldChar = objectFactory.createFldChar(); fldChar.setFldCharType(STFldCharType.END); run.getContent().add(fldChar); footerParagraph.getContent().add(run); ftr.getContent().add(footerParagraph); footer.setJaxbElement(ftr); Relationship rel = content.addTargetPart(footer); // Relate footer to document List<SectionWrapper> sections = doc.getDocumentModel().getSections(); SectPr sectPr = sections.get(sections.size() - 1).getSectPr(); if (null == sectPr) { sectPr = objectFactory.createSectPr(); content.addObject(sectPr); sections.get(sections.size() - 1).setSectPr(sectPr); } FooterReference footerReference = objectFactory.createFooterReference(); footerReference.setId(rel.getId()); footerReference.setType(HdrFtrRef.DEFAULT); sectPr.getEGHdrFtrReferences().add(footerReference); }
protected static void removeDefinedCustomXmlParts( WordprocessingMLPackage wmlPackage, String xpathStorageItemId) { List<PartName> partsToRemove = new ArrayList<PartName>(); RelationshipsPart relationshipsPart = wmlPackage.getMainDocumentPart().getRelationshipsPart(); List<Relationship> relationshipsList = ((relationshipsPart != null) && (relationshipsPart.getRelationships() != null) ? relationshipsPart.getRelationships().getRelationship() : null); Part part = null; CustomXmlDataStoragePart dataPart = null; if (relationshipsList != null) { for (Relationship relationship : relationshipsList) { if (Namespaces.CUSTOM_XML_DATA_STORAGE.equals(relationship.getType())) { part = relationshipsPart.getPart(relationship); if (IsPartToRemove(part, xpathStorageItemId)) { partsToRemove.add(part.getPartName()); } } } } if (!partsToRemove.isEmpty()) { for (int i = 0; i < partsToRemove.size(); i++) { relationshipsPart.removePart(partsToRemove.get(i)); } } }
private static void addPartsForRels( List<Alteration> list, List<Relationship> rels, RelationshipsPart rp) throws Docx4JException { for (Relationship r : rels) { if (r.getTargetMode() != null && r.getTargetMode().equals("External")) { log.debug(r.getTarget() + " is external"); // Have everything we need info wise in transmitting the rels part } else { list.add(new Alteration(rp, toStorageFormat(rp.getPart(r)))); log.debug("added part: " + r.getTarget()); } } }
// private void addPartsFromRelationships(ZipFile zf, Base source, RelationshipsPart rp) private void addPartsFromRelationships( HashMap<String, ByteArray> partByteArrays, Base source, RelationshipsPart rp, ContentTypeManager ctm) throws Docx4JException { OpcPackage pkg = source.getPackage(); // for (Iterator it = rp.iterator(); it.hasNext(); ) { // Relationship r = (Relationship)it.next(); // log.info("For Relationship Id=" + r.getId() + " Source is " // + r.getSource().getPartName() // + ", Target is " + r.getTargetURI() ); // try { // // getPart(zf, pkg, rp, r); // // } catch (Exception e) { // throw new Docx4JException("Failed to add parts from relationships", e); // } // } for (Relationship r : rp.getRelationships().getRelationship()) { log.debug( "\n For Relationship Id=" + r.getId() + " Source is " + rp.getSourceP().getPartName() + ", Target is " + r.getTarget() + ", type: " + r.getType()); // This is usually the first logged comment for // a part, so start with a line break. try { getPart(partByteArrays, pkg, rp, r, ctm); } catch (Exception e) { throw new Docx4JException("Failed to add parts from relationships", e); } } }
protected static Set<ContentAccessor> getParts(WordprocessingMLPackage srcPackage) { Set<ContentAccessor> partList = new HashSet<ContentAccessor>(); partList.add(srcPackage.getMainDocumentPart()); // Add headers/footers RelationshipsPart rp = srcPackage.getMainDocumentPart().getRelationshipsPart(); for (Relationship r : rp.getRelationships().getRelationship()) { if (r.getType().equals(Namespaces.HEADER)) { partList.add((HeaderPart) rp.getPart(r)); } else if (r.getType().equals(Namespaces.FOOTER)) { partList.add((FooterPart) rp.getPart(r)); } } return partList; }
protected static boolean IsPartToRemove(Part part, String xpathStorageItemId) { boolean ret = false; RelationshipsPart relationshipsPart = part.getRelationshipsPart(); List<Relationship> relationshipsList = ((relationshipsPart != null) && (relationshipsPart.getRelationships() != null) ? relationshipsPart.getRelationships().getRelationship() : null); CustomXmlDataStoragePropertiesPart propertiesPart = null; DatastoreItem datastoreItem = null; if ((relationshipsList != null) && (!relationshipsList.isEmpty())) { for (Relationship relationship : relationshipsList) { if (Namespaces.CUSTOM_XML_DATA_STORAGE_PROPERTIES.equals(relationship.getType())) { propertiesPart = (CustomXmlDataStoragePropertiesPart) relationshipsPart.getPart(relationship); break; } } } if (propertiesPart != null) { datastoreItem = propertiesPart.getJaxbElement(); } if (datastoreItem != null) { if ((datastoreItem.getItemID() != null) && (datastoreItem.getItemID().length() > 0)) { ret = datastoreItem.getItemID().equals(xpathStorageItemId); } if ((!ret) && (datastoreItem.getSchemaRefs() != null) && (datastoreItem.getSchemaRefs().getSchemaRef() != null) && (!datastoreItem.getSchemaRefs().getSchemaRef().isEmpty())) { for (SchemaRef ref : datastoreItem.getSchemaRefs().getSchemaRef()) { if (PART_TO_REMOVE_SCHEMA_TYPES.contains(ref.getUri())) { ret = true; break; } } } } return ret; }
/** * @param alteredParts * @param theseRels * @throws Docx4JException */ private static void addTree(List<Alteration> list, RelationshipsPart rp) throws Docx4JException { if (rp == null) return; for (Relationship r : rp.getJaxbElement().getRelationship()) { if (r.getTargetMode() != null && r.getTargetMode().equals("External")) { log.debug(r.getTarget() + " is external"); // Have everything we need info wise in transmitting the rels part } else { list.add(new Alteration(rp, toStorageFormat(rp.getPart(r)))); log.debug("add tree: " + r.getTarget()); // recurse Part nextSourcePart = rp.getPart(r); RelationshipsPart nextRP = nextSourcePart.getRelationshipsPart(); if (nextRP != null) { list.add(new Alteration(nextSourcePart.getPartName(), toStorageFormat(nextRP))); addTree(list, nextRP); } } } }
public org.docx4j.wml.P.Hyperlink newHyperlink(MainDocumentPart mdp, String text, String url) { try { // We need to add a relationship to word/_rels/document.xml.rels but since its external, we // don't use // the usual wordMLPackage.getMainDocumentPart().addTargetPart mechanism org.docx4j.relationships.ObjectFactory factory = new org.docx4j.relationships.ObjectFactory(); org.docx4j.relationships.Relationship rel = factory.createRelationship(); rel.setType(Namespaces.HYPERLINK); rel.setTarget(url); rel.setTargetMode("External"); mdp.getRelationshipsPart().addRelationship(rel); // addRelationship sets the rel's @Id org.docx4j.wml.P.Hyperlink hyp = new org.docx4j.wml.P.Hyperlink(); hyp.setId(rel.getId()); R run = Context.getWmlObjectFactory().createR(); hyp.getContent().add(run); RPr rpr = new RPr(); RStyle rStyle = new RStyle(); rStyle.setVal("Hyperlink"); rpr.setRStyle(rStyle); run.setRPr(rpr); Text t = new Text(); t.setValue(text); run.getContent().add(t); // String hpl = "<w:hyperlink r:id=\"" + rel.getId() // + "\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" " // + "xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" >" + // "<w:r>" + "<w:rPr>" // + "<w:rStyle w:val=\"Hyperlink\" />" + // "</w:rPr>" + "<w:t>" + text + "</w:t>" + "</w:r>" + "</w:hyperlink>"; // return (org.docx4j.wml.P.Hyperlink) XmlUtils.unmarshalString(hpl); return hyp; } catch (Exception e) { e.printStackTrace(); return null; } }
private void createFooterReference( WordprocessingMLPackage wordprocessingMLPackage, Relationship relationship) throws InvalidFormatException { List<SectionWrapper> sections = wordprocessingMLPackage.getDocumentModel().getSections(); SectPr sectPr = sections.get(sections.size() - 1).getSectPr(); // There is always a section wrapper, but it might not contain a sectPr if (sectPr == null) { sectPr = factory.createSectPr(); wordprocessingMLPackage.getMainDocumentPart().addObject(sectPr); sections.get(sections.size() - 1).setSectPr(sectPr); } FooterReference footerReference = factory.createFooterReference(); footerReference.setId(relationship.getId()); footerReference.setType(HdrFtrRef.DEFAULT); sectPr.getEGHdrFtrReferences().add(footerReference); }
public static void visit( WordprocessingMLPackage wmlPackage, boolean bodyOnly, Callback callback) { MainDocumentPart mainDocument = null; RelationshipsPart relPart = null; List<Relationship> relList = null; List<Object> elementList = null; if ((wmlPackage != null) && (callback != null)) { mainDocument = wmlPackage.getMainDocumentPart(); callback.walkJAXBElements(mainDocument.getJaxbElement().getBody()); if (!bodyOnly) { relPart = mainDocument.getRelationshipsPart(); relList = relPart.getRelationships().getRelationship(); for (Relationship rs : relList) { elementList = null; if (Namespaces.HEADER.equals(rs.getType())) { elementList = ((HeaderPart) relPart.getPart(rs)).getJaxbElement().getContent(); } else if (Namespaces.FOOTER.equals(rs.getType())) { elementList = ((FooterPart) relPart.getPart(rs)).getJaxbElement().getContent(); } else if (Namespaces.ENDNOTES.equals(rs.getType())) { // elementList = ((EndnotesPart) relPart.getPart(rs)).getContent(); elementList = new ArrayList(); elementList.addAll(((EndnotesPart) relPart.getPart(rs)).getJaxbElement().getEndnote()); } else if (Namespaces.FOOTNOTES.equals(rs.getType())) { // elementList = ((FootnotesPart) relPart.getPart(rs)).getContent(); elementList = new ArrayList(); elementList.addAll( ((FootnotesPart) relPart.getPart(rs)).getJaxbElement().getFootnote()); } else if (Namespaces.COMMENTS.equals(rs.getType())) { elementList = new ArrayList(); for (Comment comment : ((CommentsPart) relPart.getPart(rs)).getJaxbElement().getComment()) { elementList.addAll(comment.getEGBlockLevelElts()); } } if ((elementList != null) && (!elementList.isEmpty())) { log.debug("Processing target: " + rs.getTarget() + ", type: " + rs.getType()); callback.walkJAXBElements(elementList); } } } } }
/* recursively (i) get each Part listed in the relationships (ii) add the Part to the zip file (iii) traverse its relationship */ public void addPartsFromRelationships(ZipOutputStream out, RelationshipsPart rp) throws Docx4JException { // for (Iterator it = rp.iterator(); it.hasNext(); ) { // Relationship r = (Relationship)it.next(); // log.info("For Relationship Id=" + r.getId() + " Source is " + r.getSource().getPartName() + // ", Target is " + r.getTargetURI() ); for (Relationship r : rp.getRelationships().getRelationship()) { log.debug( "For Relationship Id=" + r.getId() + " Source is " + rp.getSourceP().getPartName() + ", Target is " + r.getTarget()); if (r.getType().equals(Namespaces.HYPERLINK)) { continue; // whether internal or external } if (r.getTargetMode() != null && r.getTargetMode().equals("External")) { // ie its EXTERNAL // As at 1 May 2008, we don't have a Part for these; // there is just the relationship. log.warn("Encountered external resource " + r.getTarget() + " of type " + r.getType()); // So continue; } try { // String resolvedPartUri = URIHelper.resolvePartUri(r.getSourceURI(), r.getTargetURI() // ).toString(); String resolvedPartUri = URIHelper.resolvePartUri(rp.getSourceURI(), new URI(r.getTarget())).toString(); // Now drop leading "/' resolvedPartUri = resolvedPartUri.substring(1); // Now normalise it .. ie abc/def/../ghi // becomes abc/ghi // Maybe this isn't necessary with a zip file, // - ZipFile class may be smart enough to do it. // But it is certainly necessary in the JCR case. // target = (new java.net.URI(target)).normalize().toString(); // log.info("Normalised, it is " + target ); // Document contents = getDocumentFromZippedPart( zf, target); if (!false) { log.debug("Getting part /" + resolvedPartUri); // Part part = p.getParts().get(new PartName("/" + resolvedPartUri)); Part part = rp.getPart(r); // 2012 09 26: If the part is actually attached to // a different package, using this you can still get it. // Use this 'feature' at your own risk! if (part == null) { log.error("Part " + resolvedPartUri + " not found!"); } else { log.debug(part.getClass().getName()); } if (!part.getPackage().equals(p)) { log.warn("Part " + resolvedPartUri + " is attached to some other package"); } savePart(out, part); } } catch (Exception e) { throw new Docx4JException( "Failed to add parts from relationships of " + rp.getSourceP().getPartName(), e); } } }
/** * Get a Part (except a relationships part), but not its relationships part or related parts. * Useful if you need quick access to just this part. This can be called directly from outside the * library, in which case the Part will not be owned by a Package until the calling code makes it * so. * * @see To get a Part and all its related parts, and add all to a package, use getPart. * @param partByteArrays * @param ctm * @param resolvedPartUri * @param rel * @return * @throws Docx4JException including if result is null */ public Part getRawPart(ContentTypeManager ctm, String resolvedPartUri, Relationship rel) throws Docx4JException { Part part = null; InputStream is = null; try { try { log.debug("resolved uri: " + resolvedPartUri); // Get a subclass of Part appropriate for this content type // This will throw UnrecognisedPartException in the absence of // specific knowledge. Hence it is important to get the is // first, as we do above. part = ctm.getPart("/" + resolvedPartUri, rel); log.info("ctm returned " + part.getClass().getName()); if (part instanceof org.docx4j.openpackaging.parts.ThemePart || part instanceof org.docx4j.openpackaging.parts.DocPropsCorePart || part instanceof org.docx4j.openpackaging.parts.DocPropsCustomPart || part instanceof org.docx4j.openpackaging.parts.DocPropsExtendedPart || part instanceof org.docx4j.openpackaging.parts.CustomXmlDataStoragePropertiesPart || part instanceof org.docx4j.openpackaging.parts.digitalsignature.XmlSignaturePart || part instanceof org.docx4j.openpackaging.parts.JaxbXmlPart) { // Nothing to do here } else if (part instanceof org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart) { log.debug("Detected BinaryPart " + part.getClass().getName()); // is = partStore.loadPart( resolvedPartUri); // ((BinaryPart)part).setBinaryData(is); } else if (part instanceof org.docx4j.openpackaging.parts.CustomXmlDataStoragePart) { // ContentTypeManager initially detects them as CustomXmlDataStoragePart; // the below changes as necessary // Is it a part we know? is = partStore.loadPart(resolvedPartUri); try { Unmarshaller u = Context.jc.createUnmarshaller(); Object o = u.unmarshal(is); log.debug(o.getClass().getName()); PartName name = part.getPartName(); if (o instanceof CoverPageProperties) { part = new DocPropsCoverPagePart(name); ((DocPropsCoverPagePart) part).setJaxbElement((CoverPageProperties) o); } else if (o instanceof org.opendope.conditions.Conditions) { part = new ConditionsPart(name); ((ConditionsPart) part).setJaxbElement((org.opendope.conditions.Conditions) o); } else if (o instanceof org.opendope.xpaths.Xpaths) { part = new XPathsPart(name); ((XPathsPart) part).setJaxbElement((org.opendope.xpaths.Xpaths) o); } else if (o instanceof org.opendope.questions.Questionnaire) { part = new QuestionsPart(name); ((QuestionsPart) part).setJaxbElement((org.opendope.questions.Questionnaire) o); } else if (o instanceof org.opendope.answers.Answers) { part = new StandardisedAnswersPart(name); ((StandardisedAnswersPart) part).setJaxbElement((org.opendope.answers.Answers) o); } else if (o instanceof org.opendope.components.Components) { part = new ComponentsPart(name); ((ComponentsPart) part).setJaxbElement((org.opendope.components.Components) o); } else if (o instanceof JAXBElement<?> && XmlUtils.unwrap(o) instanceof org.docx4j.bibliography.CTSources) { part = new BibliographyPart(name); ((BibliographyPart) part) .setJaxbElement((JAXBElement<org.docx4j.bibliography.CTSources>) o); } else { log.error("TODO: handle known CustomXmlPart part " + o.getClass().getName()); CustomXmlDataStorage data = getCustomXmlDataStorageClass().factory(); is.reset(); data.setDocument(is); // Not necessarily JAXB, that's just our method name ((org.docx4j.openpackaging.parts.CustomXmlDataStoragePart) part).setData(data); } } catch (javax.xml.bind.UnmarshalException ue) { log.warn("No JAXB model for this CustomXmlDataStorage part; " + ue.getMessage()); CustomXmlDataStorage data = getCustomXmlDataStorageClass().factory(); is.reset(); data.setDocument(is); // Not necessarily JAXB, that's just our method name ((org.docx4j.openpackaging.parts.CustomXmlDataStoragePart) part).setData(data); } } else if (part instanceof org.docx4j.openpackaging.parts.XmlPart) { is = partStore.loadPart(resolvedPartUri); // try { ((XmlPart) part).setDocument(is); // Experimental 22/6/2011; don't fall back to binary (which we used to) // } catch (Docx4JException d) { // // This isn't an XML part after all, // // even though ContentTypeManager detected it as such // // So get it as a binary part // part = getBinaryPart(partByteArrays, ctm, resolvedPartUri); // log.warn("Could not parse as XML, so using BinaryPart for " // + resolvedPartUri); // ((BinaryPart)part).setBinaryData(is); // } } else { // Shouldn't happen, since ContentTypeManagerImpl should // return an instance of one of the above, or throw an // Exception. log.error("No suitable part found for: " + resolvedPartUri); part = null; } } catch (PartUnrecognisedException e) { log.error("PartUnrecognisedException shouldn't happen anymore!", e); // Try to get it as a binary part part = getBinaryPart(ctm, resolvedPartUri); log.warn("Using BinaryPart for " + resolvedPartUri); // is = partStore.loadPart( resolvedPartUri); // ((BinaryPart)part).setBinaryData(is); } } catch (Exception ex) { // IOException, URISyntaxException ex.printStackTrace(); throw new Docx4JException("Failed to getPart", ex); } finally { IOUtils.closeQuietly(is); } if (part == null) { throw new Docx4JException( "cannot find part " + resolvedPartUri + " from rel " + rel.getId() + "=" + rel.getTarget()); } return part; }
/** * Get a Part (except a relationships part), and all its related parts. This can be called * directly from outside the library, in which case the Part will not be owned by a Package until * the calling code makes it so. * * @param zf * @param source * @param unusedZipEntries * @param pkg * @param r * @param resolvedPartUri * @throws Docx4JException * @throws InvalidFormatException */ private void getPart(OpcPackage pkg, RelationshipsPart rp, Relationship r, ContentTypeManager ctm) throws Docx4JException, InvalidFormatException, URISyntaxException { Base source = null; String resolvedPartUri = null; if (r.getType().equals(Namespaces.HYPERLINK)) { // Could be Internal or External // Example of Internal is w:drawing/wp:inline/wp:docPr/a:hlinkClick log.info("Encountered (but not loading) hyperlink " + r.getTarget()); return; } else if (r.getTargetMode() == null || !r.getTargetMode().equals("External")) { // Usual case source = rp.getSourceP(); resolvedPartUri = URIHelper.resolvePartUri(rp.getSourceURI(), new URI(r.getTarget())).toString(); // Now drop leading "/' resolvedPartUri = resolvedPartUri.substring(1); // Now normalise it .. ie abc/def/../ghi // becomes abc/ghi // Maybe this isn't necessary with a zip file, // - ZipFile class may be smart enough to do it. // But it is certainly necessary in the JCR case. // resolvedPartUri = (new java.net.URI(resolvedPartUri)).normalize().toString(); // log.info("Normalised, it is " + resolvedPartUri ); } else { // EXTERNAL if (loadExternalTargets && r.getType().equals(Namespaces.IMAGE)) { // It could instead be, for example, of type hyperlink, // and we don't want to try to fetch that log.info("Loading external resource " + r.getTarget() + " of type " + r.getType()); BinaryPart bp = ExternalResourceUtils.getExternalResource(r.getTarget()); pkg.getExternalResources().put(bp.getExternalTarget(), bp); } else { log.info( "Encountered (but not loading) external resource " + r.getTarget() + " of type " + r.getType()); } return; } String relationshipType = r.getType(); Part part; if (pkg.handled.get(resolvedPartUri) != null) { // The source Part (or Package) might have a convenience // method for this part = pkg.getParts().getParts().get(new PartName("/" + resolvedPartUri)); if (source.setPartShortcut(part, relationshipType)) { log.debug( "Convenience method established from " + source.getPartName() + " to " + part.getPartName()); } return; } part = getRawPart(ctm, resolvedPartUri, r); // will throw exception if null // The source Part (or Package) might have a convenience // method for this if (source.setPartShortcut(part, relationshipType)) { log.debug( "Convenience method established from " + source.getPartName() + " to " + part.getPartName()); } if (part instanceof BinaryPart || part instanceof DefaultXmlPart) { // The constructors of other parts should take care of this... part.setRelationshipType(relationshipType); } rp.loadPart(part, r); pkg.handled.put(resolvedPartUri, resolvedPartUri); // unusedZipEntries.put(resolvedPartUri, new Boolean(false)); RelationshipsPart rrp = getRelationshipsPart(part); if (rrp != null) { // recurse via this parts relationships, if it has any addPartsFromRelationships(part, rrp, ctm); String relPart = PartName.getRelationshipsPartName(part.getPartName().getName().substring(1)); // unusedZipEntries.put(relPart, new Boolean(false)); } }
public static void recurse( Alterations alterations, RelationshipsPart thisRP, RelationshipsPart otherRP) throws Docx4JException { log.info("######### @" + thisRP.partName.getName() + "#########"); log.info("uniques -------"); List<Relationship> uniques = thisRP.uniqueToThis(otherRP); addPartsForRels(alterations.getPartsAdded(), uniques, thisRP); List<Relationship> missings = thisRP.uniqueToOther(otherRP); addPartsForRels(alterations.getPartsDeleted(), missings, otherRP); // is this rels part itself altered? if (!thisRP.isContentEqual(otherRP)) { alterations.getPartsModified().add(new Alteration(thisRP, toStorageFormat(thisRP))); } log.info("content -------"); List<Relationship> altered = thisRP.differingContent(otherRP); addPartsForRels(alterations.getPartsModified(), altered, thisRP); // Now recurse all rels log.info("recurse ------- "); for (Relationship r : thisRP.getJaxbElement().getRelationship()) { if (r.getTargetMode() != null && r.getTargetMode().equals("External")) { // do nothing } else { if (uniques.contains(r)) { // add tree, including any external parts // (we already have the part itself) addTree(alterations.getPartsAdded(), thisRP.getPart(r).getRelationshipsPart()); } else if (missings.contains(r)) { addTree(alterations.getPartsDeleted(), thisRP.getPart(r).getRelationshipsPart()); } else { // its present in both trees. // irrespective of whether content of part is the same, content of a rel could still have // changed Part thisPart = thisRP.getPart(r); Part otherPart = otherRP.getPart(RelationshipsPart.getRelationshipByTarget(otherRP, r.getTarget())); if (thisPart.getRelationshipsPart() == null) { if (otherPart.getRelationshipsPart() != null) { // add tree, including any external parts alterations .getPartsDeleted() .add( new Alteration( thisPart.getPartName(), toStorageFormat(thisPart.getRelationshipsPart()))); addTree(alterations.getPartsDeleted(), thisPart.getRelationshipsPart()); } } else { if (otherPart.getRelationshipsPart() == null) { // add tree, including any external parts alterations .getPartsAdded() .add( new Alteration( thisPart.getPartName(), toStorageFormat(thisPart.getRelationshipsPart()))); addTree(alterations.getPartsAdded(), thisPart.getRelationshipsPart()); } else { recurse( alterations, thisPart.getRelationshipsPart(), otherPart.getRelationshipsPart()); } } } } } }
private WordprocessingMLPackage fetchComponents( WordprocessingMLPackage srcPackage, ContentAccessor contentAccessor) throws Docx4JException { // convert components to altChunk Map<Integer, CTAltChunk> replacements = new HashMap<Integer, CTAltChunk>(); Integer index = 0; justGotAComponent = false; LinkedList<Integer> continuousBeforeIndex = new LinkedList<Integer>(); List<Boolean> continuousBefore = new ArrayList<Boolean>(); List<Boolean> continuousAfter = new ArrayList<Boolean>(); for (Object block : contentAccessor.getContent()) { // Object ublock = XmlUtils.unwrap(block); if (block instanceof org.docx4j.wml.SdtBlock) { org.docx4j.wml.SdtBlock sdt = (org.docx4j.wml.SdtBlock) block; Tag tag = getSdtPr(sdt).getTag(); if (tag == null) { List<Object> newContent = new ArrayList<Object>(); newContent.add(sdt); continue; } log.info(tag.getVal()); HashMap<String, String> map = QueryString.parseQueryString(tag.getVal(), true); String componentId = map.get(BINDING_ROLE_COMPONENT); if (componentId == null) continue; // Convert the sdt to a w:altChunk // .. get the IRI String iri = ComponentsPart.getComponentById(components, componentId).getIri(); log.debug("Fetching " + iri); if (docxFetcher == null) { log.error("You need a docxFetcher (and the MergeDocx extension) to fetch components"); return srcPackage; } // .. create the part AlternativeFormatInputPart afiPart = new AlternativeFormatInputPart( getNewPartName( "/chunk", ".docx", srcPackage.getMainDocumentPart().getRelationshipsPart())); afiPart.setBinaryData(docxFetcher.getDocxFromIRI(iri)); afiPart.setContentType( new ContentType( "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")); // docx Relationship altChunkRel = srcPackage.getMainDocumentPart().addTargetPart(afiPart); CTAltChunk ac = Context.getWmlObjectFactory().createCTAltChunk(); ac.setId(altChunkRel.getId()); replacements.put(index, ac); /* * 2011 12 11 TODO. Rethink support for * od:continuousBefore and od:continuousAfter. */ // This is handled in this class if (map.get(BINDING_ROLE_COMPONENT_BEFORE) != null && map.get(BINDING_ROLE_COMPONENT_BEFORE).equals("true")) { continuousBefore.add(Boolean.TRUE); continuousBeforeIndex.addFirst(index); log.info("ctsBefore index: " + index); } else { continuousBefore.add(Boolean.FALSE); continuousBeforeIndex.addFirst(index); } // The following is handled in ProcessAltChunk if (map.get(BINDING_ROLE_COMPONENT_AFTER) != null && map.get(BINDING_ROLE_COMPONENT_AFTER).equals("true")) { continuousAfter.add(Boolean.TRUE); } else { continuousAfter.add(Boolean.TRUE); } justGotAComponent = true; } index++; } if (!justGotAComponent) { return srcPackage; } // Now replace in list for (Integer key : replacements.keySet()) { contentAccessor.getContent().set(key, replacements.get(key)); } // Go through docx in reverse order List<Object> bodyChildren = contentAccessor.getContent(); int i = 0; for (Integer indexIntoBody : continuousBeforeIndex) { if (continuousBefore.get(i)) { // Element before the w:altChunk if (indexIntoBody == 0) { // // Insert a sectPr right at the beginning of the docx? // // TODO check this isn't necessary // SectPr newSectPr = // Context.getWmlObjectFactory().createSectPr(); // SectPr.Type type = // Context.getWmlObjectFactory().createSectPrType(); // type.setVal("continuous"); // newSectPr.setType( type ); // // bodyChildren.add(0, newSectPr); } else { Object block = bodyChildren.get(indexIntoBody.intValue() - 1); if (block instanceof P && ((P) block).getPPr() != null && ((P) block).getPPr().getSectPr() != null) { makeContinuous(((P) block).getPPr().getSectPr()); } else if (block instanceof P) { // More likely PPr ppr = ((P) block).getPPr(); if (ppr == null) { ppr = Context.getWmlObjectFactory().createPPr(); ((P) block).setPPr(ppr); } SectPr newSectPr = Context.getWmlObjectFactory().createSectPr(); SectPr.Type type = Context.getWmlObjectFactory().createSectPrType(); type.setVal("continuous"); newSectPr.setType(type); ppr.setSectPr(newSectPr); } else { // Equally likely - its a table or something, so add a p P newP = Context.getWmlObjectFactory().createP(); PPr ppr = Context.getWmlObjectFactory().createPPr(); newP.setPPr(ppr); SectPr newSectPr = Context.getWmlObjectFactory().createSectPr(); SectPr.Type type = Context.getWmlObjectFactory().createSectPrType(); type.setVal("continuous"); newSectPr.setType(type); ppr.setSectPr(newSectPr); bodyChildren.add(indexIntoBody.intValue(), newP); // add // before // altChunk } } } // else nothing specified, so go with normal MergeDocx behaviour i++; } // process altChunk try { // Use reflection, so docx4j can be built // by users who don't have the MergeDocx utility Class<?> documentBuilder = Class.forName("com.plutext.merge.ProcessAltChunk"); // Method method = documentBuilder.getMethod("merge", // wmlPkgList.getClass()); Method[] methods = documentBuilder.getMethods(); Method processMethod = null; for (int j = 0; j < methods.length; j++) { log.debug(methods[j].getName()); if (methods[j].getName().equals("process")) { processMethod = methods[j]; } } if (processMethod == null) throw new NoSuchMethodException(); return (WordprocessingMLPackage) processMethod.invoke(null, srcPackage); } catch (ClassNotFoundException e) { extensionMissing(e); justGotAComponent = false; return srcPackage; // throw new Docx4JException("Problem processing w:altChunk", e); } catch (NoSuchMethodException e) { // Degrade gracefully extensionMissing(e); justGotAComponent = false; return srcPackage; // throw new Docx4JException("Problem processing w:altChunk", e); } catch (Exception e) { throw new Docx4JException("Problem processing w:altChunk", e); } }