UNPKG

diffusion

Version:

Diffusion JavaScript client

244 lines (187 loc) 7.59 kB
var AbstractRecordModel = require('data/record/model/abstract-record-model'); var FieldImpl = require('data/record/schema/field-impl'); var args2arr = require('util/array').argumentsToArray; module.exports = function MutableRecordModelImpl(constructor, schema) { AbstractRecordModel.call(this, constructor, schema); var model = schema.createModel(); this.model = function() { return model; }; this.set = function(recordName, recordIndex, fieldName, fieldIndex, value) { // Account for optional indices if (arguments.length < 5) { fieldIndex = 0; } if (arguments.length === 3) { value = fieldName; fieldName = recordIndex; recordIndex = 0; } if (arguments.length === 2) { value = recordIndex; var key = parseKey(recordName); recordName = key.recordName; recordIndex = key.recordIndex; fieldName = key.fieldName; fieldIndex = key.fieldIndex; } var schemaRecord = schema.getRecord(recordName); var record = getRecord(schemaRecord, recordIndex); var schemaField = schemaRecord.getField(fieldName); record[resolveFieldIndex(schemaField, record, fieldIndex)] = FieldImpl.normalise(schemaField, value); return this; }; this.add = function(recordName, recordIndex) { var values = args2arr(arguments); var schemaRecord; var record; if (arguments.length > 2 && typeof recordIndex === "number") { values = values.slice(2); schemaRecord = schema.getRecord(recordName); record = getRecord(schemaRecord, recordIndex); } else { schemaRecord = schema.lastRecord(); if (model.length > schemaRecord.index) { record = model[model.length - 1]; } else { throw new Error("Variable record '" + schemaRecord.name + "' has no occurrences to add a field to"); } } addValuesToRecord(schemaRecord, record, values); return this; }; this.addRecord = function() { var schemaRecord = schema.lastRecord(); if (!schemaRecord.isVariable) { throw new Error("Record '" + schemaRecord.name + "' is not variable"); } var max = schemaRecord.max; if (max !== -1 && model.length - schemaRecord.index >= max) { throw new Error("Record '" + schemaRecord.name + "' already has maximum number of occurrences"); } model.push(schemaRecord.createModel()); return this; }; this.removeRecord = function(index) { var schemaRecord = schema.lastRecord(); if (!schemaRecord.isVariable) { throw new Error("Record '" + schemaRecord.name + "' is not variable"); } var actualIndex = resolveRecordIndex(schemaRecord, model, index); if (model.length - schemaRecord.index - 1 < schemaRecord.min) { throw new Error( "Removing an occurrence of record '" + schemaRecord.name + "' would violate the minimum number of occurrences"); } model.splice(actualIndex, 1); return this; }; this.removeField = function(recordName, recordIndex, fieldIndex) { var schemaRecord = schema.getRecord(recordName); var record = getRecord(schemaRecord, recordIndex); var schemaField = schemaRecord.lastField(); if (!schemaField.isVariable) { throw new Error("Field '" + schemaField.name + "' is not a variable field"); } var actualFieldIndex = resolveFieldIndex(schemaField, record, fieldIndex); if (record.length - schemaField.index - 1 < schemaField.min) { throw new Error( "Removing an occurrence of field '" + schemaField.name + "' would violate the minimum number of occurrences"); } record.splice(actualFieldIndex, 1); return this; }; this.clearVariableRecords = function() { var schemaRecord = schema.lastRecord(); model.length = schemaRecord.index + schemaRecord.min; return this; }; this.clearVariableFields = function(recordName, recordIndex) { var schemaRecord = schema.getRecord(recordName); var record = getRecord(schemaRecord, recordIndex); var schemaField = schemaRecord.lastField(); record.length = schemaField.index + schemaField.min; return this; }; function addValuesToRecord(schemaRecord, record, values) { var schemaField = schemaRecord.lastField(); if (!schemaField.isVariable) { throw new Error("Final field of record '" + schemaRecord.name + "' is not variable"); } var max = schemaField.max; if (max !== -1) { var current = record.length - schemaField.index; if (current + values.length > max) { throw new Error("Adding values would exceed maximum number of field occurrences"); } } values.forEach(function(value) { record.push(FieldImpl.normalise(schemaField, value)); }); } function getRecord(schemaRecord, index) { return model[resolveRecordIndex(schemaRecord, model, index)]; } function parseKey(key) { var parts = key.split(".", 2); var recordName; var recordIndex; var fieldKey; if (parts.length === 1) { recordName = schema.firstRecord().name; recordIndex = 0; fieldKey = parts[0]; } else { var recordKeyParts = parseKeyPart(parts[0].trim()); recordName = recordKeyParts[0]; recordIndex = recordKeyParts[1]; fieldKey = parts[1]; } var keyParts = parseKeyPart(fieldKey); return { recordName: recordName, recordIndex: recordIndex, fieldName: keyParts[0], fieldIndex: keyParts[1] }; } function parseKeyPart(keyPart) { if (keyPart.length === 0) { throw new Error("No name specified"); } var openIndex = keyPart.indexOf("("); if (openIndex === -1) { return [keyPart, 0]; } if (openIndex === 0) { throw new Error("No name specified"); } var closeIndex = keyPart.indexOf(")"); if (closeIndex === -1 || closeIndex < openIndex) { throw new Error("'(' found without closing ')"); } if (closeIndex < keyPart.length - 1) { throw new Error("Characters found after closing ')"); } return [keyPart.substring(0, openIndex), parseInt(keyPart.substring(openIndex + 1, closeIndex), 10)]; } }; function resolveRecordIndex(record, records, index) { var actualIndex = record.getAbsoluteIndex(index); if (actualIndex > records.length - 1) { throw new Error( "Index '" + index + "' does not have a matching entry for variable occurence record: '" + record.name + "'"); } return actualIndex; } function resolveFieldIndex(field, fields, index) { var actualIndex = field.getAbsoluteIndex(index); if (actualIndex > fields.length - 1) { throw new Error( "Index '" + index + "' does not have a matching entry for variable occurence field: '" + field.name + "'"); } return actualIndex; }