Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

moved parse and serialize methods into separate classes; created joap…

… specific stanzas
  • Loading branch information...
commit 5f55d2e8ccb2b564cec66cfe0fd61aba8c22ff02 1 parent 31a24bd
@flosse authored
View
1  .npmignore
@@ -1 +1,2 @@
lib/*.coffee
+spec/*.coffee
View
4 README.markdown
@@ -23,11 +23,13 @@ comp = new xmpp.Component
port : "8888"
classes = {}
+objects = {}
router = new joap.Router comp
router.on "action", (action, clazz, instance, iq) ->
- console.log action.type
+ if clazz? and instance? and action.type is "read"
+ router.sendResponse joap.serialize(objects[clazz][instance], action), iq
router.on "read", (action, clazz, instance, iq) ->
console.log "read iq received"
View
82 lib/Parser.coffee
@@ -0,0 +1,82 @@
+ltx = require "ltx"
+joap = require "./node-xmpp-joap"
+
+JOAP_NS = "jabber:iq:joap"
+RPC_NS = "jabber:iq:rpc"
+JOAP_STANZAS = ["describe", "read","add", "edit", "delete", "search"]
+
+class Parser
+
+ @getType: (xml) ->
+ if Parser.isJOAPStanza xml then xml.getName().toLowerCase()
+ else if Parser.isRPCStanza xml then "rpc"
+
+ @isJOAPStanza: (xml) ->
+ (xml.name in JOAP_STANZAS and xml.attrs?.xmlns is JOAP_NS)
+
+ @isRPCStanza: (xml) ->
+ (xml.name is "query" and xml.attrs?.xmlns is RPC_NS)
+
+ @parse: (xml) ->
+
+ if typeof xml in ["string", "number", "boolean"] then xml
+
+ else if xml instanceof Array
+ (Parser.parse c for c in xml)
+
+ else if xml instanceof ltx.Element
+
+ if Parser.isJOAPStanza xml
+ action = {
+ type: Parser.getType xml
+ }
+ attrs = {}
+
+ a = xml.getChildren "attribute"
+ if a.length > 0
+ attrs[c.name] = c.value for c in Parser.parse a
+ action.attributes = attrs
+ n = xml.getChildren "name"
+ action.limits = Parser.parse(n) if n.length > 0
+ action
+ else if Parser.isRPCStanza xml
+ call = xml.getChild "methodCall"
+ {
+ type: Parser.getType xml
+ method: call.getChildText "methodName"
+ params: Parser.parse call.getChild "params"
+ }
+ else
+
+ child = xml.children?[0]
+
+ switch xml.getName()
+ when "string", "name"
+ child
+ when "i4", "int", "double"
+ child * 1
+ when "boolean"
+ (child is "true" or child is "1")
+ when "value"
+ Parser.parse child
+ when "struct"
+ struct = {}
+ members = (Parser.parse m for m in xml.getChildren "member")
+ struct[m.name] = m.value for m in members
+ struct
+ when "array"
+ Parser.parse xml.getChild "data"
+ when "params"
+ (Parser.parse c.getChild "value" for c in xml.getChildren "param")
+ when "data"
+ data = []
+ for d in xml.getChildren "value"
+ data.push Parser.parse d
+ data
+ when "member", "attribute"
+ {
+ name: xml.getChildText "name"
+ value: Parser.parse xml.getChild "value"
+ }
+
+exports.Parser = Parser
View
128 lib/Router.coffee
@@ -1,5 +1,6 @@
ltx = require "ltx"
events = require "events"
+joap = require "./node-xmpp-joap"
JOAP_NS = "jabber:iq:joap"
RPC_NS = "jabber:iq:rpc"
@@ -10,14 +11,14 @@ class Router extends events.EventEmitter
constructor: (@xmpp) ->
@xmpp.on "stanza", (iq) =>
- if iq.name is "iq" and (Router.isJOAPStanza xml or Router.isRPCStanza xml)
+ if iq.name is "iq" and (joap.isJOAPStanza xml or joap.isRPCStanza xml)
child = iq.children?[0]
to = iq.attrs.to
clazz = to.split('@')[0]
instance = to.split('/')[1]
- action = Router.parse child
+ action = joap.parse child
@emit action.type, action, clazz, instance, iq
@emit "action", action, clazz, instance, iq
@@ -29,113 +30,30 @@ class Router extends events.EventEmitter
to: iq.attrs.from
from: iq.attrs.to
- err
- .c(action, xmlns: JOAP_NS).up()
- .c("error", code: code)
- .t(msg)
+ if action.type isnt "rpc"
+ if action.type in JOAP_STANZAS
+ err.c(action.type, xmlns: JOAP_NS).up()
+ err
+ .c("error", code: code)
+ .t(msg)
+ else if action.type is "rpc"
+ err
+ .c("query", xmlns: RPC_NS)
+ .c("methodResponse")
+ .c("fault")
+ .cnode(new joap.Value { faultCode: code, faultString: msg })
@xmpp.send err
- @getType: (xml) ->
- if Router.isJOAPStanza xml then xml.getName().toLowerCase()
- else if Router.isRPCStanza xml then "rpc"
+ sendResponse: (data, iq) ->
- @isJOAPStanza: (xml) ->
- (xml.name in JOAP_STANZAS and xml.attrs?.xmlns is JOAP_NS)
-
- @isRPCStanza: (xml) ->
- (xml.name is "query" and xml.attrs?.xmlns is RPC_NS)
-
- @parse: (xml) ->
-
- if typeof xml in ["string", "number", "boolean"] then xml
-
- else if xml instanceof Array
- (Router.parse c for c in xml)
-
- else if xml instanceof ltx.Element
-
- if Router.isJOAPStanza xml
- action = {
- type: Router.getType xml
- }
- attrs = {}
-
- a = xml.getChildren "attribute"
- if a.length > 0
- attrs[c.name] = c.value for c in Router.parse a
- action.attributes = attrs
- n = xml.getChildren "name"
- action.limits = Router.parse(n) if n.length > 0
- action
- else if Router.isRPCStanza xml
- call = xml.getChild "methodCall"
- {
- type: Router.getType xml
- method: call.getChildText "methodName"
- params: Router.parse call.getChild "params"
- }
- else
-
- child = xml.children?[0]
-
- switch xml.getName()
- when "string", "name"
- child
- when "i4", "int", "double"
- child * 1
- when "boolean"
- (child is "true" or child is "1")
- when "value"
- Router.parse child
- when "struct"
- struct = {}
- members = (Router.parse m for m in xml.getChildren "member")
- struct[m.name] = m.value for m in members
- struct
- when "array"
- Router.parse xml.getChild "data"
- when "params"
- (Router.parse c.getChild "value" for c in xml.getChildren "param")
- when "data"
- data = []
- for d in xml.getChildren "value"
- data.push Router.parse d
- data
- when "member", "attribute"
- {
- name: xml.getChildText "name"
- value: Router.parse xml.getChild "value"
- }
-
- @serialize: (val) ->
-
- switch typeof val
-
- when "string"
- (new ltx.Element "string").t(val)
-
- when "number"
- if val % 1 is 0
- (new ltx.Element "i4").t(val.toString())
- else
- (new ltx.Element "double").t(val.toString())
-
- when "boolean"
- (new ltx.Element "boolean").t(if val is true then "1" else "0")
+ res = new ltx.Element "iq",
+ id: iq.attrs.id
+ type:'result'
+ to: iq.attrs.from
+ from: iq.attrs.to
- when "object"
- if val instanceof Array
- vals = (Router.serialize v for v in val)
- el = (new ltx.Element "array").c("data")
- for v in vals
- el.c("value").cnode(v).up()#+.up()
- el.tree()
- else
- struct = new ltx.Element "struct"
- for own k,v of val
- struct.c("member").c("name").t(k.toString())
- .up().c("value").cnode(Router.serialize v)
- struct.tree()
+ res.cnode data
+ @xmpp.send res
exports.Router = Router
View
59 lib/Serializer.coffee
@@ -0,0 +1,59 @@
+ltx = require "ltx"
+joap = require "./node-xmpp-joap"
+
+JOAP_NS = "jabber:iq:joap"
+RPC_NS = "jabber:iq:rpc"
+JOAP_STANZAS = ["describe", "read","add", "edit", "delete", "search"]
+
+Element = ltx.Element
+
+class Serializer
+
+ @serialize: (val, action) ->
+
+ if action?
+ if action.type isnt "rpc"
+ el = (new Element action.type, {xmlns:JOAP_NS})
+ switch action.type
+ when "read"
+ for k,v of val
+ el.cnode(new joap.Attribute k,v)
+ el
+ when "add"
+ el.c("newAddress").t(val).up()
+ when "edit"
+ el.c("newAddress").t(val) if val?
+ el
+ when "delete"
+ el
+ when "search"
+ for v in val
+ el.c("item").t(v.toString()).up()
+ el
+
+ else if action.type is "rpc"
+ el = (new Element "query", {xmlns:RPC_NS})
+
+ else if val?
+
+ switch typeof val
+
+ when "string"
+ (new Element "string").t(val)
+
+ when "number"
+ if val % 1 is 0
+ (new Element "int").t(val.toString())
+ else
+ (new Element "double").t(val.toString())
+
+ when "boolean"
+ (new Element "boolean").t(if val is true then "1" else "0")
+
+ when "object"
+ if val instanceof Array
+ new joap.Array val
+ else
+ new joap.Struct val
+
+exports.Serializer = Serializer
View
21 lib/node-xmpp-joap.coffee
@@ -1 +1,20 @@
-exports.Router = require("./Router").Router
+stanza = require("./stanza")
+
+exports.Router = require("./Router").Router
+
+exports.Attribute = stanza.Attribute
+exports.Member = stanza.Member
+exports.Struct = stanza.Struct
+exports.Array = stanza.Array
+exports.Value = stanza.Value
+
+Parser = require("./Parser").Parser
+
+exports.Parser = Parser
+exports.parse = Parser.parse
+exports.isJOAPStanza = Parser.isJOAPStanza
+exports.isRPCStanza = Parser.isRPCStanza
+
+Serializer = require("./Serializer").Serializer
+exports.Serializer = Serializer
+exports.serialize = Serializer.serialize
View
43 lib/stanza.coffee
@@ -0,0 +1,43 @@
+ltx = require "ltx"
+joap = require "./node-xmpp-joap"
+
+class KeyVal extends ltx.Element
+ constructor: (name, key, value) ->
+ super name
+ @c("name")
+ .t(key.toString()).up()
+ .cnode(new Value value).up().up()
+
+class Attribute extends KeyVal
+
+ constructor: (key, value) ->
+ super "attribute", key, value
+
+class Member extends KeyVal
+
+ constructor: (key, value) ->
+ super "member", key, value
+
+class Struct extends ltx.Element
+ constructor: (obj) ->
+ super "struct"
+ for own k,v of obj
+ @cnode(new Member k,v).up()
+
+class Array extends ltx.Element
+ constructor: (arr) ->
+ super "array"
+ data = @c "data"
+ for v in arr
+ data.cnode(new Value v)
+
+class Value extends ltx.Element
+ constructor: (val) ->
+ super "value"
+ @cnode(joap.serialize val)
+
+exports.Attribute = Attribute
+exports.Member = Member
+exports.Struct = Struct
+exports.Array = Array
+exports.Value = Value
View
64 spec/Router.spec.coffee → spec/Parser.spec.coffee
@@ -1,8 +1,7 @@
-describe "Router", ->
+describe "Parser", ->
joap = require "../lib/node-xmpp-joap"
ltx = require "ltx"
- Router = joap.Router
it "checks the stanzas", ->
@@ -10,31 +9,31 @@ describe "Router", ->
nonRpc1 = ltx.parse "<query xmlns='wrong:iq:rpc'></query>"
nonRpc2 = ltx.parse "<x xmlns='jabber:iq:rpc'></x>"
- joap = ltx.parse "<read xmlns='jabber:iq:joap'/>"
+ joapRead = ltx.parse "<read xmlns='jabber:iq:joap'/>"
nonJoap1 = ltx.parse "<read xmlns='jabber:iq:wrong'/>"
nonJoap2 = ltx.parse "<x xmlns='jabber:iq:joap'/>"
- (expect Router.isRPCStanza rpc).toBeTruthy()
- (expect Router.isRPCStanza nonRpc1).toBeFalsy()
- (expect Router.isRPCStanza nonRpc2).toBeFalsy()
+ (expect joap.Parser.isRPCStanza rpc).toBeTruthy()
+ (expect joap.Parser.isRPCStanza nonRpc1).toBeFalsy()
+ (expect joap.Parser.isRPCStanza nonRpc2).toBeFalsy()
- (expect Router.isJOAPStanza joap).toBeTruthy()
- (expect Router.isJOAPStanza nonJoap1).toBeFalsy()
- (expect Router.isJOAPStanza nonJoap2).toBeFalsy()
+ (expect joap.Parser.isJOAPStanza joapRead).toBeTruthy()
+ (expect joap.Parser.isJOAPStanza nonJoap1).toBeFalsy()
+ (expect joap.Parser.isJOAPStanza nonJoap2).toBeFalsy()
it "checks the type", ->
read = ltx.parse "<read xmlns='jabber:iq:joap'/>"
search = ltx.parse "<search xmlns='jabber:iq:joap'/>"
rpc = ltx.parse "<query xmlns='jabber:iq:rpc'></query>"
- (expect Router.getType read).toEqual "read"
- (expect Router.getType search).toEqual "search"
- (expect Router.getType rpc).toEqual "rpc"
+ (expect joap.Parser.getType read).toEqual "read"
+ (expect joap.Parser.getType search).toEqual "search"
+ (expect joap.Parser.getType rpc).toEqual "rpc"
describe "parse", ->
it "should be accessible", ->
- (expect Router.parse).toBeDefined()
+ (expect joap.Parser.parse).toBeDefined()
describe "action", ->
@@ -43,8 +42,8 @@ describe "Router", ->
rpc = ltx.parse "<query xmlns='jabber:iq:rpc'><methodCall>" +
"<methodName>test</methodName></methodCall></query>"
- (expect Router.parse(describe).type).toEqual "describe"
- (expect Router.parse(rpc).type).toEqual "rpc"
+ (expect joap.Parser.parse(describe).type).toEqual "describe"
+ (expect joap.Parser.parse(rpc).type).toEqual "rpc"
it "returns the parsed attribute if available", ->
read1 = ltx.parse "<read xmlns='jabber:iq:joap'>" +
@@ -56,7 +55,7 @@ describe "Router", ->
read3 = ltx.parse "<read xmlns='jabber:iq:joap'><name>foo</name><name>second</name></read>"
edit = ltx.parse "<edit xmlns='jabber:iq:joap'>" +
- "<attribute><name>foo</name><value><i4>3</i4></value></attribute>" +
+ "<attribute><name>foo</name><value><int>3</int></value></attribute>" +
"<attribute>" +
"<name>bar</name>" +
"<value>" +
@@ -65,7 +64,7 @@ describe "Router", ->
"<name>foo</name>" +
"<value>" +
"<array><data>" +
- "<value><i4>12</i4></value>" +
+ "<value><int>12</int></value>" +
"<value><string>bar</string></value>" +
"<value><boolean>0</boolean></value>" +
"<value><int>-31</int></value>" +
@@ -89,30 +88,11 @@ describe "Router", ->
"</params>" +
"</methodCall></query>"
- (expect Router.parse read1).toEqual { type: "read", attributes:{ foo: "bar", second:"value"} }
- (expect Router.parse read2).toEqual { type: "read" }
- (expect Router.parse read3).toEqual { type: "read", limits: ["foo", "second"] }
- (expect Router.parse edit).toEqual { type: "edit", attributes: {
+ (expect joap.Parser.parse read1).toEqual { type: "read", attributes:{ foo: "bar", second:"value"} }
+ (expect joap.Parser.parse read2).toEqual { type: "read" }
+ (expect joap.Parser.parse read3).toEqual { type: "read", limits: ["foo", "second"] }
+ (expect joap.Parser.parse edit).toEqual { type: "edit", attributes: {
foo: 3, bar: { foo: [12,"bar", false, -31]} }}
- (expect Router.parse rpc1).toEqual { type: "rpc", method: "test" }
- (expect Router.parse rpc2).toEqual { type: "rpc", method: "test", params: ["abc", true, -0.003 ] }
-
- describe "serialize", ->
- it "serializes basic data types", ->
- obj = {a:"foo", b:2, c: -0.3, d:true, e:[], f:{}}
-
- (expect Router.serialize "foo" ).toEqual ltx.parse "<string>foo</string>"
- (expect Router.serialize 2 ).toEqual ltx.parse "<i4>2</i4>"
- (expect Router.serialize -0.3 ).toEqual ltx.parse "<double>-0.3</double>"
- (expect Router.serialize true ).toEqual ltx.parse "<boolean>1</boolean>"
- (expect Router.serialize [] ).toEqual ltx.parse "<array><data></data></array>"
- (expect Router.serialize ["x", -0.35, false] ).toEqual ltx.parse "<array><data>" +
- "<value><string>x</string></value><value><double>-0.35</double></value><value>" +
- "<boolean>0</boolean></value></data></array>"
- (expect Router.serialize {a:"foo", b:["bar"]} ).toEqual ltx.parse "<struct>"+
- "<member><name>a</name><value><string>foo</string></value></member>" +
- "<member><name>b</name>" +
- "<value><array><data><value><string>bar</string></value></data></array>" +
- "</value></member>" +
- "</struct>"
+ (expect joap.Parser.parse rpc1).toEqual { type: "rpc", method: "test" }
+ (expect joap.Parser.parse rpc2).toEqual { type: "rpc", method: "test", params: ["abc", true, -0.003 ] }
View
55 spec/Serializer.spec.coffee
@@ -0,0 +1,55 @@
+describe "Serializer", ->
+
+ joap = require "../lib/node-xmpp-joap"
+ ltx = require "ltx"
+ Serializer = joap.Serializer
+
+ describe "serialize", ->
+
+ it "serializes basic data types", ->
+
+ (expect Serializer.serialize "foo" ).toEqual ltx.parse "<string>foo</string>"
+ (expect Serializer.serialize 2 ).toEqual ltx.parse "<int>2</int>"
+ (expect Serializer.serialize -0.3 ).toEqual ltx.parse "<double>-0.3</double>"
+ (expect Serializer.serialize true ).toEqual ltx.parse "<boolean>1</boolean>"
+ (expect Serializer.serialize [] ).toEqual ltx.parse "<array><data></data></array>"
+ (expect Serializer.serialize ["x", -0.35, false] ).toEqual ltx.parse "<array><data>" +
+ "<value><string>x</string></value><value><double>-0.35</double></value><value>" +
+ "<boolean>0</boolean></value></data></array>"
+ (expect Serializer.serialize {a:"foo", b:["bar"]} ).toEqual ltx.parse "<struct>"+
+ "<member><name>a</name><value><string>foo</string></value></member>" +
+ "<member><name>b</name>" +
+ "<value><array><data><value><string>bar</string></value></data></array>" +
+ "</value></member></struct>"
+
+ it "serializes result attributes", ->
+
+ readAct = { type: "read" }
+ addAct = { type: "add" }
+ editAct = { type: "edit" }
+ delAct = { type: "delete" }
+ searchAct = { type: "search" }
+ addr = "Class@component.example.com/instance"
+
+ readObj = {a:"foo", b:2}
+ (expect Serializer.serialize readObj, readAct).toEqual ltx.parse "<read xmlns='jabber:iq:joap'>"+
+ "<attribute><name>a</name><value><string>foo</string></value></attribute>" +
+ "<attribute><name>b</name><value><int>2</int></value></attribute>" +
+ "</read>"
+
+ (expect Serializer.serialize addr, addAct).toEqual ltx.parse "<add xmlns='jabber:iq:joap'>"+
+ "<newAddress>#{addr}</newAddress></add>"
+
+ (expect Serializer.serialize null, editAct).toEqual ltx.parse "<edit xmlns='jabber:iq:joap' />"
+ (expect Serializer.serialize addr, editAct).toEqual ltx.parse "<edit xmlns='jabber:iq:joap' >" +
+ "<newAddress>#{addr}</newAddress></edit>"
+
+ (expect Serializer.serialize null, delAct).toEqual ltx.parse "<delete xmlns='jabber:iq:joap' />"
+
+ searchResults = ["a", "b", "c"]
+ (expect Serializer.serialize searchResults, searchAct).toEqual ltx.parse "<search xmlns='jabber:iq:joap' >" +
+ "<item>a</item>" +
+ "<item>b</item>" +
+ "<item>c</item>" +
+ "</search>"
+
Please sign in to comment.
Something went wrong with that request. Please try again.