hydrate-mongodb
Version:
An Object Document Mapper (ODM) for MongoDB.
210 lines (209 loc) • 9.34 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var mappingBuilder_1 = require("./mappingBuilder");
var mappingModel_1 = require("../mappingModel");
var annotations_1 = require("./annotations");
var ObjectMappingBuilder = (function (_super) {
__extends(ObjectMappingBuilder, _super);
function ObjectMappingBuilder() {
return _super !== null && _super.apply(this, arguments) || this;
}
ObjectMappingBuilder.prototype.populateCore = function () {
var mapping = this.mapping;
var annotations = this.type.getAnnotations();
if (mapping.hasFlags(4096)) {
annotations = annotations.concat(this._getInheritedAnnotations(this.type.baseType));
}
for (var i = 0, l = annotations.length; i < l; i++) {
var annotation = this.context.currentAnnotation = annotations[i];
if (annotation.processClassAnnotation) {
annotation.processClassAnnotation(this.context, mapping, annotation);
}
}
this.context.currentAnnotation = null;
this._processType(this.type);
};
ObjectMappingBuilder.prototype._getInheritedAnnotations = function (type) {
var result = [], oldType = this.context.currentType;
while (type) {
var annotations = type.getAnnotations();
for (var i = 0; i < annotations.length; i++) {
var annotation = annotations[i];
if (annotation.processClassAnnotation) {
if (annotation.inherited) {
result.push(annotation);
}
else {
this.context.currentType = type;
this.context.currentAnnotation = annotation;
this.context.addError("Annotation cannot be defined on a mapped superclass.");
}
}
}
type = type.baseType;
}
this.context.currentType = oldType;
return result;
};
ObjectMappingBuilder.prototype._processType = function (type) {
var mapping = this.mapping;
if (type.baseType) {
this._processType(type.baseType);
}
for (var _i = 0, _a = type.properties; _i < _a.length; _i++) {
var symbol = _a[_i];
this.context.currentProperty = symbol;
var property = this._createProperty(symbol);
if (property) {
var error = mapping.validateProperty(property);
if (error) {
this.context.addError(error);
return;
}
if (property.nullable === undefined) {
property.nullable = this.context.config.nullable;
}
mapping.addProperty(property);
}
}
this.context.currentProperty = null;
for (var _b = 0, _c = type.methods; _b < _c.length; _b++) {
var method = _c[_b];
this.context.currentMethod = method;
var annotations = method.getAnnotations();
if (Array.isArray(annotations)) {
for (var i = 0, l = annotations.length; i < l; i++) {
var annotation = this.context.currentAnnotation = annotations[i];
if (annotation.processMethodAnnotation) {
annotation.processMethodAnnotation(this.context, this.mapping, method, annotation);
}
}
}
this.context.currentAnnotation = null;
}
this.context.currentMethod = null;
};
ObjectMappingBuilder.prototype._createProperty = function (symbol) {
var propertyMapping = this._createPropertyMapping(symbol);
if (!propertyMapping) {
return null;
}
var property = mappingModel_1.MappingModel.createProperty(symbol.name, propertyMapping);
property.field = this.context.config.fieldNamingStrategy(property.name);
var annotations = symbol.getAnnotations();
if (Array.isArray(annotations)) {
for (var i = 0, l = annotations.length; i < l; i++) {
var annotation = this.context.currentAnnotation = annotations[i];
if (annotation.processPropertyAnnotation) {
annotation.processPropertyAnnotation(this.context, this.mapping, property, symbol, annotation);
}
}
this.context.currentAnnotation = null;
}
return property;
};
ObjectMappingBuilder.prototype._createPropertyMapping = function (symbol) {
if (symbol.hasAnnotation(annotations_1.ConverterAnnotation)) {
return symbol.getAnnotations(annotations_1.ConverterAnnotation)[0].createMapping(this.context);
}
var propertyType = this._getPropertyType(symbol);
if (!propertyType) {
this.context.addError("Unable to determine type of property. This may be because of a circular reference or the type is used before it is defined. Try adding the @Type decorator with the name of the class as the target.");
return;
}
if (symbol.hasAnnotation(annotations_1.EnumeratedAnnotation)) {
return this._createEnumMapping(propertyType, symbol.getAnnotations(annotations_1.EnumeratedAnnotation)[0]);
}
var elementTypeAnnotation = symbol.getAnnotations(annotations_1.ElementTypeAnnotation)[0];
if (elementTypeAnnotation) {
if (!elementTypeAnnotation.target) {
this.context.addError("Unable to determine type of target. This may be because of a circular reference or the type is used before it is defined. Try changing target to name of class .");
return;
}
var mapping = this._getMapping(elementTypeAnnotation.target);
if (!mapping)
return;
if (!propertyType.isIterable) {
this.context.addError("Properties annotated @ElementType must have a type that is iterable.");
}
return this._createCollectionMapping(propertyType, mapping);
}
if (propertyType.isArray) {
this.context.addError("Properties with array types must be annotated with @ElementType to indicate the type of the array element.");
return;
}
return this._getMapping(propertyType);
};
ObjectMappingBuilder.prototype._createCollectionMapping = function (propertyType, mapping) {
if (propertyType.isArray) {
return mappingModel_1.MappingModel.createArrayMapping(mapping);
}
this.context.addError("Collections other than 'Array' are not currently supported.");
return null;
};
ObjectMappingBuilder.prototype._getPropertyType = function (symbol) {
var target;
var typeAnnotation = symbol.getAnnotations(annotations_1.TypeAnnotation)[0];
if (typeAnnotation) {
target = typeAnnotation.target;
}
if (target) {
return this.context.getType(target);
}
return symbol.type;
};
ObjectMappingBuilder.prototype._createEnumMapping = function (type, annotation) {
if (!type.isNumber) {
this.context.addError("Cannot use @Enumerated annotation on a non-numeric field.");
return;
}
var members = {};
for (var name in annotation.members) {
if (typeof name === "string" && annotation.members.hasOwnProperty(name)) {
members[name] = annotation.members[name];
}
}
var enumMapping = mappingModel_1.MappingModel.createEnumMapping(members);
return enumMapping;
};
ObjectMappingBuilder.prototype._getMapping = function (target) {
var type;
if (typeof target === "string" || typeof target === "function") {
type = this.context.getType(target);
}
else {
type = target;
}
var builder = this.context.getBuilder(type);
if (builder && builder.mapping) {
return builder.mapping;
}
var typeName;
if (type) {
typeName = type.name;
}
else if (typeof target === "string") {
typeName = target;
}
else if (typeof target === "function") {
typeName = target.name;
}
else {
typeName = "unknown";
}
this.context.addError("Unable to determine mapping for '" + typeName + "'."
+ " Has the type been added to the AnnotationMappingProvider?");
};
return ObjectMappingBuilder;
}(mappingBuilder_1.MappingBuilder));
exports.ObjectMappingBuilder = ObjectMappingBuilder;