/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.core.internal.dom;
import static org.xmind.core.internal.zip.ArchiveConstants.CONTENT_XML;
import static org.xmind.core.internal.zip.ArchiveConstants.MANIFEST_XML;
import static org.xmind.core.internal.zip.ArchiveConstants.META_XML;
import static org.xmind.core.internal.zip.ArchiveConstants.PATH_MARKER_SHEET;
import static org.xmind.core.internal.zip.ArchiveConstants.STYLES_XML;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.xmind.core.Core;
import org.xmind.core.CoreException;
import org.xmind.core.IAdaptable;
import org.xmind.core.IManifest;
import org.xmind.core.io.ByteArrayStorage;
import org.xmind.core.io.IInputSource;
import org.xmind.core.io.IOutputTarget;
import org.xmind.core.io.IStorage;
import org.xmind.core.marker.IMarkerSheet;
import org.xmind.core.style.IStyleSheet;
import org.xmind.core.util.DOMUtils;
import org.xmind.core.util.FileUtils;
/**
* @author frankshaka
*
*/
public class TempSaver {
private WorkbookImpl workbook;
private IStorage storage;
private IStorage oldStorage;
private Set<String> savedEntries;
/**
* @param workbook
*/
public TempSaver(WorkbookImpl workbook) {
super();
this.workbook = workbook;
}
/**
* @return the storage
*/
public IStorage getStorage() {
if (storage == null) {
storage = new ByteArrayStorage();
}
return storage;
}
/**
* @param storage
* the storage to set
*/
public void setStorage(IStorage storage) {
if (storage == this.storage)
return;
if (oldStorage != null) {
oldStorage = this.storage;
}
this.storage = storage;
}
public void save() throws IOException, CoreException {
savedEntries = new HashSet<String>();
try {
saveAll();
} finally {
savedEntries = null;
oldStorage = null;
}
}
private void saveAll() throws IOException, CoreException {
if (storage == null)
storage = createStorage();
IOutputTarget target = storage.getOutputTarget();
saveDOM(workbook.getMeta(), target, META_XML);
saveDOM(workbook, target, CONTENT_XML);
IMarkerSheet markerSheet = workbook.getMarkerSheet();
if (!markerSheet.isEmpty()) {
saveDOM(markerSheet, target, PATH_MARKER_SHEET);
}
IStyleSheet styleSheet = workbook.getStyleSheet();
if (!styleSheet.isEmpty()) {
saveDOM(styleSheet, target, STYLES_XML);
}
if (oldStorage != null) {
saveStorage(oldStorage, target);
}
IManifest manifest = workbook.getManifest();
saveDOM(manifest, target, MANIFEST_XML);
}
private IStorage createStorage() {
return null;
}
private void saveStorage(IStorage sourceStorage, IOutputTarget target)
throws CoreException, IOException {
IInputSource source = storage.getInputSource();
Iterator<String> entries = source.getEntries();
while (entries.hasNext()) {
String entryPath = entries.next();
if (entryPath != null && !"".equals(entryPath) //$NON-NLS-1$
&& !hasBeenSaved(entryPath)) {
saveStorageEntry(source, target, entryPath);
markSaved(entryPath);
}
}
}
/**
* @param source
* @param target
* @param entryPath
*/
private void saveStorageEntry(IInputSource source, IOutputTarget target,
String entryPath) {
try {
InputStream in = getInputStream(source, entryPath);
if (in != null) {
OutputStream out = getOutputStream(target, entryPath);
if (out != null) {
try {
FileUtils.transfer(in, out, true);
} finally {
long time = source.getEntryTime(entryPath);
if (time >= 0) {
target.setEntryTime(entryPath, time);
}
}
}
}
} catch (IOException e) {
Core.getLogger().log(e);
} catch (CoreException e) {
Core.getLogger().log(e);
}
}
private InputStream getInputStream(IInputSource source, String entryPath)
throws CoreException {
if (source.hasEntry(entryPath)) {
return source.getEntryStream(entryPath);
}
return null;
}
private void saveDOM(IAdaptable domAdapter, IOutputTarget target,
String entryPath) throws IOException, CoreException {
OutputStream out = getOutputStream(target, entryPath);
if (out != null) {
try {
DOMUtils.save(domAdapter, out, true);
} finally {
markSaved(entryPath);
}
}
}
private OutputStream getOutputStream(IOutputTarget target, String entryPath)
throws IOException, CoreException {
if (!target.isEntryAvaialble(entryPath))
return null;
return target.getEntryStream(entryPath);
}
private boolean hasBeenSaved(String entryPath) {
return savedEntries != null && savedEntries.contains(entryPath);
}
/**
* @param entryPath
*/
private void markSaved(String entryPath) {
if (savedEntries == null)
savedEntries = new HashSet<String>();
savedEntries.add(entryPath);
}
}