rave 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,89 +1,79 @@
1
- #Represents an operation to be applied on the server
2
- module Rave
3
- module Models
4
- class Operation
5
- attr_reader :type, :wave_id, :wavelet_id, :blip_id, :index, :property
6
-
7
- #Constants
8
- # Types of operations
9
- WAVELET_APPEND_BLIP = 'WAVELET_APPEND_BLIP'
10
- WAVELET_ADD_PARTICIPANT = 'WAVELET_ADD_PARTICIPANT'
11
- WAVELET_CREATE = 'WAVELET_CREATE'
12
- WAVELET_REMOVE_SELF = 'WAVELET_REMOVE_SELF'
13
- WAVELET_DATADOC_SET = 'WAVELET_DATADOC_SET'
14
- WAVELET_SET_TITLE = 'WAVELET_SET_TITLE'
15
- BLIP_CREATE_CHILD = 'BLIP_CREATE_CHILD'
16
- BLIP_DELETE = 'BLIP_DELETE'
17
- DOCUMENT_ANNOTATION_DELETE = 'DOCUMENT_ANNOTATION_DELETE'
18
- DOCUMENT_ANNOTATION_SET = 'DOCUMENT_ANNOTATION_SET'
19
- DOCUMENT_ANNOTATION_SET_NORANGE = 'DOCUMENT_ANNOTATION_SET_NORANGE'
20
- DOCUMENT_APPEND = 'DOCUMENT_APPEND'
21
- DOCUMENT_APPEND_STYLED_TEXT = 'DOCUMENT_APPEND_STYLED_TEXT'
22
- DOCUMENT_INSERT = 'DOCUMENT_INSERT'
23
- DOCUMENT_DELETE = 'DOCUMENT_DELETE'
24
- DOCUMENT_REPLACE = 'DOCUMENT_REPLACE'
25
- DOCUMENT_ELEMENT_APPEND = 'DOCUMENT_ELEMENT_APPEND'
26
- DOCUMENT_ELEMENT_DELETE = 'DOCUMENT_ELEMENT_DELETE'
27
- DOCUMENT_ELEMENT_INSERT = 'DOCUMENT_ELEMENT_INSERT'
28
- DOCUMENT_ELEMENT_INSERT_AFTER = 'DOCUMENT_ELEMENT_INSERT_AFTER'
29
- DOCUMENT_ELEMENT_INSERT_BEFORE = 'DOCUMENT_ELEMENT_INSERT_BEFORE'
30
- DOCUMENT_ELEMENT_REPLACE = 'DOCUMENT_ELEMENT_REPLACE'
31
- DOCUMENT_INLINE_BLIP_APPEND = 'DOCUMENT_INLINE_BLIP_APPEND'
32
- DOCUMENT_INLINE_BLIP_DELETE = 'DOCUMENT_INLINE_BLIP_DELETE'
33
- DOCUMENT_INLINE_BLIP_INSERT = 'DOCUMENT_INLINE_BLIP_INSERT'
34
- DOCUMENT_INLINE_BLIP_INSERT_AFTER_ELEMENT = 'DOCUMENT_INLINE_BLIP_INSERT_AFTER_ELEMENT'
35
-
36
- #Options include:
37
- # - :type
38
- # - :wave_id
39
- # - :wavelet_id
40
- # - :blip_id
41
- # - :index
42
- # - :property
43
- def initialize(options = {})
44
- @type = options[:type]
45
- @wave_id = options[:wave_id]
46
- @wavelet_id = options[:wavelet_id]
47
- @blip_id = options[:blip_id]
48
- @index = options[:index] || -1
49
- @property = options[:property]
50
- end
51
-
52
- #Serialize the operation to hash
53
- def to_hash
54
- {
55
- 'blipId' => @blip_id,
56
- 'index' => @index,
57
- 'waveletId' => @wavelet_id,
58
- 'waveId' => @wave_id,
59
- 'type' => @type,
60
- 'javaClass' => 'com.google.wave.api.impl.OperationImpl',
61
- 'property' => property_to_hash
62
- }
63
- end
64
-
65
- #Serialize teh operation to json
66
- def to_json
67
- to_hash.to_json
68
- end
69
-
70
- protected
71
- #Decide what kind of property it is and return the value that should be in the JSON
72
- def property_to_hash
73
- if @property.kind_of?(String)
74
- @property
75
- elsif @property.kind_of?(Range)
76
- {
77
- 'javaClass' => 'com.google.wave.api.Range',
78
- 'start' => @property.first,
79
- 'end' => @property.last
80
- }
81
- else
82
- #TODO: What else needs to be in here?
83
- raise "I don't know what that property is..."
84
- end
85
- end
86
-
87
- end
88
- end
89
- end
1
+ module Rave
2
+ module Models
3
+ # Represents an operation to be applied on the server.
4
+ class Operation # :nodoc:
5
+ attr_reader :index, :property
6
+
7
+ def type; @type.dup; end
8
+ def wave_id; @wave_id.dup; end
9
+ def wavelet_id; @wavelet_id.dup; end
10
+ def blip_id; @blip_id.dup; end
11
+
12
+ JAVA_CLASS = 'com.google.wave.api.impl.OperationImpl' # :nodoc:
13
+
14
+ #Constants
15
+ # Types of operations
16
+ WAVELET_APPEND_BLIP = 'WAVELET_APPEND_BLIP'
17
+ WAVELET_ADD_PARTICIPANT = 'WAVELET_ADD_PARTICIPANT'
18
+ WAVELET_REMOVE_PARTICIPANT = 'WAVELET_REMOVE_PARTICIPANT'
19
+ WAVELET_CREATE = 'WAVELET_CREATE'
20
+ WAVELET_REMOVE_SELF = 'WAVELET_REMOVE_SELF'
21
+ WAVELET_DATADOC_SET = 'WAVELET_DATADOC_SET'
22
+ WAVELET_SET_TITLE = 'WAVELET_SET_TITLE'
23
+ BLIP_CREATE_CHILD = 'BLIP_CREATE_CHILD'
24
+ BLIP_DELETE = 'BLIP_DELETE'
25
+ DOCUMENT_ANNOTATION_DELETE = 'DOCUMENT_ANNOTATION_DELETE'
26
+ DOCUMENT_ANNOTATION_SET = 'DOCUMENT_ANNOTATION_SET'
27
+ DOCUMENT_ANNOTATION_SET_NORANGE = 'DOCUMENT_ANNOTATION_SET_NORANGE'
28
+ DOCUMENT_APPEND = 'DOCUMENT_APPEND' # Plain text
29
+ DOCUMENT_APPEND_MARKUP = 'DOCUMENT_APPEND_MARKUP' # HTML
30
+ DOCUMENT_APPEND_STYLED_TEXT = 'DOCUMENT_APPEND_STYLED_TEXT'
31
+ DOCUMENT_INSERT = 'DOCUMENT_INSERT'
32
+ DOCUMENT_DELETE = 'DOCUMENT_DELETE'
33
+ DOCUMENT_REPLACE = 'DOCUMENT_REPLACE'
34
+ DOCUMENT_ELEMENT_APPEND = 'DOCUMENT_ELEMENT_APPEND'
35
+ DOCUMENT_ELEMENT_DELETE = 'DOCUMENT_ELEMENT_DELETE'
36
+ DOCUMENT_ELEMENT_INSERT = 'DOCUMENT_ELEMENT_INSERT'
37
+ DOCUMENT_ELEMENT_INSERT_AFTER = 'DOCUMENT_ELEMENT_INSERT_AFTER'
38
+ DOCUMENT_ELEMENT_INSERT_BEFORE = 'DOCUMENT_ELEMENT_INSERT_BEFORE'
39
+ DOCUMENT_ELEMENT_REPLACE = 'DOCUMENT_ELEMENT_REPLACE'
40
+ DOCUMENT_INLINE_BLIP_APPEND = 'DOCUMENT_INLINE_BLIP_APPEND'
41
+ DOCUMENT_INLINE_BLIP_DELETE = 'DOCUMENT_INLINE_BLIP_DELETE'
42
+ DOCUMENT_INLINE_BLIP_INSERT = 'DOCUMENT_INLINE_BLIP_INSERT'
43
+ DOCUMENT_INLINE_BLIP_INSERT_AFTER_ELEMENT = 'DOCUMENT_INLINE_BLIP_INSERT_AFTER_ELEMENT'
44
+
45
+ #Options include:
46
+ # - :type
47
+ # - :wave_id
48
+ # - :wavelet_id
49
+ # - :blip_id
50
+ # - :index
51
+ # - :property
52
+ def initialize(options = {})
53
+ @type = options[:type]
54
+ @wave_id = options[:wave_id]
55
+ @wavelet_id = options[:wavelet_id] || ''
56
+ @blip_id = options[:blip_id] || ''
57
+ @index = options[:index] || -1
58
+ @property = options[:property]
59
+ end
60
+
61
+ #Serialize the operation to json
62
+ def to_json
63
+ hash = {
64
+ 'blipId' => @blip_id,
65
+ 'index' => @index,
66
+ 'waveletId' => @wavelet_id,
67
+ 'waveId' => @wave_id,
68
+ 'type' => @type,
69
+ 'javaClass' => JAVA_CLASS
70
+ }
71
+
72
+ hash['property'] = @property unless @property.nil?
73
+
74
+ hash.to_json
75
+ end
76
+ end
77
+ end
78
+ end
79
+
@@ -0,0 +1,14 @@
1
+ # Extend a standard Range so that it can be serialized easily
2
+
3
+ class Range # :nodoc:
4
+ JAVA_CLASS = 'com.google.wave.api.Range'
5
+
6
+ # Convert to a hash for sending in an operation.
7
+ def to_json
8
+ {
9
+ 'javaClass' => JAVA_CLASS,
10
+ 'start' => min,
11
+ 'end' => max
12
+ }.to_json
13
+ end
14
+ end
data/lib/models/robot.rb CHANGED
@@ -1,61 +1,79 @@
1
- #Contains Robot data, event handlers and cron jobs
2
- module Rave
3
- module Models
4
- class Robot
5
- include Rave::Mixins::DataFormat
6
- include Rave::Mixins::Controller
7
-
8
- attr_reader :name, :image_url, :profile_url
9
-
10
- #Options include:
11
- # - :name
12
- # - :image_url
13
- # - :profile_url
14
- def initialize(options = {})
15
- @name = options[:name]
16
- @image_url = options[:image_url]
17
- @profile_url = options[:profile_url]
18
- @handlers = {}
19
- @cron_jobs = []
20
- register_default_handlers
21
- end
22
-
23
- #Register a handler
24
- # event_type is a string, and must be one of Rave::Models::Event::VALID_EVENTS
25
- # multiple handlers may be applied to an event
26
- def register_handler(event_type, handler)
27
- raise Rave::InvalidEventException.new("Unknown event: #{event_type}") unless Rave::Models::Event.valid_event_type?(event_type)
28
- raise Rave::InvalidHandlerException.new("Unknown handler: #{handler}") unless self.respond_to?(handler)
29
- @handlers[event_type] ||= []
30
- @handlers[event_type] << handler unless @handlers[event_type].include?(handler)
31
- end
32
-
33
- #Dispatches events to the appropriate handler
34
- def handle_event(event, context)
35
- #Ignore unhandled events
36
- if (handlers = @handlers[event.type])
37
- handlers.each do |handler|
38
- self.send(handler, event, context)
39
- end
40
- end
41
- end
42
-
43
- #Registers a cron job
44
- def register_cron_job(path, seconds)
45
- @cron_jobs << {:path => path, :seconds => seconds}
46
- end
47
-
48
- protected
49
- #Register any handlers that are defined through naming convention
50
- def register_default_handlers
51
- Event::VALID_EVENTS.each do |event|
52
- listener = event.downcase.to_sym
53
- if respond_to?(listener)
54
- register_handler(event, listener)
55
- end
56
- end
57
- end
58
-
59
- end
60
- end
1
+ require 'singleton'
2
+ require 'yaml'
3
+
4
+ module Rave
5
+ module Models
6
+ # Contains Robot data, event handlers and cron jobs.
7
+ class Robot < User
8
+ include Rave::Mixins::DataFormat
9
+ include Rave::Mixins::Controller
10
+ include Singleton
11
+
12
+ CONFIG_FILE = 'config.yaml' # :nodoc:
13
+
14
+ # Version of the robot, as in the yaml config [String]
15
+ def version # :nodoc:
16
+ @version.dup
17
+ end
18
+
19
+ def initialize() # :nodoc:
20
+ config = config_from_file
21
+ super(config)
22
+ @handlers = {}
23
+ @cron_jobs = []
24
+ @version = config[:version] || '1'
25
+ register_default_handlers
26
+ end
27
+
28
+ # Read options from user-edited yaml config file.
29
+ def config_from_file # :nodoc:
30
+ config = YAML::load(File.open(CONFIG_FILE))
31
+ hash = {}
32
+ config['robot'].each_pair { |k, v| hash[k.to_sym] = v }
33
+ hash
34
+ end
35
+
36
+ # Register a handler. Multiple handlers may be applied to a single event.
37
+ # +event_type+:: Must be one of Rave::Models::Event::*::TYPE [String]
38
+ def register_handler(event_type, handler)
39
+ raise Rave::InvalidEventException.new("Unknown event: #{event_type}") unless Rave::Models::Event.valid_type?(event_type)
40
+ raise Rave::InvalidHandlerException.new("Unknown handler: #{handler}") unless self.respond_to?(handler)
41
+ @handlers[event_type] ||= []
42
+ @handlers[event_type] << handler unless @handlers[event_type].include?(handler)
43
+ end
44
+
45
+ #Dispatches events to the appropriate handler
46
+ def handle_event(event, context) # :nodoc:
47
+ #Ignore unhandled events
48
+ if (handlers = @handlers[event.type])
49
+ handlers.each do |handler|
50
+ self.send(handler, event, context)
51
+ end
52
+ end
53
+ end
54
+
55
+ #Registers a cron job
56
+ def register_cron_job(handler, seconds)
57
+ @cron_jobs << { :path => "/_wave/cron/#{handler}", :handler => handler, :seconds => seconds }
58
+ end
59
+
60
+ # Creates a new wave with initial participants set.
61
+ # +participants+:: Humans and/or robots to start in the new wave [Array of String/User]
62
+ # Returns: The new wave, which contains a root wavelet which itself contains a root blip [Wave]
63
+ def create_wavelet(participants)
64
+ @context.create_wavelet(participants)
65
+ end
66
+
67
+ protected
68
+ #Register any handlers that are defined through naming convention
69
+ def register_default_handlers # :nodoc:
70
+ Event.types.each do |type|
71
+ listener = type.downcase.to_sym
72
+ if respond_to?(listener)
73
+ register_handler(type, listener)
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
61
79
  end
@@ -0,0 +1,62 @@
1
+ module Rave
2
+ module Models
3
+ # A wave client, acting as a wave creator, blip contributor and/or a wavelet participant.
4
+ class User < Component
5
+ ROBOT_PATTERN = /@appspot\.com$/ # :nodoc:
6
+ NOBODY_ID = "@@@nobody@@@" # :nodoc: Used as a default in certain circumstances.
7
+
8
+ # Url link to the profile of the User [String].
9
+ # NOTE: Due to a limitation in Wave, for all users except the local robot
10
+ # the url will be empty.
11
+ def profile_url # :nodoc:
12
+ @profile_url.dup
13
+ end
14
+
15
+ # Url link to the image of the User [String].
16
+ # NOTE: Due to a limitation in Wave, for all users except the local robot
17
+ # the url will be empty.
18
+ def image_url # :nodoc:
19
+ @image_url.dup
20
+ end
21
+
22
+ # Unlike other components, Users are never generated [Boolean].
23
+ def generated? # :nodoc:
24
+ false
25
+ end
26
+
27
+ # - :id
28
+ # - :name
29
+ # - :profile_url
30
+ # - :image_url
31
+ # - :context
32
+ def initialize(options = {}) # :nodoc:
33
+ options[:id].downcase! if options[:id]
34
+ super(options)
35
+ @name = options[:name]
36
+ @profile_url = options[:profile_url] || ''
37
+ @image_url = options[:image_url] || ''
38
+ end
39
+
40
+ # Printable name of the User [String].
41
+ # NOTE: Due to a limitation in Wave, for all users except the local robot
42
+ # the name is the same as the @id.
43
+ def name # :nodoc:
44
+ @name || @id
45
+ end
46
+
47
+ # Is the User a robot client rather than a human client? [Boolean]
48
+ def robot? # :nodoc:
49
+ not (@id =~ ROBOT_PATTERN).nil?
50
+ end
51
+
52
+ # Convert to string [String]
53
+ def to_s
54
+ @id
55
+ end
56
+
57
+ def to_json # :nodoc:
58
+ @id.to_json
59
+ end
60
+ end
61
+ end
62
+ end
data/lib/models/wave.rb CHANGED
@@ -1,19 +1,45 @@
1
- # Represents a Wave
2
- module Rave
3
- module Models
4
- class Wave
5
- attr_reader :id, :wavelet_ids
6
-
7
- attr_accessor :context
8
-
9
- #Options include:
10
- # - :wavelet_ids
11
- # - :id
12
- def initialize(options = {})
13
- @id = options[:id]
14
- @wavelet_ids = Set.new(options[:wavelet_ids])
15
- end
16
-
17
- end
18
- end
19
- end
1
+ module Rave
2
+ module Models
3
+ # Represents a Wave
4
+ class Wave < Component
5
+ # IDs for all wavelets that are part of the wave [Array of String]
6
+ def wavelet_ids # :nodoc:
7
+ @wavelet_ids.map { |id| id.dup }
8
+ end
9
+
10
+ #Options include:
11
+ # - :wavelet_ids
12
+ # - :id
13
+ def initialize(options = {}) # :nodoc:
14
+ if options[:id].nil? and options[:context]
15
+ super(:id => "#{GENERATED_PREFIX}_wave_#{unique_id}", :context => options[:context])
16
+ else
17
+ super(options)
18
+ end
19
+
20
+ @wavelet_ids = options[:wavelet_ids] || []
21
+ end
22
+
23
+ # All wavelets that are part of the wave [Array of Wavelet]
24
+ def wavelets # :nodoc:
25
+ @wavelet_ids.map { |id| @context.wavelets[id] }
26
+ end
27
+
28
+ # The root wavelet (it will be nil if the event refers to a private subwavelet) [Wavelet]
29
+ def root_wavelet # :nodoc:
30
+ wavelets.find { |wavelet| wavelet and wavelet.root? }
31
+ end
32
+
33
+ def print_structure(indent = 0) # :nodoc:
34
+ str = ''
35
+ str << "#{' ' * indent}Wave:#{@id}\n"
36
+
37
+ wavelets.each do |wavelet|
38
+ str << wavelet.print_structure(indent + 1)
39
+ end
40
+
41
+ str
42
+ end
43
+ end
44
+ end
45
+ end