All Downloads are FREE. Search and download functionalities are using the official Maven repository.

js.prompto.value.ConcreteInstance.js Maven / Gradle / Ivy

var CategoryType = null;
var ContextualExpression = require("../value/ContextualExpression").ContextualExpression;
var NotMutableError = require("../error/NotMutableError").NotMutableError;
var StorableDocument = require("../memstore/StorableDocument").StorableDocument;
var ExpressionValue = require("../value/ExpressionValue").ExpressionValue;
var DecimalType = require("../type/DecimalType").DecimalType;
var Variable = require("../runtime/Variable").Variable;
var Identifier = require("../grammar/Identifier").Identifier;
var Operator = require("../grammar/Operator").Operator;
var NullValue = require("./NullValue").NullValue;
var Decimal = require("./Decimal").Decimal;
var Integer = require("./Integer").Integer;
var Text = require("./Text").Text;
var Instance = require("./Value").Instance;
var DataStore = require("../store/DataStore").DataStore;
var TypeUtils = require("../utils/TypeUtils");


exports.resolve = function() {
	CategoryType = require("../type/CategoryType").CategoryType;
};

function ConcreteInstance(context, declaration) {
    Instance.call(this, new CategoryType(declaration.id));
	this.declaration = declaration;
    this.storable = false;
    if(declaration.storable) {
        var categories = declaration.collectCategories(context);
        this.storable = DataStore.instance.newStorableDocument(categories);
    }
    this.mutable = false;
	this.values = {};
	return this;
}

ConcreteInstance.prototype = Object.create(Instance.prototype);
ConcreteInstance.prototype.constructor = ConcreteInstance;

ConcreteInstance.prototype.getType = function() {
	return this.type;
};

ConcreteInstance.prototype.convertToJavaScript = function() {
    return this; // TODO, until we have a translator
};

ConcreteInstance.prototype.getDbId = function() {
    var dbId = this.values["dbId"] || null;
    return dbId == null ? null : dbId.getStorableData();
};


ConcreteInstance.prototype.getOrCreateDbId = function() {
    var dbId = this.getDbId();
    if(dbId==null) {
        dbId = this.storable.getOrCreateDbId();
        var value = TypeUtils.convertFromJavaScript(dbId);
        this.values["dbId"] = value;
    }
    return dbId;
};


ConcreteInstance.prototype.getStorableData = function() {
    // this is called when storing the instance as a field value, so we just return the dbId
    // the instance data itself will be collected as part of collectStorables
    if (this.storable == null)
        throw new NotStorableError();
    else
        return this.getOrCreateDbId();
};

ConcreteInstance.prototype.getMemberNames = function() {
	return Object.getOwnPropertyNames(this.values);
};

ConcreteInstance.prototype.collectStorables = function(list) {
    if (this.storable==null)
        throw new NotStorableError();
    if (this.storable.dirty) {
        this.getOrCreateDbId();
        list.push(this.storable);
    }
    for(var field in this.values) {
        this.values[field].collectStorables(list);
    }
};

// don't call getters from getters, so register them
// TODO: thread local storage

var activeGetters = {};

function getActiveGetters() {
	return activeGetters;
}

ConcreteInstance.prototype.getMemberValue = function(context, attrName) {
    /* if(typeof(attrName) != typeof(""))
        throw "What?"; */
	var stacked = getActiveGetters()[attrName] || null;
    var first = stacked==null;
    if(first)
        getActiveGetters()[attrName] = context;
	try {
		return this.doGetMember(context, attrName, first);
	} finally {
		if(first) {
			delete getActiveGetters()[attrName];
		}
	}
};

ConcreteInstance.prototype.doGetMember = function(context, attrName, allowGetter) {
    var getter = allowGetter ? this.declaration.findGetter(context, attrName) : null;
    if (getter != null) {
        context = context.newInstanceContext(this, null).newChildContext();
        return getter.interpret(context);
    } else if (this.declaration.hasAttribute(context, attrName) || "dbId" == attrName) {
        return this.values[attrName] || NullValue.instance;
    } else if ("text" == attrName) {
        return new Text(this.toString());
    } else
        return NullValue.instance;
};


// don't call setters from setters, so register them

var activeSetters = {};

function getActiveSetters() {
	return activeSetters;
}

ConcreteInstance.prototype.setMember = function(context, attrName, value) {
    /* if(typeof(attrName) != typeof(""))
        throw "What?"; */
    if(!this.mutable)
        throw new NotMutableError();
	var stacked = getActiveSetters()[attrName] || null;
    var first = stacked==null;
    if(first)
        getActiveSetters()[attrName] = context;
	try {
		this.doSetMember(context, attrName, value, first);
	} finally {
		if(first) {
			delete getActiveSetters()[attrName];
		}
	}
};

ConcreteInstance.prototype.doSetMember = function(context, attrName, value, allowSetter) {
    var decl = context.getRegisteredDeclaration(attrName);
	var setter = allowSetter ? this.declaration.findSetter(context,attrName) : null;
	if(setter!=null) {
		// use attribute name as parameter name for incoming value
		context = context.newInstanceContext(this, null).newChildContext();
        var id = new Identifier(attrName);
		context.registerValue(new Variable(id, decl.getType()));
		context.setValue(id, value);
		value = setter.interpret(context);
	}
    value = this.autocast(decl, value);
	this.values[attrName] = value;
    if (this.storable && decl.storable) // TODO convert object graph if(value instanceof IInstance)
        this.storable.setData(attrName, value.getStorableData());
};

ConcreteInstance.prototype.autocast = function(decl, value) {
    if(value instanceof Integer && decl.getType()==DecimalType.instance)
        value = new Decimal(value.DecimalValue());
    return value;
};

ConcreteInstance.prototype.equals = function(obj) {
	if(obj==this) {
		return true;
	} else if(!(obj instanceof ConcreteInstance)) {
		return false;
	} else {
		var names = Object.getOwnPropertyNames(this.values);
		var otherNames = Object.getOwnPropertyNames(obj.values);
		if(names.length!=otherNames.length) {
			return false;
		}
		for(var i=0;i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy