pull/330/head
laoyuyu 7 years ago
parent 2db3579f46
commit 2ef9550d86
  1. 4
      Aria/src/main/java/com/arialyy/aria/core/AriaManager.java
  2. 47
      Aria/src/main/java/com/arialyy/aria/core/command/normal/CancelAllCmd.java
  3. 2
      Aria/src/main/java/com/arialyy/aria/core/command/normal/StartCmd.java
  4. 10
      Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java
  5. 2
      Aria/src/main/java/com/arialyy/aria/core/common/TaskRecord.java
  6. 3
      Aria/src/main/java/com/arialyy/aria/core/delegate/HttpHeaderDelegate.java
  7. 4
      Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java
  8. 12
      Aria/src/main/java/com/arialyy/aria/core/download/BaseNormalTarget.java
  9. 11
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadEntity.java
  10. 10
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupEntity.java
  11. 27
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java
  12. 24
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTaskEntity.java
  13. 44
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTaskWrapper.java
  14. 41
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupWrapper.java
  15. 72
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java
  16. 1
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java
  17. 21
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java
  18. 44
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskWrapper.java
  19. 12
      Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java
  20. 1
      Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java
  21. 37
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java
  22. 6
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpDirDownloadUtil.java
  23. 5
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java
  24. 2
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsEntity.java
  25. 15
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupEntity.java
  26. 2
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsNormalEntity.java
  27. 24
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java
  28. 15
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskEntity.java
  29. 2
      Aria/src/main/java/com/arialyy/aria/core/inf/IEntity.java
  30. 2
      Aria/src/main/java/com/arialyy/aria/core/inf/IUploadListener.java
  31. 72
      Aria/src/main/java/com/arialyy/aria/core/manager/DGTEntityFactory.java
  32. 23
      Aria/src/main/java/com/arialyy/aria/core/manager/DTEntityFactory.java
  33. 4
      Aria/src/main/java/com/arialyy/aria/core/manager/ITEntityFactory.java
  34. 60
      Aria/src/main/java/com/arialyy/aria/core/manager/TEManager.java
  35. 86
      Aria/src/main/java/com/arialyy/aria/core/manager/TaskManager.java
  36. 24
      Aria/src/main/java/com/arialyy/aria/core/manager/UTEntityFactory.java
  37. 2
      Aria/src/main/java/com/arialyy/aria/core/queue/DownloadGroupTaskQueue.java
  38. 13
      Aria/src/main/java/com/arialyy/aria/core/upload/BaseNormalTarget.java
  39. 6
      Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java
  40. 9
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadEntity.java
  41. 4
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java
  42. 6
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java
  43. 45
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskWrapper.java
  44. 162
      Aria/src/main/java/com/arialyy/aria/orm/AbsDelegate.java
  45. 17
      Aria/src/main/java/com/arialyy/aria/orm/AbsWrapper.java
  46. 62
      Aria/src/main/java/com/arialyy/aria/orm/ActionPolicy.java
  47. 10
      Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java
  48. 110
      Aria/src/main/java/com/arialyy/aria/orm/DatabaseContext.java
  49. 74
      Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java
  50. 249
      Aria/src/main/java/com/arialyy/aria/orm/DbUtil.java
  51. 221
      Aria/src/main/java/com/arialyy/aria/orm/DelegateCommon.java
  52. 512
      Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java
  53. 69
      Aria/src/main/java/com/arialyy/aria/orm/DelegateManager.java
  54. 186
      Aria/src/main/java/com/arialyy/aria/orm/DelegateUpdate.java
  55. 155
      Aria/src/main/java/com/arialyy/aria/orm/DelegateWrapper.java
  56. 32
      Aria/src/main/java/com/arialyy/aria/orm/NormalList.java
  57. 716
      Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java
  58. 114
      Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java
  59. 18
      Aria/src/main/java/com/arialyy/aria/orm/annotation/Default.java
  60. 50
      Aria/src/main/java/com/arialyy/aria/orm/annotation/Foreign.java
  61. 2
      Aria/src/main/java/com/arialyy/aria/orm/annotation/Ignore.java
  62. 13
      Aria/src/main/java/com/arialyy/aria/orm/annotation/Many.java
  63. 2
      Aria/src/main/java/com/arialyy/aria/orm/annotation/NoNull.java
  64. 15
      Aria/src/main/java/com/arialyy/aria/orm/annotation/One.java
  65. 7
      Aria/src/main/java/com/arialyy/aria/orm/annotation/Primary.java
  66. 30
      Aria/src/main/java/com/arialyy/aria/orm/annotation/Table.java
  67. 17
      Aria/src/main/java/com/arialyy/aria/orm/annotation/Wrapper.java
  68. 2
      Aria/src/main/java/com/arialyy/aria/util/ALog.java
  69. 28
      Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java
  70. 152
      Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java
  71. 2
      Aria/src/main/java/com/arialyy/aria/util/ErrorHelp.java
  72. 4
      app/src/main/java/com/arialyy/simple/download/group/DownloadGroupActivity.java
  73. 2
      app/src/main/java/com/arialyy/simple/download/group/FTPDirDownloadActivity.java
  74. 6
      app/src/main/java/com/arialyy/simple/download/multi_download/MultiDownloadActivity.java
  75. 19
      aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java

@ -41,7 +41,7 @@ import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadReceiver;
import com.arialyy.aria.core.upload.UploadTaskEntity;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.DbUtil;
import com.arialyy.aria.orm.DelegateWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import java.io.File;
@ -77,7 +77,7 @@ import org.xml.sax.SAXException;
private Configuration.UploadConfig mUConfig;
private AriaManager(Context context) {
DbUtil.init(context.getApplicationContext());
DelegateWrapper.init(context.getApplicationContext());
APP = context.getApplicationContext();
regAppLifeCallback(context);
initConfig();

@ -16,13 +16,7 @@
package com.arialyy.aria.core.command.normal;
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.core.upload.UploadTaskEntity;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.CommonUtil;
import java.util.List;
/**
* Created by AriaL on 2017/6/27.
@ -44,46 +38,5 @@ public class CancelAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
@Override public void executeCmd() {
removeAll();
if (mTaskEntity instanceof DownloadTaskEntity
|| mTaskEntity instanceof DownloadGroupTaskEntity) {
handleDownloadRemove();
handleDownloadGroupRemove();
} else if (mTaskEntity instanceof UploadTaskEntity) {
handleUploadRemove();
handleUploadRemove();
}
}
/**
* 处理下载任务组的删除操作
*/
private void handleDownloadGroupRemove() {
List<DownloadGroupTaskEntity> allEntity = DbEntity.findAllData(DownloadGroupTaskEntity.class);
if (allEntity == null || allEntity.size() == 0) return;
for (DownloadGroupTaskEntity entity : allEntity) {
CommonUtil.delDownloadGroupTaskConfig(removeFile, entity);
}
}
/**
* 处理上传的删除
*/
private void handleUploadRemove() {
List<UploadTaskEntity> allEntity = DbEntity.findAllData(UploadTaskEntity.class);
if (allEntity == null || allEntity.size() == 0) return;
for (UploadTaskEntity entity : allEntity) {
CommonUtil.delUploadTaskConfig(removeFile, entity);
}
}
/**
* 处理下载的删除
*/
private void handleDownloadRemove() {
List<DownloadTaskEntity> allEntity = DbEntity.findAllData(DownloadTaskEntity.class);
if (allEntity == null || allEntity.size() == 0) return;
for (DownloadTaskEntity entity : allEntity) {
CommonUtil.delDownloadTaskConfig(removeFile, entity);
}
}
}

@ -77,7 +77,6 @@ class StartCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
|| task.getState() == IEntity.STATE_OTHER
|| task.getState() == IEntity.STATE_POST_PRE
|| task.getState() == IEntity.STATE_COMPLETE) {
//startTask();
resumeTask();
} else {
sendWaitState();
@ -85,7 +84,6 @@ class StartCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
}
} else {
if (!task.isRunning()) {
//startTask();
resumeTask();
}
}

@ -18,11 +18,13 @@ package com.arialyy.aria.core.common;
import android.content.Context;
import android.util.SparseArray;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.AbsNormalEntity;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.IDownloadListener;
import com.arialyy.aria.core.inf.IEventListener;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTaskEntity;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
@ -89,7 +91,6 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
}
}
@Override public void run() {
if (mConstance.isRunning) {
return;
@ -193,9 +194,11 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
}
}
if (mTaskEntity instanceof DownloadTaskEntity) {
CommonUtil.delDownloadTaskConfig(mTaskEntity.removeFile, (DownloadTaskEntity) mTaskEntity);
CommonUtil.delDownloadTaskConfig(mTaskEntity.removeFile,
(DownloadEntity) mTaskEntity.getEntity());
} else if (mTaskEntity instanceof UploadTaskEntity) {
CommonUtil.delUploadTaskConfig(mTaskEntity.removeFile, (UploadTaskEntity) mTaskEntity);
CommonUtil.delUploadTaskConfig(mTaskEntity.removeFile,
(UploadEntity) mTaskEntity.getEntity());
}
}
@ -226,7 +229,6 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
start();
}
/**
* 检查任务是否是新任务新任务条件
* 1文件不存在

@ -21,7 +21,7 @@ import com.arialyy.aria.orm.DbEntity;
* Created by laoyuyu on 2018/3/21.
* 任务上传或下载的记录
*/
class TaskRecord extends DbEntity{
class TaskRecord extends DbEntity {
/**
* 任务线程数
*/

@ -63,10 +63,8 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
}
if (mTaskEntity.headers.get(key) == null) {
mTaskEntity.headers.put(key, value);
mTaskEntity.update();
} else if (!mTaskEntity.headers.get(key).equals(value)) {
mTaskEntity.headers.put(key, value);
mTaskEntity.update();
}
return mTarget;
}
@ -122,7 +120,6 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
for (String key : keys) {
mTaskEntity.headers.put(key, headers.get(key));
}
mTaskEntity.update();
}
return mTarget;

@ -18,7 +18,6 @@ package com.arialyy.aria.core.download;
import android.text.TextUtils;
import com.arialyy.aria.core.manager.SubTaskManager;
import com.arialyy.aria.core.queue.DownloadGroupTaskQueue;
import com.arialyy.aria.core.queue.DownloadTaskQueue;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog;
import java.io.File;
@ -29,7 +28,6 @@ import java.util.List;
*/
abstract class BaseGroupTarget<TARGET extends BaseGroupTarget>
extends AbsDownloadTarget<TARGET, DownloadGroupEntity, DownloadGroupTaskEntity> {
private static final String TAG = "BaseGroupTarget";
/**
* 组任务名
@ -60,7 +58,6 @@ abstract class BaseGroupTarget<TARGET extends BaseGroupTarget>
public TARGET setGroupAlias(String alias) {
if (TextUtils.isEmpty(alias)) return (TARGET) this;
mEntity.setAlias(alias);
mEntity.update();
return (TARGET) this;
}
@ -158,7 +155,6 @@ abstract class BaseGroupTarget<TARGET extends BaseGroupTarget>
}
mEntity.setDirPath(dirPath);
reChangeDirPath(dirPath);
mEntity.update();
}
return true;

@ -29,7 +29,6 @@ import java.io.File;
abstract class BaseNormalTarget<TARGET extends BaseNormalTarget>
extends AbsDownloadTarget<TARGET, DownloadEntity, DownloadTaskEntity> {
private static final String TAG = "BaseNormalTarget";
/**
* 资源地址
*/
@ -42,9 +41,6 @@ abstract class BaseNormalTarget<TARGET extends BaseNormalTarget>
this.url = url;
mTargetName = targetName;
mTaskEntity = TEManager.getInstance().getTEntity(DownloadTaskEntity.class, url);
if (mTaskEntity == null) {
mTaskEntity = TEManager.getInstance().createTEntity(DownloadTaskEntity.class, url);
}
mEntity = mTaskEntity.entity;
mTaskEntity.refreshInfo = refreshInfo;
if (mEntity != null) {
@ -110,7 +106,11 @@ abstract class BaseNormalTarget<TARGET extends BaseNormalTarget>
* @return {@code true}合法
*/
@Override protected boolean checkEntity() {
return getTargetType() < GROUP_HTTP && checkUrl() && checkFilePath();
boolean b = getTargetType() < GROUP_HTTP && checkUrl() && checkFilePath();
if (b) {
mTaskEntity.save(mEntity);
}
return b;
}
/**
@ -149,7 +149,7 @@ abstract class BaseNormalTarget<TARGET extends BaseNormalTarget>
mEntity.setDownloadPath(filePath);
mEntity.setFileName(newFile.getName());
mTaskEntity.key = filePath;
mTaskEntity.update();
//mTaskEntity.update();
CommonUtil.renameDownloadConfig(oldFile.getName(), newFile.getName());
}
}

@ -21,8 +21,8 @@ import android.os.Parcelable;
import android.text.TextUtils;
import com.arialyy.aria.core.inf.AbsNormalEntity;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.orm.Foreign;
import com.arialyy.aria.orm.Primary;
import com.arialyy.aria.orm.annotation.Foreign;
import com.arialyy.aria.orm.annotation.Primary;
import com.arialyy.aria.util.CommonUtil;
/**
@ -35,12 +35,7 @@ public class DownloadEntity extends AbsNormalEntity implements Parcelable {
/**
* 所属任务组
*/
@Foreign(table = DownloadGroupEntity.class, column = "groupName") private String groupName = "";
/**
* 下载任务实体的key
*/
@Foreign(table = DownloadTaskEntity.class, column = "key") private String taskKey = "";
@Foreign(parent = DownloadGroupEntity.class, column = "groupName") private String groupName = "";
/**
* 从服务器的返回信息中获取的文件md5信息如果服务器没有返回则不会设置该信息

@ -18,8 +18,7 @@ package com.arialyy.aria.core.download;
import android.os.Parcel;
import com.arialyy.aria.core.inf.AbsGroupEntity;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.orm.OneToMany;
import java.util.ArrayList;
import com.arialyy.aria.orm.annotation.Ignore;
import java.util.List;
/**
@ -28,8 +27,11 @@ import java.util.List;
*/
public class DownloadGroupEntity extends AbsGroupEntity {
@OneToMany(table = DownloadEntity.class, key = "groupName") private List<DownloadEntity> subtask =
new ArrayList<>();
//@OneToMany(table = DownloadEntity.class, key = "groupName") private List<DownloadEntity> subtask =
// new ArrayList<>();
@Ignore
private List<DownloadEntity> subtask;
/**
* 任务组下载文件的文件夹地址

@ -24,16 +24,13 @@ import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
/**
* Created by AriaL on 2017/6/29.
* 下载任务组
*/
public class DownloadGroupTarget extends BaseGroupTarget<DownloadGroupTarget> {
private final String TAG = "DownloadGroupTarget";
/**
* 子任务下载地址
*/
@ -50,12 +47,8 @@ public class DownloadGroupTarget extends BaseGroupTarget<DownloadGroupTarget> {
this.mUrls.addAll(groupEntity.getUrls());
}
mGroupName = CommonUtil.getMd5Code(groupEntity.getUrls());
mTaskEntity = TEManager.getInstance().getTEntity(DownloadGroupTaskEntity.class, mGroupName);
if (mTaskEntity == null) {
mTaskEntity =
TEManager.getInstance().createTEntity(DownloadGroupTaskEntity.class, groupEntity);
}
mEntity = mTaskEntity.entity;
mTaskEntity = TEManager.getInstance().getGTEntity(DownloadGroupTaskEntity.class, mUrls);
mEntity = mTaskEntity.getEntity();
if (mEntity != null) {
mDirPathTemp = mEntity.getDirPath();
@ -66,11 +59,8 @@ public class DownloadGroupTarget extends BaseGroupTarget<DownloadGroupTarget> {
this.mTargetName = targetName;
this.mUrls = urls;
mGroupName = CommonUtil.getMd5Code(urls);
mTaskEntity = TEManager.getInstance().getTEntity(DownloadGroupTaskEntity.class, mGroupName);
if (mTaskEntity == null) {
mTaskEntity = TEManager.getInstance().createGTEntity(DownloadGroupTaskEntity.class, mUrls);
}
mEntity = mTaskEntity.entity;
mTaskEntity = TEManager.getInstance().getGTEntity(DownloadGroupTaskEntity.class, mUrls);
mEntity = mTaskEntity.getEntity();
}
/**
@ -88,7 +78,6 @@ public class DownloadGroupTarget extends BaseGroupTarget<DownloadGroupTarget> {
}
if (mEntity.getFileSize() <= 1 || mEntity.getFileSize() != fileSize) {
mEntity.setFileSize(fileSize);
mEntity.update();
}
return this;
}
@ -137,7 +126,8 @@ public class DownloadGroupTarget extends BaseGroupTarget<DownloadGroupTarget> {
entity.setGroupName(mGroupName);
entity.setGroupChild(true);
entity.setFileName(fileName);
entity.insert();
// TODO: 2018/4/3 是否需要在这个插入?
//entity.insert();
list.add(entity);
}
return list;
@ -164,7 +154,6 @@ public class DownloadGroupTarget extends BaseGroupTarget<DownloadGroupTarget> {
//文件夹路径通过后,并且该实体没有子任务,则创建子任务
if (mEntity.getSubTask() == null || mEntity.getSubTask().isEmpty()) {
mEntity.setSubTasks(createSubTask());
mTaskEntity.update();
} else {
updateSingleSubFileName();
}
@ -230,7 +219,6 @@ public class DownloadGroupTarget extends BaseGroupTarget<DownloadGroupTarget> {
}
mEntity.setGroupName(CommonUtil.getMd5Code(mUrls));
mEntity.update();
return true;
}
@ -251,7 +239,8 @@ public class DownloadGroupTarget extends BaseGroupTarget<DownloadGroupTarget> {
"UPDATE DownloadTaskEntity SET key='" + newPath + "' WHERE key='" + oldPath + "'");
entity.setDownloadPath(newPath);
entity.setFileName(newName);
entity.update();
// TODO: 2018/4/3 是否需要在这个更新?
//entity.update();
}
}

@ -16,24 +16,42 @@
package com.arialyy.aria.core.download;
import com.arialyy.aria.core.inf.AbsGroupTaskEntity;
import com.arialyy.aria.orm.OneToOne;
import com.arialyy.aria.orm.annotation.Foreign;
import com.arialyy.aria.orm.annotation.Ignore;
import com.arialyy.aria.orm.annotation.Primary;
/**
* Created by AriaL on 2017/7/1.
*/
public class DownloadGroupTaskEntity extends AbsGroupTaskEntity<DownloadGroupEntity> {
@OneToOne(table = DownloadGroupEntity.class, key = "groupName") public DownloadGroupEntity entity;
@Ignore private DownloadGroupEntity entity;
@Primary @Foreign(parent = DownloadGroupEntity.class, column = "groupName")
private String key;
@Override public DownloadGroupEntity getEntity() {
return entity;
}
public void setEntity(DownloadGroupEntity entity) {
this.entity = entity;
}
@Override public String getKey() {
return key;
}
public void save(DownloadGroupEntity groupEntity){
public void setKey(String key) {
this.key = key;
}
public void save(DownloadGroupEntity groupEntity) {
if (groupEntity != null) {
key = groupEntity.getKey();
entity = groupEntity;
groupEntity.save();
}
save();
}
}

@ -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;
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 DownloadGroupTaskWrapper extends AbsWrapper {
@One
public DownloadGroupEntity entity;
@Many(parentColumn = "key", entityColumn = "groupName")
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);
}
}
}

@ -0,0 +1,41 @@
/*
* 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.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 DownloadGroupWrapper 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.setSubTasks(subEntity);
}
}
}

@ -25,9 +25,11 @@ import com.arialyy.aria.core.common.ProxyHelper;
import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.core.inf.AbsReceiver;
import com.arialyy.aria.core.inf.AbsTarget;
import com.arialyy.aria.core.manager.TEManager;
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers;
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import java.util.ArrayList;
@ -106,14 +108,14 @@ public class DownloadReceiver extends AbsReceiver {
* </pre>
*/
@Deprecated public DownloadTarget load(@NonNull String url, boolean refreshInfo) {
url = CheckUtil.checkUrl(url);
CheckUtil.checkUrlInvalidThrow(url);
return new DownloadTarget(url, targetName, refreshInfo);
}
/**
* 加载下载地址如果任务组的中的下载地址改变了则任务从新的一个任务组
*
* @param urls 人刷谁
* @param urls 任务组子任务下载地址列表
*/
@Deprecated
public DownloadGroupTarget load(List<String> urls) {
@ -173,7 +175,7 @@ public class DownloadReceiver extends AbsReceiver {
* @param refreshInfo 是否刷新下载信息
*/
public FtpDownloadTarget loadFtp(@NonNull String url, boolean refreshInfo) {
url = CheckUtil.checkUrl(url);
CheckUtil.checkUrlInvalidThrow(url);
return new FtpDownloadTarget(url, targetName, refreshInfo);
}
@ -203,7 +205,7 @@ public class DownloadReceiver extends AbsReceiver {
* 加载ftp文件夹下载地址
*/
public FtpDirDownloadTarget loadFtpDir(@NonNull String dirUrl) {
dirUrl = CheckUtil.checkUrl(dirUrl);
CheckUtil.checkUrlInvalidThrow(dirUrl);
return new FtpDirDownloadTarget(dirUrl, targetName);
}
@ -257,39 +259,55 @@ public class DownloadReceiver extends AbsReceiver {
/**
* 通过下载链接获取下载实体
*
* @return 如果url错误或查找不到数据则返回null
*/
public DownloadEntity getDownloadEntity(String downloadUrl) {
downloadUrl = CheckUtil.checkUrl(downloadUrl);
if (CheckUtil.checkUrl(downloadUrl)) {
return null;
}
return DbEntity.findFirst(DownloadEntity.class, "url=? and isGroupChild='false'", downloadUrl);
}
/**
* 通过下载链接获取保存在数据库的下载任务实体
* 通过下载地址和文件保存路径获取下载任务实体
*
* @param downloadUrl 下载地址
* @return 如果url错误或查找不到数据则返回null
*/
public DownloadTaskEntity getDownloadTask(String downloadUrl) {
downloadUrl = CheckUtil.checkUrl(downloadUrl);
DownloadEntity entity = getDownloadEntity(downloadUrl);
if (entity == null || TextUtils.isEmpty(entity.getDownloadPath())) return null;
return DbEntity.findFirst(DownloadTaskEntity.class, "key=? and isGroupTask='false'",
entity.getDownloadPath());
if (CheckUtil.checkUrl(downloadUrl)) {
return null;
}
return TEManager.getInstance().getTEntity(DownloadTaskEntity.class, downloadUrl);
}
/**
* 通过下载链接获取保存在数据库的下载任务组实体
*
* @param urls 任务组子任务下载地址列表
* @return 返回对应的任务组实体如果查找不到对应的数据或子任务列表为null返回null
*/
public DownloadGroupTaskEntity getDownloadGroupTask(List<String> urls) {
CheckUtil.checkDownloadUrls(urls);
String hashCode = CommonUtil.getMd5Code(urls);
return DbEntity.findFirst(DownloadGroupTaskEntity.class, "key=?", hashCode);
public DownloadGroupTaskEntity getGroupTask(List<String> urls) {
if (urls == null || urls.isEmpty()) {
ALog.e(TAG, "获取任务组实体失败:任务组子任务下载地址列表为null");
return null;
}
return TEManager.getInstance().getGTEntity(DownloadGroupTaskEntity.class, urls);
}
/**
* 通过任务组key获取任务组实体
* 如果是httpkey为所有子任务下载地址拼接后取md5
* 如果是ftpkey为ftp服务器的文件夹路径
* 获取FTP文件夹下载任务实体
*
* @param dirPath FTP文件夹本地保存路径
* @return 返回对应的任务组实体如果查找不到对应的数据或路径为null返回null
*/
public DownloadGroupTaskEntity getDownloadGroupTask(String key) {
return DbEntity.findFirst(DownloadGroupTaskEntity.class, "key=?", key);
public DownloadGroupTaskEntity getFtpDirTask(String dirPath) {
if (TextUtils.isEmpty(dirPath)) {
ALog.e(TAG, "获取FTP文件夹实体失败:文件夹路径为null");
return null;
}
return TEManager.getInstance().getTEntity(DownloadGroupTaskEntity.class, dirPath);
}
/**
@ -327,15 +345,25 @@ public class DownloadReceiver extends AbsReceiver {
/**
* 获取任务组列表
*
* @return 如果没有任务组列表则返回null
*/
public List<DownloadGroupEntity> getGroupTaskList() {
return DownloadEntity.findAllData(DownloadGroupEntity.class);
List<DownloadGroupWrapper> wrappers = DbEntity.findRelationData(DownloadGroupWrapper.class);
if (wrappers == null || wrappers.isEmpty()) {
return null;
}
List<DownloadGroupEntity> entities = new ArrayList<>();
for (DownloadGroupWrapper wrapper : wrappers) {
entities.add(wrapper.groupEntity);
}
return entities;
}
/**
* 获取普通任务和任务组的任务列表
*/
public List<AbsEntity> getTotleTaskList() {
public List<AbsEntity> getTotalTaskList() {
List<AbsEntity> list = new ArrayList<>();
List<DownloadEntity> simpleTask = getTaskList();
List<DownloadGroupEntity> groupTask = getGroupTaskList();

@ -27,7 +27,6 @@ import java.util.Map;
*/
public class DownloadTarget extends BaseNormalTarget<DownloadTarget>
implements IHttpHeaderTarget<DownloadTarget> {
private static final String TAG = "DownloadTarget";
private HttpHeaderDelegate<DownloadTarget, DownloadEntity, DownloadTaskEntity> mDelegate;
DownloadTarget(DownloadEntity entity, String targetName) {

@ -16,17 +16,19 @@
package com.arialyy.aria.core.download;
import com.arialyy.aria.core.inf.AbsNormalTaskEntity;
import com.arialyy.aria.orm.Ignore;
import com.arialyy.aria.orm.NoNull;
import com.arialyy.aria.orm.OneToOne;
import com.arialyy.aria.orm.annotation.Foreign;
import com.arialyy.aria.orm.annotation.Ignore;
import com.arialyy.aria.orm.annotation.NoNull;
import com.arialyy.aria.orm.annotation.Primary;
/**
* Created by lyy on 2017/1/23.
* 下载任务实体
* 下载任务实体和下载实体为一对一关系下载实体删除任务实体自动删除
*/
public class DownloadTaskEntity extends AbsNormalTaskEntity<DownloadEntity> {
@OneToOne(table = DownloadEntity.class, key = "downloadPath") public DownloadEntity entity;
//@OneToOne(table = DownloadEntity.class, key = "downloadPath") public DownloadEntity entity;
@Ignore public DownloadEntity entity;
/**
* 任务的url
@ -48,6 +50,11 @@ public class DownloadTaskEntity extends AbsNormalTaskEntity<DownloadEntity> {
*/
public boolean isGroupTask = false;
/**
* Task实体对应的key
*/
@Primary @Foreign(parent = DownloadEntity.class, column = "downloadPath") public String key = "";
public DownloadTaskEntity() {
}
@ -55,6 +62,10 @@ public class DownloadTaskEntity extends AbsNormalTaskEntity<DownloadEntity> {
return entity;
}
@Override public String getKey() {
return key;
}
public void save(DownloadEntity entity) {
this.entity = entity;
if (entity != null) {

@ -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;
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 DownloadTaskWrapper 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.entity = entity;
}
}
}

@ -28,7 +28,6 @@ import com.arialyy.aria.util.ALog;
*/
public class FtpDirDownloadTarget extends BaseGroupTarget<FtpDirDownloadTarget>
implements IFtpTarget<FtpDirDownloadTarget> {
private final String TAG = "FtpDirDownloadTarget";
private FtpDelegate<FtpDirDownloadTarget, DownloadGroupEntity, DownloadGroupTaskEntity> mDelegate;
FtpDirDownloadTarget(String url, String targetName) {
@ -39,11 +38,8 @@ public class FtpDirDownloadTarget extends BaseGroupTarget<FtpDirDownloadTarget>
private void init(String key) {
mGroupName = key;
mTaskEntity = TEManager.getInstance().getTEntity(DownloadGroupTaskEntity.class, key);
if (mTaskEntity == null) {
mTaskEntity = TEManager.getInstance().createTEntity(DownloadGroupTaskEntity.class, key);
}
mTaskEntity.requestType = AbsTaskEntity.D_FTP_DIR;
mEntity = mTaskEntity.entity;
mEntity = mTaskEntity.getEntity();
if (mEntity != null) {
mDirPathTemp = mEntity.getDirPath();
}
@ -55,7 +51,11 @@ public class FtpDirDownloadTarget extends BaseGroupTarget<FtpDirDownloadTarget>
}
@Override protected boolean checkEntity() {
return getTargetType() == GROUP_FTP_DIR && checkDirPath() && checkUrl();
boolean b = getTargetType() == GROUP_FTP_DIR && checkDirPath() && checkUrl();
if (b) {
mTaskEntity.save(mEntity);
}
return b;
}
/**

@ -27,7 +27,6 @@ import com.arialyy.aria.util.CommonUtil;
*/
public class FtpDownloadTarget extends BaseNormalTarget<FtpDownloadTarget>
implements IFtpTarget<FtpDownloadTarget> {
private final String TAG = "FtpDownloadTarget";
private FtpDelegate<FtpDownloadTarget, DownloadEntity, DownloadTaskEntity> mDelegate;
FtpDownloadTarget(DownloadEntity entity, String targetName, boolean refreshInfo) {

@ -106,7 +106,7 @@ public abstract class AbsGroupUtil implements IUtil {
mGTEntity = groupEntity;
mExePool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
List<DownloadTaskEntity> tasks =
DbEntity.findDatas(DownloadTaskEntity.class, "groupName=?", mGTEntity.key);
DbEntity.findDatas(DownloadTaskEntity.class, "groupName=?", mGTEntity.getKey());
if (tasks != null && !tasks.isEmpty()) {
for (DownloadTaskEntity te : tasks) {
te.removeFile = mGTEntity.removeFile;
@ -114,10 +114,10 @@ public abstract class AbsGroupUtil implements IUtil {
mTasksMap.put(te.getEntity().getUrl(), te);
}
}
mGroupSize = mGTEntity.entity.getSubTask().size();
mGroupSize = mGTEntity.getEntity().getSubTask().size();
mTotalLen = groupEntity.getEntity().getFileSize();
isNeedLoadFileSize = mTotalLen <= 1;
for (DownloadEntity entity : mGTEntity.entity.getSubTask()) {
for (DownloadEntity entity : mGTEntity.getEntity().getSubTask()) {
File file = new File(entity.getDownloadPath());
if (entity.getState() == IEntity.STATE_COMPLETE && file.exists()) {
mCompleteNum++;
@ -190,9 +190,10 @@ public abstract class AbsGroupUtil implements IUtil {
* @param url 子任务下载地址
*/
public void cancelSubTask(String url) {
List<String> urls = mGTEntity.entity.getUrls();
List<String> urls = mGTEntity.getEntity().getUrls();
if (urls != null && !urls.isEmpty() && urls.contains(url)) {
urls.remove(url);
// TODO: 2018/4/4 有问题
DownloadTaskEntity det =
DbEntity.findFirst(DownloadTaskEntity.class, "url=? and isGroupTask='true'", url);
if (det != null) {
@ -273,7 +274,7 @@ public abstract class AbsGroupUtil implements IUtil {
dt.cancel();
}
}
delDownloadInfo();
CommonUtil.delDownloadGroupTaskConfig(mGTEntity.removeFile, mGTEntity.getEntity());
mGTEntity.deleteData();
}
@ -281,30 +282,6 @@ public abstract class AbsGroupUtil implements IUtil {
}
/**
* 删除所有子任务的下载信息
*/
private void delDownloadInfo() {
List<DownloadTaskEntity> tasks =
DbEntity.findDatas(DownloadTaskEntity.class, "groupName=?", mGTEntity.key);
if (tasks != null && !tasks.isEmpty()) {
for (DownloadTaskEntity taskEntity : tasks) {
CommonUtil.delDownloadTaskConfig(mGTEntity.removeFile, taskEntity);
}
}
File dir = new File(mGTEntity.getEntity().getDirPath());
if (mGTEntity.removeFile) {
if (dir.exists()) {
dir.delete();
}
} else {
if (!mGTEntity.getEntity().isComplete()) {
dir.delete();
}
}
}
@Override public void stop() {
closeTimer(false);
onStop();
@ -418,7 +395,7 @@ public abstract class AbsGroupUtil implements IUtil {
taskEntity.headers = mGTEntity.headers;
taskEntity.requestEnum = mGTEntity.requestEnum;
taskEntity.removeFile = mGTEntity.removeFile;
taskEntity.groupName = mGTEntity.key;
taskEntity.groupName = mGTEntity.getKey();
taskEntity.isGroupTask = true;
taskEntity.requestType = mGTEntity.requestType;
taskEntity.key = entity.getDownloadPath();

@ -44,12 +44,12 @@ public class FtpDirDownloadUtil extends AbsGroupUtil {
new FtpDirInfoThread(mGTEntity, new OnFileInfoCallback() {
@Override public void onComplete(String url, CompleteInfo info) {
if (info.code >= 200 && info.code < 300) {
for (DownloadEntity entity : mGTEntity.entity.getSubTask()) {
for (DownloadEntity entity : mGTEntity.getEntity().getSubTask()) {
mExeMap.put(entity.getUrl(), createChildDownloadTask(entity));
}
mActualTaskNum = mGTEntity.entity.getSubTask().size();
mActualTaskNum = mGTEntity.getEntity().getSubTask().size();
mGroupSize = mActualTaskNum;
mTotalLen = mGTEntity.entity.getFileSize();
mTotalLen = mGTEntity.getEntity().getFileSize();
startDownload();
}
}

@ -160,7 +160,10 @@ class HttpFileInfoThread implements Runnable {
}
return;
}
newUrl = CheckUtil.checkUrl(newUrl);
if (!CheckUtil.checkUrl(newUrl)) {
failDownload("下载失败,重定向url错误", false);
return;
}
String cookies = conn.getHeaderField("Set-Cookie");
conn = (HttpURLConnection) new URL(newUrl).openConnection();
conn = ConnectionHelp.setConnectParam(mTaskEntity, conn);

@ -18,7 +18,7 @@ package com.arialyy.aria.core.inf;
import android.os.Parcel;
import android.os.Parcelable;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.Ignore;
import com.arialyy.aria.orm.annotation.Ignore;
/**
* Created by AriaL on 2017/6/29.

@ -17,10 +17,7 @@ package com.arialyy.aria.core.inf;
import android.os.Parcel;
import android.os.Parcelable;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
import com.arialyy.aria.orm.Foreign;
import com.arialyy.aria.orm.NormalList;
import com.arialyy.aria.orm.Primary;
import com.arialyy.aria.orm.annotation.Primary;
import java.util.ArrayList;
import java.util.List;
@ -29,20 +26,16 @@ import java.util.List;
*/
public abstract class AbsGroupEntity extends AbsEntity implements Parcelable {
/**
* 组名组名为任务地址相加的urlMd5
* 组名组名为任务地址相加的urlMd5
*/
@Primary @Foreign(table = DownloadGroupTaskEntity.class, column = "key") protected String
groupName = "";
@Primary protected String groupName = "";
/**
* 任务组别名
*/
private String alias = "";
/**
* 子任务链接组
*/
@NormalList(clazz = String.class) private List<String> urls = new ArrayList<>();
private List<String> urls = new ArrayList<>();
public List<String> getUrls() {
return urls;

@ -17,8 +17,6 @@ package com.arialyy.aria.core.inf;
import android.os.Parcel;
import android.os.Parcelable;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.Ignore;
/**
* Created by AriaL on 2017/6/3.

@ -34,17 +34,25 @@ import java.util.List;
*/
public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity>
implements ITarget<TARGET> {
protected String TAG = "";
protected ENTITY mEntity;
protected TASK_ENTITY mTaskEntity;
protected String mTargetName;
protected AbsTarget() {
TAG = CommonUtil.getClassName(this);
}
/**
* 重置下载状态将任务状态设置为未开始状态
* 重置状态将任务状态设置为未开始状态
*/
public TARGET resetState() {
if (checkEntity()) {
mTaskEntity.getEntity().setState(IEntity.STATE_WAIT);
mTaskEntity.refreshInfo = true;
mTaskEntity.update();
} else {
ALog.e(TAG, "重置状态失败");
}
return (TARGET) this;
}
@ -96,10 +104,16 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
*/
public TARGET setExtendField(String str) {
if (TextUtils.isEmpty(str)) return (TARGET) this;
if (checkEntity()) {
if (TextUtils.isEmpty(mEntity.getStr()) || !mEntity.getStr().equals(str)) {
mEntity.setStr(str);
mEntity.save();
} else {
ALog.e(TAG, "设置扩展字段失败,扩展字段为null");
}
} else {
ALog.e(TAG, "设置扩展字段失败");
}
return (TARGET) this;
}
@ -138,7 +152,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
}
/**
* 检查实体是否合法
* 检查实体是否合法如果实体合法将保存实体到数据库或更新数据库中的实体对象
*
* @return {@code true} 合法
*/
@ -252,6 +266,4 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
start();
}
}
}

@ -18,8 +18,7 @@ package com.arialyy.aria.core.inf;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.RequestEnum;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.Ignore;
import com.arialyy.aria.orm.Primary;
import com.arialyy.aria.orm.annotation.Ignore;
import java.util.HashMap;
import java.util.Map;
@ -55,11 +54,6 @@ public abstract class AbsTaskEntity<ENTITY extends AbsEntity> extends DbEntity {
*/
public static final int U_FTP = 0xA2;
/**
* Task实体对应的key
*/
@Primary public String key = "";
/**
* 账号和密码
*/
@ -144,12 +138,7 @@ public abstract class AbsTaskEntity<ENTITY extends AbsEntity> extends DbEntity {
return getEntity().getState();
}
@Override public void deleteData() {
if (getEntity() != null) {
getEntity().deleteData();
}
super.deleteData();
}
public abstract String getKey();
@Override public void update() {
if (getEntity() != null) {

@ -15,7 +15,7 @@
*/
package com.arialyy.aria.core.inf;
import com.arialyy.aria.orm.Ignore;
import com.arialyy.aria.orm.annotation.Ignore;
/**
* Created by lyy on 2017/2/23.

@ -15,8 +15,6 @@
*/
package com.arialyy.aria.core.inf;
import com.arialyy.aria.core.inf.IEventListener;
/**
* Created by lyy on 2017/2/9.
* 上传监听

@ -18,6 +18,8 @@ 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.core.download.DownloadGroupTaskWrapper;
import com.arialyy.aria.core.download.DownloadGroupWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.CommonUtil;
import java.util.List;
@ -46,36 +48,56 @@ class DGTEntityFactory implements ITEntityFactory<DownloadGroupEntity, DownloadG
/**
* 通过下载实体创建任务实体
*/
@Override public DownloadGroupTaskEntity create(DownloadGroupEntity entity) {
DownloadGroupTaskEntity dgTaskEntity =
DbEntity.findFirst(DownloadGroupTaskEntity.class, "key=?", entity.getGroupName());
private DownloadGroupTaskEntity create(DownloadGroupEntity entity) {
List<DownloadGroupTaskWrapper> wrapper =
DbEntity.findRelationData(DownloadGroupTaskWrapper.class, "DownloadGroupTaskWrapper.key=?",
entity.getGroupName());
DownloadGroupTaskEntity dgTaskEntity;
if (wrapper != null && !wrapper.isEmpty()) {
dgTaskEntity = wrapper.get(0).taskEntity;
if (dgTaskEntity == null) {
dgTaskEntity = new DownloadGroupTaskEntity();
dgTaskEntity.save(entity);
dgTaskEntity.setEntity(entity);
} else if (dgTaskEntity.getEntity() == null || TextUtils.isEmpty(
dgTaskEntity.getEntity().getKey())) {
dgTaskEntity.setEntity(entity);
}
if (dgTaskEntity.entity == null || TextUtils.isEmpty(dgTaskEntity.entity.getKey())) {
dgTaskEntity.save(entity);
} else {
dgTaskEntity = new DownloadGroupTaskEntity();
dgTaskEntity.setEntity(entity);
}
return dgTaskEntity;
}
/**
* 对于任务组不能使用这个用于FTP文件夹下载
* 对于任务组不能使用这个该方法只用于FTP文件夹下载
*
* @deprecated {@link #create(String, List)}
* @deprecated 任务组使用{@link #create(String, List)}
*/
@Override @Deprecated public DownloadGroupTaskEntity create(String key) {
DownloadGroupTaskEntity dgTaskEntity =
DbEntity.findFirst(DownloadGroupTaskEntity.class, "key=?", key);
List<DownloadGroupTaskWrapper> wrapper =
DbEntity.findRelationData(DownloadGroupTaskWrapper.class, "DownloadGroupTaskWrapper.key=?",
key);
DownloadGroupTaskEntity dgTaskEntity;
if (wrapper != null && !wrapper.isEmpty()) {
dgTaskEntity = wrapper.get(0).taskEntity;
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.setEntity(getDownloadGroupEntity(key, null));
} else if (dgTaskEntity.getEntity() == null || TextUtils.isEmpty(
dgTaskEntity.getEntity().getKey())) {
dgTaskEntity.setEntity(getDownloadGroupEntity(key, null));
}
dgTaskEntity.urlEntity = CommonUtil.getFtpUrlInfo(key);
return dgTaskEntity;
} else {
dgTaskEntity = new DownloadGroupTaskEntity();
dgTaskEntity.setEntity(getDownloadGroupEntity(key, null));
dgTaskEntity.urlEntity = CommonUtil.getFtpUrlInfo(key);
return dgTaskEntity;
}
}
@Override public DownloadGroupTaskEntity create(String groupName, List<String> urls) {
@ -86,13 +108,21 @@ class DGTEntityFactory implements ITEntityFactory<DownloadGroupEntity, DownloadG
* 查询任务组实体如果数据库不存在该实体则新创建一个新的任务组实体
*/
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);
List<DownloadGroupWrapper> wrapper =
DbEntity.findRelationData(DownloadGroupWrapper.class, "DownloadGroupEntity.groupName=?",
groupName);
DownloadGroupEntity groupEntity;
if (wrapper != null && !wrapper.isEmpty()) {
groupEntity = wrapper.get(0).groupEntity;
if (groupEntity == null) {
groupEntity = new DownloadGroupEntity();
}
} else {
groupEntity = new DownloadGroupEntity();
}
return entity;
groupEntity.setGroupName(groupName);
groupEntity.setUrls(urls);
return groupEntity;
}
}

@ -18,9 +18,11 @@ package com.arialyy.aria.core.manager;
import android.text.TextUtils;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.download.DownloadTaskWrapper;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.orm.DbEntity;
import java.io.File;
import java.util.List;
/**
* Created by Aria.Lao on 2017/11/1.
@ -45,19 +47,26 @@ class DTEntityFactory implements ITEntityFactory<DownloadEntity, DownloadTaskEnt
/**
* 通过下载实体创建任务实体
*/
@Override public DownloadTaskEntity create(DownloadEntity entity) {
DownloadTaskEntity taskEntity =
DbEntity.findFirst(DownloadTaskEntity.class, "key=? and isGroupTask='false' and url=?",
private DownloadTaskEntity create(DownloadEntity entity) {
List<DownloadTaskWrapper> wrapper = DbEntity.findRelationData(DownloadTaskWrapper.class,
"DownloadTaskEntity.key=? and DownloadTaskEntity.isGroupTask='false' and DownloadTaskEntity.url=?",
entity.getDownloadPath(), entity.getUrl());
if (wrapper != null && !wrapper.isEmpty()) {
DownloadTaskEntity taskEntity = wrapper.get(0).taskEntity;
if (taskEntity == null) {
taskEntity = new DownloadTaskEntity();
taskEntity.save(entity);
taskEntity.entity = entity;
} else if (taskEntity.entity == null || TextUtils.isEmpty(taskEntity.entity.getUrl())) {
taskEntity.save(entity);
} else if (!taskEntity.entity.getUrl().equals(entity.getUrl())) { //处理地址切换而保存路径不变
taskEntity.save(entity);
taskEntity.entity = entity;
}
return taskEntity;
} else {
DownloadTaskEntity taskEntity = new DownloadTaskEntity();
taskEntity.entity = entity;
return taskEntity;
}
}
/**

@ -22,10 +22,6 @@ import com.arialyy.aria.core.inf.AbsTaskEntity;
* Created by Aria.Lao on 2017/11/1.
*/
interface ITEntityFactory<ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>> {
/**
* 通过信息实体创建任务实体
*/
TASK_ENTITY create(ENTITY entity);
/**
* 通过key创建任务只适应于单任务

@ -18,7 +18,6 @@ package com.arialyy.aria.core.manager;
import android.support.v4.util.LruCache;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.upload.UploadTaskEntity;
import com.arialyy.aria.util.ALog;
@ -29,7 +28,7 @@ import java.util.concurrent.locks.ReentrantLock;
/**
* Created by Aria.Lao on 2017/11/1.
* 任务实体管理器负责
* 任务实体管理器
*/
public class TEManager {
private static final String TAG = "TaskManager";
@ -102,31 +101,6 @@ public class TEManager {
}
}
/**
* 通过实体创建任务
*
* @return 如果任务实体创建失败返回null
*/
public <TE extends AbsTaskEntity> TE createTEntity(Class<TE> clazz, AbsEntity absEntity) {
final Lock lock = this.lock;
lock.lock();
try {
AbsTaskEntity tEntity = cache.get(convertKey(absEntity.getKey()));
if (tEntity == null || tEntity.getClass() != clazz) {
ITEntityFactory factory = chooseFactory(clazz);
if (factory == null) {
ALog.e(TAG, "任务实体创建失败");
return null;
}
tEntity = factory.create(absEntity);
cache.put(convertKey(absEntity.getKey()), tEntity);
}
return (TE) tEntity;
} finally {
lock.unlock();
}
}
private IGTEntityFactory chooseGroupFactory(Class clazz) {
if (clazz == DownloadGroupTaskEntity.class) {
return DGTEntityFactory.getInstance();
@ -146,7 +120,9 @@ public class TEManager {
}
/**
* 从任务实体管理器中获取任务实体
* 从缓存中获取任务实体如果任务实体不存在则创建任务实体
*
* @return 创建失败返回null
*/
public <TE extends AbsTaskEntity> TE getTEntity(Class<TE> clazz, String key) {
final Lock lock = this.lock;
@ -154,7 +130,33 @@ public class TEManager {
try {
AbsTaskEntity tEntity = cache.get(convertKey(key));
if (tEntity == null) {
return createTEntity(clazz, key);
} else {
return (TE) tEntity;
}
} finally {
lock.unlock();
}
}
/**
* 从缓存中获取HTTP任务组的任务实体如果任务实体不存在则创建任务实体
*
* @param urls HTTP任务组的子任务下载地址列表
* @return 地址列表为null或创建实体失败返回null
*/
public <TE extends AbsTaskEntity> TE getGTEntity(Class<TE> clazz, List<String> urls) {
if (urls == null || urls.isEmpty()) {
ALog.e(TAG, "获取HTTP任务组实体失败:任务组的子任务下载地址列表为null");
return null;
}
final Lock lock = this.lock;
lock.lock();
try {
String groupName = CommonUtil.getMd5Code(urls);
AbsTaskEntity tEntity = cache.get(convertKey(groupName));
if (tEntity == null) {
return createGTEntity(clazz, urls);
} else {
return (TE) tEntity;
}
@ -189,7 +191,7 @@ public class TEManager {
final Lock lock = this.lock;
lock.lock();
try {
return cache.put(convertKey(te.key), te) != null;
return cache.put(convertKey(te.getKey()), te) != null;
} finally {
lock.unlock();
}

@ -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));
}
}

@ -15,10 +15,13 @@
*/
package com.arialyy.aria.core.manager;
import android.text.TextUtils;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTaskEntity;
import com.arialyy.aria.core.upload.UploadTaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.Regular;
import java.util.List;
import java.util.regex.Pattern;
/**
@ -41,17 +44,26 @@ class UTEntityFactory implements ITEntityFactory<UploadEntity, UploadTaskEntity>
return INSTANCE;
}
@Override public UploadTaskEntity create(UploadEntity entity) {
UploadTaskEntity uTaskEntity =
DbEntity.findFirst(UploadTaskEntity.class, "key=?", entity.getFilePath());
private UploadTaskEntity create(UploadEntity entity) {
List<UploadTaskWrapper> wrapper =
DbEntity.findRelationData(UploadTaskWrapper.class, "UploadTaskEntity.key=?",
entity.getFilePath());
if (wrapper != null && !wrapper.isEmpty()) {
UploadTaskEntity uTaskEntity = wrapper.get(0).taskEntity;
if (uTaskEntity == null) {
uTaskEntity = new UploadTaskEntity();
uTaskEntity.entity = entity;
}
if (uTaskEntity.entity == null) {
} else if (uTaskEntity.entity == null || TextUtils.isEmpty(
uTaskEntity.entity.getFilePath())) {
uTaskEntity.entity = entity;
}
return uTaskEntity;
} else {
UploadTaskEntity uTaskEntity = new UploadTaskEntity();
uTaskEntity.entity = entity;
return uTaskEntity;
}
}
@Override public UploadTaskEntity create(String key) {
@ -67,14 +79,12 @@ class UTEntityFactory implements ITEntityFactory<UploadEntity, UploadTaskEntity>
UploadEntity entity = UploadEntity.findFirst(UploadEntity.class, "filePath=?", filePath);
if (entity == null) {
entity = new UploadEntity();
//String regex = "[/|\\\\|//]";
String regex = Regular.REG_FILE_NAME;
Pattern p = Pattern.compile(regex);
String[] strs = p.split(filePath);
String fileName = strs[strs.length - 1];
entity.setFileName(fileName);
entity.setFilePath(filePath);
entity.insert();
}
return entity;
}

@ -67,7 +67,7 @@ public class DownloadGroupTaskQueue
&& mExecutePool.getTask(entity.getEntity().getKey()) == null) {
task = (DownloadGroupTask) TaskFactory.getInstance()
.createTask(targetName, entity, DownloadGroupSchedulers.getInstance());
entity.key = entity.getEntity().getGroupName();
entity.setKey(entity.getEntity().getGroupName());
mCachePool.putTask(task);
} else {
ALog.w(TAG, "任务已存在");

@ -17,12 +17,9 @@ package com.arialyy.aria.core.upload;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.manager.TEManager;
import com.arialyy.aria.core.queue.UploadTaskQueue;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import java.io.File;
/**
@ -30,13 +27,9 @@ import java.io.File;
*/
abstract class BaseNormalTarget<TARGET extends AbsUploadTarget>
extends AbsUploadTarget<TARGET, UploadEntity, UploadTaskEntity> {
private static final String TAG = "BaseNormalTarget";
protected void initTarget(String filePath) {
mTaskEntity = TEManager.getInstance().getTEntity(UploadTaskEntity.class, filePath);
if (mTaskEntity == null) {
mTaskEntity = TEManager.getInstance().createTEntity(UploadTaskEntity.class, filePath);
}
mEntity = mTaskEntity.entity;
File file = new File(filePath);
mEntity.setFileName(file.getName());
@ -74,7 +67,11 @@ abstract class BaseNormalTarget<TARGET extends AbsUploadTarget>
}
@Override protected boolean checkEntity() {
return checkUrl() && checkFilePath();
boolean b = checkUrl() && checkFilePath();
if (b) {
mTaskEntity.save(mEntity);
}
return b;
}
/**

@ -30,7 +30,6 @@ import com.arialyy.aria.util.CommonUtil;
*/
public class FtpUploadTarget extends BaseNormalTarget<FtpUploadTarget>
implements IFtpTarget<FtpUploadTarget> {
private final String TAG = "FtpUploadTarget";
private FtpDelegate<FtpUploadTarget, UploadEntity, UploadTaskEntity> mDelegate;
FtpUploadTarget(String filePath, String targetName) {
@ -51,14 +50,15 @@ public class FtpUploadTarget extends BaseNormalTarget<FtpUploadTarget>
*/
@Override
public FtpUploadTarget setUploadUrl(@NonNull String uploadUrl) {
uploadUrl = CheckUtil.checkUrl(uploadUrl);
if (!CheckUtil.checkUrl(uploadUrl)) {
return this;
}
if (!uploadUrl.endsWith("/")) {
uploadUrl += "/";
}
mTaskEntity.urlEntity = CommonUtil.getFtpUrlInfo(uploadUrl);
if (mEntity.getUrl().equals(uploadUrl)) return this;
mEntity.setUrl(uploadUrl);
mEntity.update();
return this;
}

@ -19,15 +19,18 @@ import android.os.Parcel;
import android.os.Parcelable;
import com.arialyy.aria.core.inf.AbsNormalEntity;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.orm.Foreign;
import com.arialyy.aria.orm.Primary;
import com.arialyy.aria.orm.annotation.Foreign;
import com.arialyy.aria.orm.annotation.Primary;
/**
* Created by lyy on 2017/2/9.
* 上传文件实体
*/
public class UploadEntity extends AbsNormalEntity implements Parcelable {
@Primary @Foreign(table = UploadTaskEntity.class, column = "key") private String filePath; //文件路径
/**
* 文件上传路径
*/
@Primary @Foreign(parent = UploadTaskEntity.class, column = "key") private String filePath;
/**
* 上传完成后服务器返回的数据

@ -20,9 +20,7 @@ import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.common.ProxyHelper;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.AbsReceiver;
import com.arialyy.aria.core.scheduler.ISchedulerListener;
import com.arialyy.aria.core.scheduler.UploadSchedulers;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.CheckUtil;
@ -92,7 +90,7 @@ public class UploadReceiver extends AbsReceiver<UploadEntity> {
@Override public void removeAllTask(boolean removeFile) {
final AriaManager am = AriaManager.getInstance(AriaManager.APP);
am.setCmd(CommonUtil.createNormalCmd(targetName, new DownloadTaskEntity(),
am.setCmd(CommonUtil.createNormalCmd(targetName, new UploadTaskEntity(),
NormalCmdFactory.TASK_CANCEL_ALL, ICmd.TASK_TYPE_UPLOAD)).exe();
Set<String> keys = am.getReceiver().keySet();

@ -29,7 +29,6 @@ import java.util.Map;
*/
public class UploadTarget extends BaseNormalTarget<UploadTarget>
implements IHttpHeaderTarget<UploadTarget> {
private static final String TAG = "UploadTarget";
private HttpHeaderDelegate<UploadTarget, UploadEntity, UploadTaskEntity> mDelegate;
UploadTarget(String filePath, String targetName) {
@ -47,12 +46,13 @@ public class UploadTarget extends BaseNormalTarget<UploadTarget>
}
@Override public UploadTarget setUploadUrl(@NonNull String uploadUrl) {
uploadUrl = CheckUtil.checkUrl(uploadUrl);
if (!CheckUtil.checkUrl(uploadUrl)){
return this;
}
if (mEntity.getUrl().equals(uploadUrl)) {
return this;
}
mEntity.setUrl(uploadUrl);
mEntity.update();
return this;
}

@ -0,0 +1,45 @@
/*
* 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 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 UploadTaskWrapper 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.entity = entity;
}
}
}

@ -0,0 +1,162 @@
/*
* 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 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 (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;
}
}

@ -13,22 +13,15 @@
* 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;
package com.arialyy.aria.orm;
/**
* Created by lyy on 2017/10/17.
* Url 映射表
*/
public class UrlMapping extends DbEntity {
/**
* 各实体对应的key
* Created by laoyuyu on 2018/3/30.
*/
public String key;
public abstract class AbsWrapper {
/**
* 链接
* 处理转换
*/
public String url;
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;
}
}

@ -17,7 +17,6 @@ package com.arialyy.aria.orm;
import android.text.TextUtils;
import com.arialyy.aria.core.ErrorEntity;
import com.arialyy.aria.core.UrlMapping;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
@ -34,7 +33,7 @@ import java.util.Map;
class DBConfig {
static Map<String, Class> mapping = new HashMap<>();
static String DB_NAME;
static int VERSION = 25;
static int VERSION = 31;
static {
if (TextUtils.isEmpty(DB_NAME)) {
@ -46,13 +45,12 @@ class DBConfig {
}
static {
mapping.put("DownloadEntity", DownloadEntity.class);
mapping.put("DownloadGroupTaskEntity", DownloadGroupTaskEntity.class);
mapping.put("DownloadGroupEntity", DownloadGroupEntity.class);
mapping.put("DownloadTaskEntity", DownloadTaskEntity.class);
mapping.put("DownloadGroupTaskEntity", DownloadGroupTaskEntity.class);
mapping.put("UploadEntity", UploadEntity.class);
mapping.put("UploadTaskEntity", UploadTaskEntity.class);
mapping.put("DownloadEntity", DownloadEntity.class);
mapping.put("UploadEntity", UploadEntity.class);
mapping.put("ErrorEntity", ErrorEntity.class);
//mapping.put("UrlMapping", UrlMapping.class);
}
}

@ -0,0 +1,110 @@
/*
* 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 android.os.Environment;
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) {
//判断是否存在sd卡
boolean sdExist = android.os.Environment.MEDIA_MOUNTED.equals(
android.os.Environment.getExternalStorageState());
if (!sdExist) {
return null;
} else {
//获取sd卡路径
File file = getBaseContext().getExternalFilesDir(null);
String dbDir;
if (file != null) {
dbDir = file.getPath() + "/";
} else {
dbDir = Environment.getExternalStorageDirectory().getPath()
+ "/Android/data/"
+ getBaseContext().getPackageName()
+ "/files/";
}
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);
}
}

@ -28,7 +28,7 @@ import java.util.Map;
* Created by lyy on 2015/11/2.
* 所有数据库实体父类
*/
public class DbEntity {
public abstract class DbEntity {
private static final Object LOCK = new Object();
protected int rowID = -1;
@ -36,15 +36,14 @@ public class DbEntity {
}
///**
// * 关键字模糊检索全文
// *
// * @param column 需要查找的列
// * @param mathSql 关键字语法,exsimple “white OR green”、“blue AND red”、“white NOT green”
// */
//public static <T extends DbEntity> List<T> searchData(Class<T> clazz, String column, String mathSql) {
// return DbUtil.getInstance().searchData(clazz, column, mathSql);
//}
/**
* 查询关联数据
*
* @param expression 查询条件
*/
public static <T extends AbsWrapper> List<T> findRelationData(Class<T> clazz, String... expression) {
return DelegateWrapper.getInstance().findRelationData(clazz, expression);
}
/**
* 检查某个字段的值是否存在
@ -53,21 +52,21 @@ public class DbEntity {
* @return {@code true}该字段的对应的value已存在
*/
public static boolean checkDataExist(Class clazz, String... expression) {
return DbUtil.getInstance().checkDataExist(clazz, expression);
return DelegateWrapper.getInstance().checkDataExist(clazz, expression);
}
/**
* 清空表数据
*/
public static <T extends DbEntity> void clean(Class<T> clazz) {
DbUtil.getInstance().clean(clazz);
DelegateWrapper.getInstance().clean(clazz);
}
/**
* 直接执行sql语句
*/
public static void exeSql(String sql) {
DbUtil.getInstance().exeSql(sql);
DelegateWrapper.getInstance().exeSql(sql);
}
/**
@ -76,7 +75,7 @@ public class DbEntity {
* @return 没有数据返回null
*/
public static <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
DbUtil util = DbUtil.getInstance();
DelegateWrapper util = DelegateWrapper.getInstance();
return util.findAllData(clazz);
}
@ -97,7 +96,7 @@ public class DbEntity {
* @return 没有数据返回null
*/
public static <T extends DbEntity> List<T> findDatas(Class<T> clazz, String... expression) {
DbUtil util = DbUtil.getInstance();
DelegateWrapper util = DelegateWrapper.getInstance();
return util.findData(clazz, expression);
}
@ -110,7 +109,7 @@ public class DbEntity {
* @return 没有数据返回null
*/
public static <T extends DbEntity> T findFirst(Class<T> clazz, String... expression) {
DbUtil util = DbUtil.getInstance();
DelegateWrapper util = DelegateWrapper.getInstance();
List<T> datas = util.findData(clazz, expression);
return datas == null ? null : datas.size() > 0 ? datas.get(0) : null;
}
@ -119,14 +118,14 @@ public class DbEntity {
* 获取所有行的rowid
*/
public int[] getRowIds() {
return DbUtil.getInstance().getRowId(getClass());
return DelegateWrapper.getInstance().getRowId(getClass());
}
/**
* 获取rowid
*/
public int getRowId(@NonNull Object[] wheres, @NonNull Object[] values) {
return DbUtil.getInstance().getRowId(getClass(), wheres, values);
return DelegateWrapper.getInstance().getRowId(getClass(), wheres, values);
}
/**
@ -143,7 +142,7 @@ public class DbEntity {
* </code>
*/
public static <T extends DbEntity> void deleteData(Class<T> clazz, String... expression) {
DbUtil util = DbUtil.getInstance();
DelegateWrapper util = DelegateWrapper.getInstance();
util.delData(clazz, expression);
}
@ -151,7 +150,7 @@ public class DbEntity {
* 修改数据
*/
public void update() {
DbUtil.getInstance().modifyData(this);
DelegateWrapper.getInstance().modifyData(this);
}
/**
@ -171,7 +170,7 @@ public class DbEntity {
* 查找数据在表中是否存在
*/
private boolean thisIsExist() {
DbUtil util = DbUtil.getInstance();
DelegateWrapper util = DelegateWrapper.getInstance();
return util.isExist(getClass(), rowID);
}
@ -179,45 +178,38 @@ public class DbEntity {
* 插入数据
*/
public void insert() {
DbUtil.getInstance().insertData(this);
DelegateWrapper.getInstance().insertData(this);
updateRowID();
}
private <T extends DbEntity> T findFirst(Class<T> clazz, @NonNull String[] wheres,
@NonNull String[] values) {
DbUtil util = DbUtil.getInstance();
List<T> list = util.findData(clazz, wheres, values);
return list == null ? null : list.get(0);
}
private void updateRowID() {
try {
List<Field> fields = CommonUtil.getAllFields(getClass());
List<String> where = new ArrayList<>();
StringBuilder sb = new StringBuilder();
List<String> params = new ArrayList<>();
List<String> values = new ArrayList<>();
for (Field field : fields) {
field.setAccessible(true);
if (SqlUtil.ignoreField(field)) {
if (SqlUtil.isIgnore(field)) {
continue;
}
where.add(field.getName());
sb.append(field.getName()).append("=? AND ");
Type type = field.getType();
if (SqlUtil.isOneToOne(field)) {
values.add(SqlUtil.getOneToOneParams(field));
} else if (type == List.class) {
if (SqlUtil.isOneToMany(field)) {
values.add(SqlUtil.getOneToManyElementParams(field));
} else {
if (type == List.class) {
values.add(SqlUtil.list2Str(this, field));
}
} else if (type == Map.class) {
values.add(SqlUtil.map2Str((Map<String, String>) field.get(this)));
} else {
values.add(field.get(this) + "");
}
}
DbEntity entity = findFirst(getClass(), where.toArray(new String[where.size()]),
values.toArray(new String[values.size()]));
String temp = sb.toString();
String p = temp.substring(0, temp.length() - 5);
params.add(p);
params.addAll(values);
DbEntity entity = findFirst(getClass(), params.toArray(new String[params.size()]));
if (entity != null) {
rowID = entity.rowID;
}

@ -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,
int 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;
}
}

@ -0,0 +1,186 @@
/*
* 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.sqlite.SQLiteDatabase;
import android.text.TextUtils;
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.lang.reflect.Type;
import java.util.List;
import java.util.Map;
/**
* Created by laoyuyu on 2018/3/22.
* 增加数据更新数据
*/
class DelegateUpdate extends AbsDelegate {
private DelegateUpdate() {
}
/**
* 删除某条数据
*/
<T extends DbEntity> void delData(SQLiteDatabase db, Class<T> clazz, String... expression) {
db = checkDb(db);
CheckUtil.checkSqlExpression(expression);
String sql = "DELETE 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(DEL_DATA, sql);
db.execSQL(sql);
close(db);
}
/**
* 修改某行数据
*/
void modifyData(SQLiteDatabase db, DbEntity dbEntity) {
db = checkDb(db);
Class<?> clazz = dbEntity.getClass();
List<Field> fields = CommonUtil.getAllFields(clazz);
DbEntity cacheEntity = mDataCache.get(getCacheKey(dbEntity));
if (fields != null && fields.size() > 0) {
StringBuilder sql = new StringBuilder();
StringBuilder prams = new StringBuilder();
sql.append("UPDATE ").append(CommonUtil.getClassName(dbEntity)).append(" SET ");
int i = 0;
try {
for (Field field : fields) {
field.setAccessible(true);
if (isIgnore(dbEntity, field)) {
continue;
}
if (cacheEntity != null
&& field.get(dbEntity) == field.get(cacheEntity)
&& !field.getName().equals("state")) { //在LruCache中 state字段总是不能重新赋值...
continue;
}
String value;
prams.append(i > 0 ? ", " : "");
prams.append(field.getName()).append("='");
Type type = field.getType();
if (type == Map.class && checkMap(field)) {
value = SqlUtil.map2Str((Map<String, String>) field.get(dbEntity));
} else if (type == List.class && checkList(field)) {
value = SqlUtil.list2Str(dbEntity, field);
} else {
Object obj = field.get(dbEntity);
value = obj == null ? "" : convertValue(obj.toString());
}
prams.append(TextUtils.isEmpty(value) ? "" : value);
prams.append("'");
i++;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (!TextUtils.isEmpty(prams.toString())) {
sql.append(prams.toString());
sql.append(" where rowid=").append(dbEntity.rowID);
print(MODIFY_DATA, sql.toString());
db.execSQL(sql.toString());
}
}
mDataCache.put(getCacheKey(dbEntity), dbEntity);
close(db);
}
/**
* 插入数据
*/
void insertData(SQLiteDatabase db, DbEntity dbEntity) {
db = checkDb(db);
Class<?> clazz = dbEntity.getClass();
List<Field> fields = CommonUtil.getAllFields(clazz);
if (fields != null && fields.size() > 0) {
StringBuilder sb = new StringBuilder();
sb.append("INSERT INTO ").append(CommonUtil.getClassName(dbEntity)).append("(");
int i = 0;
try {
for (Field field : fields) {
field.setAccessible(true);
if (isIgnore(dbEntity, field)) {
continue;
}
sb.append(i > 0 ? ", " : "");
sb.append(field.getName());
i++;
}
sb.append(") VALUES (");
i = 0;
for (Field field : fields) {
field.setAccessible(true);
if (isIgnore(dbEntity, field)) {
continue;
}
sb.append(i > 0 ? ", " : "");
sb.append("'");
Type type = field.getType();
if (type == Map.class && checkMap(field)) {
sb.append(SqlUtil.map2Str((Map<String, String>) field.get(dbEntity)));
} else if (type == List.class && checkList(field)) {
sb.append(SqlUtil.list2Str(dbEntity, field));
} else {
Object obj = field.get(dbEntity);
if (obj != null) {
sb.append(convertValue(field.get(dbEntity).toString()));
}
}
sb.append("'");
i++;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
sb.append(")");
print(INSERT_DATA, sb.toString());
db.execSQL(sb.toString());
}
close(db);
}
/**
* {@code true}自动增长的主键和需要忽略的字段
*/
private boolean isIgnore(Object obj, Field field) throws IllegalAccessException {
if (SqlUtil.isIgnore(field)) {
return true;
}
if (SqlUtil.isPrimary(field)) { //忽略自动增长的主键
Primary p = field.getAnnotation(Primary.class);
if (p.autoincrement()) {
return true;
}
}
if (SqlUtil.isForeign(field)) { //忽略外键为null的字段
Object value = field.get(obj);
if (value == null || (value instanceof String && TextUtils.isEmpty(String.valueOf(value)))) {
return true;
}
}
return false;
}
}

@ -0,0 +1,155 @@
/*
* 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.database.sqlite.SQLiteDatabase;
import java.util.List;
/**
* Created by lyy on 2015/2/11.
* 数据库操作工具
*/
public class DelegateWrapper {
private static final String TAG = "DelegateWrapper";
private volatile static DelegateWrapper INSTANCE = null;
private SQLiteDatabase mDb;
private DelegateManager mDManager;
private DelegateWrapper() {
}
private DelegateWrapper(Context context) {
SqlHelper helper = SqlHelper.init(context.getApplicationContext());
mDb = helper.getWritableDatabase();
mDManager = DelegateManager.getInstance();
}
public static void init(Context context) {
synchronized (DelegateWrapper.class) {
if (INSTANCE == null) {
INSTANCE = new DelegateWrapper(context);
}
}
}
static DelegateWrapper getInstance() {
if (INSTANCE == null) {
throw new NullPointerException("请在Application中调用init进行数据库工具注册注册");
}
return INSTANCE;
}
/**
* 查询关联表数据
*
* @param expression 查询条件
*/
<T extends AbsWrapper> List<T> findRelationData(Class<T> clazz, String... expression) {
return mDManager.getDelegate(DelegateFind.class).findRelationData(mDb, clazz, expression);
}
/**
* 检查某个字段的值是否存在
*
* @param expression 字段和值"url=xxx"
* @return {@code true}该字段的对应的value已存在
*/
boolean checkDataExist(Class clazz, String... expression) {
return mDManager.getDelegate(DelegateCommon.class)
.checkDataExist(mDb, clazz, expression);
}
/**
* 清空表数据
*/
<T extends DbEntity> void clean(Class<T> clazz) {
mDManager.getDelegate(DelegateCommon.class).clean(mDb, clazz);
}
/**
* 执行sql语句
*/
void exeSql(String sql) {
mDb.execSQL(sql);
}
/**
* 删除某条数据
*/
<T extends DbEntity> void delData(Class<T> clazz, String... expression) {
mDManager.getDelegate(DelegateUpdate.class).delData(mDb, clazz, expression);
}
/**
* 修改某行数据
*/
void modifyData(DbEntity dbEntity) {
mDManager.getDelegate(DelegateUpdate.class).modifyData(mDb, dbEntity);
}
/**
* 遍历所有数据
*/
<T extends DbEntity> List<T> findAllData(Class<T> clazz) {
return mDManager.getDelegate(DelegateFind.class).findAllData(mDb, clazz);
}
/**
* 条件查寻数据
*/
<T extends DbEntity> List<T> findData(Class<T> clazz, String... expression) {
return mDManager.getDelegate(DelegateFind.class).findData(mDb, clazz, expression);
}
/**
* 通过rowId判断数据是否存在
*/
<T extends DbEntity> boolean isExist(Class<T> clazz, int rowId) {
return mDManager.getDelegate(DelegateFind.class).itemExist(mDb, clazz, rowId);
}
/**
* 插入数据
*/
void insertData(DbEntity dbEntity) {
mDManager.getDelegate(DelegateUpdate.class).insertData(mDb, dbEntity);
}
/**
* 查找某张表是否存在
*/
boolean tableExists(Class clazz) {
return mDManager.getDelegate(DelegateCommon.class).tableExists(mDb, clazz);
}
/**
* 获取所在行Id
*/
int[] getRowId(Class clazz) {
return mDManager.getDelegate(DelegateFind.class).getRowId(mDb, clazz);
}
/**
* 获取行Id
*/
int getRowId(Class clazz, Object[] wheres, Object[] values) {
return mDManager.getDelegate(DelegateFind.class).getRowId(mDb, clazz, wheres, values);
}
}

@ -1,32 +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 java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by AriaL on 2017/7/4.
* 基本类型的List只能用于常见的数据类型如果是一对多的复杂数据结构需要使用{@link OneToMany}
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface NormalList {
/**
* 数据类型
*/
Class clazz();
}

@ -20,21 +20,11 @@ import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.annotation.NonNull;
import android.support.v4.util.LruCache;
import android.text.TextUtils;
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.lang.reflect.Field;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@ -43,31 +33,34 @@ import java.util.Set;
*/
final class SqlHelper extends SQLiteOpenHelper {
private static final String TAG = "SqlHelper";
private static final int CREATE_TABLE = 0;
private static final int TABLE_EXISTS = 1;
private static final int INSERT_DATA = 2;
private static final int MODIFY_DATA = 3;
private static final int FIND_DATA = 4;
private static final int FIND_ALL_DATA = 5;
private static final int DEL_DATA = 6;
/**
* 是否将数据库保存在Sd卡{@code true}
*/
private static final boolean SAVE_IN_SDCARD = false;
static volatile SqlHelper INSTANCE = null;
private static volatile SqlHelper INSTANCE = null;
private static LruCache<String, DbEntity> mDataCache = new LruCache<>(1024);
//private static Map<String, DbEntity> mDataCache = new ConcurrentHashMap<>();
private DelegateCommon mDelegate;
static SqlHelper init(Context context) {
if (INSTANCE == null) {
synchronized (AriaManager.LOCK) {
INSTANCE = new SqlHelper(context.getApplicationContext());
synchronized (SqlHelper.class) {
DelegateCommon delegate = DelegateManager.getInstance().getDelegate(DelegateCommon.class);
INSTANCE = new SqlHelper(context.getApplicationContext(), delegate);
SQLiteDatabase db = INSTANCE.getWritableDatabase();
db = checkDb(db);
db = delegate.checkDb(db);
// SQLite在3.6.19版本中开始支持外键约束,
// 而在Android中 2.1以前的版本使用的SQLite版本是3.5.9, 在2.2版本中使用的是3.6.22.
// 但是为了兼容以前的程序,默认并没有启用该功能,如果要启用该功能
// 需要使用如下语句:
db.execSQL("PRAGMA foreign_keys=ON;");
Set<String> tables = DBConfig.mapping.keySet();
for (String tableName : tables) {
Class clazz = null;
clazz = DBConfig.mapping.get(tableName);
if (!tableExists(db, clazz)) {
createTable(db, clazz, null);
if (!delegate.tableExists(db, clazz)) {
delegate.createTable(db, clazz);
}
}
}
@ -75,8 +68,10 @@ final class SqlHelper extends SQLiteOpenHelper {
return INSTANCE;
}
private SqlHelper(Context context) {
super(context, DBConfig.DB_NAME, null, DBConfig.VERSION);
private SqlHelper(Context context, DelegateCommon delegate) {
super(SAVE_IN_SDCARD ? new DatabaseContext(context) : context, DBConfig.DB_NAME, null,
DBConfig.VERSION);
mDelegate = delegate;
}
@Override public void onCreate(SQLiteDatabase db) {
@ -85,9 +80,13 @@ final class SqlHelper extends SQLiteOpenHelper {
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < newVersion) {
if (oldVersion < 31) {
handle314AriaUpdate(db);
} else {
handleDbUpdate(db);
}
}
}
@Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//super.onDowngrade(db, oldVersion, newVersion);
@ -110,635 +109,98 @@ final class SqlHelper extends SQLiteOpenHelper {
Set<String> tables = DBConfig.mapping.keySet();
for (String tableName : tables) {
Class clazz = DBConfig.mapping.get(tableName);
if (tableExists(db, clazz)) {
if (mDelegate.tableExists(db, clazz)) {
String countColumnSql = "SELECT rowid FROM " + tableName;
Cursor cursor = db.rawQuery(countColumnSql, null);
int dbColumnNum = cursor.getColumnCount();
int newEntityColumnNum = getEntityAttr(clazz);
List<Field> fields = SqlUtil.getAllNotIgnoreField(clazz);
int newEntityColumnNum = (fields == null || fields.isEmpty()) ? 0 : fields.size();
if (dbColumnNum != newEntityColumnNum) {
back(db, clazz);
}
}
}
}
/**
* 备份
*/
private void back(SQLiteDatabase db, Class clazz) {
db = checkDb(db);
String oldTableName = CommonUtil.getClassName(clazz);
db = mDelegate.checkDb(db);
//备份数据
List<DbEntity> list = findAllData(db, clazz);
//修改原来表名字
String alertSql = "alter table " + oldTableName + " rename to " + oldTableName + "_temp";
db.beginTransaction();
List<DbEntity> list =
DelegateManager.getInstance().getDelegate(DelegateFind.class).findAllData(db, clazz);
//修改表名为中介表名
String alertSql = "ALTER TABLE " + tableName + " RENAME TO " + tableName + "_temp";
//db.beginTransaction();
db.execSQL(alertSql);
//创建一个原来新表
createTable(db, clazz, null);
//创建一个原本的表
mDelegate.createTable(db, clazz);
//传入原来的数据
if (list != null && list.size() > 0) {
DelegateUpdate update = DelegateManager.getInstance().getDelegate(DelegateUpdate.class);
for (DbEntity entity : list) {
insertData(db, entity);
}
}
//删除原来的表
String deleteSQL = "drop table IF EXISTS " + oldTableName + "_temp";
db.execSQL(deleteSQL);
db.setTransactionSuccessful();
db.endTransaction();
close(db);
}
/**
* 获取实体的字段数
*/
private int getEntityAttr(Class clazz) {
int count = 1;
List<Field> fields = CommonUtil.getAllFields(clazz);
if (fields != null && fields.size() > 0) {
for (Field field : fields) {
field.setAccessible(true);
if (SqlUtil.ignoreField(field)) {
continue;
}
count++;
}
}
return count;
}
///**
// * 关键字模糊检索全文
// *
// * @param column 需要查找的列
// * @param mathSql 关键字语法,exsimple “white OR green”、“blue AND red”、“white NOT green”
// */
//public static <T extends DbEntity> List<T> searchData(SQLiteDatabase db, Class<T> clazz,
// String column, String mathSql) {
// String sql = "SELECT * FROM "
// + CommonUtil.getClassName(clazz)
// + " WHERE "
// + column
// + " MATCH '"
// + mathSql
// + "'";
//
// Cursor cursor = db.rawQuery(sql, null);
// List<T> data = cursor.getCount() > 0 ? newInstanceEntity(db, clazz, cursor) : null;
// closeCursor(cursor);
// return data;
//}
/**
* 检查某个字段的值是否存在
*
* @param expression 字段和值"url=xxx"
* @return {@code true}该字段的对应的value已存在
*/
static synchronized 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;
}
/**
* 条件查寻数据
*/
static synchronized <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] = "'" + checkValue(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(db, clazz, cursor) : null;
closeCursor(cursor);
close(db);
return data;
}
/**
* 条件查寻数据
*/
static synchronized <T extends DbEntity> List<T> findData(SQLiteDatabase db, String tableName,
String... expression) {
Class<T> clazz = null;
try {
clazz = (Class<T>) Class.forName(tableName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return findData(db, clazz, expression);
}
/**
* 条件查寻数据
*/
@Deprecated static synchronized <T extends DbEntity> List<T> findData(SQLiteDatabase db,
Class<T> clazz, @NonNull String[] wheres, @NonNull String[] values) {
db = checkDb(db);
if (wheres.length <= 0 || values.length <= 0) {
ALog.e(TAG, "请输入查询条件");
return null;
} else if (wheres.length != values.length) {
ALog.e(TAG, "groupName 和 vaule 长度不相等");
return null;
}
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(checkValue(values[i])).append("'");
sb.append(i >= wheres.length - 1 ? "" : " AND ");
i++;
}
print(FIND_DATA, sb.toString());
Cursor cursor = db.rawQuery(sb.toString(), null);
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(db, clazz, cursor) : null;
closeCursor(cursor);
close(db);
return data;
}
private static String checkValue(String value) {
if (value.contains("'")) {
return URLEncoder.encode(value);
}
return value;
}
/**
* 查找表的所有数据
*/
static synchronized <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(db, clazz, cursor) : null;
closeCursor(cursor);
close(db);
return data;
}
/**
* 删除某条数据
*/
static synchronized <T extends DbEntity> void delData(SQLiteDatabase db, Class<T> clazz,
String... expression) {
db = checkDb(db);
CheckUtil.checkSqlExpression(expression);
//List<Field> fields = CommonUtil.getAllFields(clazz);
//for (Field field : fields) {
// if (SqlUtil.isOneToOne(field)) {
// OneToOne oto = field.getAnnotation(OneToOne.class);
// delData(db, oto.table(), oto.key() + "=?", );
// } else if (SqlUtil.isOneToMany(field)) {
// OneToMany otm = field.getAnnotation(OneToMany.class);
// delData(db, otm.table(), otm.key() + "=?", otm.key());
// }
//}
String sql = "DELETE 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);
SqlHelper.print(DEL_DATA, sql);
db.execSQL(sql);
close(db);
}
/**
* 修改某行数据
*/
static synchronized void modifyData(SQLiteDatabase db, DbEntity dbEntity) {
db = checkDb(db);
Class<?> clazz = dbEntity.getClass();
List<Field> fields = CommonUtil.getAllFields(clazz);
DbEntity cacheEntity = mDataCache.get(getCacheKey(dbEntity));
if (fields != null && fields.size() > 0) {
StringBuilder sql = new StringBuilder();
StringBuilder prams = new StringBuilder();
sql.append("UPDATE ").append(CommonUtil.getClassName(dbEntity)).append(" SET ");
int i = 0;
for (Field field : fields) {
field.setAccessible(true);
if (SqlUtil.ignoreField(field)) {
continue;
}
try {
if (cacheEntity != null
&& field.get(dbEntity) == field.get(cacheEntity)
&& !field.getName().equals("state")) { //在LruCache中 state字段总是不能重新赋值...
//if (dbEntity instanceof DownloadEntity && field.getName().equals("state")) {
// Log.i(TAG, "cacheState => "
// + ((DownloadEntity) cacheEntity).getState()
// + ", newState => "
// + ((DownloadEntity) dbEntity).getState());
//}
continue;
}
//sb.append(i > 0 ? ", " : "");
//sb.append(field.getName()).append("='");
String value;
prams.append(i > 0 ? ", " : "");
prams.append(field.getName()).append("='");
Type type = field.getType();
if (type == Map.class) {
value = SqlUtil.map2Str((Map<String, String>) field.get(dbEntity));
} else if (type == List.class) {
if (SqlUtil.isOneToMany(field)) {
value = SqlUtil.getOneToManyElementParams(field);
} else {
value = SqlUtil.list2Str(dbEntity, field);
}
} else if (SqlUtil.isOneToOne(field)) {
value = SqlUtil.getOneToOneParams(field);
} else {
Object obj = field.get(dbEntity);
value = obj == null ? "" : checkValue(obj.toString());
}
//sb.append(value == null ? "" : value);
//sb.append("'");
prams.append(TextUtils.isEmpty(value) ? "" : value);
prams.append("'");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
i++;
}
if (!TextUtils.isEmpty(prams.toString())) {
sql.append(prams.toString());
sql.append(" where rowid=").append(dbEntity.rowID);
print(MODIFY_DATA, sql.toString());
db.execSQL(sql.toString());
}
}
mDataCache.put(getCacheKey(dbEntity), dbEntity);
close(db);
update.insertData(db, entity);
}
private static String getCacheKey(DbEntity dbEntity) {
return dbEntity.getClass().getName() + "_" + dbEntity.rowID;
}
/**
* 插入数据
*/
static synchronized void insertData(SQLiteDatabase db, DbEntity dbEntity) {
db = checkDb(db);
Class<?> clazz = dbEntity.getClass();
List<Field> fields = CommonUtil.getAllFields(clazz);
if (fields != null && fields.size() > 0) {
StringBuilder sb = new StringBuilder();
sb.append("INSERT INTO ").append(CommonUtil.getClassName(dbEntity)).append("(");
int i = 0;
for (Field field : fields) {
field.setAccessible(true);
if (SqlUtil.ignoreField(field)) {
continue;
}
sb.append(i > 0 ? ", " : "");
sb.append(field.getName());
i++;
}
sb.append(") VALUES (");
i = 0;
try {
for (Field field : fields) {
field.setAccessible(true);
if (SqlUtil.ignoreField(field)) {
continue;
}
sb.append(i > 0 ? ", " : "");
sb.append("'");
Type type = field.getType();
if (type == Map.class) {
sb.append(SqlUtil.map2Str((Map<String, String>) field.get(dbEntity)));
} else if (type == List.class) {
if (SqlUtil.isOneToMany(field)) {
sb.append(SqlUtil.getOneToManyElementParams(field));
} else {
sb.append(SqlUtil.list2Str(dbEntity, field));
}
} else if (SqlUtil.isOneToOne(field)) {
sb.append(SqlUtil.getOneToOneParams(field));
} else {
sb.append(checkValue(field.get(dbEntity).toString()));
}
sb.append("'");
i++;
//删除中介表
mDelegate.dropTable(db, tableName + "_temp");
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
sb.append(")");
print(INSERT_DATA, sb.toString());
db.execSQL(sb.toString());
}
close(db);
//db.setTransactionSuccessful();
//db.endTransaction();
mDelegate.close(db);
}
/**
* 查找表是否存在
*
* @param clazz 数据库实体
* @return true该数据库实体对应的表存在false不存在
* 处理3.4版本之前数据库迁移主要是修改子表外键字段对应的值
*/
static synchronized boolean tableExists(SQLiteDatabase db, Class clazz) {
return tableExists(db, CommonUtil.getClassName(clazz));
}
static synchronized 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 clazz 数据库实体
* @param tableName 数据库实体的类名
*/
static synchronized void createTable(SQLiteDatabase db, Class clazz, String tableName) {
db = checkDb(db);
createFTSTable(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 VIRTUAL table ")
sb.append("create table ")
.append(TextUtils.isEmpty(tableName) ? CommonUtil.getClassName(clazz) : tableName)
//.append(" USING fts4(");
.append(" (");
for (Field field : fields) {
field.setAccessible(true);
if (SqlUtil.ignoreField(field)) {
continue;
}
Class<?> type = field.getType();
sb.append(field.getName());
if (type == String.class || SqlUtil.isOneToOne(field) || type.isEnum()) {
sb.append(" varchar");
} else if (type == int.class || type == Integer.class) {
sb.append(" interger");
} 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)) {
//sb.append(" PRIMARY KEY");
}
if (SqlUtil.isForeign(field)) {
//foreignArray.add(field);
}
if (SqlUtil.isNoNull(field)) {
sb.append(" NOT NULL");
}
sb.append(",");
}
private void handle314AriaUpdate(SQLiteDatabase db) {
Set<String> tables = DBConfig.mapping.keySet();
for (String tableName : tables) {
Class clazz = DBConfig.mapping.get(tableName);
for (Field field : foreignArray) {
Foreign foreign = field.getAnnotation(Foreign.class);
sb.append("FOREIGN KEY (")
.append(field.getName())
.append(") REFERENCES ")
.append(CommonUtil.getClassName(foreign.table()))
.append("(")
.append(foreign.column())
.append("),");
String pColumn = SqlUtil.getPrimaryName(clazz);
if (!TextUtils.isEmpty(pColumn)) {
//删除所有主键为null的数据
String nullSql =
"DELETE FROM " + tableName + " WHERE " + pColumn + " = '' OR " + pColumn + " IS NULL";
ALog.d(TAG, nullSql);
db.execSQL(nullSql);
//删除所有主键重复的数据
String repeatSql = "DELETE FROM "
+ tableName
+ " WHERE "
+ pColumn
+ " in (SELECT "
+ pColumn
+ " FROM "
+ tableName
+ " GROUP BY " + pColumn + " having count(" + pColumn + ") > 1)";
ALog.d(TAG, repeatSql);
db.execSQL(repeatSql);
}
String str = sb.toString();
str = str.substring(0, str.length() - 1) + ");";
print(CREATE_TABLE, str);
db.execSQL(str);
}
close(db);
}
/**
* 创建分词表
*/
private static void createFTSTable(SQLiteDatabase db) {
String tableName = "ariaFts";
String sql = "CREATE VIRTUAL TABLE " + tableName + " USING fts4(tokenize= porter)";
if (!tableExists(db, tableName)) {
db.execSQL(sql);
}
}
//备份数据
List<DbEntity> list =
DelegateManager.getInstance().getDelegate(DelegateFind.class).findAllData(db, clazz);
/**
* 打印数据库日志
*
* @param type {@link DbUtil}
*/
static void print(int type, String sql) {
if (true) {
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;
}
ALog.v(TAG, str + sql);
}
//修改表名为中介表名
String alertSql = "ALTER TABLE " + tableName + " RENAME TO " + tableName + "_temp";
db.execSQL(alertSql);
/**
* 根据数据游标创建一个具体的对象
*/
private static synchronized <T extends DbEntity> List<T> newInstanceEntity(SQLiteDatabase db,
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();
for (Field field : fields) {
field.setAccessible(true);
if (SqlUtil.ignoreField(field)) {
continue;
}
Class<?> type = field.getType();
int column = cursor.getColumnIndex(field.getName());
if (column == -1) continue;
if (type == String.class) {
field.set(entity, URLDecoder.decode(cursor.getString(column)));
} 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) {
field.setBoolean(entity, !cursor.getString(column).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) {
field.set(entity, SqlUtil.str2Map(cursor.getString(column)));
} else if (type == List.class) {
String value = cursor.getString(column);
if (SqlUtil.isOneToMany(field)) {
//主键字段
String primaryKey = SqlUtil.getPrimaryName(clazz);
if (TextUtils.isEmpty(primaryKey)) {
throw new IllegalArgumentException("List中的元素对象必须需要@Primary注解的字段");
}
//list字段保存的数据
int kc = cursor.getColumnIndex(primaryKey);
String primaryData = cursor.getString(kc);
if (TextUtils.isEmpty(primaryData)) continue;
List<T> list = findForeignData(db, primaryData, value);
if (list == null) continue;
field.set(entity, findForeignData(db, primaryData, value));
} else {
field.set(entity, SqlUtil.str2List(value, field));
}
} else if (SqlUtil.isOneToOne(field)) {
String primaryKey = SqlUtil.getPrimaryName(clazz);
if (TextUtils.isEmpty(primaryKey)) {
throw new IllegalArgumentException("@OneToOne的注解对象必须需要@Primary注解的字段");
}
int kc = cursor.getColumnIndex(primaryKey);
String params = cursor.getString(column);
String primaryData = cursor.getString(kc);
if (TextUtils.isEmpty(primaryData) || primaryData.equalsIgnoreCase("null")) continue;
List<T> list = findForeignData(db, primaryData, params);
//创建一个原本的表
mDelegate.createTable(db, clazz);
//插入数据
if (list != null && list.size() > 0) {
field.set(entity, list.get(0));
}
}
}
entity.rowID = cursor.getInt(cursor.getColumnIndex("rowid"));
mDataCache.put(getCacheKey(entity), entity);
entitys.add(entity);
}
closeCursor(cursor);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return entitys;
}
/**
* 查找一对多一对一的关联数据
*
* @param primary 当前表的主键
* @param childParams 当前表关联数据的类名 $$ 主键名
*/
private static <T extends DbEntity> List<T> findForeignData(SQLiteDatabase db, String primary,
String childParams) {
String[] params = childParams.split("\\$\\$");
return findData(db, params[0], params[1] + "=?", primary);
}
private static void closeCursor(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
DelegateUpdate update = DelegateManager.getInstance().getDelegate(DelegateUpdate.class);
try {
cursor.close();
} catch (android.database.SQLException e) {
e.printStackTrace();
for (DbEntity entity : list) {
update.insertData(db, entity);
}
} catch (Exception e) {
ALog.e(TAG, CommonUtil.getPrintException(e));
}
}
private static void close(SQLiteDatabase db) {
//if (db != null && db.isOpen()) db.close();
}
//删除中介表
mDelegate.dropTable(db, tableName + "_temp");
private static SQLiteDatabase checkDb(SQLiteDatabase db) {
if (db == null || !db.isOpen()) {
db = INSTANCE.getWritableDatabase();
mDelegate.close(db);
}
return db;
}
}

@ -16,6 +16,14 @@
package com.arialyy.aria.orm;
import android.text.TextUtils;
import com.arialyy.aria.orm.annotation.Default;
import com.arialyy.aria.orm.annotation.Foreign;
import com.arialyy.aria.orm.annotation.Ignore;
import com.arialyy.aria.orm.annotation.Many;
import com.arialyy.aria.orm.annotation.NoNull;
import com.arialyy.aria.orm.annotation.One;
import com.arialyy.aria.orm.annotation.Primary;
import com.arialyy.aria.orm.annotation.Wrapper;
import com.arialyy.aria.util.CommonUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@ -32,31 +40,41 @@ import java.util.Set;
final class SqlUtil {
/**
* 获取一对一参数
* 获取主键字段名
*/
static String getOneToOneParams(Field field) {
OneToOne oneToOne = field.getAnnotation(OneToOne.class);
if (oneToOne == null) {
throw new IllegalArgumentException("@OneToOne注解的对象必须要有@Primary注解的字段");
static String getPrimaryName(Class clazz) {
List<Field> fields = CommonUtil.getAllFields(clazz);
String column;
if (fields != null && !fields.isEmpty()) {
for (Field field : fields) {
field.setAccessible(true);
if (isPrimary(field)) {
column = field.getName();
return column;
}
}
}
return oneToOne.table().getName() + "$$" + oneToOne.key();
return null;
}
/**
* 获取List一对多参数
*
* @param field list反射字段
* 获取类中所有不被忽略的字段
*/
static String getOneToManyElementParams(Field field) {
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
if (oneToMany == null) {
throw new IllegalArgumentException("一对多元素必须被@OneToMany注解");
static List<Field> getAllNotIgnoreField(Class clazz) {
List<Field> fields = CommonUtil.getAllFields(clazz);
List<Field> temp = new ArrayList<>();
if (fields != null && fields.size() > 0) {
for (Field f : fields) {
f.setAccessible(true);
if (!isIgnore(f)) {
temp.add(f);
}
}
return temp;
} else {
return null;
}
//关联的表名
String tableName = oneToMany.table().getName();
//关联的字段
String key = oneToMany.key();
return tableName + "$$" + key;
}
/**
@ -65,10 +83,6 @@ final class SqlUtil {
* @param field list反射字段
*/
static String list2Str(DbEntity dbEntity, Field field) throws IllegalAccessException {
NormalList normalList = field.getAnnotation(NormalList.class);
if (normalList == null) {
throw new IllegalArgumentException("List中元素必须被@NormalList注解");
}
List list = (List) field.get(dbEntity);
if (list == null || list.isEmpty()) return "";
StringBuilder sb = new StringBuilder();
@ -85,17 +99,17 @@ final class SqlUtil {
* @return 如果str为null则返回null
*/
static List str2List(String str, Field field) {
NormalList normalList = field.getAnnotation(NormalList.class);
if (normalList == null) {
throw new IllegalArgumentException("List中元素必须被@NormalList注解");
}
if (TextUtils.isEmpty(str)) return null;
String[] datas = str.split("\\$\\$");
List list = new ArrayList();
String type = normalList.clazz().getName();
Class clazz = CommonUtil.getListParamType(field);
if (clazz != null) {
String type = clazz.getName();
for (String data : datas) {
list.add(checkData(type, data));
}
}
return list;
}
@ -152,9 +166,12 @@ final class SqlUtil {
}
/**
* shadow$_klass_shadow$_monitor_{@link Ignore}rowID{@link Field#isSynthetic()}{@link
* Modifier#isFinal(int)}{@link Modifier#isStatic(int)}将被忽略
*
* @return true 忽略该字段
*/
static boolean ignoreField(Field field) {
static boolean isIgnore(Field field) {
// field.isSynthetic(), 使用as热启动App时,AS会自动给你的class添加change字段
Ignore ignore = field.getAnnotation(Ignore.class);
int modifiers = field.getModifiers();
@ -164,19 +181,29 @@ final class SqlUtil {
.isStatic(modifiers) || Modifier.isFinal(modifiers);
}
/**
* 判断是否是Wrapper注解
*
* @return {@code true}
*/
static boolean isWrapper(Class clazz) {
Wrapper w = (Wrapper) clazz.getAnnotation(Wrapper.class);
return w != null;
}
/**
* 判断是否一对多注解
*/
static boolean isOneToMany(Field field) {
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
static boolean isMany(Field field) {
Many oneToMany = field.getAnnotation(Many.class);
return oneToMany != null;
}
/**
* 判断是否是一对一注解
*/
static boolean isOneToOne(Field field) {
OneToOne oneToOne = field.getAnnotation(OneToOne.class);
static boolean isOne(Field field) {
One oneToOne = field.getAnnotation(One.class);
return oneToOne != null;
}
@ -210,6 +237,16 @@ final class SqlUtil {
return nn != null;
}
/**
* 判断是否是default
*
* @return {@code true}为default
*/
static boolean isDefault(Field field) {
Default nn = field.getAnnotation(Default.class);
return nn != null;
}
private static Object checkData(String type, String data) {
if (type.equalsIgnoreCase("java.lang.String")) {
return data;
@ -222,17 +259,4 @@ final class SqlUtil {
}
return null;
}
/**
* 查找class的主键字段
*
* @return 返回主键字段名
*/
static String getPrimaryName(Class<? extends DbEntity> clazz) {
List<Field> fields = CommonUtil.getAllFields(clazz);
for (Field field : fields) {
if (isPrimary(field)) return field.getName();
}
return null;
}
}

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.orm;
package com.arialyy.aria.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -21,16 +22,9 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by AriaL on 2017/7/4.
* 外键约束
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Foreign {
/**
* 关联的表
*/
Class<? extends DbEntity> table();
/**
* 关联的列
* Created by lyy on 2015/11/2.
* 默认数据
*/
String column();
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Default {
String value() default "";
}

@ -0,0 +1,50 @@
/*
* 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.annotation;
import com.arialyy.aria.orm.ActionPolicy;
import com.arialyy.aria.orm.DbEntity;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by AriaL on 2017/7/4.
* 外键约束
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Foreign {
/**
* 关联的表
*/
Class<? extends DbEntity> parent();
/**
* 父表对应的列名
*/
String column();
/**
* ON UPDATE 约束
*/
ActionPolicy onUpdate() default ActionPolicy.NO_ACTION;
/**
* ON DELETE 约束
*/
ActionPolicy onDelete() default ActionPolicy.NO_ACTION;
}

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.arialyy.aria.orm;
package com.arialyy.aria.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.orm;
package com.arialyy.aria.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -24,13 +24,14 @@ import java.lang.annotation.Target;
* Created by AriaL on 2017/7/4.
* 一对多
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface OneToMany {
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Many {
/**
* 关联的表
* 父表对应的字段名
*/
Class<? extends DbEntity> table();
String parentColumn();
/**
* 关联的主键
* 父表在子表对应的字段
*/
String key();
String entityColumn();
}

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.arialyy.aria.orm;
package com.arialyy.aria.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.orm;
package com.arialyy.aria.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -22,17 +22,8 @@ import java.lang.annotation.Target;
/**
* Created by AriaL on 2017/7/4.
* 对一
*
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface OneToOne {
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface One {
/**
* 关联的表
*/
Class<? extends DbEntity> table();
/**
* 关联的主键
*/
String key();
}

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.arialyy.aria.orm;
package com.arialyy.aria.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -27,4 +27,9 @@ import java.lang.annotation.Target;
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Primary {
int value() default -1;
/**
* 字段需要int类型才可以自增
*/
boolean autoincrement() default false;
}

@ -0,0 +1,30 @@
/*
* 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.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by lyy on 2015/11/2.
* 设置表名如果不是使用该注解默认为类名
*/
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Table {
String tableName();
}

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.orm;
package com.arialyy.aria.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -21,16 +21,9 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by AriaL on 2017/7/4.
* 主键和外键约束
* Created by laoyuyu on 2018/3/21.
* 关系包裹
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface PrimaryAndForeign {
/**
* 关联的表
*/
Class<? extends DbEntity> table();
/**
* 关联的列
*/
String column();
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME)
public @interface Wrapper {
}

@ -25,7 +25,7 @@ import android.util.Log;
* Aria日志工具
*/
public class ALog {
public static final boolean DEBUG = true;
public static final int LOG_LEVEL_VERBOSE = 2;
public static final int LOG_LEVEL_DEBUG = 3;
public static final int LOG_LEVEL_INFO = 4;

@ -74,7 +74,8 @@ public class CheckUtil {
* 检查下载实体
*/
public static void checkDownloadEntity(DownloadEntity entity) {
entity.setUrl(checkUrl(entity.getUrl()));
checkUrlInvalidThrow(entity.getUrl());
entity.setUrl(entity.getUrl());
checkPath(entity.getDownloadPath());
}
@ -88,9 +89,9 @@ public class CheckUtil {
}
/**
* 检测下载链接是否合法如果地址中path是"//"而不是"/"将会改为"/"
* 检测url是否合法如果url不合法将抛异常
*/
public static String checkUrl(String url) {
public static void checkUrlInvalidThrow(String url) {
if (TextUtils.isEmpty(url)) {
throw new IllegalArgumentException("url不能为null");
} else if (!url.startsWith("http") && !url.startsWith("ftp")) {
@ -100,7 +101,26 @@ public class CheckUtil {
if (index == -1) {
throw new IllegalArgumentException("url不合法");
}
return url;
}
/**
* 检测url是否合法
*
* @return {@code true} 合法{@code false} 非法
*/
public static boolean checkUrl(String url) {
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 true;
}
/**

@ -30,13 +30,10 @@ import com.arialyy.aria.core.command.group.GroupCmdFactory;
import com.arialyy.aria.core.command.normal.AbsNormalCmd;
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.inf.AbsGroupTaskEntity;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTaskEntity;
import com.arialyy.aria.orm.DbEntity;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
@ -46,11 +43,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URLEncoder;
@ -62,6 +56,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
@ -73,6 +68,64 @@ import java.util.regex.Pattern;
public class CommonUtil {
private static final String TAG = "CommonUtil";
/**
* 获取map泛型类型
*
* @param map list类型字段
* @return 泛型类型
*/
public static Class[] getMapParamType(Field map) {
Class type = map.getType();
if (!type.isAssignableFrom(Map.class)) {
ALog.d(TAG, "字段类型不是Map");
return null;
}
Type fc = map.getGenericType();
if (fc == null) {
ALog.d(TAG, "该字段没有泛型参数");
return null;
}
if (fc instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) fc;
Type[] types = pt.getActualTypeArguments();
Class[] clazz = new Class[2];
clazz[0] = (Class) types[0];
clazz[1] = (Class) types[1];
return clazz;
}
return null;
}
/**
* 获取list泛型类型
*
* @param list list类型字段
* @return 泛型类型
*/
public static Class getListParamType(Field list) {
Class type = list.getType();
if (!type.isAssignableFrom(List.class)) {
ALog.d(TAG, "字段类型不是List");
return null;
}
Type fc = list.getGenericType(); // 关键的地方,如果是List类型,得到其Generic的类型
if (fc == null) {
ALog.d(TAG, "该字段没有泛型参数");
return null;
}
if (fc instanceof ParameterizedType) { //如果是泛型参数的类型
ParameterizedType pt = (ParameterizedType) fc;
return (Class) pt.getActualTypeArguments()[0]; //得到泛型里的class类型对象。
}
return null;
}
/**
* 创建文件名如果url链接有后缀名则使用url中的后缀名
*
@ -230,55 +283,6 @@ public class CommonUtil {
return null;
}
/**
* 实例化泛型的实际类型参数
*
* @throws Exception
*/
public static void typeCheck(Type type) throws Exception {
System.out.println("该类型是" + type);
// 参数化类型
if (type instanceof ParameterizedType) {
Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments();
for (int i = 0; i < typeArguments.length; i++) {
// 类型变量
if (typeArguments[i] instanceof TypeVariable) {
System.out.println("第" + (i + 1) + "个泛型参数类型是类型变量" + typeArguments[i] + ",无法实例化。");
}
// 通配符表达式
else if (typeArguments[i] instanceof WildcardType) {
System.out.println("第" + (i + 1) + "个泛型参数类型是通配符表达式" + typeArguments[i] + ",无法实例化。");
}
// 泛型的实际类型,即实际存在的类型
else if (typeArguments[i] instanceof Class) {
System.out.println("第" + (i + 1) + "个泛型参数类型是:" + typeArguments[i] + ",可以直接实例化对象");
}
}
// 参数化类型数组或类型变量数组
} else if (type instanceof GenericArrayType) {
System.out.println("该泛型类型是参数化类型数组或类型变量数组,可以获取其原始类型。");
Type componentType = ((GenericArrayType) type).getGenericComponentType();
// 类型变量
if (componentType instanceof TypeVariable) {
System.out.println("该类型变量数组的原始类型是类型变量" + componentType + ",无法实例化。");
}
// 参数化类型,参数化类型数组或类型变量数组
// 参数化类型数组或类型变量数组也可以是多维的数组,getGenericComponentType()方法仅仅是去掉最右边的[]
else {
// 递归调用方法自身
typeCheck(componentType);
}
} else if (type instanceof TypeVariable) {
System.out.println("该类型是类型变量");
} else if (type instanceof WildcardType) {
System.out.println("该类型是通配符表达式");
} else if (type instanceof Class) {
System.out.println("该类型不是泛型类型");
} else {
throw new Exception();
}
}
/**
* 根据下载任务组的url创建key
*
@ -308,28 +312,27 @@ public class CommonUtil {
* {@code false}如果任务已经完成只删除任务数据库记录
*/
public static void delDownloadGroupTaskConfig(boolean removeFile,
DownloadGroupTaskEntity tEntity) {
List<DownloadTaskEntity> tasks =
DbEntity.findDatas(DownloadTaskEntity.class, "groupName=?", tEntity.key);
if (tasks != null && !tasks.isEmpty()) {
for (DownloadTaskEntity taskEntity : tasks) {
delDownloadTaskConfig(removeFile, taskEntity);
DownloadGroupEntity groupEntity) {
if (groupEntity == null) {
ALog.e(TAG, "删除下载任务组记录失败,任务组实体为null");
return;
}
for (DownloadEntity taskEntity : groupEntity.getSubTask()) {
delDownloadTaskConfig(removeFile, taskEntity);
}
if (tEntity.getEntity() != null) {
File dir = new File(tEntity.getEntity().getDirPath());
File dir = new File(groupEntity.getDirPath());
if (removeFile) {
if (dir.exists()) {
dir.delete();
}
} else {
if (!tEntity.getEntity().isComplete()) {
if (!groupEntity.isComplete()) {
dir.delete();
}
}
tEntity.deleteData();
}
groupEntity.deleteData();
}
/**
@ -338,8 +341,7 @@ public class CommonUtil {
* @param removeFile {@code true} 不仅删除任务数据库记录还会删除已经删除完成的文件
* {@code false}如果任务已经完成只删除任务数据库记录
*/
public static void delUploadTaskConfig(boolean removeFile, UploadTaskEntity tEntity) {
UploadEntity uEntity = tEntity.getEntity();
public static void delUploadTaskConfig(boolean removeFile, UploadEntity uEntity) {
if (uEntity == null) {
return;
}
@ -353,8 +355,8 @@ public class CommonUtil {
if (config.exists()) {
config.delete();
}
//uEntity.deleteData();
tEntity.deleteData();
//下载任务实体和下载实体为一对一关系,下载实体删除,任务实体自动删除
uEntity.deleteData();
}
/**
@ -363,8 +365,7 @@ public class CommonUtil {
* @param removeFile {@code true} 不仅删除任务数据库记录还会删除已经下载完成的文件
* {@code false}如果任务已经完成只删除任务数据库记录
*/
public static void delDownloadTaskConfig(boolean removeFile, DownloadTaskEntity tEntity) {
DownloadEntity dEntity = tEntity.getEntity();
public static void delDownloadTaskConfig(boolean removeFile, DownloadEntity dEntity) {
if (dEntity == null) return;
File file = new File(dEntity.getDownloadPath());
if (removeFile) {
@ -383,9 +384,8 @@ public class CommonUtil {
if (config.exists()) {
config.delete();
}
//dEntity.deleteData();
//tEntity.deleteData();
tEntity.deleteData();
//下载任务实体和下载实体为一对一关系,下载实体删除,任务实体自动删除
dEntity.deleteData();
}
/**

@ -35,6 +35,8 @@ public class ErrorHelp {
* @param msg 错误提示
* @param ex 异常
*/
// TODO: 2018/4/4 错误应该写在文件中
@Deprecated
public static void saveError(String taskType, AbsEntity entity, String msg, String ex) {
ErrorEntity errorEntity = new ErrorEntity();
errorEntity.insertTime = System.currentTimeMillis();

@ -45,7 +45,7 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
Aria.download(this).register();
setTitle("任务组");
mUrls = getModule(GroupModule.class).getUrls();
DownloadGroupTaskEntity entity = Aria.download(this).getDownloadGroupTask(mUrls);
DownloadGroupTaskEntity entity = Aria.download(this).getGroupTask(mUrls);
if (entity != null && entity.getEntity() != null) {
DownloadGroupEntity groupEntity = entity.getEntity();
mChildList.addData(groupEntity.getSubTask());
@ -84,7 +84,7 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
Environment.getExternalStorageDirectory().getPath() + "/Download/group_test_3")
.setGroupAlias("任务组测试")
.setSubFileName(getModule(GroupModule.class).getSubName())
//.setFileSize(32895492)
.setFileSize(32895492)
.start();
break;
case R.id.stop:

@ -43,7 +43,7 @@ public class FTPDirDownloadActivity extends BaseActivity<ActivityDownloadGroupBi
super.init(savedInstanceState);
Aria.download(this).register();
setTitle("FTP文件夹下载");
DownloadGroupTaskEntity entity = Aria.download(this).getDownloadGroupTask(dir);
DownloadGroupTaskEntity entity = Aria.download(this).getFtpDirTask(dir);
if (entity != null && entity.getEntity() != null) {
DownloadGroupEntity groupEntity = entity.getEntity();
mChildList.addData(groupEntity.getSubTask());

@ -26,16 +26,12 @@ import butterknife.Bind;
import com.arialyy.annotations.Download;
import com.arialyy.annotations.DownloadGroup;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupTask;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.frame.util.FileUtil;
import com.arialyy.frame.util.show.L;
import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityMultiDownloadBinding;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@ -55,7 +51,7 @@ public class MultiDownloadActivity extends BaseActivity<ActivityMultiDownloadBin
super.init(savedInstanceState);
Aria.download(this).register();
setTitle("下载列表");
List<AbsEntity> temps = Aria.download(this).getTotleTaskList();
List<AbsEntity> temps = Aria.download(this).getTotalTaskList();
if (temps != null && !temps.isEmpty()) {
mData.addAll(temps);
}

@ -16,7 +16,9 @@
package com.arialyy.aria.core.upload;
import com.arialyy.aria.core.inf.AbsNormalTaskEntity;
import com.arialyy.aria.orm.OneToOne;
import com.arialyy.aria.orm.annotation.Foreign;
import com.arialyy.aria.orm.annotation.Ignore;
import com.arialyy.aria.orm.annotation.Primary;
import java.util.HashMap;
import java.util.Map;
@ -28,9 +30,16 @@ public class UploadTaskEntity extends AbsNormalTaskEntity<UploadEntity> {
public String attachment; //文件上传需要的key
public String contentType = "multipart/form-data"; //上传的文件类型
public String userAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)";
@OneToOne(table = UploadEntity.class, key = "filePath") public UploadEntity entity;
//@OneToOne(table = UploadEntity.class, key = "filePath") public UploadEntity entity;
@Ignore public UploadEntity entity;
public String filePath = "";
@Primary @Foreign(parent = UploadEntity.class, column = "filePath")
public String key;
/**
* 文件上传表单
*/
@ -43,11 +52,17 @@ public class UploadTaskEntity extends AbsNormalTaskEntity<UploadEntity> {
return entity;
}
@Override public String getKey() {
return key;
}
public void save(UploadEntity entity) {
if (entity != null) {
filePath = entity.getFilePath();
key = entity.getKey();
this.entity = entity;
entity.save();
}
save();
}
}

Loading…
Cancel
Save