package org.docx4j.model.datastorage.migration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import javax.xml.bind.JAXBElement; import org.docx4j.customXmlProperties.DatastoreItem; import org.docx4j.customXmlProperties.SchemaRefs; import org.docx4j.customXmlProperties.SchemaRefs.SchemaRef; import org.docx4j.jaxb.Context; import org.docx4j.openpackaging.exceptions.InvalidFormatException; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.openpackaging.parts.CustomXmlDataStoragePropertiesPart; import org.docx4j.openpackaging.parts.PartName; import org.docx4j.openpackaging.parts.opendope.ConditionsPart; import org.docx4j.openpackaging.parts.opendope.JaxbCustomXmlDataStoragePart; import org.docx4j.openpackaging.parts.opendope.QuestionsPart; import org.docx4j.openpackaging.parts.opendope.StandardisedAnswersPart; import org.docx4j.openpackaging.parts.opendope.XPathsPart; import org.docx4j.openpackaging.parts.relationships.RelationshipsPart.AddPartBehaviour; import org.docx4j.wml.CTDataBinding; import org.docx4j.wml.CTSdtContentRun; import org.docx4j.wml.R; import org.docx4j.wml.RPr; import org.docx4j.wml.SdtPr; import org.docx4j.wml.SdtRun; import org.docx4j.wml.Tag; import org.docx4j.wml.Text; import org.docx4j.wml.SdtPr.Alias; import org.opendope.answers.Answer; import org.opendope.answers.Answers; import org.opendope.conditions.Conditions; import org.opendope.questions.Question; import org.opendope.questions.Questionnaire; import org.opendope.questions.Response; import org.opendope.xpaths.Xpaths; import org.opendope.xpaths.Xpaths.Xpath.DataBinding; public class AbstractMigrator { protected XPathsPart xPathsPart; protected QuestionsPart questionsPart; protected StandardisedAnswersPart standardisedAnswersPart; protected String storeItemID; // of the answers part protected Map<String, String> keys = new HashMap<String, String>(); protected void createParts(WordprocessingMLPackage pkgOut) throws Exception { // Add OpenDoPE parts to target // .. conditions - not that we use this here ConditionsPart conditionsPart = new ConditionsPart(new PartName("/customXml/item1.xml")); // name doesn't matter pkgOut.getMainDocumentPart().addTargetPart(conditionsPart, AddPartBehaviour.RENAME_IF_NAME_EXISTS); // Word will silently drop the CXPs if they aren't added to the MDP! addPropertiesPart(conditionsPart, "http://opendope.org/conditions"); conditionsPart.setJaxbElement(new Conditions()); // .. XPaths xPathsPart = new XPathsPart(new PartName("/customXml/item1.xml")); pkgOut.getMainDocumentPart().addTargetPart(xPathsPart, AddPartBehaviour.RENAME_IF_NAME_EXISTS); addPropertiesPart(xPathsPart, "http://opendope.org/xpaths"); xPathsPart.setJaxbElement(new Xpaths()); // .. Questions questionsPart = new QuestionsPart(new PartName("/customXml/item1.xml")); pkgOut.getMainDocumentPart().addTargetPart(questionsPart, AddPartBehaviour.RENAME_IF_NAME_EXISTS); addPropertiesPart(questionsPart,"http://opendope.org/questions"); questionsPart.setJaxbElement(new Questionnaire()); Questionnaire.Questions questions = new Questionnaire.Questions(); questionsPart.getJaxbElement().setQuestions(questions); // .. Standardised Answer format standardisedAnswersPart = new StandardisedAnswersPart(new PartName("/customXml/item1.xml")); pkgOut.getMainDocumentPart().addTargetPart(standardisedAnswersPart, AddPartBehaviour.RENAME_IF_NAME_EXISTS); storeItemID = addPropertiesPart(standardisedAnswersPart, "http://opendope.org/answers"); standardisedAnswersPart.setJaxbElement(new Answers()); } protected String addPropertiesPart(JaxbCustomXmlDataStoragePart<?> customXmlDataStoragePart, String ns) throws InvalidFormatException { CustomXmlDataStoragePropertiesPart part = new CustomXmlDataStoragePropertiesPart(); org.docx4j.customXmlProperties.ObjectFactory of = new org.docx4j.customXmlProperties.ObjectFactory(); DatastoreItem dsi = of.createDatastoreItem(); String newItemId = "{" + UUID.randomUUID().toString().toUpperCase() + "}"; dsi.setItemID(newItemId); if (ns!=null) { SchemaRefs srefs = of.createSchemaRefs(); dsi.setSchemaRefs(srefs); SchemaRef sref = of.createSchemaRefsSchemaRef(); sref.setUri(ns); srefs.getSchemaRef().add(sref); } part.setJaxbElement(dsi); customXmlDataStoragePart.addTargetPart(part, AddPartBehaviour.RENAME_IF_NAME_EXISTS); return newItemId; } /** * @param r * @param replacementContent * @param key */ protected void createContentControl(RPr rPr, List<Object> replacementContent, String key) { // Has it been encountered already? if (!keys.containsKey(key) ) { // add the part entries addPartEntries(key); keys.put(key, key); } // create the content control SdtRun sdtRun = Context.getWmlObjectFactory().createSdtRun(); replacementContent.add(sdtRun); SdtPr sdtPr = Context.getWmlObjectFactory().createSdtPr(); sdtRun.setSdtPr(sdtPr); /* <w:sdtPr> <w:alias w:val="Title of document"/> <w:tag w:val="od:xpath=cktpD"/> <w:id w:val="289095091"/> <w:dataBinding w:prefixMappings="xmlns:oda='http://opendope.org/answers'" w:xpath="/oda:answers/oda:answer[@id='Title_of_document_nM']" w:storeItemID="{183E9AF4-65AB-46DF-8044-944891825721}"/> <w:text w:multiLine="1"/> </w:sdtPr> */ Alias alias = Context.getWmlObjectFactory().createSdtPrAlias(); alias.setVal(key); Tag tag = Context.getWmlObjectFactory().createTag(); tag.setVal("od:xpath=" + key); sdtPr.setTag(tag); sdtPr.setId(); CTDataBinding ctDataBinding = Context.getWmlObjectFactory().createCTDataBinding(); JAXBElement<CTDataBinding> jaxbDB = Context.getWmlObjectFactory().createSdtPrDataBinding(ctDataBinding); sdtPr.setDataBinding(ctDataBinding); ctDataBinding.setXpath("/oda:answers/oda:answer[@id='" + key +"']"); ctDataBinding.setPrefixMappings("xmlns:oda='http://opendope.org/answers'"); ctDataBinding.setStoreItemID(storeItemID); CTSdtContentRun sdtContent = Context.getWmlObjectFactory().createCTSdtContentRun(); sdtRun.setSdtContent(sdtContent); R rnew = new R(); rnew.setRPr( rPr ); // point at old rPr, if any Text text = Context.getWmlObjectFactory().createText(); text.setValue(key); rnew.getContent().add(text); sdtContent.getContent().add(rnew); } private void addPartEntries(String key) { // answer Answer a = new Answer(); a.setId(key); a.setValue("${" + key + "}"); standardisedAnswersPart.getJaxbElement().getAnswerOrRepeat().add(a); // XPath Xpaths.Xpath xp = new org.opendope.xpaths.ObjectFactory().createXpathsXpath(); xp.setId(key); xp.setQuestionID(key); DataBinding db = new org.opendope.xpaths.ObjectFactory().createXpathsXpathDataBinding(); db.setXpath("/oda:answers/oda:answer[@id='" + key +"']"); db.setPrefixMappings("xmlns:oda='http://opendope.org/answers'"); db.setStoreItemID(storeItemID); xp.setDataBinding(db); xPathsPart.getJaxbElement().getXpath().add(xp); // question Question q = new Question(); q.setId(key); q.setText(key + "?"); Response r = new Response(); r.setFree( new Response.Free() ); questionsPart.getJaxbElement().getQuestions().getQuestion().add(q); } }