module PIM
Constants
- DISABLE_EXECUTION_GUARD_THREAD_KEY
Thread variable that tells whether the execution guard is switched off for the request running on a thread, see {__before_request}. It is a thread variable, not a fiber-local one, so the Fibers and Enumerators that a request starts see it as well.
- DefaultExportFormats
Create Enum type containing all known export formats
- EmptyToNilHashAttribute
Special Hash type attribute which will always return ‘nil’ if empty in json
- EmptyToNilSetAttribute
Special Set type attribute which will always return ‘nil’ if empty in json
- InternalSystemHashAttribute
Internal system attribute of base class ‘Hash’ which does not return it’s value as json
- PublicationStatus
Create some system types
- REFERENCE_CATEGORIES_RULE
Public Class Methods
# File pim.rb, line 1234 def self.__after_request # Pop the context of the calling request. Without a matching __before_request there is none, and only # the top frame is stopped. contexts = Thread.current[:__request_contexts] context = contexts && contexts.pop outermost = contexts.nil? || contexts.empty? Thread.current[:__request_contexts] = nil if contexts && contexts.empty? frame = context ? context[:frame] : ExecutionGuard.top # Stop the frame of this request and all the frames that interrupted scopes left above it, suspended # ones included, so no watchdog thread outlives the request. This comes before the exit blocks and # the cache cleanup, which must run even if the script's deadline elapses just now: the timeout is # raised afterwards. timeout = nil begin ExecutionGuard.drop_frame frame rescue ExecutionTimeoutError => e timeout = e retry if ExecutionGuard.active?(frame) end # Call exit blocks of this request request_exit_blocks = Thread.current[:__request_exit_blocks] unless request_exit_blocks.nil? request_exit_blocks.each do |block_name, block| begin block.call rescue => e PIM.log_error "Error executing request exit block '#{block_name}'", e end end end # Back to the request exit blocks and fiber local caches of the calling request (none for the outermost one) Thread.current[:__request_exit_blocks] = context && context[:exit_blocks] Thread.current[:__caches] = context && context[:caches] # The outermost request is over, so the next request on this thread decides again whether it is guarded Thread.current.thread_variable_set(DISABLE_EXECUTION_GUARD_THREAD_KEY, nil) if outermost raise timeout if timeout end
Starts a request on the current thread, to be ended by {__after_request}: pushes the context of the calling request, starts with fresh fiber-local caches and request exit blocks, and starts the frame with the deadline of the script (see {ExecutionGuard}).
With disable_execution_guard (server property RUBY_DISABLE_EXECUTION_GUARD) the request runs without execution guard: no frame, no watchdog, no deadline. The outermost request of a thread decides. Requests nested in it inherit that and ignore the option, so a request never mixes guarded and unguarded scopes, and a request that already runs is not affected when the property is changed meanwhile.
# File pim.rb, line 1184 def self.__before_request(deadline_seconds: nil, deadline_reason_message: nil, script_path: nil, disable_execution_guard: false) # Push the context of the calling request, so __after_request can restore it. Requests can be nested (e.g. # a workflow calling before_store). The outermost one pushes the empty context, so whatever was left behind # outside of a request is cleared. contexts = (Thread.current[:__request_contexts] ||= []) outermost = contexts.empty? context = { caches: outermost ? nil : Thread.current[:__caches], exit_blocks: outermost ? nil : Thread.current[:__request_exit_blocks], frame: nil } contexts << context # The outermost request decides whether the execution guard is switched off, see above if outermost Thread.current.thread_variable_set(DISABLE_EXECUTION_GUARD_THREAD_KEY, disable_execution_guard ? true : nil) end # No request is active, so every execution-guard frame still on the stack was left behind by a request that # is over. Stop them, so the new request does not inherit their limits or get hit by their watchdogs. A # timeout that lands in here belongs to that earlier request. stale_frame = outermost ? ExecutionGuard.bottom : nil unless stale_frame.nil? PIM.log_warn "Dropping #{ExecutionGuard.depth} stale execution guard frame(s) left behind by an earlier request" begin ExecutionGuard.drop_frame stale_frame rescue ExecutionTimeoutError # Nothing to report for the new request end end # Start with fresh fiber local caches and request exit blocks Thread.current[:__caches] = nil Thread.current[:__request_exit_blocks] = {} # Without execution guard the request has no frame (stale ones of an earlier request were dropped above), so # __after_request has none to stop either return if execution_guard_disabled? # The frame is part of the context before it is started, so __after_request finds it however far the start got frame = ExecutionGuard.create_frame(deadline_seconds: deadline_seconds, reason_message: deadline_reason_message, script_path: script_path) context[:frame] = frame ExecutionGuard.start_frame frame end
# File pim.rb, line 676 def self.__fiber_local_cache name (Thread.current[:__caches] ||= {})[name.to_sym] ||= {} end
# File pim.rb, line 43 def self.active_module return @current_active_module if @current_active_module return PIM if all_modules.empty? @all_modules.values.last end
# File pim.rb, line 230 def self.additional_attributes_as_json attribute_names_per_module return active_module.additional_attributes_as_json(attribute_names_per_module) if not all_modules.empty? end
# File pim.rb, line 226 def self.additional_categories_as_json category_names_per_module return active_module.additional_categories_as_json(category_names_per_module) if not all_modules.empty? end
# File pim.rb, line 234 def self.additional_section_attributes_as_json layout_name, item return active_module.additional_section_attributes_as_json(layout_name, item) if not all_modules.empty? end
# File pim.rb, line 447 def self.after_store new_item, old_item = nil, opts = {} execute_item_method 'after_store', new_item, old_item, opts end
# File pim.rb, line 35 def self.all_modules @all_modules ||= {} end
# File pim.rb, line 1418 def self.at_request_exit block_name = nil, &block unless block.nil? block_name ||= block.to_s request_exit_blocks = (Thread.current[:__request_exit_blocks] ||= {}) request_exit_blocks[block_name] = block return block_name end unless block_name.nil? request_exit_blocks = Thread.current[:__request_exit_blocks] return request_exit_blocks.nil? ? nil : request_exit_blocks[block_name] end return nil end
# File pim.rb, line 170 def self.attribute_rules_as_json return active_module.attribute_rules_as_json if not all_modules.empty? return [] end
# File pim.rb, line 129 def self.attributes_as_json return active_module.attributes_as_json if not all_modules.empty? end
# File pim.rb, line 451 def self.before_delete new_item, opts = {} execute_item_method 'before_delete', new_item, nil, opts end
Old version: Just for compatibility with projects which directly called this method
# File pim.rb, line 407 def self.before_store old_item, new_item, called_from_import return [] if all_modules.empty? begin old_item = Item.from_json old_item, { :init_multivalue => false } if old_item rescue Exception => e PIM.log_warn("Could not resolve class of old item in 'before_store' (#{old_item})", e) end begin new_item = Item.from_json new_item, { :init_multivalue => false } rescue Exception => e PIM.log_warn("Could not resolve class of new item in 'before_store' (#{new_item})", e) end begin if new_item && new_item.kind_of?(Item) items_changed = [{ "ORIG" => new_item }] before_store = new_item.method(:before_store) if before_store.arity == 1 and not called_from_import items_changed_in_class = new_item.before_store(old_item) elsif before_store.arity == 2 items_changed_in_class = new_item.before_store(old_item, called_from_import) end items_changed_in_class.each do |item| items_changed << { "SAVE" => item } end if items_changed_in_class and items_changed_in_class.respond_to? :each return items_changed end rescue Exception => e PIM.log_error("Error in 'before_store'", e) end return [] end
# File pim.rb, line 443 def self.before_store_v2 new_item, old_item = nil, opts = {} execute_item_method 'before_store', new_item, old_item, opts end
# File pim.rb, line 672 def self.cache PIM.__fiber_local_cache(:__pim_cache) end
# File pim.rb, line 660 def self.calculate_category values return nil if all_modules.empty? values = PIM::Utils.symbolized_hash(values) active_module.calculate_category values end
# File pim.rb, line 666 def self.calculate_primary_key values return nil if all_modules.empty? values = PIM::Utils.symbolized_hash(values) active_module.calculate_primary_key values end
# File pim.rb, line 563 def self.call_item_method method_name, new_item, old_item = nil, opts = {} method_sym = method_name.to_sym return nil if not new_item.respond_to?(method_sym) item_method = new_item.method(method_sym) arity = item_method.arity.abs result = nil # # Omit calling before_store if we are called in the context # of a depublication, and the current datamodel is not aware # that this can happen. # if method_name == 'before_store' called_from_depublication = opts[:called_from_depublication] || opts['called_from_depublication'] if called_from_depublication and not active_module.has_option?(:consider_called_from_depublication) PIM.log_debug("Store method '#{method_name}' called from depublication, but current datamodel is not aware of this feature. Invocation will be omitted.") return nil end end if method_name == 'before_store' and not active_module.has_option?(:use_before_store_opts) # For compatibility: 'before_store' only has the 'called_from_import' parameter called_from_import = opts[:called_from_import] || opts['called_from_import'] if arity == 2 result = item_method.call(old_item, called_from_import) elsif arity == 1 # For compatibility: Without 'called_from_import' parameter, 'before_store' is not called at all if not called_from_import result = item_method.call(old_item) end elsif arity == 0 result = item_method.call() else PIM.log_warn("Store method '#{method_name}' does not have the correct number of arguments (#{arity} not in 0, 1 or 2)") end else if arity == 2 result = item_method.call(old_item, opts) elsif arity == 1 opts[:old_item] = opts['old_item'] = old_item result = item_method.call(opts) elsif arity == 0 result = item_method.call() else PIM.log_warn("Item method '#{method_name}' does not have the correct number of arguments (#{arity} not in 0, 1 or 2)") end end return result end
# File pim.rb, line 133 def self.categories_as_json return active_module.categories_as_json if not all_modules.empty? end
# File pim.rb, line 184 def self.category_as_json category_name return nil if all_modules.empty? category = active_module.category category_name return category.as_json if category end
# File pim.rb, line 549 def self.cleanup_items items, include_empty items.map do |item| if item.is_a?(PIM::Item) json_hash = item.as_json(include_empty: include_empty) json_string = json_hash.to_json # Creates a JSON string JSON.parse(json_string) # Creates a "cleaned up" JSON Hash elsif !is_java_item?(item) and item.is_a?(Hash) PIM.javaify(item) else item end end end
# File pim.rb, line 149 def self.communication_channels_as_json return active_module.communication_channels_as_json if not all_modules.empty? end
# File pim.rb, line 145 def self.communication_plans_as_json return active_module.communication_plans_as_json if not all_modules.empty? end
Should not be overridden in data model!
# File pim.rb, line 342 def self.compute_item_hierarchies_to_publish primary_keys, publication = nil return {} if active_module.nil? if active_module.respond_to?(:compute_item_hierarchies_to_publish) # Data model overrides 'compute_item_hierarchies_to_publish' PIM.log_info("Data model overrides 'compute_item_hierarchies_to_publish' method") return active_module.compute_item_hierarchies_to_publish(primary_keys) elsif active_module.respond_to?(:compute_items_to_publish) # Data model implements old 'compute_items_to_publish' method PIM.log_warn("Data model still implements old 'compute_items_to_publish' method") return active_module.compute_items_to_publish(primary_keys) else # Simple LRU item cache item_cache = PIM::LRUCache.new(20) # Options to retrieve publication hierarchies publication_type = PIM.get_value(publication, 'publication_type') publication_values = PIM.get_value(publication, 'publication_values') publish_only_valid = PIM.get_value(publication_values, 'only_valid') if publish_only_valid.nil? publish_only_valid = publication_type.nil? || publication_type == 'ADD' else publish_only_valid = publish_only_valid.to_s.downcase == 'true' end opts = { :item_cache => item_cache, :only_valid => publish_only_valid, :publication => (publication || {}) } # Step one: Determine the top level items for the hierarchies to publish top_level_items = active_module.get_top_level_items(primary_keys, opts) # Step two: Determine the hierarchies for each top level item item_hierarchies = {} top_level_items.each do |top_level_item, status| # Set status from top_level_item result opts[:status] = status item_hierarchy = active_module.get_item_hierarchy(top_level_item, opts) item_hierarchy = active_module.update_hierarchy(item_hierarchy, opts) item_hierarchies[top_level_item] = item_hierarchy unless item_hierarchy.nil? end return item_hierarchies end end
# File pim.rb, line 106 def self.contact_attributes_as_json return active_module.contact_attributes if not all_modules.empty? return [] end
# File pim.rb, line 194 def self.copy_item_as_json item, organization, template return nil if all_modules.empty? template = PIM::Utils.hash_from_json template, "for copy item template" arity = active_module.method(:copy_item).arity.abs copy = case arity when 3 then active_module.copy_item item, organization, template else active_module.copy_item item, organization end return copy.as_json if copy end
# File pim.rb, line 116 def self.dashboard_attributes_as_json return active_module.dashboard_attributes if not all_modules.empty? return [] end
# File pim.rb, line 121 def self.data_model_as_json return active_module.data_model_as_json if not all_modules.empty? end
# File pim.rb, line 81 def self.data_model_services service_data_model_hash_map = nil @service_data_model_hash_map = service_data_model_hash_map unless service_data_model_hash_map.nil? @service_data_model_hash_map end
# File pim.rb, line 91 def self.data_model_values_as_json return active_module.data_model_values_as_json if not all_modules.empty? return {} end
# File pim.rb, line 206 def self.default_item_as_json category_name, organization, user, template return nil if all_modules.empty? category = active_module.category category_name template = template.nil? ? {} : PIM::Utils.hash_from_json(template, "for default item template") if category and category.respond_to?(:default_item) organization = PIM::Services.__convert(organization, to: PIM::Services::OrganizationService::Organization) user = PIM::Services.__convert(user, to: PIM::Services::AccountService::LoginAccount) arity = category.method(:default_item).arity.abs item = case arity when 3 then category.default_item(organization, user, template) when 2 then category.default_item(organization, user) when 1 then category.default_item(organization) else category.default_item end return item.as_json if !item.nil? end end
# File pim.rb, line 455 def self.execute_item_method method_name, new_item, old_item = nil, opts = {} return {} if all_modules.empty? begin new_item = PIM::Item.from_json(new_item, :init_multivalue => false) rescue Exception => e PIM.log_warn("Could not create new item in '#{method_name}' for:\n#{new_item}", e) end return {} if not new_item.is_a?(PIM::Item) old_item ||= opts[:old_item] if old_item begin old_item = PIM::Item.from_json(old_item, :init_multivalue => false) rescue Exception => e PIM.log_warn("Could not create old item in '#{method_name}' for:\n#{old_item}", e) end old_item = nil if not old_item.is_a?(PIM::Item) end begin method_call_result = self.call_item_method(method_name, new_item, old_item, opts) rescue Exception => e PIM.log_error("Error calling '#{method_name}' method", e) return { "exception" => e.message } end result = {} include_empty = active_module.has_option?(:return_empty_values) if method_name == 'before_store' # Check if 'store_item' was set to false if PIM.get_value(method_call_result, :store_item) == false # NOTE: We could allow to set 'store_item' to a Hash in order to store the item as specified! # This way we would not merge the item with the old values at all! result['this'] = false result['call_after_store'] = false else result['this'] = new_item.as_json(include_empty: include_empty) call_after_store = PIM.get_value(method_call_result, :call_after_store) call_after_store = (self.call_item_method('call_after_store?', new_item, old_item, opts) == true) if call_after_store.nil? result['call_after_store'] = call_after_store end end if not is_empty?(method_call_result) if is_array?(method_call_result) result['others'] = self.cleanup_items(method_call_result, include_empty) elsif is_hash?(method_call_result) # Set 'status_values' from call result, if any self.set_javaify_method_call_result(result, method_call_result, :status_values) # Convert and add store_options and store_items to actual result result_others = {} # Use 'javaify' to convert the options to ensure no Ruby Symbol objects are used in Java self.set_javaify_method_call_result(result_others, method_call_result, :store_options) self.set_javaify_method_call_result(result_others, method_call_result, :delete_items) self.set_javaify_method_call_result(result_others, method_call_result, :validate_items) self.set_javaify_method_call_result(result_others, method_call_result, :validate_items_rules) self.set_javaify_method_call_result(result_others, method_call_result, :validate_items_attributes) # Set items to store as "cleaned up" JSON self.set_method_call_result(result_others, method_call_result, :store_items) { |items| PIM.cleanup_items(items, include_empty: include_empty) } result['others'] = result_others unless PIM.is_empty?(result_others) end end return result end
# File pim.rb, line 402 def self.execute_plan_action action_type, action_creator, action_tags, action_date, channel, organization, data return active_module.execute_plan_action(action_type, action_creator, action_tags, action_date, channel, organization, data) if not all_modules.empty? end
Absolute deadline (Time) of the current execute frame, or nil if unlimited / no frame.
# File pim.rb, line 1413 def self.execution_deadline frame = ExecutionGuard.top frame.nil? ? nil : frame.execution_deadline end
Run the block under an execution-guard frame of its own, with its watchdog. The limits of the frames it runs in (e.g. the script’s own deadline, see {__before_request}) keep applying to it, and deadline_seconds can add a wall-clock limit of its own (see {guard_execution_deadline} for a limit per part of the block). The frame and its watchdog are gone again when the block ends, however it ends, together with any frame that interrupted scopes left behind above it. Unlike {__before_request}, it does not reset fiber-local caches or request-exit blocks, so it is safe to nest for per-rule validation deadlines inside an active validate call. If the execution guard is switched off for the request (see {__before_request}) there is no frame and no watchdog: the block just runs. Returns the value of the block.
Future extension (not implemented): an optional create_exception callable could let a nested guard raise a distinct error type (e.g. for per-rule validation deadlines) while the default remains {ExecutionTimeoutError}. That would keep unstructured call budgets ({limit_execution_deadline} / RUBY_DEFAULT_EXECUTION_DEADLINE) complementary to structured per-rule caps without ambiguous rescue dispatch.
# File pim.rb, line 1298 def self.execution_guard deadline_seconds: nil, reason_message: nil, script_path: nil return yield if execution_guard_disabled? frame = ExecutionGuard.create_frame(deadline_seconds: deadline_seconds, reason_message: reason_message, script_path: script_path) begin ExecutionGuard.start_frame frame yield ensure ExecutionGuard.drop_frame frame end end
Whether the execution guard is switched off for the request running on this thread. Then the request has no frame and no watchdog, {execution_guard} just runs its block, and the other guard methods find no frame and do nothing. Internal.
# File pim.rb, line 1171 def self.execution_guard_disabled? Thread.current.thread_variable_get(DISABLE_EXECUTION_GUARD_THREAD_KEY) == true end
# File pim.rb, line 141 def self.filters_as_json return active_module.filters_as_json if not all_modules.empty? end
Format a deadline for messages: integral Floats as Integer, fractions unchanged. nil_text is used when seconds is nil (e.g. ‘unlimited’ or ‘unknown’).
# File pim.rb, line 707 def self.format_deadline_text seconds, nil_text: 'unlimited' return nil_text if seconds.nil? seconds == seconds.to_i ? seconds.to_i : seconds end
Run the block with its own wall-clock budget of seconds on the top execution-guard frame, e.g. a nested frame of {execution_guard} to cap each validation rule. The budget replaces the frame’s current deadline (it may extend it, so use it on a nested frame, not on a script’s own frame) but never goes beyond the deadlines of the enclosing frames. It is cleared again when the block ends, even if the block raises.
A timeout cannot be dodged by the block: if one was delivered while the block ran (its own, or one of the enclosing frames) but the block ended normally anyway, the code in it swallowed the error (rescue => e), so the error is raised when the block ends. That does not bound a block which never ends.
Returns the value of the block. Without a budget (no execution guard is active, or seconds is nil or not positive) the block just runs; only the check for swallowed timeouts of the enclosing frames is still done.
# File pim.rb, line 1387 def self.guard_execution_deadline seconds, reason_message = nil frame = ExecutionGuard.top return yield if frame.nil? limited = seconds.to_f > 0.0 frame.reset_execution_deadline(seconds, reason_message) if limited result = nil delivered = nil begin result = yield ensure delivered = limited ? frame.clear_execution_deadline : frame.delivered_timeout_error end # Only reached if the block ended without an exception raise delivered if delivered result end
# File pim.rb, line 39 def self.has_module? module_name @all_modules && @all_modules.include?(module_name.to_s) end
# File pim.rb, line 153 def self.hierarchies_as_json return as_json(active_module.all_hierarchies) if not all_modules.empty? end
# File pim.rb, line 157 def self.in_platform_publication_as_json return as_json(active_module.in_platform_publication) if not all_modules.empty? end
Return an item hierarchy graph for the specified item and hierarchy name. If hiearchy_name is nil, returns the “default” hierarchy.
The resulted hierarchy should have the following JSON structure:
{
"items": [
{
"primaryKey": "22222", <- Primary key of the item in the hierarchy
"level": 1 <- Level of hierarchy, starts with 0
},
...
], // Alternatively, it is also possible to use primary keys only,
e.g. items: [ "1234", "4567", ... ] however no mixture of both!
"relations": [
{
"parentItem": "", <- Primary key of the parent item
"childItem": "", <- Primary key of the child item
"relationValue": "20x", <- Value of the relationship (optional)
"relationAttribute": "amount" <- The unit of the relationship (optional)
},
...
]
}
# File pim.rb, line 286 def self.item_hierarchy_graph item, hierarchy_name = nil return nil if all_modules.empty? if is_hash?(item) begin item = Item.from_json(item, { :init_multivalue => false }) rescue Exception => e PIM.log_warn("Could not create item in 'item_hierarchy_graph' for:\n#{item}", e) end elsif is_string?(item) primary_key = item item = PIM::Services::ItemService.get_item_as_ruby(primary_key, :init_multivalue => false) PIM.log_warn("Item for primary key '#{primary_key}' in item_hierarchy_graph not found") if item.nil? end return nil if not item.is_a?(Item) # Get hierarchy graph for item hierarchy_graph = item.method(:hierarchy_graph) if hierarchy_graph arity = hierarchy_graph.arity hierarchy = case arity when 0 then item.hierarchy_graph() when 1, -1 then item.hierarchy_graph(hierarchy_name) when 2, -2 then item.hierarchy_graph(hierarchy_name, {}) else PIM.log_warn("'hierarchy_graph' method for category #{item.class} does not have the correct number of arguments (#{arity.abs} not in 0, 1 or 2)") nil end else PIM.log_info("No 'hierarchy_graph' method in category #{item.class}") hierarchy = nil end if is_hash?(hierarchy) hierarchy[:items].map! { |item| camelize(item) } if hierarchy[:items] hierarchy[:relations].map! { |relation| camelize(relation) } if hierarchy[:relations] end return hierarchy end
# File pim.rb, line 161 def self.item_scopes_as_json return as_json(active_module.item_scopes) if not all_modules.empty? end
# File pim.rb, line 249 def self.layout_as_json layout_name, opts = {} return nil if all_modules.empty? layout = active_module.layout layout_name return layout.as_json(opts) if layout end
# File pim.rb, line 137 def self.layouts_as_json return active_module.layouts_as_json if not all_modules.empty? end
Tighten the current execute’s remaining wall-clock budget to at most seconds. Never extends an existing deadline. Raises ExecutionTimeoutError if already past. Optional reason_message replaces the frame’s timeout explanation when provided. Does nothing when no execution guard is active.
# File pim.rb, line 1367 def self.limit_execution_deadline seconds, reason_message = nil frame = ExecutionGuard.top frame.limit_execution_deadline(seconds, reason_message) unless frame.nil? end
# File pim.rb, line 242 def self.managing_user_roles_as_json user, contact # FIXME: Add 'Contact' class in 'ContactService' to support execution on external Ruby! # user = PIM::Services.__convert(user, to: PIM::Services::AccountService::LoginAccount) # contact = PIM::Services.__convert(contact, to: PIM::Services::ContactService::Contact) return active_module.managing_user_roles_as_json(user, contact) if not all_modules.empty? end
# File pim.rb, line 190 def self.mapping_functions_as_json return active_module.mapping_functions_as_json if not all_modules.empty? end
# File pim.rb, line 175 def self.media_asset_naming_patterns_as_json return as_json(active_module.media_asset_naming_patterns) end
# File pim.rb, line 329 def self.merge_item_reviews new_item_review, old_item_review new_item_review = PIM::Services.__convert(new_item_review, to: PIM::Services::ReviewService::ItemReview, force: true) old_item_review = PIM::Services.__convert(old_item_review, to: PIM::Services::ReviewService::ItemReview, force: true) result = active_module.merge_item_reviews(new_item_review, old_item_review) return result if result.nil? || result == true || result == false return PIM.javaify(PIM::Utils.as_json(result)) end
# File pim.rb, line 255 def self.migrate_as_json args return nil if all_modules.empty? migrated_values = active_module.migrate!(args) return as_json(migrated_values) end
# File pim.rb, line 125 def self.option_lists_as_json return active_module.option_lists_as_json if not all_modules.empty? end
# File pim.rb, line 96 def self.organization_attributes_as_json return active_module.organization_attributes if not all_modules.empty? return [] end
# File pim.rb, line 65 def self.print_json object json = return_json(object) print json if json end
# File pim.rb, line 49 def self.reset all_modules.keys.each do |m| PIM::Utils.remove_const_on_parent m end @all_modules = nil end
# File pim.rb, line 56 def self.reset_active_module return if all_modules.empty? active_module_key = active_module.to_s PIM::Utils.remove_const_on_parent(active_module_key) new_all_modules = @all_modules.dup new_all_modules.delete(active_module_key) @all_modules = new_all_modules end
# File pim.rb, line 70 def self.return_json object return object.is_a?(String)? object : as_json(object).to_json if object end
# File pim.rb, line 111 def self.review_attributes_as_json return active_module.review_attributes if not all_modules.empty? return [] end
# File pim.rb, line 86 def self.roles_as_json return active_module.roles_as_json if not all_modules.empty? return PIM.all_roles_as_json end
# File pim.rb, line 545 def self.set_javaify_method_call_result result, method_call_result, key self.set_method_call_result(result, method_call_result, key) { |v| PIM.javaify(v) } end
# File pim.rb, line 539 def self.set_method_call_result result, method_call_result, key, &convert_block value = PIM.get_value(method_call_result, key) value = convert_block.call(value) unless value.nil? result[key.to_s] = value unless PIM.is_empty?(value) end
Suspend watchdog Thread#raise on every frame of the current thread for block. Wall-clock still advances (service calls count toward the deadline). After the block, {ExecutionGuard::Frame#resume} raises {ExecutionTimeoutError} if the top frame’s deadline elapsed — safe once Yakut Fiber.yield has completed. No-op (just yields) when no guard is active.
Note: Thread.handle_interrupt is not used. On JRuby its mask is local to a Fiber, so it would not cover the wait of the thread outside of the Fiber while a Yakut callback has yielded. The suspend count belongs to the frame, and the watchdog checks it and raises under the same mutex hold, so it covers the whole call.
# File pim.rb, line 1325 def self.suspend_execution_guard frames = ExecutionGuard.stack.dup return yield if frames.empty? # The suspensions of every frame are restored to what they were, whatever got done when a raise lands # while the frames are being suspended: an enclosing call keeps its own suspension, and no frame stays # suspended and is never enforced again. counts = frames.map { |frame| frame.suspend_count } begin frames.each { |frame| frame.suspend } yield ensure # Resume every frame even if a timeout is raised mid-loop. Bottom-up, so the top frame, which # also delivers the limits of the frames below it, resumes last. resume_error = nil frames.each_with_index do |frame, index| while frame.suspend_count > counts[index] begin frame.resume rescue => e resume_error ||= e end end end raise resume_error if resume_error end end
# File pim.rb, line 74 def self.to_json object return nil if object.nil? return object if object.is_a?(String) return object.to_json if object.respond_to?(:to_json) return object.to_s end
# File pim.rb, line 101 def self.user_attributes_as_json return active_module.user_attributes if not all_modules.empty? return [] end
# File pim.rb, line 238 def self.user_data_model_as_json user return active_module.user_data_model_as_json(user) if not all_modules.empty? end
# File pim.rb, line 617 def self.validate_as_json old_item, new_item, attributes = nil return nil if all_modules.empty? old_item = PIM::Utils.symbolized_hash(old_item) new_item = PIM::Utils.symbolized_hash(new_item) attributes = PIM::Utils.symbolized_array(attributes) validation_result = active_module.validate old_item, new_item, *attributes validation_result.as_json end
# File pim.rb, line 629 def self.validate_item_as_json item, opts = {} return nil if all_modules.empty? item = PIM::Utils.symbolized_hash(item) opts = PIM::Utils.symbolized_hash(opts) old_item = PIM::Utils.symbolized_hash(opts[:old_item]) revalidate_attributes = PIM::Utils.symbolized_array(opts[:revalidate_attributes]) calculate_attribute_states_only = PIM.get_value(opts, :calculate_attribute_states_only) validation_rule_default_execution_deadline = PIM.get_value(opts, :validation_rule_default_execution_deadline) validation_rule_max_execution_deadline = PIM.get_value(opts, :validation_rule_max_execution_deadline) validation_result = active_module.validate_item item, old_item: old_item, revalidate_attributes: revalidate_attributes, calculate_attribute_states_only: calculate_attribute_states_only, validation_rule_default_execution_deadline: validation_rule_default_execution_deadline, validation_rule_max_execution_deadline: validation_rule_max_execution_deadline validation_result.as_json end
# File pim.rb, line 655 def self.validate_items_as_json items, opts = {} return nil if all_modules.empty? return as_json(active_module.validate_items(*items, **opts)) end
Protected Class Methods
# File pim.rb, line 1440 def self.execute_in_module execute_module, &block old_active_module = @current_active_module begin execute_module = get_module(execute_module) return nil if !execute_module @current_active_module = execute_module return execute_module.module_exec(&block) ensure @current_active_module = old_active_module end end