この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

Salesforce Connect の Google ドライブ™ カスタムアダプタ

この例は、コールアウトと OAuth を使用して外部システム (この場合は Google ドライブ™ オンラインストレージサービス) に接続する方法を示しています。また、この例は、テストメソッドの疑似応答を返すことによって Web サービスコールアウトのテストの失敗を回避する方法も示しています。

この例を確実に機能させるには、OAuth を設定するときにオフラインアクセスを要求して、Salesforce が接続の更新トークンを取得および維持できるようにします。

DriveDataSourceConnection クラス

1/**
2 *   Extends the DataSource.Connection class to enable 
3 *   Salesforce to sync the external system’s schema 
4 *   and to handle queries and searches of the external data. 
5 **/
6global class DriveDataSourceConnection extends
7    DataSource.Connection {
8    private DataSource.ConnectionParams connectionInfo;
9    
10    /**
11     *   Constructor for DriveDataSourceConnection.
12     **/
13    global DriveDataSourceConnection(
14        DataSource.ConnectionParams connectionInfo) {
15        this.connectionInfo = connectionInfo;
16    }
17    
18    /**
19     *   Called when an external object needs to get a list of 
20     *   schema from the external data source, for example when 
21     *   the administrator clicks “Validate and Sync” in the 
22     *   user interface for the external data source.   
23     **/
24    override global List<DataSource.Table> sync() {
25        List<DataSource.Table> tables =
26            new List<DataSource.Table>();
27        List<DataSource.Column> columns;
28        columns = new List<DataSource.Column>();
29        columns.add(DataSource.Column.text('title', 255));
30        columns.add(DataSource.Column.text('description',255));
31        columns.add(DataSource.Column.text('createdDate',255));
32        columns.add(DataSource.Column.text('modifiedDate',255));
33        columns.add(DataSource.Column.url('selfLink'));
34        columns.add(DataSource.Column.url('DisplayUrl'));
35        columns.add(DataSource.Column.text('ExternalId',255));
36        tables.add(DataSource.Table.get('googleDrive','title',
37            columns));
38        return tables;
39    }
40
41    /**
42     *   Called to query and get results from the external 
43     *   system for SOQL queries, list views, and detail pages 
44     *   for an external object that’s associated with the 
45     *   external data source.
46     *   
47     *   The QueryContext argument represents the query to run 
48     *   against a table in the external system.
49     *   
50     *   Returns a list of rows as the query results.
51     **/
52    override global DataSource.TableResult query(
53        DataSource.QueryContext context) {
54        DataSource.Filter filter = context.tableSelection.filter;
55        String url;
56        if (filter != null) {
57            String thisColumnName = filter.columnName;
58            if (thisColumnName != null && 
59                    thisColumnName.equals('ExternalId'))
60                url = 'https://www.googleapis.com/drive/v2/'
61                + 'files/' + filter.columnValue;
62            else
63                url = 'https://www.googleapis.com/drive/v2/'
64                + 'files';
65        } else {
66            url = 'https://www.googleapis.com/drive/v2/' 
67            + 'files';
68        }
69
70        /**
71         * Filters, sorts, and applies limit and offset clauses.
72         **/
73        List<Map<String, Object>> rows = 
74            DataSource.QueryUtils.process(context, getData(url));
75        return DataSource.TableResult.get(true, null,
76            context.tableSelection.tableSelected, rows);
77    }
78
79    /**
80     *   Called to do a full text search and get results from
81     *   the external system for SOSL queries and Salesforce
82     *   global searches.
83     *   
84     *   The SearchContext argument represents the query to run 
85     *   against a table in the external system.
86     *   
87     *   Returns results for each table that the SearchContext 
88     *   requested to be searched.
89     **/
90    override global List<DataSource.TableResult> search(
91        DataSource.SearchContext context) {
92        List<DataSource.TableResult> results =
93            new List<DataSource.TableResult>();
94
95        for (Integer i =0;i< context.tableSelections.size();i++) {
96            String entity = context.tableSelections[i].tableSelected;
97            String url = 
98                'https://www.googleapis.com/drive/v2/files'+
99                '?q=fullText+contains+\''+context.searchPhrase+'\'';
100            results.add(DataSource.TableResult.get(
101                true, null, entity, getData(url)));
102        }
103
104        return results;
105    }
106
107    /**
108     *   Helper method to parse the data.
109     *   The url argument is the URL of the external system.
110     *   Returns a list of rows from the external system.
111     **/
112    public List<Map<String, Object>> getData(String url) {
113        String response = getResponse(url);
114
115        List<Map<String, Object>> rows =
116            new List<Map<String, Object>>();
117
118        Map<String, Object> responseBodyMap = (Map<String, Object>)
119            JSON.deserializeUntyped(response);
120
121        /**
122         *   Checks errors.
123         **/
124        Map<String, Object> error =
125            (Map<String, Object>)responseBodyMap.get('error');
126        if (error!=null) {
127            List<Object> errorsList =
128                (List<Object>)error.get('errors');
129            Map<String, Object> errors =
130                (Map<String, Object>)errorsList[0];
131            String errorMessage = (String)errors.get('message');
132            throw new DataSource.OAuthTokenExpiredException(errorMessage);
133        }
134
135        List<Object> fileItems=(List<Object>)responseBodyMap.get('items');
136        if (fileItems != null) {
137            for (Integer i=0; i < fileItems.size(); i++) {
138                Map<String, Object> item = 
139                    (Map<String, Object>)fileItems[i];
140                rows.add(createRow(item));  
141            }
142        } else {
143            rows.add(createRow(responseBodyMap));
144        }
145
146        return rows;
147    }
148
149    /**
150     *   Helper method to populate the External ID and Display 
151     *   URL fields on external object records based on the 'id' 
152     *   value that’s sent by the external system.
153     *   
154     *   The Map<String, Object> item parameter maps to the data 
155     *   that represents a row.
156     *   
157     *   Returns an updated map with the External ID and 
158     *   Display URL values.
159     **/
160    public Map<String, Object> createRow(
161        Map<String, Object> item){
162        Map<String, Object> row = new Map<String, Object>();
163        for ( String key : item.keySet() ) {
164            if (key == 'id') {
165                row.put('ExternalId', item.get(key));
166            } else if (key=='selfLink') {
167                row.put(key, item.get(key));
168                row.put('DisplayUrl', item.get(key));
169            } else {
170                row.put(key, item.get(key));
171            }
172        }
173        return row;
174    }
175    
176    static String mockResponse = '{' +
177      '  "kind": "drive#file",' +
178      '  "id": "12345",' +
179      '  "selfLink": "files/12345",' +
180      '  "title": "Mock File",' +
181      '  "mimeType": "application/text",' +
182      '  "description": "Mock response that’s used during tests",' +
183      '  "createdDate": "2016-04-20",' +
184      '  "modifiedDate": "2016-04-20",' +
185      '  "version": 1' +
186      '}';
187    
188    /**
189     *   Helper method to make the HTTP GET call.
190     *   The url argument is the URL of the external system.
191     *   Returns the response from the external system.
192     **/
193    public String getResponse(String url) {
194        if (System.Test.isRunningTest()) {
195          // Avoid callouts during tests. Return mock data instead.
196          return mockResponse;
197        } else {
198          // Perform callouts for production (non-test) results.
199          Http httpProtocol = new Http();
200          HttpRequest request = new HttpRequest();
201          request.setEndPoint(url);
202          request.setMethod('GET');
203          request.setHeader('Authorization', 'Bearer '+
204              this.connectionInfo.oauthToken);
205          HttpResponse response = httpProtocol.send(request);
206          return response.getBody();
207        }
208    }
209}

DriveDataSourceProvider クラス

1/**
2 *   Extends the DataSource.Provider base class to create a 
3 *   custom adapter for Salesforce Connect. The class informs 
4 *   Salesforce of the functional and authentication 
5 *   capabilities that are supported by or required to connect 
6 *   to an external system.
7 **/
8global class DriveDataSourceProvider
9    extends DataSource.Provider {
10 
11    /**
12     *   Declares the types of authentication that can be used 
13     *   to access the external system.
14     **/
15    override global List<DataSource.AuthenticationCapability>
16        getAuthenticationCapabilities() {
17        List<DataSource.AuthenticationCapability> capabilities =
18            new List<DataSource.AuthenticationCapability>();
19        capabilities.add(
20            DataSource.AuthenticationCapability.OAUTH);
21        capabilities.add(
22            DataSource.AuthenticationCapability.ANONYMOUS);
23        return capabilities;
24    }
25 
26    /**
27     *   Declares the functional capabilities that the 
28     *   external system supports.
29     **/
30    override global List<DataSource.Capability>
31        getCapabilities() {
32        List<DataSource.Capability> capabilities =
33            new List<DataSource.Capability>();
34        capabilities.add(DataSource.Capability.ROW_QUERY);
35        capabilities.add(DataSource.Capability.SEARCH);
36        return capabilities;
37    }
38
39    /**
40     *   Declares the associated DataSource.Connection class.
41     **/
42    override global DataSource.Connection getConnection(
43        DataSource.ConnectionParams connectionParams) {
44        return new DriveDataSourceConnection(connectionParams);
45    }
46}