2010年11月21日日曜日

Evernote API を使ってみる (5) リソースつきノート作成

画像やPDFといったノートの添付ファイルは「リソース」として扱う。リソースはノートに紐づくもので、単体で作成したり削除したりすることはできない(取得とメタデータの更新はできる)。リソースの扱いは(バイナリデータという性質上)他のタイプに比べるとかなり面倒。

リソースつきのノートを作成するには、以下の手順になる。

  1. 新規ノートを作成
  2. 新規リソースを作成
    -バイナリデータを設定
    -MIMEタイプを設定
    -必要ならファイル名など属性(メタデータ)を設定
  3. ノートにリソースを追加
  4. ノートのコンテンツにリソースを参照するためのen-mediaタグを追加
    -参照にはデータのハッシュ(MD5チェックサム)を使う。
  5. サービスのcreateNote()メソッドをコール
既存のノートにリソースを追加したり、削除したりするには、ノートが持っているリソースリストを変更したうえでupdateNote()をコールする。

リソースを取得するには、ノートからたどることも、リソース単体で取得することもできる。単体で取得するには、直接GUIDを指定する(そもそもリソースのGUIDなんかとってくるのが面倒><)か、ノートのGUID&リソースデータのハッシュ値を指定して取得する。ノートやリソースを取得する getNote() や getResource() には、バイナリデータやリソースの属性などを取得するかどうかのフラグがあって、必要なときだけ true を指定させるようになっている。必要ないものは全部 false にしておく。

リソースとリソースつきノートを操作するテストプログラムがこちら。
  1. public class ResourceTest {  
  2.   
  3.     private static String consumerKey = "consumer key";  
  4.     private static String consumerSecret = "consumer secret";  
  5.     private static String evernoteHost = "sandbox.evernote.com";  
  6.     private static String userName = "user name";  
  7.     private static String password = "password";  
  8.   
  9.     private static NoteStore.Client setupNoteStore(String evernoteHost, User user) throws TException {  
  10.         // NoteStore クライアントのセットアップ  
  11.         String noteStoreUrl = "https://" + evernoteHost + "/edam/note/" + user.getShardId();  
  12.         THttpClient trans = new THttpClient(noteStoreUrl);  
  13.         TBinaryProtocol prot = new TBinaryProtocol(trans);  
  14.         NoteStore.Client noteStore = new NoteStore.Client(prot, prot);  
  15.         return noteStore;  
  16.     }  
  17.   
  18.     // ファイルからバイナリストリームを読み込んでデータオブジェクトを作成するメソッド  
  19.     // 付属のサンプルコードからコピペしたもの  
  20.     private static Data readFileAsData(String fileName) throws Exception {  
  21.         FileInputStream in = new FileInputStream(fileName);  
  22.         ByteArrayOutputStream byteOut = new ByteArrayOutputStream();  
  23.         byte[] block = new byte[10240];  
  24.         int len;  
  25.         while ((len = in.read(block)) >= 0) {  
  26.             byteOut.write(block, 0, len);  
  27.         }  
  28.         in.close();  
  29.         byte[] body = byteOut.toByteArray();  
  30.         Data data = new Data();  
  31.         data.setSize(body.length);  
  32.         data.setBodyHash(MessageDigest.getInstance("MD5").digest(body));  
  33.         data.setBody(body);  
  34.         return data;  
  35.     }  
  36.   
  37.     // ハッシュ値(バイナリ配列)を文字列に変換するメソッド  
  38.     // 付属のサンプルコードからコピペしたもの  
  39.     public static String bytesToHex(byte[] bytes) {  
  40.         StringBuilder sb = new StringBuilder();  
  41.         for (byte hashByte : bytes) {  
  42.             int intVal = 0xff & hashByte;  
  43.             if (intVal < 0x10) {  
  44.                 sb.append('0');  
  45.             }  
  46.             sb.append(Integer.toHexString(intVal));  
  47.         }  
  48.         return sb.toString();  
  49.     }  
  50.       
  51.     public static void main(String[] args) {  
  52.         UserStore.Client userStore = null;  
  53.         NoteStore.Client noteStore = null;  
  54.         AuthenticationResult authResult = null;  
  55.         try {  
  56.             userStore = AuthUtil.setupUserStore(evernoteHost);  
  57.             authResult = AuthUtil.authenticate(userStore, consumerKey, consumerSecret, evernoteHost, userName, password);  
  58.             User user = authResult.getUser();  
  59.             String authToken = authResult.getAuthenticationToken();  
  60.               
  61.             noteStore = setupNoteStore(evernoteHost, user);  
  62.               
  63.             Notebook notebook = noteStore.getDefaultNotebook(authToken);  
  64.               
  65.             // リソースつき新規ノート作成  
  66.             System.out.println("** CREATE NOTE WITH RESOURCES **");  
  67.             Note note = new Note();  
  68.             note.setNotebookGuid(notebook.getGuid());  
  69.             note.setTitle("Testnote with Resources - " + new Date().getTime());  
  70.               
  71.             // リソース作成  
  72.             Resource resource1 = new Resource();  
  73.             resource1.setData(readFileAsData("image/neko.jpg")); // バイナリデータ  
  74.             resource1.setMime("image/jpeg"); // MIMEタイプ  
  75.             ResourceAttributes atts1 = new ResourceAttributes(); // リソースの属性  
  76.             atts1.setFileName("neko.jpg");  
  77.             resource1.setAttributes(atts1);  
  78.             note.addToResources(resource1); // ノートにリソースを追加  
  79.             String hashHex1 = bytesToHex(resource1.getData().getBodyHash()); // リソースのハッシュ値(MD5チェックサム)  
  80.               
  81.             Resource resource2 = new Resource();  
  82.             resource2.setData(readFileAsData("image/tori.jpg"));  
  83.             resource2.setMime("image/jpeg");  
  84.             ResourceAttributes atts2 = new ResourceAttributes();  
  85.             atts2.setFileName("tori.jpg");  
  86.             resource2.setAttributes(atts2);  
  87.             note.addToResources(resource2);  
  88.             String hashHex2 = bytesToHex(resource2.getData().getBodyHash());  
  89.             // ノートのコンテンツ。en-mediaタグにリソースのハッシュ値、MIMEタイプを入れる。  
  90.             String content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"  
  91.                 + "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml.dtd\">"  
  92.                 + "<en-note>Pictures:  
  93. "  
  94.                 + "<en-media type=\"image/jpeg\" hash=\"" + hashHex1 + "\"/>  
  95. "  
  96.                 + "<en-media type=\"image/jpeg\" hash=\"" + hashHex2 + "\"/>"  
  97.                 + "</en-note>";  
  98.             note.setContent(content);  
  99.               
  100.             Note created = noteStore.createNote(authToken, note);  
  101.             System.out.println("ノート\"" + created.getTitle() + "\"を作成しました。");  
  102.             System.out.println("ノート\"" + created.getTitle() + "\"のリソース数: " + created.getResourcesSize());  
  103.             for (Resource resource : created.getResources()) {  
  104.                 System.out.print(" - " + resource.getAttributes().getFileName());  
  105.                 System.out.println(" (guid=" + resource.getGuid() + ")");  
  106.             }  
  107.               
  108.             // リソースを追加してノートを更新  
  109.             System.out.println("** ADD RESOURCE **");  
  110.             Resource resource3 = new Resource();  
  111.             resource3.setData(readFileAsData("image/inu.jpg"));  
  112.             resource3.setMime("image/jpeg");  
  113.             ResourceAttributes atts3 = new ResourceAttributes();  
  114.             atts3.setFileName("inu.jpg");  
  115.             resource3.setAttributes(atts3);  
  116.             created.addToResources(resource3);  
  117.             String hashHex3 = bytesToHex(resource3.getData().getBodyHash());  
  118.             String content_update1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"  
  119.                 + "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml.dtd\">"  
  120.                 + "<en-note>Pictures:  
  121. "  
  122.                 + "<en-media type=\"image/jpeg\" hash=\"" + hashHex1 + "\"/>  
  123. "  
  124.                 + "<en-media type=\"image/jpeg\" hash=\"" + hashHex2 + "\"/>  
  125. "  
  126.                 + "<en-media type=\"image/jpeg\" hash=\"" + hashHex3 + "\"/>"  
  127.                 + "</en-note>";  
  128.             created.setContent(content_update1);  
  129.             Note updated1 = noteStore.updateNote(authToken, created);  
  130.             System.out.println("ノート\"" + updated1.getTitle() + "\"を更新しました。");  
  131.             System.out.println("ノート\"" + updated1.getTitle() + "\"のリソース数: " + updated1.getResourcesSize());  
  132.             for (Resource resource : updated1.getResources()) {  
  133.                 System.out.print(" - " + resource.getAttributes().getFileName());  
  134.                 System.out.println(" (guid=" + resource.getGuid() + ")");  
  135.             }  
  136.   
  137.             // リソースを削除してノートを更新  
  138.             System.out.println("** REMOVE RESOURCE **");  
  139.             Iterator<Resource> it = updated1.getResourcesIterator();  
  140.             while(it.hasNext()) {  
  141.                 Resource r = it.next();  
  142.                 if (bytesToHex(r.getData().getBodyHash()).equals(hashHex1)) {  
  143.                     it.remove();  
  144.                 }  
  145.             }  
  146.             String content_update2 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"  
  147.                 + "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml.dtd\">"  
  148.                 + "<en-note>Pictures:  
  149. "  
  150.                 + "<en-media type=\"image/jpeg\" hash=\"" + hashHex2 + "\"/>  
  151. "  
  152.                 + "<en-media type=\"image/jpeg\" hash=\"" + hashHex3 + "\"/>"  
  153.                 + "</en-note>";  
  154.             updated1.setContent(content_update2);  
  155.             Note updated2 = noteStore.updateNote(authToken, updated1);  
  156.             System.out.println("ノート\"" + updated2.getTitle() + "\"を更新しました。");  
  157.             System.out.println("ノート\"" + updated2.getTitle() + "\"のリソース数: " + updated2.getResourcesSize());  
  158.             for (Resource resource : updated2.getResources()) {  
  159.                 System.out.print(" - " + resource.getAttributes().getFileName());  
  160.                 System.out.println(" (guid=" + resource.getGuid() + ")");  
  161.             }  
  162.               
  163.             // リソースをGUIDで指定して取得  
  164.             System.out.println("** GET RESOURCE BY ID **");  
  165.             String guid = updated2.getResources().get(0).getGuid();  
  166.             Resource r = noteStore.getResource(authToken, guid, falsefalsetruefalse);  
  167.             System.out.println("リソース\"" + r.getAttributes().getFileName() + "\"を取得しました。(guid=" + r.getGuid() + ")");  
  168.   
  169.             // リソースをノートGUIDとハッシュ値で指定して取得  
  170.             System.out.println("** GET RESOURCE BY NOTE ID AND HASH **");  
  171.             byte[] hash = updated2.getResources().get(0).getData().getBodyHash();  
  172.             Resource r2 = noteStore.getResourceByHash(authToken, updated2.getGuid(), hash, falsefalsefalse);  
  173.             System.out.println("リソース\"" + r2.getAttributes().getFileName() + "\"を取得しました。(guid=" + r2.getGuid() + ")");  
  174.   
  175.             // リソースを更新(メタデータのみ可)  
  176.             System.out.println("** UPDATE RESORCE **");  
  177.             String fileName = r2.getAttributes().getFileName();  
  178.             r2.getAttributes().setFileName("update_" + fileName);  
  179.             noteStore.updateResource(authToken, r2);  
  180.             Resource r2_updated = noteStore.getResource(authToken, r2.getGuid(), falsefalsetruefalse);  
  181.             System.out.println("リソース\"" + r2_updated.getAttributes().getFileName() + "\"が更新されました。(guid=" + r2_updated.getGuid() + ")");  
  182.         } catch (Exception e) {  
  183.             e.printStackTrace();  
  184.         }  
  185.   
  186.     }  
  187.   
  188. }  

実行例。
** CREATE NOTE WITH RESOURCES **
ノート"Testnote with Resources - 1290298760809"を作成しました。
ノート"Testnote with Resources - 1290298760809"のリソース数: 2
 - tori.jpg (guid=f2f0d0d6-3a5e-4007-867d-2bafccf4bcec)
 - neko.jpg (guid=c800bf58-0ee4-47b0-bc4b-a8556ea2b830)
** ADD RESOURCE **
ノート"Testnote with Resources - 1290298760809"を更新しました。
ノート"Testnote with Resources - 1290298760809"のリソース数: 3
 - tori.jpg (guid=f2f0d0d6-3a5e-4007-867d-2bafccf4bcec)
 - neko.jpg (guid=c800bf58-0ee4-47b0-bc4b-a8556ea2b830)
 - inu.jpg (guid=96815797-6ee6-4694-a784-6c81c9eaeb10)
** REMOVE RESOURCE **
ノート"Testnote with Resources - 1290298760809"を更新しました。
ノート"Testnote with Resources - 1290298760809"のリソース数: 2
 - tori.jpg (guid=f2f0d0d6-3a5e-4007-867d-2bafccf4bcec)
 - inu.jpg (guid=96815797-6ee6-4694-a784-6c81c9eaeb10)
** GET RESOURCE BY ID **
リソース"tori.jpg"を取得しました。(guid=f2f0d0d6-3a5e-4007-867d-2bafccf4bcec)
** GET RESOURCE BY NOTE ID AND HASH **
リソース"tori.jpg"を取得しました。(guid=f2f0d0d6-3a5e-4007-867d-2bafccf4bcec)
** UPDATE RESORCE **
リソース"update_tori.jpg"が更新されました。(guid=f2f0d0d6-3a5e-4007-867d-2bafccf4bcec)

0 件のコメント:

コメントを投稿