// Generated by CoffeeScript 1.12.7
var Easydb4Migration,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  hasProp = {}.hasOwnProperty,
  indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

Easydb4Migration = (function(superClass) {
  extend(Easydb4Migration, superClass);

  function Easydb4Migration() {
    this.getTargetColumn = bind(this.getTargetColumn, this);
    this.__processGetty = bind(this.__processGetty, this);
    this.logerror = bind(this.logerror, this);
    this.loginfo = bind(this.loginfo, this);
    this.logwarn = bind(this.logwarn, this);
    this.__log = bind(this.__log, this);
    return Easydb4Migration.__super__.constructor.apply(this, arguments);
  }

  Easydb4Migration.click = function() {
    var mig;
    ez5.rootMenu.closeMenu();
    mig = new Easydb4Migration();
    return mig.start();
  };

  Easydb4Migration.label = function() {
    return "easydb4migration.button";
  };

  Easydb4Migration.is_allowed = function() {
    return ez5.session.hasSystemRight("root", "plugin.easydb4migration.migration");
  };

  Easydb4Migration.group = function() {
    return "za_other";
  };

  Easydb4Migration.submenu = function() {
    return "plugins";
  };

  Easydb4Migration.prototype.__log = function(type, args) {
    var arg, j, len1, msg;
    msg = [];
    for (j = 0, len1 = args.length; j < len1; j++) {
      arg = args[j];
      msg.push(arg + "");
    }
    if (!this.__logentries) {
      this.__logentries = [["type", "time", "msg"]];
    }
    return this.__logentries.push([type, ez5.format_date_and_time(new Date(), true), msg.join(" ")]);
  };

  Easydb4Migration.prototype.logwarn = function(msg) {
    console.info.apply(console, arguments);
    return this.__log("warn", arguments);
  };

  Easydb4Migration.prototype.loginfo = function(msg) {
    console.info.apply(console, arguments);
    return this.__log("info", arguments);
  };

  Easydb4Migration.prototype.logerror = function(msg) {
    console.error.apply(console, arguments);
    return this.__log("error", arguments);
  };

  Easydb4Migration.prototype.start = function() {
    var baseConfig, l;
    this.history = [];
    baseConfig = ez5.session.getBaseConfig("plugin", "easydb-easydb4migration-plugin");
    baseConfig = baseConfig.system || baseConfig;
    this.__config = baseConfig.easydb4migration || {};
    if (!this.__config.fylr_inst) {
      this.__config.fylr_inst = ez5.session.getInstance().name;
    }
    if (!this.__config.fylr_url || !this.__config.fylr_inst || !this.__config.fylr_uid) {
      CUI.problem({
        text: $$("easydb4migration.check_config")
      });
      return;
    }
    l = CUI.parseLocation(this.__config.fylr_url);
    if (!l) {
      CUI.problem({
        text: $$("easydb4migration.check_config")
      });
      return;
    }
    if (l.href.endsWith("/")) {
      l.href = l.href.slice(0, -1);
    }
    this.__config.fylr_url = l.href;
    this.__config.fylr_inst_uid = this.__config.fylr_inst + '/' + this.__config.fylr_uid;
    this.__plugins = Easydb4Migration.plugins.newPlugins({
      migration: this
    });
    this.__tools = Easydb4Migration.tools.newPlugins({
      migration: this
    });
    this.initSettings();
    return this.acquireLock().done((function(_this) {
      return function() {
        return _this.showModal();
      };
    })(this));
  };

  Easydb4Migration.prototype.getEasydb4ReferencePrefix = function(column_name, source_name) {
    var ref;
    if (!CUI.util.isEmpty(this.__settings.easydb4_reference_prefix)) {
      ref = this.__settings.easydb4_reference_prefix + ":";
    } else {
      ref = "";
    }
    if (column_name === "easydb4_reference") {
      return source_name + ":";
    } else {
      return ref;
    }
  };

  Easydb4Migration.prototype.getEasydb4TableName = function(tn) {
    var ref1, schema;
    if (!CUI.util.isEmpty((ref1 = this.__settings.easydb4_schema) != null ? ref1.trim() : void 0)) {
      schema = this.__settings.easydb4_schema;
    } else {
      schema = "public";
    }
    return '"source.' + schema + "." + tn + '"';
  };

  Easydb4Migration.prototype.acquireLock = function() {
    var connect, dfr;
    dfr = new CUI.Deferred();
    connect = new CUI.XHR({
      timeout: 1000,
      url: this.__config.fylr_url + '/objectstore/acquire/' + this.__config.fylr_inst_uid
    });
    dfr.fail((function(_this) {
      return function() {
        return CUI.problem({
          text: "Unable to acquire lock"
        });
      };
    })(this));
    connect.start().done((function(_this) {
      return function(res) {
        if ((res != null ? res.status : void 0) === "open") {
          return dfr.resolve();
        } else {
          return dfr.reject();
        }
      };
    })(this)).fail((function(_this) {
      return function() {
        return dfr.reject.apply(dfr, arguments);
      };
    })(this));
    return dfr.promise();
  };

  Easydb4Migration.prototype.releaseLock = function() {
    var connect;
    connect = new CUI.XHR({
      timeout: 1000,
      url: this.__config.fylr_url + '/objectstore/release/' + this.__config.fylr_inst_uid
    });
    return connect.start().fail((function(_this) {
      return function() {
        return CUI.problem({
          text: "Unable to release lock"
        });
      };
    })(this));
  };

  Easydb4Migration.prototype.debugResult = function(result, max_width) {
    var _row, _row2, col, idx, imgs, j, len1, len2, len3, len4, len5, len6, m, n, o, p, pad, r, ref1, ref2, ref3, ref4, ref5, ref6, row, sum, u, urls, w, widths, x;
    if (max_width == null) {
      max_width = 15;
    }
    pad = (function(_this) {
      return function(_s, idx, padchar) {
        var c, i, j, ref1, s, width;
        if (padchar == null) {
          padchar = " ";
        }
        s = "" + _s;
        c = [];
        width = Math.max(result.columns[idx].length, widths[idx]);
        for (i = j = 0, ref1 = width; 0 <= ref1 ? j < ref1 : j > ref1; i = 0 <= ref1 ? ++j : --j) {
          if (i >= s.length) {
            c.push(padchar);
          } else {
            c.push(s[i]);
          }
        }
        return c.join("");
      };
    })(this);
    widths = [];
    ref1 = result.columns;
    for (idx = j = 0, len1 = ref1.length; j < len1; idx = ++j) {
      col = ref1[idx];
      if (widths[idx] === void 0) {
        widths[idx] = col.length;
      } else if (col.length > widths[idx]) {
        widths[idx] = col.length;
      }
    }
    ref2 = result.rows || [];
    for (m = 0, len2 = ref2.length; m < len2; m++) {
      row = ref2[m];
      for (idx = n = 0, ref3 = row.__len; n < ref3; idx = n += 1) {
        col = _row[idx];
        if (col === null) {
          col = row[idx] = "<null>";
        }
        if (col.length > widths[idx]) {
          widths[idx] = col.length;
        }
      }
    }
    sum = 0;
    for (idx = o = 0, len3 = widths.length; o < len3; idx = ++o) {
      w = widths[idx];
      widths[idx] = Math.min(w, max_width);
      sum += widths[idx];
    }
    if (sum < 80) {
      widths[widths.length - 1] += 80 - sum;
    }
    _row = [];
    _row2 = [];
    ref4 = result.columns;
    for (idx = p = 0, len4 = ref4.length; p < len4; idx = ++p) {
      col = ref4[idx];
      _row.push(pad(col, idx));
      _row2.push(pad("", idx, "-"));
    }
    console.debug(_row.join(" | "));
    console.debug(_row2.join(" | "));
    imgs = result.columns.length === 1;
    ref5 = result.rows || [];
    for (idx = r = 0, len5 = ref5.length; r < len5; idx = ++r) {
      row = ref5[idx];
      _row = [];
      urls = [];
      for (idx = u = 0, ref6 = row.__len; u < ref6; idx = u += 1) {
        col = row[idx];
      }
      for (idx = x = 0, len6 = row.length; x < len6; idx = ++x) {
        col = row[idx];
        _row.push(pad(col, idx));
      }
      console.debug(_row.join(" | "));
    }
  };

  Easydb4Migration.prototype.dbq = function(query, max_width) {
    if (max_width == null) {
      max_width = 15;
    }
    this.query(query).done((function(_this) {
      return function(result) {
        _this.debugResult(result, max_width);
      };
    })(this)).fail((function(_this) {
      return function(err) {
        return console.error(err.debug);
      };
    })(this));
    return "...querying...";
  };

  Easydb4Migration.prototype.getFileRootUrl = function() {
    return this.__config.fylr_url + '/objectstore/file/' + this.__config.fylr_inst_uid + '/';
  };

  Easydb4Migration.prototype.query = function(query) {
    var b64DecodeUnicode, connect, dfr;
    dfr = new CUI.Deferred();
    b64DecodeUnicode = (function(_this) {
      return function(str) {
        return decodeURIComponent(atob(str).split('').map(function(c) {
          return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
        }).join(''));
      };
    })(this);
    connect = new CUI.XHR({
      url: this.getFileRootUrl() + 'migrate.sqlite',
      url_data: {
        query: query
      }
    });
    connect.start().fail((function(_this) {
      return function(err, status, debug) {
        console.error("quey", query, "error", err, "status", status, "debug", debug, "xhr", connect);
        return dfr.reject(err);
      };
    })(this)).done((function(_this) {
      return function(result) {
        var _row, _rows, cell, idx, j, len1, len2, m, ref1, row;
        if (!CUI.isArray(result != null ? result.rows : void 0) || !CUI.isArray(result != null ? result.columns : void 0)) {
          console.error("quey", query, "result", result, "xhr", connect);
          dfr.reject({
            debug: "No or unparsable data received."
          });
          return;
        }
        _rows = [];
        ref1 = result.rows;
        for (j = 0, len1 = ref1.length; j < len1; j++) {
          row = ref1[j];
          _row = {};
          _row.__len = row.length;
          _rows.push(_row);
          for (idx = m = 0, len2 = row.length; m < len2; idx = ++m) {
            cell = row[idx];
            if (CUI.isString(cell) && !cell.startsWith("/9j/4AAQSkZJRg")) {
              _row[idx] = b64DecodeUnicode(cell);
            } else {
              _row[idx] = cell;
            }
            _row[result.columns[idx]] = _row[idx];
          }
        }
        result.rows = _rows;
        return dfr.resolve(result);
      };
    })(this));
    return dfr.promise();
  };

  Easydb4Migration.prototype.initSettings = function() {
    var base;
    this.__settings = {
      eas_version: null,
      limit_main_tables: 100,
      limit_collections: true,
      skip_collection_with_more_objects_than: null,
      export_basetypes: ["pool", "user", "group", "collection", "presentation", "tags"],
      workfolder_name: "name",
      workfolder_parent: "fk_father_id",
      where_default_table: "",
      manifest_url: this.getFileRootUrl() + 'manifest.json',
      easydb4_reference_prefix: "",
      easydb4_schema: "",
      post_process_plugin: void 0,
      export_tool: void 0
    };
    this.__settings.target_lang = typeof (base = ez5.session.getConfigDatabaseLanguages())[0] === "function" ? base[0]("de-DE") : void 0;
    return this.__settings;
  };

  Easydb4Migration.prototype.showModal = function() {
    var debug_sqlite_btn, download_csv_btn, download_mapping_btn, export_json_btn, fileReader, fileUpload, fileUploadAny, file_upload_any_btn, file_upload_btn, mod, openJsonImporterModal, reload_basic_btn, reset_mapping_btn, update_modal, upload_mapping_btn;
    fileReader = new CUI.FileReader({
      onDone: (function(_this) {
        return function(file) {
          var map, ref1;
          try {
            map = JSON.parse(file.getResult()) || {};
            if ((map != null ? map.version : void 0) !== 1) {
              map = {
                mapping: map,
                version: 0
              };
            }
          } catch (error) {}
          if ((ref1 = map.mapping) != null ? ref1.source_table : void 0) {
            if (map.mapping.eadb_frontend !== _this.__info.attrs.eadb_frontend) {
              return CUI.problem({
                markdown: true,
                text: "Mapping file for **" + _this.__mapping.eadb_frontend + "** not accepted."
              });
            } else {
              _this.__mapping = map.mapping;
              if (map.version >= 1) {
                _this.__settings = map.settings;
              }
              return CUI.alert({
                markdown: true,
                text: "Mapping file for **" + _this.__mapping.eadb_frontend + "** accepted."
              }).done(function() {
                upload_mapping_btn.activate();
                if (map.version >= 1) {
                  return update_modal();
                } else {
                  _this.initMapping();
                  return _this.reloadSourceForm();
                }
              });
            }
          } else {
            return CUI.problem({
              text: "Mapping file not recognized."
            });
          }
        };
      })(this)
    });
    fileUpload = new CUI.FileUpload({
      url: this.getFileRootUrl() + 'migrate.sqlite',
      onFail: (function(_this) {
        return function(file) {
          return EAS.presentUploadError(file);
        };
      })(this),
      onDone: (function(_this) {
        return function(file) {
          console.debug("file uploaded", arguments);
          return _this.query("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").fail(function() {
            return CUI.problem({
              text: "File not recognized as SQLITE v3."
            });
          }).done(function(result) {
            return CUI.alert({
              markdown: true,
              text: "Sqlite accepted: **" + ez5.format_filesize(file.getFile().size) + "** with " + result.rows.length + " tables."
            }).done(function() {
              _this.initSettings();
              _this.__mapping = null;
              _this.initMapping();
              return update_modal();
            });
          });
        };
      })(this),
      onAlways: (function(_this) {
        return function() {
          return file_upload_btn.stopSpinner();
        };
      })(this),
      onAdd: (function(_this) {
        return function(file, idx, count) {
          var connect;
          file_upload_btn.startSpinner();
          connect = new CUI.XHR({
            method: "DELETE",
            url: _this.getFileRootUrl()
          });
          return connect.start().done(function() {
            return console.debug("adding file", file, idx, count);
          }).fail(function() {
            file_upload_btn.stopSpinner();
            return CUI.problem({
              text: "Unable to delete filestore."
            });
          });
        };
      })(this)
    });
    fileUploadAny = new CUI.FileUpload({
      url: this.__config.fylr_url + '/objectstore/file/' + this.__config.fylr_inst_uid + '/',
      add_filename_to_url: true,
      onFail: (function(_this) {
        return function(file) {
          return EAS.presentUploadError(file);
        };
      })(this),
      onDone: (function(_this) {
        return function(file) {
          var f;
          f = file.getFile();
          console.debug("file uploaded", file, f);
          return CUI.alert({
            markdown: true,
            text: "File: **" + f.name + "** [" + ez5.format_filesize(f.size) + "] uploaded."
          }).done(function() {
            return update_modal();
          });
        };
      })(this)
    });
    file_upload_btn = new CUI.FileUploadButton({
      text: "Upload Sqlite",
      icon: "upload",
      multiple: false,
      fileUpload: fileUpload
    });
    file_upload_any_btn = new CUI.FileUploadButton({
      text: "Upload File",
      icon: "upload",
      multiple: false,
      fileUpload: fileUploadAny
    });
    reload_basic_btn = new CUI.Button({
      text: "Analyze",
      icon: "refresh",
      disabled: true,
      onClick: (function(_this) {
        return function() {
          return update_modal();
        };
      })(this)
    });
    download_csv_btn = new CUI.Button({
      text: "Download Datamodel",
      disabled: true,
      onClick: (function(_this) {
        return function() {
          return _this.downloadDatamodel();
        };
      })(this),
      icon: "download"
    });
    reset_mapping_btn = new CUI.Button({
      text: "Reset Mapping",
      icon: "reset",
      disabled: true,
      onClick: (function(_this) {
        return function() {
          CUI.toaster({
            text: "Resetting mapping & settings..."
          });
          _this.__mapping = null;
          _this.initMapping();
          _this.initSettings();
          return update_modal();
        };
      })(this)
    });
    download_mapping_btn = new CUI.Button({
      text: "Download Mapping",
      icon: "download",
      disabled: true,
      onClick: (function(_this) {
        return function(ev) {
          return _this.downloadMapping(ev);
        };
      })(this)
    });
    upload_mapping_btn = new CUI.FileUploadButton({
      fileUpload: fileReader,
      multiple: false,
      text: "Upload Mapping",
      icon: "upload",
      disabled: true
    });
    export_json_btn = new CUI.Button({
      text: "Export JSON",
      icon: "download",
      disabled: true,
      onClick: (function(_this) {
        return function() {
          var connect, deletes, done_delete, file, j, len1, promise, ref1;
          export_json_btn.startSpinner();
          done_delete = 0;
          deletes = [];
          ref1 = _this.__info.fylr_files;
          for (j = 0, len1 = ref1.length; j < len1; j++) {
            file = ref1[j];
            if (file.name === "migrate.sqlite" || !file.name.endsWith(".json")) {
              continue;
            }
            connect = new CUI.XHR({
              method: "DELETE",
              url: _this.getFileRootUrl() + file.name
            });
            promise = connect.start();
            deletes.push(promise);
            promise.done(function() {
              done_delete++;
              return ez5.splash.show("easydb4migration.progress", {
                payload: "Deleting " + done_delete + "/" + deletes.length + " files on FYLR."
              });
            });
          }
          if (deletes.length > 0) {
            ez5.splash.show("easydb4migration.progress", {
              payload: "Deleting " + done_delete + "/" + deletes.length + " files on FYLR."
            });
          }
          return CUI.when(deletes).fail(function() {
            export_json_btn.stopSpinner();
            CUI.problem({
              text: "Error deleting files on FLYR."
            });
            ez5.splash.hide();
            return export_json_btn.stopSpinner();
          }).done(function() {
            return _this.exportJSON().always(function() {
              export_json_btn.stopSpinner();
              return update_modal();
            });
          });
        };
      })(this)
    });
    openJsonImporterModal = new CUI.Button({
      text: "Open JSON Importer",
      disabled: true,
      onClick: (function(_this) {
        return function() {
          return (new JSONImporter({
            manifestUrl: _this.__settings.manifest_url
          })).show();
        };
      })(this)
    });
    debug_sqlite_btn = new CUI.Button({
      text: "Sqlite Browser",
      icon: "search",
      disabled: true,
      onClick: (function(_this) {
        return function() {
          return _this.sqliteBrowser();
        };
      })(this)
    });
    update_modal = (function(_this) {
      return function() {
        var show_content;
        show_content = function() {
          var a, basetype_options, content, eas_options, eas_version, export_tool_opts, fields, file, form, fylr_url, info, j, k, lang, len1, len2, len3, len4, len5, len6, li, limit_options, m, n, o, p, plugin, post_process_opts, pre, r, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, source_table_options, strong, table, tool, txt, ul, v;
          if (_this.__info.sqlite_tables.length === 0) {
            content = new CUI.Label({
              text: "Upload sqlite file from easydb4.",
              multiline: true,
              center: true
            });
            download_csv_btn.disable();
            download_mapping_btn.disable();
            reload_basic_btn.disable();
            reset_mapping_btn.disable();
            upload_mapping_btn.disable();
            debug_sqlite_btn.disable();
            export_json_btn.disable();
            openJsonImporterModal.disable();
            mod.setContent(content);
            return;
          }
          fylr_url = _this.getFileRootUrl();
          content = [];
          ul = CUI.dom.element("UL");
          content.push("Files on FYLR:");
          content.push(ul);
          _this.__info.fylr_files.sort(function(a, b) {
            return a.name.localeCompare(b.name);
          });
          ref1 = _this.__info.fylr_files;
          for (j = 0, len1 = ref1.length; j < len1; j++) {
            file = ref1[j];
            a = CUI.dom.element("A");
            a.target = "_blank";
            a.href = fylr_url + file.name;
            a.textContent = file.name + " [" + ez5.format_filesize(file.size) + "]";
            li = CUI.dom.element("LI");
            if (!file.name.endsWith(".json") || file.name === "manifest.json" || file.name.startsWith(_this.__info.attrs.EASYDB_DEFAULT_TABLE + "-")) {
              strong = CUI.dom.element("STRONG");
              strong.appendChild(a);
              li.appendChild(strong);
            } else {
              li.appendChild(a);
            }
            ul.appendChild(li);
          }
          pre = CUI.dom.element("PRE");
          info = [];
          info.push("Attrs:");
          ref2 = _this.__info.attrs;
          for (k in ref2) {
            v = ref2[k];
            info.push(k + ": " + v);
          }
          info.push("");
          info.push("Object tables:");
          ref3 = _this.__info.tables;
          for (m = 0, len2 = ref3.length; m < len2; m++) {
            table = ref3[m];
            if (table.internal) {
              continue;
            }
            info.push(table.target_name + " (" + table.count + ")");
          }
          info.push("");
          info.push("");
          info.push("Problems:");
          if (_this.__info.problems.length) {
            info.push(_this.__info.problems.join("\n"));
          } else {
            info.push("None found.");
          }
          info.push("");
          pre.textContent = info.join("\n");
          content.push(pre);
          download_csv_btn.enable();
          download_mapping_btn.enable();
          reload_basic_btn.enable();
          reset_mapping_btn.enable();
          upload_mapping_btn.enable();
          debug_sqlite_btn.enable();
          export_json_btn.enable();
          openJsonImporterModal.enable();
          eas_options = [
            {
              text: "- no eas -",
              value: null
            }
          ];
          ref4 = _this.__info.eas_versions;
          for (n = 0, len3 = ref4.length; n < len3; n++) {
            eas_version = ref4[n];
            eas_options.push({
              text: eas_version,
              value: eas_version
            });
          }
          post_process_opts = [
            {
              text: "- none -",
              value: null
            }
          ];
          _this.__plugin_by_name = {};
          ref5 = _this.__plugins;
          for (o = 0, len4 = ref5.length; o < len4; o++) {
            plugin = ref5[o];
            post_process_opts.push({
              text: plugin.name(),
              value: plugin.name()
            });
            if (_this.__info.attrs.eadb_frontend === plugin.name() && _this.__settings.post_process_plugin === void 0) {
              _this.__settings.post_process_plugin = plugin.name();
            }
            _this.__plugin_by_name[plugin.name()] = plugin;
          }
          post_process_opts.sort(function(a, b) {
            return a.text.localeCompare(b.text);
          });
          export_tool_opts = [
            {
              text: "- none -",
              value: null
            }
          ];
          ref6 = _this.__tools;
          for (p = 0, len5 = ref6.length; p < len5; p++) {
            tool = ref6[p];
            export_tool_opts.push({
              text: tool.name(),
              value: tool.name()
            });
          }
          limit_options = [
            {
              text: "no limit: " + ((ref7 = _this.__info.table_by_name[_this.__info.attrs.EASYDB_DEFAULT_TABLE]) != null ? ref7.count : void 0),
              value: null
            }, {
              text: "10",
              value: 10
            }, {
              text: "100",
              value: 100
            }, {
              text: "1000",
              value: 1000
            }
          ];
          source_table_options = [];
          ref8 = _this.__info.tables;
          for (r = 0, len6 = ref8.length; r < len6; r++) {
            table = ref8[r];
            if (table.is_source) {
              txt = table.source_name;
              if (table.editlink) {
                txt = txt + " [editlink]";
              }
              txt += " -> " + table.target_name_full;
              source_table_options.push({
                text: txt,
                value: table.source_name
              });
            }
          }
          source_table_options.sort(function(a, b) {
            return a.text.localeCompare(b.text);
          });
          basetype_options = [
            {
              text: "Users",
              value: "user"
            }, {
              text: "Groups",
              value: "group"
            }, {
              text: "Pools",
              value: "pool"
            }, {
              text: "Collection",
              value: "collection"
            }, {
              text: "Presentation",
              value: "presentation"
            }, {
              text: "Tags",
              value: "tags"
            }
          ];
          fields = [
            {
              form: {
                label: "FYLR."
              },
              type: CUI.Output,
              name: "fylr_url",
              data: _this.__config
            }, {
              form: {
                label: "Backup origin"
              },
              type: CUI.Output,
              data: _this.__info.attrs,
              name: "SERVER_NAME"
            }, {
              form: {
                label: "Backup filename"
              },
              type: CUI.Output,
              data: _this.__info.attrs,
              name: "filename"
            }, {
              form: {
                label: "Backup timestamp"
              },
              type: CUI.Output,
              data: _this.__info.attrs,
              name: "timestamp"
            }, {
              form: {
                label: "easydb 4"
              },
              type: CUI.Output,
              data: _this.__info.attrs,
              name: "eadb_frontend"
            }, {
              form: {
                label: "Include EAS"
              },
              type: CUI.Select,
              options: eas_options,
              name: "eas_version"
            }, {
              form: {
                label: "Include Basetypes"
              },
              type: CUI.Options,
              name: "export_basetypes",
              min_checked: 0,
              horizontal: false,
              options: basetype_options
            }, {
              form: {
                label: "Limit Main Tables:"
              },
              type: CUI.Select,
              name: "limit_main_tables",
              options: limit_options
            }, {
              form: {
                label: "Limit collections to available objects:"
              },
              type: CUI.Checkbox,
              name: "limit_collections"
            }, {
              form: {
                label: "Skip collection with objects > n:"
              },
              type: CUI.NumberInput,
              name: "skip_collection_with_more_objects_than"
            }, {
              form: {
                label: "WHERE clause for: " + _this.__info.attrs.EASYDB_DEFAULT_TABLE
              },
              type: CUI.Input,
              textarea: true,
              name: "where_default_table"
            }, {
              form: {
                label: "Prefix for easydb4_reference"
              },
              type: CUI.Input,
              name: "easydb4_reference_prefix"
            }, {
              form: {
                label: "Schema of easydb4_tables"
              },
              type: CUI.Input,
              placeholder: "public",
              name: "easydb4_schema"
            }, {
              form: {
                label: "Post Process"
              },
              type: CUI.Select,
              name: "post_process_plugin",
              options: post_process_opts
            }, {
              form: {
                label: "Use Export Tool"
              },
              type: CUI.Select,
              name: "export_tool",
              options: export_tool_opts
            }, {
              form: {
                label: "Export Language Basetypes & Loca Default"
              },
              type: CUI.Select,
              options: (function() {
                var len7, ref9, results, u;
                ref9 = ez5.session.getConfigDatabaseLanguages();
                results = [];
                for (u = 0, len7 = ref9.length; u < len7; u++) {
                  lang = ref9[u];
                  results.push({
                    value: lang
                  });
                }
                return results;
              })(),
              name: "target_lang"
            }
          ];
          form = new CUI.Form({
            data: _this.__settings,
            fields: fields
          });
          _this.__sourceTableForm = new CUI.Form({
            data: _this.__settings,
            padded: true,
            fields: [
              {
                form: {
                  label: "Source Table"
                },
                type: CUI.Select,
                maximize_horizontal: true,
                name: "source_table_name",
                onDataChanged: function() {
                  return _this.reloadSourceForm();
                },
                options: source_table_options
              }
            ]
          });
          _this.initMapping();
          _this.__sourceTableForm.start();
          _this.__formLayout = new CUI.HorizontalLayout({
            left: {
              content: new CUI.VerticalLayout({
                maximize: true,
                center: {
                  content: form.start()
                }
              })
            },
            right: {
              content: new CUI.VerticalLayout({
                maximize: true,
                center: {
                  content: content
                }
              }),
              flexHandle: {
                state_name: "easydb4migration-hl-right",
                label: {
                  text: "Info"
                },
                closed: true,
                closable: true,
                hidden: false
              }
            },
            center: {
              content: [_this.__sourceTableForm, _this.renderSourceForm()]
            }
          });
          if (mod.isDestroyed()) {
            return;
          }
          mod.setContent(_this.__formLayout);
        };
        return _this.getBasicInfo().fail(function(err) {
          console.error("basic info failed:", err);
          return CUI.problem({
            text: "Failed to analyze: " + ((err != null ? err.debug : void 0) || JSON.stringify(err, "   "))
          });
        }).always(function() {
          return show_content();
        });
      };
    })(this);
    mod = new CUI.Modal({
      cancel: true,
      fill_space: "both",
      "class": "ez5-easydb-migration-suite",
      onCancel: (function(_this) {
        return function() {
          _this.releaseLock();
        };
      })(this),
      pane: {
        title: "Easydb 4 Migration Suite",
        padded: true,
        footer_left: [file_upload_btn, file_upload_any_btn, reload_basic_btn, download_csv_btn, download_mapping_btn, reset_mapping_btn, upload_mapping_btn, debug_sqlite_btn],
        footer_right: [export_json_btn, openJsonImporterModal]
      }
    });
    mod.show();
    update_modal();
  };

  Easydb4Migration.prototype.reloadSourceForm = function() {
    var form;
    form = this.renderSourceForm();
    this.__formLayout.replace([this.__sourceTableForm, form], "center");
  };

  Easydb4Migration.prototype.getTableByName = function(name) {
    var enrich, tb;
    if (!name) {
      return null;
    }
    enrich = function(table) {
      var col, j, len1, ref1;
      if (table._column_by_name) {
        return table;
      }
      table._column_by_name = {};
      ref1 = table.columns;
      for (j = 0, len1 = ref1.length; j < len1; j++) {
        col = ref1[j];
        if (!col.kind) {
          col.kind = "column";
        }
        table._column_by_name[col.name] = col;
      }
      return table;
    };
    tb = (function() {
      switch (name) {
        case "basetype:user":
          return {
            name: "basetype:user",
            columns: [
              {
                name: "login"
              }, {
                name: "_new_primary_email"
              }, {
                name: "displayname"
              }, {
                name: "reference"
              }, {
                name: "first_name"
              }, {
                name: "last_name"
              }, {
                name: "phone"
              }, {
                name: "postal_code"
              }, {
                name: "house_number"
              }, {
                name: "address_supplement"
              }, {
                name: "street"
              }, {
                name: "town"
              }, {
                name: "country"
              }, {
                name: "remarks"
              }, {
                name: "_password"
              }
            ]
          };
        default:
          return ez5.schema.CURRENT._table_by_name[name];
      }
    })();
    if (!tb) {
      return;
    }
    return enrich(tb);
  };

  Easydb4Migration.prototype.initMapping = function() {
    var col, j, len1, len2, m, ref1, ref2, source_table, target_col, target_col_name, target_table, tb_mapping;
    if (!this.__mapping) {
      this.__mapping = {
        source_table: {}
      };
    }
    this.__mapping.eadb_frontend = this.__info.attrs.eadb_frontend;
    ref1 = this.__info.tables;
    for (j = 0, len1 = ref1.length; j < len1; j++) {
      source_table = ref1[j];
      if (!source_table.is_source) {
        continue;
      }
      tb_mapping = this.__mapping.source_table[source_table.source_name];
      if (!tb_mapping) {
        tb_mapping = this.__mapping.source_table[source_table.source_name] = {
          target_table_name: null
        };
        target_table = this.getTableByName(source_table.target_name_full);
        tb_mapping.target_table_name = target_table != null ? target_table.name : void 0;
      }
      target_table = this.getTableByName(tb_mapping.target_table_name);
      if (!target_table) {
        tb_mapping.target_table_name = void 0;
      }
      if (target_table && !tb_mapping.source_column) {
        tb_mapping.source_column = {};
        ref2 = source_table.columns;
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          col = ref2[m];
          if (!col.source_name) {
            continue;
          }
          if (col.target_name) {
            target_col = target_table._column_by_name[col.target_name];
            if (target_col) {
              target_col_name = target_col.name;
              if (target_col.type === "text_l10n" || target_col.type === "text_l10n_oneline") {
                target_col_name = target_col_name + "#" + this.__settings.target_lang;
              }
            } else {
              target_col_name = null;
            }
          } else {
            target_col_name = null;
          }
          tb_mapping.source_column[col.source_name] = {
            target_column_name: target_col_name
          };
        }
      }
    }
    console.debug("Mapping:", this.__mapping);
    console.debug("Info:", this.__info);
    console.debug("Settings:", this.__settings);
  };

  Easydb4Migration.prototype.getSettings = function() {
    return this.__settings;
  };

  Easydb4Migration.prototype.renderSourceForm = function() {
    var col, data, form, have_uplink, info, j, lang, len1, len2, len3, len4, len5, len6, m, n, o, opts, ot, p, r, ref1, ref2, ref3, ref4, ref5, rows, source_table, tables, target_column, target_column_opts, target_table, target_table_opts, target_type, tb, tb_mapping, tcols, txt;
    source_table = this.__info.table_by_name[this.__settings.source_table_name];
    if (!source_table) {
      return null;
    }
    tb_mapping = this.__mapping.source_table[source_table.source_name];
    target_table = this.getTableByName(tb_mapping.target_table_name);
    target_table_opts = [
      {
        text: "- not mapped -",
        value: null
      }, {
        text: "basetype:user",
        value: "basetype:user"
      }
    ];
    tables = ez5.schema.CURRENT.tables.slice(0);
    tables.sort(function(a, b) {
      return a.name.localeCompare(b.name);
    });
    for (j = 0, len1 = tables.length; j < len1; j++) {
      ot = tables[j];
      if (ot.owned_by) {
        info = " [editlink]";
      } else {
        info = "";
      }
      target_table_opts.push({
        text: ot.name + info,
        value: ot.name
      });
    }
    target_column_opts = [
      {
        text: "",
        value: null
      }
    ];
    if (target_table) {
      have_uplink = false;
      ref1 = source_table.columns;
      for (m = 0, len2 = ref1.length; m < len2; m++) {
        col = ref1[m];
        if (col.uplink) {
          have_uplink = true;
          break;
        }
      }
      if (target_table.owned_by && !have_uplink) {
        target_column_opts.push({
          text: "- uplink -",
          value: "__UPLINK__"
        });
      }
      tcols = [];
      ref2 = target_table.columns.slice(0);
      for (n = 0, len3 = ref2.length; n < len3; n++) {
        col = ref2[n];
        if (col.kind !== "column") {
          continue;
        }
        tcols.push(col);
      }
      tcols.sort(function(a, b) {
        return a.name.localeCompare(b.name);
      });
      for (o = 0, len4 = tcols.length; o < len4; o++) {
        col = tcols[o];
        if (col.type) {
          txt = col.name + " [" + col.type + "]";
        } else {
          txt = col.name;
        }
        if (col.type === "text_l10n" || col.type === "text_l10n_oneline") {
          ref3 = ez5.session.getConfigDatabaseLanguages();
          for (p = 0, len5 = ref3.length; p < len5; p++) {
            lang = ref3[p];
            target_column_opts.push({
              text: col.name + " [" + col.type + "#" + lang + "]",
              value: col.name + "#" + lang
            });
          }
        } else {
          target_column_opts.push({
            text: txt,
            value: col.name
          });
        }
        if (col.type === "daterange") {
          target_column_opts.push({
            text: col.name + " [daterange#from]",
            value: col.name + "#from"
          });
          target_column_opts.push({
            text: col.name + " [daterange#to]",
            value: col.name + "#to"
          });
        }
      }
    }
    rows = [];
    ref4 = source_table.columns;
    for (r = 0, len6 = ref4.length; r < len6; r++) {
      col = ref4[r];
      if (!col.source_name) {
        continue;
      }
      target_type = col.target_type;
      if (col.uplink) {
        target_column = new CUI.Label({
          text: "Uplink"
        });
        target_type = "";
      } else if (col.parent_id) {
        target_column = new CUI.Label({
          text: "Parent"
        });
        target_type = "";
      } else if (col.pool_id) {
        target_column = new CUI.Label({
          text: "Pool"
        });
        target_type = "";
      } else if (col.tag) {
        target_column = new CUI.Label({
          text: "Tag"
        });
        target_type = "";
      } else if (target_table) {
        target_column = new CUI.Select({
          options: target_column_opts,
          name: "target_column_name",
          data: {
            target_column_name: ((ref5 = tb_mapping.source_column[col.source_name]) != null ? ref5.target_column_name : void 0) || null,
            source_name: col.source_name
          },
          onDataChanged: (function(_this) {
            return function(data) {
              if (!tb_mapping.source_column[data.source_name]) {
                tb_mapping.source_column[data.source_name] = {};
              }
              tb_mapping.source_column[data.source_name].target_column_name = data.target_column_name;
              if (!data.target_column_name) {
                return tb_mapping.source_column[data.source_name].not_mapped = true;
              } else {
                return delete tb_mapping.source_column[data.source_name].not_mapped;
              }
            };
          })(this)
        });
        target_column.start();
      }
      opts = col.source_options.slice(0);
      if (col.source_linkprio) {
        opts.push("linkprio: " + col.source_linkprio);
      }
      rows.push({
        source: col.source_name,
        source_type: col.source_type,
        source_options: opts.join(", "),
        target: col.target_name,
        target_column: target_column,
        target_type: target_type
      });
    }
    data = {
      target_table_name: (target_table != null ? target_table.name : void 0) || null
    };
    form = new CUI.Form({
      data: data,
      padded: true,
      fields: [
        {
          form: {
            label: "Target Table"
          },
          type: CUI.Select,
          name: "target_table_name",
          maximize_horizontal: true,
          options: target_table_opts,
          onDataChanged: (function(_this) {
            return function() {
              console.debug("update with data:", CUI.util.dump(data), source_table.source_name);
              _this.__mapping.source_table[source_table.source_name].target_table_name = data.target_table_name;
              delete _this.__mapping.source_table[source_table.source_name].source_column;
              _this.initMapping();
              return _this.reloadSourceForm();
            };
          })(this)
        }
      ]
    });
    tb = new CUI.Table({
      maximize: true,
      columns: [
        {
          name: "source"
        }, {
          name: "source_type"
        }, {
          name: "source_options"
        }, {
          name: "target"
        }, {
          name: "target_type"
        }, {
          name: "target_column"
        }
      ],
      rows: rows
    });
    return [form.start(), tb];
  };

  Easydb4Migration.prototype.sqliteBrowser = function() {
    var go_btn, history_pos, hl, inp_select, j, len1, output_table_div, ref1, run_input, run_query, sel_data, show_result, table, tb_opts, tb_select, unpack, vl;
    sel_data = {
      table: null
    };
    history_pos = 0;
    unpack = function(str) {
      var bytes, char, i, j, ref1;
      bytes = [];
      for (i = j = 0, ref1 = str.length; 0 <= ref1 ? j < ref1 : j > ref1; i = 0 <= ref1 ? ++j : --j) {
        char = str.charCodeAt(i);
        bytes.push(char >>> 8, char & 0xFF);
      }
      return bytes;
    };
    show_result = (function(_this) {
      return function(result) {
        var _row, cell, col, data, dt, fields, idx, img, j, len1, len2, m, n, ref1, ref2, ref3, row;
        fields = [];
        ref1 = result.columns;
        for (idx = j = 0, len1 = ref1.length; j < len1; idx = ++j) {
          col = ref1[idx];
          fields.push({
            type: CUI.Output,
            form: {
              label: col
            },
            name: idx + ""
          });
        }
        data = {
          rows: []
        };
        ref2 = result.rows;
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          _row = ref2[m];
          row = {};
          for (idx = n = 0, ref3 = _row.__len; n < ref3; idx = n += 1) {
            cell = _row[idx];
            if (cell === null) {
              row[idx + ""] = new CUI.EmptyLabel({
                text: "null"
              });
              continue;
            }
            if (!CUI.isString(cell)) {
              row[idx + ""] = cell;
              continue;
            }
            if (cell.startsWith("/9j/4AAQSkZJRg")) {
              img = document.createElement('img');
              img.width = 100;
              img.src = "data:image/jpeg;base64," + cell;
              row[idx + ""] = img;
            } else if ((cell != null ? cell.length : void 0) > 50 && idx > 0) {
              row[idx + ""] = cell.substr(0, 50);
            } else {
              try {
                row[idx + ""] = JSON.stringify(JSON.parse(cell), null, "   ");
              } catch (error) {
                row[idx + ""] = cell;
              }
            }
          }
          data.rows.push(row);
        }
        console.debug("Sqlite Browser:", data);
        CUI.dom.empty(output_table_div);
        dt = new CUI.DataTable({
          maximize: true,
          fields: fields,
          data: data,
          new_rows: "none",
          name: "rows",
          chunk_size: 25,
          footer_right: new CUI.Label({
            text: data.rows.length + " records."
          })
        });
        dt.start();
        return vl.replace(dt, "center");
      };
    })(this);
    tb_opts = [
      {
        text: "- Select Table -",
        value: null
      }
    ];
    ref1 = this.__info.sqlite_tables;
    for (j = 0, len1 = ref1.length; j < len1; j++) {
      table = ref1[j];
      tb_opts.push({
        text: table,
        value: table
      });
    }
    tb_select = new CUI.Select({
      options: tb_opts,
      data: sel_data,
      name: "table",
      onDataChanged: (function(_this) {
        return function() {
          inp_select.storeValue("SELECT * FROM \"" + sel_data.table + "\" LIMIT 100");
          inp_select.displayValue();
          return run_input();
        };
      })(this)
    }).start();
    inp_select = new CUI.Input({
      maximize: true,
      data: sel_data,
      textarea: true,
      name: "query",
      onKeyup: (function(_this) {
        return function(inp, ev) {
          var sql;
          if (!ev.ctrlKey()) {
            history_pos = 0;
            return;
          }
          switch (ev.keyCode()) {
            case 13:
              run_input();
              return;
            case 38:
              if (history_pos < _this.history.length) {
                history_pos++;
              }
              break;
            case 40:
              if (history_pos > 0) {
                history_pos--;
              }
              break;
            default:
              return;
          }
          ev.preventDefault();
          if (history_pos === 0) {
            inp_select.setValue("");
          }
          console.debug("history:", _this.history);
          sql = _this.history[_this.history.length - history_pos];
          console.debug(ev.keyCode(), history_pos, sql);
          if (!sql) {
            return;
          }
          return inp_select.setValue(sql);
        };
      })(this)
    }).start();
    go_btn = new CUI.Button({
      text: "Go",
      icon: "fa-caret-right",
      onClick: (function(_this) {
        return function() {
          return run_input();
        };
      })(this)
    });
    run_input = (function(_this) {
      return function() {
        var sql;
        sql = sel_data.query.trim();
        if (sql.length === 0) {
          return;
        }
        _this.history.push(sql);
        inp_select.disable();
        return run_query(sql).always(function() {
          inp_select.enable();
          return inp_select.focus();
        });
      };
    })(this);
    run_query = (function(_this) {
      return function(query) {
        go_btn.startSpinner();
        return _this.query(query).always(function() {
          return go_btn.stopSpinner();
        }).done(function(result) {
          return show_result(result);
        }).fail(function(err) {
          var lb;
          lb = new CUI.Label({
            text: (err != null ? err.debug : void 0) || (err != null ? err.error : void 0) || "Unknown error",
            multiline: true,
            centered: true
          });
          return vl.replace(lb, "center");
        });
      };
    })(this);
    hl = new CUI.HorizontalLayout({
      left: {
        content: tb_select
      },
      center: {
        content: inp_select
      },
      right: {
        content: go_btn
      }
    });
    output_table_div = CUI.dom.element("DIV");
    vl = new CUI.VerticalLayout({
      maximize: true,
      top: {
        content: hl
      }
    });
    return new CUI.Modal({
      cancel: true,
      fill_space: "both",
      pane: {
        title: "Sqlite Browser",
        padded: true,
        content: vl
      }
    }).show();
  };

  Easydb4Migration.prototype.sanitizeTablename = function(tn) {
    var _tn;
    _tn = tn.toLowerCase();
    if (_tn.startsWith("_")) {
      return _tn.substr(1);
    }
    return _tn;
  };

  Easydb4Migration.prototype.sanitizeColumnname = function(cn) {
    if (indexOf.call(this.track_create_fields, cn) >= 0) {
      return cn.replace(/easydb_/, "easydb4_");
    }
    if (cn.match(/^[0-9]/)) {
      cn = "c" + cn;
    }
    return this.sanitizeTablename(cn);
  };

  Easydb4Migration.prototype.displayname = function(cn) {
    var j, len1, name, names, part, ref1;
    names = [];
    ref1 = cn.split("_");
    for (j = 0, len1 = ref1.length; j < len1; j++) {
      part = ref1[j];
      name = part.substr(0, 1).toUpperCase() + part.substr(1);
      name = name.replace(/Easydb/g, "easydb");
      names.push(name);
    }
    return names.join(" ");
  };

  Easydb4Migration.prototype.getBasicInfo = function() {
    var count_table, count_tables, dfr, get_attrs, get_eadb_links, get_eas_versions, get_editlinks, get_fylr_files, get_sqlite_tables, get_tables, info, order_tables;
    this.__info = info = {
      sqlite_tables: [],
      eas_versions: [],
      min_eas_version: void 0,
      tables: [],
      table_by_name: {},
      table_by_id: {},
      pool_tables: [],
      tag_tables: [],
      problems: [],
      base_tables: {},
      attrs: {},
      editlinks: {},
      user_by_ref: {},
      group_by_id: {}
    };
    dfr = new CUI.Deferred();
    ez5.splash.show("easydb4migration.analysing", {
      progress: "..."
    });
    dfr.always((function(_this) {
      return function() {
        return ez5.splash.hide();
      };
    })(this));
    get_sqlite_tables = (function(_this) {
      return function() {
        return _this.query("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").done(function(result) {
          var row;
          return info.sqlite_tables = (function() {
            var j, len1, ref1, results;
            ref1 = result.rows;
            results = [];
            for (j = 0, len1 = ref1.length; j < len1; j++) {
              row = ref1[j];
              results.push(row.name);
            }
            return results;
          })();
        });
      };
    })(this);
    get_editlinks = (function(_this) {
      return function() {
        return _this.query("SELECT a.id as mask_id, a.name, b.* FROM \"source.eadb_masks\" a\n   LEFT JOIN \"source.eadb_attrs\" b ON\n    (b.referer='MA_'||a.id AND b.keystr IN ('link_field_id', 'table_id'))\nWHERE a.type='editlinks'").done(function(result) {
          var _info, attr_by_mask, j, len1, ref1, referer, row;
          attr_by_mask = {};
          ref1 = result.rows;
          for (j = 0, len1 = ref1.length; j < len1; j++) {
            row = ref1[j];
            if (!attr_by_mask[row.referer]) {
              attr_by_mask[row.referer] = {
                name: row.name,
                mask_id: row.mask_id
              };
            }
            attr_by_mask[row.referer][row.keystr] = parseInt(row.value);
          }
          for (referer in attr_by_mask) {
            _info = attr_by_mask[referer];
            if (!info.editlinks[_info.table_id]) {
              info.editlinks[_info.table_id] = [];
            }
            info.editlinks[_info.table_id].push(_info);
          }
          return;
          return console.debug("editlinks: ", result, attr_by_mask);
        });
      };
    })(this);
    get_eas_versions = (function(_this) {
      return function() {
        return _this.query("SELECT DISTINCT file_version FROM \"file\"").done(function(result) {
          var eas_version, j, len1, min_eas_version, ref1, row, v;
          info.eas_versions = (function() {
            var j, len1, ref1, results;
            ref1 = result.rows;
            results = [];
            for (j = 0, len1 = ref1.length; j < len1; j++) {
              row = ref1[j];
              results.push(row.file_version);
            }
            return results;
          })();
          min_eas_version = void 0;
          ref1 = info.eas_versions;
          for (j = 0, len1 = ref1.length; j < len1; j++) {
            eas_version = ref1[j];
            v = parseInt(eas_version);
            if (isNaN(v)) {
              continue;
            }
            if (min_eas_version === void 0 || v < min_eas_version) {
              min_eas_version = v;
            }
          }
          if (min_eas_version !== void 0) {
            info.min_eas_version = "" + min_eas_version;
          }
        });
      };
    })(this);
    get_tables = (function(_this) {
      return function() {
        return _this.query("SELECT a.table_name, a.id as column_id, a.name, a.type, a.linkprio, a.options,\n	   b.id as table_id, b.screen_name, b.options as table_options\n	     FROM \"source.eadb_columns\" a\n	     LEFT JOIN \"source.eadb_tables\" b ON (b.name = a.table_name)\n		 ORDER BY table_name, a.name").done(function(result) {
          var _col, _idx, app, col, date_col_name, editlink, editlinks, el, find, i1, idx, j, j1, k, len, len1, len10, len11, len12, len2, len3, len4, len5, len6, len7, len8, len9, link_field_ids, linked_table, linkprio, m, main_idx, msg, n, o, owned_by, owned_by_col, p, parts, r, ref1, ref10, ref11, ref12, ref13, ref14, ref15, ref16, ref17, ref18, ref19, ref2, ref20, ref21, ref22, ref23, ref24, ref25, ref3, ref4, ref5, ref6, ref7, ref8, ref9, row, table, table_options, target_name, tb, tb_id, tn, type, u, x, y, z;
          tn = null;
          ref1 = result.rows;
          for (j = 0, len1 = ref1.length; j < len1; j++) {
            row = ref1[j];
            if (tn !== row.table_name) {
              tn = row.table_name;
              table_options = ((ref2 = row.table_options) != null ? ref2.split(",") : void 0) || [];
              switch (tn) {
                case _this.__info.attrs.USER_TABLE_NAME:
                  target_name = "basetype:user";
                  break;
                default:
                  target_name = _this.sanitizeTablename(tn);
              }
              tb = {
                editlink: false,
                real_source_name: tn,
                source_name: tn,
                source_id: row.table_id,
                hierarchical: indexOf.call(table_options, "treesupport") >= 0,
                pool: false,
                target_name: target_name,
                target_displayname: row.screen_name || row.table_name,
                screen_name: row.screen_name,
                columns: [],
                _nested_tables: [],
                _linked_tables: []
              };
              editlinks = _this.__info.editlinks[row.table_id];
              if (editlinks) {
                CUI.util.pushOntoArray("internal", table_options);
                parts = tn.split("__");
                tb.real_target_name = _this.sanitizeTablename(parts.pop());
                tb.target_name = tb.real_target_name;
                tb.editlink = true;
                tb.editlinks = editlinks;
              }
              if (_this.__info.attrs.USER_TABLE_NAME === tn) {
                tb.columns.push({
                  real_source_name: "displayname",
                  source_name: "displayname",
                  target_name: "displayname",
                  source_type: "text",
                  source_options: []
                });
              } else {
                if (CUI.util.idxInArray(_this.getEasydb4TableName("eadb_changelog"), _this.__info.sqlite_tables) > -1) {
                  tb.columns.push({
                    real_source_name: "__changelog__",
                    source_name: "__changelog__",
                    target_name: "easydb4_changelog",
                    source_type: "text",
                    source_options: []
                  });
                }
              }
              info.tables.push(tb);
            }
            linkprio = void 0;
            if (row.linkprio === 1) {
              if (row.name.match(/admin.*group/)) {
                msg = "Ignoring linkprio == 1 on " + tb.source_name + "." + row.name;
                info.problems.push(msg);
              } else {
                tb.pool = true;
                linkprio = 1;
              }
            }
            if (row.linkprio === 2) {
              tb.tags = true;
              linkprio = 2;
            }
            col = {
              real_source_name: row.name,
              source_name: row.name,
              source_id: row.column_id,
              target_name: _this.sanitizeColumnname(row.name),
              source_type: row.type,
              source_options: ((ref3 = row.options) != null ? ref3.split(",") : void 0) || [],
              source_linkprio: linkprio
            };
            if (tn === _this.__info.attrs.USER_TABLE_NAME) {
              switch (col.source_name) {
                case _this.__info.attrs.USER_LOGIN_COLUMN:
                  col.target_name = "login";
                  break;
                case "password":
                  col.target_name = "_password";
                  break;
                case "email":
                  col.target_name = "_new_primary_email";
              }
            }
            if (row.type === "key") {
              col.key = true;
              if (tn === _this.__info.attrs.USER_TABLE_NAME) {
                col.target_name = "reference";
              } else {
                col.target_name = "easydb4_reference";
              }
              tb.key = col;
            }
            if (row.name === "fk_father_id") {
              tb.parent = col;
              col.parent_id = true;
              col.source_type = "parent";
              col.target_type = "number";
            }
            tb.columns.push(col);
          }
          _idx = 0;
          while (_idx < info.tables.length) {
            table = info.tables[_idx];
            len = (ref4 = table.editlinks) != null ? ref4.length : void 0;
            if (!len) {
              _idx += 1;
              continue;
            }
            if (len === 1) {
              table.link_field_id = table.editlinks[0].link_field_id;
            } else {
              link_field_ids = (function() {
                var len2, m, ref5, results;
                ref5 = table.editlinks;
                results = [];
                for (m = 0, len2 = ref5.length; m < len2; m++) {
                  el = ref5[m];
                  results.push(el.link_field_id);
                }
                return results;
              })();
              ref5 = table.editlinks;
              for (idx = m = 0, len2 = ref5.length; m < len2; idx = ++m) {
                editlink = ref5[idx];
                app = "_" + editlink.mask_id;
                if (idx === 0) {
                  tb = table;
                } else {
                  tb = CUI.util.copyObject(table, true);
                  info.tables.splice(_idx, 0, tb);
                  _idx += 1;
                }
                ref6 = tb.columns;
                for (n = 0, len3 = ref6.length; n < len3; n++) {
                  col = ref6[n];
                  if ((ref7 = col.source_id, indexOf.call(link_field_ids, ref7) >= 0) && col.source_id !== editlink.link_field_id) {
                    col.target_name = null;
                  }
                }
                tb.source_name = tb.real_source_name + app;
                tb.target_name = tb.real_target_name + app;
                tb.link_field_id = editlink.link_field_id;
              }
            }
            _idx += 1;
          }
          ref8 = info.tables;
          for (o = 0, len4 = ref8.length; o < len4; o++) {
            table = ref8[o];
            info.table_by_name[table.source_name] = table;
            info.table_by_id[table.source_id] = table;
          }
          ref9 = info.tables;
          for (p = 0, len5 = ref9.length; p < len5; p++) {
            table = ref9[p];
            idx = 0;
            while (idx < table.columns.length) {
              col = table.columns[idx];
              if (col.source_name.endsWith("_date_bis")) {
                date_col_name = col.source_name.substr(0, col.source_name.length - 9);
                find = {};
                find[date_col_name] = true;
                ref10 = ["date_bis", "date_von", "jahr_bis", "jahr_von"];
                for (r = 0, len6 = ref10.length; r < len6; r++) {
                  k = ref10[r];
                  find[date_col_name + "_" + k] = true;
                }
                ref11 = table.columns;
                for (_idx = u = 0, len7 = ref11.length; u < len7; _idx = ++u) {
                  _col = ref11[_idx];
                  if (_col.source_name === date_col_name) {
                    main_idx = _idx;
                  }
                  if (find[_col.source_name]) {
                    _col[k] = true;
                    delete find[_col.source_name];
                  }
                }
                if (Object.keys(find).length > 0) {
                  info.problems.push(table.source_name + "." + col.source_name + ": Not enough date range columns found.");
                } else {
                  table.columns.splice(main_idx + 1, 0, {
                    target_type: "daterange",
                    real_source_name: date_col_name,
                    source_name: date_col_name + "_*",
                    target_name: date_col_name + "_range",
                    target_displayname: _this.displayname(date_col_name),
                    source_options: []
                  });
                  idx += 1;
                }
              }
              if (col.target_name) {
                col.target_displayname = _this.displayname(col.target_name);
              }
              linked_table = null;
              switch (col.source_type) {
                case "parent":
                  type = "number";
                  break;
                case "date":
                  type = "date";
                  break;
                case "boolean":
                  type = "boolean";
                  break;
                case "easfile":
                  type = "eas";
                  break;
                case "time":
                  type = "datetime";
                  break;
                case "blob":
                  type = "text";
                  break;
                case "key":
                  type = "number";
                  break;
                case "text":
                  type = "text_oneline";
                  break;
                case "integer":
                case "number":
                  type = "number";
                  break;
                case "currency":
                  type = "integer.2";
                  break;
                case "image":
                  type = "number";
                  break;
                default:
                  if (col.source_type.startsWith("link_")) {
                    tb_id = col.source_type.substr(5);
                    linked_table = info.table_by_id[tb_id];
                    if (!linked_table) {
                      info.problems.push(table.source_name + "." + col.source_name + ": Table for " + col.source_type + " not found.");
                    } else if (linked_table.source_name === info.attrs.USER_TABLE_NAME) {
                      info.problems.push(table.source_name + "." + col.source_name + ": Unable to link to User Table: " + linked_table.source_name + ".");
                      type = "number";
                    } else if (linked_table.source_name === info.attrs.GROUP_TABLE_NAME) {
                      info.problems.push(table.source_name + "." + col.source_name + ": Unable to link to Group Table: " + linked_table.source_name + ".");
                      type = "number";
                    } else if (!table.editlink && linked_table.editlink) {
                      info.problems.push(table.source_name + "." + col.source_name + ": Unable to link to Editlink Table: " + linked_table.source_name + ".");
                    } else {
                      col.source_link = linked_table;
                      type = "link: " + linked_table.target_name;
                      col.target_displayname = linked_table.target_displayname;
                    }
                  } else {
                    msg = table.source_name + "." + col.source_name + ": Unknown type: " + col.source_type;
                    info.problems.push(msg);
                    type = "unknown";
                    _this.logwarn(msg);
                  }
              }
              if (!col.target_type) {
                col.target_type = type;
              }
              if (col.source_linkprio === 1) {
                if (!linked_table) {
                  info.problems.push(table.source_name + "." + col.source_name + ": Table for linkprio == 1 not found.");
                } else {
                  if ((linked_table != null ? linked_table.source_id : void 0) < Math.pow(10, 7)) {
                    if (indexOf.call(info.pool_tables, linked_table) < 0) {
                      info.pool_tables.push(linked_table);
                      linked_table.pool_table = true;
                    }
                    col.pool_id = true;
                  }
                }
              }
              if (col.source_linkprio === 2) {
                if (!linked_table) {
                  info.problems.push(table.source_name + "." + col.source_name + ": Table for linkprio == 2 not found.");
                } else {
                  CUI.util.pushOntoArray(linked_table, info.tag_tables);
                  linked_table.tag_table = true;
                  col.tag = true;
                }
              }
              idx++;
            }
          }
          ref12 = info.tables;
          for (x = 0, len8 = ref12.length; x < len8; x++) {
            table = ref12[x];
            if (table.editlink) {
              table.internal = true;
            }
            if (table.pool_table) {
              table.internal = true;
            }
            if (table.target_name === "connector") {
              table.internal = true;
            }
            if (table.target_name === "customrender") {
              table.internal = true;
            }
            if (table.target_name === "automator") {
              table.internal = true;
            }
            owned_by = null;
            owned_by_col = null;
            ref13 = table.columns;
            for (y = 0, len9 = ref13.length; y < len9; y++) {
              col = ref13[y];
              if (((ref14 = col.source_link) != null ? ref14.pool_table : void 0) && !col.pool_id) {
                console.debug("col.source_link", table.real_source_name, (ref15 = col.source_link) != null ? ref15.pool_table : void 0, col.source_link);
                col.pool_id = true;
                table.pool = true;
              }
              if (info.attrs.WORKFOLDER2_DEFAULT_TABLE) {
                if (((ref16 = col.source_link) != null ? ref16.source_name : void 0) === info.attrs.WORKFOLDER2_DEFAULT_TABLE) {
                  table.editlink = true;
                  owned_by = col.source_link;
                  owned_by_col = col;
                  break;
                }
              }
              if (info.attrs.WORKFOLDER_SECOND_TABLE) {
                if (((ref17 = col.source_link) != null ? ref17.source_name : void 0) === info.attrs.WORKFOLDER_SECOND_TABLE) {
                  table.editlink = true;
                  owned_by = col.source_link;
                  owned_by_col = col;
                  break;
                }
              }
              if (info.attrs.POWERPOINT_TABLE_NAME) {
                if (((ref18 = col.source_link) != null ? ref18.source_name : void 0) === info.attrs.POWERPOINT_TABLE_NAME) {
                  table.editlink = true;
                  owned_by = col.source_link;
                  owned_by_col = col;
                  break;
                }
              }
            }
            if (!table.editlink) {
              continue;
            }
            if (!owned_by) {
              ref19 = table.columns;
              for (z = 0, len10 = ref19.length; z < len10; z++) {
                col = ref19[z];
                if (col.source_id === table.link_field_id) {
                  owned_by = col.source_link;
                  owned_by_col = col;
                  break;
                }
              }
            }
            if (owned_by) {
              owned_by_col.uplink = true;
              table.uplink = owned_by_col;
              table.owned_by = owned_by;
              owned_by._nested_tables.push(table);
            } else {
              msg = "Owned by not found for assumed editlink table: " + table.source_name;
              info.problems.push(msg);
              _this.logwarn(msg, table);
            }
          }
          ref20 = info.tables;
          for (i1 = 0, len11 = ref20.length; i1 < len11; i1++) {
            table = ref20[i1];
            table.columns.splice(0, 0, {
              target_type: "string",
              target_name: "easydb4_reference",
              target_displayname: "easydb4 Referenz",
              source_options: ["unique"]
            });
          }
          ref21 = info.tables;
          for (j1 = 0, len12 = ref21.length; j1 < len12; j1++) {
            table = ref21[j1];
            if (info.attrs.POWERPOINT_TABLE_NAME) {
              if (table.source_name === info.attrs.POWERPOINT_TABLE_NAME) {
                info.base_tables.presentation = table;
                table.internal = true;
                table.presentation = true;
              }
              if (((ref22 = table.owned_by) != null ? ref22.source_name : void 0) === info.attrs.POWERPOINT_TABLE_NAME) {
                info.base_tables.presentation_objects = table;
                info.attrs.presentation_objects = table.source_name;
                table.internal = true;
                table.presentation = true;
              }
            }
            if (table.source_name === info.attrs.USER_TABLE_NAME) {
              info.base_tables.user = table;
              table.internal = true;
            }
            if (table.source_name === info.attrs.GROUP_TABLE_NAME) {
              info.base_tables.group = table;
              table.internal = true;
            }
            if (info.attrs.WORKFOLDER2_DEFAULT_TABLE) {
              if (table.source_name === info.attrs.WORKFOLDER2_DEFAULT_TABLE) {
                info.base_tables.workfolder = table;
                table.internal = true;
                table.workfolder = true;
              }
              if (((ref23 = table.owned_by) != null ? ref23.source_name : void 0) === info.attrs.WORKFOLDER2_DEFAULT_TABLE) {
                info.base_tables.workfolder_objects = table;
                info.attrs.workfolder_objects = table.source_name;
                table.internal = true;
                table.workfolder = true;
              }
            }
            if (info.attrs.WORKFOLDER_SECOND_TABLE) {
              if (table.source_name === info.attrs.WORKFOLDER_SECOND_TABLE) {
                info.base_tables.workfolder2 = table;
                table.internal = true;
                table.workfolder = true;
              }
              if (((ref24 = table.owned_by) != null ? ref24.source_name : void 0) === info.attrs.WORKFOLDER_SECOND_TABLE) {
                info.base_tables.workfolder2_objects = table;
                info.attrs.workfolder2_objects = table.source_name;
                table.internal = true;
                table.workfolder = true;
              }
            }
            if (_this.__settings.workfolder2_table) {
              if (table.source_name === _this.__settings.workfolder2_table) {
                info.base_tables.workfolder2 = table;
                info.attrs.workfolder2 = table.source_name;
                table.internal = true;
                table.workfolder = true;
              }
              if (((ref25 = table.owned_by) != null ? ref25.source_name : void 0) === _this.__settings.workfolder2_table) {
                info.base_tables.workfolder2_objects = table;
                info.attrs.workfolder2_objects = table.source_name;
                table.internal = true;
                table.workfolder = true;
              }
            }
            if (info.attrs.EASYDB_DEFAULT_TABLE) {
              if (table.source_name === info.attrs.EASYDB_DEFAULT_TABLE) {
                info.base_tables.easydb_default = table;
              }
            }
          }
        });
      };
    })(this);
    get_attrs = (function(_this) {
      return function() {
        var j, keys, keystr, keystrs, len1, ref1, referer;
        keys = [];
        ref1 = {
          DEFAULT_VALUE: ["USER_TABLE_NAME", "USER_LOGIN_COLUMN", "GROUP_TABLE_NAME", "GROUP_TABLE_DISPLAY_COLUMN_NAME", "EASYDB_DEFAULT_TABLE"],
          ST: ["WORKFOLDER_SECOND_TABLE", "WORKFOLDER2_DEFAULT_TABLE", "POWERPOINT_TABLE_NAME"],
          SYSTEM: ["eadb_frontend"],
          BACKUP: ["timestamp", "filename"],
          SERVER: ["SERVER_NAME"]
        };
        for (referer in ref1) {
          keystrs = ref1[referer];
          for (j = 0, len1 = keystrs.length; j < len1; j++) {
            keystr = keystrs[j];
            keys.push("'" + referer + "__" + keystr + "'");
          }
        }
        return _this.query("SELECT keystr, value FROM \"source.eadb_attrs\" WHERE (referer || '__' || keystr) IN (" + keys + ")").done(function(result) {
          var key, len2, m, ref2, ref3, row, value;
          ref2 = result.rows;
          for (m = 0, len2 = ref2.length; m < len2; m++) {
            row = ref2[m];
            info.attrs[row.keystr] = row.value;
          }
          ref3 = info.attrs;
          for (key in ref3) {
            value = ref3[key];
            if (!value) {
              info.problems.push("Key: " + key + " not found, unable to migrate.");
            }
          }
        });
      };
    })(this);
    get_eadb_links = (function(_this) {
      return function() {
        return _this.query("SELECT DISTINCT from_table_id, to_table_id FROM " + _this.getEasydb4TableName("eadb_links")).done(function(result) {
          var from_table, j, len1, nested_table, ref1, results, row, target_type, to_table;
          ref1 = result.rows;
          results = [];
          for (j = 0, len1 = ref1.length; j < len1; j++) {
            row = ref1[j];
            from_table = info.table_by_id[row.from_table_id];
            to_table = info.table_by_id[row.to_table_id];
            if (!from_table || !to_table) {
              info.problems.push("eadb_links: FROM or TO table not found: " + row.from_table_id + ", " + row.to_table_id);
              continue;
            }
            if (from_table.real_source_name !== _this.__info.attrs.EASYDB_DEFAULT_TABLE) {
              _this.logwarn("eadb_links: FROM table not EASYDB_DEFAULT_TABLE: " + from_table.real_source_name + ". Skipping.");
              continue;
            }
            target_type = "link:" + to_table.target_name;
            nested_table = {
              _linked_tables: [],
              _nested_tables: [],
              internal: true,
              eadb_links: true,
              eadb_links_from_table_id: row.from_table_id,
              eadb_links_to_table_id: row.to_table_id,
              real_source_name: "eadb_links:" + to_table.target_name,
              source_name: "eadb_links:" + to_table.target_name,
              owned_by: from_table,
              target_table: to_table,
              target_name: to_table.target_name + "_eadb_links",
              columns: [
                {
                  source_name: "to_id",
                  source_options: ["not_null"],
                  target_name: "lk_" + to_table.target_name + "_id",
                  target_type: target_type
                }, {
                  source_name: "remark",
                  source_options: [],
                  target_name: "remark",
                  target_type: "text"
                }
              ]
            };
            info.tables.push(nested_table);
            info.table_by_name[nested_table.source_name] = nested_table;
            if (to_table.editlink) {
              info.problems.push("eadb_links: Merging eadb_links into existing editlink: " + from_table.real_source_name + " -> " + to_table.real_source_name + ". eadb_links.remark will be ignored.");
              nested_table.columns.pop();
              nested_table.merge_with_table = to_table;
              nested_table.columns[0].target_name = "__UPLINK__";
              nested_table.columns[0].uplink = true;
              nested_table.target_name = to_table.target_name;
            }
            results.push(from_table._nested_tables.push(nested_table));
          }
          return results;
        });
      };
    })(this);
    order_tables = (function(_this) {
      return function() {
        var _loop, by_name, col, find_next_tables, found, have_table_names, j, len1, len2, len3, len4, len5, len6, len7, len8, m, msg, n, need_count, not_found, o, p, path, r, ref1, ref2, ref3, ref4, ref5, root_table, table, table_name, tables, tb, u, warn, x;
        ref1 = info.tables;
        for (j = 0, len1 = ref1.length; j < len1; j++) {
          table = ref1[j];
          if ((table.uplink && !table.workfolder && !table.presentation && !table.tag_table) || !table.internal) {
            table.is_source = true;
          } else if (table.eadb_links) {
            table.is_source = true;
          } else if (info.base_tables.user === table) {
            table.is_source = true;
          } else {
            table.is_source = false;
          }
          root_table = table;
          if (root_table.owned_by) {
            path = [root_table];
            while (root_table.owned_by) {
              root_table = root_table.owned_by;
              path.push(root_table);
            }
            path.reverse();
            table.target_name_full = ((function() {
              var len2, m, results;
              results = [];
              for (m = 0, len2 = path.length; m < len2; m++) {
                tb = path[m];
                results.push(tb.target_name);
              }
              return results;
            })()).join("__");
          } else {
            table.target_name_full = table.target_name;
          }
          ref2 = table.columns;
          for (m = 0, len2 = ref2.length; m < len2; m++) {
            col = ref2[m];
            if (col.source_link && !col.uplink && !col.source_link.internal) {
              CUI.util.pushOntoArray(col.source_link, root_table._linked_tables);
            }
          }
        }
        have_table_names = [];
        need_count = 0;
        ref3 = info.tables;
        for (n = 0, len3 = ref3.length; n < len3; n++) {
          table = ref3[n];
          if (table.internal) {
            continue;
          }
          need_count += 1;
        }
        find_next_tables = function() {
          var len4, len5, len6, next_table, next_tables, o, p, r, ref4, ref5, ref6, ref7;
          next_tables = [];
          ref4 = info.tables;
          for (o = 0, len4 = ref4.length; o < len4; o++) {
            table = ref4[o];
            if (table.internal) {
              continue;
            }
            if (ref5 = table.source_name, indexOf.call(have_table_names, ref5) >= 0) {
              continue;
            }
            table.depending_on_table_names = [];
            ref6 = table._linked_tables;
            for (p = 0, len5 = ref6.length; p < len5; p++) {
              tb = ref6[p];
              if (ref7 = tb.source_name, indexOf.call(have_table_names, ref7) < 0) {
                table.depending_on_table_names.push(tb.source_name);
                break;
              }
            }
            if (table.depending_on_table_names.length === 0) {
              next_tables.push(table);
            }
          }
          for (r = 0, len6 = next_tables.length; r < len6; r++) {
            next_table = next_tables[r];
            have_table_names.push(next_table.source_name);
          }
          return next_tables.length;
        };
        not_found = [];
        _loop = 0;
        while (true) {
          _loop++;
          if (_loop === 50) {
            console.error("recursion");
            break;
          }
          found = find_next_tables();
          if (have_table_names.length === need_count) {
            break;
          }
          if (found === 0) {
            ref4 = info.tables;
            for (o = 0, len4 = ref4.length; o < len4; o++) {
              table = ref4[o];
              if (table.internal) {
                continue;
              }
              if (ref5 = table.source_name, indexOf.call(have_table_names, ref5) >= 0) {
                continue;
              }
              not_found.push(table);
            }
            warn = [];
            for (p = 0, len5 = not_found.length; p < len5; p++) {
              tb = not_found[p];
              warn.push("- " + tb.source_name + " needs: " + tb.depending_on_table_names.join(', '));
            }
            msg = "Unable to order tables for export:\n" + warn.join("\n");
            info.problems.push(msg);
            _this.logwarn(msg);
            break;
          }
        }
        tables = info.tables.splice(0);
        by_name = {};
        for (r = 0, len6 = tables.length; r < len6; r++) {
          table = tables[r];
          if (table.internal) {
            info.tables.push(table);
          } else {
            by_name[table.source_name] = table;
          }
        }
        for (u = 0, len7 = have_table_names.length; u < len7; u++) {
          table_name = have_table_names[u];
          info.tables.push(by_name[table_name]);
        }
        not_found.sort(function(a, b) {
          if (a.source_name === _this.__info.attrs.EASYDB_DEFAULT_TABLE) {
            return 1;
          }
          return 0;
        });
        _this.__info.deferred_tables = not_found;
        for (x = 0, len8 = not_found.length; x < len8; x++) {
          tb = not_found[x];
          info.tables.push(tb);
        }
      };
    })(this);
    get_fylr_files = (function(_this) {
      return function() {
        var connect;
        connect = new CUI.XHR({
          url: _this.getFileRootUrl()
        });
        return connect.start().done(function(result) {
          return info.fylr_files = result.files;
        }).fail(function() {
          return info.fylr_files = [];
        });
      };
    })(this);
    count_tables = (function(_this) {
      return function() {
        return CUI.chunkWork.call(_this, {
          timeout: 0,
          items: info.tables,
          chunk_size: 1,
          call: function(items) {
            return count_table(items[0]);
          }
        });
      };
    })(this);
    count_table = (function(_this) {
      return function(tb) {
        var sel;
        ez5.splash.show("easydb4migration.analysing", {
          progress: "counting " + tb.real_source_name
        });
        if (tb.real_source_name === _this.__info.attrs.EASYDB_DEFAULT_TABLE && _this.__settings.where_default_table.trim().length > 0) {
          tb.where = " WHERE " + _this.__settings.where_default_table.trim() + " ";
        } else {
          tb.where = "";
        }
        if (tb.eadb_links) {
          sel = 'SELECT COUNT(*) FROM ' + _this.getEasydb4TableName("eadb_links") + ' WHERE to_table_id=' + tb.eadb_links_to_table_id;
        } else {
          sel = 'SELECT COUNT(*) FROM ' + _this.getEasydb4TableName(tb.real_source_name) + tb.where;
        }
        return _this.query(sel).done(function(result) {
          return tb.count = result.rows[0][0];
        });
      };
    })(this);
    ez5.splash.show("easydb4migration.analysing", {
      progress: "fylr_files"
    });
    get_fylr_files().fail(dfr.reject).done((function(_this) {
      return function() {
        return get_eas_versions().fail(dfr.reject).done(function() {
          ez5.splash.show("easydb4migration.analysing", {
            progress: "sqlite_tables"
          });
          return get_sqlite_tables().fail(dfr.reject).done(function() {
            ez5.splash.show("easydb4migration.analysing", {
              progress: "editlinks"
            });
            return get_editlinks().fail(dfr.reject).done(function() {
              ez5.splash.show("easydb4migration.analysing", {
                progress: "attrs"
              });
              return get_attrs().fail(dfr.reject).done(function() {
                ez5.splash.show("easydb4migration.analysing", {
                  progress: "tables"
                });
                return get_tables().fail(dfr.reject).done(function() {
                  ez5.splash.show("easydb4migration.analysing", {
                    progress: "eadb_links"
                  });
                  return get_eadb_links().fail(dfr.reject).done(function() {
                    return count_tables().fail(dfr.reject).done(function() {
                      ez5.splash.show("easydb4migration.analysing", {
                        progress: "order"
                      });
                      order_tables();
                      return dfr.resolve(info);
                    });
                  });
                });
              });
            });
          });
        });
      };
    })(this));
    return dfr.promise();
  };

  Easydb4Migration.prototype.track_create_fields = ["easydb_insert_time", "easydb_insert_user", "easydb_owner", "easydb_update_time", "easydb_update_user"];

  Easydb4Migration.prototype.resetMapping = function() {};

  Easydb4Migration.prototype.downloadMapping = function(ev) {
    var map;
    if (ev.hasModifierKey()) {
      return console.debug(CUI.util.dump(this.__mapping));
    } else {
      map = {
        mapping: this.__mapping,
        settings: this.__settings,
        version: 1
      };
      return CUI.FileReader.save("mapping-settings-easydb4-" + this.__mapping.eadb_frontend + ".json", JSON.stringify(map, null, "    "));
    }
  };

  Easydb4Migration.prototype.downloadDatamodel = function() {
    var _csv, add_columns, csv, idx, j, len1, len2, m, problem, ref1, ref2, table;
    csv = [["# CSV DATAMODEL DUMP " + this.__info.attrs.eadb_frontend + " " + ez5.format_date_and_time(new Date())]];
    csv.push([]);
    csv.push([]);
    if (this.__info.problems.length === 0) {
      csv.push[["# no import problems detected"]];
    } else {
      csv.push([["# Problems detected:"]]);
      csv.push([["#"]]);
      ref1 = this.__info.problems;
      for (j = 0, len1 = ref1.length; j < len1; j++) {
        problem = ref1[j];
        console.warn("Import Problem:", problem);
        csv.push([["# " + problem]]);
      }
      csv.push([]);
      csv.push([]);
    }
    add_columns = (function(_this) {
      return function(table, path) {
        var col, len2, len3, m, n, nested_table, new_path, not_null, ref2, ref3, ref4, table_path, tb, unique;
        table_path = (function() {
          var len2, m, results;
          results = [];
          for (m = 0, len2 = path.length; m < len2; m++) {
            tb = path[m];
            results.push(tb.target_name);
          }
          return results;
        })();
        ref2 = table.columns;
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          col = ref2[m];
          if (col.uplink) {
            continue;
          }
          if (col.key) {
            continue;
          }
          if (col.parent_id) {
            continue;
          }
          if (col.pool_id) {
            continue;
          }
          if (col.tag) {
            continue;
          }
          if (!col.target_name) {
            continue;
          }
          if (table.owned_by && (ref3 = col.source_name, indexOf.call(_this.track_create_fields, ref3) >= 0)) {
            continue;
          }
          if (indexOf.call(col.source_options, "unique") >= 0 && col.target_type !== "eas") {
            unique = "true";
          } else {
            unique = "";
          }
          if (indexOf.call(col.source_options, "not_null") >= 0) {
            not_null = "true";
          } else {
            not_null = "";
          }
          csv.push([table_path.join(" > "), col.target_name, col.target_type, unique, not_null, col.target_displayname]);
        }
        ref4 = table._nested_tables;
        for (n = 0, len3 = ref4.length; n < len3; n++) {
          nested_table = ref4[n];
          if (nested_table.merge_with_table) {
            continue;
          }
          new_path = path.slice(0);
          new_path.push(nested_table);
          csv.push([
            ((function() {
              var len4, o, results;
              results = [];
              for (o = 0, len4 = new_path.length; o < len4; o++) {
                tb = new_path[o];
                results.push(tb.target_name);
              }
              return results;
            })()).join(" > "), "", "", ""
          ]);
          add_columns(nested_table, new_path);
        }
      };
    })(this);
    ref2 = this.__info.tables;
    for (idx = m = 0, len2 = ref2.length; m < len2; idx = ++m) {
      table = ref2[idx];
      if (table.internal) {
        continue;
      }
      csv.push(["### TABLE " + table.source_name]);
      csv.push(["NAME", table.target_name]);
      csv.push(["DISPLAYNAME:" + this.__settings.target_lang, table.target_displayname]);
      csv.push(["POOL", table.pool]);
      csv.push(["HIERARCHICAL", table.hierarchical]);
      csv.push(["TAGS", table.tags]);
      csv.push(["SEARCH", table.source_name === this.__info.attrs.EASYDB_DEFAULT_TABLE || table.pool]);
      csv.push([]);
      csv.push([]);
      csv.push(["### COLUMNS "]);
      csv.push(["TABLE", "NAME", "TYPE", "UNIQUE", "NOT_NULL", "DISPLAYNAME:" + this.__settings.target_lang]);
      add_columns(table, [table]);
      csv.push([]);
      csv.push([]);
    }
    _csv = new CUI.CSVData({
      rows: csv
    });
    CUI.FileReader.save("datamodel-easydb4-" + this.__info.attrs.eadb_frontend + ".csv", '\uFEFF' + _csv.toText());
  };

  Easydb4Migration.prototype.fixLineEndings = function(str) {
    if (!CUI.isString(str)) {
      return str;
    }
    str = str.replace(/\\r\\n/g, "\n");
    str = str.replace(/\r\n/g, "\n");
    str = str.replace(/\r/g, "\n");
    return str.trim();
  };

  Easydb4Migration.prototype.mapObject = function(row, table, obj_by_id) {
    var _lobj, _obj, coalesce, cobj, col, col_mapping, dstr, from, gobj, id, j, jahr_bis, jahr_von, lang, len1, lobj, lobj2, lookup, msg, number, obj, ref, ref1, ref2, ref3, ref4, ref5, ref6, sn, target, target_column, target_column_name, target_link_table, target_type, tb_mapping, to, unique, url, urls, value;
    if (obj_by_id == null) {
      obj_by_id = {};
    }
    tb_mapping = this.__mapping.source_table[table.source_name];
    obj = {};
    coalesce = function() {
      var arg, j, len1;
      for (j = 0, len1 = arguments.length; j < len1; j++) {
        arg = arguments[j];
        if (!CUI.util.isEmpty(arg)) {
          return "" + arg;
        }
      }
      return null;
    };
    if (!(tb_mapping != null ? tb_mapping.source_column : void 0)) {
      return obj;
    }
    ref1 = table.columns;
    for (j = 0, len1 = ref1.length; j < len1; j++) {
      col = ref1[j];
      if (!col.source_name) {
        continue;
      }
      col_mapping = tb_mapping.source_column[col.source_name];
      if (col.uplink) {
        target_column_name = col.source_name;
      } else {
        target_column_name = col_mapping != null ? col_mapping.target_column_name : void 0;
      }
      value = this.fixLineEndings(row[col.real_source_name]);
      if (col.key) {
        obj.__key = value;
        obj_by_id[value] = obj;
      }
      if (col.parent_id) {
        if (value) {
          target = this.getTargetColumn(table.source_name, table.key.source_name);
          if (!target) {
            msg = "Unable to find target for id lookup (easydb4_reference missing?): '" + table.source_name + "'.'" + table.key.source_name + "'";
            console.error(msg, value, table, col);
            throw msg;
          }
          lookup = {};
          lookup[target.column.name] = this.getEasydb4ReferencePrefix(target.column.name, table.source_name) + value;
          obj["lookup:_id_parent"] = lookup;
        } else {
          obj["_id_parent"] = null;
        }
        continue;
      }
      if (!target_column_name && !col.pool_id && !col.tag) {
        continue;
      }
      if (col.key) {
        obj[target_column_name] = this.getEasydb4ReferencePrefix(target_column_name, table.source_name) + value;
        continue;
      }
      if (CUI.util.isEmpty(value)) {
        if (col.pool_id) {
          obj._pool = {
            pool: {}
          };
          obj._pool.pool["lookup:_id"] = {
            reference: "system:standard"
          };
        }
        continue;
      }
      target = this.getTargetColumn(table.source_name, col.real_source_name);
      unique = false;
      if (table.target_name.startsWith("basetype:")) {
        target_type = col.target_type;
      } else if (target) {
        target_type = target.column.type;
        if (((ref2 = target.column._unique_keys) != null ? ref2.length : void 0) === 1) {
          if (target.column._unique_keys[0].columns.length === 1) {
            unique = true;
            for (id in obj_by_id) {
              _obj = obj_by_id[id];
              if (_obj[target_column_name] === value) {
                value = value + " [" + row[table.key.source_name] + "]";
                this.logwarn("Deduplicated value: " + value + " in " + table.real_source_name + "[" + id + "]");
              }
            }
          }
        }
      } else {
        target_type = void 0;
      }
      if (target_type === "eas") {
        if (!this.__settings.eas_version) {
          obj["__skip_" + target_column_name] = value;
          continue;
        }
        urls = this.__eas_urls_by_id[value];
        if (urls && (urls.original || urls._original)) {
          obj[target_column_name] = [{}];
          obj[target_column_name][0].preferred = true;
          obj[target_column_name][0]["eas:filename"] = urls.original_filename;
          url = urls.original || urls._original;
          url = url.replace(/([^:]\/)\/+/g, "$1");
          obj[target_column_name][0]["eas:url"] = url;
          if (urls.preview_url) {
            obj[target_column_name][0]["eas:preview:url"] = urls.preview_url.replace(/([^:]\/)\/+/g, "$1");
          }
          obj[target_column_name][0]["_easydb4_eas_id"] = value;
        } else {
          msg = "EAS export: " + table.real_source_name + ":" + row[table.key.source_name] + ", eas id: " + value + " request version '" + this.__settings.eas_version + "' not found.";
          this.logwarn(msg);
          obj["__not_found_" + target_column_name] = value;
        }
        continue;
      }
      if (target_type === "daterange" && target.key) {
        dstr = CUI.DateTime.format(value, "store");
        if (dstr !== null) {
          if (!obj[target.column.name]) {
            obj[target.column.name] = {};
          }
          obj[target.column.name][target.key] = dstr;
          console.debug(dstr, obj[target.column.name]);
        }
        continue;
      } else if (col.target_type === "daterange") {
        sn = col.real_source_name;
        from = null;
        if (!CUI.util.isEmpty(row[sn + "_date_von"])) {
          from = CUI.DateTime.format(row[sn + "_date_von"], "store");
        }
        jahr_von = parseInt(row[sn + "_jahr_von"]);
        if (!from && !isNaN(jahr_von)) {
          from = CUI.DateTime.format("" + jahr_von, "store");
        }
        if (!from) {
          this.logwarn(table.source_name + ":" + row[table.key.source_name] + "[" + col.source_name + "]: From date not recognized, this will be stored as 'null': date_von: " + row[sn + "_date_von"] + ", jahr_von: " + row[sn + "_jahr_von"]);
        }
        to = null;
        if (!CUI.util.isEmpty(row[sn + "_date_bis"])) {
          to = CUI.DateTime.format(row[sn + "_date_bis"], "store");
        }
        jahr_bis = parseInt(row[sn + "_jahr_bis"]);
        if (!to && !isNaN(jahr_bis)) {
          to = CUI.DateTime.format("" + jahr_bis, "store");
        }
        if (!to) {
          this.logwarn(table.source_name + ":" + row[table.key.source_name] + "[" + col.source_name + "]: To date not recognized, this will be stored as 'null': date_bis: " + row[sn + "_date_bis"] + ", jahr_bis: " + row[sn + "_jahr_bis"]);
        }
        if (from && to) {
          if (parseInt(from) > parseInt(to)) {
            this.logwarn(table.source_name + ":" + row[table.key.source_name] + "[" + col.source_name + "]: From date bigger than To date: " + from + " > " + to + ". Swapping dates.");
            ref3 = [to, from], from = ref3[0], to = ref3[1];
          }
          if (from.endsWith("-01-01") && to.endsWith("-12-31")) {
            from = from.substr(0, 4);
            to = to.substr(0, 4);
          }
        }
        if (from || to) {
          obj[target_column_name] = {
            from: from,
            to: to
          };
        }
        continue;
      }
      if (target_type === "date") {
        obj[col.target_name] = {
          value: value
        };
        continue;
      }
      if (col_mapping.target) {
        _lobj = {};
        _lobj[col_mapping.target.other_column.name] = value + "";
        lobj = {};
        lobj["lookup:_id"] = _lobj;
        lobj2 = {
          _objecttype: col_mapping.target.other_table.name,
          _mask: "_all_fields"
        };
        lobj2[col_mapping.target.other_table.name] = lobj;
        obj[target_column_name] = lobj2;
      } else if (target_column_name === '__UPLINK__') {
        obj[col.source_name] = value;
      } else if (col.uplink) {
        obj[target_column_name] = value;
      } else if (target_type === "custom:base.custom-data-type-gnd.gnd") {
        if (col.source_link.real_source_name !== "dnb_normdaten") {
          this.logwarn("Unable to migrate GND from " + col.source_link.real_source_name + ".");
          continue;
        }
        cobj = {
          __gnd: {
            source: col.source_link.real_source_name,
            key: col.source_link.key.source_name,
            value: value
          }
        };
        obj[target_column_name] = cobj;
      } else if (target_type === "custom:base.custom-data-type-gazetteer.gazetteer") {
        gobj = {
          __gazetteer: {
            gazId: value
          }
        };
        obj[target_column_name] = gobj;
      } else if (target_type === "custom:base.custom-data-type-getty.getty") {
        gobj = {};
        gobj["__" + col.source_link.source_name] = {
          value: value
        };
        obj[target_column_name] = gobj;
      } else if (col.source_link) {
        if (col.pool_id) {
          obj._pool = {
            pool: {}
          };
          obj._pool.pool["lookup:_id"] = {
            reference: col.source_link.source_name + ":" + value
          };
        } else if (col.tag) {
          obj["top:_tags"] = [{}];
          obj["top:_tags"][0]["lookup:_id"] = {
            reference: col.source_link.source_name + ":" + value
          };
        } else {
          target = this.getTargetColumn(col.source_link.source_name, col.source_link.key.source_name);
          if (!target) {
            obj["lookup:" + target_column_name] = {
              __not_found_easydb4_reference: col.source_link.source_name + ":" + value
            };
            continue;
          }
          target_column = (ref4 = ez5.schema.CURRENT._table_by_name[tb_mapping.target_table_name]) != null ? ref4._column_by_name[target_column_name] : void 0;
          target_link_table = ez5.schema.CURRENT._table_by_id[target_column != null ? (ref5 = target_column._foreign_key) != null ? (ref6 = ref5.referenced_table) != null ? ref6.table_id : void 0 : void 0 : void 0];
          if (target_link_table) {
            ref = this.getEasydb4ReferencePrefix(target.column.name, col.source_link.source_name) + value;
          } else {
            ref = value + "";
          }
          if (!target_link_table) {
            this.logwarn("Unable to map source type link to " + table.source_name + "." + col.source_link.source_name + " > " + tb_mapping.target_table_name + "." + target_column_name + "[" + (target_column != null ? target_column.type : void 0) + "]");
            switch (target_type) {
              case "number":
              case "integer.2":
                number = parseInt(ref);
                if (isNaN(number)) {
                  obj[target_column_name] = 0;
                } else {
                  obj[target_column_name] = number;
                }
                break;
              default:
                obj[target_column_name] = ref;
            }
          } else {
            lobj = {
              _objecttype: target_link_table.name,
              _mask: "_all_fields"
            };
            lobj[target_link_table.name] = {};
            lobj[target_link_table.name]["lookup:_id"] = {};
            lobj[target_link_table.name]["lookup:_id"][target.column.name] = ref;
            obj[target_column_name + ":source_name"] = col.source_link.source_name;
            obj[target_column_name] = lobj;
          }
        }
      } else {
        switch (target_type) {
          case "boolean":
            if (CUI.util.isTrue(value) || value === "Y" || value === "t") {
              obj[target_column_name] = true;
            } else {
              obj[target_column_name] = false;
            }
            break;
          case "number":
          case "integer.2":
            number = parseInt(value);
            if (isNaN(number)) {
              obj[target_column_name] = 0;
            } else {
              obj[target_column_name] = number;
            }
            break;
          case "text":
          case "text_oneline":
          case "string":
            obj[target_column_name] = value + "";
            break;
          case "datetime":
            obj[target_column_name] = {
              value: value
            };
            break;
          case "text_l10n":
          case "text_l10n_oneline":
            if (target.key) {
              lang = target.key;
            } else {
              lang = this.__settings.target_lang;
            }
            if (!obj[target.column.name]) {
              obj[target.column.name] = {};
            }
            obj[target.column.name][lang] = value;
            break;
          case "custom:base.custom-data-type-link.link":
            obj[target_column_name] = {
              url: value
            };
            break;
          default:
            console.error("Unsupported target type: " + target_type, target, col_mapping, table, row, col, value);
            throw "Unsupported target type: " + target_type + " (" + table.source_name + "." + col.source_name + ")";
        }
      }
    }
    if (row._depth !== void 0) {
      obj["top:_depth"] = row._depth;
    }
    return obj;
  };

  Easydb4Migration.prototype.mergeTopLevel = function(top_level, obj) {
    var k, obj_key, v;
    obj_key = top_level._basetype || top_level._objecttype;
    if (!obj_key) {
      console.error("mergeTopLevel: No object key found:", top_level_obj);
      return obj;
    }
    if (!top_level[obj_key]) {
      top_level[obj_key] = {};
    }
    for (k in obj) {
      v = obj[k];
      if (k.startsWith("top:")) {
        top_level[k.substr(4)] = v;
      } else {
        top_level[obj_key][k] = v;
      }
    }
  };

  Easydb4Migration.prototype.exportJSON = function() {
    var collection_user_refs, export_collection, export_collections, export_groups, export_next_object_table, export_object_table, export_pool, export_pools, export_presentations, export_tags, export_users, get_eas_ids, get_objects_for_table, go_on, idx, j, ldap_sso_users, len1, len2, m, manifest, master_dfr, master_dfr2, object_ids_per_table, payload, payload_split, plugin, prepare_tables, problem, ref1, ref2, send_ldap_sso_users, sort_by_depth, store_log, table_idx, tool, update_payload;
    master_dfr = new CUI.Deferred();
    master_dfr2 = new CUI.Deferred();
    master_dfr.fail((function(_this) {
      return function(err) {
        var msg;
        msg = "Export failed: " + JSON.stringify((err != null ? err.debug : void 0) || (err != null ? err.error : void 0) || err);
        _this.logerror(msg, arguments);
        return CUI.problem({
          text: msg
        });
      };
    })(this));
    this.loginfo("Started export JSON.");
    ref1 = this.__info.problems;
    for (idx = j = 0, len1 = ref1.length; j < len1; idx = ++j) {
      problem = ref1[idx];
      this.logwarn("Problem #" + idx + ":" + problem);
    }
    master_dfr.done((function(_this) {
      return function() {
        _this.loginfo("JSON export done.");
        return store_log().done(master_dfr2.resolve).fail(master_dfr2.reject);
      };
    })(this));
    master_dfr.fail((function(_this) {
      return function() {
        _this.loginfo("JSON export failed.");
        return store_log().always(master_dfr2.reject);
      };
    })(this));
    ldap_sso_users = [];
    collection_user_refs = [];
    store_log = (function(_this) {
      return function() {
        return _this.storeTextFile("log-export-" + (_this.__info.attrs.eadb_frontend || "unknown") + ".csv", new CUI.CSVData({
          rows: _this.__logentries
        }).toText({
          delimiter: "\t",
          always_quote: false
        })).always(function() {
          return delete _this.__logentries;
        });
      };
    })(this);
    manifest = {
      source: this.__info.attrs.eadb_frontend,
      batch_size: 1000,
      eas_type: "url",
      has_passwords: true,
      payloads: [],
      __update_payloads: []
    };
    payload_split = (function(_this) {
      return function(filename, chunk_size, json) {
        var basename, depth, ext, json_chunk, obj, offset, okey, promises, write_file;
        promises = [];
        basename = ez5.bareBasename(filename);
        ext = ez5.extension(filename);
        switch (json.import_type) {
          case "collection":
            okey = "collections";
            break;
          default:
            console.error("payload_split: unsupported import_type:", json.import_type);
            return CUI.rejectedPromise();
        }
        json_chunk = {
          import_type: json.import_type
        };
        json_chunk[okey] = [];
        offset = 0;
        write_file = function() {
          var dep, to;
          console.debug("write file:", json_chunk[okey].length);
          if (json_chunk[okey].length === 0) {
            return;
          }
          if (depth !== void 0) {
            dep = "-depth-" + depth;
          } else {
            dep = "";
          }
          to = offset + json_chunk[okey].length;
          promises.push(payload(basename + "-" + (offset + 1) + "-" + to + dep + "." + ext, json_chunk));
          offset = offset + json_chunk[okey].length;
          json_chunk[okey] = [];
        };
        idx = 0;
        depth = void 0;
        while (idx < json[okey].length) {
          obj = json[okey][idx];
          if (obj._depth !== void 0) {
            if (depth !== obj._depth) {
              write_file();
              depth = obj._depth;
            }
          }
          json_chunk[okey].push(obj);
          if (json_chunk[okey].length === chunk_size) {
            write_file();
          }
          idx++;
        }
        write_file();
        return CUI.when(promises);
      };
    })(this);
    payload = (function(_this) {
      return function(filename, json, update) {
        var dfr3, filename_idx, plugin, post_promise, promises;
        if (update == null) {
          update = false;
        }
        if (indexOf.call(manifest.payloads, filename) >= 0) {
          console.error("Unable to add same payload twice:", filename);
          return CUI.rejectedPromise();
        }
        if (update) {
          manifest.__update_payloads.push(filename);
        } else {
          manifest.payloads.push(filename);
        }
        dfr3 = new CUI.Deferred();
        if (_this.__settings.post_process_plugin) {
          plugin = _this.__plugin_by_name[_this.__settings.post_process_plugin];
          if (!plugin) {
            console.error("Unable to find plugin:", _this.__settings.post_process_plugin);
          } else {
            promises = [];
            filename_idx = CUI.util.idxInArray(filename, manifest.payloads);
            post_promise = plugin.payload(filename, json, update, (function(_filename, json, use_filename_idx) {
              var ext, filename_uniq, promise;
              if (use_filename_idx === void 0) {
                use_filename_idx = filename_idx;
              }
              ext = ez5.extension(_filename);
              filename_uniq = ez5.bareBasename(_filename) + "_" + (manifest.payloads.length + 1);
              if (!CUI.util.isEmpty(ext)) {
                filename_uniq = filename_uniq + "." + ext;
              }
              manifest.payloads.splice(use_filename_idx, 0, filename_uniq);
              promise = _this.storeFile(filename_uniq, json);
              promises.push(promise);
              return promise;
            }), filename_idx);
            if (post_promise !== void 0) {
              _this.loginfo("Post process: " + _this.__settings.post_process_plugin + ": " + filename);
            }
            CUI.decide(post_promise).fail(dfr3.reject).done(function(opts) {
              if (opts == null) {
                opts = {};
              }
              return CUI.when(promises).fail(dfr3.reject).done(function() {
                if (opts.dont_store) {
                  CUI.util.removeFromArray(filename, manifest.payloads);
                  dfr3.resolve();
                  return;
                }
                return _this.storeFile(filename, json).fail(dfr3.reject).done(dfr3.resolve);
              });
            });
          }
        } else {
          _this.storeFile(filename, json).fail(dfr3.reject).done(dfr3.resolve);
        }
        return dfr3.promise();
      };
    })(this);
    update_payload = (function(_this) {
      return function(filename, json) {
        return payload(filename, json, true);
      };
    })(this);
    master_dfr.done((function(_this) {
      return function() {
        var len2, m, ref2;
        ez5.splash.done("easydb4migration.progress", {
          payload: "manifest.json"
        });
        ref2 = manifest.__update_payloads;
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          payload = ref2[m];
          manifest.payloads.push(payload);
        }
        delete manifest.__update_payloads;
        return _this.storeFile("manifest.json", manifest);
      };
    })(this));
    master_dfr.fail((function(_this) {
      return function() {
        return ez5.splash.hide();
      };
    })(this));
    sort_by_depth = (function(_this) {
      return function(items, id_key, parent_id_key) {
        var find_item_by_id, find_path, item, len2, m;
        find_item_by_id = function(id) {
          var item, len2, m;
          for (m = 0, len2 = items.length; m < len2; m++) {
            item = items[m];
            if (item[id_key] === id) {
              return item;
            }
          }
        };
        find_path = function(item, path) {
          var parent_id, parent_item;
          if (path == null) {
            path = [];
          }
          if (!parent_id_key) {
            return path;
          }
          parent_id = item[parent_id_key];
          if (!parent_id) {
            return path;
          }
          parent_item = find_item_by_id(parent_id);
          if (!parent_item) {
            console.debug("Unable to find parent for item.");
            return path;
          }
          path.push(parent_item);
          return find_path(parent_item, path);
        };
        for (m = 0, len2 = items.length; m < len2; m++) {
          item = items[m];
          item._depth = find_path(item).length;
        }
        items.sort(function(a, b) {
          if (a._depth < b._depth) {
            return -1;
          } else if (a._depth > b._depth) {
            return 1;
          } else {
            return CUI.util.compareIndex(a[id_key], b[id_key]);
          }
        });
      };
    })(this);
    export_pool = (function(_this) {
      return function(pool) {
        var col, dfr, id_key, id_parent_key, len2, m, name_col, ref2;
        dfr = new CUI.Deferred();
        ref2 = pool.columns;
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          col = ref2[m];
          if (col.source_name === "name") {
            name_col = col;
          }
        }
        if (!name_col) {
          dfr.reject("Pool column 'name' not found. Table: " + pool.source_name);
          return dfr.promise();
        }
        id_key = pool.key.source_name;
        if (pool.parent) {
          id_parent_key = pool.parent.source_name;
        }
        _this.query("SELECT * FROM " + _this.getEasydb4TableName(pool.source_name) + " ORDER BY \"" + pool.key.source_name + "\"").fail(dfr.reject).done(function(result) {
          var _pool, len3, n, pools, ref3, row;
          sort_by_depth(result.rows, id_key, id_parent_key);
          pools = [];
          ref3 = result.rows;
          for (n = 0, len3 = ref3.length; n < len3; n++) {
            row = ref3[n];
            _pool = {
              _basetype: "pool",
              _depth: row._depth,
              pool: {
                _version: 1,
                reference: pool.source_name + ":" + row[id_key],
                name: {}
              }
            };
            _pool.pool.name[_this.__settings.target_lang] = row[name_col.source_name];
            if (id_parent_key && row[id_parent_key]) {
              _pool.pool["lookup:_id_parent"] = {
                reference: pool.source_name + ":" + row[id_parent_key]
              };
            } else {
              if (pool !== _this.__info.pool_tables[0]) {
                _pool.pool.name[_this.__settings.target_lang] += " [" + pool.source_name + "]";
              }
              _pool.pool["lookup:_id_parent"] = {
                reference: "system:root"
              };
            }
            pools.push(_pool);
          }
          return dfr.resolve(pools);
        });
        return dfr.promise();
      };
    })(this);
    export_pools = (function(_this) {
      return function() {
        var dfr;
        if (indexOf.call(_this.__settings.export_basetypes, "pool") < 0) {
          return CUI.resolvedPromise();
        }
        dfr = new CUI.Deferred();
        if (_this.__info.pool_tables.length === 0) {
          dfr.resolve();
          return dfr.promise();
        }
        ez5.splash.show("easydb4migration.progress", {
          payload: "pools"
        });
        CUI.chunkWork.call(_this, {
          items: _this.__info.pool_tables,
          chunk_size: 1,
          call: function(items, idx) {
            var dfr2;
            dfr2 = new CUI.Deferred();
            export_pool(items[0]).fail(dfr2.reject).done(function(pools) {
              var idxP, len2, m, payloads, pool, pools_per_depth;
              payloads = [];
              pools_per_depth = [];
              for (idxP = m = 0, len2 = pools.length; m < len2; idxP = ++m) {
                pool = pools[idxP];
                pools_per_depth.push(pool);
                if (idxP < pools.length - 1 && pools[idxP + 1]._depth > pool._depth) {
                  payloads.push(payload("basetype_pool-" + idx + "-depth-" + pool._depth + ".json", {
                    import_type: "pool",
                    pools: pools_per_depth
                  }));
                  pools_per_depth = [];
                }
              }
              if (pools_per_depth.length > 0) {
                payloads.push(payload("basetype_pool-" + idx + "-depth-" + pools_per_depth[0]._depth + ".json", {
                  import_type: "pool",
                  pools: pools_per_depth
                }));
              }
              return CUI.when(payloads).fail(dfr2.reject).done(dfr2.resolve);
            });
            return dfr2.promise();
          }
        }).fail(dfr.reject).done(dfr.resolve);
        return dfr.promise();
      };
    })(this);
    export_tags = (function(_this) {
      return function() {
        var col, dfr, fn, len2, len3, m, n, name_col, promises, ref2, ref3, tag_table, taggroup, taggroups;
        if (indexOf.call(_this.__settings.export_basetypes, "tags") < 0) {
          return CUI.resolvedPromise();
        }
        dfr = new CUI.Deferred();
        ez5.splash.show("easydb4migration.progress", {
          payload: "tags"
        });
        taggroups = [];
        promises = [];
        ref2 = _this.__info.tag_tables;
        fn = function(taggroup, tag_table) {
          var promise;
          promise = _this.query("SELECT * FROM " + _this.getEasydb4TableName(tag_table.source_name) + " ORDER BY \"" + tag_table.key.source_name + "\"");
          promise.done(function(result) {
            var len3, n, ref3, row, tag;
            ref3 = result.rows;
            for (n = 0, len3 = ref3.length; n < len3; n++) {
              row = ref3[n];
              tag = {
                tag: {
                  reference: tag_table.source_name + ":" + row[tag_table.key.source_name],
                  displayname: {},
                  displaytype: "search",
                  is_default: false,
                  enabled: true,
                  type: "individual"
                }
              };
              tag.tag.displayname[_this.__settings.target_lang] = row[name_col.source_name];
              taggroup._tags.push(tag);
            }
          });
          return promises.push(promise);
        };
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          tag_table = ref2[m];
          ref3 = tag_table.columns;
          for (n = 0, len3 = ref3.length; n < len3; n++) {
            col = ref3[n];
            if (col.source_name === "name") {
              name_col = col;
            }
          }
          if (!name_col) {
            dfr.reject("Tag column 'name' not found.");
            return dfr.promise();
          }
          taggroup = {
            taggroup: {
              reference: "easydb4:" + tag_table.source_name,
              shortname: tag_table.source_name,
              type: "checkbox",
              displayname: {}
            },
            _tags: []
          };
          taggroup.taggroup.displayname[_this.__settings.target_lang] = tag_table.target_displayname;
          taggroups.push(taggroup);
          fn(taggroup, tag_table);
        }
        CUI.when(promises).fail(dfr.reject).done(function() {
          payload("basetype_tags.json", {
            import_type: "tags",
            tags: taggroups
          });
          return dfr.resolve();
        });
        return dfr.promise();
      };
    })(this);
    send_ldap_sso_users = (function(_this) {
      return function() {
        var len2, m, ref2, user, users;
        users = [];
        for (m = 0, len2 = ldap_sso_users.length; m < len2; m++) {
          user = ldap_sso_users[m];
          if (ref2 = user.user.reference, indexOf.call(collection_user_refs, ref2) >= 0) {
            users.push(user);
          }
        }
        _this.loginfo("LDAP/SSO users with collections: " + users.length);
        return payload("basetype_user_ldap_sso.json", {
          import_type: "user",
          users: users
        }).done(function() {
          var payload_file;
          idx = manifest.payloads.indexOf("basetype_user.json");
          if (idx === -1) {
            return _this.logwarn("basetype_user.json not found, unable to move basetype_user_ldap_sso.json.");
          } else {
            payload_file = manifest.payloads.pop();
            return manifest.payloads.splice(idx + 1, 0, payload_file);
          }
        });
      };
    })(this);
    export_users = (function(_this) {
      return function() {
        var dfr, easydb_logins, group_table, process_users, table, user_by_email, user_by_login;
        if (indexOf.call(_this.__settings.export_basetypes, "user") < 0) {
          return CUI.resolvedPromise();
        }
        dfr = new CUI.Deferred();
        group_table = _this.__info.base_tables.group;
        if (!group_table) {
          dfr.reject("No group table found.");
          return dfr.promise();
        }
        table = _this.__info.base_tables.user;
        if (!table) {
          dfr.reject("No user table found.");
          return dfr.promise();
        }
        ez5.splash.show("easydb4migration.progress", {
          payload: "users"
        });
        user_by_email = {};
        user_by_login = {};
        easydb_logins = [];
        _this.__info.user_by_ref = {};
        _this.query("SELECT * FROM " + _this.getEasydb4TableName(table.source_name) + " ORDER BY \"" + table.key.source_name + "\"").done(function(result) {
          var easydb_users;
          easydb_users = result.rows;
          return _this.query("SELECT * FROM " + _this.getEasydb4TableName("eadb_user_cache") + " ORDER BY id").done(function(result2) {
            var cache_users, len2, m, rec, ref2, ref3, row2;
            cache_users = [];
            ref2 = result2.rows;
            for (m = 0, len2 = ref2.length; m < len2; m++) {
              row2 = ref2[m];
              if (!CUI.util.isString(row2.user_record)) {
                continue;
              }
              rec = JSON.parse(row2.user_record);
              if ((ref3 = rec.logintype) !== "LoginShib2" && ref3 !== "LoginLDAP") {
                continue;
              }
              rec.login = rec.user_id;
              cache_users.push(rec);
            }
            return process_users(easydb_users, false).fail(dfr.reject).done(function() {
              easydb_logins = Object.keys(user_by_login);
              return process_users(cache_users, true).fail(dfr.reject).done(dfr.resolve);
            });
          });
        });
        process_users = function(rows, eadb_user_cache) {
          var dfr2, email, info, len2, login, m, new_login, obj, other_user, ref2, ref3, row, uid, user, user_by_id, users, warning;
          user_by_id = {};
          users = [];
          for (m = 0, len2 = rows.length; m < len2; m++) {
            row = rows[m];
            uid = row[table.key.source_name];
            user = {
              _basetype: "user",
              _groups: [],
              user: {
                _version: 1,
                reference: table.source_name + ":" + uid,
                remarks: ""
              }
            };
            user_by_id[uid] = user;
            obj = _this.mapObject(row, table);
            _this.mergeTopLevel(user, obj);
            if (user.user.login) {
              login = (ref2 = user.user.login) != null ? ref2.toLocaleLowerCase() : void 0;
              if (user.user.login === "root") {
                user.user.login = "root_easydb4";
              }
              if (user_by_login[login]) {
                if (eadb_user_cache && indexOf.call(easydb_logins, login) >= 0) {
                  warning = "User '" + user.user.login + "' already an easydb user. Skipping.";
                  _this.logwarn(warning);
                  continue;
                }
                new_login = user.user.login + user_by_login[login];
                warning = "User '" + user.user.login + "' changed login to: '" + new_login + "'";
                _this.logwarn(warning);
                user.user.login = new_login;
                user_by_login[login] += 1;
              } else {
                user_by_login[login] = 1;
              }
              user.user.reference = table.source_name + ":login:" + user.user.login;
              _this.__info.user_by_ref[user.user.reference] = user;
            } else {
              user.user.login = "easydb4:" + uid;
              _this.logwarn("User '" + uid + "' has not login. The login was set to '" + user.user.login + "'.");
            }
            if (eadb_user_cache) {
              switch (row.logintype) {
                case "LoginLDAP":
                  user.user.type = "ldap";
                  break;
                case "LoginShib2":
                  user.user.type = "sso";
              }
            } else {
              if (row.use_ldap_auth) {
                info = "User '" + user.user.login + "' has use_ldap_auth set, creating as with type: ldap.";
                _this.loginfo(info);
                user.user.type = "ldap";
              } else {
                user.user.type = "easydb";
              }
            }
            email = (ref3 = user.user._new_primary_email) != null ? ref3.trim().toLocaleLowerCase() : void 0;
            if ((email != null ? email.length : void 0) > 0) {
              if (!CUI.EmailInput.regexp.exec(email)) {
                warning = "User '" + user.user.login + "' uses a borked email. Email '" + email + "' for this user was ignored.";
                _this.logwarn(warning);
                user.user.remarks += warning + "\n";
              } else {
                other_user = user_by_email[email];
                if (other_user) {
                  warning = "User '" + other_user.user.login + "' uses the same email. Email '" + email + "' for this user was ignored.";
                  _this.logwarn(warning);
                  other_user.user.remarks += "User '" + user.user.login + "' uses same email.\n";
                  user.user.remarks += warning + "\n";
                } else {
                  user_by_email[email] = user;
                  user._emails = [
                    {
                      email: email,
                      use_for_login: false,
                      use_for_email: true,
                      send_email: false,
                      send_email_include_password: false,
                      send_email_welcome_now: false,
                      is_primary: true,
                      needs_confirmation: false
                    }
                  ];
                }
              }
            }
            delete user.user._new_primary_email;
            if (user.user._password) {
              user._password_insecure_hash = user.user._password;
              user._password_insecure_hash_method = "md5";
              user._password_hash = "md5:" + user.user._password;
              delete user.user._password;
            }
            users.push(user);
          }
          dfr2 = new CUI.Deferred();
          if (eadb_user_cache) {
            ldap_sso_users = users;
            dfr2.resolve();
          } else {
            _this.query("SELECT * FROM " + _this.getEasydb4TableName("eadb_links") + "					       WHERE\nto_table_id = " + group_table.source_id + " AND\nfrom_table_id = " + table.source_id + ' AND to_id IN (SELECT id FROM ' + _this.getEasydb4TableName(group_table.source_name) + ')').fail(dfr.reject).done(function(result) {
              var len3, n, ref4;
              ref4 = result.rows;
              for (n = 0, len3 = ref4.length; n < len3; n++) {
                row = ref4[n];
                uid = row.from_id;
                user = user_by_id[uid];
                if (!user) {
                  _this.logwarn("User not found:", uid);
                  continue;
                }
                user._groups.push({
                  _basetype: "group",
                  group: {
                    "lookup:_id": {
                      reference: group_table.source_name + ":" + row.to_id
                    }
                  }
                });
              }
              return payload("basetype_user.json", {
                import_type: "user",
                users: users
              }).done(dfr2.resolve).fail(dfr2.reject);
            });
          }
          return dfr2.promise();
        };
        return dfr.promise();
      };
    })(this);
    export_groups = (function(_this) {
      return function() {
        var dfr, table;
        if (indexOf.call(_this.__settings.export_basetypes, "group") < 0) {
          return CUI.resolvedPromise();
        }
        dfr = new CUI.Deferred();
        table = _this.__info.base_tables.group;
        if (!table) {
          dfr.reject("No group table found.");
          return dfr.promise();
        }
        ez5.splash.show("easydb4migration.progress", {
          payload: "groups"
        });
        _this.query("SELECT * FROM " + _this.getEasydb4TableName(table.source_name) + " ORDER BY \"" + table.key.source_name + "\"").done(function(result) {
          var group, group_id, groups, len2, m, name, ref2, row;
          groups = [];
          _this.__info.group_by_id = {};
          ref2 = result.rows;
          for (m = 0, len2 = ref2.length; m < len2; m++) {
            row = ref2[m];
            name = row[_this.__info.attrs.GROUP_TABLE_DISPLAY_COLUMN_NAME];
            group_id = row[table.key.source_name];
            group = {
              _basetype: "group",
              __name: name,
              group: {
                _version: 1,
                reference: table.source_name + ":" + group_id,
                displayname: {}
              }
            };
            group.group.displayname[_this.__settings.target_lang] = name;
            _this.__info.group_by_id[group_id] = group;
            groups.push(group);
          }
          payload("basetype_group.json", {
            import_type: "group",
            groups: groups
          }).fail(dfr.reject).done(dfr.resolve);
        });
        return dfr.promise();
      };
    })(this);
    export_collections = (function(_this) {
      return function() {
        var table, table2;
        if (indexOf.call(_this.__settings.export_basetypes, "collection") < 0) {
          return CUI.resolvedPromise();
        }
        table = _this.__info.base_tables.workfolder;
        if (!table) {
          _this.logwarn("No workfolder table found.");
        }
        table2 = _this.__info.base_tables.workfolder2;
        if (!table2) {
          _this.loginfo("No WORKFOLDER_SECOND_TABLE configured.");
        }
        return CUI.chunkWork.call(_this, {
          items: [[table, _this.__info.base_tables.workfolder_objects], [table2, _this.__info.base_tables.workfolder2_objects]],
          chunk_size: 1,
          call: function(items, idx) {
            if (!items[0][0]) {
              return;
            }
            return export_collection(items[0][0], items[0][1], idx);
          }
        });
      };
    })(this);
    export_collection = (function(_this) {
      return function(table, objects_table, source_idx) {
        var dfr, login_column, user_table;
        ez5.splash.show("easydb4migration.progress", {
          payload: "collections [" + table.source_name + "]"
        });
        _this.loginfo("Export Collection: " + table.source_name);
        user_table = _this.__info.base_tables.user;
        login_column = _this.__info.attrs.USER_LOGIN_COLUMN;
        dfr = new CUI.Deferred();
        _this.query("SELECT * FROM " + _this.getEasydb4TableName(table.source_name) + " ORDER BY \"" + table.key.source_name + "\"").fail(dfr.reject).done(function(result) {
          var bild_col, bild_mapping, col, collection, collection_by_id, collection_by_uid, collection_id, collections, collections_by_group_rights, colref, gname, len2, len3, m, n, name, name_appendix, owner, parent_id, ref, ref2, ref3, ref4, row, sel, uid;
          collections = [];
          collection_by_id = {};
          collection_by_uid = {};
          collections_by_group_rights = {};
          ref2 = objects_table.columns;
          for (m = 0, len2 = ref2.length; m < len2; m++) {
            col = ref2[m];
            if (!col.source_link) {
              continue;
            }
            if (col.source_link.source_name !== table.source_name) {
              bild_col = col;
              bild_mapping = _this.getTargetColumn(col.source_link.source_name, col.source_link.key.source_name);
              break;
            }
          }
          if (!bild_col || !bild_mapping) {
            console.error("Cannot find link field for collection:", bild_col, objects_table);
            dfr.reject("Cannot find link field in export_collections, easydb4_reference missing?");
            return;
          }
          if (bild_col.source_link.source_name !== _this.__info.attrs.EASYDB_DEFAULT_TABLE) {
            name_appendix = " [" + bild_col.source_link.source_name + "]";
          } else {
            name_appendix = "";
          }
          ref3 = result.rows;
          for (idx = n = 0, len3 = ref3.length; n < len3; idx = ++n) {
            row = ref3[idx];
            name = row[_this.__settings.workfolder_name].trim() + name_appendix;
            collection_id = row[table.key.source_name];
            collection = {
              _basetype: "collection",
              _objects: [],
              __bild_ids: [],
              __reference: table.source_name + ":" + collection_id,
              __parent_reference: null,
              collection: {
                _version: 1,
                reference: table.source_name + ":" + collection_id,
                type: "workfolder",
                children_allowed: true,
                objects_allowed: true,
                displayname: {}
              }
            };
            collection_by_id[collection_id] = collection;
            if (row.group_rights) {
              if (row.group_rights === "-1") {
                gname = "public";
              } else {
                gname = ((ref4 = _this.__info.group_by_id[row.group_rights]) != null ? ref4.__name : void 0) || row.group_rights + "";
              }
              name = name + " [" + gname + "]";
            }
            collection.collection.displayname[_this.__settings.target_lang] = name;
            parent_id = row[_this.__settings.workfolder_parent];
            if (parent_id) {
              colref = table.source_name + ":" + parent_id;
              collection.__parent_reference = colref;
            } else {
              owner = row.easydb_owner;
              if (owner != null ? owner.startsWith("user_") : void 0) {
                ref = user_table.source_name + ":" + login_column + ":" + owner.substr(5);
                if (!_this.__info.user_by_ref[ref]) {
                  colref = ez5.session.user.getCollectionReference();
                  _this.loginfo("User of private collection '" + name + "' not found: " + ref + " setting user to: " + colref);
                } else {
                  colref = "user:ref:" + ref;
                  collection_user_refs.push(ref);
                }
              } else {
                _this.logwarn("No easydb_owner found for collection, using migration user: " + name);
                colref = ez5.session.user.getCollectionReference();
              }
            }
            collection.collection["lookup:_id_parent"] = {
              reference: colref
            };
            uid = colref + name;
            if (collection_by_uid[uid]) {
              collection.collection.displayname[_this.__settings.target_lang] = name + " (" + collection_by_uid[uid] + ")";
              collection_by_uid[uid] += 1;
            } else {
              collection_by_uid[uid] = 1;
            }
            collections.push(collection);
          }
          sort_by_depth(collections, "__reference", "__parent_reference");
          sel = 'SELECT * FROM ' + _this.getEasydb4TableName(objects_table.source_name) + 'WHERE "' + bild_col.source_name + '" IS NOT NULL AND "' + objects_table.uplink.source_name + '" IS NOT NULL ORDER BY "' + objects_table.key.source_name + '"';
          _this.query(sel).fail(dfr.reject).done(function(result) {
            var bild_id, cn, co, json, len4, lobj, missing_count, o, ref5;
            missing_count = {
              bild_ids: [],
              collection: []
            };
            ref5 = result.rows;
            for (o = 0, len4 = ref5.length; o < len4; o++) {
              row = ref5[o];
              collection_id = row[objects_table.uplink.source_name];
              bild_id = row[bild_col.source_name];
              collection = collection_by_id[collection_id];
              if (!collection) {
                CUI.util.pushOntoArray(collection_id, missing_count.collection);
                continue;
              }
              cn = collection.collection.displayname[_this.__settings.target_lang];
              if (indexOf.call(collection.__bild_ids, bild_id) >= 0) {
                _this.logwarn("Collection '" + cn + "': Id found multiple times in collection, skipping: " + bild_id);
                continue;
              }
              collection.__bild_ids.push(bild_id);
              if (bild_id < Math.pow(10, 10)) {
                if (_this.__settings.limit_collections && indexOf.call(object_ids_per_table[bild_col.source_link.real_source_name], bild_id) < 0) {
                  missing_count.bild_ids.push(bild_id);
                  continue;
                }
                lobj = {
                  _objecttype: bild_mapping.table.name
                };
                lobj[bild_mapping.column.name] = bild_col.source_link.real_source_name + ":" + bild_id;
                co = {
                  "lookup:_global_object_id": lobj
                };
              } else {
                co = {
                  _global_object_id: bild_id + "@easydb4"
                };
              }
              collection._objects.push(co);
            }
            if (missing_count.bild_ids.length > 0) {
              _this.logwarn("Collection Objects not found: '" + bild_col.source_link.source_name + "': " + missing_count.bild_ids.length);
            }
            if (missing_count.collection.length > 0) {
              _this.logwarn("Collections not found: " + missing_count.collection.length);
            }
            if (_this.__settings.skip_collection_with_more_objects_than > 0) {
              _this.loginfo("Checking collection sizes. Will drop collection with more than " + _this.__settings.skip_collection_with_more_objects_than + " objects.");
              CUI.util.removeFromArray(null, collections, function(col) {
                if (col._objects.length > _this.__settings.skip_collection_with_more_objects_than) {
                  return _this.loginfo("Skip collection " + col.collection.displayname[_this.__settings.target_lang] + ", it has " + col._objects.length + " objects.");
                }
              });
            }
            json = {
              import_type: "collection",
              collections: collections
            };
            return payload_split("basetype_collection-no" + (source_idx + 1) + ".json", 500, json).fail(dfr.reject).done(dfr.resolve);
          });
        });
        return dfr.promise();
      };
    })(this);
    export_presentations = (function(_this) {
      return function() {
        var bilder_table, dfr, login_column, table, user_table;
        if (indexOf.call(_this.__settings.export_basetypes, "presentation") < 0) {
          return CUI.resolvedPromise();
        }
        dfr = new CUI.Deferred();
        table = _this.__info.base_tables.presentation;
        if (!table) {
          _this.logwarn("No presentation table found.");
          dfr.resolve();
          return dfr.promise();
        }
        bilder_table = _this.__info.base_tables.easydb_default;
        if (!bilder_table) {
          dfr.reject("export presentations: No EASYDB_DEFAULT_TABLE found.");
          return dfr.promise();
        }
        ez5.splash.show("easydb4migration.progress", {
          payload: "presentations"
        });
        user_table = _this.__info.base_tables.user;
        login_column = _this.__info.attrs.USER_LOGIN_COLUMN;
        _this.query("SELECT * FROM " + _this.getEasydb4TableName(table.source_name) + " ORDER BY \"" + table.key.source_name + "\"").fail(dfr.reject).done(function(result) {
          var bild_col, bild_mapping, col, colref, len2, len3, m, missing_count, n, name, objects_table, owner, presentation, presentation_by_id, presentation_by_uid, presentation_id, presentations, ref, ref2, ref3, ref4, row, sel, uid;
          presentations = [];
          presentation_by_id = {};
          presentation_by_uid = {};
          ref2 = result.rows;
          for (m = 0, len2 = ref2.length; m < len2; m++) {
            row = ref2[m];
            if (CUI.util.isEmpty(row.name)) {
              name = "Ohne Namen";
            } else {
              name = row.name.trim();
            }
            name += " [P]";
            presentation_id = row[table.key.source_name];
            presentation = {
              _basetype: "collection",
              _objects: [],
              __reference: table.source_name + ":" + presentation_id,
              __bild_ids: [],
              collection: {
                _version: 1,
                reference: table.source_name + ":" + presentation_id,
                type: "presentation",
                children_allowed: true,
                objects_allowed: true,
                displayname: {},
                webfrontend_props: {
                  presentation: {
                    slides: [
                      {
                        type: "start",
                        data: {
                          title: name,
                          info: ""
                        }
                      }
                    ],
                    settings: {
                      show_info: "no-info"
                    }
                  }
                }
              }
            };
            presentation.collection.displayname[_this.__settings.target_lang] = name;
            owner = row.easydb_owner;
            if (owner != null ? owner.startsWith("user_") : void 0) {
              ref = user_table.source_name + ":" + login_column + ":" + owner.substr(5);
              if (!_this.__info.user_by_ref[ref]) {
                colref = ez5.session.user.getCollectionReference();
                _this.logwarn("User of private presentation '" + name + "' not found: " + ref + " setting user to: " + colref);
              } else {
                colref = "user:ref:" + ref;
                collection_user_refs.push(ref);
              }
            } else {
              _this.logwarn("No easydb_owner found for collection, using migration user: " + name);
              colref = ez5.session.user.getCollectionReference();
            }
            presentation.collection["lookup:_id_parent"] = {
              reference: colref
            };
            uid = colref + name;
            if (presentation_by_uid[uid]) {
              presentation.collection.displayname[_this.__settings.target_lang] = name + " (" + presentation_by_uid[uid] + ")";
              presentation_by_uid[uid] += 1;
            } else {
              presentation_by_uid[uid] = 1;
            }
            presentations.push(presentation);
            presentation_by_id[presentation_id] = presentation;
          }
          missing_count = {
            bild: 0,
            presentation: []
          };
          objects_table = _this.__info.base_tables.presentation_objects;
          if ((objects_table != null ? objects_table.count : void 0) > 0) {
            if (objects_table.count === 0) {
              _this.logwarn("Skipping migration of table:", objects_table.source_name, ". No records found.");
              dfr.resolve();
              return;
            }
            ref3 = objects_table.columns;
            for (n = 0, len3 = ref3.length; n < len3; n++) {
              col = ref3[n];
              if (((ref4 = col.source_link) != null ? ref4.source_name : void 0) === _this.__info.attrs.EASYDB_DEFAULT_TABLE) {
                bild_col = col;
                bild_mapping = _this.getTargetColumn(col.source_link.source_name, col.source_link.key.source_name);
                break;
              }
            }
            if (!bild_col || !bild_mapping) {
              console.error("Cannot find link field for EASYDB_DEFAULT_TABLE:", bild_col, objects_table);
              dfr.reject("Cannot find link field for EASYDB_DEFAULT_TABLE in export_presentations.");
              return;
            }
            sel = 'SELECT "' + objects_table.uplink.source_name + '" AS from_id, "' + bild_col.source_name + '" AS to_id, position FROM ' + _this.getEasydb4TableName(objects_table.source_name) + 'WHERE "' + bild_col.source_name + '" IS NOT NULL AND "' + objects_table.uplink.source_name + '"  IS NOT NULL ORDER BY "' + objects_table.key.source_name + '"';
          } else {
            bild_mapping = _this.getTargetColumn(bilder_table.source_name, bilder_table.key.source_name);
            sel = "SELECT * FROM " + _this.getEasydb4TableName("eadb_links") + " WHERE from_table_id = " + table.source_id + " AND to_table_id = " + bilder_table.source_id + " ORDER BY from_id, id";
          }
          return _this.query(sel).fail(dfr.reject).done(function(result) {
            var bild_id, co, co_p, filled_slides, len4, len5, len6, lobj, o, p, r, ref5, ref6, side, slide, slide_idx, slides;
            ref5 = result.rows;
            for (o = 0, len4 = ref5.length; o < len4; o++) {
              row = ref5[o];
              presentation_id = row.from_id;
              bild_id = row.to_id;
              presentation = presentation_by_id[presentation_id];
              if (!presentation) {
                CUI.util.pushOntoArray(presentation_id, missing_count.presentation);
                continue;
              }
              slides = presentation.collection.webfrontend_props.presentation.slides;
              if (bild_id < Math.pow(10, 10)) {
                if (_this.__settings.limit_collections && indexOf.call(object_ids_per_table[bilder_table.real_source_name], bild_id) < 0) {
                  missing_count.bild = missing_count.bild + 1;
                  continue;
                }
                lobj = {
                  _objecttype: bild_mapping.table.name
                };
                lobj[bild_mapping.column.name] = bilder_table.real_source_name + ":" + bild_id;
                co = {
                  "lookup:_global_object_id": lobj
                };
                co_p = {
                  "lookup:global_object_id": lobj
                };
              } else {
                co = {
                  _global_object_id: bild_id + "@easydb4"
                };
                co_p = {
                  global_object_id: co._global_object_id
                };
              }
              slide_idx = Math.floor(row.position / 2) + 1;
              if (row.position % 2 === 0) {
                side = "left";
              } else {
                side = "right";
              }
              slide = slides[slide_idx];
              if (!slide) {
                slide = slides[slide_idx] = {
                  type: "one",
                  _side: side,
                  center: co_p
                };
              } else {
                if (slide.center) {
                  slide[slide._side] = slide.center;
                  delete slide.center;
                  slide.type = "two";
                }
                if (slide[side]) {
                  console.error("Side ", side, "already occupied.", slide);
                } else {
                  slide[side] = co_p;
                }
              }
              if (indexOf.call(presentation.__bild_ids, bild_id) >= 0) {
                continue;
              }
              presentation.__bild_ids.push(bild_id);
              presentation._objects.push(co);
            }
            if (missing_count.bild > 0) {
              _this.logwarn("Presentation Objects not found:", missing_count.bild);
            }
            if (missing_count.presentation.length > 0) {
              _this.logwarn("Presentations not found:", missing_count.presentation.length);
            }
            for (p = 0, len5 = presentations.length; p < len5; p++) {
              presentation = presentations[p];
              filled_slides = [];
              ref6 = presentation.collection.webfrontend_props.presentation.slides;
              for (r = 0, len6 = ref6.length; r < len6; r++) {
                slide = ref6[r];
                if (!slide) {
                  continue;
                }
                delete slide._side;
                filled_slides.push(slide);
              }
              presentation.collection.webfrontend_props.presentation.slides = filled_slides;
            }
            return payload_split("basetype_presentation.json", 500, {
              import_type: "collection",
              collections: presentations
            }).fail(dfr.reject).done(dfr.resolve);
          });
        });
        return dfr.promise();
      };
    })(this);
    table_idx = -1;
    export_next_object_table = (function(_this) {
      return function(dfr) {
        var table;
        if (dfr == null) {
          dfr = new CUI.Deferred();
        }
        table_idx++;
        if (table_idx === _this.__info.tables.length) {
          dfr.resolve();
          return dfr.promise();
        }
        table = _this.__info.tables[table_idx];
        if (!table.internal && !table.target_editlink) {
          export_object_table(table).fail(dfr.reject).done(function() {
            return export_next_object_table(dfr);
          });
        } else {
          export_next_object_table(dfr);
        }
        return dfr.promise();
      };
    })(this);
    object_ids_per_table = {};
    export_object_table = (function(_this) {
      return function(table) {
        var chunk_size, fake_arr, len2, limited, m, main_tables, ref2, ref3, splash_text, t, tb_mapping;
        splash_text = table.source_name;
        ez5.splash.show("easydb4migration.progress", {
          payload: splash_text
        });
        tb_mapping = _this.__mapping.source_table[table.source_name];
        if (!(tb_mapping != null ? tb_mapping.target_table_name : void 0)) {
          _this.logwarn("Skipping migration of table:", table.source_name, ". No mapping defined.");
          return CUI.resolvedPromise();
        }
        if (table.count === 0) {
          _this.logwarn("Skipping migration of table:", table.source_name, ". No records found.");
          return CUI.resolvedPromise();
        }
        fake_arr = [];
        main_tables = [_this.__info.attrs.EASYDB_DEFAULT_TABLE];
        ref2 = _this.__info.tables;
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          t = ref2[m];
          if (t.pool) {
            main_tables.push(t.source_name);
          }
        }
        if (ref3 = table.source_name, indexOf.call(main_tables, ref3) >= 0) {
          limited = true;
          if (_this.__settings.limit_main_tables > 0) {
            chunk_size = _this.__settings.limit_main_tables;
            fake_arr[chunk_size - 1] = true;
          } else {
            chunk_size = 1000;
            fake_arr[table.count - 1] = true;
          }
        } else {
          limited = true;
          chunk_size = 10000;
          fake_arr[table.count - 1] = true;
        }
        object_ids_per_table[table.real_source_name] = [];
        return CUI.chunkWork.call(_this, {
          items: fake_arr,
          chunk_size: chunk_size,
          call: function(fake_items, offset, len) {
            var dfr, limit, range;
            limit = fake_items.length;
            if (limited) {
              range = (offset + 1) + "-" + Math.min(limit + offset, len);
            } else {
              range = "";
            }
            dfr = new CUI.Deferred();
            get_objects_for_table(table, offset, limit).fail(dfr.reject).done(function(objects) {
              var _upd_obj, deferred_sources, depth, filename, find_deferred, found, init_json, json, k, len3, len4, lobj, n, o, obj, obj2, payloads, ref4, ref5, ref6, ref7, ref_target, tb, upd_obj, update_json, v;
              payloads = [];
              init_json = function() {
                return {
                  import_type: "db",
                  objecttype: tb_mapping.target_table_name,
                  objects: []
                };
              };
              json = init_json();
              for (idx = n = 0, len3 = objects.length; n < len3; idx = ++n) {
                obj = objects[idx];
                object_ids_per_table[table.real_source_name].push(obj.__key);
                obj2 = {};
                obj2._objecttype = tb_mapping.target_table_name;
                obj2._mask = "_all_fields";
                obj._version = 1;
                _this.mergeTopLevel(obj2, obj);
                json.objects.push(obj2);
                if (idx < objects.length - 1 && obj2._depth !== objects[idx + 1]["top:_depth"]) {
                  payloads.push(payload(table.source_name + "-level-" + obj2._depth + (range ? "-" + range : "") + ".json", json));
                  json = init_json();
                }
              }
              if (((ref4 = json.objects[0]) != null ? ref4._depth : void 0) !== void 0) {
                depth = "-level-" + json.objects[0]._depth;
              } else {
                depth = "";
              }
              deferred_sources = (function() {
                var len4, o, ref5, results;
                ref5 = this.__info.deferred_tables || [];
                results = [];
                for (o = 0, len4 = ref5.length; o < len4; o++) {
                  tb = ref5[o];
                  results.push(tb.source_name);
                }
                return results;
              }).call(_this);
              deferred_sources.push(table.target_name);
              find_deferred = function(obj, found) {
                var _obj, col_name, k, len4, o, v;
                if (found == null) {
                  found = [];
                }
                for (k in obj) {
                  v = obj[k];
                  if (k.endsWith(":source_name") && indexOf.call(deferred_sources, v) >= 0) {
                    col_name = k.substr(0, k.length - ":source_name".length);
                    found.push(col_name);
                  } else if (CUI.isArray(v)) {
                    for (o = 0, len4 = v.length; o < len4; o++) {
                      _obj = v[o];
                      find_deferred(_obj, found);
                    }
                  } else if (CUI.isPlainObject(v)) {
                    find_deferred(v, found);
                  }
                }
                return found;
              };
              ref_target = _this.getTargetColumn(table.source_name, table.key.source_name);
              update_json = init_json();
              ref5 = json.objects;
              for (o = 0, len4 = ref5.length; o < len4; o++) {
                obj = ref5[o];
                found = find_deferred(obj);
                if (found.length === 0) {
                  continue;
                }
                upd_obj = CUI.util.copyObject(obj, true);
                _upd_obj = upd_obj[upd_obj._objecttype];
                lobj = {};
                lobj[ref_target.column.name] = _upd_obj[ref_target.column.name];
                _upd_obj._version = _upd_obj._version + 1;
                _upd_obj["lookup:_id"] = lobj;
                update_json.objects.push(upd_obj);
                ref6 = obj[obj._objecttype];
                for (k in ref6) {
                  v = ref6[k];
                  if (indexOf.call(found, k) >= 0) {
                    delete obj[obj._objecttype][k];
                    delete obj[obj._objecttype][k + ":source_name"];
                  }
                  if (v != null ? (ref7 = v[0]) != null ? ref7["eas:url"] : void 0 : void 0) {
                    delete obj[obj._objecttype][k];
                  }
                  if (k.startsWith("_nested:")) {
                    delete obj[obj._objecttype][k];
                  }
                }
              }
              filename = table.source_name + depth + (range ? "-" + range : "") + ".json";
              payloads.push(payload(filename, json));
              if (update_json.objects.length > 0) {
                payloads.push(update_payload("update-" + filename, update_json));
              }
              return CUI.when(payloads).done(function() {
                _this.loginfo("Exported: " + table.source_name + ": " + ((range && range + "/" + len) || objects.length));
                return dfr.resolve();
              }).fail(dfr.reject);
            });
            return dfr.promise();
          }
        });
      };
    })(this);
    prepare_tables = (function(_this) {
      return function() {
        var _col, col, dfr, fn, len2, len3, len4, len5, len6, len7, m, n, nested_table, o, objects_by_table, p, parent_mapping, parent_table, promises, r, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, table, table_schema, target, target_col, tb_mapping, u;
        dfr = new CUI.Deferred();
        ref2 = _this.__info.tables;
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          nested_table = ref2[m];
          if (nested_table.internal) {
            continue;
          }
          tb_mapping = _this.__mapping.source_table[nested_table.source_name];
          table_schema = _this.getTableByName(tb_mapping != null ? tb_mapping.target_table_name : void 0);
          if (!(table_schema != null ? table_schema.owned_by : void 0)) {
            continue;
          }
          nested_table.target_editlink = true;
          ref3 = _this.__info.tables;
          for (n = 0, len3 = ref3.length; n < len3; n++) {
            table = ref3[n];
            parent_mapping = _this.__mapping.source_table[table.source_name];
            if (table_schema.owned_by.other_table_name_hint === (parent_mapping != null ? parent_mapping.target_table_name : void 0)) {
              parent_table = table;
              break;
            }
          }
          if (!parent_table) {
            dfr.reject("Target editlink: Parent table not found for nested table.", nested_table);
            return dfr.promise();
          }
          if (!parent_table._target_nested_tables) {
            parent_table._target_nested_tables = [];
          }
          ref4 = nested_table.columns;
          for (o = 0, len4 = ref4.length; o < len4; o++) {
            col = ref4[o];
            if (((ref5 = tb_mapping.source_column[col.source_name]) != null ? ref5.target_column_name : void 0) !== '__UPLINK__') {
              continue;
            }
            if (nested_table.uplink) {
              dfr.reject("Target editlink: " + table_schema.name + ": More than one uplink column found.", nested_table);
              return dfr.promise();
            }
            nested_table.uplink = col;
          }
          if (!nested_table.uplink) {
            dfr.reject("Target editlink: " + table_schema.name + ": No uplink column found.", table);
            return dfr.promise();
          }
          parent_table._target_nested_tables.push(nested_table);
        }
        promises = [];
        objects_by_table = {};
        ref6 = _this.__info.tables;
        for (p = 0, len5 = ref6.length; p < len5; p++) {
          table = ref6[p];
          ref7 = table.columns;
          fn = function(target) {
            var promise;
            promise = _this.query('SELECT DISTINCT TRIM("' + col.real_source_name + '") FROM ' + _this.getEasydb4TableName(table.real_source_name)).done(function(result) {
              var len7, ref8, results, row, u;
              if (result.rows.length === 0) {
                return;
              }
              ref8 = result.rows;
              results = [];
              for (u = 0, len7 = ref8.length; u < len7; u++) {
                row = ref8[u];
                results.push(CUI.util.pushOntoArray(row[0], objects_by_table[target.other_table.name].values));
              }
              return results;
            });
            return promises.push(promise);
          };
          for (r = 0, len6 = ref7.length; r < len6; r++) {
            col = ref7[r];
            if ((ref8 = col.source_type) !== "blob" && ref8 !== "text" && ref8 !== "integer") {
              continue;
            }
            target = _this.getTargetColumn(table.source_name, col.source_name);
            if ((target != null ? target.column.type : void 0) !== "link") {
              continue;
            }
            ref9 = target.other_table.columns;
            for (u = 0, len7 = ref9.length; u < len7; u++) {
              _col = ref9[u];
              if (col.source_name.startsWith("easydb_")) {
                continue;
              }
              if (_col.type === "text" || _col.type === "text_oneline" || _col.type === "text_l10n_oneline" || _col.type === "text_l10n") {
                target_col = _col;
                break;
              }
            }
            if (!target_col) {
              _this.logwarn("text/int > linked object [text] conversion, no target column found.", target);
              continue;
            }
            _this.loginfo("text/int > linked object conversion:" + table.source_name + "." + col.source_name + "[" + col.source_type + "] > " + table.real_source_name + "." + target_col.name + "[" + target_col.type + "]");
            target.other_column = target_col;
            _this.__mapping.source_table[table.source_name].source_column[col.source_name].target = target;
            if (!objects_by_table[target.other_table.name]) {
              objects_by_table[target.other_table.name] = {
                target_column: target_col,
                values: []
              };
            }
            fn(target);
          }
        }
        dfr = new CUI.Deferred();
        CUI.when(promises).fail(dfr.reject).done(function() {
          var info, len8, more_promises, obj, obj2, objects, promise, ref10, target_table_name, value, x;
          more_promises = [];
          for (target_table_name in objects_by_table) {
            info = objects_by_table[target_table_name];
            if (info.values.length === 0) {
              continue;
            }
            objects = [];
            ref10 = info.values;
            for (x = 0, len8 = ref10.length; x < len8; x++) {
              value = ref10[x];
              if (CUI.util.isEmpty(value)) {
                continue;
              }
              obj = {
                _version: 1
              };
              obj[info.target_column.name] = value;
              obj2 = {
                _mask: "_all_fields",
                _objecttype: target_table_name
              };
              obj2[obj2._objecttype] = obj;
              objects.push(obj2);
            }
            promise = payload(target_table_name + "-text-to-linked-objects.json", {
              import_type: "db",
              objecttype: target_table_name,
              objects: objects
            });
            more_promises.push(promise);
          }
          return CUI.when(more_promises).fail(dfr.reject).done(dfr.resolve);
        });
        return dfr.promise();
      };
    })(this);
    get_objects_for_table = (function(_this) {
      return function(table, offset, limit, where) {
        var dfr, fk_father_id, off_limit, splash_text, sql, sqlWhere, tb_mapping, tn;
        if (offset == null) {
          offset = 0;
        }
        if (limit == null) {
          limit = 0;
        }
        if (where == null) {
          where = "";
        }
        splash_text = table.source_name + " " + (offset + 1) + "-" + Math.min(table.count, offset + limit) + "/" + table.count;
        ez5.splash.show("easydb4migration.progress", {
          payload: splash_text
        });
        tb_mapping = _this.__mapping.source_table[table.source_name];
        dfr = new CUI.Deferred();
        if (limit > 0) {
          off_limit = "LIMIT " + limit;
        } else {
          off_limit = "LIMIT -1";
        }
        off_limit += " OFFSET " + offset;
        if (table.parent) {
          fk_father_id = '"' + table.parent.real_source_name + '"';
          tn = _this.getEasydb4TableName(table.real_source_name);
          sql = "WITH RECURSIVE ids AS (\n    SELECT id, 0 as level\n    FROM " + tn + " WHERE" + fk_father_id + " IS NULL\n\nUNION ALL\n\nSELECT a.id, ids.level + 1\nFROM " + tn + " a\nJOIN ids ON (a." + fk_father_id + " = ids.id)\n)\nSELECT level as _depth, b.* -- level, s.id, s.fk_father_id\nFROM ids\nJOIN " + tn + " b USING (id)\nORDER BY ids.level, id " + off_limit;
        } else {
          if (where.length > 0) {
            sqlWhere = table.where || "";
            if (sqlWhere.length > 0) {
              sqlWhere += " AND (" + where + ")";
            } else {
              sqlWhere = "WHERE " + where;
            }
          } else {
            sqlWhere = table.where || "";
          }
          sql = "SELECT * FROM " + _this.getEasydb4TableName(table.real_source_name) + " " + sqlWhere + " ORDER BY \"" + table.key.source_name + "\" " + off_limit;
        }
        _this.query(sql).fail(dfr.reject).done(function(result) {
          var changelog_by_id, export_table, map_changelog;
          changelog_by_id = {};
          map_changelog = _this.getTargetColumn(table.source_name, "__changelog__");
          export_table = function() {
            var calls, fn, len2, len3, len4, m, n, nested_table, nested_tables, nt, o, obj, obj_by_id, objects, ref2, ref3, row;
            objects = [];
            obj_by_id = {};
            ref2 = result.rows;
            for (m = 0, len2 = ref2.length; m < len2; m++) {
              row = ref2[m];
              if (map_changelog) {
                row.__changelog__ = JSON.stringify({
                  entries: changelog_by_id[row[table.key.source_name]] || []
                });
              }
              obj = _this.mapObject(row, table, obj_by_id);
              objects.push(obj);
            }
            calls = [];
            nested_tables = table._nested_tables.slice(0);
            if (table._target_nested_tables) {
              ref3 = table._target_nested_tables;
              for (n = 0, len3 = ref3.length; n < len3; n++) {
                nt = ref3[n];
                nested_tables.push(nt);
              }
            }
            fn = function(nested_table) {
              var target_mapping, target_table_name;
              target_mapping = _this.__mapping.source_table[nested_table.source_name];
              target_table_name = target_mapping != null ? target_mapping.target_table_name : void 0;
              if (!target_table_name) {
                _this.logwarn("Skipping nested table: '" + nested_table.source_name + "'. No mapping defined.");
                return;
              }
              return calls.push(function() {
                var _nested_table, _target_mapping, _target_table_name, dfr3, eadb_link_infos, len5, p, promise, promises, sel;
                if (splash_text) {
                  ez5.splash.show("easydb4migration.progress", {
                    payload: splash_text + " -- " + nested_table.real_source_name
                  });
                }
                eadb_link_infos = [];
                promises = [];
                for (p = 0, len5 = nested_tables.length; p < len5; p++) {
                  _nested_table = nested_tables[p];
                  if (!_nested_table.merge_with_table) {
                    continue;
                  }
                  _target_mapping = _this.__mapping.source_table[_nested_table.source_name];
                  _target_table_name = _target_mapping != null ? _target_mapping.target_table_name : void 0;
                  if (target_table_name !== _target_table_name) {
                    continue;
                  }
                  if (!_target_table_name) {
                    _this.logwarn("Skipped merging nested table: '" + _nested_table.source_name + "' . No mapping defined.");
                    continue;
                  }
                  sel = 'SELECT id, from_id, to_id, remark FROM ' + _this.getEasydb4TableName("eadb_links") + ' WHERE ' + 'from_table_id=' + _nested_table.eadb_links_from_table_id + ' AND ' + 'to_table_id=' + _nested_table.eadb_links_to_table_id + ' ORDER BY position ';
                  promise = _this.query(sel).done(function(result) {
                    var len6, r, ref4;
                    ref4 = result.rows;
                    for (r = 0, len6 = ref4.length; r < len6; r++) {
                      row = ref4[r];
                      eadb_link_infos.push(row);
                    }
                  });
                  promises.push(promise);
                }
                dfr3 = new CUI.Deferred();
                CUI.when(promises).fail(dfr3.reject).done(function() {
                  if (Object.keys(obj_by_id).length > 0) {
                    where = '"' + nested_table.uplink.source_name + '" IN (' + Object.keys(obj_by_id).join(',') + ')';
                  }
                  return get_objects_for_table(nested_table, void 0, void 0, where).done(function(nested_objects) {
                    var eadb_link_info, len6, len7, len8, nested_object, nk, obj2, obj_id, r, u, x;
                    nk = "_nested:" + target_table_name;
                    for (r = 0, len6 = nested_objects.length; r < len6; r++) {
                      nested_object = nested_objects[r];
                      obj_id = nested_object[nested_table.uplink.source_name];
                      obj = obj_by_id[obj_id];
                      if (!obj) {
                        continue;
                      }
                      obj2 = CUI.util.copyObject(nested_object, true);
                      delete obj2[nested_table.uplink.source_name];
                      if (!obj[nk]) {
                        obj[nk] = [];
                      }
                      _this.pushOntoArray(obj2, obj[nk]);
                    }
                    for (u = 0, len7 = nested_objects.length; u < len7; u++) {
                      nested_object = nested_objects[u];
                      for (x = 0, len8 = eadb_link_infos.length; x < len8; x++) {
                        eadb_link_info = eadb_link_infos[x];
                        if (eadb_link_info.to_id !== nested_object.__key) {
                          continue;
                        }
                        obj = obj_by_id[eadb_link_info.from_id];
                        if (!obj) {
                          continue;
                        }
                        obj2 = CUI.util.copyObject(nested_object, true);
                        delete obj2[nested_table.uplink.source_name];
                        if (!obj[nk]) {
                          obj[nk] = [];
                        }
                        obj2.__eadb_links_id = eadb_link_info.id;
                        obj2.__eadb_links_remark = eadb_link_info.remark;
                        if (CUI.util.idxInArray(null, obj[nk], function(_obj2) {
                          return _obj2.__key === obj2.__key;
                        }) === -1) {
                          _this.pushOntoArray(obj2, obj[nk]);
                        }
                      }
                    }
                  }).fail(dfr3.reject).done(dfr3.resolve);
                });
                return dfr3.promise();
              });
            };
            for (o = 0, len4 = nested_tables.length; o < len4; o++) {
              nested_table = nested_tables[o];
              if (nested_table === table) {
                dfr.reject("Nested table same as parent table.");
                return;
              }
              if (nested_table.eadb_links) {
                if (nested_table.merge_with_table) {
                  continue;
                }
                (function(nested_table) {
                  var nk, remark_target, to_id_target;
                  to_id_target = _this.getTargetColumn(nested_table.source_name, "to_id");
                  remark_target = _this.getTargetColumn(nested_table.source_name, "remark");
                  if (!to_id_target) {
                    _this.logwarn("Skipping: " + nested_table.source_name + ". No mapping defined.");
                    return;
                  }
                  nk = "_nested:" + to_id_target.table.name;
                  return calls.push(function() {
                    var dfr2, get_target_ids;
                    dfr2 = new CUI.Deferred();
                    if (splash_text) {
                      ez5.splash.show("easydb4migration.progress", {
                        payload: splash_text + " -- " + nested_table.target_table.real_source_name
                      });
                    }
                    get_target_ids = function(tb) {
                      var sel;
                      if (object_ids_per_table[tb.real_source_name]) {
                        return CUI.resolvedPromise(object_ids_per_table[tb.real_source_name]);
                      }
                      sel = 'SELECT "' + tb.key.real_source_name + '" FROM ' + _this.getEasydb4TableName(tb.real_source_name);
                      return _this.query(sel).done(function(result) {
                        var len5, p, ref4;
                        object_ids_per_table[tb.real_source_name] = [];
                        ref4 = result.rows;
                        for (p = 0, len5 = ref4.length; p < len5; p++) {
                          row = ref4[p];
                          object_ids_per_table[tb.real_source_name].push(row[0]);
                        }
                        return console.debug("Getting ids: " + tb.real_source_name + ": " + result.rows.length);
                      });
                    };
                    get_target_ids(nested_table.target_table).fail(dfr2.reject).done(function() {
                      var sel2, target_ids;
                      target_ids = object_ids_per_table[nested_table.target_table.real_source_name];
                      sel2 = 'SELECT * FROM ' + _this.getEasydb4TableName("eadb_links") + ' WHERE from_id IS NOT NULL ' + ' AND to_id IS NOT NULL ' + ' AND from_table_id = ' + nested_table.owned_by.source_id + ' AND to_table_id = ' + nested_table.target_table.source_id;
                      return _this.query(sel2).fail(dfr2.reject).done(function(result) {
                        var len5, lobj, lobj2, obj2, p, ref4, ref5, target;
                        ref4 = result.rows;
                        for (p = 0, len5 = ref4.length; p < len5; p++) {
                          row = ref4[p];
                          obj = obj_by_id[row.from_id];
                          if (!obj) {
                            continue;
                          }
                          target = _this.getTargetColumn(nested_table.target_table.source_name, nested_table.target_table.key.source_name);
                          if (!target) {
                            _this.logwarn("Target not found for: " + nested_table.target_table.source_name + " using standard  mapping.");
                            target = {
                              column: {
                                name: "__not_mapped"
                              },
                              table: {
                                name: nested_table.target_table.target_name
                              }
                            };
                          }
                          if ((ref5 = row.to_id, indexOf.call(target_ids, ref5) < 0) && nested_table.owned_by.source_id !== nested_table.target_table.source_id) {
                            _this.loginfo("eadb_links: " + nested_table.owned_by.source_name + "[" + row.from_id + "] -> " + nested_table.target_table.source_name + "[" + row.to_id + "] is missing, not exporting.");
                            continue;
                          }
                          obj2 = {};
                          lobj = {};
                          lobj["lookup:_id"] = {};
                          lobj["lookup:_id"][target.column.name] = _this.getEasydb4ReferencePrefix(target.column.name, nested_table.target_table.source_name) + row.to_id;
                          lobj2 = {};
                          lobj2 = {
                            _objecttype: target.table.name,
                            _mask: "_all_fields"
                          };
                          lobj2[lobj2._objecttype] = lobj;
                          if (remark_target != null ? remark_target.column : void 0) {
                            obj2[remark_target != null ? remark_target.column.name : void 0] = row.remark;
                          }
                          if (to_id_target != null ? to_id_target.column : void 0) {
                            obj2[to_id_target != null ? to_id_target.column.name : void 0] = lobj2;
                            obj2[(to_id_target != null ? to_id_target.column.name : void 0) + ":source_name"] = lobj2._objecttype;
                          }
                          if (!obj[nk]) {
                            obj[nk] = [];
                          }
                          _this.pushOntoArray(obj2, obj[nk]);
                        }
                        dfr2.resolve();
                      });
                    });
                    return dfr2.promise();
                  });
                })(nested_table);
                continue;
              }
              fn(nested_table);
            }
            return CUI.chainedCall.apply(null, calls).fail(dfr.reject).done(function() {
              return _this.postProcessGNDForTable(objects).fail(dfr.reject).done(function() {
                return _this.postProcessGazetteerForTable(objects).fail(dfr.reject).done(function() {
                  return _this.postProcessGettyForTable(objects).fail(dfr.reject).done(function() {
                    return dfr.resolve(objects);
                  });
                });
              });
            });
          };
          if (!map_changelog) {
            export_table();
          } else {
            _this.query("SELECT * FROM " + _this.getEasydb4TableName("eadb_changelog") + " WHERE table_id = " + table.source_id + " ORDER BY id").fail(dfr.reject).done(function(changelog_result) {
              var change_row, k, len2, len3, log_entry, m, n, ref2, ref3;
              ref2 = changelog_result.rows;
              for (idx = m = 0, len2 = ref2.length; m < len2; idx = ++m) {
                change_row = ref2[idx];
                log_entry = {};
                ref3 = ["id", "zeitpunkt", "log_entry", "user_login", "user_name", "client_ip"];
                for (n = 0, len3 = ref3.length; n < len3; n++) {
                  k = ref3[n];
                  log_entry[k] = change_row[k];
                }
                if (!changelog_by_id[change_row.key_id]) {
                  changelog_by_id[change_row.key_id] = [];
                }
                changelog_by_id[change_row.key_id].push(log_entry);
              }
              return export_table();
            });
          }
        });
        return dfr.promise();
      };
    })(this);
    this.__eas_urls_by_id = {};
    get_eas_ids = (function(_this) {
      return function() {
        if (!_this.__settings.eas_version) {
          return CUI.resolvedPromise();
        }
        ez5.splash.show("easydb4migration.progress", {
          payload: "getting eas ids"
        });
        return _this.query("SELECT eas_id, file_version, url, original_filename FROM file a LEFT JOIN filestore b\nON (b.filestore_id = a.filestore_id)").done(function(result) {
          var len2, m, ref2, results, row;
          ref2 = result.rows;
          results = [];
          for (m = 0, len2 = ref2.length; m < len2; m++) {
            row = ref2[m];
            if (!_this.__eas_urls_by_id[row.eas_id]) {
              _this.__eas_urls_by_id[row.eas_id] = {
                original_filename: row.original_filename
              };
            }
            if (_this.__settings.eas_version !== "original" && row.file_version === "original") {
              _this.__eas_urls_by_id[row.eas_id]._original = row.url;
            }
            if (row.file_version === _this.__settings.eas_version) {
              _this.__eas_urls_by_id[row.eas_id].original = row.url;
            }
            if (row.file_version === _this.__info.min_eas_version) {
              results.push(_this.__eas_urls_by_id[row.eas_id].preview_url = row.url);
            } else {
              results.push(void 0);
            }
          }
          return results;
        });
      };
    })(this);
    if (this.__settings.export_tool) {
      ref2 = this.__tools;
      for (m = 0, len2 = ref2.length; m < len2; m++) {
        tool = ref2[m];
        if (tool.name() === this.__settings.export_tool) {
          tool.run(payload).fail(master_dfr.reject).done(master_dfr.resolve);
        }
        break;
      }
    } else {
      go_on = (function(_this) {
        return function() {
          get_eas_ids().fail(master_dfr.reject).done(function() {
            return export_groups().fail(master_dfr.reject).done(function() {
              return export_users().fail(master_dfr.reject).done(function() {
                return export_pools().fail(master_dfr.reject).done(function() {
                  return export_tags().fail(master_dfr.reject).done(function() {
                    return prepare_tables().fail(master_dfr.reject).done(function() {
                      return export_next_object_table().fail(master_dfr.reject).done(function() {
                        return export_collections().fail(master_dfr.reject).done(function() {
                          return export_presentations().fail(master_dfr.reject).done(function() {
                            return send_ldap_sso_users().fail(master_dfr.reject).done(master_dfr.resolve);
                          });
                        });
                      });
                    });
                  });
                });
              });
            });
          });
        };
      })(this);
      if (this.__settings.post_process_plugin) {
        plugin = this.__plugin_by_name[this.__settings.post_process_plugin];
        CUI.decide(plugin.init()).done(go_on).fail(master_dfr.reject);
      } else {
        go_on();
      }
    }
    return master_dfr2.promise();
  };

  Easydb4Migration.prototype.pushOntoArray = function(value, arr) {
    var item, j, len1, value_s;
    value_s = JSON.stringify(value);
    for (j = 0, len1 = arr.length; j < len1; j++) {
      item = arr[j];
      if (JSON.stringify(item) === value_s) {
        this.logwarn("Skipping duplicate nested entry: " + value_s);
        return false;
      }
    }
    arr.push(value);
    return true;
  };

  Easydb4Migration.prototype.__collectRefs = function(key, obj, parent_key, parent_obj, objs) {
    var item, j, k, len1, v;
    if (objs == null) {
      objs = null;
    }
    if (objs === null) {
      objs = [];
    }
    if (CUI.util.isArray(obj)) {
      for (j = 0, len1 = obj.length; j < len1; j++) {
        item = obj[j];
        this.__collectRefs(key, item, null, null, objs);
      }
    }
    if (CUI.util.isPlainObject(obj)) {
      for (k in obj) {
        v = obj[k];
        if (k === key) {
          objs.push({
            obj: parent_obj,
            key: parent_key
          });
        } else {
          this.__collectRefs(key, v, k, obj, objs);
        }
      }
    }
    return objs;
  };

  Easydb4Migration.ID_API_URL = Easydb4Migration.JSON_EXTENSION = ".json";

  Easydb4Migration.prototype.postProcessGazetteerForTable = function(objects) {
    var chunkSize, dfr, gazetteer_objs;
    gazetteer_objs = this.__collectRefs("__gazetteer", objects);
    if (gazetteer_objs.length === 0) {
      return CUI.resolvedPromise();
    }
    dfr = new CUI.Deferred();
    console.debug("Gazetteer search process started. " + gazetteer_objs.length + " gazetteer objects.");
    chunkSize = 10;
    CUI.chunkWork.call(this, {
      items: gazetteer_objs,
      chunk_size: 10,
      call: function(items, offset) {
        var item, j, len1, message, object, offsetPlusChunk, progressString, promises;
        offsetPlusChunk = offset + chunkSize;
        if (offsetPlusChunk > gazetteer_objs.length) {
          offsetPlusChunk = gazetteer_objs.length;
        }
        progressString = (offset + 1) + "-" + offsetPlusChunk + " / " + gazetteer_objs.length;
        message = "Searching Gazetteer data. Progress: " + progressString;
        ez5.splash.show("easydb4migration.progress", {
          payload: message
        });
        console.debug(message);
        promises = [];
        for (j = 0, len1 = items.length; j < len1; j++) {
          item = items[j];
          object = item.obj[item.key];
          promises.push(this.__findAndAddGazetteerDataById(object));
        }
        return CUI.whenAll(promises);
      }
    }).always((function(_this) {
      return function() {
        console.debug("Gazetteer search process finished.");
        return dfr.resolve();
      };
    })(this));
    return dfr.promise();
  };

  Easydb4Migration.prototype.__findAndAddGazetteerDataById = function(object) {
    var deferred, gazId, xhr;
    deferred = new CUI.Deferred();
    gazId = object.__gazetteer.gazId;
    delete object.__gazetteer;
    object.gazId = gazId;
    xhr = new CUI.XHR({
      method: "GET",
      url: "https://gazetteer.dainst.org/doc/" + gazId + ".json"
    });
    xhr.start().done((function(_this) {
      return function(data) {
        var fulltext, position, ref1, ref2, ref3, ref4;
        if (!data) {
          console.warn("Empty response data for Gazetteer object.", gazId);
          return deferred.resolve();
        }
        object.displayName = data.prefName.title;
        object.otherNames = data.names;
        fulltext = object.displayName;
        if (((ref1 = object.otherNames) != null ? ref1.length : void 0) > 0) {
          fulltext = object.otherNames.map(function(otherName) {
            return otherName.title;
          }).concat(fulltext);
        }
        object._fulltext = {
          text: fulltext,
          string: object.gazId
        };
        object._standard = {
          text: object.displayName
        };
        if ((ref2 = data.prefLocation) != null ? ref2.coordinates : void 0) {
          position = {
            lng: (ref3 = data.prefLocation) != null ? ref3.coordinates[0] : void 0,
            lat: (ref4 = data.prefLocation) != null ? ref4.coordinates[1] : void 0
          };
          if (CUI.Map.isValidPosition(position)) {
            object.position = position;
          }
        }
        return deferred.resolve();
      };
    })(this)).fail((function(_this) {
      return function(err) {
        _this.logwarn("Not possible to retrieve the Gazetteer data. ID: " + gazId);
        object._fulltext = {
          text: "Gazetteer " + gazId + " not found."
        };
        return deferred.resolve();
      };
    })(this));
    return deferred.promise();
  };

  Easydb4Migration.prototype.__processGetty = function(objects, type) {
    var getty, getty_objs, gobj, ids, j, len1, q, sel, sel0;
    getty_objs = this.__collectRefs("__" + type, objects);
    if (getty_objs.length === 0) {
      return CUI.resolvedPromise();
    }
    ids = [];
    for (j = 0, len1 = getty_objs.length; j < len1; j++) {
      gobj = getty_objs[j];
      getty = gobj.obj[gobj.key]["__" + type];
      ids.push(getty.value);
    }
    switch (type) {
      case "getty_subject":
        sel0 = 'SELECT id, getty_subject_id, 0 as getty_term_id, easydb_getty_term_preferred_text as term FROM ' + this.getEasydb4TableName("getty_subject") + ' WHERE id';
        break;
      case "getty_term":
        sel0 = 'SELECT a.id, b.getty_subject_id, a.getty_term_id, term_text as term FROM ' + this.getEasydb4TableName("getty_term") + ' a LEFT JOIN ' + this.getEasydb4TableName("getty_subject") + ' b ON (b.id = a.lk_getty_subject_id) WHERE a.id';
        break;
      default:
        this.logerror("Unknown __processGetty type: " + type);
        return CUI.rejectedPromise();
    }
    sel = sel0 + ' IN (' + ids.join(",") + ')';
    console.debug("select:", sel0);
    q = this.query(sel);
    q.done((function(_this) {
      return function(result) {
        var entry, getty_entries, k, len2, len3, m, n, ref1, ref2, row, row_id, v;
        getty_entries = {};
        ref1 = result.rows;
        for (m = 0, len2 = ref1.length; m < len2; m++) {
          row = ref1[m];
          entry = {
            __getty_subject_id: row.getty_subject_id,
            __getty_term_id: row.getty_term_id,
            __term: row.term
          };
          getty_entries[row.id] = entry;
        }
        for (n = 0, len3 = getty_objs.length; n < len3; n++) {
          gobj = getty_objs[n];
          row_id = gobj.obj[gobj.key]["__" + type].value;
          ref2 = getty_entries[row_id];
          for (k in ref2) {
            v = ref2[k];
            gobj.obj[gobj.key][k] = v;
          }
        }
      };
    })(this));
    return q;
  };

  Easydb4Migration.prototype.postProcessGettyForTable = function(objects) {
    var dfr;
    dfr = new CUI.Deferred();
    this.__processGetty(objects, "getty_subject").fail(dfr.reject).done((function(_this) {
      return function() {
        return _this.__processGetty(objects, "getty_term").fail(dfr.reject).done(dfr.resolve);
      };
    })(this));
    return dfr.promise();
  };

  Easydb4Migration.prototype.postProcessGNDForTable = function(objects) {
    var dfr, gnd_objs, gobj, ids, j, len1, sel;
    gnd_objs = this.__collectRefs("__gnd", objects);
    if (gnd_objs.length === 0) {
      return CUI.resolvedPromise();
    }
    dfr = new CUI.Deferred();
    ids = [];
    for (j = 0, len1 = gnd_objs.length; j < len1; j++) {
      gobj = gnd_objs[j];
      ids.push(gobj.obj[gobj.key].__gnd.value);
    }
    sel = "SELECT *, COALESCE(\"800c\", \"800g\", \"800k\", \"800s\", \"800p\", '') AS conceptName FROM " + this.getEasydb4TableName("dnb_normdaten") + " WHERE id IN (" + ids.join(",") + ")";
    this.query(sel).fail(dfr.reject).done((function(_this) {
      return function(result) {
        var dnb_id, entry, gnd_entries, k, len2, len3, m, n, ref1, ref2, row, v;
        gnd_entries = {};
        ref1 = result.rows;
        for (m = 0, len2 = ref1.length; m < len2; m++) {
          row = ref1[m];
          entry = {
            conceptName: row.conceptName,
            conceptURI: "http://d-nb.info/gnd/" + row["001"]
          };
          entry._fulltext = {
            text: entry.conceptName,
            string: entry.conceptURI
          };
          gnd_entries[row.id] = entry;
        }
        for (n = 0, len3 = gnd_objs.length; n < len3; n++) {
          gobj = gnd_objs[n];
          dnb_id = gobj.obj[gobj.key].__gnd.value;
          ref2 = gnd_entries[dnb_id];
          for (k in ref2) {
            v = ref2[k];
            gobj.obj[gobj.key][k] = v;
          }
        }
        return dfr.resolve();
      };
    })(this));
    return dfr.promise();
  };

  Easydb4Migration.prototype.getTargetColumn = function(source_table_name, source_column_name) {
    var parts, ref1, target_col, target_col_name, target_column, target_schema, tb_mapping;
    tb_mapping = this.__mapping.source_table[source_table_name];
    if (!(tb_mapping != null ? tb_mapping.target_table_name : void 0)) {
      return null;
    }
    target_col = tb_mapping != null ? (ref1 = tb_mapping.source_column) != null ? ref1[source_column_name] : void 0 : void 0;
    if (!(target_col != null ? target_col.target_column_name : void 0)) {
      return null;
    }
    target_schema = this.getTableByName(tb_mapping.target_table_name);
    target_col_name = target_col != null ? target_col.target_column_name : void 0;
    if (!target_col_name) {
      return null;
    }
    parts = target_col_name.split("#");
    target_column = target_schema != null ? target_schema._column_by_name[parts[0]] : void 0;
    if (!target_column) {
      return null;
    }
    if (target_column._foreign_key) {
      return {
        table: target_schema,
        other_table: ez5.schema.CURRENT._table_by_id[target_column._foreign_key.referenced_table.table_id],
        column: target_column
      };
    } else {
      return {
        table: target_schema,
        column: target_column,
        key: parts[1]
      };
    }
  };

  Easydb4Migration.prototype.storeTextFile = function(filename, txt) {
    return new CUI.XHR({
      method: 'POST',
      url: this.getFileRootUrl() + filename,
      body: txt
    }).start();
  };

  Easydb4Migration.prototype.storeFile = function(filename, json) {
    return new CUI.XHR({
      method: 'POST',
      url: this.getFileRootUrl() + filename,
      json_data: json,
      json_pretty: true
    }).start();
  };

  return Easydb4Migration;

})(RootMenuApp);

ez5.session_ready(function() {
  ez5.rootMenu.registerApp(Easydb4Migration);
  Easydb4Migration.plugins = new CUI.PluginRegistry({
    "class": Easydb4MigrationPlugin
  });
  return Easydb4Migration.tools = new CUI.PluginRegistry({
    "class": Easydb4MigrationTool
  });
});
