/
media.js
157 lines (151 loc) · 4.37 KB
/
media.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
* This module provides the basic mechanism for interfacing between format/representations
* and resources, providing deserialization and serialization capabilities. This module
* performs the content negotiation for choosing the appropriate media type.
*/
var model = require("perstore/model"),
when = require("promised-io/promise").when,
Media = exports.Media = function(media){
return Media.instances[media.mediaType] = media;
};
Media.instances = {};
Media.optimumMedia = function(source, acceptTypeHeader){
var bestMedia = null, bestParameters;
var bestQuality = 0;
if(acceptTypeHeader==null){
acceptTypeHeader = "*/*";
}
var acceptTypes = acceptTypeHeader.split(/\s*,\s*/);
for(var i = 0;i < acceptTypes.length; i++){
var acceptType = acceptTypes[i];
var parts = acceptType.split(/\s*;\s*/);
var type = parts[0];
var clientQuality = 1;
var parameters = {};
for(var j = 1; j < parts.length; j++){
var part = parts[j];
var equalIndex = part.indexOf("=");
parameters[part.substring(0, equalIndex)] = part.substring(equalIndex + 1);
}
clientQuality = +(parameters.q || 1);
if("*/*" == type){
for(var instanceType in Media.instances){
checkMedia(Media.instances[instanceType]);
}
/* for persvr compatibility:
for(var i in source){
if(i.substring(0,15) == "representation:"){
checkMedia(source[i]);
}
}*/
}
else{
var media = Media.instances[type];
if(media){
checkMedia(media);
}
/* for persvr compatibility:
media = source && source["representation:" + type];
if(media){
checkMedia(media);
}*/
}
// use alternates per http://tools.ietf.org/html/draft-ietf-http-alternates-01
var alternates;
if(source && ((typeof source.getMetadata === "function" && (alternates = source.getMetadata().alternates)) || (source._metadata && (alternates = source._metadata.alternates)))){
if(!(alternates instanceof Array)){
alternates = [alternates];
}
alternates.forEach(function(alternate){
var mediaType = alternate["content-type"];
if("*/*" == type || mediaType == type){;
checkMedia({
serialize: function(){
return {
// loadFile could return a promise
forEach: function(each){
return when(exports.loadFile(alternate), function(file){
file.forEach(each);
});
}
};
},
getQuality: function(){
return +(alternate.q || 0.5);
},
mediaType: mediaType
});
}
});
}
}
function checkMedia(media){
var quality = clientQuality * media.getQuality(source);
if(source && source["content-type"] == media.mediaType){
quality += 0.5;
}
if(quality > bestQuality){
bestMedia = media;
bestParameters = parameters;
bestQuality = quality;
}
}
return bestMedia && {media: bestMedia, parameters: bestParameters};
};
exports.getColumnsToExport = function(request, item){
var columns = [];
// honor possible ?select(prop1,prop2,...)
require('rql/parser').parseQuery(request.queryString).args.forEach(function(term){
if (term.name === 'select' || term.name === 'values') {
columns = term.args;
}
});
// no (valid) ?select(...) -> dump all properties
if (columns.length === 0 && item && typeof item === 'object')
columns = Object.keys(item);
return columns;
}
// TODO move to promised-io/lazy-array
exports.forEachableToString = function(input){
if (typeof input === "string") return input;
var strings = [];
return when(input.forEach(function(block){
strings.push(block);
}), function(){
return strings.join("");
});
};
var fileModel;
exports.getFileModel = function(){
if(!fileModel){
var Model = require("perstore/model").Model;
fileModel = Model(require("perstore/store/filesystem").FileSystem({dataFolder:"files"}), exports.fileSchema);
}
return fileModel;
};
exports.setFileModel = function(value){
fileModel = value;
};
exports.fileSchema = {};
exports.saveFile = function(file, directives){
var metadata = {};
for(var i in file){
if(typeof file[i] == "string"){
metadata[i] = file[i];
}
}
return when(exports.getFileModel().put(file, directives), function(result){
var id = result.id || result;
result = {id: id};
Object.defineProperty(result, "getMetadata",{
value: function(){
return metadata;
},
enumerable: false
});
return result;
});
};
exports.loadFile = function(file, directives){
return exports.getFileModel().get(file.id, directives);
};