/**
 * 
 */
package cn.strong.fastdfs.core;

import static cn.strong.fastdfs.model.StoragePath.fromFullPath;

import java.io.File;

import rx.Observable;

import cn.strong.fastdfs.client.Consts;
import cn.strong.fastdfs.ex.FastdfsException;
import cn.strong.fastdfs.model.Metadata;
import cn.strong.fastdfs.model.StoragePath;
import cn.strong.fastdfs.utils.RxIOUtils;

/**
 * 简单 FastDFS 客户端
 * <ul>
 * <li>使用同步方法，降低未学过 RxJava 的同学的学习曲线</li>
 * <li>存储路径使用全路径</li>
 * </ul>
 * 
 * @author liulongbiao
 *
 */
public class SimpleFastdfsClient {
	final FastdfsClient delegate;

	public SimpleFastdfsClient(FastdfsClient delegate) {
		this.delegate = delegate;
	}

	/**
	 * 等待单个结果的 Observable
	 * 
	 * @param observable
	 * @return
	 */
	private static <T> T await(Observable<T> observable) {
		try {
			return observable.toBlocking().single();
		} catch (Exception e) {
			throw new FastdfsException("get single result from observable error", e);
		}
	}

	/**
	 * 上传文件
	 * 
	 * @param bytes
	 *            文件内容
	 * @param ext
	 *            文件扩展名
	 * @return 服务器存储路径
	 */
	public String upload(byte[] bytes, String ext) {
		return upload(bytes, ext, null);
	}

	/**
	 * 上传文件
	 * 
	 * @param bytes
	 *            文件内容
	 * @param ext
	 *            文件扩展名
	 * @param group
	 *            文件分组
	 * @return 服务器存储路径
	 */
	public String upload(byte[] bytes, String ext, String group) {
		return await(delegate.upload(bytes, bytes.length, ext, group).map(StoragePath::getFullPath));
	}

	/**
	 * 上传本地文件
	 * 
	 * @param file
	 *            本地文件
	 * @return 服务器存储路径
	 */
	public String upload(File file) {
		return upload(file, null);
	}

	/**
	 * 上传本地文件
	 * 
	 * @param file
	 *            本地文件
	 * @param group
	 *            文件分组
	 * @return 服务器存储路径
	 */
	public String upload(File file, String group) {
		if (file == null || !file.exists()) {
			throw new FastdfsException("file does not exist.");
		}
		return await(delegate.upload(file, group).map(StoragePath::getFullPath));
	}

	/**
	 * 上传 Appender 文件
	 * 
	 * @param bytes
	 *            文件内容
	 * @param ext
	 *            文件扩展名
	 * @return 服务器存储路径
	 */
	public String uploadAppender(byte[] bytes, String ext) {
		return uploadAppender(bytes, ext, null);
	}

	/**
	 * 上传 Appender 文件
	 * 
	 * @param bytes
	 *            文件内容
	 * @param ext
	 *            文件扩展名
	 * @param group
	 *            文件分组
	 * @return 服务器存储路径
	 */
	public String uploadAppender(byte[] bytes, String ext, String group) {
		return await(delegate.uploadAppender(bytes, bytes.length, ext, group).map(
				StoragePath::getFullPath));
	}

	/**
	 * 上传本地文件为 appender 文件
	 * 
	 * @param file
	 *            本地文件
	 * @return 服务器存储路径
	 */
	public String uploadAppender(File file) {
		return uploadAppender(file, null);
	}

	/**
	 * 上传本地文件为 appender 文件
	 * 
	 * @param file
	 *            本地文件
	 * @param group
	 *            文件分组
	 * @return 服务器存储路径
	 */
	public String uploadAppender(File file, String group) {
		if (file == null || !file.exists()) {
			throw new FastdfsException("file does not exist.");
		}
		return await(delegate.uploadAppender(file, group).map(StoragePath::getFullPath));
	}

	/**
	 * 下载文件
	 * 
	 * @param path
	 *            服务器存储路径
	 * @return 文件内容
	 */
	public byte[] download(String path) {
		return await(RxIOUtils.toBytes(delegate.download(fromFullPath(path))));
	}

	/**
	 * 下载文件到指定文件中
	 * 
	 * @param path
	 *            服务器存储路径
	 * @param file
	 *            待写入的文件
	 */
	public void download(String path, File file) {
		await(RxIOUtils.write(delegate.download(fromFullPath(path)), file));
	}

	/**
	 * 删除文件
	 * 
	 * @param path
	 *            服务器存储路径
	 */
	public void delete(String path) {
		await(delegate.delete(fromFullPath(path)));
	}

	/**
	 * 追加文件内容
	 * 
	 * @param path
	 *            服务器存储路径
	 * @param bytes
	 *            追加内容
	 */
	public void append(String path, byte[] bytes) {
		await(delegate.append(fromFullPath(path), bytes));
	}

	/**
	 * 修改文件内容
	 * 
	 * @param path
	 *            服务器存储路径
	 * @param offset
	 *            修改起始偏移量
	 * @param bytes
	 *            修改内容
	 */
	public void modify(String path, int offset, byte[] bytes) {
		await(delegate.modify(fromFullPath(path), offset, bytes));
	}

	/**
	 * 截取文件内容
	 * 
	 * @param path
	 *            服务器存储路径
	 */
	public void truncate(String path) {
		truncate(path, 0);
	}

	/**
	 * 截取文件内容
	 * 
	 * @param path
	 *            服务器存储路径
	 * @param truncatedSize
	 *            截取字节数
	 */
	public void truncate(String path, int truncatedSize) {
		await(delegate.truncate(fromFullPath(path), truncatedSize));
	}

	/**
	 * 设置文件元数据
	 * 
	 * @param path
	 *            服务器存储路径
	 * @param metadata
	 *            元数据
	 */
	public void setMetadata(String path, Metadata metadata) {
		setMetadata(path, metadata, Consts.STORAGE_SET_METADATA_FLAG_OVERWRITE);
	}

	/**
	 * 设置文件元数据
	 * 
	 * @param path
	 *            服务器存储路径
	 * @param metadata
	 *            元数据
	 * @param flag
	 *            设置标识
	 */
	public void setMetadata(String path, Metadata metadata, byte flag) {
		await(delegate.setMetadata(fromFullPath(path), metadata, flag));
	}

	/**
	 * 获取文件元数据
	 * 
	 * @param path
	 * @return
	 */
	public Metadata getMetadata(String path) {
		return await(delegate.getMetadata(fromFullPath(path)));
	}
}

@@ -3453,22 +3453,16 @@
 le) %7B%0A%09%09
-await(
 RxIOUtil
@@ -3513,16 +3513,39 @@
 ), file)
+.toCompletable().await(
 );%0A%09%7D%0A%0A%09

修改 download 实现