/**
  * Clones an object only if it hasn't been already cloned. Returns the clone.
  *
  * @param sourceObj
  * @return The clone of the source object.
  * @throws Exception
  */
 public InDesignComponent cloneIfNew(InDesignObject sourceObj, InDesignComponent targetParent)
     throws Exception {
   Map<String, InDesignObject> cloneMap = getCloneMapForDoc(sourceObj.getDocument());
   if (cloneMap.containsKey(sourceObj.getId())) return cloneMap.get(sourceObj.getId());
   InDesignComponent clone = this.clone(sourceObj);
   if (targetParent != null) targetParent.addChild(clone);
   return clone;
 }
 /**
  * Register a new object with the document so it can maintain a master index of objects by ID.
  *
  * @param object
  */
 public void registerObject(InDesignObject object) {
   String id = object.getId();
   if (id == null || this.objectsById.containsKey(id)) {
     id = assignObjectId();
     object.setId(id);
   }
   this.objectsById.put(object.getId(), object);
   object.setDocument(this);
 }
  /**
   * Import a story from one document (e.g., an InCopy article) into this document, updating style
   * references as necessary.
   *
   * @param incxStory The story to be imported.
   * @return The imported story object.
   * @throws Exception
   */
  public Story importStory(Story incxStory) throws Exception {

    Map<String, ParagraphStyle> paraStyleMap = new HashMap<String, ParagraphStyle>();

    Story newStory = new Story();
    this.assignIdAndRegister(newStory);

    Iterator<TextStyleRange> iter = incxStory.getTextStyleRangeIterator();

    while (iter.hasNext()) {
      TextStyleRange incomingTxsr = iter.next();
      TextStyleRange txsr = (TextStyleRange) this.clone(incomingTxsr);

      InDesignObject incomingStyle = incomingTxsr.getParagraphStyle();
      if (incomingStyle == null) {
        throw new Exception(
            "Failed to get object for referenced paragraph style ID ["
                + txsr.getObjectReferenceProperty(PROP_PRST)
                + "]");
      }
      String styleName = incomingStyle.getPName();
      ParagraphStyle targetPStyle = this.getParagraphStyle(styleName);
      if (targetPStyle == null) {
        targetPStyle = (ParagraphStyle) this.clone(incomingStyle);
        this.addParagraphStyle(targetPStyle);
      }
      txsr.setObjectReferenceProperty(PROP_PRST, targetPStyle);

      incomingStyle = incomingTxsr.getCharacterStyle();
      if (incomingStyle == null) {
        logger.warn(
            "Failed to get object for referenced character style ID ["
                + txsr.getObjectReferenceProperty(PROP_PRST)
                + "]");
      } else {
        styleName = incomingStyle.getPName();
        CharacterStyle targetCStyle = this.getCharacterStyle(styleName);
        if (targetCStyle == null) {
          targetCStyle = (CharacterStyle) this.clone(incomingStyle);
          this.addCharacterStyle(targetCStyle);
        }
        txsr.setObjectReferenceProperty(PROP_CRST, targetCStyle);
      }

      newStory.addChild(txsr);
    }
    this.addChild(newStory);
    return newStory;
  }
 /** @return */
 public String reportChildObjects() {
   StringBuilder report = new StringBuilder("Child Objects::\n");
   for (InDesignComponent comp : this.getChildren()) {
     String dsName = comp.getInxTagName();
     if (comp instanceof InDesignObject) {
       InDesignObject obj = (InDesignObject) comp;
       report.append("[").append(obj.getId()).append("] ");
     }
     report
         .append(comp.getClass().getSimpleName())
         .append(", <")
         .append(dsName)
         .append(">")
         .append("\n");
   }
   return report.toString();
 }
 /**
  * Constructs a new component, which may be an InDesignComponent or an InDesignObject.
  *
  * @param child
  * @return
  * @throws Exception
  */
 public InDesignComponent newInDesignComponent(Element child) throws Exception {
   logger.debug(
       "newInDesignObject(): Creating new object or component from <"
           + child.getNodeName()
           + ">...");
   if (child.hasAttribute(PROP_SELF)) {
     Class<? extends InDesignObject> objectClass = tagToObjectClassMap.get(child.getNodeName());
     if (objectClass == null) objectClass = DefaultInDesignObject.class;
     InDesignObject newObject = (InDesignObject) newObject(objectClass, child);
     logger.debug("newInDesignObject():   New object has ID [" + newObject.getId() + "]");
     return newObject;
   } else {
     Class<? extends InDesignComponent> objectClass =
         tagToComponentClassMap.get(child.getNodeName());
     if (objectClass == null) objectClass = DefaultInDesignComponent.class;
     return newComponent(objectClass, child);
   }
 }
  /**
   * @param class1
   * @param dataSource
   * @return
   * @throws Exception
   * @throws InstantiationException
   */
  private InDesignComponent newObject(Class<? extends InDesignObject> clazz, Element dataSource)
      throws Exception {
    logger.debug("newObject(): Creating new " + clazz.getSimpleName() + "...");
    InDesignObject obj = (InDesignObject) clazz.newInstance();
    obj.setDocument(this);
    if (dataSource != null) {
      logger.debug("newObject():   From element " + dataSource.getNodeName() + "...");
      obj.loadObject(dataSource);
      String selfValue = dataSource.getAttribute(PROP_SELF);
      if (selfValue != null && !"".equals(selfValue.trim())) {
        String id = InxHelper.decodeRawValueToSingleString(selfValue);
        obj.setId(id);
        this.registerObject(obj);
      } else {
        assignIdAndRegister(obj);
      }

    } else {
      assignIdAndRegister(obj);
    }
    logger.debug("newObject(): New object has ID [" + obj.getId() + "]");
    return obj;
  }
 /**
  * Unconditionally clone an InDesign Object.
  *
  * @param sourceObj
  * @return The clone of the object.
  * @throws Exception
  */
 public InDesignComponent clone(InDesignObject sourceObj) throws Exception {
   logger.debug(
       "Cloning object "
           + sourceObj.getClass().getSimpleName()
           + " ["
           + sourceObj.getId()
           + "]...");
   InDesignObject clone = sourceObj.getClass().newInstance();
   assignIdAndRegister(clone);
   // Now remember that we've cloned this source object so we can not
   // clone it again if we don't want to:
   Map<String, InDesignObject> cloneMap = getCloneMapForDoc(sourceObj.getDocument());
   cloneMap.put(sourceObj.getId(), clone);
   clone.loadObject(sourceObj, clone.getId());
   return clone;
 }
 public void addChild(InDesignComponent comp) throws Exception {
   super.addChild(comp);
   if (comp instanceof Story) {
     this.stories.add((Story) comp);
     // FIXME: Need to do some more refactoring in order to be able to do
     // this processing at this point.
     //		} else if (comp instanceof MasterSpread) {
     //			MasterSpread masterSpread = (MasterSpread)comp;
     //			this.masterSpreads.put(masterSpread.getPName(), masterSpread);
     //		} else if (comp instanceof Spread) {
     //			this.spreads.add((Spread)comp);
   } else if (comp instanceof ParagraphStyle) {
     this.pstylesByName.put(comp.getPName(), (ParagraphStyle) comp);
   } else if (comp instanceof CharacterStyle) {
     this.cstylesByName.put(comp.getPName(), (CharacterStyle) comp);
   } else if (comp instanceof DocumentPreferences) {
     this.docPrefs = (DocumentPreferences) comp;
   }
 }
 /** @param newObject */
 protected void assignIdAndRegister(InDesignObject newObject) {
   newObject.setId(this.assignObjectId());
   registerObject(newObject);
 }