commit
788c1398e0
@ -1,77 +0,0 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core; |
||||
|
||||
import com.arialyy.aria.orm.DbEntity; |
||||
|
||||
/** |
||||
* Created by Aria.Lao on 2017/8/29. |
||||
* 错误实体 |
||||
*/ |
||||
public class ErrorEntity extends DbEntity { |
||||
|
||||
/** |
||||
* 插入时间 |
||||
*/ |
||||
public long insertTime; |
||||
|
||||
/** |
||||
* 错误信息 |
||||
*/ |
||||
public String err; |
||||
|
||||
/** |
||||
* 任务名 |
||||
*/ |
||||
public String taskName; |
||||
|
||||
/** |
||||
*任务类型 |
||||
*/ |
||||
public String taskType; |
||||
|
||||
/** |
||||
* 提示 |
||||
*/ |
||||
public String msg; |
||||
|
||||
/** |
||||
* 任务key |
||||
*/ |
||||
public String key; |
||||
|
||||
@Override public String toString() { |
||||
return "ErrorEntity{" |
||||
+ "insertTime=" |
||||
+ insertTime |
||||
+ ", err='" |
||||
+ err |
||||
+ '\'' |
||||
+ ", taskName='" |
||||
+ taskName |
||||
+ '\'' |
||||
+ ", taskType='" |
||||
+ taskType |
||||
+ '\'' |
||||
+ ", msg='" |
||||
+ msg |
||||
+ '\'' |
||||
+ ", key='" |
||||
+ key |
||||
+ '\'' |
||||
+ '}'; |
||||
} |
||||
} |
@ -0,0 +1,31 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.common; |
||||
|
||||
/** |
||||
* Created by AriaL on 2018/3/3. |
||||
* 获取文件信息完成后 回调给下载线程的信息 |
||||
*/ |
||||
public class CompleteInfo { |
||||
/** |
||||
* 自定义的状态码 |
||||
*/ |
||||
public int code; |
||||
|
||||
public CompleteInfo(int code) { |
||||
this.code = code; |
||||
} |
||||
} |
@ -0,0 +1,66 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.delegate; |
||||
|
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.core.inf.AbsEntity; |
||||
import com.arialyy.aria.core.inf.AbsTaskEntity; |
||||
import com.arialyy.aria.core.inf.IFtpTarget; |
||||
import com.arialyy.aria.core.inf.ITarget; |
||||
import com.arialyy.aria.util.ALog; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/9. |
||||
* ftp 委托 |
||||
*/ |
||||
public class FtpDelegate<TARGET extends ITarget, ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>> |
||||
implements IFtpTarget<TARGET> { |
||||
private static final String TAG = "FtpDelegate"; |
||||
private ENTITY mEntity; |
||||
private TASK_ENTITY mTaskEntity; |
||||
private TARGET mTarget; |
||||
|
||||
public FtpDelegate(TARGET target, TASK_ENTITY taskEntity) { |
||||
mTarget = target; |
||||
mTaskEntity = taskEntity; |
||||
mEntity = mTaskEntity.getEntity(); |
||||
} |
||||
|
||||
@Override public TARGET charSet(String charSet) { |
||||
if (TextUtils.isEmpty(charSet)) return mTarget; |
||||
mTaskEntity.setCharSet(charSet); |
||||
return mTarget; |
||||
} |
||||
|
||||
@Override public TARGET login(String userName, String password) { |
||||
return login(userName, password, null); |
||||
} |
||||
|
||||
@Override public TARGET login(String userName, String password, String account) { |
||||
if (TextUtils.isEmpty(userName)) { |
||||
ALog.e(TAG, "用户名不能为null"); |
||||
return mTarget; |
||||
} else if (TextUtils.isEmpty(password)) { |
||||
ALog.e(TAG, "密码不能为null"); |
||||
return mTarget; |
||||
} |
||||
mTaskEntity.getUrlEntity().needLogin = true; |
||||
mTaskEntity.getUrlEntity().user = userName; |
||||
mTaskEntity.getUrlEntity().password = password; |
||||
mTaskEntity.getUrlEntity().account = account; |
||||
return mTarget; |
||||
} |
||||
} |
@ -0,0 +1,139 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.delegate; |
||||
|
||||
import android.support.annotation.NonNull; |
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.core.common.RequestEnum; |
||||
import com.arialyy.aria.core.inf.AbsEntity; |
||||
import com.arialyy.aria.core.inf.AbsTaskEntity; |
||||
import com.arialyy.aria.core.inf.IHttpHeaderTarget; |
||||
import com.arialyy.aria.core.inf.ITarget; |
||||
import com.arialyy.aria.util.ALog; |
||||
import java.util.Collection; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/9. |
||||
* HTTP header参数设置委托类 |
||||
*/ |
||||
public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>> |
||||
implements IHttpHeaderTarget<TARGET> { |
||||
private static final String TAG = "HttpHeaderDelegate"; |
||||
private ENTITY mEntity; |
||||
private TASK_ENTITY mTaskEntity; |
||||
private TARGET mTarget; |
||||
|
||||
public HttpHeaderDelegate(TARGET target, TASK_ENTITY taskEntity) { |
||||
mTarget = target; |
||||
mTaskEntity = taskEntity; |
||||
|
||||
mEntity = mTaskEntity.getEntity(); |
||||
} |
||||
|
||||
/** |
||||
* 给url请求添加Header数据 |
||||
* 如果新的header数据和数据保存的不一致,则更新数据库中对应的header数据 |
||||
* |
||||
* @param key header对应的key |
||||
* @param value header对应的value |
||||
*/ |
||||
@Override |
||||
public TARGET addHeader(@NonNull String key, @NonNull String value) { |
||||
if (TextUtils.isEmpty(key)) { |
||||
ALog.w(TAG, "设置header失败,header对应的key不能为null"); |
||||
return mTarget; |
||||
} else if (TextUtils.isEmpty(value)) { |
||||
ALog.w(TAG, "设置header失败,header对应的value不能为null"); |
||||
return mTarget; |
||||
} |
||||
if (mTaskEntity.getHeaders().get(key) == null) { |
||||
mTaskEntity.getHeaders().put(key, value); |
||||
} else if (!mTaskEntity.getHeaders().get(key).equals(value)) { |
||||
mTaskEntity.getHeaders().put(key, value); |
||||
} |
||||
return mTarget; |
||||
} |
||||
|
||||
/** |
||||
* 给url请求添加一组header数据 |
||||
* 如果新的header数据和数据保存的不一致,则更新数据库中对应的header数据 |
||||
* |
||||
* @param headers 一组http header数据 |
||||
*/ |
||||
@Override |
||||
public TARGET addHeaders(@NonNull Map<String, String> headers) { |
||||
if (headers.size() == 0) { |
||||
ALog.w(TAG, "设置header失败,map没有header数据"); |
||||
return mTarget; |
||||
} |
||||
/* |
||||
两个map比较逻辑 |
||||
1、比对key是否相同 |
||||
2、如果key相同,比对value是否相同 |
||||
3、只有当上面两个步骤中key 和 value都相同时才能任务两个map数据一致 |
||||
*/ |
||||
boolean mapEquals = false; |
||||
if (mTaskEntity.getHeaders().size() == headers.size()) { |
||||
int i = 0; |
||||
Set<String> keys = mTaskEntity.getHeaders().keySet(); |
||||
for (String key : keys) { |
||||
if (headers.containsKey(key)) { |
||||
i++; |
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
if (i == mTaskEntity.getHeaders().size()) { |
||||
int j = 0; |
||||
Collection<String> values = mTaskEntity.getHeaders().values(); |
||||
for (String value : values) { |
||||
if (headers.containsValue(value)) { |
||||
j++; |
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
if (j == mTaskEntity.getHeaders().size()) { |
||||
mapEquals = true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (!mapEquals) { |
||||
mTaskEntity.getHeaders().clear(); |
||||
Set<String> keys = headers.keySet(); |
||||
for (String key : keys) { |
||||
mTaskEntity.getHeaders().put(key, headers.get(key)); |
||||
} |
||||
} |
||||
|
||||
return mTarget; |
||||
} |
||||
|
||||
/** |
||||
* 设置请求类型,POST或GET,默认为在GET |
||||
* 只试用于HTTP请求 |
||||
* |
||||
* @param requestEnum {@link RequestEnum} |
||||
*/ |
||||
@Override |
||||
public TARGET setRequestMode(RequestEnum requestEnum) { |
||||
mTaskEntity.setRequestEnum(requestEnum); |
||||
return mTarget; |
||||
} |
||||
} |
@ -0,0 +1,97 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.download; |
||||
|
||||
import com.arialyy.aria.core.AriaManager; |
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory; |
||||
import com.arialyy.aria.core.inf.AbsEntity; |
||||
import com.arialyy.aria.core.inf.AbsTarget; |
||||
import com.arialyy.aria.core.inf.AbsTaskEntity; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
|
||||
/** |
||||
* Created by lyy on 2017/2/28. |
||||
*/ |
||||
abstract class AbsDownloadTarget<TARGET extends AbsTarget, ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity> |
||||
extends AbsTarget<TARGET, ENTITY, TASK_ENTITY> { |
||||
|
||||
static final int HTTP = 1; |
||||
static final int FTP = 2; |
||||
//HTTP任务组
|
||||
static final int GROUP_HTTP = 3; |
||||
//FTP文件夹
|
||||
static final int GROUP_FTP_DIR = 4; |
||||
|
||||
/** |
||||
* 设置的文件保存路径的临时变量 |
||||
*/ |
||||
String mTempFilePath; |
||||
|
||||
/** |
||||
* 将任务设置为最高优先级任务,最高优先级任务有以下特点: |
||||
* 1、在下载队列中,有且只有一个最高优先级任务 |
||||
* 2、最高优先级任务会一直存在,直到用户手动暂停或任务完成 |
||||
* 3、任务调度器不会暂停最高优先级任务 |
||||
* 4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效 |
||||
* 5、如果下载队列中已经满了,则会停止队尾的任务,当高优先级任务完成后,该队尾任务将自动执行 |
||||
* 6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务 |
||||
*/ |
||||
protected void setHighestPriority() { |
||||
if (checkEntity()) { |
||||
AriaManager.getInstance(AriaManager.APP) |
||||
.setCmd(CommonUtil.createNormalCmd(mTargetName, mTaskEntity, |
||||
NormalCmdFactory.TASK_HIGHEST_PRIORITY, checkTaskType())) |
||||
.exe(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 添加任务 |
||||
*/ |
||||
public void add() { |
||||
if (checkEntity()) { |
||||
AriaManager.getInstance(AriaManager.APP) |
||||
.setCmd(CommonUtil.createNormalCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CREATE, |
||||
checkTaskType())) |
||||
.exe(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取任务文件大小 |
||||
* |
||||
* @return 文件大小 |
||||
*/ |
||||
public long getFileSize() { |
||||
return getSize(); |
||||
} |
||||
|
||||
/** |
||||
* 获取单位转换后的文件大小 |
||||
* |
||||
* @return 文件大小{@code xxx mb} |
||||
*/ |
||||
public String getConvertFileSize() { |
||||
return getConvertSize(); |
||||
} |
||||
|
||||
/** |
||||
* 设置target类型 |
||||
* |
||||
* @return {@link #HTTP}、{@link #FTP}、{@link #GROUP_HTTP}、{@link #GROUP_FTP_DIR} |
||||
*/ |
||||
protected abstract int getTargetType(); |
||||
} |
@ -0,0 +1,183 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.download; |
||||
|
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.core.manager.TEManager; |
||||
import com.arialyy.aria.core.queue.DownloadTaskQueue; |
||||
import com.arialyy.aria.orm.DbEntity; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.io.File; |
||||
|
||||
/** |
||||
* Created by Aria.Lao on 2017/7/26. |
||||
*/ |
||||
abstract class BaseNormalTarget<TARGET extends BaseNormalTarget> |
||||
extends AbsDownloadTarget<TARGET, DownloadEntity, DownloadTaskEntity> { |
||||
|
||||
/** |
||||
* 资源地址 |
||||
*/ |
||||
protected String url; |
||||
|
||||
/** |
||||
* 通过地址初始化target |
||||
*/ |
||||
void initTarget(String url, String targetName, boolean refreshInfo) { |
||||
this.url = url; |
||||
mTargetName = targetName; |
||||
mTaskEntity = TEManager.getInstance().getTEntity(DownloadTaskEntity.class, url); |
||||
mEntity = mTaskEntity.getEntity(); |
||||
mTaskEntity.setRefreshInfo(refreshInfo); |
||||
if (mEntity != null) { |
||||
mTempFilePath = mEntity.getDownloadPath(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 将任务设置为最高优先级任务,最高优先级任务有以下特点: |
||||
* 1、在下载队列中,有且只有一个最高优先级任务 |
||||
* 2、最高优先级任务会一直存在,直到用户手动暂停或任务完成 |
||||
* 3、任务调度器不会暂停最高优先级任务 |
||||
* 4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效 |
||||
* 5、如果下载队列中已经满了,则会停止队尾的任务,当高优先级任务完成后,该队尾任务将自动执行 |
||||
* 6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务 |
||||
*/ |
||||
@Override public void setHighestPriority() { |
||||
super.setHighestPriority(); |
||||
} |
||||
|
||||
/** |
||||
* 下载任务是否存在 |
||||
* |
||||
* @return {@code true}任务存在 |
||||
*/ |
||||
@Override public boolean taskExists() { |
||||
return DownloadTaskQueue.getInstance().getTask(mEntity.getUrl()) != null; |
||||
} |
||||
|
||||
/** |
||||
* 获取下载实体 |
||||
*/ |
||||
public DownloadEntity getDownloadEntity() { |
||||
return mEntity; |
||||
} |
||||
|
||||
/** |
||||
* 是否在下载,该api后续版本会删除 |
||||
* |
||||
* @deprecated {@link #isRunning()} |
||||
*/ |
||||
@Deprecated public boolean isDownloading() { |
||||
return isRunning(); |
||||
} |
||||
|
||||
/** |
||||
* 是否在下载 |
||||
* |
||||
* @return {@code true}任务正在下载 |
||||
*/ |
||||
@Override public boolean isRunning() { |
||||
DownloadTask task = DownloadTaskQueue.getInstance().getTask(mEntity.getKey()); |
||||
return task != null && task.isRunning(); |
||||
} |
||||
|
||||
/** |
||||
* 检查下载实体,判断实体是否合法 |
||||
* 合法标准为: |
||||
* 1、下载路径不为null,并且下载路径是正常的http或ftp路径 |
||||
* 2、保存路径不为null,并且保存路径是android文件系统路径 |
||||
* 3、保存路径不能重复 |
||||
* |
||||
* @return {@code true}合法 |
||||
*/ |
||||
@Override protected boolean checkEntity() { |
||||
boolean b = getTargetType() < GROUP_HTTP && checkUrl() && checkFilePath(); |
||||
if (b) { |
||||
mEntity.save(); |
||||
mTaskEntity.save(); |
||||
} |
||||
return b; |
||||
} |
||||
|
||||
/** |
||||
* 检查并设置普通任务的文件保存路径 |
||||
* |
||||
* @return {@code true}保存路径合法 |
||||
*/ |
||||
private boolean checkFilePath() { |
||||
String filePath = mTempFilePath; |
||||
if (TextUtils.isEmpty(filePath)) { |
||||
ALog.e(TAG, "下载失败,文件保存路径为null"); |
||||
return false; |
||||
} else if (!filePath.startsWith("/")) { |
||||
ALog.e(TAG, "下载失败,文件保存路径【" + filePath + "】错误"); |
||||
return false; |
||||
} |
||||
File file = new File(filePath); |
||||
if (file.isDirectory()) { |
||||
if (getTargetType() == HTTP) { |
||||
ALog.e(TAG, "下载失败,保存路径【" + filePath + "】不能为文件夹,路径需要是完整的文件路径,如:/mnt/sdcard/game.zip"); |
||||
return false; |
||||
} else if (getTargetType() == FTP) { |
||||
filePath += mEntity.getFileName(); |
||||
} |
||||
} |
||||
mEntity.setFileName(file.getName()); |
||||
|
||||
//设置文件保存路径,如果新文件路径和就文件路径不同,则修改路径
|
||||
if (!filePath.equals(mEntity.getDownloadPath())) { |
||||
if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=?", filePath)) { |
||||
ALog.e(TAG, "下载失败,保存路径【" + filePath + "】已经被其它任务占用,请设置其它保存路径"); |
||||
return false; |
||||
} |
||||
File oldFile = new File(mEntity.getDownloadPath()); |
||||
File newFile = new File(filePath); |
||||
mEntity.setDownloadPath(filePath); |
||||
mEntity.setFileName(newFile.getName()); |
||||
mTaskEntity.setKey(filePath); |
||||
//mTaskEntity.update();
|
||||
if (oldFile.exists()) { |
||||
oldFile.renameTo(newFile); |
||||
CommonUtil.renameDownloadConfig(oldFile.getName(), newFile.getName()); |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 检查普通任务的下载地址 |
||||
* |
||||
* @return {@code true}地址合法 |
||||
*/ |
||||
private boolean checkUrl() { |
||||
final String url = mEntity.getUrl(); |
||||
if (TextUtils.isEmpty(url)) { |
||||
ALog.e(TAG, "下载失败,url为null"); |
||||
return false; |
||||
} else if (!url.startsWith("http") && !url.startsWith("ftp")) { |
||||
ALog.e(TAG, "下载失败,url【" + url + "】错误"); |
||||
return false; |
||||
} |
||||
int index = url.indexOf("://"); |
||||
if (index == -1) { |
||||
ALog.e(TAG, "下载失败,url【" + url + "】不合法"); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,44 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.download.wrapper; |
||||
|
||||
import com.arialyy.aria.core.download.DownloadEntity; |
||||
import com.arialyy.aria.core.download.DownloadGroupEntity; |
||||
import com.arialyy.aria.orm.AbsWrapper; |
||||
import com.arialyy.aria.orm.annotation.Many; |
||||
import com.arialyy.aria.orm.annotation.One; |
||||
import com.arialyy.aria.orm.annotation.Wrapper; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/30. |
||||
* 任务组实体和子任务实体的关系 |
||||
*/ |
||||
@Wrapper |
||||
public class DGEWrapper extends AbsWrapper { |
||||
|
||||
@One |
||||
public DownloadGroupEntity groupEntity; |
||||
|
||||
@Many(parentColumn = "groupName", entityColumn = "groupName") |
||||
public List<DownloadEntity> subEntity; |
||||
|
||||
@Override protected void handleConvert() { |
||||
if (subEntity != null && !subEntity.isEmpty()) { |
||||
groupEntity.setSubEntities(subEntity); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,44 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.download.wrapper; |
||||
|
||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity; |
||||
import com.arialyy.aria.core.download.DownloadTaskEntity; |
||||
import com.arialyy.aria.orm.AbsWrapper; |
||||
import com.arialyy.aria.orm.annotation.Many; |
||||
import com.arialyy.aria.orm.annotation.One; |
||||
import com.arialyy.aria.orm.annotation.Wrapper; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/4/11. |
||||
* 任务组任务实体和任务组任务实体的子任务实体对应关系 |
||||
*/ |
||||
@Wrapper |
||||
public class DGSTEWrapper extends AbsWrapper { |
||||
|
||||
@One |
||||
public DownloadGroupTaskEntity dgTaskEntity; |
||||
|
||||
@Many(parentColumn = "key", entityColumn = "groupName") |
||||
public List<DownloadTaskEntity> subTaskEntity; |
||||
|
||||
@Override protected void handleConvert() { |
||||
if (subTaskEntity != null && !subTaskEntity.isEmpty()) { |
||||
dgTaskEntity.setSubTaskEntities(subTaskEntity); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,65 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.download.wrapper; |
||||
|
||||
import com.arialyy.aria.core.download.DownloadGroupEntity; |
||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity; |
||||
import com.arialyy.aria.core.download.DownloadTaskEntity; |
||||
import com.arialyy.aria.core.inf.AbsTaskEntity; |
||||
import com.arialyy.aria.orm.AbsWrapper; |
||||
import com.arialyy.aria.orm.DbEntity; |
||||
import com.arialyy.aria.orm.annotation.Many; |
||||
import com.arialyy.aria.orm.annotation.One; |
||||
import com.arialyy.aria.orm.annotation.Wrapper; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/30. |
||||
* 任务组实体和任务组任务实体的关系 |
||||
*/ |
||||
@Wrapper |
||||
public class DGTEWrapper extends AbsWrapper { |
||||
|
||||
@One |
||||
public DownloadGroupEntity entity; |
||||
|
||||
@Many(parentColumn = "groupName", entityColumn = "key") |
||||
private List<DownloadGroupTaskEntity> taskEntitys; |
||||
|
||||
public DownloadGroupTaskEntity taskEntity; |
||||
|
||||
@Override protected void handleConvert() { |
||||
taskEntity = (taskEntitys == null || taskEntitys.isEmpty()) ? null : taskEntitys.get(0); |
||||
if (taskEntity != null) { |
||||
taskEntity.setEntity(entity); |
||||
List<DTEWrapper> subWrappers = |
||||
DbEntity.findRelationData(DTEWrapper.class, "DownloadTaskEntity.groupName=?", |
||||
taskEntity.getKey()); |
||||
if (subWrappers != null && !subWrappers.isEmpty()) { |
||||
List<DownloadTaskEntity> temp = new ArrayList<>(); |
||||
for (DTEWrapper dw : subWrappers) { |
||||
if (dw.taskEntity.getRequestType() == AbsTaskEntity.D_FTP) { |
||||
dw.taskEntity.setUrlEntity(CommonUtil.getFtpUrlInfo(dw.taskEntity.getUrl())); |
||||
} |
||||
temp.add(dw.taskEntity); |
||||
} |
||||
taskEntity.setSubTaskEntities(temp); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,46 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.download.wrapper; |
||||
|
||||
import com.arialyy.aria.core.download.DownloadEntity; |
||||
import com.arialyy.aria.core.download.DownloadTaskEntity; |
||||
import com.arialyy.aria.orm.AbsWrapper; |
||||
import com.arialyy.aria.orm.annotation.Many; |
||||
import com.arialyy.aria.orm.annotation.One; |
||||
import com.arialyy.aria.orm.annotation.Wrapper; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/30. |
||||
*/ |
||||
@Wrapper |
||||
public class DTEWrapper extends AbsWrapper { |
||||
|
||||
@One |
||||
public DownloadEntity entity; |
||||
|
||||
@Many(parentColumn = "downloadPath", entityColumn = "key") |
||||
private List<DownloadTaskEntity> taskEntitys = null; |
||||
|
||||
public DownloadTaskEntity taskEntity; |
||||
|
||||
@Override public void handleConvert() { |
||||
taskEntity = (taskEntitys == null || taskEntitys.isEmpty()) ? null : taskEntitys.get(0); |
||||
if (taskEntity != null) { |
||||
taskEntity.setEntity(entity); |
||||
} |
||||
} |
||||
} |
@ -1,151 +0,0 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.inf; |
||||
|
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.core.AriaManager; |
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory; |
||||
import com.arialyy.aria.core.download.DownloadEntity; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
|
||||
/** |
||||
* Created by lyy on 2017/2/28. |
||||
*/ |
||||
public abstract class AbsDownloadTarget<TARGET extends AbsTarget, ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity> |
||||
extends AbsTarget<TARGET, ENTITY, TASK_ENTITY> { |
||||
|
||||
/** |
||||
* 如果你的下载链接的header中含有md5码信息,那么你可以通过设置key,来获取从header获取该md5码信息。 |
||||
* key默认值为:Content-MD5 |
||||
* 获取md5信息:{@link DownloadEntity#getMd5Code()} |
||||
*/ |
||||
public TARGET setHeaderMd5Key(String md5Key) { |
||||
if (TextUtils.isEmpty(md5Key)) return (TARGET) this; |
||||
mTaskEntity.md5Key = md5Key; |
||||
if (TextUtils.isEmpty(mTaskEntity.md5Key) || !mTaskEntity.md5Key.equals(md5Key)) { |
||||
mTaskEntity.update(); |
||||
} |
||||
return (TARGET) this; |
||||
} |
||||
|
||||
/** |
||||
* 如果你的文件长度是放在header中,那么你需要配置key来让Aria知道正确的文件长度 |
||||
* key默认值为:Content-Length |
||||
*/ |
||||
public TARGET setHeaderContentLengthKey(String contentLength) { |
||||
if (TextUtils.isEmpty(contentLength)) return (TARGET) this; |
||||
mTaskEntity.contentLength = contentLength; |
||||
if (TextUtils.isEmpty(mTaskEntity.contentLength) || !mTaskEntity.contentLength.equals( |
||||
contentLength)) { |
||||
mTaskEntity.update(); |
||||
} |
||||
return (TARGET) this; |
||||
} |
||||
|
||||
/** |
||||
* 如果你的下载链接的header中含有文件描述信息,那么你可以通过设置key,来获取从header获取该文件描述信息。 |
||||
* key默认值为:Content-Disposition |
||||
* 获取文件描述信息:{@link DownloadEntity#getDisposition()} |
||||
*/ |
||||
public TARGET setHeaderDispositionKey(String dispositionKey) { |
||||
if (TextUtils.isEmpty(dispositionKey)) return (TARGET) this; |
||||
mTaskEntity.dispositionKey = dispositionKey; |
||||
if (TextUtils.isEmpty(mTaskEntity.dispositionKey) || !mTaskEntity.dispositionKey.equals( |
||||
dispositionKey)) { |
||||
mTaskEntity.save(); |
||||
} |
||||
return (TARGET) this; |
||||
} |
||||
|
||||
/** |
||||
* 从文件描述信息{@link #setHeaderDispositionKey(String)}中含有文件名信息,你可以通过设置key来获取header中的文件名 |
||||
* key默认值为:attachment;filename |
||||
* 获取文件名信息:{@link DownloadEntity#getServerFileName()} |
||||
*/ |
||||
public TARGET setHeaderDispositionFileKey(String dispositionFileKey) { |
||||
if (TextUtils.isEmpty(dispositionFileKey)) return (TARGET) this; |
||||
mTaskEntity.dispositionFileKey = dispositionFileKey; |
||||
if (TextUtils.isEmpty(mTaskEntity.dispositionFileKey) || !mTaskEntity.dispositionFileKey.equals( |
||||
dispositionFileKey)) { |
||||
mTaskEntity.save(); |
||||
} |
||||
return (TARGET) this; |
||||
} |
||||
|
||||
/** |
||||
* 将任务设置为最高优先级任务,最高优先级任务有以下特点: |
||||
* 1、在下载队列中,有且只有一个最高优先级任务 |
||||
* 2、最高优先级任务会一直存在,直到用户手动暂停或任务完成 |
||||
* 3、任务调度器不会暂停最高优先级任务 |
||||
* 4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效 |
||||
* 5、如果下载队列中已经满了,则会停止队尾的任务,当高优先级任务完成后,该队尾任务将自动执行 |
||||
* 6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务 |
||||
*/ |
||||
protected void setHighestPriority() { |
||||
AriaManager.getInstance(AriaManager.APP) |
||||
.setCmd(CommonUtil.createNormalCmd(mTargetName, mTaskEntity, |
||||
NormalCmdFactory.TASK_HIGHEST_PRIORITY, checkTaskType())) |
||||
.exe(); |
||||
} |
||||
|
||||
/** |
||||
* 重定向后,新url的key,默认为location |
||||
*/ |
||||
public void setRedirectUrlKey(String redirectUrlKey) { |
||||
if (TextUtils.isEmpty(redirectUrlKey)) { |
||||
ALog.e("AbsDownloadTarget", "重定向后,新url的key不能为null"); |
||||
return; |
||||
} |
||||
mTaskEntity.redirectUrlKey = redirectUrlKey; |
||||
} |
||||
|
||||
/** |
||||
* 获取任务文件大小 |
||||
* |
||||
* @return 文件大小 |
||||
*/ |
||||
public long getFileSize() { |
||||
return getSize(); |
||||
} |
||||
|
||||
/** |
||||
* 获取单位转换后的文件大小 |
||||
* |
||||
* @return 文件大小{@code xxx mb} |
||||
*/ |
||||
public String getConvertFileSize() { |
||||
return getConvertSize(); |
||||
} |
||||
|
||||
/** |
||||
* 添加任务 |
||||
*/ |
||||
public void add() { |
||||
AriaManager.getInstance(AriaManager.APP) |
||||
.setCmd(CommonUtil.createNormalCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CREATE, |
||||
checkTaskType())) |
||||
.exe(); |
||||
} |
||||
|
||||
/** |
||||
* 重新下载 |
||||
*/ |
||||
public void reStart() { |
||||
cancel(); |
||||
start(); |
||||
} |
||||
} |
@ -1,65 +0,0 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.inf; |
||||
|
||||
import android.support.annotation.NonNull; |
||||
import com.arialyy.aria.core.queue.UploadTaskQueue; |
||||
import com.arialyy.aria.core.upload.UploadEntity; |
||||
import com.arialyy.aria.core.upload.UploadTask; |
||||
import com.arialyy.aria.core.upload.UploadTaskEntity; |
||||
import com.arialyy.aria.util.CheckUtil; |
||||
|
||||
/** |
||||
* Created by AriaL on 2017/6/29. |
||||
* 任务组超类 |
||||
*/ |
||||
public abstract class AbsUploadTarget<TARGET extends AbsUploadTarget, ENTITY extends UploadEntity, TASK_ENTITY extends UploadTaskEntity> |
||||
extends AbsTarget<TARGET, ENTITY, TASK_ENTITY> { |
||||
|
||||
/** |
||||
* 设置上传路径 |
||||
* |
||||
* @param uploadUrl 上传路径 |
||||
*/ |
||||
public TARGET setUploadUrl(@NonNull String uploadUrl) { |
||||
uploadUrl = CheckUtil.checkUrl(uploadUrl); |
||||
if (mEntity.getUrl().equals(uploadUrl)) return (TARGET) this; |
||||
mEntity.setUrl(uploadUrl); |
||||
mEntity.update(); |
||||
return (TARGET) this; |
||||
} |
||||
|
||||
/** |
||||
* 下载任务是否存在 |
||||
*/ |
||||
@Override public boolean taskExists() { |
||||
return UploadTaskQueue.getInstance().getTask(mEntity.getFilePath()) != null; |
||||
} |
||||
|
||||
/** |
||||
* 是否在下载 |
||||
* |
||||
* @deprecated {@link #isRunning()} |
||||
*/ |
||||
public boolean isUploading() { |
||||
return isRunning(); |
||||
} |
||||
|
||||
@Override public boolean isRunning() { |
||||
UploadTask task = UploadTaskQueue.getInstance().getTask(mEntity.getKey()); |
||||
return task != null && task.isRunning(); |
||||
} |
||||
} |
@ -0,0 +1,43 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.inf; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/9. |
||||
*/ |
||||
public interface IFtpTarget<TARGET extends ITarget> { |
||||
/** |
||||
* 设置字符编码 |
||||
*/ |
||||
TARGET charSet(String charSet); |
||||
|
||||
/** |
||||
* ftp 用户登录信。 |
||||
* |
||||
* @param userName ftp用户名 |
||||
* @param password ftp用户密码 |
||||
*/ |
||||
TARGET login(String userName, String password); |
||||
|
||||
/** |
||||
* ftp 用户登录信息 |
||||
* |
||||
* @param userName ftp用户名 |
||||
* @param password ftp用户密码 |
||||
* @param account ftp账号 |
||||
*/ |
||||
TARGET login(String userName, String password, String account); |
||||
} |
@ -0,0 +1,52 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.inf; |
||||
|
||||
import android.support.annotation.NonNull; |
||||
import com.arialyy.aria.core.common.RequestEnum; |
||||
import com.arialyy.aria.core.download.DownloadEntity; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/9. |
||||
* HTTP Header功能接口 |
||||
*/ |
||||
public interface IHttpHeaderTarget<TARGET extends ITarget> { |
||||
|
||||
/** |
||||
* 给url请求添加Header数据 |
||||
* 如果新的header数据和数据保存的不一致,则更新数据库中对应的header数据 |
||||
* |
||||
* @param key header对应的key |
||||
* @param value header对应的value |
||||
*/ |
||||
TARGET addHeader(@NonNull String key, @NonNull String value); |
||||
|
||||
/** |
||||
* 给url请求添加一组header数据 |
||||
* 如果新的header数据和数据保存的不一致,则更新数据库中对应的header数据 |
||||
* |
||||
* @param headers 一组http header数据 |
||||
*/ |
||||
TARGET addHeaders(Map<String, String> headers); |
||||
|
||||
/** |
||||
* 设置HTTP请求类型 |
||||
* |
||||
* @param requestEnum {@link RequestEnum} |
||||
*/ |
||||
TARGET setRequestMode(RequestEnum requestEnum); |
||||
} |
@ -0,0 +1,169 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.manager; |
||||
|
||||
import com.arialyy.aria.core.download.DownloadEntity; |
||||
import com.arialyy.aria.core.download.DownloadGroupEntity; |
||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity; |
||||
import com.arialyy.aria.core.download.DownloadTaskEntity; |
||||
import com.arialyy.aria.core.download.wrapper.DGEWrapper; |
||||
import com.arialyy.aria.core.download.wrapper.DGTEWrapper; |
||||
import com.arialyy.aria.orm.DbEntity; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by Aria.Lao on 2017/11/1. |
||||
* 任务实体工厂 |
||||
*/ |
||||
class DGTEFactory implements IGTEFactory<DownloadGroupEntity, DownloadGroupTaskEntity> { |
||||
private static final String TAG = "DTEFactory"; |
||||
private static volatile DGTEFactory INSTANCE = null; |
||||
|
||||
private DGTEFactory() { |
||||
} |
||||
|
||||
public static DGTEFactory getInstance() { |
||||
if (INSTANCE == null) { |
||||
synchronized (DGTEFactory.class) { |
||||
INSTANCE = new DGTEFactory(); |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
@Override public DownloadGroupTaskEntity getGTE(String groupName, List<String> urls) { |
||||
DownloadGroupEntity entity = createDGroupEntity(groupName, urls); |
||||
List<DGTEWrapper> wrapper = |
||||
DbEntity.findRelationData(DGTEWrapper.class, "DownloadGroupTaskEntity.key=?", |
||||
entity.getGroupName()); |
||||
DownloadGroupTaskEntity gte; |
||||
|
||||
if (wrapper != null && !wrapper.isEmpty()) { |
||||
gte = wrapper.get(0).taskEntity; |
||||
if (gte == null) { |
||||
// 创建新的任务组任务实体
|
||||
gte = new DownloadGroupTaskEntity(); |
||||
//创建子任务的任务实体
|
||||
gte.setSubTaskEntities(createDGSubTaskEntity(entity)); |
||||
} else if (gte.getSubTaskEntities() == null || gte.getSubTaskEntities().isEmpty()) { |
||||
gte.setSubTaskEntities(createDGSubTaskEntity(entity)); |
||||
} |
||||
} else { |
||||
gte = new DownloadGroupTaskEntity(); |
||||
gte.setSubTaskEntities(createDGSubTaskEntity(entity)); |
||||
} |
||||
gte.setKey(entity.getGroupName()); |
||||
gte.setEntity(entity); |
||||
|
||||
return gte; |
||||
} |
||||
|
||||
@Override public DownloadGroupTaskEntity getFTE(String ftpUrl) { |
||||
List<DGTEWrapper> wrapper = |
||||
DbEntity.findRelationData(DGTEWrapper.class, "DownloadGroupTaskEntity.key=?", |
||||
ftpUrl); |
||||
DownloadGroupTaskEntity fte; |
||||
|
||||
if (wrapper != null && !wrapper.isEmpty()) { |
||||
fte = wrapper.get(0).taskEntity; |
||||
if (fte == null) { |
||||
fte = new DownloadGroupTaskEntity(); |
||||
DownloadGroupEntity dge = new DownloadGroupEntity(); |
||||
dge.setGroupName(ftpUrl); |
||||
fte.setEntity(dge); |
||||
} else if (fte.getEntity() == null) { |
||||
DownloadGroupEntity dge = new DownloadGroupEntity(); |
||||
dge.setGroupName(ftpUrl); |
||||
fte.setEntity(dge); |
||||
} |
||||
} else { |
||||
fte = new DownloadGroupTaskEntity(); |
||||
DownloadGroupEntity dge = new DownloadGroupEntity(); |
||||
dge.setGroupName(ftpUrl); |
||||
fte.setEntity(dge); |
||||
} |
||||
fte.setKey(ftpUrl); |
||||
fte.setUrlEntity(CommonUtil.getFtpUrlInfo(ftpUrl)); |
||||
|
||||
if (fte.getEntity().getSubEntities() == null) { |
||||
fte.getEntity().setSubEntities(new ArrayList<DownloadEntity>()); |
||||
} |
||||
if (fte.getSubTaskEntities() == null) { |
||||
fte.setSubTaskEntities(new ArrayList<DownloadTaskEntity>()); |
||||
} |
||||
return fte; |
||||
} |
||||
|
||||
/** |
||||
* 创建任务组子任务的任务实体 |
||||
*/ |
||||
private List<DownloadTaskEntity> createDGSubTaskEntity(DownloadGroupEntity dge) { |
||||
List<DownloadTaskEntity> list = new ArrayList<>(); |
||||
for (DownloadEntity entity : dge.getSubEntities()) { |
||||
DownloadTaskEntity taskEntity = new DownloadTaskEntity(); |
||||
taskEntity.setEntity(entity); |
||||
taskEntity.setKey(entity.getDownloadPath()); |
||||
taskEntity.setGroupName(dge.getKey()); |
||||
taskEntity.setGroupTask(true); |
||||
taskEntity.setUrl(entity.getUrl()); |
||||
list.add(taskEntity); |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
/** |
||||
* 查询任务组实体,如果数据库不存在该实体,则新创建一个新的任务组实体 |
||||
*/ |
||||
private DownloadGroupEntity createDGroupEntity(String groupName, List<String> urls) { |
||||
List<DGEWrapper> wrapper = |
||||
DbEntity.findRelationData(DGEWrapper.class, "DownloadGroupEntity.groupName=?", |
||||
groupName); |
||||
|
||||
DownloadGroupEntity groupEntity; |
||||
if (wrapper != null && !wrapper.isEmpty()) { |
||||
groupEntity = wrapper.get(0).groupEntity; |
||||
if (groupEntity == null) { |
||||
groupEntity = new DownloadGroupEntity(); |
||||
groupEntity.setSubEntities(createSubTask(groupName, urls)); |
||||
} |
||||
} else { |
||||
groupEntity = new DownloadGroupEntity(); |
||||
groupEntity.setSubEntities(createSubTask(groupName, urls)); |
||||
} |
||||
groupEntity.setGroupName(groupName); |
||||
groupEntity.setUrls(urls); |
||||
return groupEntity; |
||||
} |
||||
|
||||
/** |
||||
* 创建子任务 |
||||
*/ |
||||
private List<DownloadEntity> createSubTask(String groupName, List<String> urls) { |
||||
List<DownloadEntity> list = new ArrayList<>(); |
||||
for (int i = 0, len = urls.size(); i < len; i++) { |
||||
DownloadEntity entity = new DownloadEntity(); |
||||
entity.setUrl(urls.get(i)); |
||||
entity.setDownloadPath(groupName + "_" + i); |
||||
entity.setFileName(groupName + "_" + i); |
||||
entity.setGroupName(groupName); |
||||
entity.setGroupChild(true); |
||||
list.add(entity); |
||||
} |
||||
return list; |
||||
} |
||||
} |
@ -1,98 +0,0 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.manager; |
||||
|
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.core.download.DownloadGroupEntity; |
||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity; |
||||
import com.arialyy.aria.orm.DbEntity; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by Aria.Lao on 2017/11/1. |
||||
* 任务实体工厂 |
||||
*/ |
||||
class DGTEntityFactory implements ITEntityFactory<DownloadGroupEntity, DownloadGroupTaskEntity>, |
||||
IGTEntityFactory<DownloadGroupEntity, DownloadGroupTaskEntity> { |
||||
private static final String TAG = "DTEntityFactory"; |
||||
private static volatile DGTEntityFactory INSTANCE = null; |
||||
|
||||
private DGTEntityFactory() { |
||||
} |
||||
|
||||
public static DGTEntityFactory getInstance() { |
||||
if (INSTANCE == null) { |
||||
synchronized (DGTEntityFactory.class) { |
||||
INSTANCE = new DGTEntityFactory(); |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
/** |
||||
* 通过下载实体创建任务实体 |
||||
*/ |
||||
@Override public DownloadGroupTaskEntity create(DownloadGroupEntity entity) { |
||||
DownloadGroupTaskEntity dgTaskEntity = |
||||
DbEntity.findFirst(DownloadGroupTaskEntity.class, "key=?", entity.getGroupName()); |
||||
if (dgTaskEntity == null) { |
||||
dgTaskEntity = new DownloadGroupTaskEntity(); |
||||
dgTaskEntity.save(entity); |
||||
} |
||||
if (dgTaskEntity.entity == null || TextUtils.isEmpty(dgTaskEntity.entity.getKey())) { |
||||
dgTaskEntity.save(entity); |
||||
} |
||||
return dgTaskEntity; |
||||
} |
||||
|
||||
/** |
||||
* 对于任务组,不能使用这个,可用于FTP文件夹下载 |
||||
* |
||||
* @deprecated {@link #create(String, List)} |
||||
*/ |
||||
@Override @Deprecated public DownloadGroupTaskEntity create(String key) { |
||||
DownloadGroupTaskEntity dgTaskEntity = |
||||
DbEntity.findFirst(DownloadGroupTaskEntity.class, "key=?", key); |
||||
if (dgTaskEntity == null) { |
||||
dgTaskEntity = new DownloadGroupTaskEntity(); |
||||
dgTaskEntity.save(getDownloadGroupEntity(key, null)); |
||||
} |
||||
if (dgTaskEntity.entity == null || TextUtils.isEmpty(dgTaskEntity.entity.getKey())) { |
||||
dgTaskEntity.save(getDownloadGroupEntity(key, null)); |
||||
} |
||||
dgTaskEntity.urlEntity = CommonUtil.getFtpUrlInfo(key); |
||||
return dgTaskEntity; |
||||
} |
||||
|
||||
@Override public DownloadGroupTaskEntity create(String groupName, List<String> urls) { |
||||
return create(getDownloadGroupEntity(groupName, urls)); |
||||
} |
||||
|
||||
/** |
||||
* 查询任务组实体,如果数据库不存在该实体,则新创建一个新的任务组实体 |
||||
*/ |
||||
private DownloadGroupEntity getDownloadGroupEntity(String groupName, List<String> urls) { |
||||
DownloadGroupEntity entity = |
||||
DbEntity.findFirst(DownloadGroupEntity.class, "groupName=?", groupName); |
||||
if (entity == null) { |
||||
entity = new DownloadGroupEntity(); |
||||
entity.setGroupName(groupName); |
||||
entity.setUrls(urls); |
||||
} |
||||
return entity; |
||||
} |
||||
} |
@ -0,0 +1,46 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.manager; |
||||
|
||||
import com.arialyy.aria.core.inf.AbsEntity; |
||||
import com.arialyy.aria.core.inf.AbsTaskEntity; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 任务组通过组创建任务 |
||||
* Created by Aria.Lao on 2017/11/1. |
||||
*/ |
||||
interface IGTEFactory<ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>> { |
||||
|
||||
/** |
||||
* 获取任务组的任务实体, |
||||
* 1、创建实体和任务实体之间的关联 |
||||
* 2、如果在数据库中查找不到对应的数据,则新创建任务实体 |
||||
* |
||||
* @param groupName 任务组名 |
||||
* @param urls 子任务的下载地址 |
||||
*/ |
||||
TASK_ENTITY getGTE(String groupName, List<String> urls); |
||||
|
||||
/** |
||||
* 获取FTP文件夹的任务实体,该方法需要以下操作: |
||||
* 1、创建实体和任务实体之间的关联 |
||||
* 2、如果在数据库中查找不到对应的数据,则新创建任务实体 |
||||
* |
||||
* @param ftpUrl ftp文件夹下载路径 |
||||
*/ |
||||
TASK_ENTITY getFTE(String ftpUrl); |
||||
} |
@ -1,86 +0,0 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.manager; |
||||
|
||||
import com.arialyy.aria.core.AriaManager; |
||||
import com.arialyy.aria.core.inf.AbsTask; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.util.Iterator; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
/** |
||||
* Created by Aria.Lao on 2017/9/1. |
||||
* 任务管理器 |
||||
*/ |
||||
class TaskManager { |
||||
private static final String TAG = "TaskManager"; |
||||
private static volatile TaskManager INSTANCE = null; |
||||
private Map<String, AbsTask> map = new ConcurrentHashMap<>(); |
||||
|
||||
public static TaskManager getInstance() { |
||||
if (INSTANCE == null) { |
||||
synchronized (TaskManager.class) { |
||||
INSTANCE = new TaskManager(); |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
private TaskManager() { |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 管理器添加任务 |
||||
* |
||||
* @param key 任务的key,下载为保存路径,任务组为任务组名,上传为文件上传路径 |
||||
* @param task 任务 |
||||
* @return {@code true}添加成功 |
||||
*/ |
||||
public <T extends AbsTask> boolean addTask(String key, Class<T> clazz, T task) { |
||||
String hash = CommonUtil.keyToHashKey(key); |
||||
if (map.keySet().contains(hash)) { |
||||
ALog.e(TAG, "任务【" + key + "】已存在"); |
||||
return false; |
||||
} |
||||
map.put(CommonUtil.keyToHashKey(key), task); |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 移除任务 |
||||
* |
||||
* @param key 任务的key,下载为保存路径,任务组为任务组名,上传为文件上传路径 |
||||
*/ |
||||
public void removeTask(String key) { |
||||
String hash = CommonUtil.keyToHashKey(key); |
||||
for (Iterator<Map.Entry<String, AbsTask>> iter = map.entrySet().iterator(); iter.hasNext(); ) { |
||||
Map.Entry<String, AbsTask> entry = iter.next(); |
||||
if (entry.getKey().equals(hash)) iter.remove(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 通过key获取任务 |
||||
* |
||||
* @return 如果找不到任务,返回null,否则返回key对应的任务 |
||||
*/ |
||||
public AbsTask getTask(String key) { |
||||
return map.get(CommonUtil.keyToHashKey(key)); |
||||
} |
||||
} |
@ -0,0 +1,133 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.upload; |
||||
|
||||
import android.support.annotation.NonNull; |
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.core.manager.TEManager; |
||||
import com.arialyy.aria.core.queue.UploadTaskQueue; |
||||
import com.arialyy.aria.util.ALog; |
||||
import java.io.File; |
||||
|
||||
/** |
||||
* Created by AriaL on 2018/3/9. |
||||
*/ |
||||
abstract class BaseNormalTarget<TARGET extends AbsUploadTarget> |
||||
extends AbsUploadTarget<TARGET, UploadEntity, UploadTaskEntity> { |
||||
|
||||
protected String mTempUrl; |
||||
|
||||
void initTarget(String filePath) { |
||||
mTaskEntity = TEManager.getInstance().getTEntity(UploadTaskEntity.class, filePath); |
||||
mEntity = mTaskEntity.getEntity(); |
||||
File file = new File(filePath); |
||||
mEntity.setFileName(file.getName()); |
||||
mEntity.setFileSize(file.length()); |
||||
mTempUrl = mEntity.getUrl(); |
||||
} |
||||
|
||||
/** |
||||
* 设置上传路径 |
||||
* |
||||
* @param uploadUrl 上传路径 |
||||
*/ |
||||
public TARGET setUploadUrl(@NonNull String uploadUrl) { |
||||
mTempUrl = uploadUrl; |
||||
return (TARGET) this; |
||||
} |
||||
|
||||
/** |
||||
* 上传任务是否存在 |
||||
* |
||||
* @return {@code true}存在 |
||||
*/ |
||||
@Override public boolean taskExists() { |
||||
return UploadTaskQueue.getInstance().getTask(mEntity.getFilePath()) != null; |
||||
} |
||||
|
||||
/** |
||||
* 是否在上传 |
||||
* |
||||
* @deprecated {@link #isRunning()} |
||||
*/ |
||||
public boolean isUploading() { |
||||
return isRunning(); |
||||
} |
||||
|
||||
@Override public boolean isRunning() { |
||||
UploadTask task = UploadTaskQueue.getInstance().getTask(mEntity.getKey()); |
||||
return task != null && task.isRunning(); |
||||
} |
||||
|
||||
@Override protected boolean checkEntity() { |
||||
boolean b = checkUrl() && checkFilePath(); |
||||
if (b) { |
||||
mEntity.save(); |
||||
mTaskEntity.save(); |
||||
} |
||||
return b; |
||||
} |
||||
|
||||
/** |
||||
* 检查上传文件路径是否合法 |
||||
* |
||||
* @return {@code true} 合法 |
||||
*/ |
||||
private boolean checkFilePath() { |
||||
String filePath = mEntity.getFilePath(); |
||||
if (TextUtils.isEmpty(filePath)) { |
||||
ALog.e(TAG, "上传失败,文件路径为null"); |
||||
return false; |
||||
} else if (!filePath.startsWith("/")) { |
||||
ALog.e(TAG, "上传失败,文件路径【" + filePath + "】不合法"); |
||||
return false; |
||||
} |
||||
|
||||
File file = new File(mEntity.getFilePath()); |
||||
if (!file.exists()) { |
||||
ALog.e(TAG, "上传失败,文件【" + filePath + "】不存在"); |
||||
return false; |
||||
} |
||||
if (file.isDirectory()) { |
||||
ALog.e(TAG, "上传失败,文件【" + filePath + "】不能是文件夹"); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 检查普通任务的下载地址 |
||||
* |
||||
* @return {@code true}地址合法 |
||||
*/ |
||||
protected boolean checkUrl() { |
||||
final String url = mTempUrl; |
||||
if (TextUtils.isEmpty(url)) { |
||||
ALog.e(TAG, "上传失败,url为null"); |
||||
return false; |
||||
} else if (!url.startsWith("http") && !url.startsWith("ftp")) { |
||||
ALog.e(TAG, "上传失败,url【" + url + "】错误"); |
||||
return false; |
||||
} |
||||
int index = url.indexOf("://"); |
||||
if (index == -1) { |
||||
ALog.e(TAG, "上传失败,url【" + url + "】不合法"); |
||||
return false; |
||||
} |
||||
mEntity.setUrl(url); |
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,47 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.core.upload.wrapper; |
||||
|
||||
import com.arialyy.aria.core.upload.UploadEntity; |
||||
import com.arialyy.aria.core.upload.UploadTaskEntity; |
||||
import com.arialyy.aria.orm.AbsWrapper; |
||||
import com.arialyy.aria.orm.annotation.Many; |
||||
import com.arialyy.aria.orm.annotation.One; |
||||
import com.arialyy.aria.orm.annotation.Wrapper; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/30. |
||||
*/ |
||||
@Wrapper |
||||
public class UTEWrapper extends AbsWrapper { |
||||
|
||||
@One |
||||
public UploadEntity entity; |
||||
|
||||
@Many(parentColumn = "filePath", entityColumn = "key") |
||||
private List<UploadTaskEntity> taskEntitys = null; |
||||
|
||||
public UploadTaskEntity taskEntity; |
||||
|
||||
@Override public void handleConvert() { |
||||
//taskEntity.entity = (tEntity == null || tEntity.isEmpty()) ? null : tEntity.get(0);
|
||||
taskEntity = (taskEntitys == null || taskEntitys.isEmpty()) ? null : taskEntitys.get(0); |
||||
if (taskEntity != null) { |
||||
taskEntity.setEntity(entity); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,163 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.orm; |
||||
|
||||
import android.database.Cursor; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import android.support.v4.util.LruCache; |
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.lang.reflect.Field; |
||||
import java.net.URLEncoder; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/22. |
||||
*/ |
||||
abstract class AbsDelegate { |
||||
static final String TAG = "AbsDelegate"; |
||||
static final int CREATE_TABLE = 0; |
||||
static final int TABLE_EXISTS = 1; |
||||
static final int INSERT_DATA = 2; |
||||
static final int MODIFY_DATA = 3; |
||||
static final int FIND_DATA = 4; |
||||
static final int FIND_ALL_DATA = 5; |
||||
static final int DEL_DATA = 6; |
||||
static final int ROW_ID = 7; |
||||
static final int RELATION = 8; |
||||
static final int DROP_TABLE = 9; |
||||
|
||||
static LruCache<String, DbEntity> mDataCache = new LruCache<>(1024); |
||||
|
||||
/** |
||||
* 打印数据库日志 |
||||
* |
||||
* @param type {@link DelegateWrapper} |
||||
*/ |
||||
static void print(int type, String sql) { |
||||
if (!ALog.DEBUG) { |
||||
return; |
||||
} |
||||
String str = ""; |
||||
switch (type) { |
||||
case CREATE_TABLE: |
||||
str = "创建表 >>>> "; |
||||
break; |
||||
case TABLE_EXISTS: |
||||
str = "表是否存在 >>>> "; |
||||
break; |
||||
case INSERT_DATA: |
||||
str = "插入数据 >>>> "; |
||||
break; |
||||
case MODIFY_DATA: |
||||
str = "修改数据 >>>> "; |
||||
break; |
||||
case FIND_DATA: |
||||
str = "查询一行数据 >>>> "; |
||||
break; |
||||
case FIND_ALL_DATA: |
||||
str = "遍历整个数据库 >>>> "; |
||||
break; |
||||
case ROW_ID: |
||||
str = "查询RowId >>> "; |
||||
break; |
||||
case RELATION: |
||||
str = "查询关联表 >>> "; |
||||
break; |
||||
case DROP_TABLE: |
||||
str = "删除表 >>> "; |
||||
break; |
||||
} |
||||
ALog.d(TAG, str.concat(sql)); |
||||
} |
||||
|
||||
String getCacheKey(DbEntity dbEntity) { |
||||
return dbEntity.getClass().getName() + "_" + dbEntity.rowID; |
||||
} |
||||
|
||||
/** |
||||
* 检查list参数是否合法,list只能是{@code List<String>} |
||||
* |
||||
* @return {@code true} 合法 |
||||
*/ |
||||
boolean checkList(Field list) { |
||||
Class t = CommonUtil.getListParamType(list); |
||||
if (t != null && t == String.class) { |
||||
return true; |
||||
} else { |
||||
ALog.d(TAG, "map参数错误,支持List<String>的参数字段"); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 检查map参数是否合法,map只能是{@code Map<String, String>} |
||||
* |
||||
* @return {@code true} 合法 |
||||
*/ |
||||
boolean checkMap(Field map) { |
||||
Class[] ts = CommonUtil.getMapParamType(map); |
||||
if (ts != null |
||||
&& ts[0] != null |
||||
&& ts[1] != null |
||||
&& ts[0] == String.class |
||||
&& ts[1] == String.class) { |
||||
return true; |
||||
} else { |
||||
ALog.d(TAG, "map参数错误,支持Map<String,String>的参数字段"); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 为了防止特殊字符串导致存储失败,需要使用URL编码保存的字符串 |
||||
* |
||||
* @param value 需要保存的内容 |
||||
* @return 转换后的内容 |
||||
*/ |
||||
String convertValue(String value) { |
||||
if (!TextUtils.isEmpty(value) && value.contains("'")) { |
||||
return URLEncoder.encode(value); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
void closeCursor(Cursor cursor) { |
||||
if (cursor != null && !cursor.isClosed()) { |
||||
try { |
||||
cursor.close(); |
||||
} catch (android.database.SQLException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void close(SQLiteDatabase db) { |
||||
//if (db != null && db.isOpen()) db.close();
|
||||
} |
||||
|
||||
/** |
||||
* 检查数据库是否关闭,已经关闭的话,打开数据库 |
||||
* |
||||
* @return 返回数据库 |
||||
*/ |
||||
SQLiteDatabase checkDb(SQLiteDatabase db) { |
||||
if (db == null || !db.isOpen()) { |
||||
db = SqlHelper.INSTANCE.getWritableDatabase(); |
||||
} |
||||
return db; |
||||
} |
||||
} |
@ -0,0 +1,27 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.orm; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/30. |
||||
*/ |
||||
public abstract class AbsWrapper { |
||||
|
||||
/** |
||||
* 处理转换 |
||||
*/ |
||||
protected abstract void handleConvert(); |
||||
} |
@ -0,0 +1,62 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.orm; |
||||
|
||||
import com.arialyy.aria.orm.annotation.Foreign; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/22. |
||||
* on update 或 on delete 都可跟不同action功能 |
||||
* |
||||
* @see <a href="https://sqlite.org/foreignkeys.html"></a> |
||||
* {@link Foreign#onDelete()}、{@link Foreign#onUpdate()} |
||||
*/ |
||||
public enum ActionPolicy { |
||||
|
||||
/** |
||||
* 如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作 |
||||
*/ |
||||
NO_ACTION("NO ACTION"), |
||||
|
||||
/** |
||||
* 和NO ACTION 作用一致,和NO ACTION的区别是: |
||||
* 主表update/delete执行时,马上就触发约束; |
||||
* 而NO ACTION 是执行完成语句后才触发约束, |
||||
*/ |
||||
RESTRICT("RESTRICT"), |
||||
|
||||
/** |
||||
* 在父表上update/delete记录时,将子表上匹配记录的列设为null (要注意子表的外键列不能为not null) |
||||
*/ |
||||
SET_NULL("SET NULL"), |
||||
|
||||
/** |
||||
* 父表有变更时,子表将外键列设置成一个默认的值,default配置的值 |
||||
*/ |
||||
SET_DEFAULT("SET DEFAULT"), |
||||
|
||||
/** |
||||
* 在父表上update/delete记录时,同步update/delete掉子表的匹配记录 |
||||
*/ |
||||
CASCADE("CASCADE"); |
||||
|
||||
String function; |
||||
|
||||
ActionPolicy(String function) { |
||||
this.function = function; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,93 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.orm; |
||||
|
||||
import android.content.Context; |
||||
import android.content.ContextWrapper; |
||||
import android.database.DatabaseErrorHandler; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* 保存在sd卡的数据库使用的Context |
||||
*/ |
||||
class DatabaseContext extends ContextWrapper { |
||||
public DatabaseContext(Context context) { |
||||
super(context); |
||||
} |
||||
|
||||
/** |
||||
* 获得数据库路径,如果不存在,则创建对象对象 |
||||
*/ |
||||
@Override |
||||
public File getDatabasePath(String name) { |
||||
String dbDir = CommonUtil.getAppPath(getBaseContext()); |
||||
|
||||
dbDir += "DB";//数据库所在目录
|
||||
String dbPath = dbDir + "/" + name;//数据库路径
|
||||
//判断目录是否存在,不存在则创建该目录
|
||||
File dirFile = new File(dbDir); |
||||
if (!dirFile.exists()) { |
||||
dirFile.mkdirs(); |
||||
} |
||||
|
||||
//数据库文件是否创建成功
|
||||
boolean isFileCreateSuccess = false; |
||||
//判断文件是否存在,不存在则创建该文件
|
||||
File dbFile = new File(dbPath); |
||||
if (!dbFile.exists()) { |
||||
try { |
||||
isFileCreateSuccess = dbFile.createNewFile();//创建文件
|
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} else { |
||||
isFileCreateSuccess = true; |
||||
} |
||||
|
||||
//返回数据库文件对象
|
||||
if (isFileCreateSuccess) { |
||||
return dbFile; |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 重载这个方法,是用来打开SD卡上的数据库的,android 2.3及以下会调用这个方法。 |
||||
*/ |
||||
@Override |
||||
public SQLiteDatabase openOrCreateDatabase(String name, int mode, |
||||
SQLiteDatabase.CursorFactory factory) { |
||||
return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null); |
||||
} |
||||
|
||||
/** |
||||
* Android 4.0会调用此方法获取数据库。 |
||||
* |
||||
* @see android.content.ContextWrapper#openOrCreateDatabase(java.lang.String, int, |
||||
* android.database.sqlite.SQLiteDatabase.CursorFactory, |
||||
* android.database.DatabaseErrorHandler) |
||||
*/ |
||||
@Override |
||||
public SQLiteDatabase openOrCreateDatabase(String name, int mode, |
||||
SQLiteDatabase.CursorFactory factory, |
||||
DatabaseErrorHandler errorHandler) { |
||||
return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null); |
||||
} |
||||
} |
@ -1,249 +0,0 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package com.arialyy.aria.orm; |
||||
|
||||
import android.app.Application; |
||||
import android.content.Context; |
||||
import android.database.Cursor; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import android.support.annotation.NonNull; |
||||
import com.arialyy.aria.core.AriaManager; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CheckUtil; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by lyy on 2015/2/11. |
||||
* 数据库操作工具 |
||||
*/ |
||||
public class DbUtil { |
||||
private static final String TAG = "DbUtil"; |
||||
private volatile static DbUtil INSTANCE = null; |
||||
private int ROW_ID = 7; |
||||
private SQLiteDatabase mDb; |
||||
private SqlHelper mHelper; |
||||
|
||||
private DbUtil() { |
||||
|
||||
} |
||||
|
||||
private DbUtil(Context context) { |
||||
mHelper = SqlHelper.init(context.getApplicationContext()); |
||||
} |
||||
|
||||
public static DbUtil init(Context context) { |
||||
if (context instanceof Application) { |
||||
synchronized (AriaManager.LOCK) { |
||||
if (INSTANCE == null) { |
||||
INSTANCE = new DbUtil(context); |
||||
} |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
protected static DbUtil getInstance() { |
||||
if (INSTANCE == null) { |
||||
throw new NullPointerException("请在Application中调用init进行数据库工具注册注册"); |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
///**
|
||||
// * 关键字模糊检索全文
|
||||
// *
|
||||
// * @param column 需要查找的列
|
||||
// * @param mathSql 关键字语法,exsimple “white OR green”、“blue AND red”、“white NOT green”
|
||||
// */
|
||||
//public <T extends DbEntity> List<T> searchData(Class<T> clazz, String column, String mathSql) {
|
||||
// checkDb();
|
||||
// return SqlHelper.searchData(mDb, clazz, column, mathSql);
|
||||
//}
|
||||
|
||||
/** |
||||
* 检查某个字段的值是否存在 |
||||
* |
||||
* @param expression 字段和值"url=xxx" |
||||
* @return {@code true}该字段的对应的value已存在 |
||||
*/ |
||||
synchronized boolean checkDataExist(Class clazz, String... expression) { |
||||
checkDb(); |
||||
return SqlHelper.checkDataExist(mDb, clazz, expression); |
||||
} |
||||
|
||||
/** |
||||
* 清空表数据 |
||||
*/ |
||||
synchronized <T extends DbEntity> void clean(Class<T> clazz) { |
||||
checkDb(); |
||||
String tableName = CommonUtil.getClassName(clazz); |
||||
if (tableExists(clazz)) { |
||||
String sql = "DELETE FROM " + tableName; |
||||
exeSql(sql); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 执行sql语句 |
||||
*/ |
||||
void exeSql(String sql) { |
||||
mDb.execSQL(sql); |
||||
} |
||||
|
||||
/** |
||||
* 删除某条数据 |
||||
*/ |
||||
synchronized <T extends DbEntity> void delData(Class<T> clazz, String... expression) { |
||||
CheckUtil.checkSqlExpression(expression); |
||||
checkDb(); |
||||
SqlHelper.delData(mDb, clazz, expression); |
||||
} |
||||
|
||||
/** |
||||
* 修改某行数据 |
||||
*/ |
||||
synchronized void modifyData(DbEntity dbEntity) { |
||||
checkDb(); |
||||
SqlHelper.modifyData(mDb, dbEntity); |
||||
} |
||||
|
||||
/** |
||||
* 遍历所有数据 |
||||
*/ |
||||
synchronized <T extends DbEntity> List<T> findAllData(Class<T> clazz) { |
||||
checkDb(); |
||||
return SqlHelper.findAllData(mDb, clazz); |
||||
} |
||||
|
||||
/** |
||||
* 条件查寻数据 |
||||
*/ |
||||
synchronized <T extends DbEntity> List<T> findData(Class<T> clazz, String... expression) { |
||||
checkDb(); |
||||
return SqlHelper.findData(mDb, clazz, expression); |
||||
} |
||||
|
||||
/** |
||||
* 通过rowId判断数据是否存在 |
||||
*/ |
||||
synchronized <T extends DbEntity> boolean isExist(Class<T> clazz, int rowId) { |
||||
checkDb(); |
||||
String sql = "SELECT rowid FROM " + CommonUtil.getClassName(clazz) + " WHERE rowid=" + rowId; |
||||
Cursor cursor = mDb.rawQuery(sql, null); |
||||
boolean isExist = cursor.getCount() > 0; |
||||
cursor.close(); |
||||
return isExist; |
||||
} |
||||
|
||||
/** |
||||
* 条件查寻数据 |
||||
*/ |
||||
@Deprecated synchronized <T extends DbEntity> List<T> findData(Class<T> clazz, |
||||
@NonNull String[] wheres, @NonNull String[] values) { |
||||
checkDb(); |
||||
return SqlHelper.findData(mDb, clazz, wheres, values); |
||||
} |
||||
|
||||
/** |
||||
* 插入数据 |
||||
*/ |
||||
synchronized void insertData(DbEntity dbEntity) { |
||||
checkDb(); |
||||
SqlHelper.insertData(mDb, dbEntity); |
||||
} |
||||
|
||||
/** |
||||
* 查找某张表是否存在 |
||||
*/ |
||||
synchronized boolean tableExists(Class clazz) { |
||||
checkDb(); |
||||
return SqlHelper.tableExists(mDb, clazz); |
||||
} |
||||
|
||||
synchronized void createTable(Class clazz, String tableName) { |
||||
checkDb(); |
||||
SqlHelper.createTable(mDb, clazz, tableName); |
||||
} |
||||
|
||||
private void checkDb() { |
||||
if (mDb == null || !mDb.isOpen()) { |
||||
mDb = mHelper.getReadableDatabase(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 创建表 |
||||
*/ |
||||
private synchronized void createTable(Class clazz) { |
||||
createTable(clazz, null); |
||||
} |
||||
|
||||
/** |
||||
* 关闭数据库 |
||||
*/ |
||||
private synchronized void close() { |
||||
if (mDb != null) { |
||||
mDb.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取所在行Id |
||||
*/ |
||||
synchronized int[] getRowId(Class clazz) { |
||||
checkDb(); |
||||
Cursor cursor = mDb.rawQuery("SELECT rowid, * FROM " + CommonUtil.getClassName(clazz), null); |
||||
int[] ids = new int[cursor.getCount()]; |
||||
int i = 0; |
||||
while (cursor.moveToNext()) { |
||||
ids[i] = cursor.getInt(cursor.getColumnIndex("rowid")); |
||||
i++; |
||||
} |
||||
cursor.close(); |
||||
close(); |
||||
return ids; |
||||
} |
||||
|
||||
/** |
||||
* 获取行Id |
||||
*/ |
||||
synchronized int getRowId(Class clazz, Object[] wheres, Object[] values) { |
||||
checkDb(); |
||||
if (wheres.length <= 0 || values.length <= 0) { |
||||
ALog.e(TAG, "请输入删除条件"); |
||||
return -1; |
||||
} else if (wheres.length != values.length) { |
||||
ALog.e(TAG, "groupName 和 vaule 长度不相等"); |
||||
return -1; |
||||
} |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("SELECT rowid FROM ").append(CommonUtil.getClassName(clazz)).append(" WHERE "); |
||||
int i = 0; |
||||
for (Object where : wheres) { |
||||
sb.append(where).append("=").append("'").append(values[i]).append("'"); |
||||
sb.append(i >= wheres.length - 1 ? "" : ","); |
||||
i++; |
||||
} |
||||
SqlHelper.print(ROW_ID, sb.toString()); |
||||
Cursor c = mDb.rawQuery(sb.toString(), null); |
||||
int id = c.getColumnIndex("rowid"); |
||||
c.close(); |
||||
close(); |
||||
return id; |
||||
} |
||||
} |
@ -0,0 +1,221 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.orm; |
||||
|
||||
import android.database.Cursor; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.orm.annotation.Default; |
||||
import com.arialyy.aria.orm.annotation.Foreign; |
||||
import com.arialyy.aria.orm.annotation.Primary; |
||||
import com.arialyy.aria.util.CheckUtil; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.lang.reflect.Field; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/22. |
||||
* 通用委托,创建表,检查字段 |
||||
*/ |
||||
class DelegateCommon extends AbsDelegate { |
||||
private DelegateCommon() { |
||||
} |
||||
|
||||
/** |
||||
* 删除指定的表 |
||||
*/ |
||||
void dropTable(SQLiteDatabase db, String tableName) { |
||||
db = checkDb(db); |
||||
String deleteSQL = "DROP TABLE IF EXISTS ".concat(tableName); |
||||
print(DROP_TABLE, deleteSQL); |
||||
//db.beginTransaction();
|
||||
db.execSQL(deleteSQL); |
||||
//db.setTransactionSuccessful();
|
||||
//db.endTransaction();
|
||||
} |
||||
|
||||
/** |
||||
* 清空表数据 |
||||
*/ |
||||
<T extends DbEntity> void clean(SQLiteDatabase db, Class<T> clazz) { |
||||
db = checkDb(db); |
||||
String tableName = CommonUtil.getClassName(clazz); |
||||
if (tableExists(db, clazz)) { |
||||
String sql = "DELETE FROM " + tableName; |
||||
db.execSQL(sql); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 查找表是否存在 |
||||
* |
||||
* @param clazz 数据库实体 |
||||
* @return true,该数据库实体对应的表存在;false,不存在 |
||||
*/ |
||||
boolean tableExists(SQLiteDatabase db, Class clazz) { |
||||
return tableExists(db, CommonUtil.getClassName(clazz)); |
||||
} |
||||
|
||||
private boolean tableExists(SQLiteDatabase db, String tableName) { |
||||
db = checkDb(db); |
||||
Cursor cursor = null; |
||||
try { |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("SELECT COUNT(*) AS c FROM sqlite_master WHERE type='table' AND name='"); |
||||
sb.append(tableName); |
||||
sb.append("'"); |
||||
print(TABLE_EXISTS, sb.toString()); |
||||
cursor = db.rawQuery(sb.toString(), null); |
||||
if (cursor != null && cursor.moveToNext()) { |
||||
int count = cursor.getInt(0); |
||||
if (count > 0) { |
||||
return true; |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} finally { |
||||
closeCursor(cursor); |
||||
close(db); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* 检查某个字段的值是否存在 |
||||
* |
||||
* @param expression 字段和值"url=xxx" |
||||
* @return {@code true}该字段的对应的value已存在 |
||||
*/ |
||||
boolean checkDataExist(SQLiteDatabase db, Class clazz, String... expression) { |
||||
db = checkDb(db); |
||||
CheckUtil.checkSqlExpression(expression); |
||||
String sql = |
||||
"SELECT rowid, * FROM " + CommonUtil.getClassName(clazz) + " WHERE " + expression[0] + " "; |
||||
sql = sql.replace("?", "%s"); |
||||
Object[] params = new String[expression.length - 1]; |
||||
for (int i = 0, len = params.length; i < len; i++) { |
||||
params[i] = "'" + expression[i + 1] + "'"; |
||||
} |
||||
sql = String.format(sql, params); |
||||
print(FIND_DATA, sql); |
||||
Cursor cursor = db.rawQuery(sql, null); |
||||
final boolean isExist = cursor.getCount() > 0; |
||||
closeCursor(cursor); |
||||
close(db); |
||||
return isExist; |
||||
} |
||||
|
||||
/** |
||||
* 创建表 |
||||
* |
||||
* @param clazz 数据库实体 |
||||
*/ |
||||
void createTable(SQLiteDatabase db, Class clazz) { |
||||
db = checkDb(db); |
||||
List<Field> fields = CommonUtil.getAllFields(clazz); |
||||
if (fields != null && fields.size() > 0) { |
||||
//外键Map,在Sqlite3中foreign修饰的字段必须放在最后
|
||||
final List<Field> foreignArray = new ArrayList<>(); |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("CREATE TABLE ") |
||||
.append(CommonUtil.getClassName(clazz)) |
||||
.append(" ("); |
||||
for (Field field : fields) { |
||||
field.setAccessible(true); |
||||
if (SqlUtil.isIgnore(field)) { |
||||
continue; |
||||
} |
||||
Class<?> type = field.getType(); |
||||
sb.append(field.getName()); |
||||
if (type == String.class || type.isEnum()) { |
||||
sb.append(" VARCHAR"); |
||||
} else if (type == int.class || type == Integer.class) { |
||||
sb.append(" INTEGER"); |
||||
} else if (type == float.class || type == Float.class) { |
||||
sb.append(" FLOAT"); |
||||
} else if (type == double.class || type == Double.class) { |
||||
sb.append(" DOUBLE"); |
||||
} else if (type == long.class || type == Long.class) { |
||||
sb.append(" BIGINT"); |
||||
} else if (type == boolean.class || type == Boolean.class) { |
||||
sb.append(" BOOLEAN"); |
||||
} else if (type == java.util.Date.class || type == java.sql.Date.class) { |
||||
sb.append(" DATA"); |
||||
} else if (type == byte.class || type == Byte.class) { |
||||
sb.append(" BLOB"); |
||||
} else if (type == Map.class || type == List.class) { |
||||
sb.append(" TEXT"); |
||||
} else { |
||||
continue; |
||||
} |
||||
if (SqlUtil.isPrimary(field)) { |
||||
Primary pk = field.getAnnotation(Primary.class); |
||||
sb.append(" PRIMARY KEY"); |
||||
if (pk.autoincrement() && (type == int.class || type == Integer.class)) { |
||||
sb.append(" AUTOINCREMENT"); |
||||
} |
||||
} |
||||
|
||||
if (SqlUtil.isForeign(field)) { |
||||
foreignArray.add(field); |
||||
} |
||||
|
||||
if (SqlUtil.isNoNull(field)) { |
||||
sb.append(" NOT NULL"); |
||||
} |
||||
|
||||
if (SqlUtil.isDefault(field)) { |
||||
Default d = field.getAnnotation(Default.class); |
||||
if (!TextUtils.isEmpty(d.value())) { |
||||
sb.append(" DEFAULT ").append("'").append(d.value()).append("'"); |
||||
} |
||||
} |
||||
|
||||
sb.append(","); |
||||
} |
||||
|
||||
for (Field field : foreignArray) { |
||||
Foreign foreign = field.getAnnotation(Foreign.class); |
||||
sb.append("FOREIGN KEY (") |
||||
.append(field.getName()) |
||||
.append(") REFERENCES ") |
||||
.append(CommonUtil.getClassName(foreign.parent())) |
||||
.append("(") |
||||
.append(foreign.column()) |
||||
.append(")"); |
||||
ActionPolicy update = foreign.onUpdate(); |
||||
ActionPolicy delete = foreign.onDelete(); |
||||
if (update != ActionPolicy.NO_ACTION) { |
||||
sb.append(" ON UPDATE ").append(update.function); |
||||
} |
||||
|
||||
if (delete != ActionPolicy.NO_ACTION) { |
||||
sb.append(" ON DELETE ").append(update.function); |
||||
} |
||||
sb.append(","); |
||||
} |
||||
|
||||
String str = sb.toString(); |
||||
str = str.substring(0, str.length() - 1) + ");"; |
||||
print(CREATE_TABLE, str); |
||||
db.execSQL(str); |
||||
} |
||||
close(db); |
||||
} |
||||
} |
@ -0,0 +1,512 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.orm; |
||||
|
||||
import android.annotation.TargetApi; |
||||
import android.database.Cursor; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import android.os.Build; |
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.orm.annotation.Many; |
||||
import com.arialyy.aria.orm.annotation.One; |
||||
import com.arialyy.aria.orm.annotation.Wrapper; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CheckUtil; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.lang.reflect.Field; |
||||
import java.net.URLDecoder; |
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.WeakHashMap; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/22. |
||||
* 查询数据 |
||||
*/ |
||||
class DelegateFind extends AbsDelegate { |
||||
private final String PARENT_COLUMN_ALIAS = "p"; |
||||
private final String CHILD_COLUMN_ALIAS = "c"; |
||||
|
||||
private DelegateFind() { |
||||
} |
||||
|
||||
/** |
||||
* 查找一对多的关联数据 |
||||
* 如果查找不到数据或实体没有被{@link Wrapper}注解,将返回null |
||||
* 如果实体中没有{@link One}或{@link Many}注解,将返回null |
||||
* 如果实体中有多个{@link One}或{@link Many}注解,将返回nul |
||||
*/ |
||||
<T extends AbsWrapper> List<T> findRelationData(SQLiteDatabase db, Class<T> clazz, |
||||
String... expression) { |
||||
db = checkDb(db); |
||||
|
||||
if (SqlUtil.isWrapper(clazz)) { |
||||
StringBuilder sb = new StringBuilder(); |
||||
Field[] fields = clazz.getDeclaredFields(); |
||||
Field one = null, many = null; |
||||
boolean hasOne = false, hasMany = false; |
||||
for (Field field : fields) { |
||||
if (SqlUtil.isOne(field)) { |
||||
if (hasOne) { |
||||
ALog.w(TAG, "查询数据失败,实体中有多个@One 注解"); |
||||
return null; |
||||
} |
||||
hasOne = true; |
||||
one = field; |
||||
} |
||||
if (SqlUtil.isMany(field)) { |
||||
if (hasMany) { |
||||
ALog.w(TAG, "查询数据失败,实体中有多个@Many 注解"); |
||||
return null; |
||||
} |
||||
hasMany = true; |
||||
many = field; |
||||
} |
||||
} |
||||
|
||||
if (one == null || many == null) { |
||||
ALog.w(TAG, "查询数据失败,实体中没有@One或@Many注解"); |
||||
return null; |
||||
} |
||||
|
||||
if (many.getType() != List.class) { |
||||
ALog.w(TAG, "查询数据失败,@Many注解的字段必须是List"); |
||||
return null; |
||||
} |
||||
try { |
||||
Many m = many.getAnnotation(Many.class); |
||||
Class parentClazz = Class.forName(one.getType().getName()); |
||||
Class childClazz = Class.forName(CommonUtil.getListParamType(many).getName()); |
||||
final String pTableName = parentClazz.getSimpleName(); |
||||
final String cTableName = childClazz.getSimpleName(); |
||||
List<Field> pColumn = SqlUtil.getAllNotIgnoreField(parentClazz); |
||||
List<Field> cColumn = SqlUtil.getAllNotIgnoreField(childClazz); |
||||
List<String> pColumnAlias = new ArrayList<>(); |
||||
List<String> cColumnAlias = new ArrayList<>(); |
||||
StringBuilder pSb = new StringBuilder(); |
||||
StringBuilder cSb = new StringBuilder(); |
||||
|
||||
if (pColumn != null) { |
||||
pSb.append(pTableName.concat(".rowid AS ").concat(PARENT_COLUMN_ALIAS).concat("rowid,")); |
||||
for (Field f : pColumn) { |
||||
String temp = PARENT_COLUMN_ALIAS.concat(f.getName()); |
||||
pColumnAlias.add(temp); |
||||
pSb.append(pTableName.concat(".").concat(f.getName())) |
||||
.append(" AS ") |
||||
.append(temp) |
||||
.append(","); |
||||
} |
||||
} |
||||
|
||||
if (cColumn != null) { |
||||
pSb.append(cTableName.concat(".rowid AS ").concat(CHILD_COLUMN_ALIAS).concat("rowid,")); |
||||
for (Field f : cColumn) { |
||||
String temp = CHILD_COLUMN_ALIAS.concat(f.getName()); |
||||
cColumnAlias.add(temp); |
||||
cSb.append(cTableName.concat(".").concat(f.getName())) |
||||
.append(" AS ") |
||||
.append(temp) |
||||
.append(","); |
||||
} |
||||
} |
||||
|
||||
String pColumnAlia = pSb.toString(); |
||||
String cColumnAlia = cSb.toString(); |
||||
if (!TextUtils.isEmpty(pColumnAlia)) { |
||||
pColumnAlia = pColumnAlia.substring(0, pColumnAlia.length() - 1); |
||||
} |
||||
|
||||
if (!TextUtils.isEmpty(cColumnAlia)) { |
||||
cColumnAlia = cColumnAlia.substring(0, cColumnAlia.length() - 1); |
||||
} |
||||
|
||||
sb.append("SELECT "); |
||||
|
||||
if (!TextUtils.isEmpty(pColumnAlia)) { |
||||
sb.append(pColumnAlia).append(","); |
||||
} |
||||
if (!TextUtils.isEmpty(cColumnAlia)) { |
||||
sb.append(cColumnAlia); |
||||
} |
||||
if (TextUtils.isEmpty(pColumnAlia) && TextUtils.isEmpty(cColumnAlia)) { |
||||
sb.append(" * "); |
||||
} |
||||
|
||||
sb.append(" FROM ") |
||||
.append(pTableName) |
||||
.append(" INNER JOIN ") |
||||
.append(cTableName) |
||||
.append(" ON ") |
||||
.append(pTableName.concat(".").concat(m.parentColumn())) |
||||
.append(" = ") |
||||
.append(cTableName.concat(".").concat(m.entityColumn())); |
||||
String sql; |
||||
if (expression != null && expression.length > 0) { |
||||
CheckUtil.checkSqlExpression(expression); |
||||
sb.append(" WHERE ").append(expression[0]).append(" "); |
||||
sql = sb.toString(); |
||||
sql = sql.replace("?", "%s"); |
||||
Object[] params = new String[expression.length - 1]; |
||||
for (int i = 0, len = params.length; i < len; i++) { |
||||
params[i] = "'" + convertValue(expression[i + 1]) + "'"; |
||||
} |
||||
sql = String.format(sql, params); |
||||
} else { |
||||
sql = sb.toString(); |
||||
} |
||||
print(RELATION, sql); |
||||
Cursor cursor = db.rawQuery(sql, null); |
||||
List<T> data = |
||||
(List<T>) newInstanceEntity(clazz, parentClazz, childClazz, cursor, pColumn, cColumn, |
||||
pColumnAlias, cColumnAlias); |
||||
closeCursor(cursor); |
||||
close(db); |
||||
return data; |
||||
} catch (ClassNotFoundException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} else { |
||||
ALog.w(TAG, "查询数据失败,实体类没有使用@Wrapper 注解"); |
||||
return null; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* 创建关联查询的数据 |
||||
* |
||||
* @param pColumn 父表的所有字段 |
||||
* @param cColumn 字表的所有字段 |
||||
* @param pColumnAlias 关联查询父表别名 |
||||
* @param cColumnAlias 关联查询子表别名 |
||||
*/ |
||||
private <T extends AbsWrapper, P extends DbEntity, C extends DbEntity> List<T> newInstanceEntity( |
||||
Class<T> clazz, Class<P> parent, |
||||
Class<C> child, |
||||
Cursor cursor, |
||||
List<Field> pColumn, List<Field> cColumn, |
||||
List<String> pColumnAlias, List<String> cColumnAlias) { |
||||
try { |
||||
String parentPrimary = ""; //父表主键别名
|
||||
for (Field f : pColumn) { |
||||
if (SqlUtil.isPrimary(f)) { |
||||
parentPrimary = PARENT_COLUMN_ALIAS.concat(f.getName()); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
List<T> wrappers = new ArrayList<>(); |
||||
Map<Object, P> tempParent = new WeakHashMap<>(); // 所有父表元素,key为父表主键的值
|
||||
Map<Object, List<C>> tempChild = new WeakHashMap<>(); // 所有的字表元素,key为父表主键的值
|
||||
|
||||
Object old = null; |
||||
while (cursor.moveToNext()) { |
||||
//创建父实体
|
||||
Object ppValue = setPPValue(parentPrimary, cursor); |
||||
if (old == null || ppValue != old) { //当主键不同时,表示是不同的父表数据
|
||||
old = ppValue; |
||||
if (tempParent.get(old) == null) { |
||||
P pEntity = parent.newInstance(); |
||||
String pPrimaryName = ""; |
||||
for (int i = 0, len = pColumnAlias.size(); i < len; i++) { |
||||
Field pField = pColumn.get(i); |
||||
pField.setAccessible(true); |
||||
Class<?> type = pField.getType(); |
||||
int column = cursor.getColumnIndex(pColumnAlias.get(i)); |
||||
if (column == -1) continue; |
||||
setFieldValue(type, pField, column, cursor, pEntity); |
||||
|
||||
if (SqlUtil.isPrimary(pField) && (type == int.class || type == Integer.class)) { |
||||
pPrimaryName = pField.getName(); |
||||
} |
||||
} |
||||
|
||||
//当设置了主键,而且主键的类型为integer时,查询RowID等于主键
|
||||
pEntity.rowID = cursor.getInt( |
||||
cursor.getColumnIndex( |
||||
TextUtils.isEmpty(pPrimaryName) ? PARENT_COLUMN_ALIAS.concat("rowid") |
||||
: pPrimaryName)); |
||||
|
||||
tempParent.put(ppValue, pEntity); |
||||
} |
||||
} |
||||
|
||||
// 创建子实体
|
||||
C cEntity = child.newInstance(); |
||||
String cPrimaryName = ""; |
||||
for (int i = 0, len = cColumnAlias.size(); i < len; i++) { |
||||
Field cField = cColumn.get(i); |
||||
cField.setAccessible(true); |
||||
Class<?> type = cField.getType(); |
||||
|
||||
int column = cursor.getColumnIndex(cColumnAlias.get(i)); |
||||
if (column == -1) continue; |
||||
setFieldValue(type, cField, column, cursor, cEntity); |
||||
|
||||
if (SqlUtil.isPrimary(cField) && (type == int.class || type == Integer.class)) { |
||||
cPrimaryName = cField.getName(); |
||||
} |
||||
} |
||||
//当设置了主键,而且主键的类型为integer时,查询RowID等于主键
|
||||
cEntity.rowID = cursor.getInt( |
||||
cursor.getColumnIndex( |
||||
TextUtils.isEmpty(cPrimaryName) ? CHILD_COLUMN_ALIAS.concat("rowid") |
||||
: cPrimaryName)); |
||||
if (tempChild.get(old) == null) { |
||||
tempChild.put(old, new ArrayList<C>()); |
||||
} |
||||
tempChild.get(old).add(cEntity); |
||||
} |
||||
|
||||
List<Field> wFields = SqlUtil.getAllNotIgnoreField(clazz); |
||||
if (wFields != null && !wFields.isEmpty()) { |
||||
Set<Object> pKeys = tempParent.keySet(); |
||||
for (Object pk : pKeys) { |
||||
T wrapper = clazz.newInstance(); |
||||
P p = tempParent.get(pk); |
||||
boolean isPSet = false, isCSet = false; |
||||
for (Field f : wFields) { |
||||
if (!isPSet && f.getAnnotation(One.class) != null) { |
||||
f.set(wrapper, p); |
||||
isPSet = true; |
||||
} |
||||
if (!isCSet && f.getAnnotation(Many.class) != null) { |
||||
f.set(wrapper, tempChild.get(pk)); |
||||
isCSet = true; |
||||
} |
||||
} |
||||
wrapper.handleConvert(); //处理下转换
|
||||
wrappers.add(wrapper); |
||||
} |
||||
} |
||||
return wrappers; |
||||
} catch (InstantiationException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* 获取父表主键数据 |
||||
* |
||||
* @param parentPrimary 父表主键别名 |
||||
*/ |
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB) private Object setPPValue(String parentPrimary, |
||||
Cursor cursor) { |
||||
Object ppValue = null; |
||||
int ppColumn = cursor.getColumnIndex(parentPrimary); //父表主键所在的列
|
||||
int type = cursor.getType(ppColumn); |
||||
switch (type) { |
||||
case Cursor.FIELD_TYPE_INTEGER: |
||||
ppValue = cursor.getLong(ppColumn); |
||||
break; |
||||
case Cursor.FIELD_TYPE_FLOAT: |
||||
ppValue = cursor.getFloat(ppColumn); |
||||
break; |
||||
case Cursor.FIELD_TYPE_STRING: |
||||
ppValue = cursor.getString(ppColumn); |
||||
break; |
||||
} |
||||
return ppValue; |
||||
} |
||||
|
||||
/** |
||||
* 条件查寻数据 |
||||
*/ |
||||
<T extends DbEntity> List<T> findData(SQLiteDatabase db, Class<T> clazz, String... expression) { |
||||
db = checkDb(db); |
||||
CheckUtil.checkSqlExpression(expression); |
||||
String sql = |
||||
"SELECT rowid, * FROM " + CommonUtil.getClassName(clazz) + " WHERE " + expression[0] + " "; |
||||
sql = sql.replace("?", "%s"); |
||||
Object[] params = new String[expression.length - 1]; |
||||
for (int i = 0, len = params.length; i < len; i++) { |
||||
params[i] = "'" + convertValue(expression[i + 1]) + "'"; |
||||
} |
||||
sql = String.format(sql, params); |
||||
print(FIND_DATA, sql); |
||||
Cursor cursor = db.rawQuery(sql, null); |
||||
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null; |
||||
closeCursor(cursor); |
||||
close(db); |
||||
return data; |
||||
} |
||||
|
||||
/** |
||||
* 查找表的所有数据 |
||||
*/ |
||||
<T extends DbEntity> List<T> findAllData(SQLiteDatabase db, Class<T> clazz) { |
||||
db = checkDb(db); |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("SELECT rowid, * FROM ").append(CommonUtil.getClassName(clazz)); |
||||
print(FIND_ALL_DATA, sb.toString()); |
||||
Cursor cursor = db.rawQuery(sb.toString(), null); |
||||
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null; |
||||
closeCursor(cursor); |
||||
close(db); |
||||
return data; |
||||
} |
||||
|
||||
/** |
||||
* 根据数据游标创建一个具体的对象 |
||||
*/ |
||||
private <T extends DbEntity> List<T> newInstanceEntity(Class<T> clazz, Cursor cursor) { |
||||
List<Field> fields = CommonUtil.getAllFields(clazz); |
||||
List<T> entitys = new ArrayList<>(); |
||||
if (fields != null && fields.size() > 0) { |
||||
try { |
||||
while (cursor.moveToNext()) { |
||||
T entity = clazz.newInstance(); |
||||
String primaryName = ""; |
||||
for (Field field : fields) { |
||||
field.setAccessible(true); |
||||
if (SqlUtil.isIgnore(field)) { |
||||
continue; |
||||
} |
||||
|
||||
Class<?> type = field.getType(); |
||||
if (SqlUtil.isPrimary(field) && (type == int.class || type == Integer.class)) { |
||||
primaryName = field.getName(); |
||||
} |
||||
|
||||
int column = cursor.getColumnIndex(field.getName()); |
||||
if (column == -1) continue; |
||||
setFieldValue(type, field, column, cursor, entity); |
||||
} |
||||
//当设置了主键,而且主键的类型为integer时,查询RowID等于主键
|
||||
entity.rowID = cursor.getInt( |
||||
cursor.getColumnIndex(TextUtils.isEmpty(primaryName) ? "rowid" : primaryName)); |
||||
//mDataCache.put(getCacheKey(entity), entity);
|
||||
entitys.add(entity); |
||||
} |
||||
closeCursor(cursor); |
||||
} catch (InstantiationException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
return entitys; |
||||
} |
||||
|
||||
/** |
||||
* 设置字段的值 |
||||
* |
||||
* @throws IllegalAccessException |
||||
*/ |
||||
private void setFieldValue(Class type, Field field, int column, Cursor cursor, Object entity) |
||||
throws IllegalAccessException { |
||||
if (type == String.class) { |
||||
String temp = cursor.getString(column); |
||||
if (!TextUtils.isEmpty(temp)) { |
||||
field.set(entity, URLDecoder.decode(temp)); |
||||
} |
||||
} else if (type == int.class || type == Integer.class) { |
||||
field.setInt(entity, cursor.getInt(column)); |
||||
} else if (type == float.class || type == Float.class) { |
||||
field.setFloat(entity, cursor.getFloat(column)); |
||||
} else if (type == double.class || type == Double.class) { |
||||
field.setDouble(entity, cursor.getDouble(column)); |
||||
} else if (type == long.class || type == Long.class) { |
||||
field.setLong(entity, cursor.getLong(column)); |
||||
} else if (type == boolean.class || type == Boolean.class) { |
||||
String temp = cursor.getString(column); |
||||
if (TextUtils.isEmpty(temp)) { |
||||
field.setBoolean(entity, false); |
||||
} else { |
||||
field.setBoolean(entity, !temp.equalsIgnoreCase("false")); |
||||
} |
||||
} else if (type == java.util.Date.class || type == java.sql.Date.class) { |
||||
field.set(entity, new Date(cursor.getString(column))); |
||||
} else if (type == byte[].class) { |
||||
field.set(entity, cursor.getBlob(column)); |
||||
} else if (type == Map.class) { |
||||
String temp = cursor.getString(column); |
||||
if (!TextUtils.isEmpty(temp)) { |
||||
field.set(entity, SqlUtil.str2Map(temp)); |
||||
} |
||||
} else if (type == List.class) { |
||||
String value = cursor.getString(column); |
||||
if (!TextUtils.isEmpty(value)) { |
||||
field.set(entity, SqlUtil.str2List(value, field)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取所在行Id |
||||
*/ |
||||
int[] getRowId(SQLiteDatabase db, Class clazz) { |
||||
db = checkDb(db); |
||||
Cursor cursor = db.rawQuery("SELECT rowid, * FROM " + CommonUtil.getClassName(clazz), null); |
||||
int[] ids = new int[cursor.getCount()]; |
||||
int i = 0; |
||||
while (cursor.moveToNext()) { |
||||
ids[i] = cursor.getInt(cursor.getColumnIndex("rowid")); |
||||
i++; |
||||
} |
||||
cursor.close(); |
||||
close(db); |
||||
return ids; |
||||
} |
||||
|
||||
/** |
||||
* 获取行Id |
||||
*/ |
||||
int getRowId(SQLiteDatabase db, Class clazz, Object[] wheres, Object[] values) { |
||||
db = checkDb(db); |
||||
if (wheres.length <= 0 || values.length <= 0) { |
||||
ALog.e(TAG, "请输入删除条件"); |
||||
return -1; |
||||
} else if (wheres.length != values.length) { |
||||
ALog.e(TAG, "groupName 和 vaule 长度不相等"); |
||||
return -1; |
||||
} |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("SELECT rowid FROM ").append(CommonUtil.getClassName(clazz)).append(" WHERE "); |
||||
int i = 0; |
||||
for (Object where : wheres) { |
||||
sb.append(where).append("=").append("'").append(values[i]).append("'"); |
||||
sb.append(i >= wheres.length - 1 ? "" : ","); |
||||
i++; |
||||
} |
||||
print(ROW_ID, sb.toString()); |
||||
Cursor c = db.rawQuery(sb.toString(), null); |
||||
int id = c.getColumnIndex("rowid"); |
||||
c.close(); |
||||
close(db); |
||||
return id; |
||||
} |
||||
|
||||
/** |
||||
* 通过rowId判断数据是否存在 |
||||
*/ |
||||
<T extends DbEntity> boolean itemExist(SQLiteDatabase db, Class<T> clazz, |
||||
long rowId) { |
||||
db = checkDb(db); |
||||
String sql = "SELECT rowid FROM " + CommonUtil.getClassName(clazz) + " WHERE rowid=" + rowId; |
||||
print(ROW_ID, sql); |
||||
Cursor cursor = db.rawQuery(sql, null); |
||||
boolean isExist = cursor.getCount() > 0; |
||||
cursor.close(); |
||||
return isExist; |
||||
} |
||||
} |
@ -0,0 +1,69 @@ |
||||
/* |
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.arialyy.aria.orm; |
||||
|
||||
import android.util.SparseArray; |
||||
import java.lang.reflect.Constructor; |
||||
import java.lang.reflect.InvocationTargetException; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/22. |
||||
* Delegate管理器 |
||||
*/ |
||||
class DelegateManager { |
||||
private final String TAG = "ModuleFactory"; |
||||
|
||||
private SparseArray<AbsDelegate> mDelegates = new SparseArray<>(); |
||||
private static volatile DelegateManager INSTANCE = null; |
||||
|
||||
private DelegateManager() { |
||||
|
||||
} |
||||
|
||||
static DelegateManager getInstance() { |
||||
if (INSTANCE == null) { |
||||
synchronized (DelegateManager.class) { |
||||
INSTANCE = new DelegateManager(); |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
/** |
||||
* 获取Module |
||||
*/ |
||||
<M extends AbsDelegate> M getDelegate(Class<M> clazz) { |
||||
M delegate = (M) mDelegates.get(clazz.hashCode()); |
||||
try { |
||||
if (delegate == null) { |
||||
Constructor c = clazz.getDeclaredConstructor(); |
||||
c.setAccessible(true); |
||||
delegate = (M) c.newInstance(); |
||||
mDelegates.put(clazz.hashCode(), delegate); |
||||
return delegate; |
||||
} |
||||
} catch (InstantiationException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} catch (NoSuchMethodException e) { |
||||
e.printStackTrace(); |
||||
} catch (InvocationTargetException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return delegate; |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue