/* ThetaFileProfile Copyright (c) 2015 NTT DOCOMO,INC. Released under the MIT license http://opensource.org/licenses/mit-license.php */ package org.deviceconnect.android.deviceplugin.theta.profile; import android.content.Intent; import android.os.Bundle; import org.deviceconnect.android.deviceplugin.theta.core.ThetaDeviceClient; import org.deviceconnect.android.deviceplugin.theta.core.ThetaDeviceException; import org.deviceconnect.android.deviceplugin.theta.core.ThetaObject; import org.deviceconnect.android.message.MessageUtils; import org.deviceconnect.android.profile.FileProfile; import org.deviceconnect.android.profile.api.DConnectApi; import org.deviceconnect.android.profile.api.DeleteApi; import org.deviceconnect.android.profile.api.GetApi; import org.deviceconnect.android.provider.FileManager; import org.deviceconnect.message.DConnectMessage; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.List; /** * Theta File Profile. * * @author NTT DOCOMO, INC. */ public class ThetaFileProfile extends FileProfile { private final ThetaDeviceClient mClient; private final DConnectApi mGetReceiveApi = new GetApi() { @Override public boolean onRequest(final Intent request, final Intent response) { final String serviceId = getServiceID(request); String path = getPath(request); if (!path.startsWith("/")) { path = "/" + path; } String[] components = path.split("/"); if (components.length == 2) { final String fileName = components[1]; getFileManager().checkWritePermission(new FileManager.CheckPermissionCallback() { @Override public void onSuccess() { mClient.fetchObject(serviceId, fileName, new ThetaDeviceClient.DefaultListener() { @Override public void onObjectFetched(final byte[] data, final String mimeType) { try { setResult(response, DConnectMessage.RESULT_OK); setMIMEType(response, mimeType); setURI(response, fileName, data); } catch (IOException e) { MessageUtils.setIllegalDeviceStateError(response, e.getMessage()); } sendResponse(response); } @Override public void onFailed(final ThetaDeviceException cause) { MessageUtils.setIllegalDeviceStateError(response, cause.getMessage()); sendResponse(response); } }); } @Override public void onFail() { MessageUtils.setIllegalServerStateError(response, "Permission WRITE_EXTERNAL_STORAGE not granted."); sendResponse(response); } }); return false; } else { MessageUtils.setInvalidRequestParameterError(response, "File not found: " + path); return true; } } }; private final DConnectApi mGetListApi = new GetApi() { @Override public String getAttribute() { return ATTRIBUTE_LIST; } @Override public boolean onRequest(final Intent request, final Intent response) { return getFileList(request, response); } }; private final DConnectApi mGetDirectoryApi = new GetApi() { @Override public String getAttribute() { return "directory"; } @Override public boolean onRequest(final Intent request, final Intent response) { return getFileList(request, response); } }; private boolean getFileList(Intent request, final Intent response) { final String serviceId = getServiceID(request); final String path = getPath(request); final String order = getOrder(request); final Integer limit = getLimit(request); final Integer offset = getOffset(request); final String sortDirection; final String sortTargetParam; if (path != null && !path.equals("/")) { MessageUtils.setInvalidRequestParameterError(response, "the specified directory is not found."); return true; } if (order != null) { String[] conditions = order.split(","); if (conditions.length != 2) { MessageUtils.setInvalidRequestParameterError(response, "order is invalid."); return true; } sortTargetParam = conditions[0]; sortDirection = conditions[1]; if (!sortTargetParam.equals(PARAM_PATH) && !sortTargetParam.equals(PARAM_FILE_NAME) && !sortTargetParam.equals(PARAM_MIME_TYPE) && !sortTargetParam.equals(PARAM_UPDATE_DATE) && !sortTargetParam.equals(PARAM_FILE_SIZE) && !sortTargetParam.equals(PARAM_FILE_TYPE)) { MessageUtils.setInvalidRequestParameterError(response, "target parameter name is invalid."); return true; } if (!sortDirection.equals(Order.ASC.getValue()) && !sortDirection.equals(Order.DSEC.getValue())) { MessageUtils.setInvalidRequestParameterError(response, "direction of order is invalid."); return true; } } else { sortDirection = null; sortTargetParam = null; } mClient.fetchAllObjectList(serviceId, new ThetaDeviceClient.DefaultListener() { @Override public void onObjectList(final List<ThetaObject> objList) { int start = offset != null ? offset : 0; if (start >= objList.size()) { MessageUtils.setInvalidRequestParameterError(response, "offset is too large."); sendResponse(response); return; } List<ThetaObject> list = sortObjectList(sortTargetParam, sortDirection, objList); int end = limit != null ? start + limit : list.size(); if (end > list.size()) { end = list.size(); } list = (start < end) ? list.subList(start, end) : new LinkedList<ThetaObject>(); List<Bundle> file = new ArrayList<Bundle>(); for (ThetaObject obj : list) { Bundle b = new Bundle(); setPath(b, "/" + obj.getFileName()); setMIMEType(b, obj.getMimeType()); setFileName(b, obj.getFileName()); setUpdateDate(b, obj.getCreationTime()); //setFileSize(b, obj.mSize); // TODO file.add(b); } setFiles(response, file); setResult(response, DConnectMessage.RESULT_OK); sendResponse(response); } @Override public void onFailed(final ThetaDeviceException cause) { switch (cause.getReason()) { case ThetaDeviceException.NOT_FOUND_THETA: MessageUtils.setNotFoundServiceError(response); break; default: MessageUtils.setIllegalDeviceStateError(response, cause.getMessage()); break; } sendResponse(response); } }); return false; } private final DConnectApi mDeleteRemoveApi = new DeleteApi() { @Override public boolean onRequest(final Intent request, final Intent response) { final String serviceId = getServiceID(request); String path = getPath(request); if (!path.startsWith("/")) { path = "/" + path; } String[] components = path.split("/"); if (components.length == 2) { final String fileName = components[1]; final String removePath = path; getFileManager().checkWritePermission(new FileManager.CheckPermissionCallback() { @Override public void onSuccess() { mClient.removeObject(serviceId, fileName, new ThetaDeviceClient.DefaultListener() { @Override public void onObjectRemoved() { setResult(response, DConnectMessage.RESULT_OK); sendResponse(response); } @Override public void onFailed(final ThetaDeviceException cause) { switch (cause.getReason()) { case ThetaDeviceException.NOT_FOUND_THETA: MessageUtils.setNotFoundServiceError(response); break; case ThetaDeviceException.NOT_FOUND_OBJECT: MessageUtils.setInvalidRequestParameterError(response, "File not found: " + removePath); break; default: MessageUtils.setIllegalDeviceStateError(response, cause.getMessage()); break; } sendResponse(response); } }); } @Override public void onFail() { MessageUtils.setIllegalServerStateError(response, "Permission WRITE_EXTERNAL_STORAGE not granted."); sendResponse(response); } }); return false; } else { MessageUtils.setInvalidRequestParameterError(response, "File not found: " + path); return true; } } }; /** * Constructor. * * @param client an instance of {@link ThetaDeviceClient} * @param fileMgr an instance of {@link FileManager} */ public ThetaFileProfile(final ThetaDeviceClient client, final FileManager fileMgr) { super(fileMgr); mClient = client; addApi(mGetReceiveApi); addApi(mGetListApi); addApi(mDeleteRemoveApi); addApi(mGetDirectoryApi); } private List<ThetaObject> sortObjectList(final String targetParam, final String direction, final List<ThetaObject> list) { boolean isAsc = true; if (direction != null) { isAsc = direction.equals(Order.ASC.getValue()); } Comparator<ThetaObject> comparator = null; if (PARAM_PATH.equals(targetParam)) { comparator = new Comparator<ThetaObject>() { public int compare(final ThetaObject f1, final ThetaObject f2) { return f1.getFileName().compareTo(f2.getFileName()); } }; } else if (PARAM_MIME_TYPE.equals(targetParam)) { comparator = new Comparator<ThetaObject>() { public int compare(final ThetaObject f1, final ThetaObject f2) { return f1.getMimeType().compareTo(f2.getMimeType()); } }; } else if (PARAM_FILE_NAME.equals(targetParam)) { comparator = new Comparator<ThetaObject>() { public int compare(final ThetaObject f1, final ThetaObject f2) { return f1.getFileName().compareTo(f2.getFileName()); } }; } else if (PARAM_UPDATE_DATE.equals(targetParam)) { comparator = new Comparator<ThetaObject>() { public int compare(final ThetaObject f1, final ThetaObject f2) { long t1 = f1.getCreationTimeWithUnixTime(); long t2 = f2.getCreationTimeWithUnixTime(); return (t1 < t2) ? -1 : (t1 == t2) ? 0 : -1; } }; } else if (PARAM_FILE_SIZE.equals(targetParam)) { comparator = new Comparator<ThetaObject>() { public int compare(final ThetaObject f1, final ThetaObject f2) { return 0; //(f1.mSize - f2.mSize); // TODO } }; } // NOTE: It is not necessary to implement sorting by file type because the feature // to create any directories in the storage of THETA is not provided. if (comparator != null) { Collections.sort(list, comparator); } if (!isAsc) { Collections.reverse(list); } return list; } }