Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
dream
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
1
Issues
1
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
dream
Commits
526eb710
Commit
526eb710
authored
Jun 25, 2013
by
Sebastien Robin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gui prototype: import jio code in order to store graph data
parent
e2938b46
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
3661 additions
and
0 deletions
+3661
-0
DREAM/dream/dream/platform/static/lib/jio.js
DREAM/dream/dream/platform/static/lib/jio.js
+2851
-0
DREAM/dream/dream/platform/static/lib/jio.localstorage.js
DREAM/dream/dream/platform/static/lib/jio.localstorage.js
+431
-0
DREAM/dream/dream/platform/static/lib/md5.js
DREAM/dream/dream/platform/static/lib/md5.js
+379
-0
No files found.
DREAM/dream/dream/platform/static/lib/jio.js
0 → 100644
View file @
526eb710
/*
* Copyright 2013, Nexedi SA
* Released under the LGPL license.
* http://www.gnu.org/licenses/lgpl.html
*/
(
function
(
scope
,
hex_md5
)
{
"
use strict
"
;
var
localstorage
;
if
(
typeof
localStorage
!==
"
undefined
"
)
{
localstorage
=
{
getItem
:
function
(
item
)
{
var
value
=
localStorage
.
getItem
(
item
);
return
value
===
null
?
null
:
JSON
.
parse
(
value
);
},
setItem
:
function
(
item
,
value
)
{
return
localStorage
.
setItem
(
item
,
JSON
.
stringify
(
value
));
},
removeItem
:
function
(
item
)
{
delete
localStorage
[
item
];
},
clone
:
function
()
{
return
JSON
.
parse
(
JSON
.
stringify
(
localStorage
));
}
};
}
else
{
(
function
()
{
var
pseudo_localStorage
=
{};
localstorage
=
{
getItem
:
function
(
item
)
{
var
value
=
pseudo_localStorage
[
item
];
return
value
===
undefined
?
null
:
JSON
.
parse
(
pseudo_localStorage
[
item
]);
},
setItem
:
function
(
item
,
value
)
{
pseudo_localStorage
[
item
]
=
JSON
.
stringify
(
value
);
},
removeItem
:
function
(
item
)
{
delete
pseudo_localStorage
[
item
];
},
clone
:
function
()
{
return
JSON
.
parse
(
JSON
.
stringify
(
pseudo_localStorage
));
}
};
}());
}
/*jslint indent:2, maxlen: 80, sloppy: true */
var
jioException
=
function
(
spec
,
my
)
{
var
that
=
{};
spec
=
spec
||
{};
my
=
my
||
{};
that
.
name
=
'
jioException
'
;
that
.
message
=
spec
.
message
||
'
Unknown Reason.
'
;
that
.
toString
=
function
()
{
return
that
.
name
+
'
:
'
+
that
.
message
;
};
return
that
;
};
var
invalidCommandState
=
function
(
spec
,
my
)
{
var
that
=
jioException
(
spec
,
my
),
command
=
spec
.
command
;
spec
=
spec
||
{};
that
.
name
=
'
invalidCommandState
'
;
that
.
toString
=
function
()
{
return
that
.
name
+
'
:
'
+
command
.
getLabel
()
+
'
,
'
+
that
.
message
;
};
return
that
;
};
var
invalidStorage
=
function
(
spec
,
my
)
{
var
that
=
jioException
(
spec
,
my
),
type
=
spec
.
storage
.
getType
();
spec
=
spec
||
{};
that
.
name
=
'
invalidStorage
'
;
that
.
toString
=
function
()
{
return
that
.
name
+
'
:
'
+
'
Type "
'
+
type
+
'
",
'
+
that
.
message
;
};
return
that
;
};
var
invalidStorageType
=
function
(
spec
,
my
)
{
var
that
=
jioException
(
spec
,
my
),
type
=
spec
.
type
;
that
.
name
=
'
invalidStorageType
'
;
that
.
toString
=
function
()
{
return
that
.
name
+
'
:
'
+
type
+
'
,
'
+
that
.
message
;
};
return
that
;
};
var
jobNotReadyException
=
function
(
spec
,
my
)
{
var
that
=
jioException
(
spec
,
my
);
that
.
name
=
'
jobNotReadyException
'
;
return
that
;
};
var
tooMuchTriesJobException
=
function
(
spec
,
my
)
{
var
that
=
jioException
(
spec
,
my
);
that
.
name
=
'
tooMuchTriesJobException
'
;
return
that
;
};
var
invalidJobException
=
function
(
spec
,
my
)
{
var
that
=
jioException
(
spec
,
my
);
that
.
name
=
'
invalidJobException
'
;
return
that
;
};
var
jio
=
function
(
spec
)
{
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global command: true, jobManager: true, job: true */
var
storage
=
function
(
spec
,
my
)
{
var
that
=
{},
priv
=
{};
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
priv
.
type
=
spec
.
type
||
''
;
// Methods //
Object
.
defineProperty
(
that
,
"
getType
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
return
priv
.
type
;
}
});
/**
* Execute the command on this storage.
* @method execute
* @param {object} command The command
*/
that
.
execute
=
function
(
command
)
{
that
.
success
=
command
.
success
;
that
.
error
=
command
.
error
;
that
.
retry
=
command
.
retry
;
that
.
end
=
command
.
end
;
if
(
that
.
validate
(
command
))
{
command
.
executeOn
(
that
);
}
};
/**
* Override this function to validate specifications.
* @method isValid
* @return {boolean} true if ok, else false.
*/
that
.
isValid
=
function
()
{
return
true
;
};
that
.
validate
=
function
()
{
var
mess
=
that
.
validateState
();
if
(
mess
)
{
that
.
error
({
"
status
"
:
0
,
"
statusText
"
:
"
Invalid Storage
"
,
"
error
"
:
"
invalid_storage
"
,
"
message
"
:
mess
,
"
reason
"
:
mess
});
return
false
;
}
return
true
;
};
/**
* Returns a serialized version of this storage.
* @method serialized
* @return {object} The serialized storage.
*/
that
.
serialized
=
function
()
{
var
o
=
that
.
specToStore
()
||
{};
o
.
type
=
that
.
getType
();
return
o
;
};
/**
* Returns an object containing spec to store on localStorage, in order to
* be restored later if something wrong happen.
* Override this method!
* @method specToStore
* @return {object} The spec to store
*/
that
.
specToStore
=
function
()
{
return
{};
};
/**
* Validate the storage state. It returns a empty string all is ok.
* @method validateState
* @return {string} empty: ok, else error message.
*/
that
.
validateState
=
function
()
{
return
''
;
};
that
.
post
=
function
()
{
setTimeout
(
function
()
{
that
.
error
({
"
status
"
:
0
,
"
statusText
"
:
"
Not Implemented
"
,
"
error
"
:
"
not_implemented
"
,
"
message
"
:
"
\"
Post
\"
command is not implemented
"
,
"
reason
"
:
"
Command not implemented
"
});
});
};
that
.
put
=
function
()
{
setTimeout
(
function
()
{
that
.
error
({
"
status
"
:
0
,
"
statusText
"
:
"
Not Implemented
"
,
"
error
"
:
"
not_implemented
"
,
"
message
"
:
"
\"
Put
\"
command is not implemented
"
,
"
reason
"
:
"
Command not implemented
"
});
});
};
that
.
putAttachment
=
function
()
{
setTimeout
(
function
()
{
that
.
error
({
"
status
"
:
0
,
"
statusText
"
:
"
Not Implemented
"
,
"
error
"
:
"
not_implemented
"
,
"
message
"
:
"
\"
PutAttachment
\"
command is not implemented
"
,
"
reason
"
:
"
Command not implemented
"
});
});
};
that
.
get
=
function
()
{
setTimeout
(
function
()
{
that
.
error
({
"
status
"
:
0
,
"
statusText
"
:
"
Not Implemented
"
,
"
error
"
:
"
not_implemented
"
,
"
message
"
:
"
\"
Get
\"
command is not implemented
"
,
"
reason
"
:
"
Command not implemented
"
});
});
};
that
.
allDocs
=
function
()
{
setTimeout
(
function
()
{
that
.
error
({
"
status
"
:
0
,
"
statusText
"
:
"
Not Implemented
"
,
"
error
"
:
"
not_implemented
"
,
"
message
"
:
"
\"
AllDocs
\"
command is not implemented
"
,
"
reason
"
:
"
Command not implemented
"
});
});
};
that
.
remove
=
function
()
{
setTimeout
(
function
()
{
that
.
error
({
"
status
"
:
0
,
"
statusText
"
:
"
Not Implemented
"
,
"
error
"
:
"
not_implemented
"
,
"
message
"
:
"
\"
Remove
\"
command is not implemented
"
,
"
reason
"
:
"
Command not implemented
"
});
});
};
that
.
check
=
function
(
command
)
{
setTimeout
(
function
()
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()});
});
};
that
.
repair
=
function
(
command
)
{
setTimeout
(
function
()
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()});
});
};
that
.
success
=
function
()
{};
that
.
retry
=
function
()
{};
that
.
error
=
function
()
{};
that
.
end
=
function
()
{};
// terminate the current job.
priv
.
newCommand
=
function
(
method
,
spec
)
{
var
o
=
spec
||
{};
o
.
label
=
method
;
return
command
(
o
,
my
);
};
priv
.
storage
=
my
.
storage
;
delete
my
.
storage
;
that
.
addJob
=
function
(
method
,
storage_spec
,
doc
,
option
,
success
,
error
)
{
var
command_opt
=
{
doc
:
doc
,
options
:
option
,
callbacks
:
{
success
:
success
,
error
:
error
}
};
jobManager
.
addJob
(
job
({
storage
:
priv
.
storage
(
storage_spec
||
{}),
command
:
priv
.
newCommand
(
method
,
command_opt
)
},
my
));
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global command: true */
var
allDocsCommand
=
function
(
spec
,
my
)
{
var
that
=
command
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
// Methods //
that
.
getLabel
=
function
()
{
return
'
allDocs
'
;
};
that
.
executeOn
=
function
(
storage
)
{
storage
.
allDocs
(
that
);
};
that
.
canBeRestored
=
function
()
{
return
false
;
};
that
.
validateState
=
function
()
{
return
true
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global command: true */
var
checkCommand
=
function
(
spec
,
my
)
{
var
that
=
command
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Methods //
that
.
getLabel
=
function
()
{
return
'
check
'
;
};
that
.
validateState
=
function
()
{
if
(
!
(
typeof
that
.
getDocId
()
===
"
string
"
&&
that
.
getDocId
()
!==
""
))
{
that
.
error
({
"
status
"
:
20
,
"
statusText
"
:
"
Document Id Required
"
,
"
error
"
:
"
document_id_required
"
,
"
message
"
:
"
The document id is not provided
"
,
"
reason
"
:
"
Document id is undefined
"
});
return
false
;
}
return
true
;
};
that
.
executeOn
=
function
(
storage
)
{
storage
.
check
(
that
);
};
that
.
canBeRestored
=
function
()
{
return
false
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global postCommand: true, putCommand: true, getCommand: true,
removeCommand: true, allDocsCommand: true,
getAttachmentCommand: true, removeAttachmentCommand: true,
putAttachmentCommand: true, failStatus: true, doneStatus: true,
checkCommand: true, repairCommand: true,
hex_md5: true */
var
command
=
function
(
spec
,
my
)
{
var
that
=
{},
priv
=
{};
spec
=
spec
||
{};
my
=
my
||
{};
priv
.
commandlist
=
{
'
post
'
:
postCommand
,
'
put
'
:
putCommand
,
'
get
'
:
getCommand
,
'
remove
'
:
removeCommand
,
'
allDocs
'
:
allDocsCommand
,
'
getAttachment
'
:
getAttachmentCommand
,
'
putAttachment
'
:
putAttachmentCommand
,
'
removeAttachment
'
:
removeAttachmentCommand
,
'
check
'
:
checkCommand
,
'
repair
'
:
repairCommand
};
// creates the good command thanks to his label
if
(
spec
.
label
&&
priv
.
commandlist
[
spec
.
label
])
{
priv
.
label
=
spec
.
label
;
delete
spec
.
label
;
return
priv
.
commandlist
[
priv
.
label
](
spec
,
my
);
}
priv
.
tried
=
0
;
priv
.
doc
=
spec
.
doc
||
{};
if
(
typeof
priv
.
doc
!==
"
object
"
)
{
priv
.
doc
=
{
"
_id
"
:
priv
.
doc
.
toString
()
};
}
priv
.
option
=
spec
.
options
||
{};
priv
.
callbacks
=
spec
.
callbacks
||
{};
priv
.
success
=
[
priv
.
callbacks
.
success
||
function
()
{}];
priv
.
error
=
[
priv
.
callbacks
.
error
||
function
()
{}];
priv
.
retry
=
function
()
{
that
.
error
({
status
:
13
,
statusText
:
'
Fail Retry
'
,
error
:
'
fail_retry
'
,
message
:
'
Impossible to retry.
'
,
reason
:
'
Impossible to retry.
'
});
};
priv
.
end
=
function
()
{};
priv
.
on_going
=
false
;
// Methods //
/**
* Returns a serialized version of this command.
* @method serialized
* @return {object} The serialized command.
*/
that
.
serialized
=
function
()
{
var
o
=
{};
o
.
label
=
that
.
getLabel
();
o
.
tried
=
priv
.
tried
;
o
.
doc
=
that
.
cloneDoc
();
o
.
option
=
that
.
cloneOption
();
return
o
;
};
/**
* Returns the label of the command.
* @method getLabel
* @return {string} The label.
*/
that
.
getLabel
=
function
()
{
return
'
command
'
;
};
/**
* Gets the document id
* @method getDocId
* @return {string} The document id
*/
that
.
getDocId
=
function
()
{
return
priv
.
doc
.
_id
;
};
/**
* Gets the attachment id
* @method getAttachmentId
* @return {string} The attachment id
*/
that
.
getAttachmentId
=
function
()
{
return
priv
.
doc
.
_attachment
;
};
/**
* Returns the data of the attachment
* @method getAttachmentData
* @return {string} The data
*/
that
.
getAttachmentData
=
function
()
{
return
priv
.
doc
.
_data
||
""
;
};
/**
* Returns the data length of the attachment
* @method getAttachmentLength
* @return {number} The length
*/
that
.
getAttachmentLength
=
function
()
{
return
(
priv
.
doc
.
_data
||
""
).
length
;
};
/**
* Returns the mimetype of the attachment
* @method getAttachmentMimeType
* @return {string} The mimetype
*/
that
.
getAttachmentMimeType
=
function
()
{
return
priv
.
doc
.
_mimetype
;
};
/**
* Generate the md5sum of the attachment data
* @method md5SumAttachmentData
* @return {string} The md5sum
*/
that
.
md5SumAttachmentData
=
function
()
{
return
hex_md5
(
priv
.
doc
.
_data
||
""
);
};
/**
* Returns an information about the document.
* @method getDocInfo
* @param {string} infoname The info name.
* @return The info value.
*/
that
.
getDocInfo
=
function
(
infoname
)
{
return
priv
.
doc
[
infoname
];
};
/**
* Returns the value of an option.
* @method getOption
* @param {string} optionname The option name.
* @return The option value.
*/
that
.
getOption
=
function
(
optionname
)
{
return
priv
.
option
[
optionname
];
};
/**
* Validates the storage.
* @param {object} storage The storage.
*/
that
.
validate
=
function
(
storage
)
{
if
(
typeof
priv
.
doc
.
_id
===
"
string
"
&&
priv
.
doc
.
_id
.
match
(
"
"
))
{
that
.
error
({
"
status
"
:
21
,
"
statusText
"
:
"
Invalid Document Id
"
,
"
error
"
:
"
invalid_document_id
"
,
"
message
"
:
"
The document id is invalid
"
,
"
reason
"
:
"
The document id contains spaces
"
});
return
false
;
}
if
(
!
that
.
validateState
())
{
return
false
;
}
return
storage
.
validate
();
};
/*
* Extend this function
*/
that
.
validateState
=
function
()
{
return
true
;
};
/**
* Check if the command can be retried.
* @method canBeRetried
* @return {boolean} The result
*/
that
.
canBeRetried
=
function
()
{
return
(
priv
.
option
.
max_retry
===
undefined
||
priv
.
option
.
max_retry
===
0
||
priv
.
tried
<
priv
.
option
.
max_retry
);
};
/**
* Gets the number time the command has been tried.
* @method getTried
* @return {number} The number of time the command has been tried
*/
that
.
getTried
=
function
()
{
return
priv
.
tried
;
};
/**
* Delegate actual excecution the storage.
* @param {object} storage The storage.
*/
that
.
execute
=
function
(
storage
)
{
if
(
!
priv
.
on_going
)
{
if
(
that
.
validate
(
storage
))
{
priv
.
tried
+=
1
;
priv
.
on_going
=
true
;
storage
.
execute
(
that
);
}
}
};
/**
* Execute the good method from the storage.
* Override this function.
* @method executeOn
* @param {object} storage The storage.
*/
that
.
executeOn
=
function
(
storage
)
{};
that
.
success
=
function
(
return_value
)
{
var
i
;
priv
.
on_going
=
false
;
for
(
i
=
0
;
i
<
priv
.
success
.
length
;
i
+=
1
)
{
priv
.
success
[
i
](
return_value
);
}
priv
.
end
(
doneStatus
());
priv
.
success
=
[];
priv
.
error
=
[];
};
that
.
retry
=
function
(
return_error
)
{
priv
.
on_going
=
false
;
if
(
that
.
canBeRetried
())
{
priv
.
retry
();
}
else
{
that
.
error
(
return_error
);
}
};
that
.
error
=
function
(
return_error
)
{
var
i
;
priv
.
on_going
=
false
;
for
(
i
=
0
;
i
<
priv
.
error
.
length
;
i
+=
1
)
{
priv
.
error
[
i
](
return_error
);
}
priv
.
end
(
failStatus
());
priv
.
success
=
[];
priv
.
error
=
[];
};
that
.
end
=
function
()
{
priv
.
end
(
doneStatus
());
};
that
.
addCallbacks
=
function
(
success
,
error
)
{
if
(
arguments
.
length
>
1
)
{
priv
.
success
.
push
(
success
||
function
()
{});
priv
.
error
.
push
(
error
||
function
()
{});
}
else
{
priv
.
success
.
push
(
function
(
response
)
{
(
success
||
function
()
{})(
undefined
,
response
);
});
priv
.
error
.
push
(
function
(
err
)
{
(
success
||
function
()
{})(
err
,
undefined
);
});
}
};
that
.
onSuccessDo
=
function
(
fun
)
{
if
(
fun
)
{
priv
.
success
=
fun
;
}
else
{
return
priv
.
success
;
}
};
that
.
onErrorDo
=
function
(
fun
)
{
if
(
fun
)
{
priv
.
error
=
fun
;
}
else
{
return
priv
.
error
;
}
};
that
.
onEndDo
=
function
(
fun
)
{
priv
.
end
=
fun
;
};
that
.
onRetryDo
=
function
(
fun
)
{
priv
.
retry
=
fun
;
};
/**
* Is the command can be restored by another JIO : yes.
* @method canBeRestored
* @return {boolean} true
*/
that
.
canBeRestored
=
function
()
{
return
true
;
};
/**
* Clones the command and returns it.
* @method clone
* @return {object} The cloned command.
*/
that
.
clone
=
function
()
{
return
command
(
that
.
serialized
(),
my
);
};
/**
* Clones the command options and returns the clone version.
* @method cloneOption
* @return {object} The clone of the command options.
*/
that
.
cloneOption
=
function
()
{
return
JSON
.
parse
(
JSON
.
stringify
(
priv
.
option
));
};
/**
* Clones the document and returns the clone version.
* @method cloneDoc
* @return {object} The clone of the document.
*/
that
.
cloneDoc
=
function
()
{
return
JSON
.
parse
(
JSON
.
stringify
(
priv
.
doc
));
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global command: true */
var
getAttachmentCommand
=
function
(
spec
,
my
)
{
var
that
=
command
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
// Methods //
that
.
getLabel
=
function
()
{
return
'
getAttachment
'
;
};
that
.
executeOn
=
function
(
storage
)
{
storage
.
getAttachment
(
that
);
};
that
.
validateState
=
function
()
{
if
(
!
(
typeof
that
.
getDocId
()
===
"
string
"
&&
that
.
getDocId
()
!==
""
))
{
that
.
error
({
"
status
"
:
20
,
"
statusText
"
:
"
Document Id Required
"
,
"
error
"
:
"
document_id_required
"
,
"
message
"
:
"
The document id is not provided
"
,
"
reason
"
:
"
Document id is undefined
"
});
return
false
;
}
if
(
typeof
that
.
getAttachmentId
()
!==
"
string
"
)
{
that
.
error
({
"
status
"
:
22
,
"
statusText
"
:
"
Attachment Id Required
"
,
"
error
"
:
"
attachment_id_required
"
,
"
message
"
:
"
The attachment id must be set
"
,
"
reason
"
:
"
Attachment id not set
"
});
return
false
;
}
if
(
that
.
getAttachmentId
()
===
""
)
{
that
.
error
({
"
status
"
:
23
,
"
statusText
"
:
"
Invalid Attachment Id
"
,
"
error
"
:
"
invalid_attachment_id
"
,
"
message
"
:
"
The attachment id must not be an empty string
"
,
"
reason
"
:
"
Attachment id is empty
"
});
}
return
true
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global command: true */
var
getCommand
=
function
(
spec
,
my
)
{
var
that
=
command
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
// Methods //
that
.
getLabel
=
function
()
{
return
'
get
'
;
};
that
.
validateState
=
function
()
{
if
(
!
(
typeof
that
.
getDocId
()
===
"
string
"
&&
that
.
getDocId
()
!==
""
))
{
that
.
error
({
"
status
"
:
20
,
"
statusText
"
:
"
Document Id Required
"
,
"
error
"
:
"
document_id_required
"
,
"
message
"
:
"
The document id is not provided
"
,
"
reason
"
:
"
Document id is undefined
"
});
return
false
;
}
return
true
;
};
that
.
executeOn
=
function
(
storage
)
{
storage
.
get
(
that
);
};
that
.
canBeRestored
=
function
()
{
return
false
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global command: true */
var
postCommand
=
function
(
spec
,
my
)
{
var
that
=
command
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Methods //
that
.
getLabel
=
function
()
{
return
'
post
'
;
};
that
.
validateState
=
function
()
{
return
true
;
};
that
.
executeOn
=
function
(
storage
)
{
storage
.
post
(
that
);
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global command: true */
var
putAttachmentCommand
=
function
(
spec
,
my
)
{
var
that
=
command
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
// Methods //
that
.
getLabel
=
function
()
{
return
'
putAttachment
'
;
};
that
.
executeOn
=
function
(
storage
)
{
storage
.
putAttachment
(
that
);
};
that
.
validateState
=
function
()
{
if
(
!
(
typeof
that
.
getDocId
()
===
"
string
"
&&
that
.
getDocId
()
!==
""
))
{
that
.
error
({
"
status
"
:
20
,
"
statusText
"
:
"
Document Id Required
"
,
"
error
"
:
"
document_id_required
"
,
"
message
"
:
"
The document id is not provided
"
,
"
reason
"
:
"
Document id is undefined
"
});
return
false
;
}
if
(
typeof
that
.
getAttachmentId
()
!==
"
string
"
)
{
that
.
error
({
"
status
"
:
22
,
"
statusText
"
:
"
Attachment Id Required
"
,
"
error
"
:
"
attachment_id_required
"
,
"
message
"
:
"
The attachment id must be set
"
,
"
reason
"
:
"
Attachment id not set
"
});
return
false
;
}
if
(
that
.
getAttachmentId
()
===
""
)
{
that
.
error
({
"
status
"
:
23
,
"
statusText
"
:
"
Invalid Attachment Id
"
,
"
error
"
:
"
invalid_attachment_id
"
,
"
message
"
:
"
The attachment id must not be an empty string
"
,
"
reason
"
:
"
Attachment id is empty
"
});
}
return
true
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global command: true */
var
putCommand
=
function
(
spec
,
my
)
{
var
that
=
command
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Methods //
that
.
getLabel
=
function
()
{
return
'
put
'
;
};
that
.
validateState
=
function
()
{
if
(
!
(
typeof
that
.
getDocId
()
===
"
string
"
&&
that
.
getDocId
()
!==
""
))
{
that
.
error
({
"
status
"
:
20
,
"
statusText
"
:
"
Document Id Required
"
,
"
error
"
:
"
document_id_required
"
,
"
message
"
:
"
The document id is not provided
"
,
"
reason
"
:
"
Document id is undefined
"
});
return
false
;
}
return
true
;
};
that
.
executeOn
=
function
(
storage
)
{
storage
.
put
(
that
);
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global command: true */
var
removeAttachmentCommand
=
function
(
spec
,
my
)
{
var
that
=
command
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
// Methods //
that
.
getLabel
=
function
()
{
return
'
removeAttachment
'
;
};
that
.
executeOn
=
function
(
storage
)
{
storage
.
removeAttachment
(
that
);
};
that
.
validateState
=
function
()
{
if
(
!
(
typeof
that
.
getDocId
()
===
"
string
"
&&
that
.
getDocId
()
!==
""
))
{
that
.
error
({
"
status
"
:
20
,
"
statusText
"
:
"
Document Id Required
"
,
"
error
"
:
"
document_id_required
"
,
"
message
"
:
"
The document id is not provided
"
,
"
reason
"
:
"
Document id is undefined
"
});
return
false
;
}
if
(
typeof
that
.
getAttachmentId
()
!==
"
string
"
)
{
that
.
error
({
"
status
"
:
22
,
"
statusText
"
:
"
Attachment Id Required
"
,
"
error
"
:
"
attachment_id_required
"
,
"
message
"
:
"
The attachment id must be set
"
,
"
reason
"
:
"
Attachment id not set
"
});
return
false
;
}
if
(
that
.
getAttachmentId
()
===
""
)
{
that
.
error
({
"
status
"
:
23
,
"
statusText
"
:
"
Invalid Attachment Id
"
,
"
error
"
:
"
invalid_attachment_id
"
,
"
message
"
:
"
The attachment id must not be an empty string
"
,
"
reason
"
:
"
Attachment id is empty
"
});
}
return
true
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global command: true */
var
removeCommand
=
function
(
spec
,
my
)
{
var
that
=
command
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
// Methods //
that
.
getLabel
=
function
()
{
return
'
remove
'
;
};
that
.
validateState
=
function
()
{
if
(
!
(
typeof
that
.
getDocId
()
===
"
string
"
&&
that
.
getDocId
()
!==
""
))
{
that
.
error
({
"
status
"
:
20
,
"
statusText
"
:
"
Document Id Required
"
,
"
error
"
:
"
document_id_required
"
,
"
message
"
:
"
The document id is not provided
"
,
"
reason
"
:
"
Document id is undefined
"
});
return
false
;
}
return
true
;
};
that
.
executeOn
=
function
(
storage
)
{
storage
.
remove
(
that
);
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global command: true */
var
repairCommand
=
function
(
spec
,
my
)
{
var
that
=
command
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Methods //
that
.
getLabel
=
function
()
{
return
'
repair
'
;
};
that
.
validateState
=
function
()
{
if
(
!
(
typeof
that
.
getDocId
()
===
"
string
"
&&
that
.
getDocId
()
!==
""
))
{
that
.
error
({
"
status
"
:
20
,
"
statusText
"
:
"
Document Id Required
"
,
"
error
"
:
"
document_id_required
"
,
"
message
"
:
"
The document id is not provided
"
,
"
reason
"
:
"
Document id is undefined
"
});
return
false
;
}
return
true
;
};
that
.
executeOn
=
function
(
storage
)
{
storage
.
repair
(
that
);
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global jobStatus: true */
var
doneStatus
=
function
(
spec
,
my
)
{
var
that
=
jobStatus
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
// Methods //
that
.
getLabel
=
function
()
{
return
'
done
'
;
};
that
.
canStart
=
function
()
{
return
false
;
};
that
.
canRestart
=
function
()
{
return
false
;
};
that
.
isDone
=
function
()
{
return
true
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global jobStatus: true */
var
failStatus
=
function
(
spec
,
my
)
{
var
that
=
jobStatus
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
// Methods //
that
.
getLabel
=
function
()
{
return
'
fail
'
;
};
that
.
canStart
=
function
()
{
return
false
;
};
that
.
canRestart
=
function
()
{
return
true
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global jobStatus: true */
var
initialStatus
=
function
(
spec
,
my
)
{
var
that
=
jobStatus
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
// Methods //
that
.
getLabel
=
function
()
{
return
"
initial
"
;
};
that
.
canStart
=
function
()
{
return
true
;
};
that
.
canRestart
=
function
()
{
return
true
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global jobStatus: true */
var
jobStatus
=
function
(
spec
,
my
)
{
var
that
=
{};
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
// Methods //
that
.
getLabel
=
function
()
{
return
'
job status
'
;
};
that
.
canStart
=
function
()
{};
that
.
canRestart
=
function
()
{};
that
.
serialized
=
function
()
{
return
{
"
label
"
:
that
.
getLabel
()};
};
that
.
isWaitStatus
=
function
()
{
return
false
;
};
that
.
isDone
=
function
()
{
return
false
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global jobStatus: true */
var
onGoingStatus
=
function
(
spec
,
my
)
{
var
that
=
jobStatus
(
spec
,
my
);
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
// Methods //
that
.
getLabel
=
function
()
{
return
'
on going
'
;
};
that
.
canStart
=
function
()
{
return
false
;
};
that
.
canRestart
=
function
()
{
return
false
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global jobStatus: true, jobManager: true */
var
waitStatus
=
function
(
spec
,
my
)
{
var
that
=
jobStatus
(
spec
,
my
),
priv
=
{};
spec
=
spec
||
{};
my
=
my
||
{};
// Attributes //
priv
.
job_id_array
=
spec
.
job_id_array
||
[];
priv
.
threshold
=
0
;
// Methods //
/**
* Returns the label of this status.
* @method getLabel
* @return {string} The label: 'wait'.
*/
that
.
getLabel
=
function
()
{
return
'
wait
'
;
};
/**
* Refresh the job id array to wait.
* @method refreshJobIdArray
*/
priv
.
refreshJobIdArray
=
function
()
{
var
tmp_job_id_array
=
[],
i
;
for
(
i
=
0
;
i
<
priv
.
job_id_array
.
length
;
i
+=
1
)
{
if
(
jobManager
.
jobIdExists
(
priv
.
job_id_array
[
i
]))
{
tmp_job_id_array
.
push
(
priv
.
job_id_array
[
i
]);
}
}
priv
.
job_id_array
=
tmp_job_id_array
;
};
/**
* The status must wait for the job end before start again.
* @method waitForJob
* @param {object} job The job to wait for.
*/
that
.
waitForJob
=
function
(
job
)
{
var
i
;
for
(
i
=
0
;
i
<
priv
.
job_id_array
.
length
;
i
+=
1
)
{
if
(
priv
.
job_id_array
[
i
]
===
job
.
getId
())
{
return
;
}
}
priv
.
job_id_array
.
push
(
job
.
getId
());
};
/**
* The status stops to wait for this job.
* @method dontWaitForJob
* @param {object} job The job to stop waiting for.
*/
that
.
dontWaitForJob
=
function
(
job
)
{
var
i
,
tmp_job_id_array
=
[];
for
(
i
=
0
;
i
<
priv
.
job_id_array
.
length
;
i
+=
1
)
{
if
(
priv
.
job_id_array
[
i
]
!==
job
.
getId
())
{
tmp_job_id_array
.
push
(
priv
.
job_id_array
[
i
]);
}
}
priv
.
job_id_array
=
tmp_job_id_array
;
};
/**
* The status must wait for some milliseconds.
* @method waitForTime
* @param {number} ms The number of milliseconds
*/
that
.
waitForTime
=
function
(
ms
)
{
priv
.
threshold
=
Date
.
now
()
+
ms
;
};
/**
* The status stops to wait for some time.
* @method stopWaitForTime
*/
that
.
stopWaitForTime
=
function
()
{
priv
.
threshold
=
0
;
};
that
.
canStart
=
function
()
{
priv
.
refreshJobIdArray
();
return
(
priv
.
job_id_array
.
length
===
0
&&
Date
.
now
()
>=
priv
.
threshold
);
};
that
.
canRestart
=
function
()
{
return
that
.
canStart
();
};
that
.
serialized
=
function
()
{
return
{
"
label
"
:
that
.
getLabel
(),
"
waitfortime
"
:
priv
.
threshold
,
"
waitforjob
"
:
priv
.
job_id_array
};
};
/**
* Checks if this status is waitStatus
* @method isWaitStatus
* @return {boolean} true
*/
that
.
isWaitStatus
=
function
()
{
return
true
;
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global jobIdHandler: true, initialStatus: true, invalidJobException: true,
waitStatus: true, failStatus: true, tooMuchTriesJobException: true,
jobManager: true, jobNotReadyException: true, onGoingStatus: true */
var
job
=
function
(
spec
)
{
var
that
=
{},
priv
=
{};
spec
=
spec
||
{};
priv
.
id
=
jobIdHandler
.
nextId
();
priv
.
command
=
spec
.
command
;
priv
.
storage
=
spec
.
storage
;
priv
.
status
=
initialStatus
();
priv
.
date
=
new
Date
();
// Initialize //
if
(
!
priv
.
storage
)
{
throw
invalidJobException
({
job
:
that
,
message
:
'
No storage set
'
});
}
if
(
!
priv
.
command
)
{
throw
invalidJobException
({
job
:
that
,
message
:
'
No command set
'
});
}
// Methods //
/**
* Returns the job command.
* @method getCommand
* @return {object} The job command.
*/
that
.
getCommand
=
function
()
{
return
priv
.
command
;
};
that
.
getStatus
=
function
()
{
return
priv
.
status
;
};
that
.
getId
=
function
()
{
return
priv
.
id
;
};
that
.
getStorage
=
function
()
{
return
priv
.
storage
;
};
that
.
getDate
=
function
()
{
return
priv
.
date
;
};
/**
* Checks if the job is ready.
* @method isReady
* @return {boolean} true if ready, else false.
*/
that
.
isReady
=
function
()
{
if
(
priv
.
command
.
getTried
()
===
0
)
{
return
priv
.
status
.
canStart
();
}
return
priv
.
status
.
canRestart
();
};
/**
* Returns a serialized version of this job.
* @method serialized
* @return {object} The serialized job.
*/
that
.
serialized
=
function
()
{
return
{
id
:
priv
.
id
,
date
:
priv
.
date
.
getTime
(),
status
:
priv
.
status
.
serialized
(),
command
:
priv
.
command
.
serialized
(),
storage
:
priv
.
storage
.
serialized
()
};
};
/**
* Tells the job to wait for another one.
* @method waitForJob
* @param {object} job The job to wait for.
*/
that
.
waitForJob
=
function
(
job
)
{
if
(
priv
.
status
.
getLabel
()
!==
'
wait
'
)
{
priv
.
status
=
waitStatus
({});
}
priv
.
status
.
waitForJob
(
job
);
};
/**
* Tells the job to do not wait for a job.
* @method dontWaitForJob
* @param {object} job The other job.
*/
that
.
dontWaitFor
=
function
(
job
)
{
if
(
priv
.
status
.
getLabel
()
===
'
wait
'
)
{
priv
.
status
.
dontWaitForJob
(
job
);
}
};
/**
* Tells the job to wait for a while.
* @method waitForTime
* @param {number} ms Time to wait in millisecond.
*/
that
.
waitForTime
=
function
(
ms
)
{
if
(
priv
.
status
.
getLabel
()
!==
'
wait
'
)
{
priv
.
status
=
waitStatus
({});
}
priv
.
status
.
waitForTime
(
ms
);
};
/**
* Tells the job to do not wait for a while anymore.
* @method stopWaitForTime
*/
that
.
stopWaitForTime
=
function
()
{
if
(
priv
.
status
.
getLabel
()
===
'
wait
'
)
{
priv
.
status
.
stopWaitForTime
();
}
};
that
.
eliminated
=
function
()
{
priv
.
command
.
error
({
status
:
10
,
statusText
:
'
Stopped
'
,
error
:
'
stopped
'
,
message
:
'
This job has been stopped by another one.
'
,
reason
:
'
this job has been stopped by another one
'
});
};
that
.
notAccepted
=
function
()
{
priv
.
command
.
onEndDo
(
function
()
{
priv
.
status
=
failStatus
();
jobManager
.
terminateJob
(
that
);
});
priv
.
command
.
error
({
status
:
11
,
statusText
:
'
Not Accepted
'
,
error
:
'
not_accepted
'
,
message
:
'
This job is already running.
'
,
reason
:
'
this job is already running
'
});
};
/**
* Updates the date of the job with the another one.
* @method update
* @param {object} job The other job.
*/
that
.
update
=
function
(
job
)
{
priv
.
command
.
addCallbacks
(
job
.
getCommand
().
onSuccessDo
()[
0
],
job
.
getCommand
().
onErrorDo
()[
0
]);
priv
.
date
=
new
Date
(
job
.
getDate
().
getTime
());
};
/**
* Executes this job.
* @method execute
*/
that
.
execute
=
function
()
{
if
(
!
that
.
getCommand
().
canBeRetried
())
{
throw
tooMuchTriesJobException
({
job
:
that
,
message
:
'
The job was invoked too much time.
'
});
}
if
(
!
that
.
isReady
())
{
throw
jobNotReadyException
({
job
:
that
,
message
:
'
Can not execute this job.
'
});
}
priv
.
status
=
onGoingStatus
();
priv
.
command
.
onRetryDo
(
function
()
{
var
ms
=
priv
.
command
.
getTried
();
ms
=
ms
*
ms
*
200
;
if
(
ms
>
10000
)
{
ms
=
10000
;
}
that
.
waitForTime
(
ms
);
});
priv
.
command
.
onEndDo
(
function
(
status
)
{
priv
.
status
=
status
;
jobManager
.
terminateJob
(
that
);
});
priv
.
command
.
execute
(
priv
.
storage
);
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global announcement: true */
var
announcement
=
function
(
spec
,
my
)
{
var
that
=
{},
callback_a
=
[],
announcer
=
spec
.
announcer
||
{};
spec
=
spec
||
{};
my
=
my
||
{};
// Methods //
that
.
add
=
function
(
callback
)
{
callback_a
.
push
(
callback
);
};
that
.
remove
=
function
(
callback
)
{
var
i
,
tmp_callback_a
=
[];
for
(
i
=
0
;
i
<
callback_a
.
length
;
i
+=
1
)
{
if
(
callback_a
[
i
]
!==
callback
)
{
tmp_callback_a
.
push
(
callback_a
[
i
]);
}
}
callback_a
=
tmp_callback_a
;
};
that
.
register
=
function
()
{
announcer
.
register
(
that
);
};
that
.
unregister
=
function
()
{
announcer
.
unregister
(
that
);
};
that
.
trigger
=
function
(
args
)
{
var
i
;
for
(
i
=
0
;
i
<
callback_a
.
length
;
i
+=
1
)
{
callback_a
[
i
].
apply
(
null
,
args
);
}
};
return
that
;
};
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global localstorage: true, setInterval: true, clearInterval: true */
var
activityUpdater
=
(
function
(
spec
,
my
)
{
var
that
=
{},
priv
=
{};
spec
=
spec
||
{};
my
=
my
||
{};
priv
.
id
=
spec
.
id
||
0
;
priv
.
interval
=
400
;
priv
.
interval_id
=
null
;
// Methods //
/**
* Update the last activity date in the localStorage.
* @method touch
*/
priv
.
touch
=
function
()
{
localstorage
.
setItem
(
'
jio/id/
'
+
priv
.
id
,
Date
.
now
());
};
/**
* Sets the jio id into the activity.
* @method setId
* @param {number} id The jio id.
*/
that
.
setId
=
function
(
id
)
{
priv
.
id
=
id
;
};
/**
* Sets the interval delay between two updates.
* @method setIntervalDelay
* @param {number} ms In milliseconds
*/
that
.
setIntervalDelay
=
function
(
ms
)
{
priv
.
interval
=
ms
;
};
/**
* Gets the interval delay.
* @method getIntervalDelay
* @return {number} The interval delay.
*/
that
.
getIntervalDelay
=
function
()
{
return
priv
.
interval
;
};
/**
* Starts the activity updater. It will update regulary the last activity
* date in the localStorage to show to other jio instance that this instance
* is active.
* @method start
*/
that
.
start
=
function
()
{
if
(
!
priv
.
interval_id
)
{
priv
.
touch
();
priv
.
interval_id
=
setInterval
(
function
()
{
priv
.
touch
();
},
priv
.
interval
);
}
};
/**
* Stops the activity updater.
* @method stop
*/
that
.
stop
=
function
()
{
if
(
priv
.
interval_id
!==
null
)
{
clearInterval
(
priv
.
interval_id
);
priv
.
interval_id
=
null
;
}
};
return
that
;
}());
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global announcement: true */
var
announcer
=
(
function
(
spec
,
my
)
{
var
that
=
{},
announcement_o
=
{};
spec
=
spec
||
{};
my
=
my
||
{};
// Methods //
that
.
register
=
function
(
name
)
{
if
(
!
announcement_o
[
name
])
{
announcement_o
[
name
]
=
announcement
();
}
};
that
.
unregister
=
function
(
name
)
{
if
(
announcement_o
[
name
])
{
delete
announcement_o
[
name
];
}
};
that
.
at
=
function
(
name
)
{
return
announcement_o
[
name
];
};
that
.
on
=
function
(
name
,
callback
)
{
that
.
register
(
name
);
that
.
at
(
name
).
add
(
callback
);
};
that
.
trigger
=
function
(
name
,
args
)
{
that
.
at
(
name
).
trigger
(
args
);
};
return
that
;
}());
/*jslint indent: 2, maxlen: 80, sloppy: true */
var
jobIdHandler
=
(
function
(
spec
)
{
var
that
=
{},
id
=
0
;
spec
=
spec
||
{};
// Methods //
that
.
nextId
=
function
()
{
id
=
id
+
1
;
return
id
;
};
return
that
;
}());
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global localstorage: true, setInterval: true, clearInterval: true,
command: true, job: true, jobRules: true */
var
jobManager
=
(
function
(
spec
)
{
var
that
=
{},
job_array_name
=
'
jio/job_array
'
,
priv
=
{};
spec
=
spec
||
{};
// Attributes //
priv
.
id
=
spec
.
id
;
priv
.
interval_id
=
null
;
priv
.
interval
=
200
;
priv
.
job_array
=
[];
// Methods //
/**
* Get the job array name in the localStorage
* @method getJobArrayName
* @return {string} The job array name
*/
priv
.
getJobArrayName
=
function
()
{
return
job_array_name
+
'
/
'
+
priv
.
id
;
};
/**
* Returns the job array from the localStorage
* @method getJobArray
* @return {array} The job array.
*/
priv
.
getJobArray
=
function
()
{
return
localstorage
.
getItem
(
priv
.
getJobArrayName
())
||
[];
};
/**
* Does a backup of the job array in the localStorage.
* @method copyJobArrayToLocal
*/
priv
.
copyJobArrayToLocal
=
function
()
{
var
new_a
=
[],
i
;
for
(
i
=
0
;
i
<
priv
.
job_array
.
length
;
i
+=
1
)
{
new_a
.
push
(
priv
.
job_array
[
i
].
serialized
());
}
localstorage
.
setItem
(
priv
.
getJobArrayName
(),
new_a
);
};
/**
* Removes a job from the current job array.
* @method removeJob
* @param {object} job The job object.
*/
priv
.
removeJob
=
function
(
job
)
{
var
i
,
tmp_job_array
=
[];
for
(
i
=
0
;
i
<
priv
.
job_array
.
length
;
i
+=
1
)
{
if
(
priv
.
job_array
[
i
]
!==
job
)
{
tmp_job_array
.
push
(
priv
.
job_array
[
i
]);
}
}
priv
.
job_array
=
tmp_job_array
;
priv
.
copyJobArrayToLocal
();
};
/**
* Sets the job manager id.
* @method setId
* @param {number} id The id.
*/
that
.
setId
=
function
(
id
)
{
priv
.
id
=
id
;
};
/**
* Starts listening to the job array, executing them regulary.
* @method start
*/
that
.
start
=
function
()
{
var
i
;
if
(
priv
.
interval_id
===
null
)
{
priv
.
interval_id
=
setInterval
(
function
()
{
priv
.
restoreOldJio
();
for
(
i
=
0
;
i
<
priv
.
job_array
.
length
;
i
+=
1
)
{
that
.
execute
(
priv
.
job_array
[
i
]);
}
},
priv
.
interval
);
}
};
/**
* Stops listening to the job array.
* @method stop
*/
that
.
stop
=
function
()
{
if
(
priv
.
interval_id
!==
null
)
{
clearInterval
(
priv
.
interval_id
);
priv
.
interval_id
=
null
;
if
(
priv
.
job_array
.
length
===
0
)
{
localstorage
.
removeItem
(
priv
.
getJobArrayName
());
}
}
};
/**
* Try to restore an the inactive older jio instances.
* It will restore the on going or initial jobs from their job array
* and it will add them to this job array.
* @method restoreOldJio
*/
priv
.
restoreOldJio
=
function
()
{
var
i
,
jio_id_a
;
priv
.
lastrestore
=
priv
.
lastrestore
||
0
;
if
(
priv
.
lastrestore
>
(
Date
.
now
())
-
2000
)
{
return
;
}
jio_id_a
=
localstorage
.
getItem
(
'
jio/id_array
'
)
||
[];
for
(
i
=
0
;
i
<
jio_id_a
.
length
;
i
+=
1
)
{
priv
.
restoreOldJioId
(
jio_id_a
[
i
]);
}
priv
.
lastrestore
=
Date
.
now
();
};
/**
* Try to restore an old jio according to an id.
* @method restoreOldJioId
* @param {number} id The jio id.
*/
priv
.
restoreOldJioId
=
function
(
id
)
{
var
jio_date
;
jio_date
=
localstorage
.
getItem
(
'
jio/id/
'
+
id
)
||
0
;
if
(
new
Date
(
jio_date
).
getTime
()
<
(
Date
.
now
()
-
10000
))
{
// 10 sec
priv
.
restoreOldJobFromJioId
(
id
);
priv
.
removeOldJioId
(
id
);
priv
.
removeJobArrayFromJioId
(
id
);
}
};
/**
* Try to restore all jobs from another jio according to an id.
* @method restoreOldJobFromJioId
* @param {number} id The jio id.
*/
priv
.
restoreOldJobFromJioId
=
function
(
id
)
{
var
i
,
command_object
,
jio_job_array
;
jio_job_array
=
localstorage
.
getItem
(
'
jio/job_array/
'
+
id
)
||
[];
for
(
i
=
0
;
i
<
jio_job_array
.
length
;
i
+=
1
)
{
command_object
=
command
(
jio_job_array
[
i
].
command
);
if
(
command_object
.
canBeRestored
())
{
that
.
addJob
(
job
({
storage
:
that
.
storage
(
jio_job_array
[
i
].
storage
),
command
:
command_object
}));
}
}
};
/**
* Removes a jio instance according to an id.
* @method removeOldJioId
* @param {number} id The jio id.
*/
priv
.
removeOldJioId
=
function
(
id
)
{
var
i
,
jio_id_array
,
new_array
=
[];
jio_id_array
=
localstorage
.
getItem
(
'
jio/id_array
'
)
||
[];
for
(
i
=
0
;
i
<
jio_id_array
.
length
;
i
+=
1
)
{
if
(
jio_id_array
[
i
]
!==
id
)
{
new_array
.
push
(
jio_id_array
[
i
]);
}
}
localstorage
.
setItem
(
'
jio/id_array
'
,
new_array
);
localstorage
.
removeItem
(
'
jio/id/
'
+
id
);
};
/**
* Removes a job array from a jio instance according to an id.
* @method removeJobArrayFromJioId
* @param {number} id The jio id.
*/
priv
.
removeJobArrayFromJioId
=
function
(
id
)
{
localstorage
.
removeItem
(
'
jio/job_array/
'
+
id
);
};
/**
* Executes a job.
* @method execute
* @param {object} job The job object.
*/
that
.
execute
=
function
(
job
)
{
try
{
job
.
execute
();
}
catch
(
e
)
{
switch
(
e
.
name
)
{
case
'
jobNotReadyException
'
:
break
;
// do nothing
case
'
tooMuchTriesJobException
'
:
break
;
// do nothing
default
:
throw
e
;
}
}
priv
.
copyJobArrayToLocal
();
};
/**
* Checks if a job exists in the job array according to a job id.
* @method jobIdExists
* @param {number} id The job id.
* @return {boolean} true if exists, else false.
*/
that
.
jobIdExists
=
function
(
id
)
{
var
i
;
for
(
i
=
0
;
i
<
priv
.
job_array
.
length
;
i
+=
1
)
{
if
(
priv
.
job_array
[
i
].
getId
()
===
id
)
{
return
true
;
}
}
return
false
;
};
/**
* Terminate a job. It only remove it from the job array.
* @method terminateJob
* @param {object} job The job object
*/
that
.
terminateJob
=
function
(
job
)
{
priv
.
removeJob
(
job
);
};
/**
* Adds a job to the current job array.
* @method addJob
* @param {object} job The new job.
*/
that
.
addJob
=
function
(
job
)
{
var
result_array
=
that
.
validateJobAccordingToJobList
(
priv
.
job_array
,
job
);
priv
.
appendJob
(
job
,
result_array
);
};
/**
* Generate a result array containing action string to do with the good job.
* @method validateJobAccordingToJobList
* @param {array} job_array A job array.
* @param {object} job The new job to compare with.
* @return {array} A result array.
*/
that
.
validateJobAccordingToJobList
=
function
(
job_array
,
job
)
{
var
i
,
result_array
=
[];
for
(
i
=
0
;
i
<
job_array
.
length
;
i
+=
1
)
{
result_array
.
push
(
jobRules
.
validateJobAccordingToJob
(
job_array
[
i
],
job
));
}
return
result_array
;
};
/**
* It will manage the job in order to know what to do thanks to a result
* array. The new job can be added to the job array, but it can also be
* not accepted. It is this method which can tells jobs to wait for another
* one, to replace one or to eliminate some while browsing.
* @method appendJob
* @param {object} job The job to append.
* @param {array} result_array The result array.
*/
priv
.
appendJob
=
function
(
job
,
result_array
)
{
var
i
;
if
(
priv
.
job_array
.
length
!==
result_array
.
length
)
{
throw
new
RangeError
(
"
Array out of bound
"
);
}
for
(
i
=
0
;
i
<
result_array
.
length
;
i
+=
1
)
{
if
(
result_array
[
i
].
action
===
'
dont accept
'
)
{
return
job
.
notAccepted
();
}
}
for
(
i
=
0
;
i
<
result_array
.
length
;
i
+=
1
)
{
switch
(
result_array
[
i
].
action
)
{
case
'
eliminate
'
:
result_array
[
i
].
job
.
eliminated
();
priv
.
removeJob
(
result_array
[
i
].
job
);
break
;
case
'
update
'
:
result_array
[
i
].
job
.
update
(
job
);
priv
.
copyJobArrayToLocal
();
return
;
case
'
wait
'
:
job
.
waitForJob
(
result_array
[
i
].
job
);
break
;
default
:
break
;
}
}
priv
.
job_array
.
push
(
job
);
priv
.
copyJobArrayToLocal
();
};
that
.
serialized
=
function
()
{
var
a
=
[],
i
,
job_array
=
priv
.
job_array
||
[];
for
(
i
=
0
;
i
<
job_array
.
length
;
i
+=
1
)
{
a
.
push
(
job_array
[
i
].
serialized
());
}
return
a
;
};
return
that
;
}());
/*jslint indent: 2, maxlen: 80, sloppy: true */
var
jobRules
=
(
function
()
{
var
that
=
{},
priv
=
{};
priv
.
compare
=
{};
priv
.
action
=
{};
Object
.
defineProperty
(
that
,
"
eliminate
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
return
'
eliminate
'
;
}
});
Object
.
defineProperty
(
that
,
"
update
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
return
'
update
'
;
}
});
Object
.
defineProperty
(
that
,
"
dontAccept
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
return
'
dont accept
'
;
}
});
Object
.
defineProperty
(
that
,
"
wait
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
return
'
wait
'
;
}
});
Object
.
defineProperty
(
that
,
"
ok
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
return
'
none
'
;
}
});
that
.
default_action
=
that
.
ok
;
that
.
default_compare
=
function
(
job1
,
job2
)
{
return
job1
.
getId
()
!==
job2
.
getId
()
&&
job1
.
getStatus
().
getLabel
()
!==
"
done
"
&&
job1
.
getStatus
().
getLabel
()
!==
"
fail
"
&&
JSON
.
stringify
(
job1
.
getStorage
().
serialized
())
===
JSON
.
stringify
(
job2
.
getStorage
().
serialized
());
};
// Compare Functions //
Object
.
defineProperty
(
that
,
"
sameDocumentId
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
job1
,
job2
)
{
return
job1
.
getCommand
().
getDocId
()
===
job2
.
getCommand
().
getDocId
();
}
});
Object
.
defineProperty
(
that
,
"
sameRevision
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
job1
,
job2
)
{
return
job1
.
getCommand
().
getDocInfo
(
"
_rev
"
)
===
job2
.
getCommand
().
getDocInfo
(
"
_rev
"
);
}
});
Object
.
defineProperty
(
that
,
"
sameAttachmentId
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
job1
,
job2
)
{
return
job1
.
getCommand
().
getAttachmentId
()
===
job2
.
getCommand
().
getAttachmentId
();
}
});
Object
.
defineProperty
(
that
,
"
sameDocument
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
job1
,
job2
)
{
return
JSON
.
stringify
(
job1
.
getCommand
().
cloneDoc
())
===
JSON
.
stringify
(
job2
.
getCommand
().
cloneDoc
());
}
});
Object
.
defineProperty
(
that
,
"
sameOption
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
job1
,
job2
)
{
return
JSON
.
stringify
(
job1
.
getCommand
().
cloneOption
())
===
JSON
.
stringify
(
job2
.
getCommand
().
cloneOption
());
}
});
// Methods //
/**
* Returns an action according the jobs given in parameters.
* @method getAction
* @param {object} job1 The already existant job.
* @param {object} job2 The job to compare with.
* @return {string} An action string.
*/
priv
.
getAction
=
function
(
job1
,
job2
)
{
var
method1
,
method2
,
tmp
=
priv
.
action
,
i
,
j
,
condition_list
=
[],
res
;
method1
=
job1
.
getCommand
().
getLabel
();
method2
=
job2
.
getCommand
().
getLabel
();
tmp
=
tmp
[
method1
]
=
tmp
[
method1
]
||
{};
tmp
=
tmp
[
method2
]
=
tmp
[
method2
]
||
[];
for
(
i
=
0
;
i
<
tmp
.
length
;
i
+=
1
)
{
// browsing all method1 method2 rules
condition_list
=
tmp
[
i
].
condition_list
;
res
=
true
;
for
(
j
=
0
;
j
<
condition_list
.
length
;
j
+=
1
)
{
// test all the rule's conditions
if
(
!
condition_list
[
j
](
job1
,
job2
))
{
res
=
false
;
break
;
}
}
if
(
res
)
{
// if all respects condition list, then action
return
tmp
[
i
].
rule
();
}
}
return
that
.
default_action
();
};
/**
* Checks if the two jobs are comparable.
* @method canCompare
* @param {object} job1 The already existant job.
* @param {object} job2 The job to compare with.
* @return {boolean} true if comparable, else false.
*/
priv
.
canCompare
=
function
(
job1
,
job2
)
{
var
method1
,
method2
;
method1
=
job1
.
getCommand
().
getLabel
();
method2
=
job2
.
getCommand
().
getLabel
();
if
(
priv
.
compare
[
method1
]
&&
priv
.
compare
[
method1
][
method2
])
{
return
priv
.
compare
[
method1
][
method2
](
job1
,
job2
);
}
return
that
.
default_compare
(
job1
,
job2
);
};
/**
* Returns an action string to show what to do if we want to add a job.
* @method validateJobAccordingToJob
* @param {object} job1 The current job.
* @param {object} job2 The new job.
* @return {string} The action string.
*/
Object
.
defineProperty
(
that
,
"
validateJobAccordingToJob
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
job1
,
job2
)
{
if
(
priv
.
canCompare
(
job1
,
job2
))
{
return
{
action
:
priv
.
getAction
(
job1
,
job2
),
job
:
job1
};
}
return
{
action
:
that
.
default_action
(
job1
,
job2
),
job
:
job1
};
}
});
/**
* Adds a rule the action rules.
* @method addActionRule
* @param {string} method1 The action label from the current job.
* @param {boolean} ongoing Is this action is on going or not?
* @param {string} method2 The action label from the new job.
* @param {function} rule The rule that return an action string.
*/
Object
.
defineProperty
(
that
,
"
addActionRule
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
method1
,
method2
,
condition_list
,
rule
)
{
var
tmp
=
priv
.
action
;
tmp
=
tmp
[
method1
]
=
tmp
[
method1
]
||
{};
tmp
=
tmp
[
method2
]
=
tmp
[
method2
]
||
[];
tmp
.
push
({
"
condition_list
"
:
condition_list
,
"
rule
"
:
rule
});
}
});
/**
* Adds a rule the compare rules.
* @method addCompareRule
* @param {string} method1 The action label from the current job.
* @param {string} method2 The action label from the new job.
* @param {function} rule The rule that return a boolean
* - true if job1 and job2 can be compared, else false.
*/
Object
.
defineProperty
(
that
,
"
addCompareRule
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
method1
,
method2
,
rule
)
{
priv
.
compare
[
method1
]
=
priv
.
compare
[
method1
]
||
{};
priv
.
compare
[
method1
][
method2
]
=
rule
;
}
});
////////////////////////////////////////////////////////////////////////////
// Adding some rules
/*
Rules
original job |job to add |condition |action
post post same doc update
" " same docid, same rev wait
" put " "
" putA " "
" remove " "
" removeA " "
put post same docid, same rev wait
" put same doc update
" " same docid, same rev wait
" putA " "
" remove " "
" removeA " "
putA post same docid, same rev wait
" put " "
" putA same doc update
" " same docid, same rev, same attmt wait
" remove same docid, same rev "
" removeA same docid, same rev, same attmt "
remove post same docid, same rev wait
" put " "
" putA " "
" remove " update
" removeA " wait
removeA post same docid, same rev wait
" put " "
" putA same docid, same rev, same attmt "
" remove same docid, same rev "
" removeA same doc update
" removeA same docid, same rev, same attmt wait
get get same doc, same options update
getA getA same doc, same options update
allDocs allDocs same doc, same options update
*/
that
.
addActionRule
(
"
post
"
,
"
post
"
,
[
that
.
sameDocument
],
that
.
update
);
that
.
addActionRule
(
"
post
"
,
"
post
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
post
"
,
"
put
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
post
"
,
"
putAttachment
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
post
"
,
"
remove
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
post
"
,
"
removeAttachment
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
put
"
,
"
post
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
put
"
,
"
put
"
,
[
that
.
sameDocument
],
that
.
update
);
that
.
addActionRule
(
"
put
"
,
"
put
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
put
"
,
"
putAttachment
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
put
"
,
"
remove
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
put
"
,
"
removeAttachment
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
putAttachment
"
,
"
post
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
putAttachment
"
,
"
put
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
putAttachment
"
,
"
putAttachment
"
,
[
that
.
sameDocument
],
that
.
update
);
that
.
addActionRule
(
"
putAttachment
"
,
"
putAttachment
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
,
that
.
sameAttachmentId
],
that
.
wait
);
that
.
addActionRule
(
"
putAttachment
"
,
"
remove
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
putAttachment
"
,
"
removeAttachment
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
,
that
.
sameAttachmentId
],
that
.
wait
);
that
.
addActionRule
(
"
remove
"
,
"
post
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
remove
"
,
"
put
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
remove
"
,
"
putAttachment
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
remove
"
,
"
remove
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
update
);
that
.
addActionRule
(
"
remove
"
,
"
removeAttachment
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
removeAttachment
"
,
"
post
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
removeAttachment
"
,
"
put
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
removeAttachment
"
,
"
putAttachment
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
,
that
.
sameAttachmentId
],
that
.
wait
);
that
.
addActionRule
(
"
removeAttachment
"
,
"
remove
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
],
that
.
wait
);
that
.
addActionRule
(
"
removeAttachment
"
,
"
removeAttachment
"
,
[
that
.
sameDocument
],
that
.
update
);
that
.
addActionRule
(
"
removeAttachment
"
,
"
removeAttachment
"
,
[
that
.
sameDocumentId
,
that
.
sameRevision
,
that
.
sameAttachmentId
],
that
.
wait
);
that
.
addActionRule
(
"
get
"
,
"
get
"
,
[
that
.
sameDocument
,
that
.
sameOption
],
that
.
update
);
that
.
addActionRule
(
"
getAttachment
"
,
"
getAttachment
"
,
[
that
.
sameDocument
,
that
.
sameOption
],
that
.
update
);
that
.
addActionRule
(
"
allDocs
"
,
"
allDocs
"
,
[
that
.
sameDocument
,
that
.
sameOption
],
that
.
update
);
// end adding rules
////////////////////////////////////////////////////////////////////////////
return
that
;
}());
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global spec: true, localstorage: true,
activityUpdater: true, jobManager: true, storage: true,
storage_type_object: true, invalidStorageType: true, jobRules: true,
job: true, postCommand: true, putCommand: true, getCommand:true,
allDocsCommand: true, putAttachmentCommand: true,
getAttachmentCommand: true, removeAttachmentCommand: true,
removeCommand: true, checkCommand: true, repairCommand: true */
// Class jio
var
that
=
{},
priv
=
{},
jio_id_array_name
=
'
jio/id_array
'
;
spec
=
spec
||
{};
// Attributes //
priv
.
id
=
null
;
priv
.
storage_spec
=
spec
;
priv
.
environments
=
{};
// initialize //
priv
.
init
=
function
()
{
// Initialize the jio id and add the new id to the list
if
(
priv
.
id
===
null
)
{
var
i
,
jio_id_a
=
localstorage
.
getItem
(
jio_id_array_name
)
||
[];
priv
.
id
=
1
;
for
(
i
=
0
;
i
<
jio_id_a
.
length
;
i
+=
1
)
{
if
(
jio_id_a
[
i
]
>=
priv
.
id
)
{
priv
.
id
=
jio_id_a
[
i
]
+
1
;
}
}
jio_id_a
.
push
(
priv
.
id
);
localstorage
.
setItem
(
jio_id_array_name
,
jio_id_a
);
activityUpdater
.
setId
(
priv
.
id
);
jobManager
.
setId
(
priv
.
id
);
}
};
// Methods //
/**
* Returns a storage from a storage description.
* @method storage
* @param {object} spec The specifications.
* @param {object} my The protected object.
* @param {string} forcetype Force storage type
* @return {object} The storage object.
*/
Object
.
defineProperty
(
that
,
"
storage
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
spec
,
my
,
forcetype
)
{
var
spec_str
,
type
;
spec
=
spec
||
{};
my
=
my
||
{};
my
.
basicStorage
=
storage
;
spec_str
=
JSON
.
stringify
(
spec
);
// environment initialization
priv
.
environments
[
spec_str
]
=
priv
.
environments
[
spec_str
]
||
{};
my
.
env
=
priv
.
environments
[
spec_str
];
my
.
storage
=
that
.
storage
;
// NOTE : or proxy storage
type
=
forcetype
||
spec
.
type
||
'
base
'
;
if
(
type
===
'
base
'
)
{
return
storage
(
spec
,
my
);
}
if
(
!
storage_type_object
[
type
])
{
throw
invalidStorageType
({
"
type
"
:
type
,
"
message
"
:
"
Storage does not exists.
"
});
}
return
storage_type_object
[
type
](
spec
,
my
);
}
});
jobManager
.
storage
=
that
.
storage
;
Object
.
defineProperty
(
that
,
"
start
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
priv
.
init
();
activityUpdater
.
start
();
jobManager
.
start
();
}
});
Object
.
defineProperty
(
that
,
"
stop
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
jobManager
.
stop
();
}
});
Object
.
defineProperty
(
that
,
"
close
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
activityUpdater
.
stop
();
jobManager
.
stop
();
priv
.
id
=
null
;
}
});
/**
* Returns the jio id.
* @method getId
* @return {number} The jio id.
*/
Object
.
defineProperty
(
that
,
"
getId
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
return
priv
.
id
;
}
});
/**
* Returns the jio job rules object used by the job manager.
* @method getJobRules
* @return {object} The job rules object
*/
Object
.
defineProperty
(
that
,
"
getJobRules
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
return
jobRules
;
}
});
/**
* Checks if the storage description is valid or not.
* @method validateStorageDescription
* @param {object} description The description object.
* @return {boolean} true if ok, else false.
*/
Object
.
defineProperty
(
that
,
"
validateStorageDescription
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
description
)
{
return
that
.
storage
(
description
).
isValid
();
}
});
Object
.
defineProperty
(
that
,
"
getJobArray
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
()
{
return
jobManager
.
serialized
();
}
});
priv
.
makeCallbacks
=
function
(
param
,
callback1
,
callback2
)
{
param
.
callback
=
function
(
err
,
val
)
{
if
(
err
)
{
param
.
error
(
err
);
}
else
{
param
.
success
(
val
);
}
};
param
.
success
=
function
(
val
)
{
param
.
callback
(
undefined
,
val
);
};
param
.
error
=
function
(
err
)
{
param
.
callback
(
err
,
undefined
);
};
if
(
typeof
callback1
===
'
function
'
)
{
if
(
typeof
callback2
===
'
function
'
)
{
param
.
success
=
callback1
;
param
.
error
=
callback2
;
}
else
{
param
.
callback
=
callback1
;
}
}
else
{
param
.
callback
=
function
()
{};
}
};
priv
.
parametersToObject
=
function
(
list
,
default_options
)
{
var
k
,
i
=
0
,
callbacks
=
[],
param
=
{
"
options
"
:
{}};
for
(
i
=
0
;
i
<
list
.
length
;
i
+=
1
)
{
if
(
typeof
list
[
i
]
===
'
object
'
)
{
// this is the option
param
.
options
=
list
[
i
];
for
(
k
in
default_options
)
{
if
((
typeof
default_options
[
k
])
!==
(
typeof
list
[
i
][
k
]))
{
param
.
options
[
k
]
=
default_options
[
k
];
}
}
}
if
(
typeof
list
[
i
]
===
'
function
'
)
{
// this is a callback
callbacks
.
push
(
list
[
i
]);
}
}
priv
.
makeCallbacks
(
param
,
callbacks
[
0
],
callbacks
[
1
]);
return
param
;
};
priv
.
addJob
=
function
(
commandCreator
,
spec
)
{
jobManager
.
addJob
(
job
({
"
storage
"
:
that
.
storage
(
priv
.
storage_spec
),
"
command
"
:
commandCreator
(
spec
)
}));
};
/**
* Post a document.
* @method post
* @param {object} doc The document object. Contains at least:
* - {string} _id The document id (optional)
* For revision managing: choose at most one of the following informations:
* - {string} _rev The revision we want to update
* - {string} _revs_info The revision information we want the document to have
* - {string} _revs The revision history we want the document to have
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* @param {function} callback (optional) The callback(err,response).
* @param {function} error (optional) The callback on error, if this
* callback is given in parameter, "callback" is changed as "success",
* called on success.
*/
Object
.
defineProperty
(
that
,
"
post
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
doc
,
options
,
success
,
error
)
{
var
param
=
priv
.
parametersToObject
(
[
options
,
success
,
error
],
{
max_retry
:
0
}
);
priv
.
addJob
(
postCommand
,
{
doc
:
doc
,
options
:
param
.
options
,
callbacks
:
{
success
:
param
.
success
,
error
:
param
.
error
}
});
}
});
/**
* Put a document.
* @method put
* @param {object} doc The document object. Contains at least:
* - {string} _id The document id
* For revision managing: choose at most one of the following informations:
* - {string} _rev The revision we want to update
* - {string} _revs_info The revision information we want the document to have
* - {string} _revs The revision history we want the document to have
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* @param {function} callback (optional) The callback(err,response).
* @param {function} error (optional) The callback on error, if this
* callback is given in parameter, "callback" is changed as "success",
* called on success.
*/
Object
.
defineProperty
(
that
,
"
put
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
doc
,
options
,
success
,
error
)
{
var
param
=
priv
.
parametersToObject
(
[
options
,
success
,
error
],
{
max_retry
:
0
}
);
priv
.
addJob
(
putCommand
,
{
doc
:
doc
,
options
:
param
.
options
,
callbacks
:
{
success
:
param
.
success
,
error
:
param
.
error
}
});
}
});
/**
* Get a document.
* @method get
* @param {string} doc The document object. Contains at least:
* - {string} _id The document id
* For revision managing:
* - {string} _rev The revision we want to get. (optional)
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* For revision managing:
* - {boolean} revs Include revision history of the document.
* - {boolean} revs_info Include list of revisions, and their availability.
* - {boolean} conflicts Include a list of conflicts.
* @param {function} callback (optional) The callback(err,response).
* @param {function} error (optional) The callback on error, if this
* callback is given in parameter, "callback" is changed as "success",
* called on success.
*/
Object
.
defineProperty
(
that
,
"
get
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
doc
,
options
,
success
,
error
)
{
var
param
=
priv
.
parametersToObject
(
[
options
,
success
,
error
],
{
max_retry
:
3
}
);
priv
.
addJob
(
getCommand
,
{
doc
:
doc
,
options
:
param
.
options
,
callbacks
:
{
success
:
param
.
success
,
error
:
param
.
error
}
});
}
});
/**
* Remove a document.
* @method remove
* @param {object} doc The document object. Contains at least:
* - {string} _id The document id
* For revision managing:
* - {string} _rev The revision we want to remove
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* @param {function} callback (optional) The callback(err,response).
* @param {function} error (optional) The callback on error, if this
* callback is given in parameter, "callback" is changed as "success",
* called on success.
*/
Object
.
defineProperty
(
that
,
"
remove
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
doc
,
options
,
success
,
callback
)
{
var
param
=
priv
.
parametersToObject
(
[
options
,
success
,
callback
],
{
max_retry
:
0
}
);
priv
.
addJob
(
removeCommand
,
{
doc
:
doc
,
options
:
param
.
options
,
callbacks
:
{
success
:
param
.
success
,
error
:
param
.
error
}
});
}
});
/**
* Get a list of documents.
* @method allDocs
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* - {boolean} include_docs Include document metadata
* @param {function} callback (optional) The callback(err,response).
* @param {function} error (optional) The callback on error, if this
* callback is given in parameter, "callback" is changed as "success",
* called on success.
*/
Object
.
defineProperty
(
that
,
"
allDocs
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
options
,
success
,
error
)
{
var
param
=
priv
.
parametersToObject
(
[
options
,
success
,
error
],
{
max_retry
:
3
}
);
priv
.
addJob
(
allDocsCommand
,
{
options
:
param
.
options
,
callbacks
:
{
success
:
param
.
success
,
error
:
param
.
error
}
});
}
});
/**
* Get an attachment from a document.
* @method gettAttachment
* @param {object} doc The document object. Contains at least:
* - {string} _id The document id
* - {string} _attachment The attachment id
* For revision managing:
* - {string} _rev The document revision
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* @param {function} callback (optional) The callback(err,respons)
* @param {function} error (optional) The callback on error, if this
* callback is given in parameter, "callback" is changed as "success",
* called on success.
*/
Object
.
defineProperty
(
that
,
"
getAttachment
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
doc
,
options
,
success
,
error
)
{
var
param
=
priv
.
parametersToObject
(
[
options
,
success
,
error
],
{
max_retry
:
3
}
);
priv
.
addJob
(
getAttachmentCommand
,
{
doc
:
doc
,
options
:
param
.
options
,
callbacks
:
{
success
:
param
.
success
,
error
:
param
.
error
}
});
}
});
/**
* Put an attachment to a document.
* @method putAttachment
* @param {object} doc The document object. Contains at least:
* - {string} _id The document id
* - {string} _attachment The attachment id
* - {string} _data The attachment data
* - {string} _mimetype The attachment mimetype
* For revision managing:
* - {string} _rev The document revision
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* @param {function} callback (optional) The callback(err,respons)
* @param {function} error (optional) The callback on error, if this
* callback is given in parameter, "callback" is changed as "success",
* called on success.
*/
Object
.
defineProperty
(
that
,
"
putAttachment
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
doc
,
options
,
success
,
error
)
{
var
param
=
priv
.
parametersToObject
(
[
options
,
success
,
error
],
{
max_retry
:
0
}
);
priv
.
addJob
(
putAttachmentCommand
,
{
doc
:
doc
,
options
:
param
.
options
,
callbacks
:
{
success
:
param
.
success
,
error
:
param
.
error
}
});
}
});
/**
* Put an attachment to a document.
* @method putAttachment
* @param {object} doc The document object. Contains at least:
* - {string} _id The document id
* - {string} _attachment The attachment id
* For revision managing:
* - {string} _rev The document revision
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* @param {function} callback (optional) The callback(err,respons)
* @param {function} error (optional) The callback on error, if this
* callback is given in parameter, "callback" is changed as "success",
* called on success.
*/
Object
.
defineProperty
(
that
,
"
removeAttachment
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
doc
,
options
,
success
,
error
)
{
var
param
=
priv
.
parametersToObject
(
[
options
,
success
,
error
],
{
max_retry
:
0
}
);
priv
.
addJob
(
removeAttachmentCommand
,
{
doc
:
doc
,
options
:
param
.
options
,
callbacks
:
{
success
:
param
.
success
,
error
:
param
.
error
}
});
}
});
/**
* Check a document.
* @method check
* @param {object} doc The document object. Contains at least:
* - {string} _id The document id
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* @param {function} callback (optional) The callback(err,response).
* @param {function} error (optional) The callback on error, if this
* callback is given in parameter, "callback" is changed as "success",
* called on success.
*/
Object
.
defineProperty
(
that
,
"
check
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
doc
,
options
,
success
,
callback
)
{
var
param
=
priv
.
parametersToObject
(
[
options
,
success
,
callback
],
{
max_retry
:
3
}
);
priv
.
addJob
(
checkCommand
,
{
doc
:
doc
,
options
:
param
.
options
,
callbacks
:
{
success
:
param
.
success
,
error
:
param
.
error
}
});
}
});
/**
* Repair a document.
* @method repair
* @param {object} doc The document object. Contains at least:
* - {string} _id The document id
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* @param {function} callback (optional) The callback(err,response).
* @param {function} error (optional) The callback on error, if this
* callback is given in parameter, "callback" is changed as "success",
* called on success.
*/
Object
.
defineProperty
(
that
,
"
repair
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
doc
,
options
,
success
,
callback
)
{
var
param
=
priv
.
parametersToObject
(
[
options
,
success
,
callback
],
{
max_retry
:
3
}
);
priv
.
addJob
(
repairCommand
,
{
doc
:
doc
,
options
:
param
.
options
,
callbacks
:
{
success
:
param
.
success
,
error
:
param
.
error
}
});
}
});
return
that
;
};
// End Class jio
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global jio: true, invalidStorageType: true */
var
storage_type_object
=
{
// -> 'key':constructorFunction
'
base
'
:
function
()
{}
// overriden by jio
};
var
jioNamespace
=
(
function
(
spec
)
{
var
that
=
{};
spec
=
spec
||
{};
// Attributes //
// Methods //
/**
* Creates a new jio instance.
* @method newJio
* @param {object} spec The storage description
* @return {object} The new Jio instance.
*/
Object
.
defineProperty
(
that
,
"
newJio
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
spec
)
{
var
storage
=
spec
,
instance
=
null
;
if
(
typeof
storage
===
'
string
'
)
{
storage
=
JSON
.
parse
(
storage
);
}
else
{
storage
=
JSON
.
stringify
(
storage
);
if
(
storage
!==
undefined
)
{
storage
=
JSON
.
parse
(
storage
);
}
}
storage
=
storage
||
{
type
:
'
base
'
};
instance
=
jio
(
storage
);
instance
.
start
();
return
instance
;
}
});
/**
* Add a storage type to jio.
* @method addStorageType
* @param {string} type The storage type
* @param {function} constructor The associated constructor
*/
Object
.
defineProperty
(
that
,
"
addStorageType
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
function
(
type
,
constructor
)
{
constructor
=
constructor
||
function
()
{
return
null
;
};
if
(
storage_type_object
[
type
])
{
throw
invalidStorageType
({
type
:
type
,
message
:
'
Already known.
'
});
}
storage_type_object
[
type
]
=
constructor
;
}
});
return
that
;
}());
Object
.
defineProperty
(
scope
,
"
jIO
"
,
{
configurable
:
false
,
enumerable
:
false
,
writable
:
false
,
value
:
jioNamespace
});
}(
window
,
hex_md5
));
DREAM/dream/dream/platform/static/lib/jio.localstorage.js
0 → 100644
View file @
526eb710
/*
* Copyright 2013, Nexedi SA
* Released under the LGPL license.
* http://www.gnu.org/licenses/lgpl.html
*/
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global jIO: true, localStorage: true, setTimeout: true,
complex_queries: true */
/**
* JIO Local Storage. Type = 'local'.
* Local browser "database" storage.
*/
jIO
.
addStorageType
(
'
local
'
,
function
(
spec
,
my
)
{
spec
=
spec
||
{};
var
that
,
priv
,
localstorage
;
that
=
my
.
basicStorage
(
spec
,
my
);
priv
=
{};
/*
* Wrapper for the localStorage used to simplify instion of any kind of
* values
*/
localstorage
=
{
getItem
:
function
(
item
)
{
var
value
=
localStorage
.
getItem
(
item
);
return
value
===
null
?
null
:
JSON
.
parse
(
value
);
},
setItem
:
function
(
item
,
value
)
{
return
localStorage
.
setItem
(
item
,
JSON
.
stringify
(
value
));
},
removeItem
:
function
(
item
)
{
return
localStorage
.
removeItem
(
item
);
}
};
// attributes
priv
.
username
=
spec
.
username
||
''
;
priv
.
application_name
=
spec
.
application_name
||
'
untitled
'
;
priv
.
localpath
=
'
jio/localstorage/
'
+
priv
.
username
+
'
/
'
+
priv
.
application_name
;
// ==================== Tools ====================
/**
* Generate a new uuid
* @method generateUuid
* @return {string} The new uuid
*/
priv
.
generateUuid
=
function
()
{
var
S4
=
function
()
{
/* 65536 */
var
i
,
string
=
Math
.
floor
(
Math
.
random
()
*
0x10000
).
toString
(
16
);
for
(
i
=
string
.
length
;
i
<
4
;
i
+=
1
)
{
string
=
'
0
'
+
string
;
}
return
string
;
};
return
S4
()
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
S4
()
+
S4
();
};
/**
* Update [doc] the document object and remove [doc] keys
* which are not in [new_doc]. It only changes [doc] keys not starting
* with an underscore.
* ex: doc: {key:value1,_key:value2} with
* new_doc: {key:value3,_key:value4} updates
* doc: {key:value3,_key:value2}.
* @param {object} doc The original document object.
* @param {object} new_doc The new document object
*/
priv
.
documentObjectUpdate
=
function
(
doc
,
new_doc
)
{
var
k
;
for
(
k
in
doc
)
{
if
(
doc
.
hasOwnProperty
(
k
))
{
if
(
k
[
0
]
!==
'
_
'
)
{
delete
doc
[
k
];
}
}
}
for
(
k
in
new_doc
)
{
if
(
new_doc
.
hasOwnProperty
(
k
))
{
if
(
k
[
0
]
!==
'
_
'
)
{
doc
[
k
]
=
new_doc
[
k
];
}
}
}
};
/**
* Checks if an object has no enumerable keys
* @method objectIsEmpty
* @param {object} obj The object
* @return {boolean} true if empty, else false
*/
priv
.
objectIsEmpty
=
function
(
obj
)
{
var
k
;
for
(
k
in
obj
)
{
if
(
obj
.
hasOwnProperty
(
k
))
{
return
false
;
}
}
return
true
;
};
// ===================== overrides ======================
that
.
specToStore
=
function
()
{
return
{
"
application_name
"
:
priv
.
application_name
,
"
username
"
:
priv
.
username
};
};
that
.
validateState
=
function
()
{
if
(
typeof
priv
.
username
===
"
string
"
&&
priv
.
username
!==
''
)
{
return
''
;
}
return
'
Need at least one parameter: "username".
'
;
};
// ==================== commands ====================
/**
* Create a document in local storage.
* @method post
* @param {object} command The JIO command
*/
that
.
post
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
,
doc_id
=
command
.
getDocId
();
if
(
!
doc_id
)
{
doc_id
=
priv
.
generateUuid
();
}
doc
=
localstorage
.
getItem
(
priv
.
localpath
+
"
/
"
+
doc_id
);
if
(
doc
===
null
)
{
doc
=
command
.
cloneDoc
();
doc
.
_id
=
doc_id
;
// the document does not exist
localstorage
.
setItem
(
priv
.
localpath
+
"
/
"
+
doc_id
,
doc
);
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
doc_id
});
}
else
{
// the document already exists
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflicts
"
,
"
error
"
:
"
conflicts
"
,
"
message
"
:
"
Cannot create a new document
"
,
"
reason
"
:
"
Document already exists
"
});
}
});
};
/**
* Create or update a document in local storage.
* @method put
* @param {object} command The JIO command
*/
that
.
put
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
;
doc
=
localstorage
.
getItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
());
if
(
doc
===
null
)
{
// the document does not exist
doc
=
command
.
cloneDoc
();
}
else
{
// the document already exists
priv
.
documentObjectUpdate
(
doc
,
command
.
cloneDoc
());
}
// write
localstorage
.
setItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
(),
doc
);
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()
});
});
};
/**
* Add an attachment to a document
* @method putAttachment
* @param {object} command The JIO command
*/
that
.
putAttachment
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
;
doc
=
localstorage
.
getItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
());
if
(
doc
===
null
)
{
// the document does not exist
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Impossible to add attachment
"
,
"
reason
"
:
"
Document not found
"
});
return
;
}
// the document already exists
doc
.
_attachments
=
doc
.
_attachments
||
{};
doc
.
_attachments
[
command
.
getAttachmentId
()]
=
{
"
content_type
"
:
command
.
getAttachmentMimeType
(),
"
digest
"
:
"
md5-
"
+
command
.
md5SumAttachmentData
(),
"
length
"
:
command
.
getAttachmentLength
()
};
// upload data
localstorage
.
setItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
()
+
"
/
"
+
command
.
getAttachmentId
(),
command
.
getAttachmentData
());
// write document
localstorage
.
setItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
(),
doc
);
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
(),
"
attachment
"
:
command
.
getAttachmentId
()
});
});
};
/**
* Get a document
* @method get
* @param {object} command The JIO command
*/
that
.
get
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
=
localstorage
.
getItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
());
if
(
doc
!==
null
)
{
that
.
success
(
doc
);
}
else
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Cannot find the document
"
,
"
reason
"
:
"
Document does not exist
"
});
}
});
};
/**
* Get a attachment
* @method getAttachment
* @param {object} command The JIO command
*/
that
.
getAttachment
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
=
localstorage
.
getItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
()
+
"
/
"
+
command
.
getAttachmentId
());
if
(
doc
!==
null
)
{
that
.
success
(
doc
);
}
else
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Cannot find the attachment
"
,
"
reason
"
:
"
Attachment does not exist
"
});
}
});
};
/**
* Remove a document
* @method remove
* @param {object} command The JIO command
*/
that
.
remove
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
,
i
,
attachment_list
;
doc
=
localstorage
.
getItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
());
attachment_list
=
[];
if
(
doc
!==
null
&&
typeof
doc
===
"
object
"
)
{
if
(
typeof
doc
.
_attachments
===
"
object
"
)
{
// prepare list of attachments
for
(
i
in
doc
.
_attachments
)
{
if
(
doc
.
_attachments
.
hasOwnProperty
(
i
))
{
attachment_list
.
push
(
i
);
}
}
}
}
else
{
return
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Document not found
"
,
"
reason
"
:
"
missing
"
});
}
localstorage
.
removeItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
());
// delete all attachments
for
(
i
=
0
;
i
<
attachment_list
.
length
;
i
+=
1
)
{
localstorage
.
removeItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
()
+
"
/
"
+
attachment_list
[
i
]);
}
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()
});
});
};
/**
* Remove an attachment
* @method removeAttachment
* @param {object} command The JIO command
*/
that
.
removeAttachment
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
,
error
,
i
,
attachment_list
;
error
=
function
(
word
)
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
word
+
"
not found
"
,
"
reason
"
:
"
missing
"
});
};
doc
=
localstorage
.
getItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
());
// remove attachment from document
if
(
doc
!==
null
&&
typeof
doc
===
"
object
"
&&
typeof
doc
.
_attachments
===
"
object
"
)
{
if
(
typeof
doc
.
_attachments
[
command
.
getAttachmentId
()]
===
"
object
"
)
{
delete
doc
.
_attachments
[
command
.
getAttachmentId
()];
if
(
priv
.
objectIsEmpty
(
doc
.
_attachments
))
{
delete
doc
.
_attachments
;
}
localstorage
.
setItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
(),
doc
);
localstorage
.
removeItem
(
priv
.
localpath
+
"
/
"
+
command
.
getDocId
()
+
"
/
"
+
command
.
getAttachmentId
());
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
(),
"
attachment
"
:
command
.
getAttachmentId
()
});
}
else
{
error
(
"
Attachment
"
);
}
}
else
{
error
(
"
Document
"
);
}
});
};
/**
* Get all filenames belonging to a user from the document index
* @method allDocs
* @param {object} command The JIO command
*/
that
.
allDocs
=
function
(
command
)
{
var
i
,
row
,
path_re
,
rows
=
[],
document_list
=
[],
option
,
document_object
;
path_re
=
new
RegExp
(
"
^
"
+
complex_queries
.
stringEscapeRegexpCharacters
(
priv
.
localpath
)
+
"
/[^/]+$
"
);
option
=
command
.
cloneOption
();
if
(
typeof
complex_queries
!==
"
object
"
||
(
option
.
query
===
undefined
&&
option
.
sort_on
===
undefined
&&
option
.
select_list
===
undefined
&&
option
.
include_docs
===
undefined
))
{
rows
=
[];
for
(
i
in
localStorage
)
{
if
(
localStorage
.
hasOwnProperty
(
i
))
{
// filter non-documents
if
(
path_re
.
test
(
i
))
{
row
=
{
value
:
{}
};
row
.
id
=
i
.
split
(
'
/
'
).
slice
(
-
1
)[
0
];
row
.
key
=
row
.
id
;
if
(
command
.
getOption
(
'
include_docs
'
))
{
row
.
doc
=
JSON
.
parse
(
localStorage
.
getItem
(
i
));
}
rows
.
push
(
row
);
}
}
}
that
.
success
({
"
rows
"
:
rows
,
"
total_rows
"
:
rows
.
length
});
}
else
{
// create complex query object from returned results
for
(
i
in
localStorage
)
{
if
(
localStorage
.
hasOwnProperty
(
i
))
{
if
(
path_re
.
test
(
i
))
{
document_list
.
push
(
localstorage
.
getItem
(
i
));
}
}
}
option
.
select_list
=
option
.
select_list
||
[];
option
.
select_list
.
push
(
"
_id
"
);
if
(
option
.
include_docs
===
true
)
{
document_object
=
{};
document_list
.
forEach
(
function
(
meta
)
{
document_object
[
meta
.
_id
]
=
meta
;
});
}
complex_queries
.
QueryFactory
.
create
(
option
.
query
||
""
).
exec
(
document_list
,
option
);
document_list
=
document_list
.
map
(
function
(
value
)
{
var
o
=
{
"
id
"
:
value
.
_id
,
"
key
"
:
value
.
_id
};
if
(
option
.
include_docs
===
true
)
{
o
.
doc
=
document_object
[
value
.
_id
];
delete
document_object
[
value
.
_id
];
}
delete
value
.
_id
;
o
.
value
=
value
;
return
o
;
});
that
.
success
({
"
total_rows
"
:
document_list
.
length
,
"
rows
"
:
document_list
});
}
};
return
that
;
});
DREAM/dream/dream/platform/static/lib/md5.js
0 → 100644
View file @
526eb710
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var
hexcase
=
0
;
/* hex output format. 0 - lowercase; 1 - uppercase */
var
b64pad
=
""
;
/* base-64 pad character. "=" for strict RFC compliance */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function
hex_md5
(
s
)
{
return
rstr2hex
(
rstr_md5
(
str2rstr_utf8
(
s
)));
}
function
b64_md5
(
s
)
{
return
rstr2b64
(
rstr_md5
(
str2rstr_utf8
(
s
)));
}
function
any_md5
(
s
,
e
)
{
return
rstr2any
(
rstr_md5
(
str2rstr_utf8
(
s
)),
e
);
}
function
hex_hmac_md5
(
k
,
d
)
{
return
rstr2hex
(
rstr_hmac_md5
(
str2rstr_utf8
(
k
),
str2rstr_utf8
(
d
)));
}
function
b64_hmac_md5
(
k
,
d
)
{
return
rstr2b64
(
rstr_hmac_md5
(
str2rstr_utf8
(
k
),
str2rstr_utf8
(
d
)));
}
function
any_hmac_md5
(
k
,
d
,
e
)
{
return
rstr2any
(
rstr_hmac_md5
(
str2rstr_utf8
(
k
),
str2rstr_utf8
(
d
)),
e
);
}
/*
* Perform a simple self-test to see if the VM is working
*/
function
md5_vm_test
()
{
return
hex_md5
(
"
abc
"
).
toLowerCase
()
==
"
900150983cd24fb0d6963f7d28e17f72
"
;
}
/*
* Calculate the MD5 of a raw string
*/
function
rstr_md5
(
s
)
{
return
binl2rstr
(
binl_md5
(
rstr2binl
(
s
),
s
.
length
*
8
));
}
/*
* Calculate the HMAC-MD5, of a key and some data (raw strings)
*/
function
rstr_hmac_md5
(
key
,
data
)
{
var
bkey
=
rstr2binl
(
key
);
if
(
bkey
.
length
>
16
)
bkey
=
binl_md5
(
bkey
,
key
.
length
*
8
);
var
ipad
=
Array
(
16
),
opad
=
Array
(
16
);
for
(
var
i
=
0
;
i
<
16
;
i
++
)
{
ipad
[
i
]
=
bkey
[
i
]
^
0x36363636
;
opad
[
i
]
=
bkey
[
i
]
^
0x5C5C5C5C
;
}
var
hash
=
binl_md5
(
ipad
.
concat
(
rstr2binl
(
data
)),
512
+
data
.
length
*
8
);
return
binl2rstr
(
binl_md5
(
opad
.
concat
(
hash
),
512
+
128
));
}
/*
* Convert a raw string to a hex string
*/
function
rstr2hex
(
input
)
{
try
{
hexcase
}
catch
(
e
)
{
hexcase
=
0
;
}
var
hex_tab
=
hexcase
?
"
0123456789ABCDEF
"
:
"
0123456789abcdef
"
;
var
output
=
""
;
var
x
;
for
(
var
i
=
0
;
i
<
input
.
length
;
i
++
)
{
x
=
input
.
charCodeAt
(
i
);
output
+=
hex_tab
.
charAt
((
x
>>>
4
)
&
0x0F
)
+
hex_tab
.
charAt
(
x
&
0x0F
);
}
return
output
;
}
/*
* Convert a raw string to a base-64 string
*/
function
rstr2b64
(
input
)
{
try
{
b64pad
}
catch
(
e
)
{
b64pad
=
''
;
}
var
tab
=
"
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
"
;
var
output
=
""
;
var
len
=
input
.
length
;
for
(
var
i
=
0
;
i
<
len
;
i
+=
3
)
{
var
triplet
=
(
input
.
charCodeAt
(
i
)
<<
16
)
|
(
i
+
1
<
len
?
input
.
charCodeAt
(
i
+
1
)
<<
8
:
0
)
|
(
i
+
2
<
len
?
input
.
charCodeAt
(
i
+
2
)
:
0
);
for
(
var
j
=
0
;
j
<
4
;
j
++
)
{
if
(
i
*
8
+
j
*
6
>
input
.
length
*
8
)
output
+=
b64pad
;
else
output
+=
tab
.
charAt
((
triplet
>>>
6
*
(
3
-
j
))
&
0x3F
);
}
}
return
output
;
}
/*
* Convert a raw string to an arbitrary string encoding
*/
function
rstr2any
(
input
,
encoding
)
{
var
divisor
=
encoding
.
length
;
var
i
,
j
,
q
,
x
,
quotient
;
/* Convert to an array of 16-bit big-endian values, forming the dividend */
var
dividend
=
Array
(
Math
.
ceil
(
input
.
length
/
2
));
for
(
i
=
0
;
i
<
dividend
.
length
;
i
++
)
{
dividend
[
i
]
=
(
input
.
charCodeAt
(
i
*
2
)
<<
8
)
|
input
.
charCodeAt
(
i
*
2
+
1
);
}
/*
* Repeatedly perform a long division. The binary array forms the dividend,
* the length of the encoding is the divisor. Once computed, the quotient
* forms the dividend for the next step. All remainders are stored for later
* use.
*/
var
full_length
=
Math
.
ceil
(
input
.
length
*
8
/
(
Math
.
log
(
encoding
.
length
)
/
Math
.
log
(
2
)));
var
remainders
=
Array
(
full_length
);
for
(
j
=
0
;
j
<
full_length
;
j
++
)
{
quotient
=
Array
();
x
=
0
;
for
(
i
=
0
;
i
<
dividend
.
length
;
i
++
)
{
x
=
(
x
<<
16
)
+
dividend
[
i
];
q
=
Math
.
floor
(
x
/
divisor
);
x
-=
q
*
divisor
;
if
(
quotient
.
length
>
0
||
q
>
0
)
quotient
[
quotient
.
length
]
=
q
;
}
remainders
[
j
]
=
x
;
dividend
=
quotient
;
}
/* Convert the remainders to the output string */
var
output
=
""
;
for
(
i
=
remainders
.
length
-
1
;
i
>=
0
;
i
--
)
output
+=
encoding
.
charAt
(
remainders
[
i
]);
return
output
;
}
/*
* Encode a string as utf-8.
* For efficiency, this assumes the input is valid utf-16.
*/
function
str2rstr_utf8
(
input
)
{
var
output
=
""
;
var
i
=
-
1
;
var
x
,
y
;
while
(
++
i
<
input
.
length
)
{
/* Decode utf-16 surrogate pairs */
x
=
input
.
charCodeAt
(
i
);
y
=
i
+
1
<
input
.
length
?
input
.
charCodeAt
(
i
+
1
)
:
0
;
if
(
0xD800
<=
x
&&
x
<=
0xDBFF
&&
0xDC00
<=
y
&&
y
<=
0xDFFF
)
{
x
=
0x10000
+
((
x
&
0x03FF
)
<<
10
)
+
(
y
&
0x03FF
);
i
++
;
}
/* Encode output as utf-8 */
if
(
x
<=
0x7F
)
output
+=
String
.
fromCharCode
(
x
);
else
if
(
x
<=
0x7FF
)
output
+=
String
.
fromCharCode
(
0xC0
|
((
x
>>>
6
)
&
0x1F
),
0x80
|
(
x
&
0x3F
));
else
if
(
x
<=
0xFFFF
)
output
+=
String
.
fromCharCode
(
0xE0
|
((
x
>>>
12
)
&
0x0F
),
0x80
|
((
x
>>>
6
)
&
0x3F
),
0x80
|
(
x
&
0x3F
));
else
if
(
x
<=
0x1FFFFF
)
output
+=
String
.
fromCharCode
(
0xF0
|
((
x
>>>
18
)
&
0x07
),
0x80
|
((
x
>>>
12
)
&
0x3F
),
0x80
|
((
x
>>>
6
)
&
0x3F
),
0x80
|
(
x
&
0x3F
));
}
return
output
;
}
/*
* Encode a string as utf-16
*/
function
str2rstr_utf16le
(
input
)
{
var
output
=
""
;
for
(
var
i
=
0
;
i
<
input
.
length
;
i
++
)
output
+=
String
.
fromCharCode
(
input
.
charCodeAt
(
i
)
&
0xFF
,
(
input
.
charCodeAt
(
i
)
>>>
8
)
&
0xFF
);
return
output
;
}
function
str2rstr_utf16be
(
input
)
{
var
output
=
""
;
for
(
var
i
=
0
;
i
<
input
.
length
;
i
++
)
output
+=
String
.
fromCharCode
((
input
.
charCodeAt
(
i
)
>>>
8
)
&
0xFF
,
input
.
charCodeAt
(
i
)
&
0xFF
);
return
output
;
}
/*
* Convert a raw string to an array of little-endian words
* Characters >255 have their high-byte silently ignored.
*/
function
rstr2binl
(
input
)
{
var
output
=
Array
(
input
.
length
>>
2
);
for
(
var
i
=
0
;
i
<
output
.
length
;
i
++
)
output
[
i
]
=
0
;
for
(
var
i
=
0
;
i
<
input
.
length
*
8
;
i
+=
8
)
output
[
i
>>
5
]
|=
(
input
.
charCodeAt
(
i
/
8
)
&
0xFF
)
<<
(
i
%
32
);
return
output
;
}
/*
* Convert an array of little-endian words to a string
*/
function
binl2rstr
(
input
)
{
var
output
=
""
;
for
(
var
i
=
0
;
i
<
input
.
length
*
32
;
i
+=
8
)
output
+=
String
.
fromCharCode
((
input
[
i
>>
5
]
>>>
(
i
%
32
))
&
0xFF
);
return
output
;
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length.
*/
function
binl_md5
(
x
,
len
)
{
/* append padding */
x
[
len
>>
5
]
|=
0x80
<<
((
len
)
%
32
);
x
[(((
len
+
64
)
>>>
9
)
<<
4
)
+
14
]
=
len
;
var
a
=
1732584193
;
var
b
=
-
271733879
;
var
c
=
-
1732584194
;
var
d
=
271733878
;
for
(
var
i
=
0
;
i
<
x
.
length
;
i
+=
16
)
{
var
olda
=
a
;
var
oldb
=
b
;
var
oldc
=
c
;
var
oldd
=
d
;
a
=
md5_ff
(
a
,
b
,
c
,
d
,
x
[
i
+
0
],
7
,
-
680876936
);
d
=
md5_ff
(
d
,
a
,
b
,
c
,
x
[
i
+
1
],
12
,
-
389564586
);
c
=
md5_ff
(
c
,
d
,
a
,
b
,
x
[
i
+
2
],
17
,
606105819
);
b
=
md5_ff
(
b
,
c
,
d
,
a
,
x
[
i
+
3
],
22
,
-
1044525330
);
a
=
md5_ff
(
a
,
b
,
c
,
d
,
x
[
i
+
4
],
7
,
-
176418897
);
d
=
md5_ff
(
d
,
a
,
b
,
c
,
x
[
i
+
5
],
12
,
1200080426
);
c
=
md5_ff
(
c
,
d
,
a
,
b
,
x
[
i
+
6
],
17
,
-
1473231341
);
b
=
md5_ff
(
b
,
c
,
d
,
a
,
x
[
i
+
7
],
22
,
-
45705983
);
a
=
md5_ff
(
a
,
b
,
c
,
d
,
x
[
i
+
8
],
7
,
1770035416
);
d
=
md5_ff
(
d
,
a
,
b
,
c
,
x
[
i
+
9
],
12
,
-
1958414417
);
c
=
md5_ff
(
c
,
d
,
a
,
b
,
x
[
i
+
10
],
17
,
-
42063
);
b
=
md5_ff
(
b
,
c
,
d
,
a
,
x
[
i
+
11
],
22
,
-
1990404162
);
a
=
md5_ff
(
a
,
b
,
c
,
d
,
x
[
i
+
12
],
7
,
1804603682
);
d
=
md5_ff
(
d
,
a
,
b
,
c
,
x
[
i
+
13
],
12
,
-
40341101
);
c
=
md5_ff
(
c
,
d
,
a
,
b
,
x
[
i
+
14
],
17
,
-
1502002290
);
b
=
md5_ff
(
b
,
c
,
d
,
a
,
x
[
i
+
15
],
22
,
1236535329
);
a
=
md5_gg
(
a
,
b
,
c
,
d
,
x
[
i
+
1
],
5
,
-
165796510
);
d
=
md5_gg
(
d
,
a
,
b
,
c
,
x
[
i
+
6
],
9
,
-
1069501632
);
c
=
md5_gg
(
c
,
d
,
a
,
b
,
x
[
i
+
11
],
14
,
643717713
);
b
=
md5_gg
(
b
,
c
,
d
,
a
,
x
[
i
+
0
],
20
,
-
373897302
);
a
=
md5_gg
(
a
,
b
,
c
,
d
,
x
[
i
+
5
],
5
,
-
701558691
);
d
=
md5_gg
(
d
,
a
,
b
,
c
,
x
[
i
+
10
],
9
,
38016083
);
c
=
md5_gg
(
c
,
d
,
a
,
b
,
x
[
i
+
15
],
14
,
-
660478335
);
b
=
md5_gg
(
b
,
c
,
d
,
a
,
x
[
i
+
4
],
20
,
-
405537848
);
a
=
md5_gg
(
a
,
b
,
c
,
d
,
x
[
i
+
9
],
5
,
568446438
);
d
=
md5_gg
(
d
,
a
,
b
,
c
,
x
[
i
+
14
],
9
,
-
1019803690
);
c
=
md5_gg
(
c
,
d
,
a
,
b
,
x
[
i
+
3
],
14
,
-
187363961
);
b
=
md5_gg
(
b
,
c
,
d
,
a
,
x
[
i
+
8
],
20
,
1163531501
);
a
=
md5_gg
(
a
,
b
,
c
,
d
,
x
[
i
+
13
],
5
,
-
1444681467
);
d
=
md5_gg
(
d
,
a
,
b
,
c
,
x
[
i
+
2
],
9
,
-
51403784
);
c
=
md5_gg
(
c
,
d
,
a
,
b
,
x
[
i
+
7
],
14
,
1735328473
);
b
=
md5_gg
(
b
,
c
,
d
,
a
,
x
[
i
+
12
],
20
,
-
1926607734
);
a
=
md5_hh
(
a
,
b
,
c
,
d
,
x
[
i
+
5
],
4
,
-
378558
);
d
=
md5_hh
(
d
,
a
,
b
,
c
,
x
[
i
+
8
],
11
,
-
2022574463
);
c
=
md5_hh
(
c
,
d
,
a
,
b
,
x
[
i
+
11
],
16
,
1839030562
);
b
=
md5_hh
(
b
,
c
,
d
,
a
,
x
[
i
+
14
],
23
,
-
35309556
);
a
=
md5_hh
(
a
,
b
,
c
,
d
,
x
[
i
+
1
],
4
,
-
1530992060
);
d
=
md5_hh
(
d
,
a
,
b
,
c
,
x
[
i
+
4
],
11
,
1272893353
);
c
=
md5_hh
(
c
,
d
,
a
,
b
,
x
[
i
+
7
],
16
,
-
155497632
);
b
=
md5_hh
(
b
,
c
,
d
,
a
,
x
[
i
+
10
],
23
,
-
1094730640
);
a
=
md5_hh
(
a
,
b
,
c
,
d
,
x
[
i
+
13
],
4
,
681279174
);
d
=
md5_hh
(
d
,
a
,
b
,
c
,
x
[
i
+
0
],
11
,
-
358537222
);
c
=
md5_hh
(
c
,
d
,
a
,
b
,
x
[
i
+
3
],
16
,
-
722521979
);
b
=
md5_hh
(
b
,
c
,
d
,
a
,
x
[
i
+
6
],
23
,
76029189
);
a
=
md5_hh
(
a
,
b
,
c
,
d
,
x
[
i
+
9
],
4
,
-
640364487
);
d
=
md5_hh
(
d
,
a
,
b
,
c
,
x
[
i
+
12
],
11
,
-
421815835
);
c
=
md5_hh
(
c
,
d
,
a
,
b
,
x
[
i
+
15
],
16
,
530742520
);
b
=
md5_hh
(
b
,
c
,
d
,
a
,
x
[
i
+
2
],
23
,
-
995338651
);
a
=
md5_ii
(
a
,
b
,
c
,
d
,
x
[
i
+
0
],
6
,
-
198630844
);
d
=
md5_ii
(
d
,
a
,
b
,
c
,
x
[
i
+
7
],
10
,
1126891415
);
c
=
md5_ii
(
c
,
d
,
a
,
b
,
x
[
i
+
14
],
15
,
-
1416354905
);
b
=
md5_ii
(
b
,
c
,
d
,
a
,
x
[
i
+
5
],
21
,
-
57434055
);
a
=
md5_ii
(
a
,
b
,
c
,
d
,
x
[
i
+
12
],
6
,
1700485571
);
d
=
md5_ii
(
d
,
a
,
b
,
c
,
x
[
i
+
3
],
10
,
-
1894986606
);
c
=
md5_ii
(
c
,
d
,
a
,
b
,
x
[
i
+
10
],
15
,
-
1051523
);
b
=
md5_ii
(
b
,
c
,
d
,
a
,
x
[
i
+
1
],
21
,
-
2054922799
);
a
=
md5_ii
(
a
,
b
,
c
,
d
,
x
[
i
+
8
],
6
,
1873313359
);
d
=
md5_ii
(
d
,
a
,
b
,
c
,
x
[
i
+
15
],
10
,
-
30611744
);
c
=
md5_ii
(
c
,
d
,
a
,
b
,
x
[
i
+
6
],
15
,
-
1560198380
);
b
=
md5_ii
(
b
,
c
,
d
,
a
,
x
[
i
+
13
],
21
,
1309151649
);
a
=
md5_ii
(
a
,
b
,
c
,
d
,
x
[
i
+
4
],
6
,
-
145523070
);
d
=
md5_ii
(
d
,
a
,
b
,
c
,
x
[
i
+
11
],
10
,
-
1120210379
);
c
=
md5_ii
(
c
,
d
,
a
,
b
,
x
[
i
+
2
],
15
,
718787259
);
b
=
md5_ii
(
b
,
c
,
d
,
a
,
x
[
i
+
9
],
21
,
-
343485551
);
a
=
safe_add
(
a
,
olda
);
b
=
safe_add
(
b
,
oldb
);
c
=
safe_add
(
c
,
oldc
);
d
=
safe_add
(
d
,
oldd
);
}
return
Array
(
a
,
b
,
c
,
d
);
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function
md5_cmn
(
q
,
a
,
b
,
x
,
s
,
t
)
{
return
safe_add
(
bit_rol
(
safe_add
(
safe_add
(
a
,
q
),
safe_add
(
x
,
t
)),
s
),
b
);
}
function
md5_ff
(
a
,
b
,
c
,
d
,
x
,
s
,
t
)
{
return
md5_cmn
((
b
&
c
)
|
((
~
b
)
&
d
),
a
,
b
,
x
,
s
,
t
);
}
function
md5_gg
(
a
,
b
,
c
,
d
,
x
,
s
,
t
)
{
return
md5_cmn
((
b
&
d
)
|
(
c
&
(
~
d
)),
a
,
b
,
x
,
s
,
t
);
}
function
md5_hh
(
a
,
b
,
c
,
d
,
x
,
s
,
t
)
{
return
md5_cmn
(
b
^
c
^
d
,
a
,
b
,
x
,
s
,
t
);
}
function
md5_ii
(
a
,
b
,
c
,
d
,
x
,
s
,
t
)
{
return
md5_cmn
(
c
^
(
b
|
(
~
d
)),
a
,
b
,
x
,
s
,
t
);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function
safe_add
(
x
,
y
)
{
var
lsw
=
(
x
&
0xFFFF
)
+
(
y
&
0xFFFF
);
var
msw
=
(
x
>>
16
)
+
(
y
>>
16
)
+
(
lsw
>>
16
);
return
(
msw
<<
16
)
|
(
lsw
&
0xFFFF
);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function
bit_rol
(
num
,
cnt
)
{
return
(
num
<<
cnt
)
|
(
num
>>>
(
32
-
cnt
));
}
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