package org.xmind.ui.internal.imports.lighten;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.json.JSONArray;
import org.json.JSONObject;
import org.xmind.core.IControlPoint;
import org.xmind.core.INotes;
import org.xmind.core.IRelationship;
import org.xmind.core.ISheet;
import org.xmind.core.ITopic;
import org.xmind.core.IWorkbook;
import org.xmind.core.internal.dom.DOMConstants;
import org.xmind.core.internal.dom.PlainNotesContentImpl;
import org.xmind.core.internal.dom.SheetImpl;
import org.xmind.core.internal.dom.TopicExtensionElementImpl;
import org.xmind.core.internal.dom.TopicExtensionImpl;
import org.xmind.core.internal.dom.TopicImpl;
import org.xmind.core.internal.dom.WorkbookImpl;
import org.xmind.core.style.IStyle;
import org.xmind.core.style.IStyleSheet;
import org.xmind.core.style.IStyled;
import org.xmind.core.util.Point;
import org.xmind.ui.internal.MindMapUIPlugin;
import org.xmind.ui.style.Styles;
import org.xmind.ui.wizards.MindMapImporter;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class LightenImporter extends MindMapImporter implements ErrorHandler {
private ISheet targetSheet;
private IStyleSheet targetStyleSheet;
private IStyle theme;
private Map<IStyled, IStyle> styleMap;
private static final String PIXEL_POINT = "pt"; //$NON-NLS-1$
public LightenImporter(String sourcePath, IWorkbook targetWorkbook) {
super(sourcePath, targetWorkbook);
}
@Override
public void build() throws InvocationTargetException, InterruptedException {
MindMapUIPlugin.getDefault().getUsageDataCollector()
.increase("ImportFromLightenCount"); //$NON-NLS-1$
ZipInputStream zis = null;
try {
getMonitor().beginTask(null, 100);
zis = new ZipInputStream(new FileInputStream(getSourcePath()));
ZipEntry entry;
JSONObject json = null;
while ((entry = zis.getNextEntry()) != null)
if (LightenConstants.CONTENT_FILE_NAME
.equals(entry.getName())) {
getMonitor().worked(40);
BufferedInputStream bis = new BufferedInputStream(zis);
BufferedReader reader = new BufferedReader(
new InputStreamReader(bis, "utf-8")); //$NON-NLS-1$
StringBuilder sb = new StringBuilder();
String read;
while ((read = reader.readLine()) != null) {
sb.append(read).append('\n');
}
json = new JSONObject(sb.toString());
getMonitor().worked(10);
}
zis.close();
zis = null;
if (json != null) {
addTargetSheet(parseJsonIntoWorkbook(json));
}
getMonitor().worked(50);
getMonitor().done();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (zis != null) {
try {
zis.closeEntry();
zis.close();
} catch (Exception e) {
zis = null;
}
}
}
postBuilded();
}
private ISheet parseJsonIntoWorkbook(JSONObject json) {
WorkbookImpl workbook = (WorkbookImpl) getTargetWorkbook();
targetSheet = workbook.createSheet();
SheetImpl sheet = (SheetImpl) targetSheet;
if (targetStyleSheet == null) {
targetStyleSheet = workbook.getStyleSheet();
}
if (styleMap == null) {
styleMap = new HashMap<IStyled, IStyle>();
}
if (json.has(LightenConstants.SHEET_ATTR_SKE_THEME))
parseTheme(
json.getJSONObject(LightenConstants.SHEET_ATTR_SKE_THEME));
if (json.has(LightenConstants.SHEET_ATTR_UPDATE_TIME))
sheet.getImplementation().setAttribute(DOMConstants.ATTR_TIMESTAMP,
((Long) ((Double) (json.getDouble(
LightenConstants.SHEET_ATTR_UPDATE_TIME) * 1000))
.longValue()).toString());
if (json.has(LightenConstants.SHEET_ATTR_ROOT)) {
JSONObject rootTopicJson = (JSONObject) json
.get(LightenConstants.SHEET_ATTR_ROOT);
ITopic rootTopic = parseTopic(rootTopicJson, sheet);
sheet.replaceRootTopic(rootTopic);
if (json.has(LightenConstants.SHEET_ATTR_RIGHT_NUM)) {
TopicExtensionImpl topicExtension = (TopicExtensionImpl) rootTopic
.createExtension("org.xmind.ui.map.unbalanced"); //$NON-NLS-1$
TopicExtensionElementImpl element = (TopicExtensionElementImpl) topicExtension
.getContent().getCreatedChild("right-number"); //$NON-NLS-1$
element.setTextContent(((Integer) json
.getInt(LightenConstants.SHEET_ATTR_RIGHT_NUM))
.toString());
}
}
if (json.has(LightenConstants.SHEET_ATTR_RELATION)) {
JSONArray relationshipsJson = json
.getJSONArray(LightenConstants.SHEET_ATTR_RELATION);
for (int i = 0; i < relationshipsJson.length(); i++) {
JSONObject relationshipJson = relationshipsJson
.getJSONObject(i);
IRelationship relationship = workbook.createRelationship();
relationship.setEnd1Id(relationshipJson
.getString(LightenConstants.RELATION_START_ID));
relationship.setEnd2Id(relationshipJson
.getString(LightenConstants.RELATION_END_ID));
if (relationshipJson
.has(LightenConstants.RELATION_CTRL_POINT1)) {
IControlPoint controlPoint1 = relationship
.getControlPoint(0);
controlPoint1.setPosition(deserializePoint(relationshipJson
.getString(LightenConstants.RELATION_CTRL_POINT1)));
}
if (relationshipJson
.has(LightenConstants.RELATION_CTRL_POINT2)) {
IControlPoint controlPoint2 = relationship
.getControlPoint(1);
controlPoint2.setPosition(deserializePoint(relationshipJson
.getString(LightenConstants.RELATION_CTRL_POINT2)));
}
sheet.addRelationship(relationship);
}
}
if (json.has(LightenConstants.SHEET_ATTR_CLR_THEME)) {
String themeName = parseTheme(
json.getJSONObject(LightenConstants.SHEET_ATTR_CLR_THEME));
importStyleAndTheme(themeName);
}
return targetSheet;
}
private ITopic parseTopic(JSONObject json, ISheet sheet) {
IWorkbook workbook = sheet.getOwnedWorkbook();
TopicImpl topic = (TopicImpl) workbook.createTopic();
if (json.has(LightenConstants.TOPIC_ATTR_TITLE))
topic.setTitleText(
json.getString(LightenConstants.TOPIC_ATTR_TITLE));
if (json.has(LightenConstants.TOPIC_ATTR_ID))
topic.getImplementation().setAttribute(DOMConstants.ATTR_ID,
json.getString(LightenConstants.TOPIC_ATTR_ID));
if (json.has(LightenConstants.TOPIC_ATTR_SUBTOPIC)) {
JSONArray subtopicJson = json
.getJSONArray(LightenConstants.TOPIC_ATTR_SUBTOPIC);
for (int i = 0; i < subtopicJson.length(); i++) {
ITopic subtopic = parseTopic(subtopicJson.getJSONObject(i),
sheet);
topic.add(subtopic);
}
}
if (json.has(LightenConstants.TOPIC_ATTR_NOTE)) {
JSONObject notesJson = json
.getJSONObject(LightenConstants.TOPIC_ATTR_NOTE);
if (notesJson.has(LightenConstants.NOTE_ATTR_TEXT)) {
INotes notes = topic.getNotes();
PlainNotesContentImpl plainNotes = (PlainNotesContentImpl) workbook
.createNotesContent(INotes.PLAIN);
try {
plainNotes.setTextContent(notesJson
.getString(LightenConstants.NOTE_ATTR_TEXT));
} catch (Exception e) {
}
notes.setContent(INotes.PLAIN, plainNotes);
}
}
if (json.has(LightenConstants.TOPIC_ATTR_DETACH)
&& json.getBoolean(LightenConstants.TOPIC_ATTR_DETACH)
&& json.has(LightenConstants.TOPIC_ATTR_POS)) {
topic.setPosition(deserializePoint(
json.getString(LightenConstants.TOPIC_ATTR_POS)));
}
if (json.has(LightenConstants.TOPIC_ATTR_FOLDED))
topic.setFolded(
json.getBoolean(LightenConstants.TOPIC_ATTR_FOLDED));
if (json.has(LightenConstants.TOPIC_ATTR_STYLE))
setTopicStyle(topic,
json.getJSONObject(LightenConstants.TOPIC_ATTR_STYLE));
return topic;
}
private Point deserializePoint(String point) {
int commaPos = point.indexOf(',');
int x = Double.valueOf(point.substring(1, commaPos)).intValue();
int y = Double
.valueOf(point.substring(commaPos + 1, point.length() - 1))
.intValue();
return new Point(x, y);
}
private String parseTheme(JSONObject json) {
String name = json.getString(LightenConstants.THEME_ATTR_NAME);
if (json.has(LightenConstants.THEME_ATTR_MAIN))
parseThemeStyle(IStyle.TOPIC, Styles.FAMILY_MAIN_TOPIC,
json.getJSONObject(LightenConstants.THEME_ATTR_MAIN));
if (json.has(LightenConstants.THEME_ATTR_SUB))
parseThemeStyle(IStyle.TOPIC, Styles.FAMILY_SUB_TOPIC,
json.getJSONObject(LightenConstants.THEME_ATTR_SUB));
if (json.has(LightenConstants.THEME_ATTR_MAP))
parseThemeStyle(IStyle.MAP, Styles.FAMILY_MAP,
json.getJSONObject(LightenConstants.THEME_ATTR_MAP));
if (json.has(LightenConstants.THEME_ATTR_CENTRAL))
parseThemeStyle(IStyle.TOPIC, Styles.FAMILY_CENTRAL_TOPIC,
json.getJSONObject(LightenConstants.THEME_ATTR_CENTRAL));
if (json.has(LightenConstants.THEME_ATTR_FLOAT))
parseThemeStyle(IStyle.TOPIC, Styles.FAMILY_FLOATING_TOPIC,
json.getJSONObject(LightenConstants.THEME_ATTR_FLOAT));
if (json.has(LightenConstants.THEME_ATTR_RELATION))
parseThemeStyle(IStyle.RELATIONSHIP, Styles.FAMILY_RELATIONSHIP,
json.getJSONObject(LightenConstants.THEME_ATTR_RELATION));
return name;
}
private void parseThemeStyle(String type, String styleFamily,
JSONObject json) {
if (json.has(LightenConstants.STYLE_ATTR_LINE_CLR))
registerTheme(type, styleFamily, DOMConstants.ATTR_LINE_COLOR,
colorToRgb(json
.getString(LightenConstants.STYLE_ATTR_LINE_CLR)));
if (json.has(LightenConstants.STYLE_ATTR_FILL_CLR))
registerTheme(type, styleFamily, DOMConstants.ATTR_FILL, colorToRgb(
json.getString(LightenConstants.STYLE_ATTR_FILL_CLR)));
if (json.has(LightenConstants.STYLE_ATTR_FONT_FAMILY))
registerTheme(type, styleFamily, DOMConstants.ATTR_FONT_FAMILY,
json.getString(LightenConstants.STYLE_ATTR_FONT_FAMILY));
if (json.has(LightenConstants.STYLE_ATTR_FONT_CLR))
registerTheme(type, styleFamily, DOMConstants.ATTR_COLOR,
colorToRgb(json
.getString(LightenConstants.STYLE_ATTR_FONT_CLR)));
if (json.has(LightenConstants.STYLE_ATTR_CORNER_RADIUS))
registerTheme(type, styleFamily, DOMConstants.ATTR_LINE_CORNER,
json.getInt(LightenConstants.STYLE_ATTR_CORNER_RADIUS)
+ PIXEL_POINT);
if (json.has(LightenConstants.STYLE_ATTR_LINE_WIDTH))
registerTheme(type, styleFamily, DOMConstants.ATTR_LINE_WIDTH,
json.getInt(LightenConstants.STYLE_ATTR_LINE_WIDTH)
+ PIXEL_POINT);
}
private void registerStyle(IStyled styleOwner, String key, String value) {
if (value == null)
return;
IStyle style = styleMap.get(styleOwner);
if (style == null) {
style = targetStyleSheet.createStyle(styleOwner.getStyleType());
targetStyleSheet.addStyle(style, IStyleSheet.NORMAL_STYLES);
styleMap.put(styleOwner, style);
}
style.setProperty(key, value);
}
private void registerTheme(String type, String styleFamily, String styleKey,
String styleValue) {
if (styleFamily == null || styleKey == null || styleValue == null)
return;
if (theme == null) {
theme = targetStyleSheet.createStyle(IStyle.THEME);
targetStyleSheet.addStyle(theme, IStyleSheet.MASTER_STYLES);
}
IStyle defaultStyle = theme.getDefaultStyle(styleFamily);
if (defaultStyle == null) {
defaultStyle = targetStyleSheet.createStyle(type);
targetStyleSheet.addStyle(defaultStyle,
IStyleSheet.AUTOMATIC_STYLES);
theme.setDefaultStyleId(styleFamily, defaultStyle.getId());
}
defaultStyle.setProperty(styleKey, styleValue);
}
private void importStyleAndTheme(String themeName) {
IStyleSheet targetStyleSheet = getTargetWorkbook().getStyleSheet();
for (Entry<IStyled, IStyle> entry : styleMap.entrySet()) {
IStyled styled = entry.getKey();
IStyle style = entry.getValue();
IStyle imported = targetStyleSheet.importStyle(style);
if (imported != null) {
styled.setStyleId(imported.getId());
}
}
if (theme != null) {
theme.setName(themeName);
IStyle imported = targetStyleSheet.importStyle(theme);
if (imported != null) {
targetSheet.setThemeId(imported.getId());
}
}
}
private String colorToRgb(String colorPoint) {
if ("0.00".equals(colorPoint.substring(colorPoint.lastIndexOf(',') + 1, //$NON-NLS-1$
colorPoint.length() - 1).trim())) {//ignore when opacity is 0.00
return null;
}
StringBuilder sb = new StringBuilder().append('#');
char[] chars = colorPoint.toCharArray();
StringBuilder splitBuilder = new StringBuilder();
for (char c : chars) {
if (c != '{' && c != ' ') {
if (c == ',') {
String value = Integer.toHexString(
Integer.valueOf(splitBuilder.toString()));
if (value.length() == 1) {
sb.append('0');
}
sb.append(value);
splitBuilder = new StringBuilder();
} else {
splitBuilder.append(c);
}
}
}
return sb.toString();
}
private void setTopicStyle(ITopic topic, JSONObject json) {
if (json.has(LightenConstants.STYLE_ATTR_LINE_CLR)) {
registerStyle(topic, DOMConstants.ATTR_LINE_COLOR, colorToRgb(
json.getString(LightenConstants.STYLE_ATTR_LINE_CLR)));
}
if (json.has(LightenConstants.STYLE_ATTR_FONT_CLR)) {
registerStyle(topic, DOMConstants.ATTR_COLOR, colorToRgb(
json.getString(LightenConstants.STYLE_ATTR_FONT_CLR)));
}
if (json.has(LightenConstants.STYLE_ATTR_FONT_WEIGHT)) {
registerStyle(topic, DOMConstants.ATTR_FONT_WEIGHT,
json.getString(LightenConstants.STYLE_ATTR_FONT_WEIGHT));
}
}
public void error(SAXParseException arg0) throws SAXException {
log(arg0, null);
}
public void fatalError(SAXParseException arg0) throws SAXException {
log(arg0, null);
}
public void warning(SAXParseException arg0) throws SAXException {
log(arg0, null);
}
}