Yellowfin REST API コンテンツのインポート オプション指定の例

## はじめに
以前に、REST API を介して、Yellowfin からコンテンツをエクスポートおよびインポートする方法を 3 回に分けて紹介しました。
[第 1 回 『Yellowfin REST API エクスポートできるコンテンツの確認』]( https://qiita.com/ExtremeCarvFJ/items/34447db30788b8a1445e)
[第 2 回 『Yellowfin REST API コンテンツのエクスポート』](https://qiita.com/ExtremeCarvFJ/items/b00a1f982ea5f3b480b5)
[第 3 回 『Yellowfin REST API コンテンツのインポート』](https://qiita.com/ExtremeCarvFJ/items/f4a3fc55ff7fe22f7672)
3 回に渡って記述した記事の内容としては、該当するコンテンツをエクスポートして、エクスポートしたコンテンツを全てインポートする流れでした。
一方で、一般的な運用としては、エクスポートしたコンテンツの中から、修正したコンテンツのみをインポートする場面も多くあるかと思います。例えば、レポートは修正したが、レポートが参照するビューは修正していないため、レポートだけをインポートし、そのレポートを既存ビューに紐づけるような処理が該当します。
REST API でどのようなオプション指定を実施すれば、上記のような処理が可能になるかを、本記事の中で説明したいと思います。

[Yellowfin ReDoc](https://developers.yellowfinbi.com/dev/api-docs/current/#tag/import-export) サイトにも API に関する詳細情報が載せられています。併せてご確認ください。

## コンテンツのエクスポート
[第 1 回 『Yellowfin REST API エクスポートできるコンテンツの確認』]( https://qiita.com/ExtremeCarvFJ/items/34447db30788b8a1445e) を参照して、まずはエクスポート可能なコンテンツ一覧を確認します。
続いて、[第 2 回 『Yellowfin REST API コンテンツのエクスポート』](https://qiita.com/ExtremeCarvFJ/items/b00a1f982ea5f3b480b5)を参照して、コンテンツをエクスポートします。

## エクスポートファイルに含まれるコンテンツの確認
以下の php プログラムを実行することで、エクスポートファイルに含まれるコンテンツ一覧を表示することができます。
なお、アクセストークンを取得するまでのコードは、[第 1 回 『Yellowfin REST API エクスポートできるコンテンツの確認』]( https://qiita.com/ExtremeCarvFJ/items/34447db30788b8a1445e) を参照願います。以下のコードは、取得したアクセストークンを使って、cURL の中で API を呼び出して処理する部分からを記述しています(参考までに、コード全容は "おまけ" の箇所に載せています)。
```php:exportedContents.php
$text ='curl -X "POST" "http://localhost:8080/api/rpc/import-export/get-import-content" ';
$text = $text.'-H "Accept: application/vnd.yellowfin.api-v2+json" ';
$text = $text.'-H "Authorization: YELLOWFIN ts='.$time.', nonce=123, token='.$accessToken.'" ';
$text = $text.'-H "Content-Type: multipart/form-data" -H "cache-control: no-cache" ';
$text = $text.'--form "contentToProcess=@export.yfx;type=application/octet-stream" ';
```
コードの内容としては、ほぼ[第 3 回 『Yellowfin REST API コンテンツのインポート』](https://qiita.com/ExtremeCarvFJ/items/f4a3fc55ff7fe22f7672)と同様の処理です。
違いとしては、cURL の中で指定する API が get-import-content に変わった程度です。同 API を呼び出して、cURL の中で指定するファイル (contentToProcess=@export.yfx) の中身を読み出します。

結果、例えば以下のようなコンテンツ一覧情報を取得できます。
```json:コンテンツ一覧
{
	"items": [
		{
			"resourceName": "MS SQL",
			"resourceDescription": "",
			"resourceId": 100847,
			"resourceUUID": "b6bd416e-814e-48f0-ab53-ecc3a665f4b5",
			"resourceType": "DATASOURCE"
		},
		{
			"resourceName": "timeseries",
			"resourceDescription": "",
			"resourceId": 100848,
			"resourceUUID": "f3d0a67f-83cc-40d4-b709-2cb194debb84",
			"resourceType": "VIEW"
		},
		{
			"resourceName": "共有",
			"resourceId": 100951,
			"resourceUUID": "4b900a09-2d81-4e7d-a421-0a95351198ed",
			"resourceType": "RPTCATEGORY",
			"resourceCode": "51716709"
		},
		{
			"resourceName": "コンテンツ",
			"resourceId": 100952,
			"resourceUUID": "5016ab12-b33f-4c2e-91ed-d5899cad2cdf",
			"resourceType": "RPTSUBCATEGORY",
			"resourceCode": "30B330F330C630F330C4"
		},
		{
			"resourceName": "timeseries",
			"resourceDescription": "",
			"resourceId": 100933,
			"resourceUUID": "b45c2d32-7c36-4164-9039-c657bed13b61",
			"resourceType": "REPORT"
		}
	],
	"_links": {
		"menu": {
			"href": "/api/menus/mobile-menu",
			"options": [
				"GET"
			]
		},
		"api": {
			"href": "/api",
			"options": [
				"GET"
			]
		},
		"self": {
			"href": "/api/rpc/import-export/get-import-content",
			"options": [
				"POST"
			]
		}
	}
}
```

JSON の配列内で、各コンテンツに対して、順に itemIndex が振られています。上記 JSON ファイルに示されているコンテンツ一覧を簡単にまとめると下記表の通りです。
インポート時に、itemIndex と resourceId を指定して、インポートをスキップするコンテンツや、インポートするコンテンツと紐づける既存コンテンツを決定します。
|itemIndex|resourceName|resourceType|resourceId|
|---|---|---|---|
|0|MS SQL|データソース (DATASOURCE)|100847|
|1|timeseries|ビュー (VIEW)|100848|
|2|共有|親フォルダ (RPTCATEGORY)|100951|
|3|コンテンツ|子フォルダ (RPTSUBCATEGORY)|100952|
|4|timeseries|レポート (REPORT)|100933|

## コンテンツのインポート
2 つ具体的なコードを例示して、処理の流れを説明します。
いずれの例に関しても、アクセストークンを取得するまでのコードは、[第 1 回 『Yellowfin REST API エクスポートできるコンテンツの確認』]( https://qiita.com/ExtremeCarvFJ/items/34447db30788b8a1445e) を参照願います。以下では、取得したアクセストークンを使って、cURL の中で API を呼び出して処理する部分からを記述しています。

### インポートするレポートを既存ビューと紐づける場合
1 つ目はインポートするレポートを既存ビューと紐づける例です。
```php:importContents1.php
$text ='curl -X "POST" "http://localhost:8080/api/rpc/import-export/import-content" ';
$text = $text.'-H "Accept: application/vnd.yellowfin.api-v2+json" ';
$text = $text.'-H "Authorization: YELLOWFIN ts='.$time.', nonce=123, token='.$accessToken.'" ';
$text = $text.'-H "Content-Type: multipart/form-data" -H "cache-control: no-cache" ';
$text = $text.'--form "contentToProcess=@export.yfx;type=application/octet-stream" ';
$text = $text.'--form "importOptions=[{itemIndex: 0, optionKey: \'SKIP\', optionValue:\'TRUE\'},';
$text = $text.'{itemIndex: 1, optionKey: \'SKIP\', optionValue:\'TRUE\'},';
$text = $text.'{itemIndex:4, optionKey: \'VIEW\', optionValue:\'VIEW100848\'}];type=application/json"';
echo exec($text);
```
インポートするレポートを、既存のビューに紐づけるため、 export.yfx からはデータソースとビューはインポートする必要はありません。
`itemIndex: 0, optionKey: \'SKIP\', optionValue:\'TRUE\'` でデータソースのインポートをスキップし、`itemIndex: 1, optionKey: \'SKIP\', optionValue:\'TRUE\'` でビューのインポートをスキップしています。
` itemIndex:4, optionKey: \'VIEW\', optionValue:\'VIEW100848\'` で、インポートするレポートに対して紐づけるビューを指定しています。
itemIndex で指定する数値と、ビューの resourceId は、先述の表をご確認ください。

### インポートするビューを既存データソースと紐づける場合
2 つ目はインポートするビューを既存データソースと紐づける例です。
```php:importContents2.php
$text ='curl -X "POST" "http://localhost:8080/api/rpc/import-export/import-content" ';
$text = $text.'-H "Accept: application/vnd.yellowfin.api-v2+json" ';
$text = $text.'-H "Authorization: YELLOWFIN ts='.$time.', nonce=123, token='.$accessToken.'" ';
$text = $text.'-H "Content-Type: multipart/form-data" -H "cache-control: no-cache" ';
$text = $text.'--form "contentToProcess=@export.yfx;type=application/octet-stream" ';
$text = $text.'--form "importOptions=[{itemIndex: 0, optionKey: \'SKIP\', optionValue:\'TRUE\'},';
$text = $text.'{itemIndex: 1, optionKey: \'SOURCE\', optionValue:\'SOURCE100847\'}];';
$text = $text.'type=application/json"';
echo exec($text);
```
インポートするビューを、既存のデータソースに紐づけるため、 export.yfx からはデータソースはインポートする必要はありません。
`itemIndex: 0, optionKey: \'SKIP\', optionValue:\'TRUE\'` でデータソースのインポートをスキップしています。
` itemIndex: 1, optionKey: \'SOURCE\', optionValue:\'SOURCE100847\'` で、インポートするビューに対して紐づけるデータソースを指定しています。
itemIndex で指定する数値と、データソースの resourceId は、先述の表をご確認ください。

## 最後に
インポートするコンテンツの中から、インポートをスキップするコンテンツを指定し、代わりに紐づけるコンテンツを指定する流れがお分かりいただけましたでしょうか。Yellowfin コンテンツのエクスポート、インポートを実施したことがある方であればお分かりいただけるかと思いますが、GUI で実施する手順をそのまま API に対しても実行している感じです。
開発環境から本番環境に対するコンテンツの移行をプログラム処理で実施したい場合など、是非本記事の内容をご参照ください。

では皆様、良いデータ分析を! Cheers!!

## おまけ（コード全容）
```php:exportedContents.php
<?php
//変数の宣言
$adminId = 'admin@yellowfin.com.au';
$adminPassword = 'test';
$time = ceil(microtime(true)*1000);
$url = 'http://localhost:8080/api/refresh-tokens';
$url2 = 'http://localhost:8080/api/access-tokens';
$refreshToken = "";
$accessToken = "";

//リフレッシュトークン
$header = array(
	'Authorization:YELLOWFIN ts='.$time.', nonce=123',
	'Accept:application/vnd.yellowfin.api-v2+json',
	'Content-Type:application/json;charset=UTF-8'
);

$body = array(
	'userName'=>$adminId,
	'password'=>$adminPassword
);
$body_json = json_encode($body, JSON_PRETTY_PRINT);

$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $body_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
$json_result = json_decode($result);
$refreshToken = $json_result->securityToken;
curl_close($ch);

//アクセストークン
$header2 = array(
	'Authorization:YELLOWFIN ts='.$time.', nonce=123, token='.$refreshToken,
	'Accept:application/vnd.yellowfin.api-v2+json',
	'Content-Type:application/json'
);

$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_HTTPHEADER, $header2);
curl_setopt($ch2, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch2, CURLOPT_POSTFIELDS, '');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_URL, $url2);
curl_close($ch);
$result2 = curl_exec($ch2);
$json_result2 = json_decode($result2);
$accessToken=$json_result2->securityToken;

//インポート処理
$text ='curl -X "POST" "http://localhost:8080/api/rpc/import-export/get-import-content" ';
$text = $text.'-H "Accept: application/vnd.yellowfin.api-v2+json" ';
$text = $text.'-H "Authorization: YELLOWFIN ts='.$time.', nonce=123, token='.$accessToken.'" ';
$text = $text.'-H "Content-Type: multipart/form-data" -H "cache-control: no-cache" ';
$text = $text.'--form "contentToProcess=@export.yfx;type=application/octet-stream" ';
echo $text = exec($text);
?>
```

```php:importContents1.php
<?php
//Variables
$adminId = 'admin@yellowfin.com.au';
$adminPassword = 'test';
$time = ceil(microtime(true)*1000);
$url = 'http://localhost:8080/api/refresh-tokens';
$url2 = 'http://localhost:8080/api/access-tokens';
$refreshToken = "";
$accessToken = "";

//Refresh token
$header = array(
	'Authorization:YELLOWFIN ts='.$time.', nonce=123',
	'Accept:application/vnd.yellowfin.api-v2+json',
	'Content-Type:application/json;charset=UTF-8'
);

$body = array(
	'userName'=>$adminId,
	'password'=>$adminPassword
);
$body_json = json_encode($body, JSON_PRETTY_PRINT);

$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $body_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
$json_result = json_decode($result);
$refreshToken = $json_result->securityToken;
curl_close($ch);

//Access token
$header2 = array(
	'Authorization:YELLOWFIN ts='.$time.', nonce=123, token='.$refreshToken,
	'Accept:application/vnd.yellowfin.api-v2+json',
	'Content-Type:application/json'
);

$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_HTTPHEADER, $header2);
curl_setopt($ch2, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch2, CURLOPT_POSTFIELDS, '');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_URL, $url2);
curl_close($ch);
$result2 = curl_exec($ch2);
$json_result2 = json_decode($result2);
$accessToken=$json_result2->securityToken;

//Import contents
$text ='curl -X "POST" "http://localhost:8080/api/rpc/import-export/import-content" ';
$text = $text.'-H "Accept: application/vnd.yellowfin.api-v2+json" ';
$text = $text.'-H "Authorization: YELLOWFIN ts='.$time.', nonce=123, token='.$accessToken.'" ';
$text = $text.'-H "Content-Type: multipart/form-data" -H "cache-control: no-cache" ';
$text = $text.'--form "contentToProcess=@export.yfx;type=application/octet-stream" ';
$text = $text.'--form "importOptions=[{itemIndex: 0, optionKey: \'SKIP\', optionValue:\'TRUE\'},';
$text = $text.'{itemIndex: 1, optionKey: \'SKIP\', optionValue:\'TRUE\'},';
$text = $text.'{itemIndex:4, optionKey: \'VIEW\', optionValue:\'VIEW100848\'}];type=application/json"';
echo exec($text);
?>
```

```php:importContents2.php
<?php
//Variables
$adminId = 'admin@yellowfin.com.au';
$adminPassword = 'test';
$time = ceil(microtime(true)*1000);
$url = 'http://localhost:8080/api/refresh-tokens';
$url2 = 'http://localhost:8080/api/access-tokens';
$refreshToken = "";
$accessToken = "";

//Refresh token
$header = array(
	'Authorization:YELLOWFIN ts='.$time.', nonce=123',
	'Accept:application/vnd.yellowfin.api-v2+json',
	'Content-Type:application/json;charset=UTF-8'
);

$body = array(
	'userName'=>$adminId,
	'password'=>$adminPassword
);
$body_json = json_encode($body, JSON_PRETTY_PRINT);

$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $body_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
$json_result = json_decode($result);
$refreshToken = $json_result->securityToken;
curl_close($ch);

//Access token
$header2 = array(
	'Authorization:YELLOWFIN ts='.$time.', nonce=123, token='.$refreshToken,
	'Accept:application/vnd.yellowfin.api-v2+json',
	'Content-Type:application/json'
);

$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_HTTPHEADER, $header2);
curl_setopt($ch2, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch2, CURLOPT_POSTFIELDS, '');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_URL, $url2);
curl_close($ch);
$result2 = curl_exec($ch2);
$json_result2 = json_decode($result2);
$accessToken=$json_result2->securityToken;

//Import contents
$text ='curl -X "POST" "http://localhost:8080/api/rpc/import-export/import-content" ';
$text = $text.'-H "Accept: application/vnd.yellowfin.api-v2+json" ';
$text = $text.'-H "Authorization: YELLOWFIN ts='.$time.', nonce=123, token='.$accessToken.'" ';
$text = $text.'-H "Content-Type: multipart/form-data" -H "cache-control: no-cache" ';
$text = $text.'--form "contentToProcess=@export.yfx;type=application/octet-stream" ';
$text = $text.'--form "importOptions=[{itemIndex: 0, optionKey: \'SKIP\', optionValue:\'TRUE\'},';
$text = $text.'{itemIndex: 1, optionKey: \'SOURCE\', optionValue:\'SOURCE100847\'}];';
$text = $text.'type=application/json"';
echo exec($text);
?>
```