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

Salesforce Connect のループバックカスタムアダプター

次の例は、クエリで絞り込みを処理する方法を示しています。簡潔に示すため、この例では、Salesforce 組織を、それ自体を���部システムとして同組織に接続しています。

LoopbackDataSourceConnection クラス

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 LoopbackDataSourceConnection 
7    extends DataSource.Connection {
8
9    /**
10     *   Constructors.
11     **/
12    global LoopbackDataSourceConnection(
13        DataSource.ConnectionParams connectionParams) {
14    }
15    global LoopbackDataSourceConnection() {}
16    
17    /**
18     *   Called when an external object needs to get a list of 
19     *   schema from the external data source, for example when 
20     *   the administrator clicks “Validate and Sync” in the 
21     *   user interface for the external data source.   
22     **/
23    override global List<DataSource.Table> sync() {
24        List<DataSource.Table> tables = 
25            new List<DataSource.Table>();        
26        List<DataSource.Column> columns;
27        columns = new List<DataSource.Column>();
28        columns.add(DataSource.Column.text('ExternalId', 255));
29        columns.add(DataSource.Column.url('DisplayUrl'));
30        columns.add(DataSource.Column.text('Name', 255));
31        columns.add(
32            DataSource.Column.number('NumberOfEmployees', 18, 0));
33        tables.add(
34            DataSource.Table.get('Looper', 'Name', columns));
35        return tables;
36    }
37    
38    /**
39     *   Called to query and get results from the external 
40     *   system for SOQL queries, list views, and detail pages 
41     *   for an external object that’s associated with the 
42     *   external data source.
43     *   
44     *   The QueryContext argument represents the query to run 
45     *   against a table in the external system.
46     *   
47     *   Returns a list of rows as the query results.
48     **/
49    override global DataSource.TableResult 
50        query(DataSource.QueryContext context) {
51        if (context.tableSelection.columnsSelected.size() == 1 &&
52            context.tableSelection.columnsSelected.get(0).aggregation ==
53                DataSource.QueryAggregation.COUNT) {
54            integer count = execCount(getCountQuery(context));
55            List<Map<String, Object>> countResponse =
56                new List<Map<String, Object>>();
57            Map<String, Object> countRow =
58                new Map<String, Object>();
59            countRow.put(
60                context.tableSelection.columnsSelected.get(0).columnName,
61                count);
62            countResponse.add(countRow);
63            return DataSource.TableResult.get(context,countResponse);
64        } else {
65            List<Map<String,Object>> rows = execQuery(
66                getSoqlQuery(context));
67            return DataSource.TableResult.get(context,rows);
68        }
69    }
70    
71    /**
72     *   Called to do a full text search and get results from
73     *   the external system for SOSL queries and Salesforce
74     *   global searches.
75     *   
76     *   The SearchContext argument represents the query to run 
77     *   against a table in the external system.
78     *   
79     *   Returns results for each table that the SearchContext 
80     *   requested to be searched.
81     **/
82    override global List<DataSource.TableResult> 
83        search(DataSource.SearchContext context) {        
84        return DataSource.SearchUtils.searchByName(context, this);
85    }
86
87    /**
88     *   Helper method to execute the SOQL query and 
89     *   return the results.
90     **/
91    private List<Map<String,Object>> 
92        execQuery(String soqlQuery) {
93        List<Account> objs = Database.query(soqlQuery);
94        List<Map<String,Object>> rows = 
95            new List<Map<String,Object>>();
96        for (Account obj : objs) {
97            Map<String,Object> row = new Map<String,Object>();
98            row.put('Name', obj.Name);
99            row.put('NumberOfEmployees', obj.NumberOfEmployees);
100            row.put('ExternalId', obj.Id);
101            row.put('DisplayUrl', 
102                URL.getOrgDomainUrl().toExternalForm() + 
103                    obj.Id);
104            rows.add(row);
105        }
106        return rows;
107    }
108
109    /**
110     *   Helper method to get aggregate count.
111     **/
112    private integer execCount(String soqlQuery) {
113        integer count = Database.countQuery(soqlQuery);
114        return count;
115    }
116
117    /**
118     *   Helper method to create default aggregate query.
119     **/
120    private String getCountQuery(DataSource.QueryContext context) {
121        String baseQuery = 'SELECT COUNT() FROM Account';
122        String filter = getSoqlFilter('', 
123            context.tableSelection.filter);
124        if (filter.length() > 0)
125            return baseQuery + ' WHERE ' + filter;
126        return baseQuery;
127    }
128
129    /**
130     *   Helper method to create default query.
131     **/
132    private String getSoqlQuery(DataSource.QueryContext context) {
133        String baseQuery = 
134            'SELECT Id,Name,NumberOfEmployees FROM Account';
135        String filter = getSoqlFilter('', 
136            context.tableSelection.filter);
137        if (filter.length() > 0)
138            return baseQuery + ' WHERE ' + filter;
139        return baseQuery;
140    }
141
142    /**
143     *   Helper method to handle query filter.
144     **/
145    private String getSoqlFilter(String query, 
146        DataSource.Filter filter) {
147        if (filter == null) {
148            return query;
149        }
150        String append;
151        DataSource.FilterType type = filter.type;
152        List<Map<String,Object>> retainedRows = 
153            new List<Map<String,Object>>();
154        if (type == DataSource.FilterType.NOT_) {
155            DataSource.Filter subfilter = filter.subfilters.get(0);
156            append = getSoqlFilter('NOT', subfilter);
157        } else if (type == DataSource.FilterType.AND_) {
158            append =  
159                getSoqlFilterCompound('AND', filter.subfilters);
160        } else if (type == DataSource.FilterType.OR_) {
161            append = 
162                getSoqlFilterCompound('OR', filter.subfilters);
163        } else {
164            append = getSoqlFilterExpression(filter);
165        }
166        return query + ' ' + append;
167    }
168    
169    /**
170     *   Helper method to handle query subfilters.
171     **/
172    private String getSoqlFilterCompound(String operator, 
173        List<DataSource.Filter> subfilters) {
174        String expression = ' (';
175        boolean first = true;
176        for (DataSource.Filter subfilter : subfilters) {
177            if (first)
178                first = false;
179            else
180                expression += ' ' + operator + ' ';
181            expression += getSoqlFilter('', subfilter);
182        }
183        expression += ') ';
184        return expression;
185    }
186    
187    /**
188     *   Helper method to handle query filter expressions.
189     **/
190    private String getSoqlFilterExpression(
191        DataSource.Filter filter) {
192        String columnName = filter.columnName;
193        String operator;
194        Object expectedValue = filter.columnValue;
195        if (filter.type == DataSource.FilterType.EQUALS) {
196            operator = '=';
197        } else if (filter.type == 
198            DataSource.FilterType.NOT_EQUALS) {
199            operator = '<>';
200        } else if (filter.type == 
201            DataSource.FilterType.LESS_THAN) {
202            operator = '<';
203        } else if (filter.type == 
204            DataSource.FilterType.GREATER_THAN) {
205            operator = '>';
206        } else if (filter.type == 
207            DataSource.FilterType.LESS_THAN_OR_EQUAL_TO) {
208            operator = '<=';
209        } else if (filter.type == 
210            DataSource.FilterType.GREATER_THAN_OR_EQUAL_TO) {
211            operator = '>=';
212        } else if (filter.type == 
213            DataSource.FilterType.STARTS_WITH) {
214            return mapColumnName(columnName) + 
215            ' LIKE \'' + String.valueOf(expectedValue) + '%\'';
216        } else if (filter.type == 
217            DataSource.FilterType.ENDS_WITH) {
218            return mapColumnName(columnName) + 
219            ' LIKE \'%' + String.valueOf(expectedValue) + '\'';
220        } else if (filter.type == 
221            DataSource.FilterType.LIKE_) {
222            return mapColumnName(columnName) + 
223            ' LIKE \'' + String.valueOf(expectedValue) + '\'';
224        } else {
225            throwException(
226            'Implementing other filter types is left as an exercise for the reader: ' 
227            + filter.type);
228        }
229        return mapColumnName(columnName) + 
230            ' ' + operator + ' ' + wrapValue(expectedValue);
231    }
232    
233    /**
234     *   Helper method to map column names.
235     **/
236    private String mapColumnName(String apexName) {
237        if (apexName.equalsIgnoreCase('ExternalId'))
238            return 'Id';
239        if (apexName.equalsIgnoreCase('DisplayUrl'))
240            return 'Id';
241        return apexName;
242    }
243
244    /**
245    *   Helper method to wrap expression Strings with quotes.
246    **/
247    private String wrapValue(Object foundValue) {
248        if (foundValue instanceof String)
249            return '\'' + String.valueOf(foundValue) + '\'';
250        return String.valueOf(foundValue);
251    }
252}

LoopbackDataSourceProvider クラス

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 LoopbackDataSourceProvider 
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.ANONYMOUS);
21        capabilities.add(
22            DataSource.AuthenticationCapability.BASIC);
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 
43        getConnection(DataSource.ConnectionParams connectionParams) {
44        return new LoopbackDataSourceConnection();
45    }
46}