Created
June 14, 2012 16:27
-
-
Save baio/2931322 to your computer and use it in GitHub Desktop.
odataprovider multi-valued
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define ["Ural/Modules/ODataFilter", "Ural/Modules/DataFilterOpts", "Ural/Libs/datajs"], (fr, frOpts) -> | |
class ODataProvider | |
@serviceHost: -> __g.serviceHost | |
@_parse: (item, parent)-> | |
if item == null or item == undefined or item instanceof Date or typeof item != "object" then return item | |
if item.results and Array.isArray item.results | |
arr = item.results | |
if item.d && Array.isArray item.d | |
arr = item.d | |
if Array.isArray item | |
arr = item | |
if (arr) then return arr.map (i) -> ODataProvider._parse i, parent | |
obj = {} | |
for own prop of item | |
if prop == "__deferred" | |
return if _.str.endsWith parent, "s" then [] else id : __g.nullRefVal() | |
if prop != "__metadata" | |
obj[prop] = ODataProvider._parse item[prop], prop | |
obj | |
@_isDelete: (item) -> item and item.__state and item.__state.__status == "removed" | |
@_getEndPoint: (name, item, isIndex) -> | |
if item.__endPointBinding | |
root = item.__endPointBinding["$root"] | |
root = item.__endPointBinding if typeof item.__endPointBinding == "string" | |
if root | |
if typeof root == "object" | |
indexEndPoint = root.index | |
itemEndPoint = root.item | |
else | |
itemEndPoint = root | |
else | |
itemEndPoint = name.replace /^(.*)s$/, "$1" | |
indexEndPoint ?= itemEndPoint.pluralize() | |
if isIndex then indexEndPoint else itemEndPoint | |
@_isNew: (item) -> | |
item.id == null or item.id == -1 | |
@_getKeyVal: (id) -> | |
if typeof id == "string" then "'#{id}'" else id | |
@_isObjectArray: (val) -> | |
Array.isArray(val) and (val.length == 0 or (typeof(val[0]) == "object" and !(val[0] instanceof Date))) | |
@_formatRequest: (name, item, metadata, parentName, parent, parentContentId, totalCount) -> | |
res = [] | |
expnads = [] | |
totalCount ?= 1 | |
cid = totalCount | |
isDelete = ODataProvider._isDelete item | |
parentId = parent.id if parent | |
key = ODataProvider._getKeyVal item.id | |
parentKey = ODataProvider._getKeyVal parentId | |
if !isDelete | |
flattered = {} | |
for own prop of item | |
val = item[prop] | |
#if val != null and (typeof val != "object" or val instanceof Date) and !Array.isArray(val) and prop != "__endPointBinding" | |
if val != null and prop != "__endPointBinding" and prop != "__state" and !ODataProvider._isObjectArray val | |
flattered[prop] = val | |
if val == null | |
flattered[prop] = null | |
propVal = parent[name] if parent | |
isArrayProp = if propVal then ODataProvider._isObjectArray propVal #Array.isArray(propVal) and typeof(propVal[0]) == "object" and !(propVal[0] instanceof Date) else false | |
typeName = if isArrayProp then name.singularize() else name | |
itemEP = ODataProvider._getEndPoint name, item, false | |
indexEP = ODataProvider._getEndPoint name, item, true | |
if !parentName | |
#root item | |
if isDelete | |
data = method: "DELETE", uri: "#{indexEP}(#{key})" | |
else | |
data = if ODataProvider._isNew item then method: "POST", uri: indexEP else method: "PUT", uri: "#{indexEP}(#{key})" | |
else | |
parentName = parentName.replace /^(.*)s$/, "$1" | |
parIndexEP = ODataProvider._getEndPoint parentName, parent, true | |
#nested item | |
if isDelete | |
ref = if !isArrayProp then name else "#{name}(#{item.id})" | |
data = method: "DELETE", uri: "#{parIndexEP}(#{parentId})/$links/#{ref}" | |
else | |
if item.id == __g.nullRefVal() then return res | |
ref = if ODataProvider._isNew parent then "$#{parentContentId}" else "#{parIndexEP}(#{parentId})" | |
if !ODataProvider._isNew item | |
###here actual update of referenced item### | |
res.push | |
headers: {"Content-ID": cid} | |
requestUri: "#{indexEP}(#{item.id})" | |
method: "PUT" | |
data: flattered | |
cid++ | |
###here update link to referenced item### | |
data = method: (if isArrayProp then "POST" else "PUT"), uri: "#{ref}/$links/#{name}" | |
flattered = uri : "#{indexEP}(#{item.id})" | |
else | |
if isArrayProp | |
data = method: "POST", uri: "#{ref}/#{name}" | |
else | |
res.push | |
headers: {"Content-ID": cid} | |
requestUri: indexEP | |
method: "POST" | |
data: flattered | |
data = method: "PUT", uri: "#{ref}/$links/#{name}" | |
flattered = uri : "$#{cid}" | |
cid++ | |
res.push | |
headers: {"Content-ID": cid} | |
requestUri: data.uri | |
method: data.method | |
data: flattered | |
totalCount += res.length | |
if !isDelete | |
for own prop of item | |
if prop == "__state" || prop == "__parent" || prop == "__endPointBinding" then continue | |
val = item[prop] | |
epb = item.__endPointBinding[prop] if item.__endPointBinding | |
if Array.isArray(val) | |
if ODataProvider._isObjectArray val #val.length and typeof(val[0]) == "object" and !(val[0] instanceof Date) | |
states = item.__state[prop] if item.__state | |
val = val.concat states.filter((v) -> v.__status == "removed") if states | |
for i, ix in val | |
i.__state = states[ix] if states | |
i.__endPointBinding = epb if epb | |
nested = ODataProvider._formatRequest prop, i, metadata, name, item, cid, totalCount | |
totalCount += nested.length | |
res = res.concat nested | |
else if val != null and typeof val == "object" and !(val instanceof Date) | |
val.__state = item.__state[prop] if item.__state | |
val.__endPointBinding = epb if epb | |
nested = ODataProvider._formatRequest prop, val, metadata, name, item, cid, totalCount | |
totalCount += nested.length | |
res = res.concat nested | |
res | |
load: (srcName, filter, callback) -> | |
stt = @_getStatement srcName, filter | |
OData.read stt, (data) -> callback null, ODataProvider._parse(data) | |
_getStatement: (srcName, filter) -> | |
@_getSatementByODataFilter srcName, fr.convert filter | |
_getExpand: (srcName, expand) -> | |
res = frOpts.expandOpts.get srcName, expand | |
if res == "" then null | |
res ?= expand | |
_getOrderBy: (srcName, filter, orderby) -> | |
singleItemFilter = filter.match /^.*id eq .*$/ if filter | |
if singleItemFilter then return null | |
orderby ?= frOpts.orderBy.get srcName | |
_getSatementByODataFilter: (srcName, oDataFilter) -> | |
expand = @_getExpand srcName, oDataFilter.$expand | |
if !oDataFilter.$isAction | |
srcName = srcName.pluralize() | |
orderby = @_getOrderBy srcName, oDataFilter.$filter, oDataFilter.$orderby | |
srch = _u.urlAddSearch "#{ODataProvider.serviceHost()}#{srcName}", | |
if oDataFilter.$filter then "$filter=#{oDataFilter.$filter}", | |
if oDataFilter.$top then "$top=#{oDataFilter.$top}", | |
if oDataFilter.$skip then "$skip=#{oDataFilter.$skip}", | |
if expand then "$expand=#{expand}", | |
if orderby then "$orderby=#{orderby}" | |
if oDataFilter.$args | |
for own arg of oDataFilter.$args | |
srch = _u.urlAddSearch srch, "#{arg}=#{oDataFilter.$args[arg]}" | |
srch | |
@_getMetadata: (srcName, item) -> | |
null | |
@_getSaveRequestData: (srcName, item) -> | |
#metadata = ODataProvider._getMetadata srcName, item | |
if item.__parent | |
parentId = item.__parent.id | |
parentTypeName = item.__parent.typeName | |
req = ODataProvider._formatRequest srcName, item, null, parentTypeName, parentId | |
req.sort (a, b) -> a.headers["Content-ID"] - b.headers["Content-ID"] | |
__batchRequests: [ | |
__changeRequests: req | |
] | |
@_getBodyError: (body) -> | |
xmlDoc = $.parseXML body | |
$xml = $(body) | |
#TO DO | |
$xml[1].children[1].textContent | |
@_parseSaveResponseData: (data) -> | |
res = [] | |
for batchResponse in data.__batchResponses | |
for changeResponse in batchResponse.__changeResponses | |
res.push | |
type: null | |
contentId: changeResponse.headers["Content-ID"] if changeResponse.headers | |
data: changeResponse.data | |
error: changeResponse.message | |
bodyError : if changeResponse.response and changeResponse.response.body then ODataProvider._getBodyError changeResponse.response.body else null | |
res | |
save: (srcName, item, callback) -> | |
request = | |
requestUri: "#{ODataProvider.serviceHost()}$batch" | |
method: "POST" | |
data: ODataProvider._getSaveRequestData srcName, item | |
OData.request request | |
, (data) => | |
resp = ODataProvider._parseSaveResponseData data | |
errs = resp.filter (f) -> f.error | |
if !errs.length and (!item.__state or item.__state.__status != "removed") | |
expand = @_getExpand srcName, "$item" | |
rootResp = resp.filter((x) -> x.contentId == "1")[0] | |
id = if rootResp and rootResp.data then rootResp.data.id else item.id | |
@load srcName, $filter : { id: {$eq: id}}, $expand: expand, (err, data) -> | |
if !err then data = data[0] | |
callback err, data | |
else | |
callback errs.map((err) -> if err.bodyError then err.bodyError else err.error).join '\n' | |
, (err) -> | |
callback err | |
, OData.batchHandler | |
delete: (srcName, id, callback) -> | |
@save srcName, {id : id, __state : {__status : "removed"} } , callback | |
dataProvider: new ODataProvider() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment