Source: snet.maia

///
/// @license
/// Copyright 2020 Roberto Luiz Souza Monteiro,
///                Renata Souza Barreto,
///                Hernane Borges de Barros Pereira.
///
/// Licensed under the Apache License, Version 2.0 (the 'License');
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at;
///
///   http://www.apache.org/licenses/LICENSE-2.0;
///
/// Unless required by applicable law or agreed to in writing, software;
/// distributed under the License is distributed on an 'AS IS' BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, eitherMath.express or implied.
/// See the License for the specific language governing permissions and;
/// limitations under the License.
///

 ///
 /// Library for building semantic networks.
 /// @namespace snet
 ///
namespace snet {
    ///
    /// Convert a file in DLF format to JSON.
    /// @method dlfFileToJson
    /// @memberof snet
    /// @param {string}   fileContents - DLF file contents.
    /// @param {object}   properties - Network properties (n, m and directed).
    /// @param {string}   topology - Network topology. It can be:
    ///                              chain, circle or clique.
    /// @param {boolean}  weighted - The created network must be weighted based
    ///                              on the number of occurrences of the connections
    ///                              between the vertices.
    /// @param {object}   network - Network previously created to insert new data.
    /// @return {object}  A JSON containing the network.
    ///
    function dlfFileToJson(fileContents, properties, topology, weighted, network) {
        if (core.type(properties) == "undefined") {
            properties = {
                "n": 0,
                "m": 0,
                "directed": true
            }
        } else {
            properties.n = 0
            properties.m = 0
            properties.directed = true
        }
        if (core.type(topology) == "undefined") {
            topology = "chain"
        }
        if (core.type(weighted) == "undefined") {
            weighted = true
        }
        if (core.type(network) == "undefined") {
            network = {
                "nodes": [],
                "edges": []
            }
        }

        // Search engine.
        queryObject = ""
        edgeIndex = []

        function findNode(element, index, list) {
            thisNode = list[index]
            found = (element.label == queryObject)
            return(found)
        }
        function findEdge(element, index, list) {
            thisNode = list[index]
            found = ((element.source == queryObject.source) && (element.target== queryObject.target))
            edgeIndex = index
            return(found)
        }

        id = -1
        nodes = []
        endOfRecord = false

        t1 = core.date()
        
        fileLines = core.split(core.replace(fileContents, "\r\n", "\n"), "\n")

        system.println("Processing " + fileLines.length + " lines ...")

        for (l = 0; l < fileLines.length; l = l + 1) {
            if ((l != 0) && (l % 1000 == 0)) {
                system.println("Processed " + l.toString() + " lines of " + fileLines.length.toString() + ".")
            }
            line = fileLines[l]
            line = core.replace(line, "\t", " ")
            record = core.splitCSV(line.trim(), " ", true)
            if (record[0] == "{S}") {
                endOfRecord = true
            }
            if (core.length(record) >= 1) {
                if (!endOfRecord) {
                    id = id + 1
                    label = core.toString(record[0])
                    x = ""
                    y = ""
                    size = ""
                    if (x == "") {
                        x = math.random()
                    }
                    if (y == "") {
                        y = math.random()
                    }
                    if (size == "") {
                        size = 1
                    }
                    node = {
                        "id": "n" + id,
                        "label": label,
                        "x": x,
                        "y": y,
                        "size": size
                    }
                    nodes.push(node)
                } else {
                    foreach (nodes; index; node) {
                        queryObject = node.label
                        nodeFound = network.nodes.find(findNode)
                        if (core.type(nodeFound) == "undefined") {
                            node.id = "n" + network.nodes.length
                            network.nodes.push(node)
                        } else {
                            node.id = nodeFound.id
                        }
                    }
                    if (topology == "chain") {
                        for (i = 0; i < nodes.length - 1; i = i + 1) {
                            node1 = nodes[i]
                            node2 = nodes[i + 1]

                            edgeIndex = []
                            queryObject = {"source": node1.id, "target": node2.id}
                            edgeFound = network.edges.find(findEdge)
                            
                            if (core.type(edgeFound) == "undefined") {
                                edge = {
                                    "id": "e" + network.edges.length,
                                    "source": node1.id,
                                    "target": node2.id,
                                    "size": 1,
                                    "type": "arrow"
                                }
                                network.edges.push(edge)
                            } else {
                                if (weighted) {
                                    edge = network.edges[edgeIndex]
                                    edge.size = edge.size + 1
                                }
                            }
                        }
                    } elseif (topology == "clique") {
                        foreach (nodes; index1; node1) {
                            foreach (nodes; index2; node2) {
                                if (index1 != index2) {
                                    edgeIndex = []
                                    queryObject = {"source": node1.id, "target": node2.id}
                                    edgeFound = network.edges.find(findEdge)

                                    if (core.type(edgeFound) == "undefined") {
                                        edge = {
                                            "id": "e" + network.edges.length,
                                            "source": node1.id,
                                            "target": node2.id,
                                            "size": 1,
                                            "type": "arrow"
                                        }
                                        network.edges.push(edge)
                                    } else {
                                        if (weighted) {
                                            edge = network.edges[edgeIndex]
                                            edge.size = edge.size + 1
                                        }
                                    }
                                }
                            }
                        }
                    } elseif (topology == "circle") {
                        for (i = 0; i < nodes.length - 1; i = i + 1) {
                            node1 = nodes[i]
                            node2 = nodes[i + 1]

                            edgeIndex = []
                            queryObject = {"source": node1.id, "target": node2.id}
                            edgeFound = network.edges.find(findEdge)
                            
                            if (core.type(edgeFound) == "undefined") {
                                edge = {
                                    "id": "e" + network.edges.length,
                                    "source": node1.id,
                                    "target": node2.id,
                                    "size": 1,
                                    "type": "arrow"
                                }
                                network.edges.push(edge)
                            } else {
                                if (weighted) {
                                    edge = network.edges[edgeIndex]
                                    edge.size = edge.size + 1
                                }
                            }

                            if (i + 1 == nodes.length - 1) {
                                node1 = nodes[i + 1]
                                node2 = nodes[0]

                                edgeIndex = []
                                queryObject = {"source": node1.id, "target": node2.id}
                                edgeFound = network.edges.find(findEdge)

                                if (core.type(edgeFound) == "undefined") {
                                    edge = {
                                        "id": "e" + network.edges.length,
                                        "source": node1.id,
                                        "target": node2.id,
                                        "size": 1,
                                        "type": "arrow"
                                    }
                                    network.edges.push(edge)
                                } else {
                                    if (weighted) {
                                        edge = network.edges[edgeIndex]
                                        edge.size = edge.size + 1
                                    }
                                }
                            }
                        }
                    }
                    id = -1
                    nodes = []
                    endOfRecord = false
                }
            }
        }

        properties.n = network.nodes.length
        properties.m = network.edges.length
        
        t2 = core.date()
        t = t2 - t1

        system.println("Processed " + l.toString() + " lines of " + fileLines.length.toString() + ".")
        system.println("Elapsed time: " + t + " ms.")

        return(network)
    }
}