/**
@module ember-flexberry-data
*/
import { isNone } from '@ember/utils';
import { isArray } from '@ember/array';
import { getOwner } from '@ember/application';
import DS from 'ember-data';
import isObject from '../utils/is-object';
/**
Base serializer for {{#crossLink "Offline.LocalStore"}}{{/crossLink}}.
@class Offline
@extends <a href="http://emberjs.com/api/data/classes/DS.JSONSerializer.html">JSONSerializer</a>
*/
export default DS.JSONSerializer.extend({
/*
Serializer initialization.
*/
init: function() {
this._super(...arguments);
let owner = getOwner(this);
let localStore = owner.lookup('store:local');
this.set('store', localStore);
},
/**
Returns the resource's attributes formatted as a JSON-API "attributes object".
[More info](http://emberjs.com/api/data/classes/DS.JSONSerializer.html#method_extractAttributes).
@method extractAttributes
@param {Object} model
@param {Object} hash
@return {Object}
*/
extractAttributes(model, hash) {
let attributes = this._super(...arguments);
model.eachAttribute((key, { type }) => {
if (type === 'boolean') {
let attributeKey = this.keyForAttribute ? this.keyForAttribute(key, 'deserialize') : key;
if (typeof hash[attributeKey] === 'string') {
attributes[key] = hash[attributeKey] === 'true' ? true : hash[attributeKey] === null ? null : false;
}
}
});
return attributes;
},
/**
Method `serializeAttribute` can be used to customize how DS.attr properties are serialized.
[More info](http://emberjs.com/api/data/classes/DS.JSONSerializer.html#method_serializeAttribute).
@method serializeAttribute
@param {DS.Snapshot} snapshot
@param {Object} json
@param {String} key
@param {Object} attribute
*/
serializeAttribute(snapshot, json, key, attribute) {
let attributeKey = this.keyForAttribute ? this.keyForAttribute(key, 'serialize') : key;
let value = snapshot.attr(key);
switch (attribute.type) {
case 'boolean':
if (typeof value === 'boolean') {
json[attributeKey] = `${value}`;
} else if (typeof value === 'undefined') {
json[attributeKey] = 'false';
} else {
this._super(...arguments);
}
break;
case 'decimal':
//Value should be a decimal number
if (typeof value === 'string') {
value = +(value.replace(',', '.'));
}
if (isFinite(value) || typeof value === 'undefined') {
this._super(...arguments);
} else {
throw new Error(`Trying to save '${value}' value of '${key}' field of '${snapshot.modelName}' that should be a decimal`);
}
break;
case 'number':
//Value should be a number
if (typeof value === 'string') {
value = +value;
}
if (isFinite(value) || typeof value === 'undefined') {
this._super(...arguments);
} else {
throw new Error(`Trying to save '${value}' value of '${key}' field of '${snapshot.modelName}' that should be a number`);
}
break;
default:
this._super(...arguments);
}
},
serializePolymorphicType: function(snapshot, json, relationship) {
let key = relationship.key;
let belongsTo = snapshot.belongsTo(key);
key = this.keyForAttribute ? this.keyForAttribute(key, 'serialize') : key;
if (isNone(belongsTo)) {
json['_' + key + '_type'] = null;
} else {
json['_' + key + '_type'] = belongsTo.modelName;
}
},
/**
Normalization method for arrays of objects.
[More info](http://emberjs.com/api/data/classes/DS.JSONSerializer.html#method_normalizeArrayResponse).
@method normalizeArrayResponse
@param {DS.Store} store
@param {DS.Model} type
@param {Object} payload
@return {Object}
*/
normalizeArrayResponse(store, type, payload) {
if (isArray(payload)) {
payload = { data: payload };
}
payload.included = [];
payload.data = payload.data.map((item) => {
let normalize = this.normalize(type, item);
if (normalize.included) {
normalize.included.forEach((i) => { payload.included.push(i); });
}
return normalize.data;
});
return payload;
},
/*
Returns a relationship formatted as a JSON-API "relationship object".
See http://jsonapi.org/format/#document-resource-object-relationships
*/
extractRelationship(relationshipModelName, relationshipHash) {
if (isObject(relationshipHash) && isNone(relationshipHash.type)) {
relationshipHash.type = relationshipModelName;
} else if (!isObject(relationshipHash) && !isNone(relationshipHash)) {
let hash = {
id: relationshipHash,
type: relationshipModelName
};
relationshipHash = hash;
}
return relationshipHash;
},
/*
Returns a polymorphic relationship formatted as a JSON-API "relationship object".
See http://jsonapi.org/format/#document-resource-object-relationships
*/
extractPolymorphicRelationship(relationshipModelName, relationshipHash, relationshipOptions) {
let key = relationshipOptions.key ? relationshipOptions.key : relationshipOptions.relationshipKey;
let typeField = '_' + key + '_type';
if (relationshipOptions.resourceHash.hasOwnProperty(typeField)) {
relationshipHash.type = relationshipOptions.resourceHash[typeField];
delete relationshipOptions.resourceHash[typeField];
} else {
relationshipHash.type = relationshipModelName;
}
return relationshipHash;
},
/*
Check if the given hasMany relationship should be serialized.
*/
_shouldSerializeHasMany(snapshot, key, relationship) {
const relationshipType = snapshot.type.determineRelationshipType(relationship, this.store);
if (this._mustSerialize(key)) {
return true;
}
return this._canSerialize(key) &&
(relationshipType === 'manyToNone' ||
relationshipType === 'manyToMany' ||
relationshipType === 'manyToOne');
}
});