rhoconnect-adapters 1.0.0.beta1

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.
Files changed (106) hide show
  1. data/.gitignore +4 -0
  2. data/CHANGELOG +4 -0
  3. data/Gemfile +18 -0
  4. data/README.md +239 -0
  5. data/Rakefile +31 -0
  6. data/bin/rhoconnect-adapters +35 -0
  7. data/generators/crm/templates/application/application.rb +34 -0
  8. data/generators/crm/templates/source/source_adapter.rb +10 -0
  9. data/generators/crm/templates/source/source_spec.rb +25 -0
  10. data/generators/crm/templates/spec/spec_helper.rb +64 -0
  11. data/generators/crm/vendor/ms_dynamics/adapter.rb +301 -0
  12. data/generators/crm/vendor/ms_dynamics/application.rb +56 -0
  13. data/generators/crm/vendor/ms_dynamics/lib/crm_metadata_service.rb +43 -0
  14. data/generators/crm/vendor/ms_dynamics/lib/crm_service.rb +141 -0
  15. data/generators/crm/vendor/ms_dynamics/lib/discovery_service.rb +51 -0
  16. data/generators/crm/vendor/ms_dynamics/lib/wlid_service.rb +159 -0
  17. data/generators/crm/vendor/ms_dynamics/ms_dynamics.rb +45 -0
  18. data/generators/crm/vendor/ms_dynamics/settings/Account.yml +46 -0
  19. data/generators/crm/vendor/ms_dynamics/settings/Contact.yml +40 -0
  20. data/generators/crm/vendor/ms_dynamics/settings/GenericObject.yml +18 -0
  21. data/generators/crm/vendor/ms_dynamics/settings/Lead.yml +53 -0
  22. data/generators/crm/vendor/ms_dynamics/settings/Opportunity.yml +41 -0
  23. data/generators/crm/vendor/ms_dynamics/settings/settings.yml +9 -0
  24. data/generators/crm/vendor/ms_dynamics/spec/application_spec.rb +23 -0
  25. data/generators/crm/vendor/ms_dynamics/spec/sources/account_spec.rb +49 -0
  26. data/generators/crm/vendor/ms_dynamics/spec/sources/contact_spec.rb +49 -0
  27. data/generators/crm/vendor/ms_dynamics/spec/sources/lead_spec.rb +49 -0
  28. data/generators/crm/vendor/ms_dynamics/spec/sources/opportunity_spec.rb +62 -0
  29. data/generators/crm/vendor/ms_dynamics/spec/spec_helper.rb +78 -0
  30. data/generators/crm/vendor/ms_dynamics/spec_data/Account.yml +6 -0
  31. data/generators/crm/vendor/ms_dynamics/spec_data/Contact.yml +7 -0
  32. data/generators/crm/vendor/ms_dynamics/spec_data/GenericObject.yml +3 -0
  33. data/generators/crm/vendor/ms_dynamics/spec_data/Lead.yml +12 -0
  34. data/generators/crm/vendor/ms_dynamics/spec_data/Opportunity.yml +6 -0
  35. data/generators/crm/vendor/ms_dynamics/templates.rb +57 -0
  36. data/generators/crm/vendor/oracle_on_demand/adapter.rb +421 -0
  37. data/generators/crm/vendor/oracle_on_demand/application.rb +64 -0
  38. data/generators/crm/vendor/oracle_on_demand/settings/Account.yml +91 -0
  39. data/generators/crm/vendor/oracle_on_demand/settings/Contact.yml +54 -0
  40. data/generators/crm/vendor/oracle_on_demand/settings/GenericObject.yml +21 -0
  41. data/generators/crm/vendor/oracle_on_demand/settings/Lead.yml +72 -0
  42. data/generators/crm/vendor/oracle_on_demand/settings/Opportunity.yml +69 -0
  43. data/generators/crm/vendor/oracle_on_demand/settings/settings.yml +8 -0
  44. data/generators/crm/vendor/oracle_on_demand/spec/application_spec.rb +14 -0
  45. data/generators/crm/vendor/oracle_on_demand/spec/sources/account_spec.rb +50 -0
  46. data/generators/crm/vendor/oracle_on_demand/spec/sources/contact_spec.rb +50 -0
  47. data/generators/crm/vendor/oracle_on_demand/spec/sources/lead_spec.rb +51 -0
  48. data/generators/crm/vendor/oracle_on_demand/spec/sources/opportunity_spec.rb +51 -0
  49. data/generators/crm/vendor/oracle_on_demand/spec_data/Account.yml +8 -0
  50. data/generators/crm/vendor/oracle_on_demand/spec_data/Contact.yml +8 -0
  51. data/generators/crm/vendor/oracle_on_demand/spec_data/GenericObject.yml +4 -0
  52. data/generators/crm/vendor/oracle_on_demand/spec_data/Lead.yml +14 -0
  53. data/generators/crm/vendor/oracle_on_demand/spec_data/Opportunity.yml +6 -0
  54. data/generators/crm/vendor/oracle_on_demand/templates.rb +52 -0
  55. data/generators/crm/vendor/salesforce/adapter.rb +315 -0
  56. data/generators/crm/vendor/salesforce/application.rb +80 -0
  57. data/generators/crm/vendor/salesforce/settings/Account.yml +53 -0
  58. data/generators/crm/vendor/salesforce/settings/Contact.yml +61 -0
  59. data/generators/crm/vendor/salesforce/settings/GenericObject.yml +13 -0
  60. data/generators/crm/vendor/salesforce/settings/Lead.yml +73 -0
  61. data/generators/crm/vendor/salesforce/settings/Opportunity.yml +48 -0
  62. data/generators/crm/vendor/salesforce/settings/settings.yml +6 -0
  63. data/generators/crm/vendor/salesforce/spec/application_spec.rb +14 -0
  64. data/generators/crm/vendor/salesforce/spec/sources/account_spec.rb +50 -0
  65. data/generators/crm/vendor/salesforce/spec/sources/contact_spec.rb +50 -0
  66. data/generators/crm/vendor/salesforce/spec/sources/lead_spec.rb +51 -0
  67. data/generators/crm/vendor/salesforce/spec/sources/opportunity_spec.rb +51 -0
  68. data/generators/crm/vendor/salesforce/spec_data/Account.yml +14 -0
  69. data/generators/crm/vendor/salesforce/spec_data/Contact.yml +8 -0
  70. data/generators/crm/vendor/salesforce/spec_data/GenericObject.yml +3 -0
  71. data/generators/crm/vendor/salesforce/spec_data/Lead.yml +10 -0
  72. data/generators/crm/vendor/salesforce/spec_data/Opportunity.yml +10 -0
  73. data/generators/crm/vendor/salesforce/templates.rb +45 -0
  74. data/generators/crm/vendor/sugar/adapter.rb +291 -0
  75. data/generators/crm/vendor/sugar/application.rb +50 -0
  76. data/generators/crm/vendor/sugar/settings/Account.yml +49 -0
  77. data/generators/crm/vendor/sugar/settings/Contact.yml +62 -0
  78. data/generators/crm/vendor/sugar/settings/GenericObject.yml +12 -0
  79. data/generators/crm/vendor/sugar/settings/Lead.yml +76 -0
  80. data/generators/crm/vendor/sugar/settings/Opportunity.yml +49 -0
  81. data/generators/crm/vendor/sugar/settings/settings.yml +9 -0
  82. data/generators/crm/vendor/sugar/spec/application_spec.rb +25 -0
  83. data/generators/crm/vendor/sugar/spec/sources/account_spec.rb +53 -0
  84. data/generators/crm/vendor/sugar/spec/sources/contact_spec.rb +53 -0
  85. data/generators/crm/vendor/sugar/spec/sources/lead_spec.rb +54 -0
  86. data/generators/crm/vendor/sugar/spec/sources/opportunity_spec.rb +54 -0
  87. data/generators/crm/vendor/sugar/spec_data/Account.yml +13 -0
  88. data/generators/crm/vendor/sugar/spec_data/Contact.yml +8 -0
  89. data/generators/crm/vendor/sugar/spec_data/GenericObject.yml +3 -0
  90. data/generators/crm/vendor/sugar/spec_data/Lead.yml +16 -0
  91. data/generators/crm/vendor/sugar/spec_data/Opportunity.yml +10 -0
  92. data/generators/crm/vendor/sugar/sugar.rb +33 -0
  93. data/generators/crm/vendor/sugar/templates.rb +58 -0
  94. data/generators/rhoconnect-adapters.rb +217 -0
  95. data/lib/rhoconnect-adapters/crm/crm.rb +31 -0
  96. data/lib/rhoconnect-adapters/soap_service.rb +70 -0
  97. data/lib/rhoconnect-adapters/version.rb +3 -0
  98. data/lib/rhoconnect-adapters.rb +2 -0
  99. data/rhoconnect-adapters.gemspec +36 -0
  100. data/spec/apps/ms_dynamics_spec.rb +19 -0
  101. data/spec/apps/oracle_on_demand_spec.rb +20 -0
  102. data/spec/apps/salesforce_spec.rb +18 -0
  103. data/spec/apps/sugar_spec.rb +18 -0
  104. data/spec/generator/generator_spec.rb +113 -0
  105. data/spec/spec_helper.rb +57 -0
  106. metadata +288 -0
@@ -0,0 +1,78 @@
1
+ require 'rubygems'
2
+
3
+ # Set environment to test
4
+ ENV['RHO_ENV'] = 'test'
5
+ ROOT_PATH = File.expand_path(File.join(File.dirname(__FILE__),'..'))
6
+
7
+ require 'bundler'
8
+ Bundler.require(:default, ENV['RHO_ENV'].to_sym)
9
+
10
+ # Try to load vendor-ed rhoconnect, otherwise load the gem
11
+ begin
12
+ require 'vendor/rhoconnect/lib/rhoconnect'
13
+ rescue LoadError
14
+ require 'rhoconnect'
15
+ end
16
+
17
+ $:.unshift File.join(File.dirname(__FILE__), "..") # FIXME:
18
+ # Load our rhoconnect application
19
+ require 'application'
20
+ include Rhoconnect
21
+
22
+ require 'rhoconnect/test_methods'
23
+
24
+ # Monkey patch to fix the following issue:
25
+ # /Library/Ruby/Gems/1.8/gems/rspec-core-2.5.1/lib/rspec/core/shared_example_group.rb:45:
26
+ # in `ensure_shared_example_group_name_not_taken': Shared example group '...' already exists (ArgumentError)
27
+ module RSpec
28
+ module Core
29
+ module SharedExampleGroup
30
+ private
31
+ def ensure_shared_example_group_name_not_taken(name)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ module TestHelpers
38
+ class << self
39
+ @created_records = {}
40
+ attr_accessor :created_records
41
+
42
+ @already_authenticated = false
43
+ attr_accessor :already_authenticated
44
+ end
45
+ end
46
+
47
+ shared_examples_for "SpecHelper" do
48
+ include Rhoconnect::TestMethods
49
+
50
+ def load_credentials(backend)
51
+ file = YAML.load_file(File.join(ROOT_PATH,'..','rhoconnect-adapters-test',"#{Rhoconnect.under_score(backend)}.yml"))
52
+ return file.nil? ? {} : file
53
+ end
54
+
55
+ before(:all) do
56
+ credentials = load_credentials(Application.backend)
57
+ @test_user = "#{credentials[:test_user]}"
58
+ @test_password = "#{credentials[:test_password]}"
59
+ puts "Specify test user before running these specs" unless @test_user.length > 0
60
+ puts "Specify test user password before running these specs" unless @test_password.length > 0
61
+ unless TestHelpers.already_authenticated
62
+ Store.db.flushdb
63
+ if @test_user.length > 0 and @test_password.length > 0
64
+ puts "Performing authentication with #{Application.backend} CRM instance for the user [#{@test_user}]"
65
+ TestHelpers.already_authenticated = Application.authenticate(@test_user,@test_password)
66
+ end
67
+ end
68
+ end
69
+
70
+ before(:each) do
71
+ # preserving auth info
72
+ auth_info = RhoconnectAdapters::CRM::MsDynamics.load_auth_info(@test_user)
73
+ Store.db.flushdb
74
+ Application.initializer(ROOT_PATH)
75
+ # restoring auth info in the DB
76
+ RhoconnectAdapters::CRM::MsDynamics.save_auth_info(@test_user,auth_info) unless auth_info.nil?
77
+ end
78
+ end
@@ -0,0 +1,6 @@
1
+ Account:
2
+ name: ACME Co.
3
+ numberofemployees: 30
4
+ telephone1: (333)-333-3333
5
+ websiteurl: www.acme.com
6
+ accountcategorycode: Standard
@@ -0,0 +1,7 @@
1
+ Contact:
2
+ gendercode: Male
3
+ firstname: John
4
+ lastname: Smith
5
+ emailaddress1: myemail@domain.com
6
+ jobtitle: Sales Assistant
7
+ telephone1: (333)-333-3333
@@ -0,0 +1,3 @@
1
+ <%=class_name%>:
2
+ # put all of your sample data for specs here in the form of hash
3
+ # { field_name => sample_field_value }
@@ -0,0 +1,12 @@
1
+ Lead:
2
+ firstname: John
3
+ lastname: Smith
4
+ mobilephone: (555)111-1111
5
+ emailaddress1: john.smith@example.com
6
+ companyname: ABC Company
7
+ jobtitle: Sales Assistant
8
+ estimatedvalue: 40000
9
+ estimatedclosedate: 5/15/2011
10
+ address1_country: USA
11
+ address1_city: San Francisco
12
+ address1_line1: 111 Market St.
@@ -0,0 +1,6 @@
1
+ Opportunity:
2
+ name: 600 Hard Drives
3
+ estimatedvalue: 5000
4
+ closeprobability: 75
5
+ description: close-out sale
6
+
@@ -0,0 +1,57 @@
1
+ # these are MsDynamics-specific Templater::Generator templates
2
+ module RhoconnectAdapters
3
+ module CRM
4
+ module MsDynamics
5
+ class << self
6
+ def configure_gemfile
7
+ # put all specific dependencies here
8
+ # in the form of hash {'gem' => 'version'}
9
+ {}
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ RhoconnectAdapters::CRMAppGenerator.add_vendor_templates :directory, :msdynamics_lib_files do |dir,name,crm|
17
+ dir.source = File.join('..','..','vendor','ms_dynamics','lib')
18
+ dir.destination = File.join("#{name}", 'vendor','ms_dynamics','lib')
19
+ end
20
+
21
+ RhoconnectAdapters::CRMAppGenerator.add_vendor_templates :file, :ms_dynamics_main_require do |file,name,crm|
22
+ file.source = File.join('..','..','vendor','ms_dynamics','ms_dynamics.rb')
23
+ file.destination = File.join("#{name}", 'vendor','ms_dynamics','ms_dynamics.rb')
24
+ end
25
+
26
+ RhoconnectAdapters::CRMAppGenerator.add_vendor_templates :file, :settings_yml do |file,name,crm|
27
+ file.source = File.join('..','..','vendor','ms_dynamics','settings','settings.yml')
28
+ file.destination = File.join("#{name}", 'vendor','ms_dynamics','settings','settings.yml')
29
+ end
30
+
31
+ RhoconnectAdapters::CRMAppGenerator.add_vendor_templates :file, :application_spec do |file,name,crm|
32
+ file.source = File.join('..','..','vendor','ms_dynamics','spec','application_spec.rb')
33
+ file.destination = File.join("#{name}", 'spec','application_spec.rb')
34
+ end
35
+
36
+ RhoconnectAdapters::CRMSourceGenerator.add_vendor_templates :file, :object_yml do |file,name,crm|
37
+ source_name = name.gsub('-', '_').camel_case
38
+ source_filename = File.join('..','..','vendor','ms_dynamics','settings',"#{source_name}.yml")
39
+ if File.exists? File.join(CRMSourceGenerator.source_root, source_filename)
40
+ file.source = source_filename
41
+ else
42
+ file.source = File.join('..','..','vendor','ms_dynamics','settings',"GenericObject.yml")
43
+ end
44
+ file.destination = File.join('vendor','ms_dynamics','settings', "#{source_name}.yml")
45
+ end
46
+
47
+ RhoconnectAdapters::CRMSourceGenerator.add_vendor_templates :template, :spec_data do |template,name,crm|
48
+ source_name = name.gsub('-', '_').camel_case
49
+ source_filename = File.join('..','..','vendor','ms_dynamics','spec_data',"#{source_name}.yml")
50
+ if File.exists? File.join(CRMSourceGenerator.source_root, source_filename)
51
+ template.source = source_filename
52
+ else
53
+ template.source = File.join('..','..','vendor','ms_dynamics','spec_data',"GenericObject.yml")
54
+ end
55
+ template.destination = File.join('vendor','ms_dynamics','spec_data', "#{source_name}.yml")
56
+ end
57
+
@@ -0,0 +1,421 @@
1
+ require 'rhoconnect-adapters'
2
+ require 'rhoconnect-adapters/soap_service'
3
+ require 'active_support/inflector'
4
+
5
+ module RhoconnectAdapters
6
+ module CRM
7
+ module OracleOnDemand
8
+ RhoconnectAdapters::SoapService.node_namespaces.merge!({'s' => 'http://schemas.xmlsoap.org/soap/envelope/',
9
+ 'plns' => 'urn:crmondemand/ws/picklist/',
10
+ 'pldoc' => 'urn:/crmondemand/xml/picklist'});
11
+ RhoconnectAdapters::SoapService.envelope_namespaces += <<-DESC
12
+ xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"
13
+ DESC
14
+
15
+ class Adapter < SourceAdapter
16
+ @picklist_namespaces = RhoconnectAdapters::SoapService.envelope_namespaces + "\nxmlns:wsdl=\"urn:crmondemand/ws/picklist/\""
17
+ attr_accessor :crm_object
18
+ attr_accessor :crm_object_namespaces
19
+ attr_accessor :fields
20
+
21
+ class << self
22
+ attr_accessor :picklist_namespaces
23
+
24
+ def get_columns(fields)
25
+ columns = ""
26
+ fields.each do |key,val|
27
+ columns += "<wsdl:#{key}></wsdl:#{key}>"
28
+ end
29
+ columns
30
+ end
31
+
32
+ def get_columns_values(fields)
33
+ columns = ""
34
+ fields.each do |key,val|
35
+ if not val
36
+ next
37
+ end
38
+ columns += "<wsdl:#{key}>#{val}</wsdl:#{key}>"
39
+ end
40
+ columns
41
+ end
42
+ end
43
+
44
+ def initialize(source)
45
+ super(source)
46
+ @fields = {}
47
+ @crm_object = self.class.name
48
+ @title_fields = ['Id']
49
+ end
50
+
51
+ def configure_fields
52
+ # this is going to be used in XPath searches
53
+ RhoconnectAdapters::SoapService.node_namespaces.merge!({"#{crm_object}doc" => "urn:/crmondemand/xml/#{crm_object}/Data"});
54
+
55
+ # this is going to be passed in SOAP requests
56
+ @crm_object_namespaces = RhoconnectAdapters::SoapService.envelope_namespaces
57
+ @crm_object_namespaces += "\nxmlns:wsdl=\"urn:crmondemand/ws/ecbs/#{crm_object.downcase}/\""
58
+
59
+ # initialize fields map
60
+ @fields = get_object_settings['Query_Fields']
61
+
62
+ @field_picklists = {}
63
+ static_picklists = get_object_settings['StaticPicklist']
64
+ if static_picklists != nil
65
+ static_picklists.each do |element_name, values|
66
+ @field_picklists[element_name] = values
67
+ end
68
+ end
69
+
70
+ @object_fields = get_object_settings['ObjectFields']
71
+ @object_fields = {} if @object_fields == nil
72
+
73
+ # title fields are used in metadata to show
74
+ # records in the list
75
+ @title_fields = get_object_settings['TitleFields']
76
+
77
+ @fields
78
+ end
79
+
80
+ def get_object_settings
81
+ return @object_settings if @object_settings
82
+ begin
83
+ @object_settings = RhoconnectAdapters::CRM::Field.load_file(File.join(ROOT_PATH,'vendor','oracle_on_demand','settings',"#{crm_object}.yml"))
84
+ rescue Exception => e
85
+ puts "Error opening CRMObjects settings file: #{e}"
86
+ puts e.backtrace.join("\n")
87
+ raise e
88
+ end
89
+ end
90
+
91
+ def get_picklists
92
+ begin
93
+ nonquery_fields = get_object_settings['NonQuery_MappingWS_Fields']
94
+ fields.each do |element_name, element_def|
95
+ # use object field only of it has not been excluded
96
+ # explicitly in the object's settings
97
+ next if nonquery_fields.has_key? element_name
98
+
99
+ data_type = element_def['Type']
100
+ # for picklists - get values
101
+ # but only for those that are not
102
+ # already defined statically
103
+ if data_type == 'Picklist' and not @field_picklists.has_key?(element_name)
104
+ @field_picklists[element_name] = get_picklist(element_name)
105
+ end
106
+ end
107
+ rescue RestClient::Exception => e
108
+ raise e
109
+ end
110
+ end
111
+
112
+ def get_picklist(element_name)
113
+ # check if we already have it in Store
114
+ picklist = Store.get_data("#{crm_object}:#{element_name}_picklist",Array)
115
+ return picklist if picklist.size != 0
116
+
117
+ password = Store.get_value("#{current_user.login}:password")
118
+ wsse = RhoconnectAdapters::SoapService.compose_wsse_header(current_user.login, password)
119
+ body = "<wsdl:PicklistWS_GetPicklistValues_Input>
120
+ <wsdl:RecordType>#{crm_object}</wsdl:RecordType>
121
+ <wsdl:FieldName>#{element_name}</wsdl:FieldName>
122
+ </wsdl:PicklistWS_GetPicklistValues_Input>"
123
+ req = RhoconnectAdapters::SoapService.compose_message(wsse, body, Adapter.picklist_namespaces)
124
+
125
+ field_values = []
126
+ response = nil
127
+ begin
128
+ response = RhoconnectAdapters::SoapService.send_request_raw("#{@endpoint_url}/GetPicklistValues",
129
+ req,
130
+ "\"document/urn:crmondemand/ws/picklist/:GetPicklistValues\"",
131
+ @session_cookie);
132
+
133
+ oracle_rec = RhoconnectAdapters::SoapService.select_node(Nokogiri::XML(response), '//pldoc:PicklistValue')
134
+ oracle_rec.each do |pval|
135
+ disabled = RhoconnectAdapters::SoapService.select_node_text(pval, 'pldoc:Disabled')
136
+ field_values << RhoconnectAdapters::SoapService.select_node_text(pval, 'pldoc:DisplayValue') if not disabled == 'Y'
137
+ end
138
+
139
+ rescue RestClient::Exception => e
140
+ raise e
141
+ end
142
+ # server stateless session id is returned with the response
143
+ @session_cookie = response.cookies
144
+ Store.put_data("#{crm_object}:#{element_name}_picklist", field_values)
145
+ field_values
146
+ end
147
+
148
+ def login
149
+ @endpoint_url = Store.get_value("#{current_user.login}:service_url")
150
+
151
+ # get types information from the GetPicklistValues WS
152
+ get_picklists
153
+ end
154
+
155
+ def execute_soap_action(action, soap_body)
156
+ action_prefix = "#{crm_object}" + action
157
+ soapaction = "\"document/urn:crmondemand/ws/ecbs/#{crm_object.downcase}/:"
158
+ soapaction += action_prefix + '"'
159
+
160
+ password = Store.get_value("#{current_user.login}:password")
161
+ wsse = RhoconnectAdapters::SoapService.compose_wsse_header(current_user.login, password)
162
+ body = "<wsdl:#{crm_object}#{action}_Input>
163
+ #{soap_body}
164
+ </wsdl:#{crm_object}#{action}_Input>"
165
+ req = RhoconnectAdapters::SoapService.compose_message(wsse, body, crm_object_namespaces)
166
+
167
+ response = nil
168
+ begin
169
+ response = RhoconnectAdapters::SoapService.send_request_raw("#{@endpoint_url}/#{crm_object}",
170
+ req,
171
+ soapaction,
172
+ @session_cookie);
173
+ rescue RestClient::Exception => e
174
+ raise e
175
+ end
176
+ # server stateless session id is returned with the response
177
+ @session_cookie = response.cookies
178
+
179
+ RhoconnectAdapters::SoapService.select_node(Nokogiri::XML(response), "//#{crm_object}doc:ListOf#{crm_object}")[0]
180
+ end
181
+
182
+ def query(params=nil)
183
+ # TODO: Query your backend data source and assign the records
184
+ # to a nested hash structure called @result. For example:
185
+ # @result = {
186
+ # "1"=>{"name"=>"Acme", "industry"=>"Electronics"},
187
+ # "2"=>{"name"=>"Best", "industry"=>"Software"}
188
+ # }
189
+ @result = {}
190
+ fetch_more = 'true'
191
+ start_row = 0
192
+ begin
193
+
194
+ soap_body = "<wsdl:ListOf#{crm_object} recordcountneeded=\"true\" pagesize=\"100\" startrownum=\"#{start_row.to_s}\">
195
+ <wsdl:#{crm_object} searchspec=\"\">
196
+ #{Adapter.get_columns(fields)}
197
+ </wsdl:#{crm_object}>
198
+ </wsdl:ListOf#{crm_object}>"
199
+
200
+ query_results = execute_soap_action('QueryPage', soap_body)
201
+ fetch_more = query_results['lastpage'] == 'true' ? false : true;
202
+
203
+ query_results.children.each do |record|
204
+ if record.name == "#{crm_object}"
205
+ id_field = RhoconnectAdapters::SoapService.select_node_text(record, "#{crm_object}doc:Id")
206
+ converted_record = {}
207
+ # grab only the allowed fields
208
+ fields.each do |element_name,element_def|
209
+ converted_record[element_name] = RhoconnectAdapters::SoapService.select_node_text(record, "#{crm_object}doc:#{element_name}")
210
+ end
211
+ @result[id_field] = converted_record
212
+ end
213
+ end
214
+ start_row = @result.size
215
+ end while fetch_more
216
+ @result
217
+ end
218
+
219
+ def sync
220
+ # Manipulate @result before it is saved, or save it
221
+ # yourself using the Rhoconnect::Store interface.
222
+ # By default, super is called below which simply saves @result
223
+ super
224
+ end
225
+
226
+ def metadata
227
+ # define the metadata
228
+ show_fields = []
229
+ new_fields = []
230
+ edit_fields = []
231
+ model_name = "" + crm_object
232
+ model_name[0] = model_name[0,1].downcase
233
+ record_sym = '@' + "#{model_name}"
234
+
235
+ fields.each do |element_name,element_def|
236
+ next if element_name == 'Id'
237
+
238
+ # 1) - read-only show fields
239
+ field_type = 'labeledvalueli'
240
+ field = {
241
+ :name => "#{model_name}\[#{element_name}\]",
242
+ :label => element_def['Label'],
243
+ :type => field_type,
244
+ :value => "{{#{record_sym}/#{element_name}}}"
245
+ }
246
+ show_fields << field
247
+
248
+ new_field = field.clone
249
+ new_field[:type] = 'labeledinputli'
250
+ new_field.delete(:value)
251
+ case element_def['Type']
252
+ when 'Picklist'
253
+ new_field[:type] = 'select'
254
+ values = []
255
+ # make first element a blanc value
256
+ values[0] = nil
257
+ values.concat @field_picklists[element_name]
258
+ new_field[:values] = values
259
+ new_field[:value] = values[0]
260
+ when 'object'
261
+ end
262
+
263
+ new_fields << new_field if not element_def['Type'] == 'object'
264
+
265
+ edit_field = new_field.clone
266
+ edit_field[:value] = "{{#{record_sym}/#{element_name}}}"
267
+ edit_fields << edit_field
268
+ end
269
+
270
+ # Show
271
+ show_list = { :name => 'list', :type => 'list', :children => show_fields }
272
+ show_form = {
273
+ :name => "#{crm_object}_show",
274
+ :type => 'show_form',
275
+ :title => "#{crm_object} details",
276
+ :object => "#{crm_object}",
277
+ :model => "#{model_name}",
278
+ :id => "{{#{record_sym}/object}}",
279
+ :children => [show_list]
280
+ }
281
+
282
+ # New
283
+ new_list = show_list.clone
284
+ new_list[:children] = new_fields
285
+ new_form = {
286
+ :type => 'new_form',
287
+ :title => "New #{crm_object}",
288
+ :object => "#{crm_object}",
289
+ :model => "#{model_name}",
290
+ :children => [new_list]
291
+ }
292
+
293
+ # Edit
294
+ edit_list = show_list.clone
295
+ edit_list[:children] = edit_fields
296
+ edit_form = {
297
+ :type => 'update_form',
298
+ :title => "Edit #{crm_object}",
299
+ :object => "#{crm_object}",
300
+ :model => "#{model_name}",
301
+ :id => "{{#{record_sym}/object}}",
302
+ :children => [edit_list]
303
+ }
304
+
305
+ # Index
306
+ title_field_metadata = @title_fields.collect { |field_name | "{{#{field_name.to_s}}} " }.join(' ')
307
+ object_rec = {
308
+ :object => "#{crm_object}",
309
+ :id => "{{object}}",
310
+ :type => 'linkobj',
311
+ :text => "#{title_field_metadata}"
312
+ }
313
+
314
+ index_form = {
315
+ :object => "#{crm_object}",
316
+ :title => "#{crm_object.pluralize}",
317
+ :type => 'index_form',
318
+ :children => [object_rec],
319
+ :repeatable => "{{#{record_sym.pluralize}}}"
320
+ }
321
+
322
+ # return JSON
323
+ { 'index' => index_form, 'show' => show_form, 'new' => new_form, 'edit' => edit_form }.to_json
324
+ end
325
+
326
+ def create(create_hash,blob=nil)
327
+ # TODO: Create a new record in your backend data source
328
+ # If your rhodes rhom object contains image/binary data
329
+ # (has the image_uri attribute), then a blob will be provided
330
+ created_object_id = nil
331
+ request_fields = {}
332
+ fields.each do |element_name, element_def|
333
+ field_value = create_hash[element_name]
334
+ if field_value != nil and element_name != 'Id'
335
+ request_fields[element_name] = field_value
336
+ end
337
+ end
338
+
339
+ soap_body = "<wsdl:ListOf#{crm_object}>
340
+ <wsdl:#{crm_object}>
341
+ #{Adapter.get_columns_values(request_fields)}
342
+ </wsdl:#{crm_object}>
343
+ </wsdl:ListOf#{crm_object}>"
344
+
345
+ begin
346
+ oracle_rec = execute_soap_action('Insert', soap_body)
347
+ created_object_id = RhoconnectAdapters::SoapService.select_node_text(oracle_rec, "//#{crm_object}doc:Id").to_s
348
+ rescue RestClient::Exception => e
349
+ raise e
350
+ end
351
+
352
+ # return new object ids
353
+ created_object_id
354
+ end
355
+
356
+ def update(update_hash)
357
+ updated_object_id = nil
358
+ request_fields = {}
359
+ fields.each do |element_name,element_def|
360
+ field_value = update_hash[element_name]
361
+ if field_value != nil
362
+ request_fields[element_name] = field_value
363
+ end
364
+ end
365
+ # check if 'Id' is present
366
+ # it may be available as an 'id'
367
+ if request_fields['Id'] == nil
368
+ request_fields['Id'] = update_hash['id']
369
+ end
370
+
371
+ if request_fields['Id'] == nil
372
+ raise SourceAdapterObjectConflictError.new("'Id' field must be specified for the Update request")
373
+ end
374
+
375
+ soap_body = "<wsdl:ListOf#{crm_object}>
376
+ <wsdl:#{crm_object}>
377
+ #{Adapter.get_columns_values(request_fields)}
378
+ </wsdl:#{crm_object}>
379
+ </wsdl:ListOf#{crm_object}>"
380
+
381
+ begin
382
+ oracle_rec = execute_soap_action('Update', soap_body)
383
+ updated_object_id = RhoconnectAdapters::SoapService.select_node_text(oracle_rec, "#{crm_object}doc:Id")
384
+ rescue RestClient::Exception => e
385
+ raise e
386
+ end
387
+ updated_object_id
388
+ end
389
+
390
+ def delete(delete_hash)
391
+ deleted_object_id = delete_hash['Id'] || delete_hash['id']
392
+
393
+ if deleted_object_id == nil
394
+ raise SourceAdapterObjectConflictError.new("'Id' field must be specified for the Delete request")
395
+ end
396
+
397
+ request_fields = {}
398
+ request_fields['Id'] = deleted_object_id
399
+
400
+ soap_body = "<wsdl:ListOf#{crm_object}>
401
+ <wsdl:#{crm_object}>
402
+ #{Adapter.get_columns_values(request_fields)}
403
+ </wsdl:#{crm_object}>
404
+ </wsdl:ListOf#{crm_object}>"
405
+
406
+ begin
407
+ execute_soap_action('Delete', soap_body)
408
+ rescue RestClient::Exception => e
409
+ raise e
410
+ end
411
+
412
+ deleted_object_id
413
+ end
414
+
415
+ def logoff
416
+ # logoff if necessary
417
+ end
418
+ end
419
+ end
420
+ end
421
+ end
@@ -0,0 +1,64 @@
1
+ require 'rhoconnect-adapters'
2
+ require 'rest-client'
3
+
4
+ module RhoconnectAdapters
5
+ module CRM
6
+ module OracleOnDemand
7
+ class Application < Rhoconnect::Base
8
+ class << self
9
+ def authenticate(username,password,session)
10
+ begin
11
+ oraclecrm_url = Application.get_settings[:oraclecrm_service_url]
12
+ request_url = oraclecrm_url + "?command=" + 'login'
13
+
14
+ # here we just verifying the credetials
15
+ # by logging in and immediately logging out
16
+ in_headers = {
17
+ "UserName" => username,
18
+ "Password" => password
19
+ };
20
+
21
+ RestClient.get(request_url, in_headers) do |response,request,result,&block|
22
+ case response.code
23
+ when 200
24
+ # store password to be used by SourceAdaptors
25
+ Store.put_value("#{username}:password", password)
26
+ Store.put_value("#{username}:service_url", oraclecrm_url)
27
+
28
+ # since we established the session only
29
+ # to verify the credentials - close the session here
30
+ request_url = "#{oraclecrm_url}" + '?command=' + 'logoff'
31
+ in_headers = { "Cookie" => response.headers[:set_cookie] };
32
+ RestClient.get(request_url, in_headers)
33
+ else
34
+ raise "LOGIN/PASSWORD ERROR : #{response.code} : #{response}"
35
+ end
36
+ end
37
+ rescue Exception => e
38
+ warn "Can't authenticate user #{username}: " + e.inspect
39
+ return false
40
+ end
41
+ true
42
+ end
43
+ def get_settings
44
+ return @settings if @settings
45
+ begin
46
+ file = YAML.load_file(File.join(ROOT_PATH,'settings','settings.yml'))
47
+ env = (ENV['RHO_ENV'] || :development).to_sym
48
+ @settings = file[env]
49
+
50
+ # vendor-specific settings
51
+ file = YAML.load_file(File.join(ROOT_PATH,'vendor','oracle_on_demand','settings','settings.yml'))
52
+ @settings.merge!(file[env])
53
+ rescue Exception => e
54
+ puts "Error opening settings file: #{e}"
55
+ puts e.backtrace.join("\n")
56
+ raise e
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+