<|start_filename|>AnnotationTool/annotate/src/utils.js<|end_filename|>
const copy = (obj) => {
    return JSON.parse(JSON.stringify(obj));
}

const newEmptyArray = (length) => {
    var array = new Array
    for(var i = 0; i < length; i++){
        array.push(new Array)
    }
    return array
}

const sample = (array) => {
    return array[Math.floor(Math.random() * array.length)]
}

const searchEdges = (group1, group2, edges) => {
    var candidateEdges = new Array
    for(let i = 0; i < group1.nodes.length; i++){
        for(let j = 0; j < group2.nodes.length; j++){
            for(let z = 0; z < edges.length; z++){
                let currEdge = edges[z]
                if((currEdge.node1 === group1.nodes[i].tableName && currEdge.node2 === group2.nodes[j].tableName) || (currEdge.node2 === group1.nodes[i].tableName && currEdge.node1 === group2.nodes[j].tableName)){
                    candidateEdges.push(edges[z])
                }
            }
        }
    }
    return candidateEdges
}

const searchJoinPath = (nodes, edges, selectedTables) => {
    var selectedNodes = new Array
    for(let i = 0; i < selectedTables.length; i++){
        for(let j = 0; j < nodes.length; j++){
            if(selectedTables[i] === nodes[j].tableName){
                selectedNodes.push(nodes[j])
                break
            }
        }
    }

    // Initially, each node is a group
    var groups = new Array
    for(let i = 0; i < selectedNodes.length; i++){
        groups.push({
            nodes: [selectedNodes[i]],
            edges: []
        })
    }
    var oldGroupLength = groups.length
    var newGroups = new Array
    // Merge Groups
    while(newGroups.length != 1 && newGroups.length != oldGroupLength){
        oldGroupLength = newGroups.length
        newGroups = new Array
        while(groups.length > 0){
            // Pop one from the left most position
            let currGroup = groups.splice(0, 1)[0]
            // Merge with other groups
            let groupsToRemove = new Array
            for(let i = 0; i < groups.length; i++){
                let candidateEdges = searchEdges(currGroup, groups[i], edges)
                if(candidateEdges.length > 0){
                    // Merge
                    groupsToRemove.push(groups[i])
                    currGroup.nodes = currGroup.nodes.concat(groups[i].nodes)
                    currGroup.edges.push(candidateEdges[0]) // Only get the first edge, Prone to introduce bugs
                    currGroup.edges = currGroup.edges.concat(groups[i].edges)
                }
            }
            newGroups.push(currGroup)
            //: Remove
            for(let i = 0; i < groupsToRemove.length; i++){
                let index = groups.indexOf(groupsToRemove[i])
                groups.splice(index, 1)
            }
        }
        groups = newGroups
    }

    console.log(newGroups)
    // To From Clause
    if(newGroups.length != 1){
        return ""
    }
    var fromClause = ""
    var finalGroup = newGroups[0]
    if(finalGroup.edges.length === 0){
        fromClause = `from ${finalGroup.nodes[0].tableName}`
    }else{
        var tableAliasMap = {}
        var currTableAliasIndex = 0
        for(let i = 0; i < finalGroup.edges.length; i++){
            let e = finalGroup.edges[i]
            let node1 = e['node1']
            let node2 = e['node2']
            let col1 = e['col1']
            let col2 = e['col2']
            if(i == 0){
                currTableAliasIndex += 1
                tableAliasMap[node1] = currTableAliasIndex
                currTableAliasIndex += 1
                tableAliasMap[node2] = currTableAliasIndex
                fromClause = `from ${node1} AS T${tableAliasMap[node1]} JOIN ${node2} AS T${tableAliasMap[node2]} ON T${tableAliasMap[node1]}.${col1} = T${tableAliasMap[node2]}.${col2}`
            }else{
                if(node1 in tableAliasMap && !(node2 in tableAliasMap)){
                    currTableAliasIndex += 1
                    tableAliasMap[node2] = currTableAliasIndex
                    fromClause += ` JOIN ${node2} AS T${tableAliasMap[node2]} ON T${tableAliasMap[node1]}.${col1} = T${tableAliasMap[node2]}.${col2}`
                }else if(node2 in tableAliasMap && !(node1 in tableAliasMap)){
                    currTableAliasIndex += 1
                    tableAliasMap[node1] = currTableAliasIndex
                    fromClause += ` JOIN ${node1} AS T${tableAliasMap[node1]} ON T${tableAliasMap[node2]}.${col2} = T${tableAliasMap[node1]}.${col1}`
                }
            }
        }
    }
    return fromClause
}

export default {
    copy,
    newEmptyArray,
    searchJoinPath,
    sample
}

<|start_filename|>AnnotationTool/annotate/src/event_bus.js<|end_filename|>
import Vue from 'vue'

// Event bus essentially is a component without any templates and styles

export const EventBus = new Vue()


<|start_filename|>AnnotationTool/annotate/src/network.js<|end_filename|>
import axios from "axios";

const baseurl = "/"

const getRemainingConversatioin = () => {
  const url = baseurl + "api/meta";
  return axios.get(url)
}

const getAnnotationList = () => {
    const url = baseurl + "api/annotation_list"
    return axios.get(url)
}

const getAnnotation = (cid) => {
    const url = baseurl + "api/annotate"
    if (cid) {
        return axios.get(url + "/" + cid)
    }
    return axios.get(url)
}

const getAnnotationByDatabaseId = (dbId) => {
    const url = baseurl + "api/annotate/db/" + dbId
    return axios.get(url)
}

const postAnnotation = (payload) => {
    const url = baseurl + "api/annotate"
    return axios.post(url, payload)
}

const login = (payload) => {
    const url = baseurl + "api/login"
    return axios.post(url, payload)
}

const getDatabase = (dbId) => {
    const url = baseurl + "api/db/" + dbId
    return axios.get(url)
}

const getDatabaseList = () => {
    const url = baseurl + "api/db_list/"
    return axios.get(url)
}

const parseSql = (payload) => {
    const url = baseurl + "api/sql/"
    return axios.post(url, payload)
}

const submitNewConversation = (payload) => {
    const url = baseurl + "api/conversation/"
    return axios.post(url, payload)
}

const getNewAnnotationList = () => {
    const url = baseurl + "api/new_annotation_list"
    return axios.get(url)
}

const getConversationbyId = (cid) => {
    const url = baseurl + "api/conversation/" + cid
    return axios.get(url)
}

// Translate Databases
const getTranslateDatabaseList = () => {
    const url = baseurl + "api/translate/database/"
    return axios.get(url)
}

const getTranslateDatabaseById = (dbId) => {
    const url = baseurl + "api/translate/database/" + dbId
    return axios.get(url)
}

const submitTranslation = (payload) => {
    const url = baseurl + "api/translate/database/"
    return axios.post(url, payload)
}

// Translate SparC conversations
const getTranslateConversationList = (dbId) => {
    const url = baseurl + "api/translate/database/" + dbId + "/conversations/"
    return axios.get(url)
}

const getTranslatedDatabaseByid = (dbId) => {
    const url = baseurl + "api/translated/database/" + dbId
    return axios.get(url)
}

const getTranslateConversationbyId = (cid) => {
    const url = baseurl + "api/translate/conversation/" + cid
    return axios.get(url)
}

const deleteTranslateConversation = (cid) => {
    const url = baseurl + "api/translate/conversation/" + cid
    return axios.delete(url)
}

const submitTranslateConversation = (payload) => {
    const url = baseurl + "api/translate/conversation/"
    return axios.post(url, payload)
}

export default {
  getRemainingConversatioin,
  getAnnotationList,
  getAnnotation,
  getAnnotationByDatabaseId,
  postAnnotation,
  login,
  getDatabase,
  getDatabaseList,
  parseSql,
  submitNewConversation,
  getNewAnnotationList,
  getConversationbyId,
  getTranslateDatabaseList,
  getTranslateDatabaseById,
  submitTranslation,
  getTranslateConversationList,
  getTranslatedDatabaseByid,
  getTranslateConversationbyId,
  deleteTranslateConversation,
  submitTranslateConversation
}

<|start_filename|>AnnotationTool/annotate/src/routes.js<|end_filename|>
import Login from './components/Login.vue'
import Annotation from './components/Annotation.vue'
import AnnotationList from './components/AnnotationList.vue'
import DatabaseList from './components/DatabaseList.vue'
import NewAnnotation from './components/NewAnnotation.vue'
import NewAnnotationList from './components/NewAnnotationList.vue'
import TranslateDatabaseList from './components/translation/TranslateDatabaseList.vue'
import TranslateDatabase from './components/translation/TranslateDatabase.vue'
import TranslateConversationList from './components/translation/TranslateConversationList.vue'
import TranslateAnnotation from './components/translation/TranslateAnnotation.vue'

const routes = [
  { path: "/login", component: Login, name: "login" },
  { path: "/translate/conversation/:id", component: TranslateAnnotation, name: "translateAnnotation"}, 
  { path: "/translate/database/:id/conversations/", component: TranslateConversationList, name: "translateConversations" }, 
  { path: "/translate/database/:id", component: TranslateDatabase, name: "translate" }, 
  { path: "/translate/database", component: TranslateDatabaseList, name: "translateDatabases" },
  { path: "/database", component: DatabaseList, name: "databases" },
  { path: "/database/:id", component: NewAnnotation, name: "newConversation" },
  { path: "/conversation/:id", component: NewAnnotation, name: "detailedConversation" },
  { path: "/conversation", component: NewAnnotationList, name: "newConversationList" },
  { path: "/list", component: AnnotationList, name: "list" },
  { path: "/:id(ex_\\d+)", component: Annotation, name: "detail" },
  { path: "/", component: Annotation, name: "root" },
];

export default routes