OdfOfficeMeta.java

/**
 * **********************************************************************
 *
 * <p>DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 *
 * <p>Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
 *
 * <p>Use is subject to license terms.
 *
 * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0. You can also obtain a copy of the License at
 * http://odftoolkit.org/docs/license.txt
 *
 * <p>Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 *
 * <p>See the License for the specific language governing permissions and limitations under the
 * License.
 *
 * <p>**********************************************************************
 */
package org.odftoolkit.odfdom.incubator.meta;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.odftoolkit.odfdom.dom.element.dc.DcCreatorElement;
import org.odftoolkit.odfdom.dom.element.dc.DcDateElement;
import org.odftoolkit.odfdom.dom.element.dc.DcDescriptionElement;
import org.odftoolkit.odfdom.dom.element.dc.DcLanguageElement;
import org.odftoolkit.odfdom.dom.element.dc.DcSubjectElement;
import org.odftoolkit.odfdom.dom.element.dc.DcTitleElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaAutoReloadElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaCreationDateElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaDocumentStatisticElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaEditingCyclesElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaEditingDurationElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaGeneratorElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaHyperlinkBehaviourElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaInitialCreatorElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaKeywordElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaPrintDateElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaPrintedByElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaTemplateElement;
import org.odftoolkit.odfdom.dom.element.meta.MetaUserDefinedElement;
import org.odftoolkit.odfdom.dom.element.office.OfficeDocumentMetaElement;
import org.odftoolkit.odfdom.dom.element.office.OfficeMetaElement;
import org.odftoolkit.odfdom.pkg.OdfElement;
import org.odftoolkit.odfdom.pkg.OdfFileDom;
import org.odftoolkit.odfdom.type.Duration;

/**
 * <code>OdfOfficeMeta</code> represent the meta data feature in the ODF document.
 *
 * <p>It provides convenient method to get meta data info.
 */
public class OdfOfficeMeta {

  private OfficeMetaElement mOfficeMetaElement;
  private boolean mAutomaticUpdate = true;

  /**
   * Constructor of <code>OdfOfficeMeta</code> feature.
   *
   * @param metaDom the file DOM element of meta.xml
   */
  public OdfOfficeMeta(OdfFileDom metaDom) {
    OfficeDocumentMetaElement metaEle =
        OdfElement.findFirstChildNode(OfficeDocumentMetaElement.class, metaDom);
    mOfficeMetaElement = OdfElement.findFirstChildNode(OfficeMetaElement.class, metaEle);
  }

  /**
   * Get the instance of <code>OfficeMetaElement</code> which represents this feature.
   *
   * @return the instance of OfficeMetaElement
   */
  public OfficeMetaElement getOfficeMetaElement() {
    return mOfficeMetaElement;
  }

  /**
   * Receives the value of the ODFDOM element representation <code>MetaGeneratorElement</code> , See
   * {@odf.element meta:generator}.
   *
   * @return the generator info of the current document;
   *     <p><code>null</code>, if the element is not set.
   */
  public String getGenerator() {
    MetaGeneratorElement metaGenerator =
        OdfElement.findFirstChildNode(MetaGeneratorElement.class, mOfficeMetaElement);
    if (metaGenerator != null) {
      return metaGenerator.getTextContent();
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>MetaGeneratorElement</code> , See
   * {@odf.element meta:generator}.
   *
   * @param generator set the specified document generator. NULL will remove the element from the
   *     meta.xml.
   */
  public void setGenerator(String generator) {
    MetaGeneratorElement metaGeneratorEle =
        OdfElement.findFirstChildNode(MetaGeneratorElement.class, mOfficeMetaElement);
    if (generator == null) {
      if (metaGeneratorEle != null) {
        mOfficeMetaElement.removeChild(metaGeneratorEle);
      }
    } else {
      if (metaGeneratorEle == null) {
        metaGeneratorEle = mOfficeMetaElement.newMetaGeneratorElement();
      }
      metaGeneratorEle.setTextContent(generator);
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>DcTitleElement</code> , See
   * {@odf.element dc:title}.
   *
   * @return the title of the current document;
   *     <p><code>null</code>, if the element is not set.
   */
  public String getTitle() {

    DcTitleElement titleEle =
        OdfElement.findFirstChildNode(DcTitleElement.class, mOfficeMetaElement);
    if (titleEle != null) {
      return titleEle.getTextContent();
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>DcTitleElement</code> , See
   * {@odf.element dc:title}.
   *
   * @param title set the specified document title. NULL will remove the element from the meta.xml.
   */
  public void setTitle(String title) {
    DcTitleElement titleEle =
        OdfElement.findFirstChildNode(DcTitleElement.class, mOfficeMetaElement);
    if (title == null) {
      if (titleEle != null) {
        mOfficeMetaElement.removeChild(titleEle);
      }
    } else {
      if (titleEle == null) {
        titleEle = mOfficeMetaElement.newDcTitleElement();
      }
      titleEle.setTextContent(title);
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>DcDescriptionElement</code> , See
   * {@odf.element dc:description}.
   *
   * @return the description of the current document;
   *     <p><code>null</code>, if the element is not set.
   */
  public String getDescription() {
    DcDescriptionElement descEle =
        OdfElement.findFirstChildNode(DcDescriptionElement.class, mOfficeMetaElement);
    if (descEle != null) {
      return descEle.getTextContent();
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>DcDescriptionElement</code> , See
   * {@odf.element dc:description}.
   *
   * @param description set the specified document description. NULL will remove the element from
   *     the meta.xml.
   */
  public void setDescription(String description) {
    DcDescriptionElement descEle =
        OdfElement.findFirstChildNode(DcDescriptionElement.class, mOfficeMetaElement);
    if (description == null) {
      if (descEle != null) {
        mOfficeMetaElement.removeChild(descEle);
      }
    } else {
      if (descEle == null) {
        descEle = mOfficeMetaElement.newDcDescriptionElement();
      }
      descEle.setTextContent(description);
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>DcSubjectElement</code> , See
   * {@odf.element dc:subject}.
   *
   * @return the subject of the current document;
   *     <p><code>null</code>, if the element is not set.
   */
  public String getSubject() {
    DcSubjectElement subjectEle =
        OdfElement.findFirstChildNode(DcSubjectElement.class, mOfficeMetaElement);
    if (subjectEle != null) {
      return subjectEle.getTextContent();
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>DcSubjectElement</code> , See
   * {@odf.element dc:subject}.
   *
   * @param subject set the specified document subject. NULL will remove the element from the
   *     meta.xml.
   */
  public void setSubject(String subject) {
    DcSubjectElement subjectEle =
        OdfElement.findFirstChildNode(DcSubjectElement.class, mOfficeMetaElement);
    if (subject == null) {
      if (subjectEle != null) {
        mOfficeMetaElement.removeChild(subjectEle);
      }
    } else {
      if (subjectEle == null) {
        subjectEle = mOfficeMetaElement.newDcSubjectElement();
      }
      subjectEle.setTextContent(subject);
    }
  }

  /**
   * Receives the list value of the ODFDOM element representation <code>MetaKeywordElement</code> ,
   * See {@odf.element meta:keyword}.
   *
   * @return the keywords of the current document;
   *     <p><code>null</code>, if the element is not set.
   */
  public List<String> getKeywords() {
    List<String> keywords = new ArrayList<String>();
    MetaKeywordElement keywordEle =
        OdfElement.findFirstChildNode(MetaKeywordElement.class, mOfficeMetaElement);
    if (keywordEle != null) {
      keywords.add(keywordEle.getTextContent());
      MetaKeywordElement keywordNext;
      while ((keywordNext = OdfElement.findNextChildNode(MetaKeywordElement.class, keywordEle))
          != null) {
        keywords.add(keywordNext.getTextContent());
        keywordEle = keywordNext;
      }
      return keywords;
    } else {
      return null;
    }
  }

  /**
   * Sets the list value of the ODFDOM element representation <code>MetaKeywordElement</code> , See
   * {@odf.element meta:keyword}.
   *
   * @param keyList set the specified list of keywords
   */
  public void setKeywords(List<String> keyList) {
    MetaKeywordElement keywordEle =
        OdfElement.findFirstChildNode(MetaKeywordElement.class, mOfficeMetaElement);
    List<MetaKeywordElement> toBeDeleted = new ArrayList<MetaKeywordElement>();
    if (keywordEle != null) {
      MetaKeywordElement keywordTmp;
      toBeDeleted.add(keywordEle);
      while ((keywordTmp = OdfElement.findNextChildNode(MetaKeywordElement.class, keywordEle))
          != null) {
        keywordEle = keywordTmp;
        toBeDeleted.add(keywordTmp);
      }
    }

    // remove the original
    for (MetaKeywordElement keyele : toBeDeleted) {
      mOfficeMetaElement.removeChild(keyele);
    }
    // add new
    for (int i = 0; i < keyList.size(); i++) {
      MetaKeywordElement keywordElement = mOfficeMetaElement.newMetaKeywordElement();
      keywordElement.setTextContent(keyList.get(i));
    }
  }

  /**
   * Add the keyword to the current document. Create child element {@odf.element meta:keyword}.
   *
   * @param keyword the value of child element {@odf.element meta:keyword}.
   */
  public void addKeyword(String keyword) {
    MetaKeywordElement keywordElement = mOfficeMetaElement.newMetaKeywordElement();
    keywordElement.setTextContent(keyword);
  }

  /**
   * Receives the list value of the ODFDOM element representation <code>MetaUserDefinedElement
   * </code> , See {@odf.element meta:user-defined}.
   *
   * @return get the list of user-defined metadata names;
   *     <p><code>null</code>, if the element is not set.
   */
  public List<String> getUserDefinedDataNames() {
    List<String> definedNames = new ArrayList<String>();
    MetaUserDefinedElement definedEle =
        OdfElement.findFirstChildNode(MetaUserDefinedElement.class, mOfficeMetaElement);
    if (definedEle != null) {

      definedNames.add(definedEle.getMetaNameAttribute());
      MetaUserDefinedElement definedNext;
      while ((definedNext = OdfElement.findNextChildNode(MetaUserDefinedElement.class, definedEle))
          != null) {

        definedNames.add(definedNext.getMetaNameAttribute());

        definedEle = definedNext;
      }
      return definedNames;
    } else {
      return null;
    }
  }

  /**
   * Receives the ODFDOM element representation <code>MetaUserDefinedElement</code> by attribute
   * name, See {@odf.element meta:user-defined}.
   *
   * @param name the name of the user-defined metadata
   * @return the <code>MetaUserDefinedElement</code> which is identified by the specified name;
   *     <p><code>null</code>, if the element is not set.
   */
  public MetaUserDefinedElement getUserDefinedElementByAttributeName(String name) {
    MetaUserDefinedElement definedEle =
        OdfElement.findFirstChildNode(MetaUserDefinedElement.class, mOfficeMetaElement);
    if (definedEle != null) {
      if (definedEle.getMetaNameAttribute().equals(name)) {
        return definedEle;
      }
      MetaUserDefinedElement definedNext;
      while ((definedNext = OdfElement.findNextChildNode(MetaUserDefinedElement.class, definedEle))
          != null) {

        if (definedNext.getMetaNameAttribute().equals(name)) {
          return definedNext;
        }

        definedEle = definedNext;
      }
      return null;
    } else {
      return null;
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>MetaUserDefinedElement</code> by
   * attribute name, See {@odf.element meta:user-defined}.
   *
   * @param name the name of the user-defined metadata
   * @return the value of the user-defined metadata with the specified name;
   *     <p><code>null</code>, if the element is not set.
   */
  public String getUserDefinedDataValue(String name) {
    MetaUserDefinedElement definedElement = getUserDefinedElementByAttributeName(name);
    if (definedElement != null) {
      return definedElement.getTextContent();
    }
    return null;
  }

  /**
   * Receives the data type of the ODFDOM element representation <code>MetaUserDefinedElement</code>
   * by attribute name, See {@odf.element meta:user-defined}.
   *
   * @param name the name of the user-defined metadata
   * @return the data type of the user-defined metadata with the specified name;
   *     <p><code>null</code>, if the element is not set.
   */
  public String getUserDefinedDataType(String name) {
    MetaUserDefinedElement definedElement = getUserDefinedElementByAttributeName(name);
    if (definedElement != null) {
      return definedElement.getMetaValueTypeAttribute();
    }
    return null;
  }

  /**
   * Remove the ODFDOM element representation <code>MetaUserDefinedElement</code> by attribute name,
   * See {@odf.element meta:user-defined}.
   *
   * @param name the name of the user-defined metadata
   */
  public void removeUserDefinedDataByName(String name) {
    MetaUserDefinedElement definedElement = getUserDefinedElementByAttributeName(name);
    if (definedElement != null) {
      mOfficeMetaElement.removeChild(definedElement);
    }
  }

  /**
   * Sets the value of the ODFDOM element representation <code>MetaUserDefinedElement</code> by
   * attribute name, See {@odf.element meta:user-defined}.
   *
   * @param name the name need to set for the user-defined metadata
   * @param value the value need to set for the user-defined metadata
   */
  public void setUserDefinedDataValue(String name, String value) {
    MetaUserDefinedElement definedElement = getUserDefinedElementByAttributeName(name);
    if (definedElement != null) {
      definedElement.setTextContent(value);
    }
  }

  /**
   * Sets the data type of the ODFDOM element representation <code>MetaUserDefinedElement</code> by
   * attribute name, See {@odf.element meta:user-defined}.
   *
   * @param name the name need to set for the user-defined metadata
   * @param value the value need to set for the user-defined metadata
   */
  public void setUserDefinedDataType(String name, String value) {
    MetaUserDefinedElement definedElement = getUserDefinedElementByAttributeName(name);
    if (definedElement != null) {
      definedElement.setMetaValueTypeAttribute(value);
    }
  }

  /**
   * Sets the ODFDOM element representation <code>MetaUserDefinedElement</code> , See {@odf.element
   * meta:user-defined} if the element with the attribute name exists,then update;or create a new
   * element if type or value is null,the original will not be updated.
   *
   * @param name the name need to set for the user-defined metadata
   * @param type the data type need to set for the user-defined metadata
   * @param value the value need to set for the user-defined metadata
   */
  public void setUserDefinedData(String name, String type, String value) {
    // test if name exists
    MetaUserDefinedElement definedElement = getUserDefinedElementByAttributeName(name);
    // if exists, then update,if parameter is null, then don't change
    if (definedElement != null) {
      if (type != null) {
        definedElement.setMetaValueTypeAttribute(type);
      }
      if (value != null) {
        definedElement.setTextContent(value);
      }
    } else {
      // if not exists, add
      definedElement = mOfficeMetaElement.newMetaUserDefinedElement(name, type);
      definedElement.setTextContent(value);
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>MetaInitialCreatorElement</code>
   * , See {@odf.element meta:initial-creator}.
   *
   * @return get the initial creator of the current document;
   *     <p><code>null</code>, if the element is not set.
   */
  public String getInitialCreator() {
    MetaInitialCreatorElement iniCreatorEle =
        OdfElement.findFirstChildNode(MetaInitialCreatorElement.class, mOfficeMetaElement);
    if (iniCreatorEle != null) {
      return iniCreatorEle.getTextContent();
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>MetaInitialCreatorElement</code> ,
   * See {@odf.element meta:initial-creator}.
   *
   * @param initialCreator set the specified initial creator. NULL will remove the element from the
   *     meta.xml.
   */
  public void setInitialCreator(String initialCreator) {
    MetaInitialCreatorElement initialCreatorEle =
        OdfElement.findFirstChildNode(MetaInitialCreatorElement.class, mOfficeMetaElement);
    if (initialCreator == null) {
      if (initialCreatorEle != null) {
        mOfficeMetaElement.removeChild(initialCreatorEle);
      }
    } else {
      if (initialCreatorEle == null) {
        initialCreatorEle = mOfficeMetaElement.newMetaInitialCreatorElement();
      }
      initialCreatorEle.setTextContent(initialCreator);
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>DcCreatorElement</code> , See
   * {@odf.element dc:creator}
   *
   * @return the creator of the current document;
   *     <p><code>null</code>, if the element is not set.
   */
  public String getCreator() {
    DcCreatorElement creatorEle =
        OdfElement.findFirstChildNode(DcCreatorElement.class, mOfficeMetaElement);
    if (creatorEle != null) {
      return creatorEle.getTextContent();
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>DcCreatorElement</code> , See
   * {@odf.element dc:creator}.
   *
   * @param creator set the specified creator. NULL will remove the element from the meta.xml.
   */
  public void setCreator(String creator) {
    DcCreatorElement creatorEle =
        OdfElement.findFirstChildNode(DcCreatorElement.class, mOfficeMetaElement);
    if (creator == null) {
      if (creatorEle != null) {
        mOfficeMetaElement.removeChild(creatorEle);
      }
    } else {
      if (creatorEle == null) {
        creatorEle = mOfficeMetaElement.newDcCreatorElement();
      }
      creatorEle.setTextContent(creator);
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>MetaPrintedByElement</code> , See
   * {@odf.element meta:printed-by}
   *
   * @return the name of the last person who printed the current document;
   *     <p><code>null</code>, if element is not set
   */
  public String getPrintedBy() {
    MetaPrintedByElement printedByEle =
        OdfElement.findFirstChildNode(MetaPrintedByElement.class, mOfficeMetaElement);
    if (printedByEle != null) {
      return printedByEle.getTextContent();
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>MetaPrintedByElement</code> , See
   * {@odf.element meta:printed-by}.
   *
   * @param printedBy the name need to set for the last person who printed the current document.
   *     NULL will remove the element from the meta.xml.
   */
  public void setPrintedBy(String printedBy) {
    MetaPrintedByElement printedByEle =
        OdfElement.findFirstChildNode(MetaPrintedByElement.class, mOfficeMetaElement);
    if (printedBy == null) {
      if (printedByEle != null) {
        mOfficeMetaElement.removeChild(printedByEle);
      }
    } else {
      if (printedByEle == null) {
        printedByEle = mOfficeMetaElement.newMetaPrintedByElement();
      }
      printedByEle.setTextContent(printedBy);
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>MetaCreationDateElement</code> ,
   * See {@odf.element meta:creation-date}
   *
   * @return the date and time when the document was created initially;
   *     <p><code>null</code>, if element is not set
   */
  public Calendar getCreationDate() {
    MetaCreationDateElement creationDateEle =
        OdfElement.findFirstChildNode(MetaCreationDateElement.class, mOfficeMetaElement);
    if (creationDateEle != null) {
      return stringToCalendar(creationDateEle.getTextContent());
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>MetaCreationDateElement</code> , See
   * {@odf.element meta:creation-date}.
   *
   * @param creationDate the date and time need to set. NULL will remove the element from the
   *     meta.xml.
   */
  public void setCreationDate(Calendar creationDate) {
    MetaCreationDateElement creationDateEle =
        OdfElement.findFirstChildNode(MetaCreationDateElement.class, mOfficeMetaElement);
    if (creationDate == null) {
      if (creationDateEle != null) {
        mOfficeMetaElement.removeChild(creationDateEle);
      }
    } else {
      if (creationDateEle == null) {
        creationDateEle = mOfficeMetaElement.newMetaCreationDateElement();
      }
      creationDateEle.setTextContent(calendarToString(creationDate));
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>DcDateElement</code> , See
   * {@odf.element dc:date}.
   *
   * @return the date and time when the document was last modified;
   *     <p><code>null</code>, if the element is not set.
   */
  public Calendar getDate() {
    DcDateElement dcDateEle =
        OdfElement.findFirstChildNode(DcDateElement.class, mOfficeMetaElement);
    if (dcDateEle != null) {
      return stringToCalendar(dcDateEle.getTextContent());
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>DcDateElement</code> , See
   * {@odf.element dc:date}.
   *
   * @param date the date and time need to set. NULL will remove the element from the meta.xml.
   */
  public void setDate(Calendar date) {
    DcDateElement dcDateEle =
        OdfElement.findFirstChildNode(DcDateElement.class, mOfficeMetaElement);
    if (date == null) {
      if (dcDateEle != null) {
        mOfficeMetaElement.removeChild(dcDateEle);
      }
    } else {
      if (dcDateEle == null) {
        dcDateEle = mOfficeMetaElement.newDcDateElement();
      }
      dcDateEle.setTextContent(calendarToString(date));
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>MetaPrintDateElement</code> , See
   * {@odf.element meta:print-date}.
   *
   * @return the date and time when the document was last printed;
   *     <p><code>null</code>, if the element is not set.
   */
  public Calendar getPrintDate() {
    MetaPrintDateElement printDateEle =
        OdfElement.findFirstChildNode(MetaPrintDateElement.class, mOfficeMetaElement);
    if (printDateEle != null) {
      return stringToCalendar(printDateEle.getTextContent());
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>MetaPrintDateElement</code> , See
   * {@odf.element meta:print-date}.
   *
   * @param printDate the date and time need to set. NULL will remove the element from the meta.xml.
   */
  public void setPrintDate(Calendar printDate) {
    MetaPrintDateElement printDateEle =
        OdfElement.findFirstChildNode(MetaPrintDateElement.class, mOfficeMetaElement);
    if (printDate == null) {
      if (printDateEle != null) {
        mOfficeMetaElement.removeChild(printDateEle);
      }
    } else {
      if (printDateEle == null) {
        printDateEle = mOfficeMetaElement.newMetaPrintDateElement();
      }
      printDateEle.setTextContent(calendarToString(printDate));
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>DcLanguageElement</code> , See
   * {@odf.element dc:language}.
   *
   * @return the default language of the document;
   *     <p><code>null</code>, if the element is not set.
   */
  public String getLanguage() {
    DcLanguageElement languageEle =
        OdfElement.findFirstChildNode(DcLanguageElement.class, mOfficeMetaElement);
    if (languageEle != null) {
      return languageEle.getTextContent();
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>DcLanguageElement</code> , See
   * {@odf.element dc:language}.
   *
   * @param language the default language need to set fo the current document. NULL will remove the
   *     element from the meta.xml.
   */
  public void setLanguage(String language) {
    DcLanguageElement languageEle =
        OdfElement.findFirstChildNode(DcLanguageElement.class, mOfficeMetaElement);
    if (language == null) {
      if (languageEle != null) {
        mOfficeMetaElement.removeChild(languageEle);
      }
    } else {
      if (languageEle == null) {
        languageEle = mOfficeMetaElement.newDcLanguageElement();
      }
      languageEle.setTextContent(language);
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>MetaEditingCyclesElement</code> ,
   * See {@odf.element meta:editing-cycles}.
   *
   * @return the number of times that the document has been edited;
   *     <p><code>null</code>, if the element is not set.
   */
  public Integer getEditingCycles() {
    MetaEditingCyclesElement editingCyclesEle =
        OdfElement.findFirstChildNode(MetaEditingCyclesElement.class, mOfficeMetaElement);
    if (editingCyclesEle != null) {
      return Integer.valueOf(editingCyclesEle.getTextContent());
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>MetaEditingCyclesElement</code> , See
   * {@odf.element meta:editing-cycles}.
   *
   * @param editingCycles set the specified edit times. NULL will remove the element from the
   *     meta.xml.
   */
  public void setEditingCycles(Integer editingCycles) {
    MetaEditingCyclesElement editingCyclesEle =
        OdfElement.findFirstChildNode(MetaEditingCyclesElement.class, mOfficeMetaElement);
    if (editingCycles == null) {
      if (editingCyclesEle != null) {
        mOfficeMetaElement.removeChild(editingCyclesEle);
      }
    } else {
      if (editingCyclesEle == null) {
        editingCyclesEle = mOfficeMetaElement.newMetaEditingCyclesElement();
      }
      editingCyclesEle.setTextContent(String.valueOf(editingCycles));
    }
  }

  /**
   * Receives the value of the ODFDOM element representation <code>MetaEditingDurationElement</code>
   * , See {@odf.element meta:editing-duration}.
   *
   * @return the total time spent editing the document;
   *     <p><code>null</code>, if the element is not set.
   */
  public Duration getEditingDuration() {
    MetaEditingDurationElement editiingDurationEle =
        OdfElement.findFirstChildNode(MetaEditingDurationElement.class, mOfficeMetaElement);
    if (editiingDurationEle != null) {
      return Duration.valueOf(editiingDurationEle.getTextContent());
    }
    return null;
  }

  /**
   * Sets the value of the ODFDOM element representation <code>MetaEditingDurationElement</code> ,
   * See {@odf.element meta:editing-duration}.
   *
   * @param editingDuration the time need to set. NULL will remove the element from the meta.xml.
   */
  public void setEditingDuration(Duration editingDuration) {
    MetaEditingDurationElement editingDurationEle =
        OdfElement.findFirstChildNode(MetaEditingDurationElement.class, mOfficeMetaElement);
    if (editingDuration == null) {
      if (editingDurationEle != null) {
        mOfficeMetaElement.removeChild(editingDurationEle);
      }
    } else {
      if (editingDurationEle == null) {
        editingDurationEle = mOfficeMetaElement.newMetaEditingDurationElement();
      }
      editingDurationEle.setTextContent(editingDuration.toString());
    }
  }

  /**
   * Receives the sub feature of OdfMetaDocumentStatistic.
   *
   * @return the statistics about the document which can be represented by <code>
   *     OdfMetaDocumentStatistic</code> feature;
   *     <p><code>null</code>, if the feature is not exist.
   */
  public OdfMetaDocumentStatistic getDocumentStatistic() {
    MetaDocumentStatisticElement element = getDocumentStatisticElement();
    if (element != null) {
      return new OdfMetaDocumentStatistic(element);
    } else {
      return null;
    }
  }

  /**
   * Receives the OdfMetaHyperlinkBehaviour feature.
   *
   * @return the default behavior of hyperlinks in the current document which can be represented by
   *     <code>OdfMetaHyperlinkBehaviour</code> feature;
   *     <p><code>null</code>, if the feature is not exist.
   */
  public OdfMetaHyperlinkBehaviour getHyperlinkBehaviour() {
    MetaHyperlinkBehaviourElement element = getHyperlinkBehaviourElement();
    if (element != null) {
      return new OdfMetaHyperlinkBehaviour(element);
    } else {
      return null;
    }
  }

  /**
   * Receives the OdfMetaAutoReload feature.
   *
   * @return the information whether the document is reloaded or replaced by another document after
   *     a certain period of time has elapsed.
   *     <p>It can be represented by <code>OdfMetaAutoReload</code> feature;
   *     <p><code>null</code>, if the feature is not exist.
   */
  public OdfMetaAutoReload getAutoReload() {
    MetaAutoReloadElement element = getAutoReloadElement();
    if (element != null) {
      return new OdfMetaAutoReload(element);
    } else {
      return null;
    }
  }

  /**
   * Receives the OdfMetaTemplate feature.
   *
   * @return the information specified the URL for the document that was used to create a document.
   *     <p>It can be represented by <code>OdfMetaTemplate</code> feature;
   *     <p><code>null</code>, if the feature is not exist.
   */
  public OdfMetaTemplate getTemplate() {
    MetaTemplateElement element = getTemplateElement();
    if (element != null) {
      return new OdfMetaTemplate(element);
    } else {
      return null;
    }
  }

  private MetaDocumentStatisticElement getDocumentStatisticElement() {
    return OdfElement.findFirstChildNode(MetaDocumentStatisticElement.class, mOfficeMetaElement);
  }

  private MetaHyperlinkBehaviourElement getHyperlinkBehaviourElement() {
    return OdfElement.findFirstChildNode(MetaHyperlinkBehaviourElement.class, mOfficeMetaElement);
  }

  private MetaAutoReloadElement getAutoReloadElement() {
    return OdfElement.findFirstChildNode(MetaAutoReloadElement.class, mOfficeMetaElement);
  }

  private MetaTemplateElement getTemplateElement() {
    return OdfElement.findFirstChildNode(MetaTemplateElement.class, mOfficeMetaElement);
  }

  /**
   * Change valid string of calendar to Calendar type.
   *
   * @param baseDate the string of a calender
   * @return the object of Calender
   */
  private Calendar stringToCalendar(String baseDate) {
    // Calendar calendar=new GregorianCalendar();
    Calendar calendar = Calendar.getInstance();
    Date d1 = null;
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

    try {
      d1 = sdf.parse(baseDate);
    } catch (Exception e) {
      // invalid format or null value in meta.xml
      // d1=new Date();
    }

    calendar.setTime(d1);
    return calendar;
  }

  /**
   * Convert a <code>Canlender</code> object to <code>String</code> object.
   *
   * @param calendar an instanceof <code>Canlender</code>
   * @return the String format(yyyy-MM-dd'T'HH:mm:ss) of Calendar.
   */
  private String calendarToString(Calendar calendar) {
    return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(calendar.getTime());
  }

  /**
   * @param enableAutomaticUpdate If the automatic update of metadata is enabled, metadata such as
   *     last modified data is set during saving the document. The default is <code>true</code>,
   *     disabling the default allows to load and save a document without changing any data.
   */
  public void setAutomaticUpdate(boolean enableAutomaticUpdate) {
    mAutomaticUpdate = enableAutomaticUpdate;
  }

  /**
   * @return If the automatic update of metadata is enabled, metadata such as last modified data is
   *     set during saving the document. The default is <code>true</code>, disabling the default
   *     allows to load and save a document without changing any data.
   */
  public boolean hasAutomaticUpdate() {
    return mAutomaticUpdate;
  }

  @Override
  public String toString() {
    if (mOfficeMetaElement != null) {
      return mOfficeMetaElement.toString();
    } else {
      return null;
    }
  }
}