SchemaImportHelper.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /***************************************************************************************
  2. * IBM Confidential
  3. *
  4. * OCO Source Materials
  5. *
  6. * IBM Cognos Products: Moser
  7. *
  8. * (C) Copyright IBM Corp. 2020
  9. *
  10. * The source code for this program is not published or otherwise
  11. * divested of its trade secrets, irrespective of what has been
  12. * deposited with the U.S. Copyright Office.
  13. *
  14. ***************************************************************************************/
  15. package com.ibm.bi.platform.modeling.sdk.examples;
  16. import static com.ibm.bi.platform.modeling.sdk.examples.ModelingRESTEndpoints.datasourcesURL;
  17. import static com.ibm.bi.platform.modeling.sdk.examples.ModelingRESTEndpoints.metadataImportURL;
  18. import java.io.IOException;
  19. import com.ibm.bi.platform.modeling.sdk.examples.internal.UnexpectedHTTPResponseException;
  20. import com.ibm.bi.platform.moser.core.tasks.TaskState;
  21. import com.ibm.json.java.JSONArray;
  22. import com.ibm.json.java.JSONObject;
  23. /**
  24. * Example to demonstrate how to load a data source schema
  25. *
  26. * - Load metadata
  27. * - Load metadata with selected tables
  28. * - Reload metadata
  29. *
  30. */
  31. public class SchemaImportHelper extends AsynchronousTasksRunner {
  32. /**
  33. * @param origin product url origin
  34. */
  35. public SchemaImportHelper(String origin) {
  36. super(origin);
  37. }
  38. /**
  39. * Load schema metadata
  40. *
  41. * @param datasourceId
  42. * datasource store id
  43. * @param connectionId
  44. * datasource connection store id
  45. * @param signonId
  46. * signon object store id
  47. * @param importOptions
  48. * json schema import spec
  49. * @return schema id or null
  50. * @throws UnexpectedHTTPResponseException
  51. * @throws IOException
  52. */
  53. public String loadMetadata(String datasourceId, String connectionId, String signonId, String importOptions)
  54. throws UnexpectedHTTPResponseException, IOException {
  55. String schemaId = createSchemaImportOptions(datasourceId, connectionId, signonId, importOptions);
  56. String response = importSchema(datasourceId, connectionId, signonId, schemaId);
  57. // response contains base module store id if successful, error message if failed
  58. System.out.println("Schema import is finished. Final response: " + response );
  59. return schemaId;
  60. }
  61. /**
  62. * Reload metadata example. Will change import options of already imported schema
  63. * @param datasourceId
  64. * datasource store id
  65. * @param connectionId
  66. * datasource connection store id
  67. * @param signonId
  68. * signon object store id
  69. * @param schemaId
  70. * schema store id
  71. * @param importOptions
  72. * schema import options
  73. * @param signonSpec
  74. * optional signon spec for multiple or prompted signons
  75. * @throws UnexpectedHTTPResponseException
  76. */
  77. public void reloadMetadata(String datasourceId, String connectionId, String signonId, String schemaId, String importOptions)
  78. throws UnexpectedHTTPResponseException {
  79. updateSchemaImportOptions(datasourceId, connectionId, signonId, schemaId, importOptions);
  80. String response = importSchema(datasourceId, connectionId, signonId, schemaId);
  81. // response contains base module store id if successful, error message if failed
  82. System.out.println("Schema import is finished. Final response: " + response );
  83. }
  84. /**
  85. * Post schema definition describing what to import.
  86. *
  87. * @param datasourceId
  88. * datasource store id
  89. * @param connectionId
  90. * datasource connection store id
  91. * @param signonId
  92. * signon object store id
  93. * @param definition
  94. * the schema definition , e.g.
  95. * {"schema":"FOODMART","catalog":"null","type":"dataSourceSchema","schemaType":"user","defaultName":"FOODMART"}
  96. *
  97. * or { "schema": "Person", "catalog": "AdventureWorks2014",
  98. * "schemaType": "user", "specification": { "dataStatistics":
  99. * "none", "excludedTables": [], "dataSamplingSize": 1000,
  100. * "version": "1.0", "importPrimaryForeignKeys": true },
  101. * "defaultName": "AdventureWorks2014/Person", "type":"dataSourceSchema" }
  102. * @throws UnexpectedHTTPResponseException
  103. * @throws IOException
  104. */
  105. protected String createSchemaImportOptions(String datasourceId, String connectionId, String signonId, String definition)
  106. throws UnexpectedHTTPResponseException, IOException {
  107. String url = getOrigin() + datasourcesURL + datasourceId + "/connections/" + connectionId + "/signons/"
  108. + signonId + "/schemas";
  109. String schemaId = getSchemaId(executePostRequest(url, definition, new Integer(201)));
  110. return schemaId;
  111. }
  112. /**
  113. * @param executePostRequest
  114. * @return
  115. * @throws IOException
  116. */
  117. private static String getSchemaId(String response) throws IOException {
  118. JSONObject rsp = JSONObject.parse(response);
  119. JSONArray data = (JSONArray) rsp.get("data");
  120. JSONObject schema = (JSONObject) data.get(0);
  121. return (String) schema.get("id");
  122. }
  123. /**
  124. * Put schema definition describing what to re-import. Results of the old import options will be overridden by new
  125. *
  126. * @param datasourceId
  127. * datasource store id
  128. * @param connectionId
  129. * datasource connection store id
  130. * @param signonId
  131. * signon object store id
  132. * @param schemaId
  133. * schema CM id
  134. * @param definition
  135. * the schema definition , e.g.
  136. * {"schema":"FOODMART","catalog":"null","type":"dataSourceSchema","schemaType":"user","defaultName":"FOODMART"}
  137. *
  138. * or { "schema": "Person", "catalog": "AdventureWorks2014",
  139. * "schemaType": "user", "specification": { "dataStatistics":
  140. * "none", "excludedTables": [], "dataSamplingSize": 1000,
  141. * "version": "1.0", "importPrimaryForeignKeys": true },
  142. * "defaultName": "AdventureWorks2014/Person", "type":"dataSourceSchema" }
  143. * @throws UnexpectedHTTPResponseException
  144. * @return response body
  145. */
  146. protected String updateSchemaImportOptions(String datasourceId, String connectionId, String signonId,
  147. String schemaId, String definition) throws UnexpectedHTTPResponseException {
  148. String url = getOrigin() + datasourcesURL + datasourceId + "/connections/" + connectionId + "/signons/"
  149. + signonId + "/schemas/" + schemaId;
  150. String response = executePutRequest(url, definition, new Integer(201));
  151. return response;
  152. }
  153. /**
  154. * Import schema
  155. *
  156. * @param datasourceId
  157. * datasource store id
  158. * @param connectionId
  159. * datasource connection store id
  160. * @param signonId
  161. * signon object store id
  162. * @param schemaId
  163. * schema CM id
  164. *
  165. * @return schema's base module artifact id in content manager database
  166. * @throws UnexpectedHTTPResponseException
  167. */
  168. protected String importSchema(String datasourceId, String connectionId, String signonId, String schemaId)
  169. throws UnexpectedHTTPResponseException {
  170. JSONObject parameters = new JSONObject();
  171. parameters.put("datasource_id", datasourceId);
  172. parameters.put("connection_id", connectionId);
  173. parameters.put("signon_id", signonId);
  174. parameters.put("schema_id", schemaId);
  175. String url = getOrigin() + metadataImportURL;
  176. // start schema import - base module definition creation
  177. // initiate asynchronous schema import
  178. String task = executePostRequest(url, parameters.toString(), Integer.valueOf(202));
  179. JSONObject response = executeAsychronousTask(task);
  180. if (TaskState.SUCCESS.equals(response.get("state"))) {
  181. // return base module id
  182. JSONArray ids = (JSONArray) ((JSONObject) response.get("response")).get("ids");
  183. return ids.get(0).toString();
  184. }
  185. // return error message
  186. return response.toString();
  187. }
  188. /**
  189. * Return schema json specification, which can be used to import schema
  190. *
  191. * @param qualifiedSchemaName
  192. * string in the format "database:catalog:null:schema"
  193. * @param connectionSpec null or a connection json spec for multiple or prompted signons
  194. * @return response json , e.g. { "data": [ { "schema": "CUSTAGGR",
  195. * "catalog": null, "schemaType": "user", "specification": {
  196. * "cleanColumnLabels": true, "dataStatistics": "all",
  197. * "excludedTables": [], "cleanTableLabels": true, "version": "1.0",
  198. * "importPrimaryForeignKeys": true, "dataSamplingSize": 1000 },
  199. * "id": "Foodmart_DB2:Foodmart_DB2:null:CUSTAGGR", "type":
  200. * "dataSourceSchema", "defaultName": "CUSTAGGR", "status":
  201. * "not_loaded" } ] }
  202. * @throws UnexpectedHTTPResponseException
  203. */
  204. public JSONObject getSchemaSpecification(String datasourceId, String connectionId, String signonId, String qualifiedSchemaName)
  205. throws UnexpectedHTTPResponseException {
  206. // /datasources/{datasourceid}/connections/{connectionid}/signons/{signonid}/schemas/{qualifiedNameEncoded}
  207. String url = getOrigin() + datasourcesURL + datasourceId + "/connections/" + connectionId + "/signons/" + signonId + "/schemas/" + encodeURL(qualifiedSchemaName);
  208. String response = executeGetRequest(url, Integer.valueOf(200), null);
  209. try {
  210. JSONObject schema = JSONObject.parse(response);
  211. return schema;
  212. } catch (IOException e) {
  213. e.printStackTrace();
  214. }
  215. return null;
  216. }
  217. /**
  218. * Search and return schema object store id, provided schema and catalog name
  219. *
  220. * @param connectionId datasource connection object store id
  221. * @param connectionSpec optional connection spec for multiple or prompted signons
  222. * @param schema_name schema name, can be null, depending on datasource
  223. * @param catalog schema catalog, can be null, depending on datasource
  224. * @return schema id
  225. * @throws UnexpectedHTTPResponseException
  226. */
  227. public String getSchemaId(String datasourceId, String connectionId, String signonId, String schema_name, String catalog_name)
  228. throws UnexpectedHTTPResponseException{
  229. // nothing to match
  230. if(schema_name == null && catalog_name == null){
  231. return null;
  232. }
  233. String url = getOrigin() + datasourcesURL + datasourceId + "/connections/" + connectionId + "/signons/"
  234. + signonId + "/schemas";
  235. String response = executeGetRequest(url, Integer.valueOf(200), null);
  236. try {
  237. JSONObject data = JSONObject.parse(response);
  238. JSONArray data_items = (JSONArray) data.get("schemas");
  239. for (Object item : data_items) {
  240. JSONObject descriptor = (JSONObject) item;
  241. if (descriptor.get("status").equals("loaded")) {
  242. String schema = (String) descriptor.get("schema");
  243. String catalog = (String) descriptor.get("catalog");
  244. if (schema_name == null && catalog_name.equals(catalog)) {
  245. return descriptor.get("id").toString();
  246. } else if (catalog_name == null && schema_name.equals(schema)) {
  247. return descriptor.get("id").toString();
  248. } else if (schema_name.equals(schema) && catalog_name.equals(catalog)) {
  249. return descriptor.get("id").toString();
  250. }
  251. }
  252. }
  253. } catch (IOException e) {
  254. e.printStackTrace();
  255. }
  256. return null;
  257. }
  258. /**
  259. * Return an array of tables for the schema
  260. *
  261. * @param qualifiedSchemaName
  262. * string in the format "datasource:connection:catalog:schema"
  263. * @param connectionSpec
  264. * null or a connection json spec for multiple or prompted
  265. * signons
  266. * @return response json array of tables, e.g.
  267. * {"data":["BOSTONNY_SALES_AGGR","CANADA_YEAR_SALES_AGGR",
  268. * "COUNTRY_YEAR_SALES_AGGR","FACTTABLE","OTTAWATORONTO_SALES_AGGR",
  269. * "REGION","SALES_AGGR","TIME","US_YEAR_SALES_AGGR","YEAR_SALES_AGGR"]}
  270. * @throws UnexpectedHTTPResponseException
  271. */
  272. public JSONArray getSchemaTables(String datasourceId, String connectionId, String signonId,
  273. String qualifiedSchemaName) throws UnexpectedHTTPResponseException {
  274. // /datasources/{datasourceid}/connections/{connectionid}/signons/{signonid}/schemas/tables?id={qualifiedNameEncoded}
  275. String url = getOrigin() + datasourcesURL + datasourceId + "/connections/" + connectionId + "/signons/"
  276. + signonId + "/schemas/tables" + "?schemaid=" + encodeURL(qualifiedSchemaName);
  277. String response = executeGetRequest(url, Integer.valueOf(200), null);
  278. try {
  279. JSONObject data = JSONObject.parse(response);
  280. return (JSONArray) data.get("tables");
  281. } catch (IOException e) {
  282. e.printStackTrace();
  283. }
  284. return null;
  285. }
  286. /** scenarios **/
  287. /**
  288. * Reload metadata example. Loads all tables for the given schema. Schema
  289. * import options are pre-configured and loaded from file
  290. *
  291. * @param datasourceId
  292. * datasource store ID
  293. * @param connectionId
  294. * datasource connection store ID
  295. * @param signonId
  296. * signon object store ID
  297. * @param importOptions
  298. * import option specification json string
  299. * @return schema content store id
  300. * @throws UnexpectedHTTPResponseException
  301. * @throws IOException
  302. */
  303. public String runReLoadMetadataExample(String datasourceId, String connectionId, String signonId,
  304. String importOptions) throws UnexpectedHTTPResponseException, IOException {
  305. JSONObject importSpec = JSONObject.parse(importOptions);
  306. String schema_name = (String) importSpec.get("schema"), catalog_name = (String) importSpec.get("catalog");
  307. String schemaId = getSchemaId(datasourceId, connectionId, signonId, schema_name, catalog_name);
  308. reloadMetadata(datasourceId, connectionId, signonId, schemaId, importOptions);
  309. return schemaId;
  310. }
  311. /**
  312. * Load metadata example. Loads selected tables for the given schema. Schema
  313. * import options are configured during example execution
  314. *
  315. * @param datasourceId
  316. * datasource store id
  317. * @param connectionId
  318. * datasource connection store id
  319. * @param signonId
  320. * signon object store id
  321. * @param importOptions
  322. * json schema import spec
  323. *
  324. * @param datasource_name
  325. * datasource name
  326. * @param connection_name
  327. * datasource connection name
  328. * @param catalog_name
  329. * catalog name or null, note both schema and catalog can not be
  330. * null
  331. * @param schema_name
  332. * schema name or null, note both schema and catalog can not be
  333. * null
  334. *
  335. * @return schema content store id
  336. * @throws UnexpectedHTTPResponseException
  337. * @throws IOException
  338. */
  339. public String runLoadMetadataWithSelectedTablesExample(String datasourceId, String connectionId, String signonId,
  340. String datasource_name, String connection_name, String catalog_name, String schema_name)
  341. throws UnexpectedHTTPResponseException, IOException {
  342. String qualifiedSchemaName = datasource_name + ":" + connection_name + ":" + catalog_name + ":" + schema_name;
  343. JSONObject importOptions = getSchemaSpecification(datasourceId, connectionId, signonId, qualifiedSchemaName);
  344. if (importOptions == null) {
  345. return null;
  346. }
  347. JSONObject specification = (JSONObject) importOptions.get("specification");
  348. JSONArray tables = getSchemaTables(datasourceId, connectionId, signonId, qualifiedSchemaName);
  349. if (tables == null) {
  350. return null;
  351. }
  352. JSONArray tablesToExclude = (JSONArray) specification.get("excludedTables");
  353. for (int i = tables.size() / 2; i < tables.size(); i++) {
  354. tablesToExclude.add(tables.get(i));
  355. }
  356. importOptions.remove("id");
  357. importOptions.put("status", "pending");
  358. return loadMetadata(datasourceId, connectionId, signonId, importOptions.toString());
  359. }
  360. /**
  361. * Load metadata example. Loads all tables for the given schema. Schema
  362. * import options are pre-configured and loaded from file
  363. *
  364. * @param datasourceId
  365. * datasource store id
  366. * @param connectionId
  367. * datasource connection store id
  368. * @param signonId
  369. * signon object store id
  370. * @param importOptions
  371. * json schema import spec
  372. * @return schema content store id
  373. * @throws UnexpectedHTTPResponseException
  374. * @throws IOException
  375. */
  376. public String runLoadMetadataExample(String datasourceId, String connectionId, String signonId,
  377. String importOptions) throws UnexpectedHTTPResponseException, IOException {
  378. return loadMetadata(datasourceId, connectionId, signonId, importOptions);
  379. }
  380. /**
  381. * Removes a dataSourceSchema object from CM - clears import
  382. *
  383. * @throws UnexpectedHTTPResponseException
  384. */
  385. public void clearSchema(String schemaId) throws UnexpectedHTTPResponseException{
  386. if(schemaId == null){
  387. return;
  388. }
  389. String url = getOrigin() + schemasURL + schemaId;
  390. executeDeleteRequest(url, Integer.valueOf(200), null);
  391. }
  392. /* (non-Javadoc)
  393. * @see com.ibm.bi.platform.modeling.sdk.examples.AsynchronousTasksRunner#getTasksURL()
  394. */
  395. @Override
  396. public String getTasksURL() {
  397. return ModelingRESTEndpoints.metadataImportTasksURL;
  398. }
  399. }