Apex Wrapper Salesforce Metadata API Part 1

\:cloud: Metadata API

以下の日本語訳です。少々長いので分けています。

https://github.com/financialforcedev/apex-mdapi

#Documentation
このREADMEのドキュメントに加えて、次のブログでもライブラリについて説明しています。

 + [Apex Wrapper SalesforceメタデータAPI（apex-mdapi）での指定ログイン情報の使用](https://qiita.com/Keiji_otsubo/items/43f633ae40495cf1e984)
 + [ApexメタデータAPIを使用したフロー画面の作成の自動化](http://andyinthecloud.com/2015/11/28/automating-the-creation-of-flow-screens-with-apex-metadata-api/)
 + [Apex Metadata API Q&A](http://andyinthecloud.com/2014/11/22/apex-metadata-api-qa/)
 + [Summer’14向けに合理化および簡素化されたApexメタデータAPI](http://andyinthecloud.com/2014/08/14/apex-metadata-api-streamlined-and-simplified-for-summer14/)
 + [インストール後のApexメタデータAPI構成が解決しました！](http://andyinthecloud.com/2014/07/29/post-install-apex-metadata-api-configuration-solved/)
 + [ApexメタデータAPIとSpring’14：王国への鍵！](http://andyinthecloud.com/2014/04/24/apex-metadata-api-and-spring14-keys-to-the-kingdom/)
 + [ApexからメタデータAPIを呼び出す方法の概要。](http://andyinthecloud.com/2013/10/27/introduction-to-calling-the-metadata-api-from-apex/)
 + [Spring’14プレリリース：Apexのレイアウトの更新](http://andyinthecloud.com/category/metadata-api/)
 + [「ほら、手を使わないで！」 ：パッケージのインストールとアンインストールの自動化！](http://andyinthecloud.com/2013/06/23/look-ma-no-hands-automating-install-and-uninstall-of-packages/)
 + [ApexメタデータAPIとバッチApexサポートのスクリプト](http://andyinthecloud.com/2013/05/06/scripting-the-apex-metadata-api-and-batch-apex-support/)
 + [ApexメタデータAPISpring’13アップデート：組織設定アクセス](http://andyinthecloud.com/2013/03/10/apex-metadata-api-spring13-update-org-settings-access/)
 

このAPIは、標準ドキュメントに記載されているAPIタイプと操作を可能な限り反映しています。提供される動作と機能は、特定の操作を介して使用およびアクセスできるメタデータに関して、Salesforceのドキュメントで説明されているとおりです。

+ Salesforce Metadata API Developers Guide

#Showcase

この新しいセクションは、人々がこのライブラリを使用して構築しているクールなツールとアプリケーションを紹介することを目的としています。ここであなたの名前と作成をライトで希望する場合は、詳細についてGitHubの問題を提起してください。喜んで紹介します！

![image.png](https://raw.githubusercontent.com/financialforcedev/apex-mdapi/master/images/showcase-layouteditingviamdapi.png)

Layout Editing Tool by [BoonPlus](https://github.com/BoonPlus)

#Background and Motivation
プラットフォームの宣言型の性質を取り入れたソリューションや便利なユーティリティを開発したいと考えるApex開発者が増えているようです。そのことについてはFinancialForce.comにあるものを含めてください！このようなソリューションは、管理者が作成する必要のあるカスタムフィールドやオブジェクト、および/または既存のパッケージ内のオブジェクトへのカスタマイズに動的に適応しています。


管理者がこれらのソリューションをますます活用するにつれて、自動化のトピックが発生します。これらのソリューションの開発者は、管理者に手動で作成してからソリューションに参照するように依頼することなく、ウィザードを実装したり、ソリューションを自己構成したりすることで、管理者を支援できますか？

#Apexから呼び出すための概要

Salesforceは、開発者がオフプラットフォームとオンプラットフォームの両方で（Apex開発者として）使用できる多数のAPIを提供します。プラットフォームから離れていて（Herokuなど）、管理の自動化に役立つコードを開発している場合。次に、SalesforceメタデータAPI（Salesforce WebServiceコネクタ経由）を利用してこれを支援できます。これは、オブジェクト、フィールド、ページ、およびその他の多くのコンポーネントタイプを作成するための堅牢ですぐに利用できるAPIです。


SalesforceはプラットフォームApex開発者にApexDescribeを介してこの情報の一部（メタデータAPIカバレッジのサブセット）をクエリする手段を提供しますが、Apexからこのメタデータをネイティブに操作する手段はまだ提供していません。これはパイプラインにあると言われていますが、これがいつ到着するかは個人的にはわかりません。

読み進める前に、[このアイデア](https://success.salesforce.com/ideaView?id=08730000000l4TkAAI)に投票し、ネイティブメタデータAPIを入手してください。

では、その間にApex開発者として何ができるでしょうか。 Apexは、Webサービスや最近ではRESTベースのAPIへのアウトバウンド呼び出しを行うのに非常に優れていることがわかりました。これは、いつものように、少数のガバナーが知っておく必要があります。では、なぜApexはMetadata Web ServicesAPIを呼び出せないのでしょうか。結局のところ、そのためのWSDLがあり、Apex開発者としてWSDLをApexにインポートし、それが生成するコードを使用して呼び出しを行うことができます...

#Examples
以下は、[MetadataServiceExamples.cls](https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataServiceExamples.cls)を使った例です。

```
public static void createObject()
	{
		MetadataService.MetadataPort service = createService();		
		MetadataService.CustomObject customObject = new MetadataService.CustomObject();
		customObject.fullName = 'Test__c';
		customObject.label = 'Test';
		customObject.pluralLabel = 'Tests';
		customObject.nameField = new MetadataService.CustomField();
		customObject.nameField.type_x = 'Text';
		customObject.nameField.label = 'Test Record';
		customObject.deploymentStatus = 'Deployed';
		customObject.sharingModel = 'ReadWrite';
		List<MetadataService.SaveResult> results = 		
			service.createMetadata(
				new MetadataService.Metadata[] { customObject });		
		handleSaveResults(results[0]);
	}
	
	public static void createField()
	{
		MetadataService.MetadataPort service = createService();		
		MetadataService.CustomField customField = new MetadataService.CustomField();
		customField.fullName = 'Test__c.TestField__c';
		customField.label = 'Test Field';
		customField.type_x = 'Text';
		customField.length = 42;
		List<MetadataService.SaveResult> results = 		
			service.createMetadata(
				new MetadataService.Metadata[] { customField });				
		handleSaveResults(results[0]);
	}

	public static void createPage()
	{
		MetadataService.MetadataPort service = createService();		
		MetadataService.ApexPage apexPage = new MetadataService.ApexPage();
		apexPage.apiVersion = 25;
		apexPage.fullName = 'test';
		apexPage.label = 'Test Page';
		apexPage.content = EncodingUtil.base64Encode(Blob.valueOf('<apex:page/>'));
		List<MetadataService.SaveResult> results = 		
			service.createMetadata(
				new MetadataService.Metadata[] { apexPage });				
		handleSaveResults(results[0]);
	}

	public static void listMetadata()
	{
		MetadataService.MetadataPort service = createService();		
		List<MetadataService.ListMetadataQuery> queries = new List<MetadataService.ListMetadataQuery>();		
		MetadataService.ListMetadataQuery queryWorkflow = new MetadataService.ListMetadataQuery();
		queryWorkflow.type_x = 'Workflow';
		queries.add(queryWorkflow);		
		MetadataService.ListMetadataQuery queryValidationRule = new MetadataService.ListMetadataQuery();
		queryValidationRule.type_x = 'ValidationRule';
		queries.add(queryValidationRule);		
		MetadataService.FileProperties[] fileProperties = service.listMetadata(queries, 25);
		for(MetadataService.FileProperties fileProperty : fileProperties)
			System.debug(fileProperty.fullName);
	}
	
	public static MetadataService.MetadataPort createService()
	{ 
		MetadataService.MetadataPort service = new MetadataService.MetadataPort();
		service.SessionHeader = new MetadataService.SessionHeader_element();
		service.SessionHeader.sessionId = UserInfo.getSessionId();
		return service;		
	}
```

更なる詳細は[こちら](https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataServiceExamples.cls)

#Community Examples

+ 選択リスト値の更新に関連する例を提出してくれた[mohit-address](https://github.com/mohit-address)に感謝します。
+ [レポートの複製作成](https://github.com/financialforcedev/apex-mdapi/issues/147)に関連する優れた例を提出してくれた[KGFTW](https://github.com/KGFTW)に感謝します。

Report Cloning with Apex Metadata API

```
/**
	 * Method cloneReport(String sFolderApiName, String sReportApiName, String tFolderApiName, String tReportApiName)
	 * @param sFolderApiName: api name of the (source) folder of the report to clone
	 * @param sReportApiName: api name of the (source) report to clone
	 * @param tFolderApiName: api name of the (target) folder to create the cloned report in
	 * @param tReportApiName: api name of the (target) cloned report 
	 */
	public static void cloneReport(String sFolderApiName, String sReportApiName, String tFolderApiName, String tReportApiName) {
	    MetadataService.MetadataPort service = new MetadataService.MetadataPort();
	    service.SessionHeader = new MetadataService.SessionHeader_element();
	    service.SessionHeader.sessionId = UserInfo.getSessionId();
	
	    // Get the report to clone
	    MetadataService.Report reportToClone = (MetadataService.Report) service.readMetadata('Report', new String[] { sFolderApiName+'/'+sReportApiName }).getRecords()[0];
	
	    // Instanciate a new one to attribute the same metadata from the report to clone
	    MetadataService.Report apexReport = new MetadataService.Report();
	    // Set the cloned report properties from parameters and the source report
	    apexReport.name = reportToClone.name + ' Clone';
	    apexReport.fullName = tFolderApiName + '/' + tReportApiName;
	    apexReport.reportType = reportToClone.reportType;
	    apexReport.description = reportToClone.description;
	    apexReport.format = reportToClone.format;
	    apexReport.filter = reportToClone.filter;
	    apexReport.showDetails = reportToClone.showDetails;
	    apexReport.sortColumn = reportToClone.sortColumn;
	    apexReport.sortOrder = reportToClone.sortOrder;
	    apexReport.groupingsAcross = reportToClone.groupingsAcross;
	    apexReport.groupingsDown = reportToClone.groupingsDown;
	    apexReport.chart = reportToClone.chart;
	    apexReport.timeFrameFilter = reportToClone.timeFrameFilter;
	    apexReport.columns = reportToClone.columns;
	
	    // Create the report clone
	    List<MetadataService.SaveResult> results = service.createMetadata(new MetadataService.Metadata[] { apexReport });
	
	    // Handle results
	    handleSaveResults(results[0]);
	}
You can use the report clone example like this...

MetadataServiceExamples.cloneReport('Source_Folder_Api_Name','Source_Report_Api_Name','Target_Folder_Api_Name','Tar
```