Class: UU::ObjectStore::ObjectStore

Inherits:
Object
  • Object
show all
Defined in:
uu_objectstore-0.0.6/lib/uu/object_store/object_store.rb,
uu_objectstore-0.0.6/lib/uu/object_store/object_store/uu_object.rb,
uu_objectstore-0.0.6/lib/uu/object_store/object_store/uu_object_query.rb,
uu_objectstore-0.0.6/lib/uu/object_store/object_store/concurrency_strategy.rb,
uu_objectstore-0.0.6/lib/uu/object_store/object_store/object_store_exception.rb,
uu_objectstore-0.0.6/lib/uu/object_store/object_store/object_store_fatal_exception.rb

Overview

Object store component providing external storage for uuApps data.

Examples:

Basic usage:

obj_store = UU::ObjectStore::ObjectStore.init(object_store_uri)
begin
  object = obj_store.load(:dataKey => data_key, :schemaUri => schema_uri)
  object.data[:attribute] = value
  obj_store.save(object)
ensure
  obj_store.close
end

Defined Under Namespace

Classes: ConcurrencyStrategy, ObjectStoreException, ObjectStoreFatalException, UUObject, UUObjectQuery

Constant Summary

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Object) init(object_store_uri, parameters = {})

Creates new instance of object store.

Parameters:

  • object_store_uri (String, UU::OS::UESURI)

    URI of object store

  • parameters (Hash) (defaults to: {})

    Additional initialization parameters

Options Hash (parameters):

  • concurrencyStrategy (ConcurrencyStrategy)

    Concurrency strategy to be used (optional, defaults to VERSION_BASED)

  • credentials (String, File)

    Authentication token to be used for object store operations (optional, see Session.login for possible values)

  • waitTimeout (Fixnum)

    Maximum time (in seconds) to wait for uuObject unlock when loading uuObject (defaults to 30 seconds, usable only for locking concurrency strategies)



43
44
45
# File 'uu_objectstore-0.0.6/lib/uu/object_store/object_store.rb', line 43

def self.init(object_store_uri, parameters = {})
  ObjectStore.new(object_store_uri, parameters)
end

Instance Method Details

- (UUObject) attach(uu_object)

Attaches given serialized uuObject (value obtained from detach) to this object store instance. Attached uuObject must use same type of concurrency strategy as this instance of object store. Also in case of locking concurrency strategy, attach method can be called only before any other uuObject is loaded using this instance of object store.

Parameters:

  • uu_object (String)

    Serialized uuObject (value obtained from detach)

Returns:



404
405
406
407
408
409
410
411
412
413
414
415
416
# File 'uu_objectstore-0.0.6/lib/uu/object_store/object_store.rb', line 404

def attach(uu_object)
  uu_object = ObjectStore::UUObject.new(uu_object)
  lock_uri = uu_object.send(:lock_uri)
  if (((lock_uri.nil?) && ((@concurrency_strategy == ConcurrencyStrategy::SINGLE_LOCKING) || (@concurrency_strategy == ConcurrencyStrategy::BULK_LOCKING))) ||
  (!lock_uri.nil?) && (@concurrency_strategy != ConcurrencyStrategy::SINGLE_LOCKING) && (@concurrency_strategy != ConcurrencyStrategy::BULK_LOCKING))
    raise 'uuObject can be attached only to ObjectStore using same type of concurrency strategy as ObjectStore from which it was detached.'
  end
  if ((!@lock_uri.nil?) && (lock_uri != @lock_uri))
    raise 'Instance of ObjectStore uses locking concurrency strategy and has already some loaded uuObjects. Attach can be called only on fresh instance of ObjectStore.'
  end
  @lock_uri = lock_uri if @lock_uri.nil?
  return uu_object
end

- (Object) close

Method closes instance of object store and also removes all existing locks on managed uuObjects. Once instance of object store is closed, it cannot be used (Throws exception for each invoked operation. New instance must be created to access object store).



366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
# File 'uu_objectstore-0.0.6/lib/uu/object_store/object_store.rb', line 366

def close
  @closed = true
  if @lock_uri.nil?
    @authz_token = nil
    @authn_token = nil
    return
  end
  authenticate do
    svc = UU::OS::REST::RemoteClient.new(self.class)
    svc.add_header(:uu_objectstore_authorization, @authz_token)
    svc.post(:unlock, @object_store_uri, {:lockUri => @lock_uri}.to_json)
  end
  @authz_token = nil
  @authn_token = nil
  return
end

- (Object) delete(parameters)

Method deletes existing uuObject. In case deleted object is locked by concurrent process, deletion of object fails and concurrent modification exception is thrown.

Parameters:

  • parameters (UUObject)

    Instance of loaded uuObject

  • parameters (String, UU::OS::UESURI)

    URI of uuObject

  • parameters (Hash)

    Unique uuObject identification data

Options Hash (parameters):

  • :uri (String, UU::OS::UESURI)

    URI of uuObject

  • :dataKey (String)

    Unique identifier of uuObject within schema (must be set if :uri parameter is not used)

  • :schemaUri (String, UU::OS::UESURI)

    URI of schema where to look for object (optional, if not set object store default schema is used)

Raises:

  • (ObjectStoreException)

    Exception caused by wrong input or wrong usage of API. Specific cause can be determined based on error code.

  • (ObjectStoreFatalException)

    Internal uuObjectStore exception. Specific cause can be determined based on error code.



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
# File 'uu_objectstore-0.0.6/lib/uu/object_store/object_store.rb', line 281

def delete(parameters)
  if @closed
    raise 'Instance of object store is closed. Initialize new instance of object store.'
  end
  if ((parameters.kind_of?UUObject) && (parameters.send(:lock_uri) != @lock_uri))
    raise 'Instance of uuObject was loaded by another instance of ObjectStore. You have to use same instance of ObjectStore.'
  end
  authenticate do
    obj_uri = nil
    if (parameters.kind_of?UUObject)
      # Parameter was instance of uuObject
      obj_uri = parameters.uri
      return if obj_uri.nil?
    elsif (parameters.kind_of?String) || (parameters.kind_of?UU::OS::UESURI)
      # Parameter was uuObject URI
      obj_uri = parameters
    elsif parameters.kind_of?Hash
      if parameters.has_key?:uri
        # Parameter was Hash with uuObject URI
        obj_uri = parameters[:uri]
      else
        # We have to find uuObject URI via query (using dataKey and schema)
        data_key = parameters[:dataKey]
        data_key = parameters[:data_key] if data_key.nil?
        schema_uri = parameters[:schemaUri]
        schema_uri = parameters[:schema_uri] if schema_uri.nil?
        raise ArgumentError.new('Parameters must contain uuObject URI or dataKey and schema URI.') if (data_key.nil?) || (schema_uri.nil?)

        svc = UU::OS::REST::RemoteClient.new(self.class)
        svc.add_header(:uu_objectstore_authorization, @authz_token)
        svc.add_parameter(:query, "dataKey = '#{data_key}'")
        svc.add_parameter(:schemaUri, schema_uri)
        raw = svc.raw_get(:getObjectList, @object_store_uri)
        result = svc.process_result(raw)
        @authz_token = raw[2][:uu_objectstore_authorization]
        result = UU::OS::REST::ResultList.new(ObjectStore::UUObjectQuery, ObjectStore::UUObject, result)
        if result.size == 0
          # Raise fake main entity exception which is valid for this situation
          init_data = "{\"code\":\"UU.OS/E05207.M00\",\"errorMessages\":[{\"code\":\"UU.OS/E05207.M00\",\"localizedMessage\":\"Object with dataKey #{data_key} does not exist in schema #{schema_uri}.\"}]}"
          raise UU::OS::REST::MainEntityException.new(init_data)
        end

        obj_attr = result[0]
        obj_uri = obj_attr.uri
      end
    else
      raise ArgumentError.new('Parameter must be uuObject URI or Hash (containing unique object identification).')
    end
    svc = UU::OS::REST::RemoteClient.new(self.class)
    svc.add_header(:uu_objectstore_authorization, @authz_token)
    svc.add_parameter(:lockUri, @lock_uri)
    raw = svc.raw_post(:deleteObject, obj_uri)
    svc.process_result(raw)
    @authz_token = raw[2][:uu_objectstore_authorization]
  end
  return
end

- (String) detach(uu_object)

Detaches instance of given uuObject from this object store instance. Result of method is serialized uuObject in JSON format. This result should be used only for calling of attach method. For common serialization of uuObject use method to_json directly on instance of uuObject.

Parameters:

  • uu_object (UUObject)

    Instance of uuObject

Returns:

  • (String)

    Serialized uuObject



390
391
392
393
394
395
# File 'uu_objectstore-0.0.6/lib/uu/object_store/object_store.rb', line 390

def detach(uu_object)
  if ((!uu_object.uri.nil?) && (uu_object.send(:lock_uri) != @lock_uri))
    raise 'Instance of uuObject was loaded by another instance of ObjectStore. You have to use same instance of ObjectStore.'
  end
  return uu_object.to_json(:detach_format => true, :inc_orig_data => (@concurrency_strategy == ConcurrencyStrategy::MERGE))
end

- (UUObject) load(parameters)

Loads object according to given parameters. In case of locking concurrency strategy is used (SINGLE_LOCKING or BULK_LOCKING) loaded object is locked, or concurrent modification exception is thrown if object is already locked by concurrent process.

Parameters:

  • parameters (String, UU::OS::UESURI)

    URI of uuObject

  • parameters (Hash)

    Unique uuObject identification data

Options Hash (parameters):

  • :uri (String, UU::OS::UESURI)

    URI of uuObject

  • :dataKey (String)

    Unique identifier of uuObject within schema (must be set if :uri parameter is not used)

  • :schemaUri (String, UU::OS::UESURI)

    URI of schema where to look for object (optional, if not set object store default schema is used)

Returns:

Raises:

  • (ObjectStoreException)

    Exception caused by wrong input or wrong usage of API. Specific cause can be determined based on error code.

  • (ObjectStoreFatalException)

    Internal uuObjectStore exception. Specific cause can be determined based on error code.



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
# File 'uu_objectstore-0.0.6/lib/uu/object_store/object_store.rb', line 84

def load(parameters)
  if @closed
    raise 'Instance of object store is closed. Initialize new instance of object store.'
  end
  authenticate do
    obj_uri = nil
    if (parameters.kind_of?String) || (parameters.kind_of?UU::OS::UESURI)
      # Parameter was uuObject URI
      obj_uri = parameters
    elsif (parameters.kind_of?Hash) && (parameters.has_key?:uri)
      # Parameter was Hash with uuObject URI
      obj_uri = parameters[:uri]
    end
    uu_object = nil
    if !obj_uri.nil?
      # In case of locking strategies do not load object immediately. It has to be loaded after lock (to fetch most recent data).
      if (@concurrency_strategy != ConcurrencyStrategy::SINGLE_LOCKING) && (@concurrency_strategy != ConcurrencyStrategy::BULK_LOCKING)
        # uuObject URI was given as parameter, we have to load uuObject
        svc = UU::OS::REST::RemoteClient.new(self.class)
        svc.add_header(:uu_objectstore_authorization, @authz_token)
        raw = svc.raw_get(:getObjectAttributes, obj_uri)
        result = svc.process_result(raw)
        @authz_token = raw[2][:uu_objectstore_authorization]
        uu_object = ObjectStore::UUObject.new(result)
      end
    elsif (parameters.kind_of?Hash)
      # We have to find uuObject URI via query (using dataKey and schema).
      # This needs to be done even for locking strategies, because we have no object URI to call lock on.
      data_key = parameters[:dataKey]
      data_key = parameters[:data_key] if data_key.nil?
      schema_uri = parameters[:schemaUri]
      schema_uri = parameters[:schema_uri] if schema_uri.nil?
      raise ArgumentError.new('Parameters must contain uuObject URI or dataKey and schema URI.') if (data_key.nil?) || (schema_uri.nil?)

      svc = UU::OS::REST::RemoteClient.new(self.class)
      svc.add_header(:uu_objectstore_authorization, @authz_token)
      svc.add_parameter(:schemaUri, schema_uri)
      svc.add_parameter(:query, "dataKey = '#{data_key}'")
      raw = svc.raw_get(:getObjectList, @object_store_uri)
      result = svc.process_result(raw)
      @authz_token = raw[2][:uu_objectstore_authorization]
      result = UU::OS::REST::ResultList.new(ObjectStore::UUObjectQuery, ObjectStore::UUObject, result)
      if result.size == 0
        # Raise fake main entity exception which is valid for this situation
        init_data = "{\"code\":\"UU.OS/E05207.M00\",\"errorMessages\":[{\"code\":\"UU.OS/E05207.M00\",\"localizedMessage\":\"Object with dataKey #{data_key} does not exist in schema #{schema_uri}.\"}]}"
        raise UU::OS::REST::MainEntityException.new(init_data)
      end

      uu_object = result[0]
      obj_uri = uu_object.uri
    else
      raise ArgumentError.new('Parameter must be uuObject URI or Hash (containing unique object identification).')
    end

    if (@concurrency_strategy == ConcurrencyStrategy::SINGLE_LOCKING) || (@concurrency_strategy == ConcurrencyStrategy::BULK_LOCKING)
      # In case of locking strategy, we have to lock and reload object
      svc = UU::OS::REST::RemoteClient.new(self.class)
      svc.add_header(:uu_objectstore_authorization, @authz_token)
      result = nil
      wait_for_unlock(@wait_timeout) do
        raw = svc.raw_post(:lock, @object_store_uri, {:lockUri => @lock_uri, :objects => [obj_uri]}.to_json)
        result = svc.process_result(raw)
      end
      @authz_token = raw[2][:uu_objectstore_authorization]
      @lock_uri = result[1..-2]

      svc = UU::OS::REST::RemoteClient.new(self.class)
      svc.add_header(:uu_objectstore_authorization, @authz_token)
      raw = svc.raw_get(:getObjectAttributes, obj_uri)
      result = svc.process_result(raw)
      @authz_token = raw[2][:uu_objectstore_authorization]
      uu_object = ObjectStore::UUObject.new(result)
      uu_object.send(:lock_uri=, @lock_uri)
    end

    return uu_object
  end
end

- (UU::OS::REST::ResultList<UUObjectQuery, UUObject>) query(schema_uri, query = nil)

Method finds all uuObjects matching given criteria. Keep in mind, that in case of locking version strategy (SINGLE_LOCKING or BULK_LOCKING) returned objects are not automatically locked. Each of object to be modified must be explicitly locked using load method, else concurrent modification exception will be thrown upon object save.

Parameters:

Returns:

Raises:

  • (ObjectStoreException)

    Exception caused by wrong input or wrong usage of API. Specific cause can be determined based on error code.

  • (ObjectStoreFatalException)

    Internal uuObjectStore exception. Specific cause can be determined based on error code.



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'uu_objectstore-0.0.6/lib/uu/object_store/object_store.rb', line 247

def query(schema_uri, query = nil)
  if @closed
    raise 'Instance of object store is closed. Initialize new instance of object store.'
  end
  authenticate do
    dto = ObjectStore::UUObjectQuery.new(query)
    svc = UU::OS::REST::RemoteClient.new(self.class)
    svc.add_header(:uu_objectstore_authorization, @authz_token)
    svc.add_parameter(:query, dto.query)
    svc.add_parameter(:schemaUri, schema_uri)
    svc.add_parameter(:pageIndex, dto.page_index) if !dto.page_index.nil?
    svc.add_parameter(:pageSize, dto.page_size) if !dto.page_size.nil?
    if ((dto.query_parameters.kind_of?Hash) && (dto.query_parameters.size > 0))
      svc.add_parameter(:queryParameters, to_hash_with_iso_dates(dto.query_parameters).to_json)
    end
    raw = svc.raw_get(:getObjectList, @object_store_uri)
    result = svc.process_result(raw)
    @authz_token = raw[2][:uu_objectstore_authorization]
    return UU::OS::REST::ResultList.new(ObjectStore::UUObjectQuery, ObjectStore::UUObject, result)
  end
end

- (UU::OS::UESURI) save(uu_object)

Method saves given uuObject (updates existing or creates new). Method may throw concurrent modification exception in case saved object is locked by another process, or if current object state violates constraints required by used concurrency strategy.

Each object can be saved only once, it has to be re-loaded before next modification (with exception of concurrency strategy NONE). Method will throw exception on repeated object save.

Parameters:

  • uu_object (UUObject)

    Instance of uuObject

Returns:

Raises:

  • (ObjectStoreException)

    Exception caused by wrong input or wrong usage of API. Specific cause can be determined based on error code.

  • (ObjectStoreFatalException)

    Internal uuObjectStore exception. Specific cause can be determined based on error code.



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
# File 'uu_objectstore-0.0.6/lib/uu/object_store/object_store.rb', line 176

def save(uu_object)
  if @closed
    raise 'Instance of object store is closed. Initialize new instance of object store.'
  end
  if (@concurrency_strategy != ConcurrencyStrategy::NONE) && (uu_object.send(:saved))
    raise 'Instance of uuObject was already saved. Re-load uuObject before next modification.'
  end
  if (!uu_object.uri.nil?)
    if ((uu_object.send(:lock_uri).nil?) && ((@concurrency_strategy == ConcurrencyStrategy::SINGLE_LOCKING) || (@concurrency_strategy == ConcurrencyStrategy::BULK_LOCKING)))
      # Check-in can be called only if object is locked
      raise 'Instance of uuObject cannot be saved. It has to be loaded via load method when locking concurrency strategy is used.'
    end
    if (uu_object.send(:lock_uri) != @lock_uri)
      raise 'Instance of uuObject was loaded by another instance of ObjectStore. You have to use same instance of ObjectStore.'
    end
  end
  authenticate do
    obj_uri = nil
    if uu_object.uri.nil?
      # New object
      payload = {:schemaUri => uu_object.schema_uri, :dataKey => uu_object.data_key, :data => to_hash_with_iso_dates(uu_object.data)}
      svc = UU::OS::REST::RemoteClient.new(self.class)
      svc.add_header(:uu_objectstore_authorization, @authz_token)
      raw = svc.raw_post(:createObject, @object_store_uri, payload.to_json)
      result = svc.process_result(raw)
      @authz_token = raw[2][:uu_objectstore_authorization]
      obj_uri = UU::OS::UESURI.new(result)
    else
      # Updated object
      svc = UU::OS::REST::RemoteClient.new(self.class)
      svc.add_header(:uu_objectstore_authorization, @authz_token)
      payload = {:version => uu_object.version, :concurrencyStrategy => @concurrency_strategy, :lockUri => @lock_uri}
      if @concurrency_strategy == ConcurrencyStrategy::MERGE
        # For concurrency strategy MERGE, prepare custom set of data
        orig_data = uu_object.data.send(:orig_data)
        data = {}
        orig_data.each_key do |key|
          data[key] = uu_object.data[key]
        end
        payload[:originalData] = to_hash_with_iso_dates(orig_data)
        payload[:data] = to_hash_with_iso_dates(data)
        if uu_object.send(:data_key_changed)
          payload[:originalDataKey] = uu_object.send(:orig_data_key)
          payload[:dataKey] = uu_object.data_key
        end
      else
        payload[:dataKey] = uu_object.data_key
        payload[:data] = to_hash_with_iso_dates(uu_object.data)
      end
      raw = svc.raw_post(:setObjectAttributes, uu_object.uri, payload.to_json)
      result = svc.process_result(raw)
      @authz_token = raw[2][:uu_objectstore_authorization]
      obj_uri = UU::OS::UESURI.new(result)
    end
    uu_object.send(:saved=, true)
    return obj_uri
  end
end

- (Object) unlock(uu_object)

This method is usable only for locking concurrency strategies. It allows to unlock uuObject without calling save method (for SINGLE_LOCKING strategy) or closing of object store instance (for both SINGLE_LOCKING or BULK_LOCKING). In case object is not locked, or locking strategy is not used, method does nothing.

Parameters:

  • uu_object (UUObject)

    Instance of locked uuObject

Raises:

  • (ObjectStoreException)

    Exception caused by wrong input or wrong usage of API. Specific cause can be determined based on error code.

  • (ObjectStoreFatalException)

    Internal uuObjectStore exception. Specific cause can be determined based on error code.



349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'uu_objectstore-0.0.6/lib/uu/object_store/object_store.rb', line 349

def unlock(uu_object)
  return if uu_object.nil?
  return if uu_object.uri.nil?
  return if @lock_uri.nil?
  authenticate do
    svc = UU::OS::REST::RemoteClient.new(self.class)
    svc.add_header(:uu_objectstore_authorization, @authz_token)
    raw = svc.raw_post(:unlock, @object_store_uri, {:lockUri => @lock_uri, :objects => [uu_object.uri]}.to_json)
    svc.process_result(raw)
    @authz_token = raw[2][:uu_objectstore_authorization]
  end
  return
end