You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
6.1 KiB
JavaScript
194 lines
6.1 KiB
JavaScript
/*
|
|
* Copyright DataStax, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const tableMappingsModule = require('./table-mappings');
|
|
const TableMappings = tableMappingsModule.TableMappings;
|
|
const DefaultTableMappings = tableMappingsModule.DefaultTableMappings;
|
|
|
|
/**
|
|
* Represents the parsed user information of the table mappings of a model.
|
|
* @ignore
|
|
*/
|
|
class ModelMappingInfo {
|
|
/**
|
|
* @param {String} keyspace
|
|
* @param {Array<{name, isView}>} tables
|
|
* @param {TableMappings} mappings
|
|
* @param {Map<String,ModelColumnInfo>} columns
|
|
*/
|
|
constructor(keyspace, tables, mappings, columns) {
|
|
this.keyspace = keyspace;
|
|
this.tables = tables;
|
|
this._mappings = mappings;
|
|
this._columns = columns;
|
|
|
|
// Define a map of column information per property name
|
|
/** @type {Map<String, ModelColumnInfo>} */
|
|
this._documentProperties = new Map();
|
|
for (const modelColumnInfo of columns.values()) {
|
|
this._documentProperties.set(modelColumnInfo.propertyName, modelColumnInfo);
|
|
}
|
|
}
|
|
|
|
getColumnName(propName) {
|
|
const modelColumnInfo = this._documentProperties.get(propName);
|
|
if (modelColumnInfo !== undefined) {
|
|
// There is an specific name transformation between the column name and the property name
|
|
return modelColumnInfo.columnName;
|
|
}
|
|
// Rely on the TableMappings (i.e. maybe there is a convention defined for this property)
|
|
return this._mappings.getColumnName(propName);
|
|
}
|
|
|
|
getPropertyName(columnName) {
|
|
const modelColumnInfo = this._columns.get(columnName);
|
|
if (modelColumnInfo !== undefined) {
|
|
// There is an specific name transformation between the column name and the property name
|
|
return modelColumnInfo.propertyName;
|
|
}
|
|
// Rely on the TableMappings (i.e. maybe there is a convention defined for this column)
|
|
return this._mappings.getPropertyName(columnName);
|
|
}
|
|
|
|
getFromModelFn(propName) {
|
|
const modelColumnInfo = this._documentProperties.get(propName);
|
|
return modelColumnInfo !== undefined ? modelColumnInfo.fromModel : null;
|
|
}
|
|
|
|
getToModelFn(columnName) {
|
|
const modelColumnInfo = this._columns.get(columnName);
|
|
return modelColumnInfo !== undefined ? modelColumnInfo.toModel : null;
|
|
}
|
|
|
|
newInstance() {
|
|
return this._mappings.newObjectInstance();
|
|
}
|
|
|
|
/**
|
|
* Parses the user options into a map of model names and ModelMappingInfo.
|
|
* @param {MappingOptions} options
|
|
* @param {String} currentKeyspace
|
|
* @returns {Map<String, ModelMappingInfo>}
|
|
*/
|
|
static parse(options, currentKeyspace) {
|
|
const result = new Map();
|
|
if (!options || !options.models) {
|
|
return result;
|
|
}
|
|
|
|
Object.keys(options.models).forEach(modelName => {
|
|
const modelOptions = options.models[modelName];
|
|
result.set(modelName, ModelMappingInfo._create(modelName, currentKeyspace, modelOptions));
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
static _create(modelName, currentKeyspace, modelOptions) {
|
|
if (!currentKeyspace && (!modelOptions || !modelOptions.keyspace)) {
|
|
throw new Error(
|
|
'You should specify the keyspace of the model in the MappingOptions when the Client is not using a keyspace');
|
|
}
|
|
|
|
if (!modelOptions) {
|
|
return ModelMappingInfo.createDefault(modelName, currentKeyspace);
|
|
}
|
|
|
|
let tables;
|
|
|
|
if (modelOptions.tables && modelOptions.tables.length > 0) {
|
|
tables = modelOptions.tables.map(item => {
|
|
const table = { name: null, isView: false };
|
|
if (typeof item === 'string') {
|
|
table.name = item;
|
|
} else if (item) {
|
|
table.name = item.name;
|
|
table.isView = !!item.isView;
|
|
}
|
|
|
|
if (!table.name) {
|
|
throw new Error(`Table name not specified for model '${modelName}'`);
|
|
}
|
|
|
|
return table;
|
|
});
|
|
} else {
|
|
tables = [ { name: modelName, isView: false }];
|
|
}
|
|
|
|
if (modelOptions.mappings && !(modelOptions.mappings instanceof TableMappings)) {
|
|
throw new Error('mappings should be an instance of TableMappings');
|
|
}
|
|
|
|
const columns = new Map();
|
|
if (modelOptions.columns !== null && typeof modelOptions.columns === 'object') {
|
|
Object.keys(modelOptions.columns).forEach(columnName => {
|
|
columns.set(columnName, ModelColumnInfo.parse(columnName, modelOptions.columns[columnName]));
|
|
});
|
|
}
|
|
|
|
return new ModelMappingInfo(
|
|
modelOptions.keyspace || currentKeyspace,
|
|
tables,
|
|
modelOptions.mappings || new DefaultTableMappings(),
|
|
columns
|
|
);
|
|
}
|
|
|
|
static createDefault(modelName, currentKeyspace) {
|
|
return new ModelMappingInfo(
|
|
currentKeyspace,
|
|
[ { name: modelName, isView: false }],
|
|
new DefaultTableMappings(),
|
|
new Map());
|
|
}
|
|
}
|
|
|
|
class ModelColumnInfo {
|
|
constructor(columnName, propertyName, toModel, fromModel) {
|
|
this.columnName = columnName;
|
|
this.propertyName = propertyName;
|
|
|
|
if (toModel && typeof toModel !== 'function') {
|
|
throw new TypeError(`toModel type for property '${propertyName}' should be a function (obtained ${
|
|
typeof toModel})`);
|
|
}
|
|
|
|
if (fromModel && typeof fromModel !== 'function') {
|
|
throw new TypeError(`fromModel type for property '${propertyName}' should be a function (obtained ${
|
|
typeof fromModel})`);
|
|
}
|
|
|
|
this.toModel = toModel;
|
|
this.fromModel = fromModel;
|
|
}
|
|
|
|
static parse(columnName, value) {
|
|
if (!value) {
|
|
return new ModelColumnInfo(columnName, columnName);
|
|
}
|
|
|
|
if (typeof value === 'string') {
|
|
return new ModelColumnInfo(columnName, value);
|
|
}
|
|
|
|
return new ModelColumnInfo(columnName, value.name || columnName, value.toModel, value.fromModel);
|
|
}
|
|
}
|
|
|
|
module.exports = ModelMappingInfo; |