package org.xmind.ui.blackbox;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.xmind.core.event.ICoreEventListener;
import org.xmind.core.event.ICoreEventRegistration;
import org.xmind.core.event.ICoreEventSource;
import org.xmind.core.event.ICoreEventSupport;
import org.xmind.core.internal.event.CoreEventSupport;
/**
* @author Jason Wong
*/
public class BlackBoxLibrary implements IBlackBoxLibrary, ICoreEventSource {
private static final String MAP_REMOVE = "mapRemove"; //$NON-NLS-1$
private static final String VERSION_ADD = "versionAdd"; //$NON-NLS-1$
private static final String VERSION_REMOVE = "versionRemove"; //$NON-NLS-1$
private List<IBlackBoxMap> maps = new ArrayList<IBlackBoxMap>();
private List<String> savedSrcs = new ArrayList<String>();
private File blackbox = null;
private ICoreEventSupport coreEventSupport;
public BlackBoxLibrary() {
load();
}
public synchronized void addVersion(String source, String mapID,
IBlackBoxVersion version) {
IBlackBoxMap map = findMapBySource(source);
if (map == null) {
BlackBoxMap m = new BlackBoxMap(this, mapID);
m.setSource(source);
map = m;
this.maps.add(map);
}
Set<IBlackBoxVersion> versions = map.getVersions();
if (versions.size() == 0) {
versions.add(version);
} else if (versions.size() < 3 && !version.isReliable()) {
versions.add(version);
} else {
IBlackBoxVersion trash = null;
trash = findTrashVersion(versions, version.isReliable());
versions.remove(trash);
versions.add(version);
BlackBoxManager.addTrash(trash);
}
if (!isSavedMap(source)) {
this.savedSrcs.add(source);
}
save(map);
fireTargetEvent(VERSION_ADD, version);
}
public synchronized boolean removeMap(IBlackBoxMap map) {
if (this.maps.remove(map)) {
BlackBoxManager.addTrash(map);
save(map);
fireTargetEvent(MAP_REMOVE, map);
return true;
} else {
return false;
}
}
public synchronized boolean removeVersion(IBlackBoxMap map, String timestamp) {
Set<IBlackBoxVersion> versions = map.getVersions();
for (IBlackBoxVersion v : versions) {
if (v.getTimestamp().equals(timestamp)) {
if (versions.remove(v)) {
BlackBoxManager.addTrash(v);
save(map);
if (versions.size() == 0) {
removeMap(map);
fireTargetEvent(MAP_REMOVE, map);
}
fireTargetEvent(VERSION_REMOVE, v);
return true;
} else {
return false;
}
}
}
return false;
}
public synchronized IBlackBoxMap[] getMaps() {
load();
return this.maps.toArray(new IBlackBoxMap[this.maps.size()]);
}
public synchronized IBlackBoxMap findMapBySource(String source) {
for (IBlackBoxMap map : this.maps) {
if (source.equals(map.getSource()))
return map;
}
return null;
}
public synchronized IBlackBoxMap findMapByID(String id) {
for (IBlackBoxMap map : this.maps) {
if (map.getID().equals(id))
return map;
}
return null;
}
public synchronized boolean isSavedMap(String source) {
if (source == null)
return false;
return this.savedSrcs.contains(source);
}
public synchronized void removeSavedMap(String source) {
if (!(savedSrcs.size() > 0) || source == null)
return;
if (isSavedMap(source)) {
savedSrcs.remove(source);
}
}
private void load() {
File blackbox = new File(BlackBoxManager.getBlackboxPath());
if (!blackbox.exists())
return;
maps.clear();
File[] infos = blackbox.listFiles();
for (File info : infos) {
String fileName = info.getName();
String[] parts = fileName.split("\\."); //$NON-NLS-1$s
if (fileName.contains(BlackBoxManager.FILE_INFO_EXT)) {
try {
loadBackupInfo(info, parts);
} catch (IOException e) {
BlackBoxManager
.log("Error occurred while loading maps.", e); //$NON-NLS-1$
}
} else if (fileName.contains(BlackBoxManager.FILE_XMIND_EXT)) {
loadMapInfo(info, parts);
}
}
}
private synchronized void save(IBlackBoxMap map) {
File metaFile = getMetaFile(map.getID());
if (!metaFile.exists()) {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(metaFile));
writer.write(map.getSource());
writer.flush();
} catch (IOException e) {
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException e) {
}
}
}
BlackBoxManager.clearTrashes();
}
private File getMetaFile(String mapID) {
if (blackbox == null) {
blackbox = new File(BlackBoxManager.getBlackboxPath());
}
File metaFile = new File(blackbox, mapID
+ BlackBoxManager.FILE_INFO_EXT);
return metaFile;
}
public ICoreEventRegistration registerCoreEventListener(String type,
ICoreEventListener listener) {
return getCoreEventSupport().registerGlobalListener(type, listener);
}
private void fireTargetEvent(String eventType, Object target) {
getCoreEventSupport().dispatchTargetChange(this, eventType, target);
}
public ICoreEventSupport getCoreEventSupport() {
if (coreEventSupport == null) {
coreEventSupport = new CoreEventSupport();
}
return coreEventSupport;
}
/**
* If isReliable value is true, returns the last saved the reliable version.
* else returns the older save unreliable version.
*
* @param isReliable
* @return The IBlackBoxVersion will be replaced
*/
private IBlackBoxVersion findTrashVersion(Set<IBlackBoxVersion> versions,
boolean isReliable) {
if (isReliable) {
for (IBlackBoxVersion v : versions) {
if (v.isReliable()) {
return v;
}
}
}
IBlackBoxVersion trash = null;
for (IBlackBoxVersion v : versions) {
if (v.isReliable())
continue;
if (trash == null) {
trash = v;
continue;
}
trash = trash.compareTo(v) > 0 ? v : trash;
}
return trash;
}
private void loadBackupInfo(File info, String[] parts) throws IOException {
BlackBoxMap map = null;
String mapID = null;
for (String part : parts) {
if (part.length() == BlackBoxManager.MD5_LENGTH) {
mapID = part;
break;
}
}
if (mapID == null)
return;
map = (BlackBoxMap) findMapByID(mapID);
if (map == null) {
map = new BlackBoxMap(this, mapID);
maps.add(map);
}
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(info));
StringBuffer sb = new StringBuffer();
while (reader.ready()) {
sb.append(reader.readLine());
}
String source = sb.toString();
map.setSource(source);
} finally {
if (reader != null)
reader.close();
}
}
private void loadMapInfo(File info, String[] parts) {
BlackBoxMap map = null;
String mapID = null;
boolean reliable = false;
String timestamp = null;
for (String part : parts) {
if (part.length() == BlackBoxManager.MD5_LENGTH)
mapID = part;
else if (part.length() == 1)
reliable = "a".equals(part) ? true : false; //$NON-NLS-1$
else if (part.length() == BlackBoxManager.TIMESTAMP_LENGTH)
timestamp = part;
}
if (mapID == null || timestamp == null)
return;
map = (BlackBoxMap) findMapByID(mapID);
if (map == null) {
map = new BlackBoxMap(this, mapID);
maps.add(map);
}
Set<IBlackBoxVersion> versions = map.getVersions();
if (versions.size() < 3) {
BlackBoxVersion v = new BlackBoxVersion(mapID, timestamp, reliable);
v.setFile(info);
versions.add(v);
}
}
}