var Confidential = require("./../confidentiality_encryption/Confidential").Confidential;
var DatumFields = require("./../datum/DatumFields").DatumFields;
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
var UserMask = require("./UserMask").UserMask;
var DEFAULT_CORPUS_MODEL = require("./../corpus/corpus.json");
/**
* @class The Speaker represents a source of data, usually a
* language consultant who is a native speaker of the language,
* or a psycholinguistics experiment participant.
* Each consultant has their own I-language and/or dialects which they
* speak (unlike a published source which usually discusses an E-language
* or standard or normal expected production of an utterance.)
* Speakers can have any number of additional fields or metadata
* that a team might use to help cluster or understand variation in data.
*
* As "Informant" is not politically correct in many contexts, and "consultant" is
* ambigious word outside of field work, the word "speaker" is used in communication with
* users and in the url of db queries/api.
*
* A speaker might also be associated to a user. In this case a speaker
* has the same information as a user plus extra, some info (e.g. date of birth)
* which must be kept confidential. Speaker's gravatar are locked to
* default unless he/she wants to be public associated with/his username.
* Speakers which are also users have permissions about the level of
* access to the data (read only, add/edit).
*
* @name Speaker
* @extends UserMask
* @constructs
*/
var Speaker = function Speaker(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Speaker";
}
this.debug("Constructing Speaker: ", options);
if (!options || (!options._rev && !options.fields)) {
//If its a new participant with out a revision and without fields use the defaults
options = options || {};
options.fields = this.defaults.fields;
}
UserMask.apply(this, arguments);
};
Speaker.prototype = Object.create(UserMask.prototype, /** @lends Speaker.prototype */ {
constructor: {
value: Speaker
},
api: {
value: "speakers"
},
INTERNAL_MODELS: {
value: {
username: FieldDBObject.DEFAULT_STRING,
anonymousCode: FieldDBObject.DEFAULT_STRING,
gravatar: FieldDBObject.DEFAULT_STRING,
fields: DatumFields,
user: UserMask,
confidential: Confidential
}
},
defaults: {
get: function() {
var doc = {
fields: DEFAULT_CORPUS_MODEL.speakerFields
};
return JSON.parse(JSON.stringify(doc));
}
},
confidentiality: {
get: function() {
if (this.fields) {
return this.fields.confidentiality.value;
} else {
return;
}
},
set: function(value) {
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
// this.warn("Cannot change the public/private of " + this.collection + " (it must be anonymous). " + value);
this.fields.confidentiality.value = value;
}
},
fields: {
get: function() {
this.debug("getting fields");
return this._fields;
},
set: function(value) {
if (value === this._fields) {
return;
}
if (!value) {
delete this._fields;
return;
} else {
if (typeof this.INTERNAL_MODELS["fields"] === "function" && Object.prototype.toString.call(value) === "[object Array]") {
value = new this.INTERNAL_MODELS["fields"](value);
}
}
if (!value.confidential) {
value.confidential = this.confidential;
}
this._fields = value;
}
},
buildGravatar: {
value: function() {
this._gravatar = "968b8e7fb72b5ffe2915256c28a9414c";
return this._gravatar;
}
},
gravatar: {
get: function() {
return this.buildGravatar();
},
set: function(value) {
this.warn("Cannot set the gravatar of a " + this.fieldDBtype + " (it must be anonymous)." + value);
}
},
username: {
get: function() {
if (this.fields && this.fields.username && this.fields.username.value) {
// this.debug("this.fields.username.value :", this.fields.username.value + ":");
if (this.fields.confidentiality.value === "generalize") {
this.fields.username.mask = "A native speaker";
} else if (this.fields.confidentiality.value === "team") {
this.todo("IF the user is part of the team, they can see the username of the consultant.");
this.fields.username.mask = this.anonymousCode;
} else if (this.fields.confidentiality.value === "anonymous") {
this.fields.username.mask = this.anonymousCode || this.fields.username.mask;
} else if (this.fields.confidentiality.value === "public") {
this.fields.username.mask = this.fields.username.value;
} else {
this.fields.username.mask = "A native speaker";
}
if (this.fields.username.decryptedMode) {
return this.fields.username.value;
} else {
return this.fields.username.mask;
}
} else {
if (this.id) {
return this.id;
}
return;
}
},
set: function(value) {
if (!this.confidential) {
this.warn("Cannot set the username before the confidential is set");
return;
}
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
// this.fields.username.debugMode = true;
// this.fields.username.decryptedMode = true;
this.fields.username.confidential = this.confidential;
this.fields.username.value = value;
}
},
encryptByCorpus: {
value: true
},
id: {
get: function() {
return this.anonymousCode;
},
set: function(value) {
this.anonymousCode = value;
}
},
anonymousCode: {
get: function() {
try {
if (this.fields && this.fields.anonymousCode) {
return this.fields.anonymousCode.value.toUpperCase();
} else {
return this._id;
}
} catch (e) {
this.warn("there was a problem getting the anonymousCode of this speaker", e);
return this._id;
}
},
set: function(value) {
var actualUsername;
if (this.fields && this.fields.username && this.fields.username.value) {
this.fields.username.decryptedMode = true;
actualUsername = this.fields.username.value;
this.fields.username.decryptedMode = false;
}
if (actualUsername && value.toLowerCase().indexOf(actualUsername) > -1) {
this.bug("Cannot set the anonymous code to contain any part of the user's actual username, this would potentially breach their confidentiality.");
return;
}
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
this.fields.anonymousCode.value = this._id = value;
this.debug("Set the id and the anonymousCode of this user" + this._id, this);
if (!this.encryptByCorpus) {
this.confidential = new Confidential({
secretkey: value
});
}
}
},
confidential: {
get: function() {
this.debug("using this speaker's confidential encrypter");
return this.confidentialEncrypter;
},
set: function(value) {
if (value === this.confidentialEncrypter) {
return;
}
if (typeof value.encrypt !== "function" && value.secretkey) {
value = new this.INTERNAL_MODELS["confidential"](value);
}
this.confidentialEncrypter = value;
if (this.fields) {
// this.debug("setting speaker fields confidential in the Speaker.confidential set function.");
this.fields.confidential = value;
}
}
},
dateOfBirth: {
configurable: true,
get: function() {
if (this.fields && this.fields.dateOfBirth) {
return this.fields.dateOfBirth.value;
} else {
return;
}
},
set: function(value) {
this.debug("Setting dateOfBirth " + value, this.confidential);
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
// this.fields.debugMode = true;
this.fields.dateOfBirth.value = value;
}
},
firstname: {
configurable: true,
get: function() {
if (this.fields && this.fields.firstname) {
return this.fields.firstname.value;
} else {
return;
}
},
set: function(value) {
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
if (this.fields && this.fields.firstname) {
// this.fields.debugMode = true;
this.fields.firstname.value = value;
} else {
this.fields.firstname.value = value;
}
}
},
lastname: {
configurable: true,
get: function() {
if (this.fields && this.fields.lastname) {
return this.fields.lastname.value;
} else {
return;
}
},
set: function(value) {
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
if (this.fields && this.fields.lastname) {
// this.fields.debugMode = true;
this.fields.lastname.value = value;
} else {
this.fields.lastname.value = value;
}
}
},
languages: {
get: function() {
if (this.fields) {
return this.fields.languages.value;
} else {
return;
}
},
set: function(value) {
var stringvalue;
var objectvalue;
if (typeof value === "string") {
this.debug("User set the languages with a string");
if (this.fields.languages && this.fields.languages && this.fields.languages.json) {
this.confirm("Do you want to set the languages from " + JSON.stringify(this.fields.languages.json) + " to " + value);
}
stringvalue = value;
objectvalue = {
value: value,
label: "languages",
json: {
languages: value.split(",")
}
};
objectvalue.json.languages = objectvalue.json.languages.map(function(languageName) {
return {
iso: languageName.toLowerCase().trim(),
name: languageName.trim(),
nativeName: languageName.trim()
};
});
} else {
objectvalue = value;
}
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
if (stringvalue) {
this.fields.languages.value = stringvalue;
}
this.debug("setting language ", objectvalue);
for (var property in objectvalue) {
if (!objectvalue.hasOwnProperty(property)) {
continue;
}
this.debug("looking at " + property);
this.fields.languages[property] = objectvalue[property];
}
}
},
dialects: {
get: function() {
return this.languages;
},
set: function(value) {
return this.languages = value;
}
},
user: {
get: function() {
if (!this.userMask) {
var self = this;
if (this.public && this.username) {
this.userMask = new this.INTERNAL_MODELS["user"]({});
this.userMask.username = this.username;
this.userMask.fetch().then(function(result) {
self.debug("Fetched speaker\"s user mask", result);
}, function(error) {
self.debug("Failed to fetch speaker\"s user mask", error);
}).fail(function(error) {
console.error(error.stack, self);
});
} else {
this.userMask = {};
}
this.userMask = {
username: this.anonymousCode,
gravatar: this.gravatar
};
}
return this.userMask;
},
set: function(value) {
if (value === this.userMask) {
return;
}
if (!value) {
value = {};
}
this.userMask = value;
}
},
languageOne: {
get: function() {
return this.getLanguageNumber(0);
},
set: function(value) {
return this.setLanguageNumber(0, value);
}
},
languageTwo: {
get: function() {
return this.getLanguageNumber(1);
},
set: function(value) {
return this.setLanguageNumber(1, value);
}
},
languageThree: {
get: function() {
return this.getLanguageNumber(2);
},
set: function(value) {
return this.setLanguageNumber(2, value);
}
},
languageFour: {
get: function() {
return this.getLanguageNumber(3);
},
set: function(value) {
return this.setLanguageNumber(3, value);
}
},
languageFive: {
get: function() {
return this.getLanguageNumber(4);
},
set: function(value) {
return this.setLanguageNumber(4, value);
}
},
getLanguageNumber: {
value: function(number) {
if (!this.fields || !this.fields.languages || !this.fields.languages.json || !this.fields.languages.json.languages || !this.fields.languages.json.languages[number]) {
return;
}
return this.fields.languages.json.languages[number];
}
},
setLanguageNumber: {
value: function(number, value) {
if (!this.fields || !this.fields.languages) {
return;
}
this.fields.languages.json = this.fields.languages.json || {
languages: []
};
if (value === this.fields.languages.json.languages[number]) {
return;
}
if (value.iso) {
value = {
language: value,
fluency: {
"comprehensionFluency": "native",
"speakingFluency": "native"
},
dates: {
start: "",
end: "",
proportionOfUse: ""
}
};
}
value.fluency = value.fluency || {};
value.dates = value.dates || {};
value.language = value.language || {};
this.fields.languages.json.languages[number] = value;
return this.fields.languages.json.languages[number];
}
}
});
exports.Speaker = Speaker;