Type INodeModel interface

This commit is contained in:
Paulo Gustavo Veiga 2022-01-03 07:12:12 -08:00
parent b1809816b0
commit 954ee444ca
7 changed files with 127 additions and 169 deletions

View File

@ -22,7 +22,7 @@ class FeatureModelFactory {
model: NoteModel, model: NoteModel,
}]; }];
static createModel(type: string, attributes): FeatureModel { static createModel(type: FeatureType, attributes): FeatureModel {
$assert(type, 'type can not be null'); $assert(type, 'type can not be null');
$assert(attributes, 'attributes can not be null'); $assert(attributes, 'attributes can not be null');

View File

@ -74,7 +74,7 @@ abstract class IMindmap {
abstract hasAlreadyAdded(node: INodeModel): boolean; abstract hasAlreadyAdded(node: INodeModel): boolean;
abstract createNode(type: NodeType, id: number):void; abstract createNode(type: NodeType, id: number): INodeModel
abstract createRelationship(fromNode: NodeModel, toNode: NodeModel): void; abstract createRelationship(fromNode: NodeModel, toNode: NodeModel): void;

View File

@ -18,6 +18,7 @@
*/ */
import { $assert, $defined } from '@wisemapping/core-js'; import { $assert, $defined } from '@wisemapping/core-js';
import FeatureModel from './FeatureModel'; import FeatureModel from './FeatureModel';
import IMindmap from './IMindmap';
import Mindmap from './Mindmap'; import Mindmap from './Mindmap';
// regex taken from https://stackoverflow.com/a/34763398/58128 // regex taken from https://stackoverflow.com/a/34763398/58128
@ -37,7 +38,7 @@ abstract class INodeModel {
getId(): number { getId(): number {
return this.getProperty('id'); return this.getProperty('id');
} }
abstract getFeatures(): Array<FeatureModel>; abstract getFeatures(): FeatureModel[];
/** */ /** */
setId(id: number): void { setId(id: number): void {
@ -54,33 +55,26 @@ abstract class INodeModel {
} }
getType(): NodeModelType { getType(): NodeModelType {
return this.getProperty('type'); return this.getProperty('type') as NodeModelType;
} }
/** */
setType(type: NodeModelType): void { setType(type: NodeModelType): void {
this.putProperty('type', type); this.putProperty('type', type);
} }
/** */
setText(text: string): void { setText(text: string): void {
this.putProperty('text', text); this.putProperty('text', text);
} }
/** */ getText(): string {
getText() {
return this.getProperty('text'); return this.getProperty('text');
} }
/** */ setPosition(x: number, y: number): void {
setPosition(x, y) { this.putProperty('position', `{x:${x},y:${y}}`);
$assert(!Number.isNaN(parseInt(x, 10)), `x position is not valid:${x}`);
$assert(!Number.isNaN(parseInt(y, 10)), `y position is not valid:${y}`);
this.putProperty('position', `{x:${parseInt(x, 10)},y:${parseInt(y, 10)}}`);
} }
/** */ getPosition(): { x: number, y: number } {
getPosition() {
const value = this.getProperty('position'); const value = this.getProperty('position');
let result = null; let result = null;
if (value != null) { if (value != null) {
@ -89,13 +83,11 @@ abstract class INodeModel {
return result; return result;
} }
/** */ setImageSize(width: number, height: number) {
setImageSize(width, height) {
this.putProperty('imageSize', `{width:${width},height:${height}}`); this.putProperty('imageSize', `{width:${width},height:${height}}`);
} }
/** */ getImageSize(): {width: number, height: number} {
getImageSize() {
const value = this.getProperty('imageSize'); const value = this.getProperty('imageSize');
let result = null; let result = null;
if (value != null) { if (value != null) {
@ -104,28 +96,23 @@ abstract class INodeModel {
return result; return result;
} }
/** */ setImageUrl(url: string) {
setImageUrl(url) {
this.putProperty('imageUrl', url); this.putProperty('imageUrl', url);
} }
/** */ getMetadata(): string {
getMetadata() {
return this.getProperty('metadata'); return this.getProperty('metadata');
} }
/** */ setMetadata(json: string): void {
setMetadata(json) {
this.putProperty('metadata', json); this.putProperty('metadata', json);
} }
/** */ getImageUrl(): string {
getImageUrl() {
return this.getProperty('imageUrl'); return this.getProperty('imageUrl');
} }
/** */ getMindmap(): IMindmap {
getMindmap() {
return this._mindmap; return this._mindmap;
} }
@ -133,23 +120,22 @@ abstract class INodeModel {
* lets the mindmap handle the disconnect node operation * lets the mindmap handle the disconnect node operation
* @see mindplot.model.IMindmap.disconnect * @see mindplot.model.IMindmap.disconnect
*/ */
disconnect() { disconnect(): void {
const mindmap = this.getMindmap(); const mindmap = this.getMindmap();
mindmap.disconnect(this); mindmap.disconnect(this);
} }
/** */ /** */
getShapeType() { getShapeType(): string {
return this.getProperty('shapeType'); return this.getProperty('shapeType');
} }
/** */ /** */
setShapeType(type) { setShapeType(type: string) {
this.putProperty('shapeType', type); this.putProperty('shapeType', type);
} }
/** */ setOrder(value: number) {
setOrder(value) {
$assert( $assert(
(typeof value === 'number' && Number.isFinite(value)) || value == null, (typeof value === 'number' && Number.isFinite(value)) || value == null,
'Order must be null or a number', 'Order must be null or a number',
@ -157,120 +143,98 @@ abstract class INodeModel {
this.putProperty('order', value); this.putProperty('order', value);
} }
/** */ getOrder(): number {
getOrder() {
return this.getProperty('order'); return this.getProperty('order');
} }
/** */ setFontFamily(fontFamily: string): void {
setFontFamily(fontFamily) {
this.putProperty('fontFamily', fontFamily); this.putProperty('fontFamily', fontFamily);
} }
/** */ getFontFamily(): string {
getFontFamily() {
return this.getProperty('fontFamily'); return this.getProperty('fontFamily');
} }
/** */ /** */
setFontStyle(fontStyle) { setFontStyle(fontStyle: string) {
this.putProperty('fontStyle', fontStyle); this.putProperty('fontStyle', fontStyle);
} }
/** */ getFontStyle(): string {
getFontStyle() {
return this.getProperty('fontStyle'); return this.getProperty('fontStyle');
} }
/** */
setFontWeight(weight) { setFontWeight(weight) {
this.putProperty('fontWeight', weight); this.putProperty('fontWeight', weight);
} }
/** */
getFontWeight() { getFontWeight() {
return this.getProperty('fontWeight'); return this.getProperty('fontWeight');
} }
/** */ setFontColor(color: string) {
setFontColor(color) {
this.putProperty('fontColor', color); this.putProperty('fontColor', color);
} }
/** */ getFontColor(): string {
getFontColor() {
return this.getProperty('fontColor'); return this.getProperty('fontColor');
} }
/** */ setFontSize(size: number) {
setFontSize(size) {
this.putProperty('fontSize', size); this.putProperty('fontSize', size);
} }
/** */ getFontSize(): number {
getFontSize() {
return this.getProperty('fontSize'); return this.getProperty('fontSize');
} }
/** */ getBorderColor(): string {
getBorderColor() {
return this.getProperty('borderColor'); return this.getProperty('borderColor');
} }
/** */ setBorderColor(color: string): void {
setBorderColor(color) {
this.putProperty('borderColor', color); this.putProperty('borderColor', color);
} }
/** */ getBackgroundColor(): string {
getBackgroundColor() {
return this.getProperty('backgroundColor'); return this.getProperty('backgroundColor');
} }
/** */ setBackgroundColor(color: string) {
setBackgroundColor(color) {
this.putProperty('backgroundColor', color); this.putProperty('backgroundColor', color);
} }
/** */ areChildrenShrunken(): boolean {
areChildrenShrunken() {
const result = this.getProperty('shrunken'); const result = this.getProperty('shrunken');
return $defined(result) ? result : false; return $defined(result) ? result : false;
} }
/** /**
* @return {Boolean} true if the children nodes are hidden by the shrink option * @return {Boolean} true if the children nodes are hidden by the shrink option
*/ */
setChildrenShrunken(value) { setChildrenShrunken(value: boolean) {
this.putProperty('shrunken', value); this.putProperty('shrunken', value);
} }
/** isNodeModel(): boolean {
* @return {Boolean} true
*/
isNodeModel() {
return true; return true;
} }
/** /**
* @return {Boolean} true if the node model has a parent assigned to it * @return {Boolean} true if the node model has a parent assigned to it
*/ */
isConnected() { isConnected(): boolean {
return this.getParent() != null; return this.getParent() != null;
} }
/** @abstract */ abstract append(node): void;
// eslint-disable-next-line no-unused-vars
append(node) {
throw new Error('Unsupported operation');
}
/** /**
* lets the mindmap handle the connect node operation * lets the mindmap handle the connect node operation
* @throws will throw an error if parent is null or undefined * @throws will throw an error if parent is null or undefined
* @see mindplot.model.IMindmap.connect * @see mindplot.model.IMindmap.connect
*/ */
connectTo(parent) { connectTo(parent: INodeModel) {
$assert(parent, 'parent can not be null'); $assert(parent, 'parent can not be null');
const mindmap = this.getMindmap(); const mindmap = this.getMindmap();
mindmap.connect(parent, this); mindmap.connect(parent, this);
@ -280,7 +244,7 @@ abstract class INodeModel {
* @param target * @param target
* @return target * @return target
*/ */
copyTo(target) { copyTo(target: INodeModel): INodeModel {
const source = this; const source = this;
// Copy properties ... // Copy properties ...
const keys = source.getPropertiesKeys(); const keys = source.getPropertiesKeys();
@ -306,7 +270,7 @@ abstract class INodeModel {
* lets parent handle the delete node operation, or, if none defined, calls the mindmap to * lets parent handle the delete node operation, or, if none defined, calls the mindmap to
* remove the respective branch * remove the respective branch
*/ */
deleteNode() { deleteNode(): void {
const mindmap = this.getMindmap(); const mindmap = this.getMindmap();
// console.log("Before:" + mindmap.inspect()); // console.log("Before:" + mindmap.inspect());
@ -323,7 +287,7 @@ abstract class INodeModel {
abstract getPropertiesKeys(): string[]; abstract getPropertiesKeys(): string[];
abstract getProperty(key: string); abstract getProperty(key: string): any;
abstract putProperty(key: string, value: any): void; abstract putProperty(key: string, value: any): void;

View File

@ -19,14 +19,14 @@ import { $assert, $defined } from '@wisemapping/core-js';
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import INodeModel, { NodeModelType } from './INodeModel'; import INodeModel, { NodeModelType } from './INodeModel';
import FeatureModelFactory from './FeatureModelFactory'; import FeatureModelFactory from './FeatureModelFactory';
import FeatureModel from './FeatureModel'; import FeatureModel, { FeatureType } from './FeatureModel';
import Mindmap from './Mindmap'; import Mindmap from './Mindmap';
class NodeModel extends INodeModel { class NodeModel extends INodeModel {
private _properties: {}; private _properties: {};
private _children: INodeModel[]; private _children: NodeModel[];
private _features: FeatureModel[]; private _features: FeatureModel[];
private _parent: INodeModel; private _parent: NodeModel;
constructor(type: NodeModelType, mindmap: Mindmap, id: number) { constructor(type: NodeModelType, mindmap: Mindmap, id: number) {
$assert(type, 'Node type can not be null'); $assert(type, 'Node type can not be null');
@ -46,7 +46,7 @@ class NodeModel extends INodeModel {
* @param attributes * @param attributes
* @return {mindplot.model.FeatureModel} the created feature model * @return {mindplot.model.FeatureModel} the created feature model
*/ */
createFeature(type, attributes) { createFeature(type: FeatureType, attributes: any): FeatureModel {
return FeatureModelFactory.createModel(type, attributes); return FeatureModelFactory.createModel(type, attributes);
} }
@ -54,12 +54,11 @@ class NodeModel extends INodeModel {
* @param feature * @param feature
* @throws will throw an error if feature is null or undefined * @throws will throw an error if feature is null or undefined
*/ */
addFeature(feature) { addFeature(feature: FeatureModel) {
$assert(feature, 'feature can not be null'); $assert(feature, 'feature can not be null');
this._features.push(feature); this._features.push(feature);
} }
/** */
getFeatures() { getFeatures() {
return this._features; return this._features;
} }
@ -69,7 +68,7 @@ class NodeModel extends INodeModel {
* @throws will throw an error if feature is null or undefined * @throws will throw an error if feature is null or undefined
* @throws will throw an error if the feature could not be removed * @throws will throw an error if the feature could not be removed
*/ */
removeFeature(feature) { removeFeature(feature: FeatureModel) {
$assert(feature, 'feature can not be null'); $assert(feature, 'feature can not be null');
const size = this._features.length; const size = this._features.length;
this._features = this._features.filter((f) => feature.getId() !== f.getId()); this._features = this._features.filter((f) => feature.getId() !== f.getId());
@ -80,7 +79,7 @@ class NodeModel extends INodeModel {
* @param {String} type the feature type, e.g. icon or link * @param {String} type the feature type, e.g. icon or link
* @throws will throw an error if type is null or undefined * @throws will throw an error if type is null or undefined
*/ */
findFeatureByType(type) { findFeatureByType(type: string) {
$assert(type, 'type can not be null'); $assert(type, 'type can not be null');
return this._features.filter((feature) => feature.getType() === type); return this._features.filter((feature) => feature.getType() === type);
} }
@ -91,7 +90,7 @@ class NodeModel extends INodeModel {
* @throws will throw an error if feature could not be found * @throws will throw an error if feature could not be found
* @return the feature with the given id * @return the feature with the given id
*/ */
findFeatureById(id) { findFeatureById(id: number) {
$assert($defined(id), 'id can not be null'); $assert($defined(id), 'id can not be null');
const result = this._features.filter((feature) => feature.getId() === id); const result = this._features.filter((feature) => feature.getId() === id);
$assert(result.length === 1, `Feature could not be found:${id}`); $assert(result.length === 1, `Feature could not be found:${id}`);
@ -108,7 +107,7 @@ class NodeModel extends INodeModel {
* @param value * @param value
* @throws will throw an error if key is null or undefined * @throws will throw an error if key is null or undefined
*/ */
putProperty(key, value) { putProperty(key: string, value: string | number | boolean) {
$defined(key, 'key can not be null'); $defined(key, 'key can not be null');
this._properties[key] = value; this._properties[key] = value;
} }
@ -176,25 +175,22 @@ class NodeModel extends INodeModel {
* @param {mindplot.model.NodeModel} child * @param {mindplot.model.NodeModel} child
* @throws will throw an error if child is null, undefined or not a NodeModel object * @throws will throw an error if child is null, undefined or not a NodeModel object
*/ */
removeChild(child): void { removeChild(child: NodeModel): void {
$assert(child && child.isNodeModel(), 'Only NodeModel can be appended to Mindmap object.'); $assert(child && child.isNodeModel(), 'Only NodeModel can be appended to Mindmap object.');
this._children = this._children.filter((c) => c !== child); this._children = this._children.filter((c) => c !== child);
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
child._parent = null; child._parent = null;
} }
/** */ getChildren(): NodeModel[] {
getChildren() {
return this._children; return this._children;
} }
/** */ getParent(): NodeModel {
getParent() {
return this._parent; return this._parent;
} }
/** */ setParent(parent: NodeModel): void {
setParent(parent) {
$assert(parent !== this, 'The same node can not be parent and child if itself.'); $assert(parent !== this, 'The same node can not be parent and child if itself.');
this._parent = parent; this._parent = parent;
} }

View File

@ -19,11 +19,13 @@ import {
} from '@wisemapping/core-js'; } from '@wisemapping/core-js';
import ModelCodeName from './ModelCodeName'; import ModelCodeName from './ModelCodeName';
import Mindmap from '../model/Mindmap'; import Mindmap from '../model/Mindmap';
import INodeModel from '../model/INodeModel';
import FeatureModelFactory from '../model/FeatureModelFactory'; import FeatureModelFactory from '../model/FeatureModelFactory';
import NodeModel from '../model/NodeModel';
class XMLSerializerBeta { class XMLSerializerBeta {
toXML(mindmap) { private static MAP_ROOT_NODE = 'map';
toXML(mindmap: Mindmap) {
$assert(mindmap, 'Can not save a null mindmap'); $assert(mindmap, 'Can not save a null mindmap');
const document = createDocument(); const document = createDocument();
@ -38,21 +40,20 @@ class XMLSerializerBeta {
// Create branches ... // Create branches ...
const topics = mindmap.getBranches(); const topics = mindmap.getBranches();
for (let i = 0; i < topics.length; i++) { topics.forEach((topic) => {
const topic = topics[i];
const topicDom = this._topicToXML(document, topic); const topicDom = this._topicToXML(document, topic);
mapElem.append(topicDom); mapElem.append(topicDom);
} });
return document; return document;
} }
_topicToXML(document, topic) { _topicToXML(document: Document, topic: NodeModel) {
const parentTopic = document.createElement('topic'); const parentTopic = document.createElement('topic');
// Set topic attributes... // Set topic attributes...
if (topic.getType() === 'CentralTopic') { if (topic.getType() === 'CentralTopic') {
parentTopic.setAttribute('central', true); parentTopic.setAttribute('central', new Boolean(true).toString());
} else { } else {
const parent = topic.getParent(); const parent = topic.getParent();
if (parent == null || parent.getType() === 'CentralTopic') { if (parent == null || parent.getType() === 'CentralTopic') {
@ -60,7 +61,7 @@ class XMLSerializerBeta {
parentTopic.setAttribute('position', `${pos.x},${pos.y}`); parentTopic.setAttribute('position', `${pos.x},${pos.y}`);
} else { } else {
const order = topic.getOrder(); const order = topic.getOrder();
parentTopic.setAttribute('order', order); parentTopic.setAttribute('order', order.toString());
} }
} }
@ -75,7 +76,7 @@ class XMLSerializerBeta {
} }
if (topic.areChildrenShrunken()) { if (topic.areChildrenShrunken()) {
parentTopic.setAttribute('shrink', true); parentTopic.setAttribute('shrink', new Boolean(true).toString());
} }
// Font properties ... // Font properties ...
@ -117,36 +118,31 @@ class XMLSerializerBeta {
} }
// ICONS // ICONS
let i; const icons = topic.findFeatureByType('icons');
const icons = topic.getIcons(); icons.forEach((icon)=>{
for (i = 0; i < icons.length; i++) {
const icon = icons[i];
const iconDom = this._iconToXML(document, icon); const iconDom = this._iconToXML(document, icon);
parentTopic.append(iconDom); parentTopic.append(iconDom);
} });
// LINKS // LINKS
const links = topic.getLinks(); const links = topic.findFeatureByType('links');
for (i = 0; i < links.length; i++) { icons.forEach((link)=>{
const link = links[i];
const linkDom = this._linkToXML(document, link); const linkDom = this._linkToXML(document, link);
parentTopic.append(linkDom); parentTopic.append(linkDom);
} });
const notes = topic.getNotes(); const notes = topic.findFeatureByType('note');
for (i = 0; i < notes.length; i++) { notes.forEach((note)=>{
const note = notes[i];
const noteDom = this._noteToXML(document, note); const noteDom = this._noteToXML(document, note);
parentTopic.append(noteDom); parentTopic.append(noteDom);
} });
// CHILDREN TOPICS // CHILDREN TOPICS
const childTopics = topic.getChildren(); const childTopics = topic.getChildren();
for (i = 0; i < childTopics.length; i++) { childTopics.forEach((childTopic)=>{
const childTopic = childTopics[i];
const childDom = this._topicToXML(document, childTopic); const childDom = this._topicToXML(document, childTopic);
parentTopic.append(childDom); parentTopic.append(childDom);
} });
return parentTopic; return parentTopic;
} }
@ -288,13 +284,13 @@ class XMLSerializerBeta {
const childTopic = this._deserializeNode(child, mindmap); const childTopic = this._deserializeNode(child, mindmap);
childTopic.connectTo(topic); childTopic.connectTo(topic);
} else if (child.tagName === 'icon') { } else if (child.tagName === 'icon') {
const icon = this._deserializeIcon(child, topic); const icon = this._deserializeIcon(child);
topic.addFeature(icon); topic.addFeature(icon);
} else if (child.tagName === 'link') { } else if (child.tagName === 'link') {
const link = this._deserializeLink(child, topic); const link = this._deserializeLink(child);
topic.addFeature(link); topic.addFeature(link);
} else if (child.tagName === 'note') { } else if (child.tagName === 'note') {
const note = this._deserializeNote(child, topic); const note = this._deserializeNote(child);
topic.addFeature(note); topic.addFeature(note);
} }
} }
@ -303,23 +299,21 @@ class XMLSerializerBeta {
return topic; return topic;
} }
_deserializeIcon(domElem) { _deserializeIcon(domElem: Element) {
let icon = domElem.getAttribute('id'); let icon = domElem.getAttribute('id');
icon = icon.replace('images/', 'icons/legacy/'); icon = icon.replace('images/', 'icons/legacy/');
return FeatureModelFactory.createModel(FeatureModelFactory.Icon.id, { id: icon }); return FeatureModelFactory.createModel('icon', { id: icon });
} }
_deserializeLink(domElem) { _deserializeLink(domElem: Element) {
return FeatureModelFactory.createModel(FeatureModelFactory.Link.id, { url: domElem.getAttribute('url') }); return FeatureModelFactory.createModel('link', { url: domElem.getAttribute('url') });
} }
_deserializeNote(domElem) { _deserializeNote(domElem: Element) {
const text = domElem.getAttribute('text'); const text = domElem.getAttribute('text');
return FeatureModelFactory.createModel(FeatureModelFactory.Note.id, { text: text == null ? ' ' : text }); return FeatureModelFactory.createModel('note', { text: text == null ? ' ' : text });
} }
} }
XMLSerializerBeta.MAP_ROOT_NODE = 'map';
// eslint-disable-next-line camelcase
export default XMLSerializerBeta; export default XMLSerializerBeta;

View File

@ -18,12 +18,17 @@
import { $assert, $defined, createDocument } from '@wisemapping/core-js'; import { $assert, $defined, createDocument } from '@wisemapping/core-js';
import { Point } from '@wisemapping/web2d'; import { Point } from '@wisemapping/web2d';
import Mindmap from '../model/Mindmap'; import Mindmap from '../model/Mindmap';
import INodeModel, { TopicShape } from '../model/INodeModel'; import { TopicShape } from '../model/INodeModel';
import ConnectionLine from '../ConnectionLine'; import ConnectionLine from '../ConnectionLine';
import FeatureModelFactory from '../model/FeatureModelFactory'; import FeatureModelFactory from '../model/FeatureModelFactory';
import NodeModel from '../model/NodeModel';
import { FeatureType } from '../model/FeatureModel';
class XMLSerializerPela { class XMLSerializerPela {
toXML(mindmap) { private static MAP_ROOT_NODE = 'map';
private _idsMap: {};
toXML(mindmap: Mindmap) {
$assert(mindmap, 'Can not save a null mindmap'); $assert(mindmap, 'Can not save a null mindmap');
const document = createDocument(); const document = createDocument();
@ -64,7 +69,7 @@ class XMLSerializerPela {
return document; return document;
} }
_topicToXML(document, topic) { _topicToXML(document: Document, topic: NodeModel) {
const parentTopic = document.createElement('topic'); const parentTopic = document.createElement('topic');
// Set topic attributes... // Set topic attributes...
@ -75,7 +80,7 @@ class XMLSerializerPela {
parentTopic.setAttribute('position', `${pos.x},${pos.y}`); parentTopic.setAttribute('position', `${pos.x},${pos.y}`);
const order = topic.getOrder(); const order = topic.getOrder();
if (typeof order === 'number' && Number.isFinite(order)) { parentTopic.setAttribute('order', order); } if (typeof order === 'number' && Number.isFinite(order)) { parentTopic.setAttribute('order', order.toString()); }
} }
const text = topic.getText(); const text = topic.getText();
@ -88,9 +93,10 @@ class XMLSerializerPela {
parentTopic.setAttribute('shape', shape); parentTopic.setAttribute('shape', shape);
if (shape === TopicShape.IMAGE) { if (shape === TopicShape.IMAGE) {
const size = topic.getImageSize();
parentTopic.setAttribute( parentTopic.setAttribute(
'image', 'image',
`${topic.getImageSize().width},${topic.getImageSize().height `${size.width},${size.height
}:${topic.getImageUrl()}`, }:${topic.getImageUrl()}`,
); );
} }
@ -102,7 +108,7 @@ class XMLSerializerPela {
// Font properties ... // Font properties ...
const id = topic.getId(); const id = topic.getId();
parentTopic.setAttribute('id', id); parentTopic.setAttribute('id', id.toString());
let font = ''; let font = '';
@ -243,14 +249,18 @@ class XMLSerializerPela {
// Add all the topics nodes ... // Add all the topics nodes ...
const childNodes = Array.from(rootElem.childNodes); const childNodes = Array.from(rootElem.childNodes);
const topicsNodes = childNodes.filter((child) => (child.nodeType === 1 && child.tagName === 'topic')); const topicsNodes = childNodes.
filter((child: ChildNode) => (child.nodeType === 1 && (child as Element).tagName === 'topic'))
.map((c) => c as Element);
topicsNodes.forEach((child) => { topicsNodes.forEach((child) => {
const topic = this._deserializeNode(child, mindmap); const topic = this._deserializeNode(child, mindmap);
mindmap.addBranch(topic); mindmap.addBranch(topic);
}); });
// Then all relationshops, they are connected to topics ... // Then all relationshops, they are connected to topics ...
const relationshipsNodes = childNodes.filter((child) => (child.nodeType === 1 && child.tagName === 'relationship')); const relationshipsNodes = childNodes.
filter((child: ChildNode) => (child.nodeType === 1 && (child as Element).tagName === 'relationship'))
.map((c) => c as Element);
relationshipsNodes.forEach((child) => { relationshipsNodes.forEach((child) => {
try { try {
const relationship = XMLSerializerPela._deserializeRelationship(child, mindmap); const relationship = XMLSerializerPela._deserializeRelationship(child, mindmap);
@ -266,15 +276,15 @@ class XMLSerializerPela {
return mindmap; return mindmap;
} }
_deserializeNode(domElem, mindmap) { _deserializeNode(domElem: Element, mindmap: Mindmap) {
const type = domElem.getAttribute('central') != null const type = domElem.getAttribute('central') != null
? 'CentralTopic' ? 'CentralTopic'
: 'MainTopic'; : 'MainTopic';
// Load attributes... // Load attributes...
let id = domElem.getAttribute('id'); let id = null;
if ($defined(id)) { if ($defined(domElem.getAttribute('id'))) {
id = parseInt(id, 10); id = Number.parseInt(domElem.getAttribute('id'), 10);
} }
if (this._idsMap[id]) { if (this._idsMap[id]) {
@ -300,7 +310,7 @@ class XMLSerializerPela {
} }
if (font[1]) { if (font[1]) {
topic.setFontSize(font[1]); topic.setFontSize(Number.parseInt(font[1], 10));
} }
if (font[2]) { if (font[2]) {
@ -327,7 +337,7 @@ class XMLSerializerPela {
topic.setImageUrl(url); topic.setImageUrl(url);
const split = size.split(','); const split = size.split(',');
topic.setImageSize(split[0], split[1]); topic.setImageSize(Number.parseInt(split[0], 10), Number.parseInt(split[1], 10));
} }
} }
@ -350,13 +360,13 @@ class XMLSerializerPela {
const isShrink = domElem.getAttribute('shrink'); const isShrink = domElem.getAttribute('shrink');
// Hack: Some production maps has been stored with the central topic collapsed. This is a bug. // Hack: Some production maps has been stored with the central topic collapsed. This is a bug.
if ($defined(isShrink) && type !== 'CentralTopic') { if ($defined(isShrink) && type !== 'CentralTopic') {
topic.setChildrenShrunken(isShrink); topic.setChildrenShrunken(Boolean(isShrink));
} }
const position = domElem.getAttribute('position'); const position = domElem.getAttribute('position');
if ($defined(position)) { if ($defined(position)) {
const pos = position.split(','); const pos = position.split(',');
topic.setPosition(pos[0], pos[1]); topic.setPosition(Number.parseInt(pos[0]), Number.parseInt(pos[1]));
} }
const metadata = domElem.getAttribute('metadata'); const metadata = domElem.getAttribute('metadata');
@ -368,29 +378,31 @@ class XMLSerializerPela {
const children = Array.from(domElem.childNodes); const children = Array.from(domElem.childNodes);
children.forEach((child) => { children.forEach((child) => {
if (child.nodeType === Node.ELEMENT_NODE) { if (child.nodeType === Node.ELEMENT_NODE) {
if (child.tagName === 'topic') { const elem = child as Element;
const childTopic = this._deserializeNode(child, mindmap); if (elem.tagName === 'topic') {
const childTopic = this._deserializeNode(elem, mindmap);
childTopic.connectTo(topic); childTopic.connectTo(topic);
} else if (FeatureModelFactory.isSupported(child.tagName)) { } else if (FeatureModelFactory.isSupported(elem.tagName)) {
// Load attributes ... // Load attributes ...
const namedNodeMap = child.attributes; const namedNodeMap = elem.attributes;
const attributes = {}; const attributes = {};
for (let j = 0; j < namedNodeMap.length; j++) { for (let j = 0; j < namedNodeMap.length; j++) {
const attribute = namedNodeMap.item(j); const attribute = namedNodeMap.item(j);
attributes[attribute.name] = attribute.value; attributes[attribute.name] = attribute.value;
} }
// Has text node ?. // Has text node ?.
const textAttr = XMLSerializerPela._deserializeTextAttr(child); const textAttr = XMLSerializerPela._deserializeTextAttr(elem);
if (textAttr) { if (textAttr) {
attributes.text = textAttr; attributes['text'] = textAttr;
} }
// Create a new element .... // Create a new element ....
const featureType = child.tagName; const featureType = elem.tagName as FeatureType;
const feature = FeatureModelFactory.createModel(featureType, attributes); const feature = FeatureModelFactory.createModel(featureType, attributes);
topic.addFeature(feature); topic.addFeature(feature);
} else if (child.tagName === 'text') { } else if (elem.tagName === 'text') {
const nodeText = XMLSerializerPela._deserializeNodeText(child); const nodeText = XMLSerializerPela._deserializeNodeText(child);
topic.setText(nodeText); topic.setText(nodeText);
} }
@ -400,7 +412,7 @@ class XMLSerializerPela {
return topic; return topic;
} }
static _deserializeTextAttr(domElem) { static _deserializeTextAttr(domElem: Element): string {
let value = domElem.getAttribute('text'); let value = domElem.getAttribute('text');
if (!$defined(value)) { if (!$defined(value)) {
const children = domElem.childNodes; const children = domElem.childNodes;
@ -497,13 +509,5 @@ class XMLSerializerPela {
} }
} }
/**
* a wisemap's root element tag name
* @constant
* @type {String}
* @default
*/
XMLSerializerPela.MAP_ROOT_NODE = 'map';
// eslint-disable-next-line camelcase
export default XMLSerializerPela; export default XMLSerializerPela;