incubator-odf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From svanteschub...@apache.org
Subject svn commit: r1747358 [2/3] - in /incubator/odf/trunk/simple/src: main/java/org/odftoolkit/simple/Document.java test/java/org/odftoolkit/simple/text/SectionTest.java test/resources/SectionContinuedList.odt
Date Wed, 08 Jun 2016 07:18:50 GMT

Modified: incubator/odf/trunk/simple/src/main/java/org/odftoolkit/simple/Document.java
URL: http://svn.apache.org/viewvc/incubator/odf/trunk/simple/src/main/java/org/odftoolkit/simple/Document.java?rev=1747358&r1=1747357&r2=1747358&view=diff
==============================================================================
--- incubator/odf/trunk/simple/src/main/java/org/odftoolkit/simple/Document.java (original)
+++ incubator/odf/trunk/simple/src/main/java/org/odftoolkit/simple/Document.java Wed Jun  8 07:18:50 2016
@@ -1,4 +1,5 @@
-/************************************************************************
+/**
+ * **********************************************************************
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
  *
@@ -18,7 +19,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
- ************************************************************************/
+ ***********************************************************************
+ */
 package org.odftoolkit.simple;
 
 import java.io.ByteArrayInputStream;
@@ -105,2565 +107,2620 @@ import org.xml.sax.ErrorHandler;
  * This abstract class is representing one of the possible ODF documents
  */
 public abstract class Document extends OdfSchemaDocument implements TableContainer {
-	// Static parts of file references
-	private static final String SLASH = "/";
-	private OdfMediaType mMediaType;
-	private Meta mOfficeMeta;
-	private long documentOpeningTime;
-	private TableContainerImpl tableContainerImpl;
-	private static final Pattern CONTROL_CHAR_PATTERN = Pattern.compile("\\p{Cntrl}");
-	private static final String EMPTY_STRING = "";
-
-	private IdentityHashMap<OdfElement, Component> mComponentRepository = new IdentityHashMap<OdfElement, Component>();
-
-	// FIXME: This field is only used in method copyResourcesFrom to improve
-	// copy performance, should not be used in any other way.
-	// methods loadDocument(String documentPath) and loadDocument(File file)
-	// will initialize it.
-	// This field and its methods should be removed after ODFDOM supplies batch
-	// copy.
-	private File mFile = null;
-
-	// if the copy foreign slide for several times,
-	// the same style might be copied for several times with the different name
-	// so use styleRenameMap to keep track the renamed style so we can reuse the
-	// style,
-	// rather than new several styles which only have the different style names.
-	// while if the style elements really have the same style name but with
-	// different content
-	// such as that these style elements are from different document
-	// so the value for each key should be a list
-	private HashMap<String, List<String>> styleRenameMap = new HashMap<String, List<String>>();
-	// the map is used to record if the renamed style name is appended to the
-	// current dom
-	private HashMap<String, Boolean> styleAppendMap = new HashMap<String, Boolean>();
-
-	// the object rename map for image.
-	// can not easily recognize if the embedded document are the same.
-	// private HashMap<String, String> objectRenameMap = new HashMap<String,
-	// String>();
-
-	// Using static factory instead of constructor
-	protected Document(OdfPackage pkg, String internalPath, OdfMediaType mediaType) {
-		super(pkg, internalPath, mediaType.getMediaTypeString());
-		mMediaType = mediaType;
-		// set document opening time.
-		documentOpeningTime = System.currentTimeMillis();
-	}
-
-	/**
-	 * This enum contains all possible media types of Document documents.
-	 */
-	public enum OdfMediaType implements MediaType {
-
-		CHART("application/vnd.oasis.opendocument.chart", "odc"),
-		CHART_TEMPLATE("application/vnd.oasis.opendocument.chart-template", "otc"),
-		FORMULA("application/vnd.oasis.opendocument.formula", "odf"),
-		FORMULA_TEMPLATE("application/vnd.oasis.opendocument.formula-template", "otf"),
-		DATABASE_FRONT_END("application/vnd.oasis.opendocument.base", "odb"),
-		GRAPHICS("application/vnd.oasis.opendocument.graphics", "odg"),
-		GRAPHICS_TEMPLATE("application/vnd.oasis.opendocument.graphics-template", "otg"),
-		IMAGE("application/vnd.oasis.opendocument.image", "odi"),
-		IMAGE_TEMPLATE("application/vnd.oasis.opendocument.image-template", "oti"),
-		PRESENTATION("application/vnd.oasis.opendocument.presentation", "odp"),
-		PRESENTATION_TEMPLATE("application/vnd.oasis.opendocument.presentation-template", "otp"),
-		SPREADSHEET("application/vnd.oasis.opendocument.spreadsheet", "ods"),
-		SPREADSHEET_TEMPLATE("application/vnd.oasis.opendocument.spreadsheet-template", "ots"),
-		TEXT("application/vnd.oasis.opendocument.text", "odt"),
-		TEXT_MASTER("application/vnd.oasis.opendocument.text-master", "odm"),
-		TEXT_TEMPLATE("application/vnd.oasis.opendocument.text-template", "ott"),
-		TEXT_WEB("application/vnd.oasis.opendocument.text-web", "oth");
-
-		private final String mMediaType;
-		private final String mSuffix;
-
-		OdfMediaType(String mediaType, String suffix) {
-			this.mMediaType = mediaType;
-			this.mSuffix = suffix;
-		}
-
-		/**
-		 * @return the mediatype String of this document
-		 */
-		public String getMediaTypeString() {
-			return mMediaType;
-		}
-
-		/**
-		 * @return the ODF filesuffix of this document
-		 */
-		public String getSuffix() {
-			return mSuffix;
-		}
-
-		/**
-		 *
-		 * @param mediaType
-		 *            string defining an ODF document
-		 * @return the according OdfMediatype encapuslating the given string and
-		 *         the suffix
-		 */
-		public static OdfMediaType getOdfMediaType(String mediaType) {
-			OdfMediaType odfMediaType = null;
-			if (mediaType != null) {
-				String mediaTypeShort = mediaType.substring(mediaType.lastIndexOf(".") + 1, mediaType.length());
-				mediaTypeShort = mediaTypeShort.replace('-', '_').toUpperCase();
-				try {
-					odfMediaType = OdfMediaType.valueOf(mediaTypeShort);
-				} catch (IllegalArgumentException e) {
-					throw new IllegalArgumentException("Given mediaType '" + mediaType + "' is either not yet supported or not an ODF mediatype!");
-				}
-			}
-			return odfMediaType;
-		}
-	}
-
-	/**
-	 * Loads an Document from the given resource. NOTE: Initial meta data will
-	 * be added in this method.
-	 *
-	 * @param res
-	 *            a resource containing a package with a root document
-	 * @param odfMediaType
-	 *            the media type of the root document
-	 * @return the Document document or NULL if the media type is not supported
-	 *         by SIMPLE.
-	 * @throws java.lang.Exception
-	 *             - if the document could not be created.
-	 */
-	protected static Document loadTemplate(Resource res, OdfMediaType odfMediaType) throws Exception {
-		InputStream in = res.createInputStream();
-		OdfPackage pkg = null;
-		try {
-			pkg = OdfPackage.loadPackage(in);
-		} finally {
-			in.close();
-		}
-		Document newDocument = newDocument(pkg, ROOT_DOCUMENT_PATH, odfMediaType);
-		// add initial meta data to new document.
-		initializeMetaData(newDocument);
-		return newDocument;
-	}
-
-	/**
-	 * Loads a Document from the provided path.
-	 *
-	 * <p>
-	 * Document relies on the file being available for read access over the
-	 * whole life cycle of Document.
-	 * </p>
-	 *
-	 * @param documentPath
-	 *            - the path from where the document can be loaded
-	 * @param password
-	 *            - file password.
-	 * @return the Document from the given path or NULL if the media type is not
-	 *         supported by SIMPLE.
-	 * @throws java.lang.Exception
-	 *             - if the document could not be created.
-	 * @since 0.8
-	 */
-	public static Document loadDocument(String documentPath, String password) throws Exception {
-		File file = new File(documentPath);
-		return loadDocument(file, password);
-	}
-
-	/**
-	 * Loads a Document from the provided path.
-	 *
-	 * <p>
-	 * Document relies on the file being available for read access over the
-	 * whole life cycle of Document.
-	 * </p>
-	 *
-	 * @param documentPath
-	 *            - the path from where the document can be loaded
-	 * @return the Document from the given path or NULL if the media type is not
-	 *         supported by SIMPLE.
-	 * @throws java.lang.Exception
-	 *             - if the document could not be created.
-	 */
-	public static Document loadDocument(String documentPath) throws Exception {
-		File file = new File(documentPath);
-		return loadDocument(file);
-	}
-
-	/**
-	 * Creates a Document from the Document provided by a resource Stream.
-	 *
-	 * <p>
-	 * Since an InputStream does not provide the arbitrary (non sequentiell)
-	 * read access needed by Document, the InputStream is cached. This usually
-	 * takes more time compared to the other createInternalDocument methods. An
-	 * advantage of caching is that there are no problems overwriting an input
-	 * file.
-	 * </p>
-	 *
-	 * @param inStream
-	 *            - the InputStream of the ODF document.
-	 * @return the document created from the given InputStream
-	 * @throws java.lang.Exception
-	 *             - if the document could not be created.
-	 */
-	public static Document loadDocument(InputStream inStream) throws Exception {
-		return loadDocument(OdfPackage.loadPackage(inStream));
-	}
-
-	/**
-	 * Creates a Document from the Document provided by a File.
-	 *
-	 * <p>
-	 * Document relies on the file being available for read access over the
-	 * whole lifecycle of Document.
-	 * </p>
-	 *
-	 * @param file
-	 *            - a file representing the ODF document.
-	 * @return the document created from the given File
-	 * @throws java.lang.Exception
-	 *             - if the document could not be created.
-	 */
-	public static Document loadDocument(File file) throws Exception {
-		Document doc = loadDocument(OdfPackage.loadPackage(file));
-		doc.setFile(file);
-		return doc;
-	}
-
-	/**
-	 * Creates a Document from the Document provided by a File.
-	 *
-	 * <p>
-	 * Document relies on the file being available for read access over the
-	 * whole lifecycle of Document.
-	 * </p>
-	 *
-	 * @param file
-	 *            - a file representing the ODF document.
-	 * @param password
-	 *            - file password.
-	 * @return the document created from the given File
-	 * @throws java.lang.Exception
-	 *             - if the document could not be created.
-	 * @since 0.7
-	 */
-	public static Document loadDocument(File file, String password) throws Exception {
-		Document doc = loadDocument(OdfPackage.loadPackage(file, password, null));
-		doc.setFile(file);
-		return doc;
-	}
-
-	/**
-	 * Creates a Document from the Document provided by an ODF package.
-	 *
-	 * @param odfPackage
-	 *            - the ODF package containing the ODF document.
-	 * @return the root document of the given OdfPackage
-	 * @throws java.lang.Exception
-	 *             - if the ODF document could not be created.
-	 */
-	public static Document loadDocument(OdfPackage odfPackage) throws Exception {
-		return loadDocument(odfPackage, ROOT_DOCUMENT_PATH);
-	}
-
-	/**
-	 * Creates a Document from the Document provided by an ODF package.
-	 *
-	 * @param odfPackage
-	 *            - the ODF package containing the ODF document.
-	 * @param internalPath
-	 *            - the path to the ODF document relative to the package root.
-	 * @return the root document of the given OdfPackage
-	 * @throws java.lang.Exception
-	 *             - if the ODF document could not be created.
-	 */
-	public static Document loadDocument(OdfPackage odfPackage, String internalPath) throws Exception {
-		String documentMediaType = odfPackage.getMediaTypeString(internalPath);
-		if (documentMediaType == null) {
-			throw new IllegalArgumentException("Given internalPath '" + internalPath + "' is an illegal or inappropriate argument.");
-		}
-		OdfMediaType odfMediaType = OdfMediaType.getOdfMediaType(documentMediaType);
-		if (odfMediaType == null) {
-			ErrorHandler errorHandler = odfPackage.getErrorHandler();
-			Matcher matcherCTRL = CONTROL_CHAR_PATTERN.matcher(documentMediaType);
-			if (matcherCTRL.find()) {
-				documentMediaType = matcherCTRL.replaceAll(EMPTY_STRING);
-			}
-			OdfValidationException ve = new OdfValidationException(OdfSchemaConstraint.DOCUMENT_WITHOUT_ODF_MIMETYPE, internalPath, documentMediaType);
-			if (errorHandler != null) {
-				errorHandler.fatalError(ve);
-			}
-			throw ve;
-		}
-		return newDocument(odfPackage, internalPath, odfMediaType);
-	}
-
-	/**
-	 * Sets password of this document.
-	 *
-	 * @param password
-	 *            the password of this document.
-	 * @since 0.8
-	 */
-	public void setPassword(String password) {
-		getPackage().setPassword(password);
-	}
-
-	// return null if the media type can not be recognized.
-	private static Document loadDocumentFromTemplate(OdfMediaType odfMediaType) throws Exception {
-
-		switch (odfMediaType) {
-		case TEXT:
-		case TEXT_TEMPLATE:
-		case TEXT_MASTER:
-		case TEXT_WEB:
-			// documentTemplate = TextDocument.EMPTY_TEXT_DOCUMENT_RESOURCE;
-			TextDocument document = TextDocument.newTextDocument();
-			document.changeMode(TextDocument.OdfMediaType.TEXT_WEB);
-			return document;
-
-		case SPREADSHEET:
-			SpreadsheetDocument spreadsheet = SpreadsheetDocument.newSpreadsheetDocument();
-			spreadsheet.changeMode(SpreadsheetDocument.OdfMediaType.SPREADSHEET);
-			return spreadsheet;
-
-		case SPREADSHEET_TEMPLATE:
-			SpreadsheetDocument spreadsheettemplate = SpreadsheetDocument.newSpreadsheetDocument();
-			spreadsheettemplate.changeMode(SpreadsheetDocument.OdfMediaType.SPREADSHEET_TEMPLATE);
-			return spreadsheettemplate;
-
-		case PRESENTATION:
-			PresentationDocument presentation = PresentationDocument.newPresentationDocument();
-			presentation.changeMode(PresentationDocument.OdfMediaType.PRESENTATION);
-			return presentation;
-
-		case PRESENTATION_TEMPLATE:
-			PresentationDocument presentationtemplate = PresentationDocument.newPresentationDocument();
-			presentationtemplate.changeMode(PresentationDocument.OdfMediaType.PRESENTATION_TEMPLATE);
-			return presentationtemplate;
-
-		case GRAPHICS:
-			GraphicsDocument graphics = GraphicsDocument.newGraphicsDocument();
-			graphics.changeMode(GraphicsDocument.OdfMediaType.GRAPHICS);
-			return graphics;
-
-		case GRAPHICS_TEMPLATE:
-			GraphicsDocument graphicstemplate = GraphicsDocument.newGraphicsDocument();
-			graphicstemplate.changeMode(GraphicsDocument.OdfMediaType.GRAPHICS_TEMPLATE);
-			return graphicstemplate;
-
-		case CHART:
-			ChartDocument chart = ChartDocument.newChartDocument();
-			chart.changeMode(ChartDocument.OdfMediaType.CHART);
-			return chart;
-
-		case CHART_TEMPLATE:
-			ChartDocument charttemplate = ChartDocument.newChartDocument();
-			charttemplate.changeMode(ChartDocument.OdfMediaType.CHART_TEMPLATE);
-			return charttemplate;
-
-			// case IMAGE:
-			// case IMAGE_TEMPLATE:
-
-		default:
-			throw new IllegalArgumentException("Given mediaType '" + odfMediaType.toString() + "' is either not yet supported or not an ODF mediatype!");
-		}
-	}
-
-	/**
-	 * Creates one of the ODF documents based a given mediatype.
-	 *
-	 * @param odfMediaType
-	 *            The ODF Mediatype of the ODF document to be created.
-	 * @return The ODF document, which mediatype dependends on the parameter or
-	 *         NULL if media type were not supported.
-	 */
-	private static Document newDocument(OdfPackage pkg, String internalPath, OdfMediaType odfMediaType) {
-		Document newDoc = null;
-		switch (odfMediaType) {
-		case TEXT:
-			newDoc = new TextDocument(pkg, internalPath, TextDocument.OdfMediaType.TEXT);
-			break;
-
-		case TEXT_TEMPLATE:
-			newDoc = new TextDocument(pkg, internalPath, TextDocument.OdfMediaType.TEXT_TEMPLATE);
-			break;
-
-		case TEXT_MASTER:
-			newDoc = new TextDocument(pkg, internalPath, TextDocument.OdfMediaType.TEXT_MASTER);
-			break;
-
-		case TEXT_WEB:
-			newDoc = new TextDocument(pkg, internalPath, TextDocument.OdfMediaType.TEXT_WEB);
-			break;
-
-		case SPREADSHEET:
-			newDoc = new SpreadsheetDocument(pkg, internalPath, SpreadsheetDocument.OdfMediaType.SPREADSHEET);
-			break;
-
-		case SPREADSHEET_TEMPLATE:
-			newDoc = new SpreadsheetDocument(pkg, internalPath, SpreadsheetDocument.OdfMediaType.SPREADSHEET_TEMPLATE);
-			break;
-
-		case PRESENTATION:
-			newDoc = new PresentationDocument(pkg, internalPath, PresentationDocument.OdfMediaType.PRESENTATION);
-			break;
-
-		case PRESENTATION_TEMPLATE:
-			newDoc = new PresentationDocument(pkg, internalPath, PresentationDocument.OdfMediaType.PRESENTATION_TEMPLATE);
-			break;
-
-		case GRAPHICS:
-			newDoc = new GraphicsDocument(pkg, internalPath, GraphicsDocument.OdfMediaType.GRAPHICS);
-			break;
-
-		case GRAPHICS_TEMPLATE:
-			newDoc = new GraphicsDocument(pkg, internalPath, GraphicsDocument.OdfMediaType.GRAPHICS_TEMPLATE);
-			break;
-
-		case CHART:
-			newDoc = new ChartDocument(pkg, internalPath, ChartDocument.OdfMediaType.CHART);
-			break;
-
-		case CHART_TEMPLATE:
-			newDoc = new ChartDocument(pkg, internalPath, ChartDocument.OdfMediaType.CHART_TEMPLATE);
-			break;
-		// case IMAGE:
-		// case IMAGE_TEMPLATE:
-
-		default:
-			newDoc = null;
-			throw new IllegalArgumentException("Given mediaType '" + odfMediaType.mMediaType + "' is not yet supported!");
-		}
-		// returning null if MediaType is not supported
-		return newDoc;
-	}
-
-	/**
-	 * Returns an embedded OdfPackageDocument from the given package path.
-	 *
-	 * @param documentPath
-	 *            path to the ODF document within the package. The path is
-	 *            relative to the current document.
-	 * @return an embedded Document
-	 */
-	public Document getEmbeddedDocument(String documentPath) {
-		String internalPath = getDocumentPath() + documentPath;
-		internalPath = normalizeDocumentPath(internalPath);
-		Document embeddedDocument = (Document) mPackage.getCachedDocument(internalPath);
-		// if the document was not already loaded, fine mimetype and create a
-		// new instance
-		if (embeddedDocument == null) {
-			String mediaTypeString = getMediaTypeString();
-			OdfMediaType odfMediaType = OdfMediaType.getOdfMediaType(mediaTypeString);
-			if (odfMediaType == null) {
-				embeddedDocument = newDocument(mPackage, internalPath, odfMediaType);
-			} else {
-				try {
-					String documentMediaType = mPackage.getMediaTypeString(internalPath);
-					odfMediaType = OdfMediaType.getOdfMediaType(documentMediaType);
-					if (odfMediaType == null) {
-						return null;
-					}
-					embeddedDocument = Document.loadDocument(mPackage, internalPath);
-				} catch (Exception ex) {
-					Logger.getLogger(OdfPackageDocument.class.getName()).log(Level.SEVERE, null, ex);
-				}
-			}
-		}
-		return embeddedDocument;
-	}
-
-	/**
-	 * Method returns all embedded OdfPackageDocuments, which match a valid
-	 * OdfMediaType, of the root OdfPackageDocument.
-	 *
-	 * @return a list with all embedded documents of the root OdfPackageDocument
-	 */
-	// ToDo: (Issue 219 - PackageRefactoring) - Better return Path of
-	// Documents??
-	public List<Document> getEmbeddedDocuments() {
-		List<Document> embeddedObjects = new ArrayList<Document>();
-		// ToDo: (Issue 219 - PackageRefactoring) - Algorithm enhancement:
-		// Instead going through all the files for each mimetype, better
-		// Check all files, which have a mimetype if it is one of the desired,
-		// perhaps start with ODF prefix
-		for (OdfMediaType mediaType : OdfMediaType.values()) {
-			embeddedObjects.addAll(getEmbeddedDocuments(mediaType));
-		}
-		return embeddedObjects;
-	}
-
-	/**
-	 * Method returns all embedded OdfPackageDocuments of the root
-	 * OdfPackageDocument matching the according MediaType. This is done by
-	 * matching the subfolder entries of the manifest file with the given
-	 * OdfMediaType.
-	 *
-	 * @param mediaType
-	 *            media type which is used as a filter
-	 * @return embedded documents of the root OdfPackageDocument matching the
-	 *         given media type
-	 */
-	public List<Document> getEmbeddedDocuments(OdfMediaType mediaType) {
-		String wantedMediaString = null;
-		if (mediaType != null) {
-			wantedMediaString = mediaType.getMediaTypeString();
-		}
-		List<Document> embeddedObjects = new ArrayList<Document>();
-		// check manifest for current embedded OdfPackageDocuments
-		Set<String> manifestEntries = mPackage.getFilePaths();
-		for (String path : manifestEntries) {
-			// any directory that is not the root document "/"
-			if (path.length() > 1 && path.endsWith(SLASH)) {
-				String entryMediaType = mPackage.getFileEntry(path).getMediaTypeString();
-				// if the entry is a document (directory has mediaType)
-				if (entryMediaType != null) {
-					// if a specific ODF mediatype was requested
-					if (wantedMediaString != null) {
-						// test if the desired mediatype matches the current
-						if (entryMediaType.equals(wantedMediaString)) {
-							normalizeDocumentPath(path);
-							embeddedObjects.add(getEmbeddedDocument(path));
-						}
-					} else {
-						// test if any ODF mediatype matches the current
-						for (OdfMediaType type : OdfMediaType.values()) {
-							if (entryMediaType.equals(type.getMediaTypeString())) {
-								embeddedObjects.add(getEmbeddedDocument(path));
-							}
-						}
-					}
-				}
-			}
-		}
-		return embeddedObjects;
-	}
-
-	/**
-	 * Embed an OdfPackageDocument to the current OdfPackageDocument. All the
-	 * file entries of child document will be embedded as well to the current
-	 * document package.
-	 *
-	 * @param documentPath
-	 *            to the directory the ODF document should be inserted (relative
-	 *            to the current document).
-	 * @param sourceDocument
-	 *            the OdfPackageDocument to be embedded.
-	 */
-	public void insertDocument(OdfPackageDocument sourceDocument, String documentPath) {
-		super.insertDocument(sourceDocument, documentPath);
-	}
-
-	/**
-	 * Sets the media type of the Document
-	 *
-	 * @param odfMediaType
-	 *            media type to be set
-	 */
-	protected void setOdfMediaType(OdfMediaType odfMediaType) {
-		mMediaType = odfMediaType;
-		super.setMediaTypeString(odfMediaType.getMediaTypeString());
-	}
-
-	/**
-	 * Gets the media type of the Document
-	 */
-	protected OdfMediaType getOdfMediaType() {
-		return mMediaType;
-	}
-
-	/**
-	 * Get the meta data feature instance of the current document
-	 *
-	 * @return the meta data feature instance which represent
-	 *         <code>office:meta</code> in the meta.xml
-	 */
-	public Meta getOfficeMetadata() {
-		if (mOfficeMeta == null) {
-			try {
-				mOfficeMeta = new Meta(getMetaDom());
-			} catch (Exception ex) {
-				Logger.getLogger(Document.class.getName()).log(Level.SEVERE, null, ex);
-			}
-		}
-		return mOfficeMeta;
-	}
-
-	/**
-	 * Save the document to an OutputStream. Delegate to the root document and
-	 * save possible embedded Documents.
-	 *
-	 * <p>
-	 * If the input file has been cached (this is the case when loading from an
-	 * InputStream), the input file can be overwritten.
-	 * </p>
-	 *
-	 * <p>
-	 * If not, the OutputStream may not point to the input file! Otherwise this
-	 * will result in unwanted behaviour and broken files.
-	 * </p>
-	 *
-	 * <p>
-	 * When save the embedded document to a stand alone document, all the file
-	 * entries of the embedded document will be copied to a new document
-	 * package. If the embedded document is outside of the current document
-	 * directory, you have to embed it to the sub directory and refresh the link
-	 * of the embedded document. you should reload it from the stream to get the
-	 * saved embedded document.
-	 *
-	 * @param out
-	 *            - the OutputStream to write the file to
-	 * @throws java.lang.Exception
-	 *             if the document could not be saved
-	 */
-	public void save(OutputStream out) throws Exception {
-		// 2DO FLUSH AND SAVE IN PACKAGE
-		flushDoms();
-		updateMetaData();
-		if (!isRootDocument()) {
-			Document newDoc = loadDocumentFromTemplate(getOdfMediaType());
-			newDoc.insertDocument(this, ROOT_DOCUMENT_PATH);
-			newDoc.updateMetaData();
-			newDoc.mPackage.save(out);
-			// ToDo: (Issue 219 - PackageRefactoring) - Return the document,
-			// when not closing!
-			// Should we close the sources now? User will never receive the open
-			// package!
-		} else {
-			// 2DO MOVE CACHE TO PACKAGE
-			// // the root document only have to flush the DOM of all open child
-			// documents
-			// flushAllDOMs();
-			mPackage.save(out);
-		}
-	}
-
-	/**
-	 * Save the document to a given file.
-	 *
-	 * <p>
-	 * If the input file has been cached (this is the case when loading from an
-	 * InputStream), the input file can be overwritten.
-	 * </p>
-	 *
-	 * <p>
-	 * Otherwise it's allowed to overwrite the input file as long as the same
-	 * path name is used that was used for loading (no symbolic link foo2.odt
-	 * pointing to the loaded file foo1.odt, no network path X:\foo.odt pointing
-	 * to the loaded file D:\foo.odt).
-	 * </p>
-	 *
-	 * <p>
-	 * When saving the embedded document to a stand alone document, all files of
-	 * the embedded document will be copied to a new document package. If the
-	 * embedded document is outside of the current document directory, you have
-	 * to embed it to the sub directory and refresh the link of the embedded
-	 * document. You should reload it from the given file to get the saved
-	 * embedded document.
-	 *
-	 * @param file
-	 *            - the file to save the document
-	 * @throws java.lang.Exception
-	 *             if the document could not be saved
-	 */
-	public void save(File file) throws Exception {
-		// 2DO FLUSH AND SAVE IN PACKAGE
-		flushDoms();
-		updateMetaData();
-		if (!isRootDocument()) {
-			Document newDoc = loadDocumentFromTemplate(getOdfMediaType());
-			newDoc.insertDocument(this, ROOT_DOCUMENT_PATH);
-			newDoc.updateMetaData();
-			newDoc.mPackage.save(file);
-			// ToDo: (Issue 219 - PackageRefactoring) - Return the document,
-			// when not closing!
-			// Should we close the sources now? User will never receive the open
-			// package!
-		} else {
-			this.mPackage.save(file);
-		}
-	}
-
-	/**
-	 * Save the document to a given file with given password.
-	 *
-	 * <p>
-	 * If the input file has been cached (this is the case when loading from an
-	 * InputStream), the input file can be overwritten.
-	 * </p>
-	 *
-	 * <p>
-	 * Otherwise it's allowed to overwrite the input file as long as the same
-	 * path name is used that was used for loading (no symbolic link foo2.odt
-	 * pointing to the loaded file foo1.odt, no network path X:\foo.odt pointing
-	 * to the loaded file D:\foo.odt).
-	 * </p>
-	 *
-	 * <p>
-	 * When saving the embedded document to a stand alone document, all files of
-	 * the embedded document will be copied to a new document package. If the
-	 * embedded document is outside of the current document directory, you have
-	 * to embed it to the sub directory and refresh the link of the embedded
-	 * document. You should reload it from the given file to get the saved
-	 * embedded document.
-	 *
-	 * @param file
-	 *            the file to save the document.
-	 * @param file
-	 *            the password of this document.
-	 *
-	 * @throws java.lang.Exception
-	 *             if the document could not be saved
-	 * @since 0.8
-	 */
-	public void save(File file, String password) throws Exception {
-		// 2DO FLUSH AND SAVE IN PACKAGE
-		flushDoms();
-		updateMetaData();
-		if (!isRootDocument()) {
-			Document newDoc = loadDocumentFromTemplate(getOdfMediaType());
-			newDoc.insertDocument(this, ROOT_DOCUMENT_PATH);
-			newDoc.updateMetaData();
-			newDoc.mPackage.setPassword(password);
-			newDoc.mPackage.save(file);
-			// ToDo: (Issue 219 - PackageRefactoring) - Return the document,
-			// when not closing!
-			// Should we close the sources now? User will never receive the open
-			// package!
-		} else {
-			mPackage.setPassword(password);
-			mPackage.save(file);
-		}
-	}
-
-	/**
-	 * Close the OdfPackage and release all temporary created data. Acter
-	 * execution of this method, this class is no longer usable. Do this as the
-	 * last action to free resources. Closing an already closed document has no
-	 * effect. Note that this will not close any cached documents.
-	 */
-	@Override
-	public void close() {
-		// set all member variables explicit to null
-		mMediaType = null;
-		mOfficeMeta = null;
-		mComponentRepository.clear();
-		super.close();
-	}
-
-	/**
-	 * Get the content root of a document.
-	 *
-	 * You may prefer to use the getContentRoot methods of subclasses of
-	 * Document. Their return parameters are already casted to respective
-	 * subclasses of OdfElement.
-	 *
-	 * @param clazz
-	 *            the type of the content root, depend on the document type
-	 * @return the child element of office:body, e.g. office:text for text docs
-	 * @throws Exception
-	 *             if the file DOM could not be created.
-	 */
-	@SuppressWarnings("unchecked")
-	protected <T extends OdfElement> T getContentRoot(Class<T> clazz) throws Exception {
-		OdfElement contentRoot = getContentDom().getRootElement();
-		OfficeBodyElement contentBody = OdfElement.findFirstChildNode(OfficeBodyElement.class, contentRoot);
-		NodeList childs = contentBody.getChildNodes();
-		for (int i = 0; i < childs.getLength(); i++) {
-			Node cur = childs.item(i);
-			if ((cur != null) && clazz.isInstance(cur)) {
-				return (T) cur;
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Get the content root of a document.
-	 *
-	 * You may prefer to use the getContentRoot methods of subclasses of
-	 * Document.
-	 *
-	 * @return the child element of office:body, e.g. office:text for text docs
-	 * @throws Exception
-	 *             if the file DOM could not be created.
-	 */
-	public OdfElement getContentRoot() throws Exception {
-		return getContentRoot(OdfElement.class);
-	}
-
-	@Override
-	public String toString() {
-		return "\n" + getMediaTypeString() + " - ID: " + this.hashCode() + " " + getPackage().getBaseURI();
-	}
-
-	/**
-	 * Insert an Image from the specified uri to the end of the Document.
-	 *
-	 * @param imageUri
-	 *            The URI of the image that will be added to the document, add
-	 *            image stream to the package, in the 'Pictures/' graphic
-	 *            directory with the same image file name as in the URI. If the
-	 *            imageURI is relative first the user.dir is taken to make it
-	 *            absolute.
-	 * @return Returns the internal package path of the image, which was created
-	 *         based on the given URI.
-	 * */
-	public String newImage(URI imageUri) {
-		try {
-			OdfContentDom contentDom = this.getContentDom();
-			OdfDrawFrame drawFrame = contentDom.newOdfElement(OdfDrawFrame.class);
-			XPath xpath = contentDom.getXPath();
-			if (this instanceof SpreadsheetDocument) {
-				TableTableCellElement lastCell = (TableTableCellElement) xpath.evaluate("//table:table-cell[last()]", contentDom, XPathConstants.NODE);
-				lastCell.appendChild(drawFrame);
-				drawFrame.removeAttribute("text:anchor-type");
-
-			} else if (this instanceof TextDocument) {
-				TextPElement lastPara = (TextPElement) xpath.evaluate("//text:p[last()]", contentDom, XPathConstants.NODE);
-				if (lastPara == null) {
-					lastPara = ((TextDocument) this).newParagraph();
-				}
-				lastPara.appendChild(drawFrame);
-				drawFrame.setTextAnchorTypeAttribute(TextAnchorTypeAttribute.Value.PARAGRAPH.toString());
-			} else if (this instanceof PresentationDocument) {
-				DrawPageElement lastPage = (DrawPageElement) xpath.evaluate("//draw:page[last()]", contentDom, XPathConstants.NODE);
-				lastPage.appendChild(drawFrame);
-			}
-			OdfDrawImage image = (OdfDrawImage) drawFrame.newDrawImageElement();
-			String imagePath = image.newImage(imageUri);
-			return imagePath;
-		} catch (Exception ex) {
-			Logger.getLogger(Document.class.getName()).log(Level.SEVERE, null, ex);
-		}
-		return null;
-	}
-
-	/**
-	 * Meta data about the document will be initialized. Following metadata data
-	 * is being added:
-	 * <ul>
-	 * <li>The initial creator name will be the Java user.name System property.</li>
-	 * <li>The date and time when this document was created using the current
-	 * data.</li>
-	 * <li>The number of times this document has been edited.</li>
-	 * <li>The default language will be the Java user.language System property.</li>
-	 * </ul>
-	 *
-	 * @param newDoc
-	 *            the Document object which need to initialize meta data.
-	 *
-	 *            TODO:This method will be moved to OdfMetadata class. see
-	 *            http://odftoolkit.org/bugzilla/show_bug.cgi?id=204
-	 */
-	private static void initializeMetaData(Document newDoc) {
-		Meta metaData = newDoc.getOfficeMetadata();
-		// add initial-creator info.
-		String creator = System.getProperty("user.name");
-		metaData.setInitialCreator(creator);
-		// add creation-date info.
-		Calendar calendar = Calendar.getInstance();
-		metaData.setCreationDate(calendar);
-		// add editing-cycles info.
-		metaData.setEditingCycles(0);
-		// add language info.
-		String language = System.getProperty("user.language");
-		if (language != null) {
-			metaData.setLanguage(language);
-		}
-	}
-
-	/**
-	 * Update document meta data in the ODF document. Following metadata data is
-	 * being updated:
-	 * <ul>
-	 * <li>The name of the person who last modified this document will be the
-	 * Java user.name System property</li>
-	 * <li>The date and time when the document was last modified using current
-	 * data</li>
-	 * <li>The number of times this document has been edited is incremented by 1
-	 * </li>
-	 * <li>The total time spent editing this document</li>
-	 * </ul>
-	 *
-	 * TODO:This method will be moved to OdfMetadata class. see
-	 * http://odftoolkit.org/bugzilla/show_bug.cgi?id=204
-	 *
-	 * @throws Exception
-	 */
-	private void updateMetaData() throws Exception {
-		if (mMetaDom != null) {
-			Meta metaData = getOfficeMetadata();
-			String creator = System.getProperty("user.name");
-			// update creator info.
-			metaData.setCreator(creator);
-			// update date info.
-			Calendar calendar = Calendar.getInstance();
-			metaData.setDcdate(calendar);
-			// update editing-cycles info.
-			Integer cycle = metaData.getEditingCycles();
-			if (cycle != null) {
-				metaData.setEditingCycles(++cycle);
-			} else {
-				metaData.setEditingCycles(1);
-			}
-			// update editing-duration info.
-			long editingDuration = calendar.getTimeInMillis() - documentOpeningTime;
-			editingDuration = (editingDuration < 1) ? 1 : editingDuration;
-			try {
-				DatatypeFactory aFactory = DatatypeFactory.newInstance();
-				metaData.setEditingDuration(new Duration(aFactory.newDurationDayTime(editingDuration)));
-			} catch (DatatypeConfigurationException e) {
-				Logger.getLogger(Document.class.getName()).log(Level.SEVERE, "editing duration update fail as DatatypeFactory can not be instanced", e);
-			}
-		}
-	}
-
-	// /////////////////
-	// Following is the implementation of locale settings
-	// ////////////////
-
-	/**
-	 * <p>
-	 * Unicode characters are in general divided by office applications into
-	 * three different types:
-	 *
-	 * <p>
-	 * 1) There is CJK: the Chinese, Japanese and Korean script (also old
-	 * Vietnamese belong to this group). See
-	 * http://en.wikipedia.org/wiki/CJK_characters
-	 *
-	 * <p>
-	 * 2) There is CTL: Complex Text Layout, which uses BIDI algorithms and/or
-	 * glyph modules. See http://en.wikipedia.org/wiki/Complex_Text_Layout
-	 *
-	 * <p>
-	 * 3) And there is all the rest, which was once called by MS Western.
-	 */
-	public enum ScriptType {
-		/**
-		 * Western language
-		 */
-		WESTERN,
-		/**
-		 * Chinese, Japanese and Korean
-		 */
-		CJK,
-		/**
-		 * Complex Text Layout language
-		 */
-		CTL;
-
-	}
-
-	private final static HashSet<String> CJKLanguage = new HashSet<String>();
-	private final static HashSet<String> CTLLanguage = new HashSet<String>();
-	{
-		CJKLanguage.add("zh"); // LANGUAGE_CHINES
-		CJKLanguage.add("ja"); // LANGUAGE_JAPANESE
-		CJKLanguage.add("ko"); // LANGUAGE_KOREANE
-
-		CTLLanguage.add("am"); // LANGUAGE_AMHARIC_ETHIOPIA
-		CTLLanguage.add("ar"); // LANGUAGE_ARABIC_SAUDI_ARABIA
-		CTLLanguage.add("as"); // LANGUAGE_ASSAMESE
-		CTLLanguage.add("bn"); // LANGUAGE_BENGALI
-		CTLLanguage.add("bo"); // LANGUAGE_TIBETAN
-		CTLLanguage.add("brx");// LANGUAGE_USER_BODO_INDIA
-		CTLLanguage.add("dgo");// LANGUAGE_USER_DOGRI_INDIA
-		CTLLanguage.add("dv"); // LANGUAGE_DHIVEHI
-		CTLLanguage.add("dz"); // LANGUAGE_DZONGKHA
-		CTLLanguage.add("fa"); // LANGUAGE_FARSI
-		CTLLanguage.add("gu"); // LANGUAGE_GUJARATI
-		CTLLanguage.add("he"); // LANGUAGE_HEBREW
-		CTLLanguage.add("hi"); // LANGUAGE_HINDI
-		CTLLanguage.add("km"); // LANGUAGE_KHMER
-		CTLLanguage.add("kn"); // LANGUAGE_KANNADA
-		CTLLanguage.add("ks"); // LANGUAGE_KASHMIRI
-		CTLLanguage.add("ku"); // LANGUAGE_USER_KURDISH_IRAQ
-		CTLLanguage.add("lo"); // LANGUAGE_LAO
-		CTLLanguage.add("mai");// LANGUAGE_USER_MAITHILI_INDIA
-		CTLLanguage.add("ml"); // LANGUAGE_MALAYALAM
-		CTLLanguage.add("mn"); // LANGUAGE_MONGOLIAN_MONGOLIAN
-		CTLLanguage.add("mni");// LANGUAGE_MANIPURI
-		CTLLanguage.add("mr"); // LANGUAGE_MARATHI
-		CTLLanguage.add("my"); // LANGUAGE_BURMESE
-		CTLLanguage.add("ne"); // LANGUAGE_NEPALI
-		CTLLanguage.add("or"); // LANGUAGE_ORIYA
-		CTLLanguage.add("pa"); // LANGUAGE_PUNJABI
-		CTLLanguage.add("sa"); // LANGUAGE_SANSKRIT
-		CTLLanguage.add("sd"); // LANGUAGE_SINDHI
-		CTLLanguage.add("si"); // LANGUAGE_SINHALESE_SRI_LANKA
-		CTLLanguage.add("syr");// LANGUAGE_SYRIAC
-		CTLLanguage.add("ta"); // LANGUAGE_TAMIL
-		CTLLanguage.add("te"); // LANGUAGE_TELUGU
-		CTLLanguage.add("th"); // LANGUAGE_THAI
-		CTLLanguage.add("ug"); // LANGUAGE_UIGHUR_CHINA
-		CTLLanguage.add("ur"); // LANGUAGE_URDU
-		CTLLanguage.add("yi"); // LANGUAGE_YIDDISH
-	}
-
-	/**
-	 * <p>
-	 * Set a locale information.
-	 * <p>
-	 * The locale information will affect the language and country setting of
-	 * the document. Thus the font settings, the spell checkings and etc will be
-	 * affected.
-	 *
-	 * @param locale
-	 *            - an instance of Locale
-	 */
-	public void setLocale(Locale locale) {
-		setLocale(locale, getScriptType(locale));
-	}
-
-	public static ScriptType getScriptType(Locale locale) {
-		String language = locale.getLanguage();
-		if (CJKLanguage.contains(language))
-			return ScriptType.CJK;
-		if (CTLLanguage.contains(language))
-			return ScriptType.CTL;
-		return ScriptType.WESTERN;
-
-	}
-
-	/**
-	 * <p>
-	 * Set a locale of a specific script type.
-	 * <p>
-	 * If the locale is not belone to the script type, nothing will happen.
-	 *
-	 * @param locale
-	 *            - Locale information
-	 * @param scriptType
-	 *            - The script type
-	 */
-	public void setLocale(Locale locale, ScriptType scriptType) {
-		try {
-			switch (scriptType) {
-			case WESTERN:
-				setWesternLanguage(locale);
-				break;
-			case CJK:
-				setDefaultAsianLanguage(locale);
-				break;
-			case CTL:
-				setDefaultComplexLanguage(locale);
-				break;
-			}
-		} catch (Exception e) {
-			Logger.getLogger(Document.class.getName()).log(Level.SEVERE, "Failed to set locale", e);
-		}
-	}
-
-	/**
-	 * <p>
-	 * Get a locale information of a specific script type.
-	 *
-	 * @param scriptType
-	 *            - The script type
-	 * @return the Locale information
-	 */
-	public Locale getLocale(ScriptType scriptType) {
-		try {
-			switch (scriptType) {
-			case WESTERN:
-				return getDefaultLanguageByProperty(OdfTextProperties.Country, OdfTextProperties.Language);
-			case CJK:
-				return getDefaultLanguageByProperty(OdfTextProperties.CountryAsian, OdfTextProperties.LanguageAsian);
-			case CTL:
-				return getDefaultLanguageByProperty(OdfTextProperties.CountryComplex, OdfTextProperties.LanguageComplex);
-			}
-		} catch (Exception e) {
-			Logger.getLogger(Document.class.getName()).log(Level.SEVERE, "Failed to get locale", e);
-		}
-		return null;
-	}
-
-	/**
-	 * This method will set the default language and country information of the
-	 * document, based on the parameter of the Locale information.
-	 *
-	 * @param locale
-	 *            - an instance of Locale that the default language and country
-	 *            will be set to.
-	 * @throws Exception
-	 */
-	private void setWesternLanguage(Locale locale) throws Exception {
-		if (getScriptType(locale) != ScriptType.WESTERN)
-			return;
-
-		OdfOfficeStyles styles = getStylesDom().getOfficeStyles();
-		Iterable<OdfDefaultStyle> defaultStyles = styles.getDefaultStyles();
-		if (defaultStyles != null) {
-			Iterator<OdfDefaultStyle> itera = defaultStyles.iterator();
-			while (itera.hasNext()) {
-				OdfDefaultStyle style = itera.next();
-				if (style.getFamily().getProperties().contains(OdfTextProperties.Language)) {
-					style.setProperty(OdfTextProperties.Language, locale.getLanguage());
-					style.setProperty(OdfTextProperties.Country, locale.getCountry());
-				}
-			}
-		}
-	}
-
-	private Locale getDefaultLanguageByProperty(OdfStyleProperty countryProp, OdfStyleProperty languageProp) throws Exception {
-		String lang = null, ctry = null;
-
-		OdfOfficeStyles styles = getStylesDom().getOfficeStyles();
-
-		// get language and country setting from default style setting for
-		// paragraph
-		OdfDefaultStyle defaultStyle = styles.getDefaultStyle(OdfStyleFamily.Paragraph);
-		if (defaultStyle != null) {
-			if (defaultStyle.hasProperty(countryProp) && defaultStyle.hasProperty(languageProp)) {
-				ctry = defaultStyle.getProperty(countryProp);
-				lang = defaultStyle.getProperty(languageProp);
-				return new Locale(lang, ctry);
-			}
-		}
-		// if no default style setting for paragraph
-		// get language and country setting from other default style settings
-		Iterable<OdfDefaultStyle> defaultStyles = styles.getDefaultStyles();
-		Iterator<OdfDefaultStyle> itera = defaultStyles.iterator();
-		while (itera.hasNext()) {
-			OdfDefaultStyle style = itera.next();
-			if (style.hasProperty(countryProp) && style.hasProperty(languageProp)) {
-				ctry = style.getProperty(countryProp);
-				lang = style.getProperty(languageProp);
-				return new Locale(lang, ctry);
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * This method will return an instance of Locale, which presents the default
-	 * language and country information settings in this document.
-	 *
-	 * @return an instance of Locale that the default language and country is
-	 *         set to.
-	 */
-
-	/**
-	 * This method will set the default Asian language and country information
-	 * of the document, based on the parameter of the Locale information. If the
-	 * Locale instance is not set a Asian language (Chinese, Traditional
-	 * Chinese, Japanese and Korean, nothing will take effect.
-	 *
-	 * @param locale
-	 *            - an instance of Locale that the default Asian language and
-	 *            country will be set to.
-	 * @throws Exception
-	 */
-	private void setDefaultAsianLanguage(Locale locale) throws Exception {
-		if (getScriptType(locale) != ScriptType.CJK)
-			return;
-		String user_language = locale.getLanguage();
-		if (!user_language.equals(Locale.CHINESE.getLanguage()) && !user_language.equals(Locale.TRADITIONAL_CHINESE.getLanguage())
-				&& !user_language.equals(Locale.JAPANESE.getLanguage()) && !user_language.equals(Locale.KOREAN.getLanguage()))
-			return;
-
-		OdfOfficeStyles styles = getStylesDom().getOfficeStyles();
-		Iterable<OdfDefaultStyle> defaultStyles = styles.getDefaultStyles();
-		if (defaultStyles != null) {
-			Iterator<OdfDefaultStyle> itera = defaultStyles.iterator();
-			while (itera.hasNext()) {
-				OdfDefaultStyle style = itera.next();
-				if (style.getFamily().getProperties().contains(OdfTextProperties.LanguageAsian)) {
-					style.setProperty(OdfTextProperties.LanguageAsian, locale.getLanguage());
-					style.setProperty(OdfTextProperties.CountryAsian, locale.getCountry());
-				}
-			}
-		}
-	}
-
-	/**
-	 * This method will set the default complex language and country information
-	 * of the document, based on the parameter of the Locale information.
-	 *
-	 * @param locale
-	 *            - an instance of Locale that the default complex language and
-	 *            country will be set to.
-	 * @throws Exception
-	 */
-	private void setDefaultComplexLanguage(Locale locale) throws Exception {
-		if (getScriptType(locale) != ScriptType.CTL)
-			return;
-		OdfOfficeStyles styles = getStylesDom().getOfficeStyles();
-		Iterable<OdfDefaultStyle> defaultStyles = styles.getDefaultStyles();
-		if (defaultStyles != null) {
-			Iterator<OdfDefaultStyle> itera = defaultStyles.iterator();
-			while (itera.hasNext()) {
-				OdfDefaultStyle style = itera.next();
-				if (style.getFamily().getProperties().contains(OdfTextProperties.LanguageComplex)) {
-					style.setProperty(OdfTextProperties.LanguageComplex, locale.getLanguage());
-					style.setProperty(OdfTextProperties.CountryComplex, locale.getCountry());
-				}
-			}
-		}
-	}
-
-	/**
-	 * This method will search both the document content and header/footer,
-	 * return an iterator of section objects.
-	 * <p>
-	 * The sections defined in embed document won't be covered.
-	 *
-	 * @return an iterator of Section objects
-	 */
-	public Iterator<Section> getSectionIterator() {
-		TextSectionElement element;
-		ArrayList<Section> list = new ArrayList<Section>();
-		try {
-			// search in content.xml
-			OdfElement root = getContentDom().getRootElement();
-			OfficeBodyElement officeBody = OdfElement.findFirstChildNode(OfficeBodyElement.class, root);
-			NodeList sectionList = officeBody.getElementsByTagNameNS(OdfDocumentNamespace.TEXT.getUri(), "section");
-			for (int i = 0; i < sectionList.getLength(); i++) {
-				element = (TextSectionElement) sectionList.item(i);
-				list.add(Section.getInstance(element));
-			}
-
-			// Search in style.xml
-			root = getStylesDom().getRootElement();
-			OfficeMasterStylesElement masterStyle = OdfElement.findFirstChildNode(OfficeMasterStylesElement.class, root);
-			sectionList = masterStyle.getElementsByTagNameNS(OdfDocumentNamespace.TEXT.getUri(), "section");
-			for (int i = 0; i < sectionList.getLength(); i++) {
-				element = (TextSectionElement) sectionList.item(i);
-				list.add(Section.getInstance(element));
-			}
-
-		} catch (Exception e) {
-			Logger.getLogger(Document.class.getName()).log(Level.SEVERE, "Failed in sectionIterator", e);
-		}
-		return list.iterator();
-	}
-
-	/**
-	 * This method will search both the document content and header/footer,
-	 * return a section with a specific name.
-	 * <p>
-	 * This method won't search in the embed document.
-	 * <p>
-	 * Null will be returned if there is no section found.
-	 *
-	 * @param name
-	 *            - the name of a section
-	 * @return a section object with a specific name
-	 */
-	public Section getSectionByName(String name) {
-		TextSectionElement element;
-		try {
-			OdfElement root = getContentDom().getRootElement();
-			OfficeBodyElement officeBody = OdfElement.findFirstChildNode(OfficeBodyElement.class, root);
-			XPath xpath = getContentDom().getXPath();
-			String xpathValue = ".//text:section[@text:name=\"" + name + "\"]";
-			element = (TextSectionElement) xpath.evaluate(xpathValue, officeBody, XPathConstants.NODE);
-			if (element != null) {
-				return Section.getInstance(element);
-			}
-
-			root = getStylesDom().getRootElement();
-			OfficeMasterStylesElement masterStyle = OdfElement.findFirstChildNode(OfficeMasterStylesElement.class, root);
-			xpath = getStylesDom().getXPath();
-			element = (TextSectionElement) xpath.evaluate(".//text:section[@text:name=\"" + name + "\"]", masterStyle, XPathConstants.NODE);
-			if (element != null) {
-				return Section.getInstance(element);
-			}
-
-		} catch (Exception e) {
-			Logger.getLogger(Document.class.getName()).log(Level.SEVERE, "Failed in getSectionByName", e);
-		}
-
-		return null;
-
-	}
-
-	/**
-	 * Remove an ODF element from the document. All the resources that are only
-	 * related with this element will be removed at the same time.
-	 *
-	 * @param odfElement
-	 *            - the odf element that would be moved.
-	 */
-	public boolean removeElementLinkedResource(OdfElement odfElement) {
-		boolean success = deleteLinkedRef(odfElement);
-		success &= deleteStyleRef(odfElement);
-		return success;
-	}
-
-	/**
-	 * Return a unique string with a character "a" followed by randomly
-	 * generating 6 hex numbers
-	 *
-	 * @return a unique string
-	 */
-	String makeUniqueName() {
-		return String.format("a%06x", (int) (Math.random() * 0xffffff));
-	}
-
-	private String getNewUniqueString(String oldStr) {
-		int lastIndex = oldStr.lastIndexOf("-");
-		if (lastIndex == -1) {
-			return oldStr + "-" + makeUniqueName();
-		}
-		String suffix = oldStr.substring(lastIndex + 1);
-		if (suffix.matches("a[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]")) {
-			return oldStr.substring(0, lastIndex + 1) + makeUniqueName();
-		} else
-			return oldStr + "-" + makeUniqueName();
-	}
-
-	private void updateAttribute(Attr attr) {
-		String oldID = attr.getValue();
-		String newID = getNewUniqueString(oldID);
-		attr.setValue(newID);
-	}
-
-	/**
-	 * Make a content copy of the specified element, and the returned element
-	 * should have the specified ownerDocument.
-	 *
-	 * @param element
-	 *            The element that need to be copied
-	 * @param dom
-	 *            The specified DOM tree that the returned element belong to
-	 * @param deep
-	 *            If true, recursively clone the subtree under the element,
-	 *            false, only clone the element itself
-	 * @return Returns a duplicated element which is not in the DOM tree with
-	 *         the specified element
-	 */
-	Node cloneForeignElement(Node element, OdfFileDom dom, boolean deep) {
-		if (element instanceof OdfElement) {
-			OdfElement cloneElement = dom.createElementNS(((OdfElement) element).getOdfName());
-
-			NamedNodeMap attributes = element.getAttributes();
-			if (attributes != null) {
-				for (int i = 0; i < attributes.getLength(); i++) {
-					Node item = attributes.item(i);
-					String qname = null;
-					String prefix = item.getPrefix();
-					if (prefix == null) {
-						qname = item.getLocalName();
-						cloneElement.setAttribute(qname, item.getNodeValue());
-					} else {
-						qname = prefix + ":" + item.getLocalName();
-						cloneElement.setAttributeNS(item.getNamespaceURI(), qname, item.getNodeValue());
-					}
-				}
-			}
-
-			if (deep) {
-				Node childNode = element.getFirstChild();
-				while (childNode != null) {
-					cloneElement.appendChild(cloneForeignElement(childNode, dom, true));
-					childNode = childNode.getNextSibling();
-				}
-			}
-
-			return cloneElement;
-		} else {
-			return dom.createTextNode(element.getNodeValue());
-		}
-
-	}
-
-	/**
-	 * This method will update all the attribute "xml:id" to make it unique
-	 * within the whole document content
-	 * <p>
-	 * This method is usually be invoked before inserting a copied ODF element
-	 * to document content.
-	 *
-	 * @param element
-	 *            - the element that need to be inserted.
-	 */
-	void updateXMLIds(OdfElement element) {
-		try {
-			XPath xpath = getContentDom().getXPath();
-			String xpathValue = "//*[@xml:id]";
-			NodeList childList = (NodeList) xpath.evaluate(xpathValue, element, XPathConstants.NODESET);
-			if (childList == null)
-				return;
-
-			for (int i = 0; i < childList.getLength(); i++) {
-				OdfElement ele = (OdfElement) childList.item(i);
-				Attr attri = ele.getAttributeNodeNS(OdfDocumentNamespace.XML.getUri(), "id");
-				updateAttribute(attri);
-			}
-		} catch (Exception e) {
-			Logger.getLogger(Document.class.getName()).log(Level.SEVERE, "Failed in updateXMLIds", e);
-		}
-	}
-
-	/**
-	 * This method will update all the attribute
-	 * "text:name","table:name","draw:name","chart:name", to make it unique
-	 * within the whole document content.
-	 * <p>
-	 * This method is usually be invoked before inserting a copied ODF element
-	 * to document content.
-	 *
-	 * @param element
-	 *            - the element that need to be inserted.
-	 */
-	// anim:name, chart:name, config:name, office:name, presentation:name,
-	// svg:name,
-	void updateNames(OdfElement element) {
-		try {
-			XPath xpath = getContentDom().getXPath();
-			String xpathValue = "descendant-or-self::node()[@text:name|@table:name|@draw:name|@chart:name]";
-			NodeList childList = (NodeList) xpath.evaluate(xpathValue, element, XPathConstants.NODESET);
-			if (childList == null)
-				return;
-			for (int i = 0; i < childList.getLength(); i++) {
-				OdfElement ele = (OdfElement) childList.item(i);
-				Attr attri = ele.getAttributeNodeNS(OdfDocumentNamespace.TEXT.getUri(), "name");
-				if (attri != null)
-					updateAttribute(attri);
-				attri = ele.getAttributeNodeNS(OdfDocumentNamespace.TABLE.getUri(), "name");
-				if (attri != null)
-					updateAttribute(attri);
-				if (ele instanceof DrawFrameElement)// only update draw:frame
-				{
-					attri = ele.getAttributeNodeNS(OdfDocumentNamespace.DRAW.getUri(), "name");
-					if (attri != null)
-						updateAttribute(attri);
-				}
-			}
-		} catch (Exception e) {
-			Logger.getLogger(Document.class.getName()).log(Level.SEVERE, "Failed in updateXMLIds", e);
-		}
-	}
-
-	/**
-	 * This method will copy the linked resource of the element which need to be
-	 * copied, from the source package to the target package.
-	 * <p>
-	 * If the target package contains a resource with the same path and name,
-	 * the name of the resource will be renamed.
-	 * <p>
-	 * This method will copy resources all in one batch.
-	 *
-	 * @param sourceCloneEle
-	 *            - the element that need to be copied
-	 * @param srcDocument
-	 *            - the source document
-	 */
-	void copyLinkedRefInBatch(OdfElement sourceCloneEle, Document srcDocument) {
-		try {
-   			OdfFileDom fileDom = (OdfFileDom) sourceCloneEle.getOwnerDocument();
-			XPath xpath;
-			if (fileDom instanceof OdfContentDom) {
-				xpath = ((OdfContentDom) fileDom).getXPath();
-			} else {
-				xpath = ((OdfStylesDom) fileDom).getXPath();
-			}
-			// OdfPackageDocument srcDoc = fileDom.getDocument();
-			// new a map to put the original name and the rename string, in case
-			// that the same name might be referred by the slide several times.
-			HashMap<String, String> objectRenameMap = new HashMap<String, String>();
-			NodeList linkNodes = (NodeList) xpath.evaluate(".//*[@xlink:href]", sourceCloneEle, XPathConstants.NODESET);
-			for (int i = 0; i <= linkNodes.getLength(); i++) {
-				OdfElement object = null;
-				if (linkNodes.getLength() == i) {
-					if (sourceCloneEle.hasAttributeNS(OdfDocumentNamespace.XLINK.getUri(), "href")) {
-						object = sourceCloneEle;
-					} else {
-						break;
-					}
-				} else {
-					object = (OdfElement) linkNodes.item(i);
-				}
-				String refObjPath = object.getAttributeNS(OdfDocumentNamespace.XLINK.getUri(), "href");
-				if (refObjPath != null && refObjPath.length() > 0) {
-					// the path of the object is start with "./"
-					boolean hasPrefix = false;
-					String prefix = "./";
-					String newObjPath;
-					if (refObjPath.startsWith(prefix)) {
-						refObjPath = refObjPath.substring(2);
-						hasPrefix = true;
-					}
-					// check if this linked resource has been copied
-					if (objectRenameMap.containsKey(refObjPath)) {
-						// this object has been copied already
-						newObjPath = objectRenameMap.get(refObjPath);
-						object.setAttributeNS(OdfDocumentNamespace.XLINK.getUri(), "xlink:href", hasPrefix ? (prefix + newObjPath) : newObjPath);
-						continue;
-					}
-					// check if the current document contains the same path
-					OdfFileEntry fileEntry = getPackage().getFileEntry(refObjPath);
-					// note: if refObjPath is a directory, it must end with '/'
-					if (fileEntry == null) {
-						fileEntry = getPackage().getFileEntry(refObjPath + "/");
-					}
-					if (fileEntry != null) {
-						// rename the object path
-						newObjPath = objectRenameMap.get(refObjPath);
-						if (newObjPath == null) {
-							// if refObjPath still contains ".", it means that
-							// it has the suffix
-							// then change the name before the suffix string
-							int dotIndex = refObjPath.indexOf(".");
-							if (dotIndex != -1) {
-								newObjPath = refObjPath.substring(0, dotIndex) + "-" + makeUniqueName() + refObjPath.substring(dotIndex);
-							} else {
-								newObjPath = refObjPath + "-" + makeUniqueName();
-							}
-							objectRenameMap.put(refObjPath, newObjPath);
-						}
-						object.setAttributeNS(OdfDocumentNamespace.XLINK.getUri(), "xlink:href", hasPrefix ? (prefix + newObjPath) : newObjPath);
-					} else
-						objectRenameMap.put(refObjPath, refObjPath);
-				}
-			}
-			// copy resource in batch
-			copyResourcesFrom(srcDocument, objectRenameMap);
-		} catch (Exception e) {
-			Logger.getLogger(Document.class.getName()).log(Level.SEVERE, null, e);
-		}
-	}
+    // Static parts of file references
 
-	/*****************************/
-	/*
+    private static final String SLASH = "/";
+    private OdfMediaType mMediaType;
+    private Meta mOfficeMeta;
+    private long documentOpeningTime;
+    private TableContainerImpl tableContainerImpl;
+    private static final Pattern CONTROL_CHAR_PATTERN = Pattern.compile("\\p{Cntrl}");
+    private static final String EMPTY_STRING = "";
+
+    private IdentityHashMap<OdfElement, Component> mComponentRepository
+        = new IdentityHashMap<OdfElement, Component>();
+
+    // FIXME: This field is only used in method copyResourcesFrom to improve
+    // copy performance, should not be used in any other way.
+    // methods loadDocument(String documentPath) and loadDocument(File file)
+    // will initialize it.
+    // This field and its methods should be removed after ODFDOM supplies batch
+    // copy.
+    private File mFile = null;
+
+    // if the copy foreign slide for several times,
+    // the same style might be copied for several times with the different name
+    // so use styleRenameMap to keep track the renamed style so we can reuse the
+    // style,
+    // rather than new several styles which only have the different style names.
+    // while if the style elements really have the same style name but with
+    // different content
+    // such as that these style elements are from different document
+    // so the value for each key should be a list
+    private HashMap<String, List<String>> styleRenameMap = new HashMap<String, List<String>>();
+    // the map is used to record if the renamed style name is appended to the
+    // current dom
+    private HashMap<String, Boolean> styleAppendMap = new HashMap<String, Boolean>();
+
+    // the object rename map for image.
+    // can not easily recognize if the embedded document are the same.
+    // private HashMap<String, String> objectRenameMap = new HashMap<String,
+    // String>();
+    // Using static factory instead of constructor
+    protected Document(OdfPackage pkg, String internalPath, OdfMediaType mediaType) {
+        super(pkg, internalPath, mediaType.getMediaTypeString());
+        mMediaType = mediaType;
+        // set document opening time.
+        documentOpeningTime = System.currentTimeMillis();
+    }
+
+    /**
+     * This enum contains all possible media types of Document documents.
+     */
+    public enum OdfMediaType implements MediaType {
+
+        CHART("application/vnd.oasis.opendocument.chart", "odc"),
+        CHART_TEMPLATE("application/vnd.oasis.opendocument.chart-template", "otc"),
+        FORMULA("application/vnd.oasis.opendocument.formula", "odf"),
+        FORMULA_TEMPLATE("application/vnd.oasis.opendocument.formula-template", "otf"),
+        DATABASE_FRONT_END("application/vnd.oasis.opendocument.base", "odb"),
+        GRAPHICS("application/vnd.oasis.opendocument.graphics", "odg"),
+        GRAPHICS_TEMPLATE("application/vnd.oasis.opendocument.graphics-template", "otg"),
+        IMAGE("application/vnd.oasis.opendocument.image", "odi"),
+        IMAGE_TEMPLATE("application/vnd.oasis.opendocument.image-template", "oti"),
+        PRESENTATION("application/vnd.oasis.opendocument.presentation", "odp"),
+        PRESENTATION_TEMPLATE("application/vnd.oasis.opendocument.presentation-template", "otp"),
+        SPREADSHEET("application/vnd.oasis.opendocument.spreadsheet", "ods"),
+        SPREADSHEET_TEMPLATE("application/vnd.oasis.opendocument.spreadsheet-template", "ots"),
+        TEXT("application/vnd.oasis.opendocument.text", "odt"),
+        TEXT_MASTER("application/vnd.oasis.opendocument.text-master", "odm"),
+        TEXT_TEMPLATE("application/vnd.oasis.opendocument.text-template", "ott"),
+        TEXT_WEB("application/vnd.oasis.opendocument.text-web", "oth");
+
+        private final String mMediaType;
+        private final String mSuffix;
+
+        OdfMediaType(String mediaType, String suffix) {
+            this.mMediaType = mediaType;
+            this.mSuffix = suffix;
+        }
+
+        /**
+         * @return the mediatype String of this document
+         */
+        public String getMediaTypeString() {
+            return mMediaType;
+        }
+
+        /**
+         * @return the ODF filesuffix of this document
+         */
+        public String getSuffix() {
+            return mSuffix;
+        }
+
+        /**
+         *
+         * @param mediaType string defining an ODF document
+         * @return the according OdfMediatype encapusulating the given string and
+         * the suffix
+         */
+        public static OdfMediaType getOdfMediaType(String mediaType) {
+            OdfMediaType odfMediaType = null;
+            if (mediaType != null) {
+                String mediaTypeShort
+                    = mediaType.substring(mediaType.lastIndexOf(".") + 1, mediaType.length());
+                mediaTypeShort = mediaTypeShort.replace('-', '_').toUpperCase();
+                try {
+                    odfMediaType = OdfMediaType.valueOf(mediaTypeShort);
+                } catch (IllegalArgumentException e) {
+                    throw new IllegalArgumentException("Given mediaType '" + mediaType
+                        + "' is either not yet supported or not an ODF mediatype!");
+                }
+            }
+            return odfMediaType;
+        }
+    }
+
+    /**
+     * Loads an Document from the given resource. NOTE: Initial meta data will
+     * be added in this method.
+     *
+     * @param res a resource containing a package with a root document
+     * @param odfMediaType the media type of the root document
+     * @return the Document document or NULL if the media type is not supported
+     * by SIMPLE.
+     * @throws java.lang.Exception - if the document could not be created.
+     */
+    protected static Document loadTemplate(Resource res, OdfMediaType odfMediaType) throws Exception {
+        InputStream in = res.createInputStream();
+        OdfPackage pkg = null;
+        try {
+            pkg = OdfPackage.loadPackage(in);
+        } finally {
+            in.close();
+        }
+        Document newDocument = newDocument(pkg, ROOT_DOCUMENT_PATH, odfMediaType);
+        // add initial meta data to new document.
+        initializeMetaData(newDocument);
+        return newDocument;
+    }
+
+    /**
+     * Loads a Document from the provided path.
+     *
+     * <p>
+     * Document relies on the file being available for read access over the
+     * whole life cycle of Document.
+     * </p>
+     *
+     * @param documentPath - the path from where the document can be loaded
+     * @param password - file password.
+     * @return the Document from the given path or NULL if the media type is not
+     * supported by SIMPLE.
+     * @throws java.lang.Exception - if the document could not be created.
+     * @since 0.8
+     */
+    public static Document loadDocument(String documentPath, String password) throws Exception {
+        File file = new File(documentPath);
+        return loadDocument(file, password);
+    }
+
+    /**
+     * Loads a Document from the provided path.
+     *
+     * <p>
+     * Document relies on the file being available for read access over the
+     * whole life cycle of Document.
+     * </p>
+     *
+     * @param documentPath - the path from where the document can be loaded
+     * @return the Document from the given path or NULL if the media type is not
+     * supported by SIMPLE.
+     * @throws java.lang.Exception - if the document could not be created.
+     */
+    public static Document loadDocument(String documentPath) throws Exception {
+        File file = new File(documentPath);
+        return loadDocument(file);
+    }
+
+    /**
+     * Creates a Document from the Document provided by a resource Stream.
+     *
+     * <p>
+     * Since an InputStream does not provide the arbitrary (non sequentiell)
+     * read access needed by Document, the InputStream is cached. This usually
+     * takes more time compared to the other createInternalDocument methods. An
+     * advantage of caching is that there are no problems overwriting an input
+     * file.
+     * </p>
+     *
+     * @param inStream - the InputStream of the ODF document.
+     * @return the document created from the given InputStream
+     * @throws java.lang.Exception - if the document could not be created.
+     */
+    public static Document loadDocument(InputStream inStream) throws Exception {
+        return loadDocument(OdfPackage.loadPackage(inStream));
+    }
+
+    /**
+     * Creates a Document from the Document provided by a File.
+     *
+     * <p>
+     * Document relies on the file being available for read access over the
+     * whole lifecycle of Document.
+     * </p>
+     *
+     * @param file - a file representing the ODF document.
+     * @return the document created from the given File
+     * @throws java.lang.Exception - if the document could not be created.
+     */
+    public static Document loadDocument(File file) throws Exception {
+        Document doc = loadDocument(OdfPackage.loadPackage(file));
+        doc.setFile(file);
+        return doc;
+    }
+
+    /**
+     * Creates a Document from the Document provided by a File.
+     *
+     * <p>
+     * Document relies on the file being available for read access over the
+     * whole lifecycle of Document.
+     * </p>
+     *
+     * @param file - a file representing the ODF document.
+     * @param password - file password.
+     * @return the document created from the given File
+     * @throws java.lang.Exception - if the document could not be created.
+     * @since 0.7
+     */
+    public static Document loadDocument(File file, String password) throws Exception {
+        Document doc = loadDocument(OdfPackage.loadPackage(file, password, null));
+        doc.setFile(file);
+        return doc;
+    }
+
+    /**
+     * Creates a Document from the Document provided by an ODF package.
+     *
+     * @param odfPackage - the ODF package containing the ODF document.
+     * @return the root document of the given OdfPackage
+     * @throws java.lang.Exception - if the ODF document could not be created.
+     */
+    public static Document loadDocument(OdfPackage odfPackage) throws Exception {
+        return loadDocument(odfPackage, ROOT_DOCUMENT_PATH);
+    }
+
+    /**
+     * Creates a Document from the Document provided by an ODF package.
+     *
+     * @param odfPackage - the ODF package containing the ODF document.
+     * @param internalPath - the path to the ODF document relative to the
+     * package root.
+     * @return the root document of the given OdfPackage
+     * @throws java.lang.Exception - if the ODF document could not be created.
+     */
+    public static Document loadDocument(OdfPackage odfPackage, String internalPath) throws Exception {
+        String documentMediaType = odfPackage.getMediaTypeString(internalPath);
+        if (documentMediaType == null) {
+            throw new IllegalArgumentException("Given internalPath '" + internalPath
+                + "' is an illegal or inappropriate argument.");
+        }
+        OdfMediaType odfMediaType = OdfMediaType.getOdfMediaType(documentMediaType);
+        if (odfMediaType == null) {
+            ErrorHandler errorHandler = odfPackage.getErrorHandler();
+            Matcher matcherCTRL = CONTROL_CHAR_PATTERN.matcher(documentMediaType);
+            if (matcherCTRL.find()) {
+                documentMediaType = matcherCTRL.replaceAll(EMPTY_STRING);
+            }
+            OdfValidationException ve
+                = new OdfValidationException(OdfSchemaConstraint.DOCUMENT_WITHOUT_ODF_MIMETYPE, internalPath,
+                    documentMediaType);
+            if (errorHandler != null) {
+                errorHandler.fatalError(ve);
+            }
+            throw ve;
+        }
+        return newDocument(odfPackage, internalPath, odfMediaType);
+    }
+
+    /**
+     * Sets password of this document.
+     *
+     * @param password the password of this document.
+     * @since 0.8
+     */
+    public void setPassword(String password) {
+        getPackage().setPassword(password);
+    }
+
+    // return null if the media type can not be recognized.
+    private static Document loadDocumentFromTemplate(OdfMediaType odfMediaType) throws Exception {
+
+        switch (odfMediaType) {
+            case TEXT:
+            case TEXT_TEMPLATE:
+            case TEXT_MASTER:
+            case TEXT_WEB:
+                // documentTemplate = TextDocument.EMPTY_TEXT_DOCUMENT_RESOURCE;
+                TextDocument document = TextDocument.newTextDocument();
+                document.changeMode(TextDocument.OdfMediaType.TEXT_WEB);
+                return document;
+
+            case SPREADSHEET:
+                SpreadsheetDocument spreadsheet = SpreadsheetDocument.newSpreadsheetDocument();
+                spreadsheet.changeMode(SpreadsheetDocument.OdfMediaType.SPREADSHEET);
+                return spreadsheet;
+
+            case SPREADSHEET_TEMPLATE:
+                SpreadsheetDocument spreadsheettemplate = SpreadsheetDocument.newSpreadsheetDocument();
+                spreadsheettemplate.changeMode(SpreadsheetDocument.OdfMediaType.SPREADSHEET_TEMPLATE);
+                return spreadsheettemplate;
+
+            case PRESENTATION:
+                PresentationDocument presentation = PresentationDocument.newPresentationDocument();
+                presentation.changeMode(PresentationDocument.OdfMediaType.PRESENTATION);
+                return presentation;
+
+            case PRESENTATION_TEMPLATE:
+                PresentationDocument presentationtemplate = PresentationDocument.newPresentationDocument();
+                presentationtemplate.changeMode(PresentationDocument.OdfMediaType.PRESENTATION_TEMPLATE);
+                return presentationtemplate;
+
+            case GRAPHICS:
+                GraphicsDocument graphics = GraphicsDocument.newGraphicsDocument();
+                graphics.changeMode(GraphicsDocument.OdfMediaType.GRAPHICS);
+                return graphics;
+
+            case GRAPHICS_TEMPLATE:
+                GraphicsDocument graphicstemplate = GraphicsDocument.newGraphicsDocument();
+                graphicstemplate.changeMode(GraphicsDocument.OdfMediaType.GRAPHICS_TEMPLATE);
+                return graphicstemplate;
+
+            case CHART:
+                ChartDocument chart = ChartDocument.newChartDocument();
+                chart.changeMode(ChartDocument.OdfMediaType.CHART);
+                return chart;
+
+            case CHART_TEMPLATE:
+                ChartDocument charttemplate = ChartDocument.newChartDocument();
+                charttemplate.changeMode(ChartDocument.OdfMediaType.CHART_TEMPLATE);
+                return charttemplate;
+
+            // case IMAGE:
+            // case IMAGE_TEMPLATE:
+            default:
+                throw new IllegalArgumentException("Given mediaType '" + odfMediaType.toString()
+                    + "' is either not yet supported or not an ODF mediatype!");
+        }
+    }
+
+    /**
+     * Creates one of the ODF documents based a given mediatype.
+     *
+     * @param odfMediaType The ODF Mediatype of the ODF document to be created.
+     * @return The ODF document, which mediatype dependends on the parameter or
+     * NULL if media type were not supported.
+     */
+    private static Document newDocument(OdfPackage pkg, String internalPath, OdfMediaType odfMediaType) {
+        Document newDoc = null;
+        switch (odfMediaType) {
+            case TEXT:
+                newDoc = new TextDocument(pkg, internalPath, TextDocument.OdfMediaType.TEXT);
+                break;
+
+            case TEXT_TEMPLATE:
+                newDoc = new TextDocument(pkg, internalPath, TextDocument.OdfMediaType.TEXT_TEMPLATE);
+                break;
+
+            case TEXT_MASTER:
+                newDoc = new TextDocument(pkg, internalPath, TextDocument.OdfMediaType.TEXT_MASTER);
+                break;
+
+            case TEXT_WEB:
+                newDoc = new TextDocument(pkg, internalPath, TextDocument.OdfMediaType.TEXT_WEB);
+                break;
+
+            case SPREADSHEET:
+                newDoc
+                    = new SpreadsheetDocument(pkg, internalPath, SpreadsheetDocument.OdfMediaType.SPREADSHEET);
+                break;
+
+            case SPREADSHEET_TEMPLATE:
+                newDoc
+                    = new SpreadsheetDocument(pkg, internalPath,
+                        SpreadsheetDocument.OdfMediaType.SPREADSHEET_TEMPLATE);
+                break;
+
+            case PRESENTATION:
+                newDoc
+                    = new PresentationDocument(pkg, internalPath,
+                        PresentationDocument.OdfMediaType.PRESENTATION);
+                break;
+
+            case PRESENTATION_TEMPLATE:
+                newDoc
+                    = new PresentationDocument(pkg, internalPath,
+                        PresentationDocument.OdfMediaType.PRESENTATION_TEMPLATE);
+                break;
+
+            case GRAPHICS:
+                newDoc = new GraphicsDocument(pkg, internalPath, GraphicsDocument.OdfMediaType.GRAPHICS);
+                break;
+
+            case GRAPHICS_TEMPLATE:
+                newDoc
+                    = new GraphicsDocument(pkg, internalPath, GraphicsDocument.OdfMediaType.GRAPHICS_TEMPLATE);
+                break;
+
+            case CHART:
+                newDoc = new ChartDocument(pkg, internalPath, ChartDocument.OdfMediaType.CHART);
+                break;
+
+            case CHART_TEMPLATE:
+                newDoc = new ChartDocument(pkg, internalPath, ChartDocument.OdfMediaType.CHART_TEMPLATE);
+                break;
+            // case IMAGE:
+            // case IMAGE_TEMPLATE:
+
+            default:
+                newDoc = null;
+                throw new IllegalArgumentException("Given mediaType '" + odfMediaType.mMediaType
+                    + "' is not yet supported!");
+        }
+        // returning null if MediaType is not supported
+        return newDoc;
+    }
+
+    /**
+     * Returns an embedded OdfPackageDocument from the given package path.
+     *
+     * @param documentPath path to the ODF document within the package. The path
+     * is relative to the current document.
+     * @return an embedded Document
+     */
+    public Document getEmbeddedDocument(String documentPath) {
+        String internalPath = getDocumentPath() + documentPath;
+        internalPath = normalizeDocumentPath(internalPath);
+        Document embeddedDocument = (Document) mPackage.getCachedDocument(internalPath);
+        // if the document was not already loaded, fine mimetype and create a
+        // new instance
+        if (embeddedDocument == null) {
+            String mediaTypeString = getMediaTypeString();
+            OdfMediaType odfMediaType = OdfMediaType.getOdfMediaType(mediaTypeString);
+            if (odfMediaType == null) {
+                embeddedDocument = newDocument(mPackage, internalPath, odfMediaType);
+            } else {
+                try {
+                    String documentMediaType = mPackage.getMediaTypeString(internalPath);
+                    odfMediaType = OdfMediaType.getOdfMediaType(documentMediaType);
+                    if (odfMediaType == null) {
+                        return null;
+                    }
+                    embeddedDocument = Document.loadDocument(mPackage, internalPath);
+                } catch (Exception ex) {
+                    Logger.getLogger(OdfPackageDocument.class.getName()).log(Level.SEVERE, null, ex);
+                }
+            }
+        }
+        return embeddedDocument;
+    }
+
+    /**
+     * Method returns all embedded OdfPackageDocuments, which match a valid
+     * OdfMediaType, of the root OdfPackageDocument.
+     *
+     * @return a list with all embedded documents of the root OdfPackageDocument
+     */
+    // ToDo: (Issue 219 - PackageRefactoring) - Better return Path of
+    // Documents??
+    public List<Document> getEmbeddedDocuments() {
+        List<Document> embeddedObjects = new ArrayList<Document>();
+        // ToDo: (Issue 219 - PackageRefactoring) - Algorithm enhancement:
+        // Instead going through all the files for each mimetype, better
+        // Check all files, which have a mimetype if it is one of the desired,
+        // perhaps start with ODF prefix
+        for (OdfMediaType mediaType : OdfMediaType.values()) {
+            embeddedObjects.addAll(getEmbeddedDocuments(mediaType));
+        }
+        return embeddedObjects;
+    }
+
+    /**
+     * Method returns all embedded OdfPackageDocuments of the root
+     * OdfPackageDocument matching the according MediaType. This is done by
+     * matching the subfolder entries of the manifest file with the given
+     * OdfMediaType.
+     *
+     * @param mediaType media type which is used as a filter
+     * @return embedded documents of the root OdfPackageDocument matching the
+     * given media type
+     */
+    public List<Document> getEmbeddedDocuments(OdfMediaType mediaType) {
+        String wantedMediaString = null;
+        if (mediaType != null) {
+            wantedMediaString = mediaType.getMediaTypeString();
+        }
+        List<Document> embeddedObjects = new ArrayList<Document>();
+        // check manifest for current embedded OdfPackageDocuments
+        Set<String> manifestEntries = mPackage.getFilePaths();
+        for (String path : manifestEntries) {
+            // any directory that is not the root document "/"
+            if (path.length() > 1 && path.endsWith(SLASH)) {
+                String entryMediaType = mPackage.getFileEntry(path).getMediaTypeString();
+                // if the entry is a document (directory has mediaType)
+                if (entryMediaType != null) {
+                    // if a specific ODF mediatype was requested
+                    if (wantedMediaString != null) {
+                        // test if the desired mediatype matches the current
+                        if (entryMediaType.equals(wantedMediaString)) {
+                            normalizeDocumentPath(path);
+                            embeddedObjects.add(getEmbeddedDocument(path));
+                        }
+                    } else {
+                        // test if any ODF mediatype matches the current
+                        for (OdfMediaType type : OdfMediaType.values()) {
+                            if (entryMediaType.equals(type.getMediaTypeString())) {
+                                embeddedObjects.add(getEmbeddedDocument(path));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return embeddedObjects;
+    }
+
+    /**
+     * Embed an OdfPackageDocument to the current OdfPackageDocument. All the
+     * file entries of child document will be embedded as well to the current
+     * document package.
+     *
+     * @param documentPath to the directory the ODF document should be inserted
+     * (relative to the current document).
+     * @param sourceDocument the OdfPackageDocument to be embedded.
+     */
+    public void insertDocument(OdfPackageDocument sourceDocument, String documentPath) {
+        super.insertDocument(sourceDocument, documentPath);
+    }
+
+    /**
+     * Sets the media type of the Document
+     *
+     * @param odfMediaType media type to be set
+     */
+    protected void setOdfMediaType(OdfMediaType odfMediaType) {
+        mMediaType = odfMediaType;
+        super.setMediaTypeString(odfMediaType.getMediaTypeString());
+    }
+
+    /**
+     * Gets the media type of the Document
+     */
+    protected OdfMediaType getOdfMediaType() {
+        return mMediaType;
+    }
+
+    /**
+     * Get the meta data feature instance of the current document
+     *
+     * @return the meta data feature instance which represent
+     * <code>office:meta</code> in the meta.xml
+     */
+    public Meta getOfficeMetadata() {
+        if (mOfficeMeta == null) {
+            try {
+                mOfficeMeta = new Meta(getMetaDom());
+            } catch (Exception ex) {
+                Logger.getLogger(Document.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        }
+        return mOfficeMeta;
+    }
+
+    /**
+     * Save the document to an OutputStream. Delegate to the root document and
+     * save possible embedded Documents.
+     *
+     * <p>
+     * If the input file has been cached (this is the case when loading from an
+     * InputStream), the input file can be overwritten.
+     * </p>
+     *
+     * <p>
+     * If not, the OutputStream may not point to the input file! Otherwise this
+     * will result in unwanted behaviour and broken files.
+     * </p>
+     *
+     * <p>
+     * When save the embedded document to a stand alone document, all the file
+     * entries of the embedded document will be copied to a new document
+     * package. If the embedded document is outside of the current document
+     * directory, you have to embed it to the sub directory and refresh the link
+     * of the embedded document. you should reload it from the stream to get the
+     * saved embedded document.
+     *
+     * @param out - the OutputStream to write the file to
+     * @throws java.lang.Exception if the document could not be saved
+     */
+    public void save(OutputStream out) throws Exception {
+        // 2DO FLUSH AND SAVE IN PACKAGE
+        flushDoms();
+        updateMetaData();
+        if (!isRootDocument()) {
+            Document newDoc = loadDocumentFromTemplate(getOdfMediaType());
+            newDoc.insertDocument(this, ROOT_DOCUMENT_PATH);
+            newDoc.updateMetaData();
+            newDoc.mPackage.save(out);
+            // ToDo: (Issue 219 - PackageRefactoring) - Return the document,
+            // when not closing!
+            // Should we close the sources now? User will never receive the open
+            // package!
+        } else {
+            // 2DO MOVE CACHE TO PACKAGE
+            // // the root document only have to flush the DOM of all open child
+            // documents
+            // flushAllDOMs();
+            mPackage.save(out);
+        }
+    }
+
+    /**
+     * Save the document to a given file.
+     *
+     * <p>
+     * If the input file has been cached (this is the case when loading from an
+     * InputStream), the input file can be overwritten.
+     * </p>
+     *
+     * <p>
+     * Otherwise it's allowed to overwrite the input file as long as the same
+     * path name is used that was used for loading (no symbolic link foo2.odt
+     * pointing to the loaded file foo1.odt, no network path X:\foo.odt pointing
+     * to the loaded file D:\foo.odt).
+     * </p>
+     *
+     * <p>
+     * When saving the embedded document to a stand alone document, all files of
+     * the embedded document will be copied to a new document package. If the
+     * embedded document is outside of the current document directory, you have
+     * to embed it to the sub directory and refresh the link of the embedded
+     * document. You should reload it from the given file to get the saved
+     * embedded document.
+     *
+     * @param file - the file to save the document
+     * @throws java.lang.Exception if the document could not be saved
+     */
+    public void save(File file) throws Exception {
+        // 2DO FLUSH AND SAVE IN PACKAGE
+        flushDoms();
+        updateMetaData();
+        if (!isRootDocument()) {
+            Document newDoc = loadDocumentFromTemplate(getOdfMediaType());
+            newDoc.insertDocument(this, ROOT_DOCUMENT_PATH);
+            newDoc.updateMetaData();
+            newDoc.mPackage.save(file);
+            // ToDo: (Issue 219 - PackageRefactoring) - Return the document,
+            // when not closing!
+            // Should we close the sources now? User will never receive the open
+            // package!
+        } else {
+            this.mPackage.save(file);
+        }
+    }
+
+    /**
+     * Save the document to a given file with given password.
+     *
+     * <p>
+     * If the input file has been cached (this is the case when loading from an
+     * InputStream), the input file can be overwritten.
+     * </p>
+     *
+     * <p>
+     * Otherwise it's allowed to overwrite the input file as long as the same
+     * path name is used that was used for loading (no symbolic link foo2.odt
+     * pointing to the loaded file foo1.odt, no network path X:\foo.odt pointing
+     * to the loaded file D:\foo.odt).
+     * </p>
+     *
+     * <p>
+     * When saving the embedded document to a stand alone document, all files of
+     * the embedded document will be copied to a new document package. If the
+     * embedded document is outside of the current document directory, you have
+     * to embed it to the sub directory and refresh the link of the embedded
+     * document. You should reload it from the given file to get the saved
+     * embedded document.
+     *
+     * @param file the file to save the document.
+     * @param file the password of this document.
+     *
+     * @throws java.lang.Exception if the document could not be saved
+     * @since 0.8
+     */
+    public void save(File file, String password) throws Exception {
+        // 2DO FLUSH AND SAVE IN PACKAGE
+        flushDoms();
+        updateMetaData();
+        if (!isRootDocument()) {
+            Document newDoc = loadDocumentFromTemplate(getOdfMediaType());
+            newDoc.insertDocument(this, ROOT_DOCUMENT_PATH);
+            newDoc.updateMetaData();
+            newDoc.mPackage.setPassword(password);
+            newDoc.mPackage.save(file);
+            // ToDo: (Issue 219 - PackageRefactoring) - Return the document,
+            // when not closing!
+            // Should we close the sources now? User will never receive the open
+            // package!
+        } else {
+            mPackage.setPassword(password);
+            mPackage.save(file);
+        }
+    }
+
+    /**
+     * Close the OdfPackage and release all temporary created data. Acter
+     * execution of this method, this class is no longer usable. Do this as the
+     * last action to free resources. Closing an already closed document has no
+     * effect. Note that this will not close any cached documents.
+     */
+    @Override
+    public void close() {
+        // set all member variables explicit to null
+        mMediaType = null;
+        mOfficeMeta = null;

[... 2928 lines stripped ...]


Mime
View raw message