rhoconnect-adapters 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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
+