/** * */ package org.dita2indesign.indesign.inx.model; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.dita2indesign.indesign.inx.visitors.InDesignDocumentVisitor; import org.dita2indesign.util.DataUtil; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; /** * Base class for InDesign components. */ public abstract class InDesignComponent { private InDesignComponent parent; private List<InDesignComponent> childObjects = new ArrayList<InDesignComponent>(); private Map<String, InxValue> properties = new HashMap<String, InxValue>(); private InDesignDocument document; private String inxTagname = null; protected Map<String, String> tags = new HashMap<String, String>(); /** * Load any subcomponents of the component. * @param dataSource * @throws Exception */ public void loadComponent(Element dataSource) throws Exception { loadPropertiesFromDataSource(dataSource); Iterator<Element> elemIter = DataUtil.getElementChildrenIterator(dataSource); // Process all child components. // Subclasses that need to do additional things with children must // iterate over their children and do whatever they need to do. while (elemIter.hasNext()) { Element child = elemIter.next(); // logger.debug("loadObject(): Input element is <" + child.getNodeName() + ">"); InDesignComponent obj = this.getDocument().newInDesignComponent(child); this.addChild(obj); } setTagsFromPtagProperty(); } /** * @throws Exception */ protected void setTagsFromPtagProperty() throws Exception { // Value is a list of lists, each sublist being a key/value pair. InxValueList propValue = (InxValueList)getPropertyValue(InDesignDocument.PROP_PTAG); if (propValue != null) { Iterator<InxValue> iter = ((InxValueList)propValue).getItems().iterator(); while (iter.hasNext()) { InxValueList tag = (InxValueList)iter.next(); String label = tag.getItems().get(0).toString(); String value = tag.getItems().get(1).toString(); this.tags.put(label, value); } } } /** * @param dataSource * @throws Exception */ private void loadPropertiesFromDataSource(Element dataSource) throws Exception { this.inxTagname = dataSource.getNodeName(); NamedNodeMap atts = dataSource.getAttributes(); for (int i = 0; i < atts.getLength(); i++) { Attr att = (Attr)atts.item(i); String rawValue = att.getNodeValue(); InxValue value = null; try { value = InxHelper.newValue(rawValue); } catch (Exception e) { e.printStackTrace(); throw e; } this.properties.put(att.getNodeName(), value); } } /** * @param run * @throws Exception */ public void addChild(InDesignComponent child) throws Exception { this.childObjects.add(child); child.setParent(this); } /** * Set the parent for the object (e.g., when adding it to an existing structure. * @param inDesignObject */ public void setParent(InDesignComponent parent) { this.parent = parent; } /** * @param propName * @return */ public boolean hasProperty(String propName) { return this.properties.containsKey(propName); } /** * Returns the containing document for the component. * @return Containing document or null if the component is not associated with a document. */ protected InDesignDocument getDocument() { return this.document; } /** * @return */ public InDesignComponent getParent() { return this.parent; } /** * @param document */ public void setDocument(InDesignDocument document) { this.document = document; } /** * * @param propName * @return * @throws Exception */ protected long getLongProperty(String propName) throws Exception { InxValue valueObj = getValueObject(propName); if (valueObj == null) return 0L; if (valueObj instanceof InxLongBase) { return ((InxLongBase)valueObj).getValue().longValue(); } throw new Exception("Property named \"" + propName + "\" is not a long value"); } /** * @param propName * @return */ public InxValue getValueObject(String propName) { InxValue valueObj = null; if (this.properties.containsKey(propName)) { valueObj = this.properties.get(propName); } return valueObj; } /** * @param propPagc * @return * @throws Exception */ public double getDoubleProperty(String propName) throws Exception { InxValue valueObj = getValueObject(propName); if (valueObj == null) return 0.0; if (valueObj instanceof InxDouble) { return ((InxDouble)valueObj).getValue().doubleValue(); } throw new Exception("Property named \"" + propName + "\" is not a double value"); } /** * @param propName * @return * @throws Exception */ public String getStringProperty(String propName) throws Exception { InxValue valueObj = getValueObject(propName); if (valueObj == null) return null; if (valueObj instanceof InxString) { return ((InxString)valueObj).getValue(); } throw new Exception("Property named \"" + propName + "\" is not a String value"); } /** * @param propName * @return * @throws Exception */ public Map<String, String> getStringMapListProperty(String propName) throws Exception { InxValue valueObj = getValueObject(propName); if (valueObj == null) return null; if (valueObj instanceof InxStringMap) { return ((InxStringMap)valueObj).getValue(); } throw new Exception("Property named \"" + propName + "\" is not a string map value"); } /** * @param propSelf * @return * @throws Exception */ protected String getObjectReferenceProperty(String propName) throws Exception { InxValue valueObj = getValueObject(propName); if (valueObj == null) return null; if (valueObj instanceof InxObjectRef) { return ((InxObjectRef)valueObj).getValue(); } throw new Exception("Property named \"" + propName + "\" is not an Object Reference value"); } /** * @param object */ protected void registerObject(InDesignObject object) { this.getDocument().registerObject(object); } /** * @param propName * @return * @throws Exception */ @SuppressWarnings("unchecked") public Enum getEnumProperty(String propName) throws Exception { if (this.properties.containsKey(propName)) { } return null; } /** * @param propName * @return * @throws Exception */ protected List<? extends InxValue> getValueListProperty(String propName) throws Exception { InxValue valueObj = getValueObject(propName); if (valueObj == null) return null; // Should we return empty list? if (valueObj instanceof InxValueList) { return ((InxValueList)valueObj).getValue(); } throw new Exception("Property named \"" + propName + "\" is not a value list"); } /** * @param attName * @return * @throws Exception */ protected boolean getBooleanProperty(String attName) throws Exception { if (this.properties.containsKey(attName)) { return ((InxBoolean)properties.get(attName)).getValue().booleanValue(); } return false; } /** * @param visitor * @throws Exception */ public void accept(InDesignDocumentVisitor visitor) throws Exception { visitor.visit(this); } /** * @return */ public List<InDesignComponent> getChildren() { return this.childObjects; } public void setStringProperty(String propName, String value) { InxString inxValue = new InxString(value); this.properties.put(propName, inxValue); } /** * Gets full property map for this component. * @return The component's property map. */ public Map<String, InxValue> getPropertyMap() { // updatePropertyMap(); return this.properties; } /** * Gets the Inx value of the specified property. * @param propName The property to get the value of. * @return InxValue object for the property, if it exists. */ public InxValue getPropertyValue(String propName) { return this.properties.get(propName); } /** * Sets the specified property to the provided value. * @param propName Name of the property to set. * @param value The INX value to set. */ public void setProperty(String propName, InxValue value) { this.properties.put(propName, value); } /** * @return */ public String getInxTagName() { return inxTagname; } /** * Sets a property from raw INX value. * @param propName Property to be set. * @param rawValue Value to use. */ public void setPropertyFromRawValue(String propName, String rawValue) throws Exception { InxValue value = InxHelper.newValue(rawValue); this.setProperty(propName, value); } /** * Updates the component's property map with any dynamic properties. * @throws Exception */ public abstract void updatePropertyMap() throws Exception; /** * @param sourceObj * @throws Exception */ protected void loadComponent(InDesignComponent sourceObj) throws Exception { this.inxTagname = sourceObj.getInxTagName(); if (sourceObj != null) { for (String propName : sourceObj.getPropertyMap().keySet()) { this.setProperty(propName, sourceObj.getPropertyValue(propName)); } } setTagsFromPtagProperty(); for (InDesignComponent child : sourceObj.getChildren()) { InDesignComponent newChild = this.getDocument().clone(child); addChild(newChild); } } /** * @param propName * @param geometry */ public void setGeometryProperty(String propName, Geometry geometry) { InxValue geometryValue = new InxGeometry(geometry); this.setProperty(propName, geometryValue); } /** * Sets the INX tagname to use for this component. * @param tagName The XML tag name to use. */ public void setInxTagName(String tagName) { this.inxTagname = tagName; } /** * Get the name of the object. * @return Name value, possibly null. * @throws Exception */ public String getPName() throws Exception { return this.getStringProperty(InDesignDocument.PROP_PNAM); } /** * @param name */ protected void setPName(String name) { this.setStringProperty(InDesignDocument.PROP_PNAM, name); } /** * Set a property that is a reference to an object. * @param propName * @param targetObj */ public void setObjectReferenceProperty(String propName, InDesignObject targetObj) { InxValue objRef = new InxObjectRef((targetObj != null ? targetObj.getId() : "n")); setProperty(propName, objRef); } /** * @param label * @param value */ public void insertLabel(String label, String value) { this.tags.put(label, value); } /** * @param label * @return */ public String extractLabel(String label) { if (this.tags.containsKey(label)) { return this.tags.get(label); } return null; } /** * @return */ public Map<String, String> getLabels() { return this.tags; } /** * @return */ public String getLabel() { String label = this.tags.get(InDesignDocument.TAG_KEY_LABEL); if (label == null) label = ""; return label; } /** * Returns true if the component is marked as overrideable. * @return True if component can be overridden. * @throws Exception */ public boolean isOverrideable() throws Exception { return getBooleanProperty("ovbl"); } /** * Removes the specified property from the component's * property map if the property exists. * @param propName The name of the property to remove. */ public void removeProperty(String propName) { this.properties.remove(propName); } }