Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jio-main
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Hardik Juneja
jio-main
Commits
bf46a5d5
Commit
bf46a5d5
authored
Dec 31, 2013
by
Tristan Cavelier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Queries are now asynchronous
parent
f8c1966d
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
521 additions
and
244 deletions
+521
-244
complex_queries.js
complex_queries.js
+190
-62
src/jio.storage/indexstorage.js
src/jio.storage/indexstorage.js
+23
-22
src/jio.storage/localstorage.js
src/jio.storage/localstorage.js
+21
-20
src/queries/begin.js
src/queries/begin.js
+2
-2
src/queries/core/complexquery.js
src/queries/core/complexquery.js
+73
-14
src/queries/core/query.js
src/queries/core/query.js
+57
-28
src/queries/core/simplequery.js
src/queries/core/simplequery.js
+17
-17
src/queries/core/tool.js
src/queries/core/tool.js
+41
-1
test/queries/tests.js
test/queries/tests.js
+97
-78
No files found.
complex_queries.js
View file @
bf46a5d5
...
...
@@ -19,8 +19,8 @@
return
module
(
exports
);
}
window
.
complex_queries
=
{};
module
(
window
.
complex_queries
);
}([
'
exports
'
],
function
(
to_export
)
{
module
(
window
.
complex_queries
,
RSVP
);
}([
'
exports
'
],
function
(
to_export
,
RSVP
)
{
"
use strict
"
;
/**
...
...
@@ -742,7 +742,7 @@ var query_class_dict = {};
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global Query: true, query_class_dict: true, inherits: true,
_export
: true, QueryFactory: tru
e */
_export
, QueryFactory, RSVP, sequenc
e */
/**
* The ComplexQuery inherits from Query, and compares one or several metadata
...
...
@@ -798,8 +798,7 @@ ComplexQuery.prototype.toString = function () {
str_list
.
push
(
query
.
toString
());
str_list
.
push
(
this_operator
);
});
str_list
.
pop
();
// remove last operator
str_list
.
push
(
"
)
"
);
str_list
[
str_list
.
length
-
1
]
=
"
)
"
;
// replace last operator
return
str_list
.
join
(
"
"
);
};
...
...
@@ -828,13 +827,41 @@ ComplexQuery.prototype.serialized = function () {
* @return {Boolean} true if all match, false otherwise
*/
ComplexQuery
.
prototype
.
AND
=
function
(
item
,
wildcard_character
)
{
var
i
;
for
(
i
=
0
;
i
<
this
.
query_list
.
length
;
i
+=
1
)
{
if
(
!
this
.
query_list
[
i
].
match
(
item
,
wildcard_character
))
{
return
false
;
var
j
,
promises
=
[];
for
(
j
=
0
;
j
<
this
.
query_list
.
length
;
j
+=
1
)
{
promises
.
push
(
this
.
query_list
[
j
].
match
(
item
,
wildcard_character
));
}
function
cancel
()
{
var
i
;
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
if
(
typeof
promises
.
cancel
===
'
function
'
)
{
promises
.
cancel
();
}
}
}
return
true
;
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
var
i
,
count
=
0
;
function
resolver
(
value
)
{
if
(
!
value
)
{
resolve
(
false
);
}
count
+=
1
;
if
(
count
===
promises
.
length
)
{
resolve
(
true
);
}
}
function
rejecter
(
err
)
{
reject
(
err
);
cancel
();
}
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
promises
[
i
].
then
(
resolver
,
rejecter
);
}
},
cancel
);
};
/**
...
...
@@ -847,13 +874,41 @@ ComplexQuery.prototype.AND = function (item, wildcard_character) {
* @return {Boolean} true if one match, false otherwise
*/
ComplexQuery
.
prototype
.
OR
=
function
(
item
,
wildcard_character
)
{
var
i
;
for
(
i
=
0
;
i
<
this
.
query_list
.
length
;
i
+=
1
)
{
if
(
this
.
query_list
[
i
].
match
(
item
,
wildcard_character
))
{
return
true
;
var
j
,
promises
=
[];
for
(
j
=
0
;
j
<
this
.
query_list
.
length
;
j
+=
1
)
{
promises
.
push
(
this
.
query_list
[
j
].
match
(
item
,
wildcard_character
));
}
function
cancel
()
{
var
i
;
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
if
(
typeof
promises
.
cancel
===
'
function
'
)
{
promises
.
cancel
();
}
}
}
return
false
;
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
var
i
,
count
=
0
;
function
resolver
(
value
)
{
if
(
value
)
{
resolve
(
true
);
}
count
+=
1
;
if
(
count
===
promises
.
length
)
{
resolve
(
false
);
}
}
function
rejecter
(
err
)
{
reject
(
err
);
cancel
();
}
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
promises
[
i
].
then
(
resolver
,
rejecter
);
}
},
cancel
);
};
/**
...
...
@@ -866,7 +921,11 @@ ComplexQuery.prototype.OR = function (item, wildcard_character) {
* @return {Boolean} true if one match, false otherwise
*/
ComplexQuery
.
prototype
.
NOT
=
function
(
item
,
wildcard_character
)
{
return
!
this
.
query_list
[
0
].
match
(
item
,
wildcard_character
);
return
sequence
([
function
()
{
return
this
.
query_list
[
0
].
match
(
item
,
wildcard_character
);
},
function
(
answer
)
{
return
!
answer
;
}]);
};
query_class_dict
.
complex
=
ComplexQuery
;
...
...
@@ -876,7 +935,7 @@ _export("ComplexQuery", ComplexQuery);
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global parseStringToObject: true, emptyFunction: true, sortOn: true, limit:
true, select: true, _export: true, stringEscapeRegexpCharacters: true,
deepClone
: tru
e */
deepClone
, RSVP, sequenc
e */
/**
* The query to use to filter a list of objects.
...
...
@@ -939,7 +998,7 @@ function Query() {
* second is the length.
*/
Query
.
prototype
.
exec
=
function
(
item_list
,
option
)
{
var
i
=
0
;
var
i
,
promises
=
[]
;
if
(
!
Array
.
isArray
(
item_list
))
{
throw
new
TypeError
(
"
Query().exec(): Argument 1 is not of type 'array'
"
);
}
...
...
@@ -953,20 +1012,34 @@ Query.prototype.exec = function (item_list, option) {
if
(
option
.
wildcard_character
===
undefined
)
{
option
.
wildcard_character
=
'
%
'
;
}
while
(
i
<
item_list
.
length
)
{
if
(
!
item_list
[
i
]
||
!
this
.
match
(
item_list
[
i
],
option
.
wildcard_character
)
)
{
item_list
.
splice
(
i
,
1
);
for
(
i
=
0
;
i
<
item_list
.
length
;
i
+=
1
)
{
if
(
!
item_list
[
i
])
{
promises
.
push
(
RSVP
.
resolve
(
false
)
);
}
else
{
i
+=
1
;
promises
.
push
(
this
.
match
(
item_list
[
i
],
option
.
wildcard_character
))
;
}
}
if
(
option
.
sort_on
)
{
sortOn
(
option
.
sort_on
,
item_list
);
}
if
(
option
.
limit
)
{
limit
(
option
.
limit
,
item_list
);
}
select
(
option
.
select_list
||
[],
item_list
);
return
sequence
([
function
()
{
return
RSVP
.
all
(
promises
);
},
function
(
answers
)
{
var
j
;
for
(
j
=
answers
.
length
-
1
;
j
>=
0
;
j
-=
1
)
{
if
(
!
answers
[
j
])
{
item_list
.
splice
(
j
,
1
);
}
}
if
(
option
.
sort_on
)
{
return
sortOn
(
option
.
sort_on
,
item_list
);
}
},
function
()
{
if
(
option
.
limit
)
{
return
limit
(
option
.
limit
,
item_list
);
}
},
function
()
{
return
select
(
option
.
select_list
||
[],
item_list
);
},
function
()
{
return
item_list
;
}]);
};
/**
...
...
@@ -978,7 +1051,7 @@ Query.prototype.exec = function (item_list, option) {
* @return {Boolean} true if match, false otherwise
*/
Query
.
prototype
.
match
=
function
()
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
};
...
...
@@ -1004,24 +1077,39 @@ Query.prototype.parse = function (option) {
* @return {Any} The parser result
*/
function
recParse
(
object
,
option
)
{
var
i
,
query
=
object
.
parsed
;
var
query
=
object
.
parsed
;
if
(
query
.
type
===
"
complex
"
)
{
for
(
i
=
0
;
i
<
query
.
query_list
.
length
;
i
+=
1
)
{
object
.
parsed
=
query
.
query_list
[
i
];
recParse
(
object
,
option
);
query
.
query_list
[
i
]
=
object
.
parsed
;
}
object
.
parsed
=
query
;
that
.
onParseComplexQuery
(
object
,
option
);
}
else
if
(
query
.
type
===
"
simple
"
)
{
that
.
onParseSimpleQuery
(
object
,
option
);
return
sequence
([
function
()
{
return
sequence
(
query
.
query_list
.
map
(
function
(
v
,
i
)
{
/*jslint unparam: true */
return
function
()
{
sequence
([
function
()
{
object
.
parsed
=
query
.
query_list
[
i
];
return
recParse
(
object
,
option
);
},
function
()
{
query
.
query_list
[
i
]
=
object
.
parsed
;
}]);
};
}));
},
function
()
{
object
.
parsed
=
query
;
return
that
.
onParseComplexQuery
(
object
,
option
);
}]);
}
if
(
query
.
type
===
"
simple
"
)
{
return
that
.
onParseSimpleQuery
(
object
,
option
);
}
}
object
=
{
"
parsed
"
:
JSON
.
parse
(
JSON
.
stringify
(
that
.
serialized
()))};
that
.
onParseStart
(
object
,
option
);
recParse
(
object
,
option
);
that
.
onParseEnd
(
object
,
option
);
return
object
.
parsed
;
return
sequence
([
function
()
{
return
that
.
onParseStart
(
object
,
option
);
},
function
()
{
return
recParse
(
object
,
option
);
},
function
()
{
return
that
.
onParseEnd
(
object
,
option
);
},
function
()
{
return
object
.
parsed
;
}]);
};
/**
...
...
@@ -1112,7 +1200,7 @@ _export("objectToSearchText", objectToSearchText);
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global Query: true, inherits: true, query_class_dict: true, _export: true,
convertStringToRegExp
: true
*/
convertStringToRegExp
, RSVP
*/
/**
* The SimpleQuery inherits from Query, and compares one metadata value
...
...
@@ -1193,7 +1281,7 @@ SimpleQuery.prototype.serialized = function () {
* @return {Boolean} true if match, false otherwise
*/
SimpleQuery
.
prototype
[
"
=
"
]
=
function
(
object_value
,
comparison_value
,
wildcard_character
)
{
wildcard_character
)
{
var
value
,
i
;
if
(
!
Array
.
isArray
(
object_value
))
{
object_value
=
[
object_value
];
...
...
@@ -1205,12 +1293,12 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value,
}
if
(
comparison_value
===
undefined
)
{
if
(
value
===
undefined
)
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
if
(
value
===
undefined
)
{
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
if
(
convertStringToRegExp
(
...
...
@@ -1218,10 +1306,10 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value,
wildcard_character
).
test
(
value
.
toString
())
)
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
}
return
false
;
return
RSVP
.
resolve
(
false
)
;
};
/**
...
...
@@ -1234,7 +1322,7 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value,
* @return {Boolean} true if not match, false otherwise
*/
SimpleQuery
.
prototype
[
"
!=
"
]
=
function
(
object_value
,
comparison_value
,
wildcard_character
)
{
wildcard_character
)
{
var
value
,
i
;
if
(
!
Array
.
isArray
(
object_value
))
{
object_value
=
[
object_value
];
...
...
@@ -1246,12 +1334,12 @@ SimpleQuery.prototype["!="] = function (object_value, comparison_value,
}
if
(
comparison_value
===
undefined
)
{
if
(
value
===
undefined
)
{
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
if
(
value
===
undefined
)
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
if
(
convertStringToRegExp
(
...
...
@@ -1259,10 +1347,10 @@ SimpleQuery.prototype["!="] = function (object_value, comparison_value,
wildcard_character
).
test
(
value
.
toString
())
)
{
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
}
return
true
;
return
RSVP
.
resolve
(
true
)
;
};
/**
...
...
@@ -1282,7 +1370,7 @@ SimpleQuery.prototype["<"] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
<
comparison_value
;
return
RSVP
.
resolve
(
value
<
comparison_value
)
;
};
/**
...
...
@@ -1303,7 +1391,7 @@ SimpleQuery.prototype["<="] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
<=
comparison_value
;
return
RSVP
.
resolve
(
value
<=
comparison_value
)
;
};
/**
...
...
@@ -1324,7 +1412,7 @@ SimpleQuery.prototype[">"] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
>
comparison_value
;
return
RSVP
.
resolve
(
value
>
comparison_value
)
;
};
/**
...
...
@@ -1345,7 +1433,7 @@ SimpleQuery.prototype[">="] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
>=
comparison_value
;
return
RSVP
.
resolve
(
value
>=
comparison_value
)
;
};
query_class_dict
.
simple
=
SimpleQuery
;
...
...
@@ -1353,7 +1441,7 @@ query_class_dict.simple = SimpleQuery;
_export
(
"
SimpleQuery
"
,
SimpleQuery
);
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global _export
: true
*/
/*global _export
, RSVP
*/
/**
* Escapes regexp special chars from a string.
...
...
@@ -1642,6 +1730,46 @@ function convertStringToRegExp(string, wildcard_character) {
_export
(
'
convertStringToRegExp
'
,
convertStringToRegExp
);
/**
* sequence(thens): Promise
*
* Executes a sequence of *then* callbacks. It acts like
* `smth().then(callback).then(callback)...`. The first callback is called with
* no parameter.
*
* Elements of `thens` array can be a function or an array contaning at most
* three *then* callbacks: *onFulfilled*, *onRejected*, *onNotified*.
*
* When `cancel()` is executed, each then promises are cancelled at the same
* time.
*
* @param {Array} thens An array of *then* callbacks
* @return {Promise} A new promise
*/
function
sequence
(
thens
)
{
var
promises
=
[];
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
,
notify
)
{
var
i
;
promises
[
0
]
=
new
RSVP
.
Promise
(
function
(
resolve
)
{
resolve
();
});
for
(
i
=
0
;
i
<
thens
.
length
;
i
+=
1
)
{
if
(
Array
.
isArray
(
thens
[
i
]))
{
promises
[
i
+
1
]
=
promises
[
i
].
then
(
thens
[
i
][
0
],
thens
[
i
][
1
],
thens
[
i
][
2
]);
}
else
{
promises
[
i
+
1
]
=
promises
[
i
].
then
(
thens
[
i
]);
}
}
promises
[
i
].
then
(
resolve
,
reject
,
notify
);
},
function
()
{
var
i
;
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
promises
[
i
].
cancel
();
}
});
}
return
to_export
;
}));
src/jio.storage/indexstorage.js
View file @
bf46a5d5
...
...
@@ -719,28 +719,29 @@
}
}
complex_queries
.
QueryFactory
.
create
(
option
.
query
||
''
).
exec
(
db
,
option
);
for
(
i
=
0
;
i
<
db
.
length
;
i
+=
1
)
{
id
=
db
[
i
].
_id
;
if
(
delete_id
)
{
delete
db
[
i
].
_id
;
}
if
(
option
.
include_docs
)
{
db
[
i
]
=
{
"
id
"
:
id
,
"
value
"
:
db
[
i
],
"
doc
"
:
db
[
i
][
"
_
"
+
now
]
};
delete
db
[
i
].
doc
[
"
_
"
+
now
];
delete
db
[
i
].
value
[
"
_
"
+
now
];
}
else
{
db
[
i
]
=
{
"
id
"
:
id
,
"
value
"
:
db
[
i
]
};
}
}
command
.
success
(
200
,
{
"
data
"
:
{
"
total_rows
"
:
db
.
length
,
"
rows
"
:
db
}});
exec
(
db
,
option
).
then
(
function
()
{
for
(
i
=
0
;
i
<
db
.
length
;
i
+=
1
)
{
id
=
db
[
i
].
_id
;
if
(
delete_id
)
{
delete
db
[
i
].
_id
;
}
if
(
option
.
include_docs
)
{
db
[
i
]
=
{
"
id
"
:
id
,
"
value
"
:
db
[
i
],
"
doc
"
:
db
[
i
][
"
_
"
+
now
]
};
delete
db
[
i
].
doc
[
"
_
"
+
now
];
delete
db
[
i
].
value
[
"
_
"
+
now
];
}
else
{
db
[
i
]
=
{
"
id
"
:
id
,
"
value
"
:
db
[
i
]
};
}
}
command
.
success
(
200
,
{
"
data
"
:
{
"
total_rows
"
:
db
.
length
,
"
rows
"
:
db
}});
});
},
function
(
err
)
{
if
(
err
.
status
===
404
)
{
return
command
.
success
(
200
,
{
"
data
"
:
{
"
total_rows
"
:
0
,
"
rows
"
:
[]}});
...
...
src/jio.storage/localstorage.js
View file @
bf46a5d5
...
...
@@ -446,26 +446,27 @@
});
}
complex_queries
.
QueryFactory
.
create
(
options
.
query
||
""
).
exec
(
document_list
,
options
);
document_list
=
document_list
.
map
(
function
(
value
)
{
var
o
=
{
"
id
"
:
value
.
_id
,
"
key
"
:
value
.
_id
};
if
(
options
.
include_docs
===
true
)
{
o
.
doc
=
document_object
[
value
.
_id
];
delete
document_object
[
value
.
_id
];
}
if
(
delete_id
)
{
delete
value
.
_id
;
}
o
.
value
=
value
;
return
o
;
});
command
.
success
({
"
data
"
:
{
"
total_rows
"
:
document_list
.
length
,
"
rows
"
:
document_list
}});
exec
(
document_list
,
options
).
then
(
function
()
{
document_list
=
document_list
.
map
(
function
(
value
)
{
var
o
=
{
"
id
"
:
value
.
_id
,
"
key
"
:
value
.
_id
};
if
(
options
.
include_docs
===
true
)
{
o
.
doc
=
document_object
[
value
.
_id
];
delete
document_object
[
value
.
_id
];
}
if
(
delete_id
)
{
delete
value
.
_id
;
}
o
.
value
=
value
;
return
o
;
});
command
.
success
({
"
data
"
:
{
"
total_rows
"
:
document_list
.
length
,
"
rows
"
:
document_list
}});
});
}
};
...
...
src/queries/begin.js
View file @
bf46a5d5
...
...
@@ -19,8 +19,8 @@
return
module
(
exports
);
}
window
.
complex_queries
=
{};
module
(
window
.
complex_queries
);
}([
'
exports
'
],
function
(
to_export
)
{
module
(
window
.
complex_queries
,
RSVP
);
}([
'
exports
'
],
function
(
to_export
,
RSVP
)
{
"
use strict
"
;
/**
...
...
src/queries/core/complexquery.js
View file @
bf46a5d5
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global Query: true, query_class_dict: true, inherits: true,
_export
: true, QueryFactory: tru
e */
_export
, QueryFactory, RSVP, sequenc
e */
/**
* The ComplexQuery inherits from Query, and compares one or several metadata
...
...
@@ -56,8 +56,7 @@ ComplexQuery.prototype.toString = function () {
str_list
.
push
(
query
.
toString
());
str_list
.
push
(
this_operator
);
});
str_list
.
pop
();
// remove last operator
str_list
.
push
(
"
)
"
);
str_list
[
str_list
.
length
-
1
]
=
"
)
"
;
// replace last operator
return
str_list
.
join
(
"
"
);
};
...
...
@@ -86,13 +85,41 @@ ComplexQuery.prototype.serialized = function () {
* @return {Boolean} true if all match, false otherwise
*/
ComplexQuery
.
prototype
.
AND
=
function
(
item
,
wildcard_character
)
{
var
i
;
for
(
i
=
0
;
i
<
this
.
query_list
.
length
;
i
+=
1
)
{
if
(
!
this
.
query_list
[
i
].
match
(
item
,
wildcard_character
))
{
return
false
;
var
j
,
promises
=
[];
for
(
j
=
0
;
j
<
this
.
query_list
.
length
;
j
+=
1
)
{
promises
.
push
(
this
.
query_list
[
j
].
match
(
item
,
wildcard_character
));
}
function
cancel
()
{
var
i
;
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
if
(
typeof
promises
.
cancel
===
'
function
'
)
{
promises
.
cancel
();
}
}
}
return
true
;
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
var
i
,
count
=
0
;
function
resolver
(
value
)
{
if
(
!
value
)
{
resolve
(
false
);
}
count
+=
1
;
if
(
count
===
promises
.
length
)
{
resolve
(
true
);
}
}
function
rejecter
(
err
)
{
reject
(
err
);
cancel
();
}
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
promises
[
i
].
then
(
resolver
,
rejecter
);
}
},
cancel
);
};
/**
...
...
@@ -105,13 +132,41 @@ ComplexQuery.prototype.AND = function (item, wildcard_character) {
* @return {Boolean} true if one match, false otherwise
*/
ComplexQuery
.
prototype
.
OR
=
function
(
item
,
wildcard_character
)
{
var
i
;
for
(
i
=
0
;
i
<
this
.
query_list
.
length
;
i
+=
1
)
{
if
(
this
.
query_list
[
i
].
match
(
item
,
wildcard_character
))
{
return
true
;
var
j
,
promises
=
[];
for
(
j
=
0
;
j
<
this
.
query_list
.
length
;
j
+=
1
)
{
promises
.
push
(
this
.
query_list
[
j
].
match
(
item
,
wildcard_character
));
}
function
cancel
()
{
var
i
;
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
if
(
typeof
promises
.
cancel
===
'
function
'
)
{
promises
.
cancel
();
}
}
}
return
false
;
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
var
i
,
count
=
0
;
function
resolver
(
value
)
{
if
(
value
)
{
resolve
(
true
);
}
count
+=
1
;
if
(
count
===
promises
.
length
)
{
resolve
(
false
);
}
}
function
rejecter
(
err
)
{
reject
(
err
);
cancel
();
}
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
promises
[
i
].
then
(
resolver
,
rejecter
);
}
},
cancel
);
};
/**
...
...
@@ -124,7 +179,11 @@ ComplexQuery.prototype.OR = function (item, wildcard_character) {
* @return {Boolean} true if one match, false otherwise
*/
ComplexQuery
.
prototype
.
NOT
=
function
(
item
,
wildcard_character
)
{
return
!
this
.
query_list
[
0
].
match
(
item
,
wildcard_character
);
return
sequence
([
function
()
{
return
this
.
query_list
[
0
].
match
(
item
,
wildcard_character
);
},
function
(
answer
)
{
return
!
answer
;
}]);
};
query_class_dict
.
complex
=
ComplexQuery
;
...
...
src/queries/core/query.js
View file @
bf46a5d5
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global parseStringToObject: true, emptyFunction: true, sortOn: true, limit:
true, select: true, _export: true, stringEscapeRegexpCharacters: true,
deepClone
: tru
e */
deepClone
, RSVP, sequenc
e */
/**
* The query to use to filter a list of objects.
...
...
@@ -64,7 +64,7 @@ function Query() {
* second is the length.
*/
Query
.
prototype
.
exec
=
function
(
item_list
,
option
)
{
var
i
=
0
;
var
i
,
promises
=
[]
;
if
(
!
Array
.
isArray
(
item_list
))
{
throw
new
TypeError
(
"
Query().exec(): Argument 1 is not of type 'array'
"
);
}
...
...
@@ -78,20 +78,34 @@ Query.prototype.exec = function (item_list, option) {
if
(
option
.
wildcard_character
===
undefined
)
{
option
.
wildcard_character
=
'
%
'
;
}
while
(
i
<
item_list
.
length
)
{
if
(
!
item_list
[
i
]
||
!
this
.
match
(
item_list
[
i
],
option
.
wildcard_character
)
)
{
item_list
.
splice
(
i
,
1
);
for
(
i
=
0
;
i
<
item_list
.
length
;
i
+=
1
)
{
if
(
!
item_list
[
i
])
{
promises
.
push
(
RSVP
.
resolve
(
false
)
);
}
else
{
i
+=
1
;
promises
.
push
(
this
.
match
(
item_list
[
i
],
option
.
wildcard_character
))
;
}
}
if
(
option
.
sort_on
)
{
sortOn
(
option
.
sort_on
,
item_list
);
}
if
(
option
.
limit
)
{
limit
(
option
.
limit
,
item_list
);
}
select
(
option
.
select_list
||
[],
item_list
);
return
sequence
([
function
()
{
return
RSVP
.
all
(
promises
);
},
function
(
answers
)
{
var
j
;
for
(
j
=
answers
.
length
-
1
;
j
>=
0
;
j
-=
1
)
{
if
(
!
answers
[
j
])
{
item_list
.
splice
(
j
,
1
);
}
}
if
(
option
.
sort_on
)
{
return
sortOn
(
option
.
sort_on
,
item_list
);
}
},
function
()
{
if
(
option
.
limit
)
{
return
limit
(
option
.
limit
,
item_list
);
}
},
function
()
{
return
select
(
option
.
select_list
||
[],
item_list
);
},
function
()
{
return
item_list
;
}]);
};
/**
...
...
@@ -103,7 +117,7 @@ Query.prototype.exec = function (item_list, option) {
* @return {Boolean} true if match, false otherwise
*/
Query
.
prototype
.
match
=
function
()
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
};
...
...
@@ -129,24 +143,39 @@ Query.prototype.parse = function (option) {
* @return {Any} The parser result
*/
function
recParse
(
object
,
option
)
{
var
i
,
query
=
object
.
parsed
;
var
query
=
object
.
parsed
;
if
(
query
.
type
===
"
complex
"
)
{
for
(
i
=
0
;
i
<
query
.
query_list
.
length
;
i
+=
1
)
{
object
.
parsed
=
query
.
query_list
[
i
];
recParse
(
object
,
option
);
query
.
query_list
[
i
]
=
object
.
parsed
;
}
object
.
parsed
=
query
;
that
.
onParseComplexQuery
(
object
,
option
);
}
else
if
(
query
.
type
===
"
simple
"
)
{
that
.
onParseSimpleQuery
(
object
,
option
);
return
sequence
([
function
()
{
return
sequence
(
query
.
query_list
.
map
(
function
(
v
,
i
)
{
/*jslint unparam: true */
return
function
()
{
sequence
([
function
()
{
object
.
parsed
=
query
.
query_list
[
i
];
return
recParse
(
object
,
option
);
},
function
()
{
query
.
query_list
[
i
]
=
object
.
parsed
;
}]);
};
}));
},
function
()
{
object
.
parsed
=
query
;
return
that
.
onParseComplexQuery
(
object
,
option
);
}]);
}
if
(
query
.
type
===
"
simple
"
)
{
return
that
.
onParseSimpleQuery
(
object
,
option
);
}
}
object
=
{
"
parsed
"
:
JSON
.
parse
(
JSON
.
stringify
(
that
.
serialized
()))};
that
.
onParseStart
(
object
,
option
);
recParse
(
object
,
option
);
that
.
onParseEnd
(
object
,
option
);
return
object
.
parsed
;
return
sequence
([
function
()
{
return
that
.
onParseStart
(
object
,
option
);
},
function
()
{
return
recParse
(
object
,
option
);
},
function
()
{
return
that
.
onParseEnd
(
object
,
option
);
},
function
()
{
return
object
.
parsed
;
}]);
};
/**
...
...
src/queries/core/simplequery.js
View file @
bf46a5d5
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global Query: true, inherits: true, query_class_dict: true, _export: true,
convertStringToRegExp
: true
*/
convertStringToRegExp
, RSVP
*/
/**
* The SimpleQuery inherits from Query, and compares one metadata value
...
...
@@ -81,7 +81,7 @@ SimpleQuery.prototype.serialized = function () {
* @return {Boolean} true if match, false otherwise
*/
SimpleQuery
.
prototype
[
"
=
"
]
=
function
(
object_value
,
comparison_value
,
wildcard_character
)
{
wildcard_character
)
{
var
value
,
i
;
if
(
!
Array
.
isArray
(
object_value
))
{
object_value
=
[
object_value
];
...
...
@@ -93,12 +93,12 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value,
}
if
(
comparison_value
===
undefined
)
{
if
(
value
===
undefined
)
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
if
(
value
===
undefined
)
{
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
if
(
convertStringToRegExp
(
...
...
@@ -106,10 +106,10 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value,
wildcard_character
).
test
(
value
.
toString
())
)
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
}
return
false
;
return
RSVP
.
resolve
(
false
)
;
};
/**
...
...
@@ -122,7 +122,7 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value,
* @return {Boolean} true if not match, false otherwise
*/
SimpleQuery
.
prototype
[
"
!=
"
]
=
function
(
object_value
,
comparison_value
,
wildcard_character
)
{
wildcard_character
)
{
var
value
,
i
;
if
(
!
Array
.
isArray
(
object_value
))
{
object_value
=
[
object_value
];
...
...
@@ -134,12 +134,12 @@ SimpleQuery.prototype["!="] = function (object_value, comparison_value,
}
if
(
comparison_value
===
undefined
)
{
if
(
value
===
undefined
)
{
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
if
(
value
===
undefined
)
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
if
(
convertStringToRegExp
(
...
...
@@ -147,10 +147,10 @@ SimpleQuery.prototype["!="] = function (object_value, comparison_value,
wildcard_character
).
test
(
value
.
toString
())
)
{
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
}
return
true
;
return
RSVP
.
resolve
(
true
)
;
};
/**
...
...
@@ -170,7 +170,7 @@ SimpleQuery.prototype["<"] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
<
comparison_value
;
return
RSVP
.
resolve
(
value
<
comparison_value
)
;
};
/**
...
...
@@ -191,7 +191,7 @@ SimpleQuery.prototype["<="] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
<=
comparison_value
;
return
RSVP
.
resolve
(
value
<=
comparison_value
)
;
};
/**
...
...
@@ -212,7 +212,7 @@ SimpleQuery.prototype[">"] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
>
comparison_value
;
return
RSVP
.
resolve
(
value
>
comparison_value
)
;
};
/**
...
...
@@ -233,7 +233,7 @@ SimpleQuery.prototype[">="] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
>=
comparison_value
;
return
RSVP
.
resolve
(
value
>=
comparison_value
)
;
};
query_class_dict
.
simple
=
SimpleQuery
;
...
...
src/queries/core/tool.js
View file @
bf46a5d5
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global _export
: true
*/
/*global _export
, RSVP
*/
/**
* Escapes regexp special chars from a string.
...
...
@@ -287,3 +287,43 @@ function convertStringToRegExp(string, wildcard_character) {
}
_export
(
'
convertStringToRegExp
'
,
convertStringToRegExp
);
/**
* sequence(thens): Promise
*
* Executes a sequence of *then* callbacks. It acts like
* `smth().then(callback).then(callback)...`. The first callback is called with
* no parameter.
*
* Elements of `thens` array can be a function or an array contaning at most
* three *then* callbacks: *onFulfilled*, *onRejected*, *onNotified*.
*
* When `cancel()` is executed, each then promises are cancelled at the same
* time.
*
* @param {Array} thens An array of *then* callbacks
* @return {Promise} A new promise
*/
function
sequence
(
thens
)
{
var
promises
=
[];
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
,
notify
)
{
var
i
;
promises
[
0
]
=
new
RSVP
.
Promise
(
function
(
resolve
)
{
resolve
();
});
for
(
i
=
0
;
i
<
thens
.
length
;
i
+=
1
)
{
if
(
Array
.
isArray
(
thens
[
i
]))
{
promises
[
i
+
1
]
=
promises
[
i
].
then
(
thens
[
i
][
0
],
thens
[
i
][
1
],
thens
[
i
][
2
]);
}
else
{
promises
[
i
+
1
]
=
promises
[
i
].
then
(
thens
[
i
]);
}
}
promises
[
i
].
then
(
resolve
,
reject
,
notify
);
},
function
()
{
var
i
;
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
promises
[
i
].
cancel
();
}
});
}
test/queries/tests.js
View file @
bf46a5d5
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global define, exports, require, module, complex_queries, window, test, ok,
deepEqual, s
inon
*/
deepEqual, s
top, start
*/
// define([module_name], [dependencies], module);
(
function
(
dependencies
,
module
)
{
...
...
@@ -23,11 +23,14 @@
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
complex_queries
.
QueryFactory
.
create
(
''
).
exec
(
doc_list
);
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
],
'
Nothing done on the list
'
);
stop
();
complex_queries
.
QueryFactory
.
create
(
''
).
exec
(
doc_list
).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
],
'
Nothing done on the list
'
);
}).
always
(
start
);
});
test
(
'
Simple Query
'
,
function
()
{
...
...
@@ -35,20 +38,26 @@
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a"
'
).
exec
(
doc_list
);
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
}
],
'
Document with several identifier should be removed
'
);
stop
();
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a"
'
).
exec
(
doc_list
).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
}
],
'
Document with several identifier should be removed
'
);
doc_list
=
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
a
"
,
"
b
"
]}
];
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a"
'
).
exec
(
doc_list
);
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
a
"
,
"
b
"
]}
],
'
Document with several identifier should be kept
'
);
doc_list
=
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
a
"
,
"
b
"
]}
];
return
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a"
'
).
exec
(
doc_list
);
}).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
a
"
,
"
b
"
]}
],
'
Document with several identifier should be kept
'
);
}).
always
(
start
);
});
test
(
'
Complex Query
'
,
function
()
{
...
...
@@ -56,35 +65,40 @@
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
stop
();
complex_queries
.
QueryFactory
.
create
(
'
identifier: "b" AND identifier: "c"
'
).
exec
(
doc_list
)
;
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
],
'
Document with only one identifier should be removed
'
);
).
exec
(
doc_list
)
.
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
],
'
Document with only one identifier should be removed
'
);
doc_list
=
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a" OR identifier: "c"
'
).
exec
(
doc_list
);
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
],
'
All document matches
'
);
doc_list
=
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
return
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a" OR identifier: "c"
'
).
exec
(
doc_list
);
}).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
],
'
All document matches
'
);
doc_list
=
[
{
"
identifier
"
:
"
a
"
,
"
title
"
:
"
o
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
complex_queries
.
QueryFactory
.
create
(
'
(identifier: "a" OR identifier: "b") AND title: "o"
'
).
exec
(
doc_list
);
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
,
"
title
"
:
"
o
"
}
],
'
Only first document should be kept
'
);
doc_list
=
[
{
"
identifier
"
:
"
a
"
,
"
title
"
:
"
o
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
return
complex_queries
.
QueryFactory
.
create
(
'
(identifier: "a" OR identifier: "b") AND title: "o"
'
).
exec
(
doc_list
);
}).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
,
"
title
"
:
"
o
"
}
],
'
Only first document should be kept
'
);
}).
always
(
start
);
});
test
(
'
Wildcard Character
'
,
function
()
{
...
...
@@ -93,40 +107,43 @@
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
];
stop
();
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a%"
'
).
exec
(
doc_list
,
{
// "wildcard_character": "%" // default
})
;
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
],
'
All documents should be kept
'
);
})
.
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
],
'
All documents should be kept
'
);
doc_list
=
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
];
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a%"
'
).
exec
(
doc_list
,
{
"
wildcard_character
"
:
null
});
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a%
"
}
],
'
Document "a%" should be kept
'
);
doc_list
=
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
];
doc_list
=
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
];
complex_queries
.
QueryFactory
.
create
(
'
identifier: "b"
'
).
exec
(
doc_list
,
{
"
wildcard_character
"
:
"
b
"
});
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
],
'
All documents should be kept
'
);
return
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a%"
'
).
exec
(
doc_list
,
{
"
wildcard_character
"
:
null
});
}).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a%
"
}
],
'
Document "a%" should be kept
'
);
doc_list
=
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
];
return
complex_queries
.
QueryFactory
.
create
(
'
identifier: "b"
'
).
exec
(
doc_list
,
{
"
wildcard_character
"
:
"
b
"
});
}).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
],
'
All documents should be kept
'
);
}).
always
(
start
);
});
test
(
"
Additional Filters
"
,
function
()
{
...
...
@@ -135,14 +152,16 @@
{
"
identifier
"
:
"
a
"
,
"
title
"
:
"
f
"
},
{
"
identifier
"
:
"
b
"
,
"
title
"
:
"
d
"
}
];
stop
();
complex_queries
.
QueryFactory
.
create
(
''
).
exec
(
doc_list
,
{
"
select_list
"
:
[
"
title
"
],
"
limit
"
:
[
2
,
1
],
"
sort_on
"
:
[[
"
identifier
"
,
"
ascending
"
],
[
"
title
"
,
"
descending
"
]]
});
deepEqual
(
doc_list
,
[
{
"
title
"
:
"
d
"
}
],
'
The first document should be kept
'
);
}).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
title
"
:
"
d
"
}
],
'
The first document should be kept
'
);
}).
always
(
start
);
});
}));
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment