{{if}}this.hasParentClass(){{then}}{{js:this.getParentClass().name/}}{{Domain*}}// ***************************************************************************************************** //
// Web API for Domain: {{js:this.name;/}}
// Generated by WarpWorks, version: v0.1
// Generated on: {{js:(new Date()).toLocaleString();/}}
// ***************************************************************************************************** //

//
// Root for {{js:this.name;/}}
//

get_{{js:this.name;/}} = function  () {
    if (!_{{js:this.name;/}})
        _{{js:this.name;/}} = new {{js:this.name;/}} (null, null, "Root", null);
    return _{{js:this.name;/}};
}

get_Domain_fromJSON = function (json) {
    var domain = get_{{js:this.name;/}}().addNew_Domain(json.name, json.desc, json.id);
    domain.fromJSON(json, null);

    // In the JSON format, references have been replaces with OIDs.
    // Now we must replace any of these OIDs with real object references again
    // (same code as on server side...)
    var oid = -1;
    var target = null;
    for (i in domain.entities) {

        var e = domain.entities[i];
        if (e.hasParentClass()) {
            oid = e.getParentClass();
            target = domain.findElementByID(oid);
            if (target)
                e.setParentClass(target);
            // Else: Assume that target is in different domain
            // TBD: Think of some kind of "lazy loading" for entities in different domains!
        }
        for (i in e.relationships) {
            var r = e.relationships[i];
            oid = r.getTargetEntity();
            target = domain.findElementByID(oid);
            if (target)
                r.setTargetEntity(target);
        }
        for (i in e.tableViews) {
            var tv = e.tableViews[i];
            for (j in tv.tableItems) {
                var ti = tv.tableItems[j];
                oid = ti.property;
                target = domain.findElementByID(oid);
                if(target)
                    ti.setProperty(target);
            }
        }
        for (i in e.pageViews) {
            var pv = e.pageViews[i];
            for (j in pv.panels) {
                var p = pv.panels[j];
                for (k in p.relationshipPanelItems) {
                    var rpi = p.relationshipPanelItems[k];
                    oid = rpi.relationship;
                    target = domain.findElementByID(oid);
                    if(target)
                        rpi.setRelationship(target);
                }
                for (l in p.basicPropertyPanelItems) {
                    var bppi = p.basicPropertyPanelItems[l];
                    oid = bppi.basicProperty;
                    target = domain.findElementByID(oid);
                    if (target)
                        bppi.setBasicProperty(target);
                }
                for (m in p.enumPanelItems) {
                    var epi = p.enumPanelItems[m];
                    oid = epi.enumeration;
                    target = domain.findElementByID(oid);
                    if (target)
                        epi.setEnumeration(target);
                }
            }
        }
    }

    return domain;
}

var _{{js:this.name;/}} = null;

//
// Class Base
//

function Base(type, parent, id, name, desc) {
    if (/\W/i.test(name) || name.length < 2) throw "Invalid name: '" + name + "'. Please use only a-z, A-Z, 0-9 or _!";
    this.type = type;
    this.parent = parent;
    this.id = id;
    this.name = name.replace(/ /g, ''); // Remove whitespaces
    this.desc = desc;
}

// Methods

Base.prototype.getDomain = function () {
    var domain = this;
    while (domain.type != "Domain")
        domain = domain.parent;
    return domain;
}

Base.prototype.compareToMyID = function (id) {
  return ""+this.id === ""+id;
}

Base.prototype.idToJSON = function () {
    return this.id;
}

Base.prototype.findElementByID = function (id) {
    var allElems = this.getAllElements(true);
    for (i in allElems) if (allElems[i].compareToMyID(id)) {
        var r = allElems[i];
        return r;
    }
    return null;
}

{{Entity*}}//
// Class "{{js:this.name;/}}"
//

// Constructor
function {{js:this.name;/}} (parent, id, name, desc) {
    // Initialize base class
    {{if}}this.hasParentClass(){{then}}{{js:this.getParentClass().name/}}.call(this, parent, id, name, desc);{{else}}
    Base.call(this, "{{js:this.name;/}}", parent, id, name, desc);{{/if}}
{{BasicProperty?}}
    // Properties:{{BasicProperty*}}
    this.{{js:this.name;/}}={{js:this.defaultValue;/}};{{/BasicProperty}}{{/BasicProperty?}}
    {{if}}this.name === "Domain"{{then}}this.id_counter = 1;{{/if}}
{{Enumeration?}}
    // Enumerations:{{Enumeration*}}
    this.{{js:this.name;/}}="";{{/Enumeration}}{{/Enumeration?}}
{{Relationship?}}
    // Relationships:{{Relationship*}}
    this.{{js:this.name;/}} = [];{{/Relationship}}{{/Relationship?}}
}

// Inheritance
{{js:this.name;/}}.prototype = Object.create({{if}}this.hasParentClass(){{then}}{{js:this.getParentClass().name/}}{{else}}Base{{/if}}.prototype);
{{js:this.name;/}}.prototype.constructor = {{js:this.name;/}};

{{Enumeration?}}// Definitions for Enumerations{{Enumeration*}}
{{js:this.getParent_Entity().name;/}}.prototype.enumDef_{{js:this.name;/}} = [{{Literal*}}{{js:this.itemIsFirst?'':', ';/}}"{{js:this.name;/}}"{{/Literal}}];
{{/Enumeration}}{{/Enumeration?}}
//
// Methods
//
{{Aggregation?}}// Manage Aggregations:{{Aggregation*}}
{{js:this.getParent_Entity().name;/}}.prototype.addNew_{{js:this.getTargetEntity().name;/}} = function (name, desc, existingID) {
    var id = existingID ? existingID : {{if}}this.getTargetEntity().name === "Domain"{{then}}1;// 1 == ID for new Domains{{else}}this.getDomain().createNewID();{{/if}}
    var new_{{js:this.name;/}} = new {{js:this.getTargetEntity().name;/}} (this, id, name, desc);
    new_{{js:this.name;/}}.type = "{{js:this.getTargetEntity().name;/}}";
    this.{{js:this.name;/}}.push (new_{{js:this.name;/}});
    return new_{{js:this.name;/}};
}
{{js:this.getParent_Entity().name;/}}.prototype.remove_{{js:this.getTargetEntity().name;/}} = function (id) {
    var idx = -1;
    this.{{js:this.name;/}}.forEach (function (elem, i) {
        if (elem.compareToMyID(id)) idx = i;
    });
    if(idx != -1)
        this.{{js:this.name;/}}.splice(idx, 1);
    else
        throw "Element not found: "+id;
}{{/Aggregation}}{{/Aggregation?}}

// Misc utility functions
{{js:this.name;/}}.prototype.getAllElements = function (includeSelf)
{
    var r = new Array ();
    if (includeSelf) r = r.concat(this);{{Aggregation*}}
    for (i in this.{{js:this.name;/}}) r = r.concat(this.{{js:this.name;/}}[i].getAllElements(true));{{/Aggregation}}
    return r;
}

{{js:this.name;/}}.prototype.toJSON = function () {
    {{Relationship*}}{{if}}this.isAggregation{{then}}// Get JSON for aggregated entities:
    var json_{{js:this.name;/}} = [];
    for (i in this.{{js:this.name;/}}) json_{{js:this.name;/}}.push(this.{{js:this.name;/}}[i].toJSON());{{else}}//Get JSON for associations:
    var json_{{js:this.name;/}} = [];
    for (i in this.{{js:this.name;/}}) json_{{js:this.name;/}}.push(this.{{js:this.name;/}}[i].id);{{/if}}
    {{/Relationship}}
    return {
        name: this.name,
        desc: this.desc,
        type: this.type,
        id: this.idToJSON(){{BasicProperty!?}}{{BasicProperty!*}},
        {{js:this.name;/}}: this.{{js:this.name;/}}{{/BasicProperty!}}{{/BasicProperty!?}}{{Enumeration!?}}{{Enumeration!*}},
        {{js:this.name;/}}: this.{{js:this.name;/}}{{/Enumeration!}}{{/Enumeration!?}}{{Relationship!?}}{{Relationship!*}},
        {{js:this.name;/}}: json_{{js:this.name;/}}{{/Relationship!}}{{/Relationship!?}}
    }
}

{{js:this.name;/}}.prototype.fromJSON = function (json, parent) {
    // Base attibutes:
    this.parent = parent;
    this.name = json.name;
    this.desc = json.desc;
    this.type =  json.type;
    this.id = json.id;{{BasicProperty!?}}
    // Basic Properties:{{BasicProperty!*}}
    this.{{js:this.name;/}} = json.{{js:this.name;/}};{{/BasicProperty!}}{{/BasicProperty!?}}{{Enumeration!?}}
    // Enumerations: {{Enumeration!*}}
    this.{{js:this.name;/}} = json.{{js:this.name;/}};{{/Enumeration!}}{{/Enumeration!?}}
    {{Aggregation!*}}
    for (var i in json.{{js:this.name;/}}) {
        var jsElem = json.{{js:this.name;/}}[i];
        var newElem = this.addNew_{{js:this.getTargetEntity().name;/}}(jsElem.name, jsElem.desc, jsElem.id);
        newElem.fromJSON(jsElem, this);
    }{{/Aggregation!}}{{Association!*}}
    this.{{js:this.name;/}}=json.{{js:this.name;/}}; // Currently only works for *unary* associations!{{/Association!}}
}

{{/Entity}}
{{Options}} {"saveAs": ["public", "this.name+'_WebAPI.js';"] } {{/Options}}{{/Domain}}
