/** * Copyright (c) 2008 Really Strategies, Inc. */ package org.dita2indesign.indesign.builders; import java.io.File; import java.util.ArrayList; import java.util.List; import net.sourceforge.dita4publishers.util.conversion.ConversionConfigValue; import net.sourceforge.dita4publishers.util.conversion.ConversionConfigValueMap; import net.sourceforge.dita4publishers.util.conversion.StringConfigValue; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dita2indesign.indesign.inx.model.InDesignDocument; import org.dita2indesign.indesign.inx.model.InxHelper; import org.dita2indesign.indesign.inx.model.MasterSpread; import org.dita2indesign.indesign.inx.model.Page; import org.dita2indesign.indesign.inx.model.PageSideOption; import org.dita2indesign.indesign.inx.model.Spread; import org.dita2indesign.indesign.inx.model.Story; import org.dita2indesign.indesign.inx.model.TextFrame; import org.xml.sax.InputSource; /** * Takes an RSuite content assembly representing a single publication issue as input * and generates a new InDesign document with links to the issue's articles placed * in placeholder frames. */ public class InDesignDocumentBuilder { public static final String CONFIG_PARAM_NEXT_MASTER = "nextMaster"; public static final String CONFIG_PARAM_PAGES = "pages"; public static final String CONFIG_PARAM_MASTER_NAME = "masterName"; public static final String CONFIG_PARAM_START_PAGE = "startPage"; public static final String CONFIG_PARAM_FIRST_MASTER = "firstMaster"; /** * */ public static final String INITIAL_FRAME_LABEL = "initialFrame"; private static Log log = LogFactory.getLog(InDesignDocumentBuilder.class); public static final String NS_URI = "http://www.reallysi.com"; private int _pageCtr = 0; /** * @param context * @param gdTemplate * @param gdIssueCa */ public InDesignDocumentBuilder() { } /** * @param issueCaSource * @param inDesignTemplateSource * @param context * @return */ public InDesignDocument buildDocument(InputSource inDesignTemplateSource) throws Exception { if (log.isDebugEnabled()) log.debug("buildDocument(): inDesignTemplateSource=\"" + inDesignTemplateSource.getSystemId() + "\""); // Load the template then clone it to make our starting doc. InDesignDocument template = new InDesignDocument(inDesignTemplateSource); InDesignDocument doc = new InDesignDocument(template, true); return doc; } public void addInCopyArticleToDoc( InDesignDocument inDesignDoc, File incx, ConversionConfigValueMap spreadConfig) throws Exception { throw new RuntimeException("Method not updated to latest INX library"); // String initialMasterName = spreadConfig.getStringValue(CONFIG_PARAM_FIRST_MASTER); // // if (initialMasterName == null) { // throw new Exception("No value for required configuration item \"" + CONFIG_PARAM_FIRST_MASTER + "\""); // } // // MasterSpread masterSpread = inDesignDoc.getMasterSpread(initialMasterName); // if (masterSpread == null) // { // throw new Exception("The masterSpread " + initialMasterName + " was not found in the template."); // } // // _pageCtr++; // // boolean isEvenPage = (_pageCtr%2==0)?true:false; // Spread spread; // // if (_pageCtr == 1) // { // spread = inDesignDoc.getSpread(0); // // Make sure the first page is a right-hand page. // Page page = spread.getPages().get(0); // page.setPageSide(PageSideOption.RIGHT_HAND); // page.setAppliedMaster(masterSpread); // page.overrideMasterSpreadObjects(); // } // else // { // // FIXME: If the first page to create // // is a right-hand page, then can // // create it in isolation, otherwise, // // have to create a two-page sequence // int spreadNbr = _pageCtr/2; // spread = inDesignDoc.getSpread(spreadNbr); // if (spread == null) // { // spread = inDesignDoc.addSpread(initialMasterName); // } // Page page = spread.addPage(_pageCtr); // page.setAppliedMaster(masterSpread); // page.overrideMasterSpreadObjects(); // } // // // Read the incx file // DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // DocumentBuilder db = dbf.newDocumentBuilder(); // Document doc = db.parse(incx); // NodeList cflos = doc.getElementsByTagName("cflo"); // Element cflo = (Element) cflos.item(0); // cflo.setAttribute("Self", "rc_UR-" + _pageCtr); // // // // Make the frame // TextFrame frame = makeDefaultTextFrame(inDesignDoc, isEvenPage); // // spread.addRectangle(frame); // // // Make the story // Story incxStory = inDesignDoc.newStory(cflo); // frame.setParentStory(incxStory); } /** * Adds an InCopy (INCX) article to the document. Overrides overrideable * frames from the master page and then flows into the overridden frame, * starting with the frame labeled "initialFrame" or first overrideable * frame, no initalFrame frame is found. * @param context * @param inDesignDoc * @param incx * @param spreadConfig * @throws Exception */ public void addIncxArticleToDoc( InDesignDocument inDesignDoc, File incx, ConversionConfigValueMap spreadConfig) throws Exception { // Make the story Story incxStory = null; try { incxStory = InxHelper.getStoryForIncxDoc(inDesignDoc, incx); } catch (Exception e) { log.error("Exception from getStoryForIncxDoc: " + e.getMessage(), e); throw e; } ConversionConfigValue value = spreadConfig.get(CONFIG_PARAM_FIRST_MASTER); PageCreationOptions pageCreationOptions = getPageCreationOptions( spreadConfig, CONFIG_PARAM_FIRST_MASTER, value); // FIXME: Allow each topic type to configure whether or not it starts // a new page sequence. pageCreationOptions.setStartNewMainThread(true); List<TextFrame> frames = addPagesForPageMaster(inDesignDoc, pageCreationOptions); TextFrame firstFrame = frames.get(0); TextFrame lastFrame = frames.get(frames.size() - 1); value = spreadConfig.get(CONFIG_PARAM_NEXT_MASTER); if (value != null) { pageCreationOptions = getPageCreationOptions( spreadConfig, CONFIG_PARAM_FIRST_MASTER, value); List<TextFrame> nextFrames = addPagesForPageMaster(inDesignDoc, pageCreationOptions); lastFrame.setNextInThread(nextFrames.get(0)); } // Walk the thread and set the story on each member in the thread. TextFrame frame = firstFrame; while (frame != null) { frame.setParentStory(incxStory); frame = frame.getNextInThread(); } } public List<TextFrame> addPagesForPageMaster( InDesignDocument inDesignDoc, PageCreationOptions pageCreationOptions) throws Exception, Exception { String initialMasterName = pageCreationOptions.getPageMasterName(); MasterSpread master = inDesignDoc. getMasterSpread(initialMasterName); if (master == null) { throw new Exception("The masterSpread " + pageCreationOptions.getPageMasterName() + " was not found in the template."); } _pageCtr++; // We will always add at least one page per page master. boolean isEvenPage = (_pageCtr%2==0) ? true : false; log.info("addIncxArticleToDoc(): _pageCtr=" + _pageCtr + ", isEvenPage=" + isEvenPage); // If necessary, force to next page so page // even/odd matches the "startPage" setting: List<TextFrame> frames = new ArrayList<TextFrame>(); Spread spread; Page page = null; // Get the spread and page for the current page counter: if (_pageCtr == 1) // First spread is a special case because the spread always exists // and we always get the odd page. { spread = getSpreadForPageCtr(inDesignDoc, initialMasterName); page = spread.getOddPage(); } else { // First get the spread for the initial page // counter, without regard for startPage value: spread = getSpreadForPageCtr(inDesignDoc, initialMasterName); page = spread.addPage(_pageCtr); } // Now add a blank page if our start page is not the same // as the page we have: if (("odd".equals(pageCreationOptions.getStartPage()) && isEvenPage) || ("even".equals(pageCreationOptions.getStartPage()) && !isEvenPage)) { _pageCtr++; spread = getSpreadForPageCtr(inDesignDoc, initialMasterName); page = spread.addPage(_pageCtr); } page.setAppliedMaster(master); page.overrideMasterSpreadObjects(); TextFrame frame = getInitialTextFrame(initialMasterName, page); frames.add(frame); if (pageCreationOptions.startNewMainThread()) { // Unthread the frame we have from it's preceding thread member, if // any. TextFrame prevFrame = frame.getPreviousInThread(); if (prevFrame != null) { frame.setPreviousInThread(null); prevFrame.setNextInThread(null); } } // Add additional pages per the pagesToAdd value: // Thread the frames across any added pages, adding // the frames to the list to be returned. if (pageCreationOptions.getPagesToAdd() > 1) { List<Page> pages = new ArrayList<Page>(); log.info("Adding " + (pageCreationOptions.getPagesToAdd() - 1) + " additional pages..."); for (int i = 0; i < pageCreationOptions.getPagesToAdd(); i++) { _pageCtr++; log.info(" Adding page " + _pageCtr + "..."); spread = getSpreadForPageCtr(inDesignDoc, master.getName()); log.info(" Spread index=" + spread.getSpreadIndex()); page = spread.addPage(_pageCtr); page.setAppliedMaster(master); pages.add(page); } // Now override the overridable objects and thread // text frames from page-to-page. for (Page newPage : pages) { newPage.setAppliedMaster(master); newPage.overrideMasterSpreadObjects(); frame = getInitialTextFrame(initialMasterName, newPage); TextFrame prevFrame = frames.get(frames.size() - 1); prevFrame.setNextInThread(frame); frame.setPreviousInThread(prevFrame); frames.add(frame); if (!frame.getLastFrameInThread().equals(frame)) { frames.add(frame.getLastFrameInThread()); } } } return frames; } public TextFrame getInitialTextFrame( String initialMasterName, Page page) throws Exception, Exception { // Now look for a text frame with the label "initialFrame" or // just get the first text frame in the list of frames. String targetLabel = INITIAL_FRAME_LABEL; String targetLabel2 = INITIAL_FRAME_LABEL + (page.getPageSide().equals(PageSideOption.LEFT_HAND)? "Even" : "Odd"); TextFrame frame = getFrameForLabel(page, targetLabel); if (frame == null) { frame = getFrameForLabel(page, targetLabel2); } if (frame == null) { log.info("Failed to find a frame named \"" + targetLabel + "\" or \"" + targetLabel2 + "\", using first overrideable text frame."); frame = getFirstFrame(page); } if (frame == null) { throw new Exception("Failed to find an overridable frame for page master \"" + initialMasterName + "\""); } return frame; } public PageCreationOptions getPageCreationOptions( ConversionConfigValueMap spreadConfig, String pageMasterOptionsName, ConversionConfigValue configValue) throws Exception { PageCreationOptions pageCreationOptions = new PageCreationOptions(); if (configValue instanceof StringConfigValue) { String initialMasterName = spreadConfig.getStringValue(pageMasterOptionsName); if (initialMasterName == null) { throw new Exception("No value for required configuration item \"" + pageMasterOptionsName + "\""); } pageCreationOptions.setPageMasterName(initialMasterName); String temp = spreadConfig.getStringValue(CONFIG_PARAM_START_PAGE); if (temp != null && !"".equals(temp.trim())) { pageCreationOptions.setStartPage(temp); } } else if (configValue instanceof ConversionConfigValueMap ) { ConversionConfigValueMap map = (ConversionConfigValueMap)configValue; String initialMasterName = map.getStringValue(CONFIG_PARAM_MASTER_NAME); if (initialMasterName == null) { throw new Exception("No value for required configuration item \"" + CONFIG_PARAM_MASTER_NAME + "\" for parameter " + pageMasterOptionsName) ; } pageCreationOptions.setPageMasterName(initialMasterName); String temp = map.getStringValue(CONFIG_PARAM_START_PAGE); if (temp != null && !"".equals(temp.trim())) { pageCreationOptions.setStartPage(temp); } temp = map.getStringValue(CONFIG_PARAM_PAGES); if (temp != null && !"".equals(temp.trim())) { int pagesToAdd = 1; try { pagesToAdd = Integer.valueOf(temp).intValue(); } catch (NumberFormatException e) { log.warn("Value \"" + temp + "\" for parameter \"" + CONFIG_PARAM_PAGES + "\" for property \"" + pageMasterOptionsName + "\" is not an integer."); } pageCreationOptions.setPagesToAdd(pagesToAdd); } } else { throw new Exception("Unrecognized value object \"" + configValue.getClass().getSimpleName() + "\""); } return pageCreationOptions; } /** * Gets the spread for the specified page number. * If the spread does not already exist, adds it to * the InDesign document. Does not override any * overrideable options as that has to be done at the * page or spread level depending on how pages are being * added to the spread. * @param inDesignDoc The document to get the spread from. * @param pageMasterName The page master to use for the spread * @return The spread. * @throws Exception */ public Spread getSpreadForPageCtr( InDesignDocument inDesignDoc, String pageMasterName) throws Exception { Spread spread; int spreadNbr = 0; if (_pageCtr > 1) { spreadNbr = (_pageCtr == 2 ? 1 : (_pageCtr/2)); // The 2nd page starts on the 2nd spread } log.info("addIncxArticleToDoc(): Spread number is " + spreadNbr); spread = inDesignDoc.getSpread(spreadNbr); if (spread == null) { spread = inDesignDoc.addSpread(pageMasterName); } return spread; } /** * Gets the first overridable frame from the page * @param page * @return First overrideable frame, or null if there is no overridable frame. * @throws Exception */ private TextFrame getFirstFrame(Page page) throws Exception { TextFrame frame = null; for (TextFrame candFrame : page.getAllFrames()) { if (candFrame.isOverrideable()) { return candFrame; } } return frame; } /** * @param page * @param targetLabel * @return */ public TextFrame getFrameForLabel(Page page, String targetLabel) { TextFrame frame = null; for (TextFrame candFrame : page.getAllFrames()) { String label = candFrame.getLabel(); if (targetLabel.equals(label)) { frame = candFrame; break; } } return frame; } public void addArticleToBook(InDesignDocument inDesignDoc, File incx, String masterSpreadName) throws Exception { throw new RuntimeException("Method not updated to latest INX library"); // _pageCtr++; // // MasterSpread masterSpread = inDesignDoc.getMasterSpread(masterSpreadName); // if (masterSpread == null) // { // throw new Exception("The masterSpread " + masterSpreadName + " was not found in the template."); // } // // boolean evenPage = (_pageCtr%2==0)?true:false; // Spread spread; // if (_pageCtr == 1) // { // spread = inDesignDoc.getSpread(0); // Page page = spread.getPages().get(0); // page.setAppliedMaster(masterSpread); // page.overrideMasterSpreadObjects(); // } // else // if (evenPage) // { // int spreadNbr = _pageCtr/2; // spread = inDesignDoc.getSpread(spreadNbr); // if (spread == null) // { // spread = inDesignDoc.addSpread(masterSpreadName); // } // Page page = spread.addPage(_pageCtr); // page.setAppliedMaster(masterSpread); // page.overrideMasterSpreadObjects(); // } // // // Read the incx file // DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // DocumentBuilder db = dbf.newDocumentBuilder(); // Document doc = db.parse(incx); // NodeList cflos = doc.getElementsByTagName("cflo"); // Element cflo = (Element) cflos.item(0); // cflo.setAttribute("Self", "rc_UR-" + _pageCtr); // // // // Make the frame // TextFrame frame = inDesignDoc.newTextFrame(); // // // Add the frame to the page // double xTranslate = evenPage?-414:0; // double yTranslate = 1; // if (_pageCtr == 1) // { // xTranslate = 1; // } // // double x1 = 36; // This is the left margin // double x2 = 377; // double y1 = -235; // I don't understand this value at all // double y2 = 233; // // frame.getGeometry().getBoundingBox().setCorners(x1, y1, x2, y2); // frame.getGeometry().getTransformationMatrix().setXTranslation(xTranslate); // frame.getGeometry().getTransformationMatrix().setYTranslation(yTranslate); // // spread.addRectangle(frame); // // // Make the story // Story incxStory = inDesignDoc.newStory(cflo); // frame.setParentStory(incxStory); } }