summaryrefslogtreecommitdiff
path: root/cpp/bindings/qpid/ruby/lib/qpid/message.rb
blob: edef0ac2a0255069cc38da8e2a2ddb444ef67c0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

require 'cqpid'

module Qpid

  module Messaging

    # A +Message+ represents an routable piece of information.
    #
    # The content for a message is automatically encoded and decoded.
    #
    class Message

      # Creates a new instance of +Message+.
      #
      # ==== Options
      #
      # * :content - The content.
      #
      # ==== Examples
      #
      #   message = Qpid::Messaging::Message.new :content => "This is a message."
      #
      def initialize(args = {})
        @message_impl = (args[:impl] if args[:impl]) || nil
        @message_impl = Cqpid::Message.new if @message_impl.nil?
        @content = nil
        args = {} if args.nil?
        self.content = args[:content] if args[:content]
      end

      def message_impl # :nodoc:
        @message_impl
      end

      # Sets the address to which replies should be sent for the +Message+.
      #
      # *NOTE:* The address must be an instance of Address.
      #
      # ==== Options
      #
      # * address - an instance of +Address+
      #
      # ==== Examples
      #
      #   msg.reply_to = Qpid:Messaging::Address.new "my-responses"
      #
      def reply_to=(address)
        raise ArgumentError, "Agument must be an Address" unless address.is_a? Qpid::Messaging::Address
        @message_impl.setReplyTo address.address_impl
      end

      # Returns the reply to address for the +Message+.
      #
      def reply_to
        address_impl = @message_impl.getReplyTo
        # only return an address if a reply to was specified
        Qpid::Messaging::Address.new(nil, nil, nil, nil, address_impl) if address_impl
      end

      # Sets the subject for the +Message+.
      #
      # ==== Options
      #
      # * subject - the subject
      #
      # ==== Examples
      #
      #   msg.subject = "mysubject"
      #
      def subject=(subject); @message_impl.setSubject subject; end

      # Returns the subject of the +Message+.
      #
      # ==== Options
      #
      #   puts "The subject is #{msg.subject}"
      #
      def subject; @message_impl.getSubject; end

      # Sets the content type for the +Message+.
      #
      # This should be set by the sending applicaton and indicates to
      # recipients of the message how to interpret or decode the content.
      #
      # By default, only dictionaries and maps are automatically given a content
      # type. If this content type is replaced then retrieving the content will
      # not behave correctly.
      #
      # ==== Options
      #
      # * content_type - the content type.
      #
      def content_type=(content_type); @message_impl.setContentType content_type; end

      # Returns the content type for the +Message+.
      #
      # ==== Examples
      #
      #   case msg.content_type
      #     when "myapp/image"
      #       ctl.handle_image msg
      #       end
      #     when "myapp/audio"
      #       ctl.handle_audio msg
      #       end
      #   end
      #
      def content_type; @message_impl.getContentType; end

      # Sets the message id.
      #
      # *NOTE:* this field must be a UUID type currently. A non-UUID value will
      # be converted to a zero UUID, though a blank ID will be left untouched.
      #
      # ==== Options
      #
      # * id - the id
      #
      # ==== Examples
      #
      #
      def message_id=(message_id); @message_impl.setMessageId message_id.to_s; end

      # Returns the message id.
      #
      # See +message_id=+ for details.
      def message_id; @message_impl.getMessageId; end

      # Sets the user id for the +Message+.
      #
      # This should in general be the user-id which was used when authenticating
      # the connection itself, as the messaging infrastructure will verify
      # this.
      #
      # See +Qpid::Messaging::Connection.authenticated_username+
      #
      # *NOTE:* If the id is not a +String+ then the id is set using
      # the object's string representation.
      #
      # ==== Options
      #
      # * id - the id
      #
      def user_id=(user_id); @message_impl.setUserId user_id; end

      # Returns the user id for the +Message+.
      #
      # See +user_id=+ for details.
      #
      def user_id; @message_impl.getUserId; end

      # Sets the correlation id of the +Message+.
      #
      # The correlation id can be used as part of a protocol for message
      # exchange patterns; e.g., a requestion-response pattern might require
      # the correlation id of the request and the response to match, or it
      # might use the message id of the request as the correlation id on
      # the response
      #
      # *NOTE:* If the id is not a +String+ then the id is setup using
      # the object's string representation.
      #
      # ==== Options
      #
      # * id - the id
      #
      def correlation_id=(correlation_id); @message_impl.setCorrelationId correlation_id; end

      # Returns the correlation id of the +Message+.
      #
      # *NOTE:* See +correlation_id=+ for details.
      #
      def correlation_id; @message_impl.getCorrelationId; end

      # Sets the priority of the +Message+.
      #
      # This may be used by the messaging infrastructure to prioritize
      # delivery of messages with higher priority.
      #
      # *NOTE:* If the priority is not an integer type then it is set using
      # the object's integer representation. If the integer value is greater
      # than 8-bits then only the first 8-bits are used.
      #
      # ==== Options
      #
      # * priority - the priority
      #
      def priority=(priority); @message_impl.setPriority priority; end

      # Returns the priority for the +Message+.
      #
      def priority; @message_impl.getPriority; end

      # Sets the time-to-live in milliseconds.
      #
      # ==== Options
      #
      # * duration - the number of milliseconds
      #
      def ttl=(duration)
        if duration.is_a? Qpid::Messaging::Duration
          @message_impl.setTtl duration.duration_impl
        else
          @message_impl.setTtl Cqpid::Duration.new duration.to_i
        end
      end

      # Returns the time-to-live in milliseconds.
      def ttl; Qpid::Messaging::Duration.new @message_impl.getTtl.getMilliseconds; end

      # Sets the durability of the +Message+.
      #
      # This is a hint to the messaging infrastructure that the message
      # should be persisted or otherwise stored. This helps to ensure
      # that th emessage is not lost during to failures or a shutdown.
      #
      # ==== Options
      #
      # * durable - the durability flag (def. false)
      #
      def durable=(durable); @message_impl.setDurable durable; end

      # Returns the durability for the +Message+.
      #
      def durable; @message_impl.getDurable; end

      # This is a hint to the messaging infrastructure that if de-duplication
      # is required, that this message should be examined to determine if it
      # is a duplicate.
      #
      # ==== Options
      #
      # * redelivered - sets the redelivered state (def. false)
      #
      # ==== Examples
      #
      #   # processed is an array of processed message ids
      #   msg.redelivered = true if processed.include? msg.message_id
      #
      def redelivered=(redelivered); @message_impl.setRedelivered redelivered; end

      # Returns whether the +Message+ has been marked as redelivered.
      #
      def redelivered; @message_impl.getRedelivered; end

      # Returns all named properties.
      #
      # *NOTE:* It is recommended to use the []= method for
      # retrieving and setting properties. Using this method may
      # result in non-deterministic behavior.
      #
      def properties; @message_impl.getProperties; end

      # Returns the value for the named property.
      #
      # ==== Options
      #
      # * name - the property name
      #
      # ==== Examples
      #
      #   # use of message properties to mark a message as digitally signed
      #   verify(msg) if msg[:signed]
      #
      def [](key); self.properties[key.to_s]; end

      # Assigns a value to the named property.
      #
      # *NOTE:* Both the key or the value may be a symbol, but they will
      # both be converted to a +String+ for ease of transport.
      #
      # ==== Options
      #
      # * name - the property name
      # * value - the property value
      def []=(key, value); @message_impl.setProperty(key.to_s, value.to_s); end

      # Sets the content for the +Message+.
      #
      # Content is automatically encoded for Array and Hash types. Other types
      # need to set their own content types (via +content_type+) in order to
      # specify how recipients should process the content.
      #
      # ==== Options
      #
      # * content - the content
      #
      # ==== Examples
      #
      #   msg.content = "This is a simple message." # a simple message
      #   msg.content = {:foo => :bar} # content is automatically encoded
      #
      def content=(content)
        content_type = nil
        @content = content
        case @content
        when Hash
          content_type = "amqp/map"
          new_content  = {}
          content.each_pair{|key, value| new_content[key.to_s] = value.to_s}
          @content = new_content
        when Array
          new_content  = []
          content_type = "amqp/list"
          content.each {|element| new_content << element.to_s}
          @content = new_content
        end
        if content_type.nil?
          @message_impl.setContent @content
        else
          Qpid::Messaging.encode @content, self, content_type
        end
      end

      # Returns the content of the +Message+.
      #
      # Content is automatically decoded based on the specified content type.
      # If the content type is application-specific, then no decoding is
      # performed and the content is returnedas a +String+ representation.
      #
      # For example, if an array of integers are sent, then the receiver will
      # find the message content to be an array of String objects, where each
      # String is a representation of the sent integer value.
      #
      def content
        if @content.nil?
          @content = @message_impl.getContent

          # decode the content is necessary if it
          # has an encoded content type
          if ["amqp/list", "amqp/map"].include? @message_impl.getContentType
            @content = Qpid::Messaging.decode(self,
                                              @message_impl.getContentType)
          end

        end
        @content
      end

      # Returns the content's size.
      #
      def content_size; @message_impl.getContentSize; end

    end

  end

end