/** Licensed Materials - Property of IBM IBM Cognos Products: DOCS (C) Copyright IBM Corp. 2013 US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import com.ibm.json.java.JSONArray; import com.ibm.json.java.JSONObject; /** * This code creates a simple model corresponding to the GOSALES example * showing sales by product type / product line. */ public class StartToFinish { /** * URL to the server with the FMD SDK installed. */ final private static String BI_SERVER_URL = "http://localhost:9300/p2pd/servlet/dispatch/"; /** * The URL part that directs requests to the FMD SDK. */ final private static String BASE_URL = BI_SERVER_URL + "FmCommand/"; /** * Path to the model location. */ final private static String OUTPUT_FILE = "c:/gosales_sdk.fmd"; /** * POJO code that creates HTTP request passing data in JSON format. *

Should the request return a error or a warning, they are written out to the system error stream.

* @param keyword The URL path segment used to identify the request * @param method The HTTP method to use ("GET", "POST", "PUT", "DELETE"). * @param json The data to be passed with the request, might be null * @param modelObjectId The Id of the model object targeted by this request, may be null * @return The JSON data returned by the SDK. Might be null. */ static protected JSONObject callFMD(String keyword, String method, JSONObject json, String modelObjectId) { OutputStream os = null; BufferedReader br = null; HttpURLConnection conn = null; try { URL url = (modelObjectId == null) ? new URL(BASE_URL + keyword) : new URL(BASE_URL + keyword + "/"+modelObjectId); conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setRequestMethod(method); // By default, server only allows "GET" and "POST" requests. Use X-header // to pass other verbs. if ("GET".equals(method) || "POST".equals(method)) conn.setRequestMethod(method); else if ("PUT".equals(method) || "DELETE".equals(method)) { conn.setRequestMethod("POST"); conn.setRequestProperty("X-HTTP-Method-Override", method); } conn.setRequestProperty("Content-Type", "application/json; charset=utf-8"); if (json != null) { os = conn.getOutputStream(); os.write(json.serialize().getBytes()); os.flush(); } br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); String output; StringBuffer tmp = new StringBuffer(); while ((output = br.readLine()) != null) { tmp.append(output); } JSONObject result = JSONObject.parse(tmp.toString()); JSONArray errorsArray = (JSONArray) result.get("errors"); if (errorsArray != null) System.err.println("Errors for request \"" + keyword + "\": " + errorsArray.toString()); JSONArray warningsArray = (JSONArray) result.get("warnings"); if (warningsArray != null) System.err.println("Warnings for request \"" + keyword + "\": " + warningsArray.toString()); return result; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (json != null) json.clear(); try { if (os != null) os.close(); if (br != null) br.close(); } catch (IOException e) { e.printStackTrace(); } if (conn != null) conn.disconnect(); } return null; } /** * Convenience function used to create a model element. See {@link #callFMD(String, String, JSONObject, String)} * for description of arguments. * @param keyword The URL path segment used to identify the request * @param json The data to be passed with the request, might be null * @return The Id of the model object, if returned by the SDK. Might be null. */ static protected String fmdCreate(String keyword, JSONObject json) { JSONObject result = callFMD(keyword, "POST", json, null); return (String) result.get("id"); } /** * A convenience function wrapping "save model to a stream" request. * @param file The local file in which to save the stream contents * @param modelObjectId The Id of the model object targeted by this request * @return true if model was saved successfully */ static protected boolean saveToFile(File file, String modelObjectId) { BufferedReader replyReader = null; HttpURLConnection conn = null; BufferedWriter fileWriter = null; try { URL url = new URL(BASE_URL + "model_save_stream/" + modelObjectId); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setUseCaches(false); conn.setRequestProperty("Cache-Control", "no-cache"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Content-Type", "text/plain"); replyReader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); String output; fileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),"UTF-8")); while ((output = replyReader.readLine()) != null) { fileWriter.write(output); fileWriter.newLine(); } fileWriter.flush(); return true; } catch (IOException e) { e.printStackTrace(); } finally { try { if (replyReader != null) replyReader.close(); if (fileWriter != null) fileWriter.close(); if (conn != null) conn.disconnect(); } catch (IOException ex) { ex.printStackTrace(); } } return false; } /** * Convenience method creating a pair of a text and locale. */ static protected JSONArray localizedText(String text, String locale) { JSONObject tmp = new JSONObject(); tmp.put("text", text); tmp.put("locale", locale); JSONArray nameArray = new JSONArray(1); nameArray.add(tmp); return nameArray; } public static void main(String[] args) throws IOException { // create model in memory JSONObject json = new JSONObject(); json.put("name", "Project"); json.put("namespace", "Model"); json.put("locale", "EN"); String modelId = fmdCreate("model_new", json); // datasource json.put("parent", modelId); json.put("name", "great_outdoors_sales"); json.put("cmDataSource", "great_outdoors_sales"); json.put("catalog", "GOSALES"); json.put("schema", "gosales"); json.put("queryType", "relational"); json.put("functionSetId", "V_SQLServer"); json.put("interface", "SS"); String idDataSource = fmdCreate("datasource", json); // relational dimension json.put("parent", modelId); json.put("name", localizedText("Products", "EN")); String idDimension = fmdCreate("relational_dimension", json); // level - Line json.put("parent", idDimension); json.put("name", localizedText("Line", "EN")); String idLevel = fmdCreate("level", json); // query item - Product Line Code json.put("parent", idLevel); json.put("name", localizedText("Product Line Code", "EN")); json.put("usage", "identifier"); json.put("datatype", "int32"); json.put("precision", "10"); json.put("scale", "0"); json.put("isLevelKey", "true"); String idProductLineCode = fmdCreate("query_item", json); // query item - Product Line json.put("parent", idLevel); json.put("name", localizedText("Product Line En", "EN")); json.put("usage", "identifier"); json.put("datatype", "nVarChar"); json.put("size", "30"); String idProductLine = fmdCreate("query_item", json); // role json.put("parent", idProductLine); json.put("name", localizedText("_memberCaption", "EN")); fmdCreate("query_item_role", json); // level - Type json.put("parent", idDimension); json.put("name", localizedText("Type", "EN")); String idTypeLevel = fmdCreate("level", json); // query item - Product Type Code json.put("parent", idTypeLevel); json.put("name", localizedText("Product Type Code", "EN")); json.put("usage", "identifier"); json.put("datatype", "int32"); json.put("precision", "10"); json.put("scale", "0"); json.put("isLevelKey", "true"); String idProductTypeCode = fmdCreate("query_item", json); // query item - Product Type Code json.put("parent", idTypeLevel); json.put("name", localizedText("Product Type En", "EN")); json.put("usage", "identifier"); json.put("datatype", "nVarChar"); json.put("size", "40"); String idProductType = fmdCreate("query_item", json); // role json.put("parent", idProductType); json.put("name", localizedText("_memberCaption", "EN")); fmdCreate("query_item_role", json); // create relational hierarchy json.put("parent", idDimension); json.put("name", localizedText("ByType", "EN")); json.put("multiRoot", "false"); json.put("rootMember", "All"); json.put("rootCaption", "All"); json.put("isParentChild", "false"); json.put("defaultHierarchy", "true"); // have a level reference JSONArray jsonLevelRefs = new JSONArray(); jsonLevelRefs.add(idLevel); jsonLevelRefs.add(idTypeLevel); json.put("levels", jsonLevelRefs); fmdCreate("relational_hierarchy", json); // physical definitions - table PRODUCT_LINE json.put("parent", idDimension); json.put("name", "PRODUCT_LINE"); json.put("datasource", idDataSource); String idTableLine = fmdCreate("physical_table", json); // physical definitions - table PRODUCT_TYPE json.put("parent", idDimension); json.put("name", "PRODUCT_TYPE"); json.put("datasource", idDataSource); String idTableType = fmdCreate("physical_table", json); // physical definitions - table PRODUCT json.put("parent", idDimension); json.put("name", "PRODUCT"); json.put("datasource", idDataSource); String idTableProduct = fmdCreate("physical_table", json); // create a joint with an association PRODUCT_TYPE <-> PRODUCT_LINE json.put("parent", idDimension); json.put("name", "FK_PRODUCT_TYPE_PRODUCT_LINE"); json.put("leftTable", idTableLine); json.put("rightTable", idTableType); json.put("leftMinCardinality", "one"); json.put("leftMaxCardinality", "one"); json.put("rightMinCardinality", "one"); json.put("rightMaxCardinality", "many"); String idJoin = fmdCreate("physical_join", json); json.put("parent", idJoin); json.put("leftColumn", "PRODUCT_LINE_CODE"); json.put("operator", "equals"); json.put("rightColumn", "PRODUCT_LINE_CODE"); fmdCreate("physical_association", json); // create a joint with an association PRODUCT_TYPE <-> PRODUCT json.put("parent", idDimension); json.put("name", "FK_PRODUCT_PRODUCT_TYPE"); json.put("leftTable", idTableType); json.put("rightTable", idTableProduct); json.put("leftMinCardinality", "one"); json.put("leftMaxCardinality", "one"); json.put("rightMinCardinality", "one"); json.put("rightMaxCardinality", "many"); String idJoinProduct = fmdCreate("physical_join", json); json.put("parent", idJoinProduct); json.put("leftColumn", "PRODUCT_TYPE_CODE"); json.put("operator", "equals"); json.put("rightColumn", "PRODUCT_TYPE_CODE"); fmdCreate("physical_association", json); // query items mapping - 1 json.put("parent", idDimension); json.put("columnName", "PRODUCT_LINE_CODE"); json.put("table", idTableLine); json.put("queryItem", idProductLineCode); fmdCreate("query_item_mapping", json); // query items mapping - 2 json.put("parent", idDimension); json.put("columnName", "PRODUCT_LINE_EN"); json.put("table", idTableLine); json.put("queryItem", idProductLine); fmdCreate("query_item_mapping", json); // query items mapping - 3 json.put("parent", idDimension); json.put("columnName", "PRODUCT_TYPE_CODE"); json.put("table", idTableType); json.put("queryItem", idProductTypeCode); fmdCreate("query_item_mapping", json); // query items mapping - 4 json.put("parent", idDimension); json.put("columnName", "PRODUCT_TYPE_EN"); json.put("table", idTableType); json.put("queryItem", idProductType); fmdCreate("query_item_mapping", json); // cube json.put("parent", modelId); json.put("name", localizedText("ProductSales", "EN")); String idCube = fmdCreate("cube", json); // measure dimension json.put("parent", idCube); json.put("name", localizedText("Measures", "EN")); String idMeasureDimension = fmdCreate("measure_dimension", json); // measure Quantity json.put("parent", idMeasureDimension); json.put("name", localizedText("Quantity", "EN")); json.put("usage", "fact"); json.put("datatype", "int32"); json.put("precision", "10"); json.put("scale", "0"); json.put("regularAggregate", "sum"); String idMeasure = fmdCreate("measure", json); // set it as a default measure in the measure dimension json.put("defaultMeasure", idMeasure); callFMD("measure_dimension", "PUT", json, idMeasureDimension); // physical definition - table ORDER_DETAILS JSONObject tableOrderDetails = new JSONObject(); tableOrderDetails.put("parent", idMeasureDimension); tableOrderDetails.put("name", "ORDER_DETAILS"); tableOrderDetails.put("datasource", idDataSource); String idTableOrderDetails = fmdCreate("physical_table", tableOrderDetails); // physical definition - query item mapping QUANTITY json.put("parent", idMeasureDimension); json.put("columnName", "QUANTITY"); json.put("table", idTableOrderDetails); json.put("queryItem", idMeasure); fmdCreate("query_item_mapping", json); // relationship Products<-->Measures json.put("parent", idCube); json.put("name", "Products-Measures"); json.put("leftObjectRef", idDimension); json.put("leftMinCardinality", "one"); json.put("leftMaxCardinality", "one"); json.put("rightObjectRef", idMeasureDimension); json.put("rightMinCardinality", "one"); json.put("rightMaxCardinality", "many"); JSONArray expressionParts = new JSONArray(); JSONObject part1 = new JSONObject(); part1.put("columnName", "PRODUCT_NUMBER"); part1.put("tableName", "PRODUCT"); part1.put("dataSourceRef", idDataSource); part1.put("objectRef", idDimension); // relational dimension expressionParts.add(part1); expressionParts.add("="); JSONObject part2 = new JSONObject(); part2.put("columnName", "PRODUCT_NUMBER"); part2.put("tableName", "ORDER_DETAILS"); part2.put("dataSourceRef", idDataSource); part2.put("objectRef", idMeasureDimension); // measure dimension expressionParts.add(part2); json.put("expression", expressionParts); fmdCreate("relationship", json); // save model saveToFile(new File(OUTPUT_FILE), modelId); // deploy cube json.put("contentManagerModelPath", "~/folder[@name='My Folders']"); json.put("packageName", "FMDSDKdemo"); json.put("refreshDataSources", "true"); json.put("cube", idCube); callFMD("cube_deploy", "POST", json, null); // register cube json.put("cube", idCube); callFMD("cube_register", "POST", json, null); // start the cube json.put("cube", idCube); callFMD("cube_start", "POST", json, null); System.out.println("Cube is ready."); } }