define(["jquery", "underscore", "backbone", "models/DataONEObject"], function (
$,
_,
Backbone,
DataONEObject,
) {
/**
* @class EMLNonNumericDomain
* @classdesc EMLNonNumericDomain represents the measurement scale of a nominal
* or ordinal measurement scale attribute, and is an extension of
* EMLMeasurementScale.
* @classcategory Models/Metadata/EML211
* @see https://eml.ecoinformatics.org/schema/eml-attribute_xsd.html#AttributeType_AttributeType_measurementScale_AttributeType_AttributeType_measurementScale_nominal_nonNumericDomain
* @extends Backbone.Model
* @constructor
*/
var EMLNonNumericDomain = Backbone.Model.extend(
/** @lends EMLNonNumericDomain.prototype */ {
type: "EMLNonNumericDomain",
/* Attributes of an EMLNonNumericDomain object */
defaults: function () {
return {
/* Attributes from EML, extends attributes from EMLMeasurementScale */
measurementScale: null, // the name of this measurement scale
nonNumericDomain: [], // One or more of enumeratedDomain, textDomain, references
};
},
/**
* The map of lower case to camel case node names
* needed to deal with parsing issues with $.parseHTML().
* Use this until we can figure out issues with $.parseXML().
* @type {object}
*/
nodeNameMap: {
nonnumericdomain: "nonNumericDomain",
enumerateddomain: "enumeratedDomain",
textdomain: "textDomain",
externalcodeset: "externalCodeSet",
codesetname: "codesetName",
codeseturl: "codesetURL",
entityCodeList: "entityCodeList",
entityreference: "entityReference",
valueattributereference: "valueAttributeReference",
definitionattributereference: "definitionAttributeReference",
orderattributereference: "orderAttributeReference",
sourced: "source",
},
/* Initialize an EMLNonNumericDomain object */
initialize: function (attributes, options) {
this.on("change:nonNumericDomain", this.trickleUpChange);
},
/**
* Parse the incoming measurementScale's XML elements
*/
parse: function (attributes, options) {
var $objectDOM;
var nonNumericDomainNodeList;
var domainNodeList; // the list of domain elements
var domain; // the text or enumerated domain to parse
var domainObject; // The parsed domain object to be added to attributes.nonNumericDomain
var rootNodeName; // Name of the fragment root elements
if (attributes.objectDOM) {
rootNodeName = $(attributes.objectDOM)[0].localName;
$objectDOM = $(attributes.objectDOM);
} else if (attributes.objectXML) {
rootNodeName = $(attributes.objectXML)[0].localName;
$objectDOM = $($(attributes.objectXML)[0]);
} else {
return {};
}
// do we have an appropriate measurementScale tree?
var index = _.indexOf(
["measurementscale", "nominal", "ordinal"],
rootNodeName,
);
if (index == -1) {
throw new Error(
"The measurement scale XML does not have a root " +
"node of 'measurementScale', 'nominal', or 'ordinal'.",
);
}
// If measurementScale is present, add it
if (rootNodeName == "measurementscale") {
attributes.measurementScale = $objectDOM
.children()
.first()[0].localName;
$objectDOM = $objectDOM.children().first();
} else {
attributes.measurementScale = $objectDOM.localName;
}
nonNumericDomainNodeList = $objectDOM.find("nonnumericdomain");
if (nonNumericDomainNodeList && nonNumericDomainNodeList.length > 0) {
domainNodeList = nonNumericDomainNodeList[0].children;
} else {
// No content is available, return
return attributes;
}
// Initialize an array of nonNumericDomain objects
attributes.nonNumericDomain = [];
// Set each domain if we have it
if (domainNodeList && domainNodeList.length > 0) {
_.each(
domainNodeList,
function (domain) {
if (domain) {
// match the camelCase name since DOMParser() is XML-aware
switch (domain.localName) {
case "textdomain":
domainObject = this.parseTextDomain(domain);
break;
case "enumerateddomain":
domainObject = this.parseEnumeratedDomain(domain);
break;
case "references":
// TODO: Support references
console.log(
"In EMLNonNumericDomain.parse()" +
"We don't support references yet ",
);
default:
console.log(
"Unrecognized nonNumericDomain: " + domain.nodeName,
);
}
}
attributes.nonNumericDomain.push(domainObject);
},
this,
);
}
// Add in the textDomain content if present
// TODO
attributes.objectDOM = $objectDOM[0];
return attributes;
},
/* Parse the nonNumericDomain/textDomain fragment
* returning an object with a textDomain attribute, like:
* {
* textDomain: {
* definition: "Some definition",
* pattern: ["*", "\w", "[0-9]"],
* source: "Some source reference"
* }
* }
*/
parseTextDomain: function (domain) {
var domainObject = {};
domainObject.textDomain = {};
var xmlID;
var definition;
let patterns = [];
var source;
// Add the XML id attribute
if ($(domain).attr("id")) {
xmlID = $(domain).attr("id");
} else {
// Generate an id if it's not found
xmlID = DataONEObject.generateId();
}
domainObject.textDomain.xmlID = xmlID;
// Add the definition
definition = $(domain).children("definition").text();
domainObject.textDomain.definition = definition;
// Add the pattern
_.each($(domain).children("pattern"), function (pattern) {
patterns.push(pattern.textContent);
});
domainObject.textDomain.pattern = patterns;
// Add the source
source = $(domain).children("sourced").text();
domainObject.textDomain.source = source;
return domainObject;
},
/* Parse the nonNumericDomain/enumeratedDomain fragment
* returning an object with an enumeratedDomain attribute, like:
* var emlCitation = {};
* var nonNumericDomain = [
* {
* enumeratedDomain: {
* codeDefinition: [
* {
* code: "Some code", // required
* definition: "Some definition", // required
* source: "Some source"
* } // repeatable
* ]
* }
* }, // or
* {
* enumeratedDomain: {
* externalCodeSet: [
* {
* codesetName: "Some code", // required
* citation: [emlCitation], // one of citation or codesetURL
* codesetURL: ["Some URL"] // is required, both repeatable
* } // repeatable
* ]
* }
* }, // or
* {
* enumeratedDomain: {
* entityCodeList: {
* entityReference: "Some reference", // required
* valueAttributeReference: "Some attr reference", // required
* definitionAttributeReference: "Some definition attr reference", // required
* orderAttributeReference: "Some order attr reference"
* }
* }
* }
* ]
*/
parseEnumeratedDomain: function (domain) {
var domainObject = {};
domainObject.enumeratedDomain = {};
var codeDefinition = {};
var externalCodeSet = {};
var entityCodeList = {};
var xmlID;
// Add the XML id attribute
if ($(domain).attr("id")) {
xmlID = $(domain).attr("id");
} else {
// Generate an id if it's not found
xmlID = DataONEObject.generateId();
}
domainObject.enumeratedDomain.xmlID = xmlID;
// Add the codeDefinitions if present
var codeDefinitions = $(domain).children("codedefinition");
if (codeDefinitions.length) {
domainObject.enumeratedDomain.codeDefinition = [];
_.each(codeDefinitions, function (codeDef) {
var code = $(codeDef).children("code").text();
var definition = $(codeDef).children("definition").text();
var source = $(codeDef).children("sourced").text() || undefined;
domainObject.enumeratedDomain.codeDefinition.push({
code: code,
definition: definition,
source: source,
});
});
}
return domainObject;
},
/* Serialize the model to XML */
serialize: function () {
var objectDOM = this.updateDOM();
var xmlString = objectDOM.outerHTML;
// Camel-case the XML
xmlString = this.formatXML(xmlString);
return xmlString;
},
/* Copy the original XML DOM and update it with new values from the model */
updateDOM: function (objectDOM) {
var objectDOM;
var xmlID; // The id of the textDomain or enumeratedDomain fragment
var nonNumericDomainNode;
var domainType; // Either textDomain or enumeratedDomain
var $domainInDOM; // The jQuery object of the text or enumerated domain from the DOM
var nodeToInsertAfter;
var domainNode; // Either a textDomain or enumeratedDomain node
var definitionNode;
var patternNode;
var sourceNode;
var enumeratedDomainNode;
var codeDefinitions;
var codeDefinitionNode;
var codeNode;
var type = this.get("measurementScale");
if (typeof type === "undefined") {
console.warn("Defaulting to an nominal measurementScale.");
type = "nominal";
}
if (!objectDOM) {
objectDOM = this.get("objectDOM");
}
var objectXML = this.get("objectXML");
// If present, use the cached DOM
if (objectDOM) {
objectDOM = objectDOM.cloneNode(true);
// otherwise, use the cached XML
} else if (objectXML) {
objectDOM = $(objectXML)[0].cloneNode(true);
// This is new, create it
} else {
objectDOM = document.createElement(type);
}
if (this.get("nonNumericDomain").length) {
// Update each nonNumericDomain in the DOM
_.each(
this.get("nonNumericDomain"),
function (domain, i) {
// Is this a textDomain or enumeratedDomain?
if (typeof domain.textDomain === "object") {
domainType = "textDomain";
xmlID = domain.textDomain.xmlID;
} else if (typeof domain.enumeratedDomain === "object") {
domainType = "enumeratedDomain";
xmlID = domain.enumeratedDomain.xmlID;
} else {
console.log("Unrecognized NonNumericDomain type. Skipping.");
// TODO: Handle references here
}
// Update the existing DOM node by id
if (xmlID && $(objectDOM).find("#" + xmlID).length) {
if (domainType === "textDomain") {
let originalTextDomain = $(objectDOM)
.find("#" + xmlID)
.find("textdomain");
//If there are existing textDomain nodes in the DOM, update them
if (originalTextDomain.length) {
let updatedTextDomain = this.updateTextDomain(
domain.textDomain,
originalTextDomain,
);
originalTextDomain.replaceWith(updatedTextDomain);
}
//If there are no textDomain nodes in the DOM, create new ones
else {
//Create new textDomain nodes
let newTextDomain = this.createTextDomain(
domain.textDomain,
);
//Insert the new textDomain nodes into the nonNumericDomain node
$($(objectDOM).children("nonnumericdomain")[i]).html(
newTextDomain,
);
}
} else if (domainType === "enumeratedDomain") {
this.updateEnumeratedDomainDOM(
domain.enumeratedDomain,
$domainInDOM,
);
}
//If there is no XML ID but there are the same number of nonNumericDomains in the model and DOM
} else if (
this.get("nonNumericDomain").length ==
$(objectDOM).children("nonnumericdomain").length &&
$(objectDOM).children("nonnumericdomain").length >= i
) {
//If this is a text domain,
if (typeof domain.textDomain === "object") {
let originalTextDomain = $(
$(objectDOM).children("nonnumericdomain")[i],
).find("textdomain");
//If there are existing textDomain nodes in the DOM, update them
if (originalTextDomain.length) {
let updatedTextDomain = this.updateTextDomain(
domain.textDomain,
originalTextDomain,
);
originalTextDomain.replaceWith(updatedTextDomain);
}
//If there are no textDomain nodes in the DOM, create new ones
else {
//Create new textDomain nodes
var newTextDomain = this.createTextDomain(
domain.textDomain,
);
//Insert the new textDomain nodes into the nonNumericDomain node
$($(objectDOM).children("nonnumericdomain")[i]).html(
newTextDomain,
);
}
} else if (typeof domain.enumeratedDomain === "object") {
//Get the nonNumericDomain node from the DOM
var nonNumericDomainNode =
$(objectDOM).children("nonnumericdomain")[i],
enumeratedDomain =
$(nonNumericDomainNode).children("enumerateddomain");
if (enumeratedDomain.length) {
this.updateEnumeratedDomainDOM(
domain.enumeratedDomain,
enumeratedDomain,
);
} else {
//Remove the textDomain node and replace it with an enumeratedDomain node
var textDomainToReplace = $(objectDOM).find("textdomain");
if (textDomainToReplace.length > 0) {
$(textDomainToReplace[i]).replaceWith(
this.createEnumeratedDomainDOM(domain.enumeratedDomain),
);
} else {
nonNumericDomainNode.html(
this.createEnumeratedDomainDOM(
domain.enumeratedDomain,
document.createElement("enumerateddomain"),
),
);
}
}
}
// Otherwise append to the DOM
} else {
// Add the nonNumericDomain element
nonNumericDomainNode =
document.createElement("nonnumericdomain");
if (domainType === "textDomain") {
// Add the definiton element
domainNode = document.createElement("textdomain");
if (domain.textDomain.definition) {
definitionNode = document.createElement("definition");
$(definitionNode).text(domain.textDomain.definition);
$(domainNode).append(definitionNode);
}
// Add the pattern element(s)
if (domain.textDomain.pattern.length) {
_.each(
domain.textDomain.pattern,
function (pattern) {
patternNode = document.createElement("pattern");
$(patternNode).text(pattern);
$(domainNode).append(patternNode);
},
this,
);
}
// Add the source element
if (domain.textDomain.source) {
sourceNode = document.createElement("sourced"); // Accommodate parseHTML() with "d"
$(sourceNode).text(domain.textDomain.source);
$(domainNode).append(sourceNode);
}
} else if (domainType === "enumeratedDomain") {
nonNumericDomainNode.append(
this.createEnumeratedDomainDOM(domain.enumeratedDomain),
);
} else {
console.log(
"The domainType: " + domainType + " is not recognized.",
);
}
$(nonNumericDomainNode).append(domainNode);
$(objectDOM).append(nonNumericDomainNode);
}
},
this,
);
} else {
// We have no content, so can't create a valid domain
console.log(
"In EMLNonNumericDomain.updateDOM(),\n" +
"references are not handled yet. Returning undefined.",
);
// TODO: handle references here
return undefined;
}
return objectDOM;
},
/*
* Update the codeDefinitionList in the first enumeratedDomain
* found in the nonNumericDomain array.
* TODO: Refactor this to support externalCodeSet and entityCodeList
* TODO: Support the source field
* TODO: Support repeatable enumeratedDomains
* var nonNumericDomain = [
* {
* enumeratedDomain: {
* codeDefinition: [
* {
* code: "Some code", // required
* definition: "Some definition", // required
* source: "Some source"
* } // repeatable
* ]
* }
* }
* ]
*/
updateEnumeratedDomain: function (code, definition, index) {
var nonNumericDomain = this.get("nonNumericDomain");
var enumeratedDomain = {};
var codeDefinitions;
if (typeof code == "string" && !code.trim().length) {
code = "";
}
if (typeof definition == "string" && !definition.trim().length) {
definition = "";
}
// Create from scratch
if (
!nonNumericDomain.length ||
!nonNumericDomain[0] ||
!nonNumericDomain[0].enumeratedDomain
) {
nonNumericDomain[0] = {
enumeratedDomain: {
codeDefinition: [
{
code: code,
definition: definition,
},
],
},
};
}
// Update existing
else {
enumeratedDomain = this.get("nonNumericDomain")[0].enumeratedDomain;
if (typeof enumeratedDomain !== "undefined") {
//If there is no code or definition, then remove it from the code list
if (!code && code !== 0 && !definition && definition !== 0) {
this.removeCode(index);
} else if (enumeratedDomain.codeDefinition.length >= index) {
//Create a new code object and insert it into the array
enumeratedDomain.codeDefinition[index] = {
code: code,
definition: definition,
};
} else {
//Create a new code object and append it to the end of the array
enumeratedDomain.codeDefinition.push({
code: code,
definition: definition,
});
}
}
}
//Manually trigger the change event since we're updating an array on the model
this.trigger("change:nonNumericDomain");
},
/*
* Given a `codeDefinition` HTML node and an enumeratedDomain list,
* this function will update the HTML node code definitions with
* all the code definitions listed in the enumeratedDomain
*
* @param {object} enumeratedDomain - A literal object with an array of codeDefinitions
* @param {DOM Element or jQuery Object} - A DOM Element or jQuery selection that represents the <enumeratedDomain> node
*/
updateEnumeratedDomainDOM: function (
enumeratedDomain,
enumeratedDomainNode,
) {
if (enumeratedDomain.codeDefinition.length) {
// Update each codeDefinition
_.each(
enumeratedDomain.codeDefinition,
function (codeDef, i) {
var codeDefNode = $(
$(enumeratedDomainNode).children("codedefinition")[i],
);
if (!codeDefNode.length) {
codeDefNode = $(document.createElement("codedefinition"));
$(enumeratedDomainNode).append(codeDefNode);
}
// Update the required code element
if (codeDef.code) {
var codeNode = codeDefNode.children("code");
//If there is no <code> XML node, make one
if (!codeNode.length) {
codeNode = $(document.createElement("code"));
codeDefNode.append(codeNode);
}
//Add the code text to the <code> node
codeNode.text(codeDef.code);
} else {
codeDefNode.children("code").remove();
}
// Update the required definition element
if (codeDef.definition) {
var defNode = codeDefNode.children("definition");
//If there is no <definition> XML node, make one
if (!defNode.length) {
defNode = $(document.createElement("definition"));
codeDefNode.append(defNode);
}
//Add the definition text to the <definition> node
defNode.text(codeDef.definition);
} else {
codeDefNode.children("definition").remove();
}
// Update the optional source element
if (codeDef.source) {
// Accommodate parseHTML() with source"d"
var sourceNode = codeDefNode.children("sourced");
//If there is no <source> XML node, make one
if (!sourceNode.length) {
sourceNode = $(document.createElement("sourced"));
codeDefNode.append(sourceNode);
}
sourceNode.text(codeDef.source);
} else {
codeDefNode.children("sourced").remove();
}
},
this,
);
// If there are more codeDefinition nodes than there are codeDefinitions
// in the model, then we need to remove the extraneous nodes
var numNodes =
$(enumeratedDomainNode).children("codedefinition").length,
numCodes = enumeratedDomain.codeDefinition.length;
if (numNodes > numCodes) {
//Get the extraneous nodes by selecting the last X child elements
var nodesToRemove = $(enumeratedDomainNode)
.children("codedefinition")
.slice((numNodes - numCodes) * -1);
//Remove them from the DOM
nodesToRemove.remove();
}
} else if (domain.enumeratedDomain.externalCodeSet) {
// TODO Handle externalCodeSet
} else if (domain.enumeratedDomain.entityCodeList) {
// TODO Handle entityCodeList
}
return enumeratedDomainNode;
},
/*
* Given an enumeratedDomain list, this function will create an
* <enumeratedDomain> HTML element with all the code definitions
* listed in the enumeratedDomain object
*
* @param {object} enumeratedDomain - A literal object with an array of codeDefinitions
* @return {DOM Element} - An <enumerateddomain> DOM element tree with code definitions
*/
createEnumeratedDomainDOM: function (enumeratedDomain) {
var enumeratedDomainNode = document.createElement("enumerateddomain");
if (enumeratedDomain.codeDefinition.length) {
// Add each codeDefinition
_.each(
enumeratedDomain.codeDefinition,
function (codeDef) {
var codeDefinitionNode = document.createElement("codedefinition");
// Add the required code element
if (codeDef.code) {
var codeNode = document.createElement("code");
$(codeNode).text(codeDef.code);
$(codeDefinitionNode).append(codeNode);
}
// Add the required definition element
if (codeDef.definition) {
var definitionNode = document.createElement("definition");
$(definitionNode).text(codeDef.definition);
$(codeDefinitionNode).append(definitionNode);
}
// Add the optional source element
if (codeDef.source) {
var sourceNode = document.createElement("sourced"); // Accommodate parseHTML() with "d"
$(sourceNode).text(codeDef.source);
$(codeDefinitionNode).append(sourceNode);
}
$(enumeratedDomainNode).append(codeDefinitionNode);
},
this,
);
} else if (domain.enumeratedDomain.externalCodeSet) {
// TODO Handle externalCodeSet
} else if (domain.enumeratedDomain.entityCodeList) {
// TODO Handle entityCodeList
}
return enumeratedDomainNode;
},
/*
* Given a textDomain object, and textDomain DOM object, this function
* will update all the DOM elements with the textDomain object values
*
* @param {object} textDomain - A literal object representing an EML text domain
* @param {DOM Element} textDomainEl - The <textDomain> DOM Element to update
* @return {DOM Element} - An <textdomain> DOM element tree to update
*/
updateTextDomain: function (textDomain, textDomainEl) {
if (
typeof textDomainEl === "undefined" ||
(typeof textDomainEl == "object" && textDomainEl.length == 0)
)
var textDomainEl = document.createElement("textdomain");
//Create a shortcut to the jQuery object of the text domain element
var $textDomainEl = $(textDomainEl);
var definitionEl = $textDomainEl.find("definition");
//Update the definition element text
if (definitionEl.length > 0) definitionEl.text(textDomain.definition);
else {
$textDomainEl.prepend(
$(document.createElement("definition")).text(textDomain.definition),
);
}
// Remove existing patterns
$textDomainEl.find("pattern").remove();
// Add any new patterns
if (textDomain.pattern && textDomain.pattern.length) {
let patterns = Array.from(textDomain.pattern).reverse();
_.each(patterns, function (pattern) {
//Don't serialize strings with only empty characters
if (typeof pattern == "string" && !pattern.trim().length) return;
var patternNode = document.createElement("pattern");
$(patternNode).text(pattern);
// Prepend before the sourced element if present
if ($textDomainEl.find("sourced").length) {
$textDomainEl.find("sourced").before(patternNode);
} else {
$textDomainEl.append(patternNode);
}
});
}
// Update any new source
if (textDomain.source) {
if ($textDomainEl.find("sourced").length) {
$textDomainEl.find("sourced").text(textDomain.source);
} else {
//
var src = document.createElement("sourced");
src.textContent = textDomain.source;
$textDomainEl.find("textDomain").append(src);
}
} else {
// Remove the source in the DOM not present in the textDomain
// TODO: Uncomment this when we support "source" in the UI
// $domainInDOM.children("source").remove();
}
return textDomainEl;
},
/*
* Creates a textDomain DOM object with the textDomain object values
*
* @param {object} textDomain - A literal object representing an EML text domain
* @return {DOM Element} - An <textdomain> DOM element tree to update
*/
createTextDomain: function (textDomain) {
var textDomainEl = document.createElement("textdomain");
this.updateTextDomain(textDomain, textDomainEl);
return textDomainEl;
},
/*
* Get the DOM node preceding the given nodeName
* to find what position in the EML document
* the named node should be appended
*/
getEMLPosition: function (objectDOM, nodeName) {
// TODO: set the node order
var nodeOrder = ["enumerateddomain", "textdomain"];
var position = _.indexOf(nodeOrder, nodeName);
// Append to the bottom if not found
if (position == -1) {
return $(objectDOM).children().last()[0];
}
// Otherwise, go through each node in the node list and find the
// position where this node will be inserted after
for (var i = position - 1; i >= 0; i--) {
if ($(objectDOM).find(nodeOrder[i]).length) {
return $(objectDOM).find(nodeOrder[i]).last()[0];
}
}
},
/* Let the top level package know of attribute changes from this object */
trickleUpChange: function () {
MetacatUI.rootDataPackage.packageModel.set("changed", true);
},
validate: function () {
var errors = {};
if (!this.get("nonNumericDomain").length)
errors.nonNumericDomain = "Choose a possible value type.";
else {
var domain = this.get("nonNumericDomain")[0];
_.each(
Object.keys(domain),
function (key) {
//For enumerated domain types
if (key == "enumeratedDomain" && domain[key].codeDefinition) {
var isEmpty =
domain[key].codeDefinition.length == 0 ? true : false;
//Validate the list of codes
for (var i = 0; i < domain[key].codeDefinition.length; i++) {
var codeDef = domain[key].codeDefinition[i];
//If either the code or definition is missing in at least one codeDefinition set,
//then this model is invalid
if (
(codeDef.code && !codeDef.definition) ||
(!codeDef.code && codeDef.definition)
) {
errors.enumeratedDomain =
"Provide both a code and definition in each row.";
i = domain[key].codeDefinition.length;
} else if (
domain[key].codeDefinition.length == 1 &&
!codeDef.code &&
!codeDef.definition
)
isEmpty = true;
}
if (isEmpty)
errors.enumeratedDomain =
"Define at least one code and definition.";
} else if (
key == "textDomain" &&
(typeof domain[key] != "object" || !domain[key].definition)
) {
errors.definition =
"Provide a description of the kind of text allowed.";
}
},
this,
);
}
if (Object.keys(errors).length) return errors;
else {
this.trigger("valid");
return;
}
},
/*
* Climbs up the model heirarchy until it finds the EML model
*
* @return {EML211 or false} - Returns the EML 211 Model or false if not found
*/
getParentEML: function () {
var emlModel = this.get("parentModel"),
tries = 0;
while (emlModel.type !== "EML" && tries < 6) {
emlModel = emlModel.get("parentModel");
tries++;
}
if (emlModel && emlModel.type == "EML") return emlModel;
else return false;
},
removeCode: function (index) {
var codeToRemove =
this.get("nonNumericDomain")[0].enumeratedDomain.codeDefinition[
index
];
var newCodeList = _.without(
this.get("nonNumericDomain")[0].enumeratedDomain.codeDefinition,
codeToRemove,
);
this.get("nonNumericDomain")[0].enumeratedDomain.codeDefinition =
newCodeList;
this.trigger("change:nonNumericDomain");
},
},
);
return EMLNonNumericDomain;
});