/* This file is part of ZamiaDroid.
*
* ZamiaDroid is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZamiaDroid is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ZamiaDroid. If not, see <http://www.gnu.org/licenses/>.
*/
package uni.projecte.controler;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import org.xmlpull.v1.XmlSerializer;
import android.content.Context;
import android.database.Cursor;
import android.os.Environment;
import android.util.Log;
import uni.projecte.dataLayer.CitationManager.Zamia.ZamiaCitationReader;
import uni.projecte.dataLayer.CitationManager.Zamia.ZamiaCitationXMLparser;
import uni.projecte.dataLayer.ProjectManager.ZamiaProjectWriter;
import uni.projecte.dataLayer.ProjectManager.xml.ZamiaProjectXMLparser;
import uni.projecte.dataLayer.ThesaurusManager.ThesaurusElement;
import uni.projecte.dataLayer.bd.AttributeDbAdapter;
import uni.projecte.dataLayer.bd.ProjectDbAdapter;
import uni.projecte.dataLayer.bd.ResearchDbAdapter;
import uni.projecte.dataLayer.utils.FileUtils;
import uni.projecte.dataLayer.utils.IoUtils;
import uni.projecte.dataTypes.CitationPhoto;
import uni.projecte.dataTypes.Compress;
import uni.projecte.dataTypes.ProjectField;
public class BackupControler {
private static final String BACKUP_MODE="Backups";
private static final String EXPORT_MODE="Projects";
private static String photoPath="Backups/photos/";
private String zamiaDroidPath;
private ResearchDbAdapter rsDB;
private AttributeDbAdapter atDB;
private ProjectDbAdapter prDB;
private Context baseContext;
private PreferencesControler prefC;
public BackupControler(Context context){
this.baseContext=context;
prefC= new PreferencesControler(baseContext);
zamiaDroidPath=prefC.getDefaultPath();
}
/*
*
* copy db's projects from version2 to version3
*
*/
public void copyProjects(){
rsDB= new ResearchDbAdapter(baseContext);
prDB= new ProjectDbAdapter(baseContext);
atDB= new AttributeDbAdapter(baseContext);
rsDB.open();
atDB.open();
prDB.open();
Cursor projects=rsDB.fetchAllResearches();
projects.moveToFirst();
while(!projects.isAfterLast()){
long projId=prDB.createProject(projects.getString(1), projects.getString(2),"");
Cursor attributes=atDB.fetchAllFieldsFromProjectWithDefaultOrder(projId);
attributes.moveToFirst();
prDB.startTransaction();
while(!attributes.isAfterLast()){
boolean visible=true;
int intVis=attributes.getInt(7);
if(intVis==0) visible=false;
prDB.createField(projId, attributes.getString(2), attributes.getString(4), attributes.getString(8), attributes.getString(5), attributes.getString(3),attributes.getString(6),visible);
attributes.moveToNext();
}
prDB.endTransaction();
attributes.close();
projects.moveToNext();
}
projects.close();
rsDB.deleteDatabase();
atDB.deleteDatabase();
rsDB.close();
atDB.close();
prDB.close();
}
public void clearTH(){
ThesaurusControler tC= new ThesaurusControler(baseContext);
tC.removeThList();
}
public XmlSerializer writeZamiaProject(long projId, ZamiaProjectWriter zpW, boolean includeCitationStructure){
ProjectControler pC= new ProjectControler(baseContext);
ProjectSecondLevelControler slP= new ProjectSecondLevelControler(baseContext);
DataTypeControler dtC= new DataTypeControler(baseContext);
ThesaurusControler tC=new ThesaurusControler(baseContext);
pC.loadProjectInfoById(projId);
if(includeCitationStructure) zpW.openCitationDocument();
else zpW.openDocument();
zpW.openProject(pC.getName(), prefC.getLang());
zpW.setDescription("");
zpW.setProjectType(pC.getProjType());
ThesaurusElement th=tC.loadThInfo();
if(th!=null){
zpW.setThesaurus(th.getThType(),pC.getThName(),th.getSourceId(),th.getSourceType());
}
zpW.openFieldList();
ArrayList<ProjectField> fieldList=pC.getProjFields(projId);
Iterator<ProjectField> fieldIterator=fieldList.iterator();
//for
while (fieldIterator.hasNext()) {
ProjectField pF=fieldIterator.next();
zpW.openField(pF.getLabel(), pF.getName(), pF.getDesc(),pF.getType(),pF.getValue());
if(pF.getType().equals("secondLevel")){
ArrayList<ProjectField> slList= slP.getProjFields(pF.getId());
Iterator<ProjectField> slFieldIterator=slList.iterator();
zpW.openSLFields();
while(slFieldIterator.hasNext()){
ProjectField sPF=slFieldIterator.next();
zpW.openField(sPF.getLabel(), sPF.getName(), sPF.getDesc(),sPF.getType(),sPF.getValue());
if(sPF.getType().equals("complex")){
zpW.addItemsList(dtC.getItemsbySecondLevelFieldId(sPF.getId()));
}
zpW.closeField();
}
zpW.closeSLFields();
}
else if(pF.getType().equals("complex")){
zpW.addItemsList(dtC.getItemsbyFieldId(pF.getId()));
}
zpW.closeField();
}
zpW.closeFieldList();
zpW.writeCitationCoordinate();
zpW.closeProject();
if(!includeCitationStructure) zpW.closeDocument();
return zpW.getSerializer();
}
public String backupProject(long projId, String fileName, String exportMode){
ZamiaProjectWriter zpW= new ZamiaProjectWriter();
writeZamiaProject(projId, zpW, false);
zpW.writeToFile(zpW.convertXML2String(), fileName,exportMode,baseContext);
return zpW.convertXML2String();
}
public void backupProjectCitations(long projId, String fileName){
CitationControler sC= new CitationControler(baseContext);
sC.exportProject(projId, baseContext, fileName, "Zamia");
}
private String getPhotoTempBackupPath(){
return Environment.getExternalStorageDirectory() +"/"+zamiaDroidPath+"/"+photoPath;
}
private String getZippedPhotosPath(){
return Environment.getExternalStorageDirectory() +"/"+zamiaDroidPath+"/Backups/photos.zip";
}
public String getProjectsPath(){
return Environment.getExternalStorageDirectory() +"/"+zamiaDroidPath+"/Projects/";
}
private int backupProjectPhotos(long projId) {
String photoLocation = getPhotoTempBackupPath();
File f = new File(photoLocation);
if(!f.exists()) f.mkdir();
else{
FileUtils.deleteRecursive(f);
f.mkdir();
}
PhotoControler photoCnt= new PhotoControler(baseContext);
ArrayList<CitationPhoto> photoList=photoCnt.getPhotoCitationPhotos(projId);
Iterator<CitationPhoto> itCitPhoto=photoList.iterator();
while(itCitPhoto.hasNext()){
CitationPhoto tmpPhoto=itCitPhoto.next();
File originFile=new File(tmpPhoto.getPhotoPath());
FileUtils.copyFileToDir(originFile, new File(photoLocation+originFile.getName()));
}
String[] filesInside=f.list();
int size=filesInside.length;
return size;
}
/*
* This method creates a Backup of the Project structure and citations contained on a zipFile
*
*/
public int exportProject(long projId,String fileName,boolean backupPhotos){
backupProject(projId, "zp_"+fileName,BACKUP_MODE);
backupProjectCitations(projId, "zc_"+fileName);
if(backupPhotos){
int photosMoved=backupProjectPhotos(projId);
if(photosMoved==0) backupPhotos=false;
}
long size= zipFiles(fileName,backupPhotos);
if(size>0) return 1;
else return (int) size;
}
public int exportProjectStructure(long projId, String fileName){
return backupProject(projId, fileName,EXPORT_MODE).length();
}
public long importProjectStructure(String projName, String fileName, String thName){
ProjectZamiaControler zpControler= new ProjectZamiaControler(baseContext);
long projId=zpControler.createProject(projName,thName, "");
zpControler.setAutoFields(false);
//Same project doesn't exist
if(projId >-1){
ZamiaProjectXMLparser zpXM= new ZamiaProjectXMLparser(zpControler);
zpXM.readXML(baseContext,fileName,false);
if(zpXM.isError()){
//Wrong file
projId=-2;
zpControler.removeProject(projId);
}
}
return projId;
}
/*
*
* This method restores a Backup called @fileName. If @projId is < 0 the project contained on the backup will be created
* with @projName. When @projId > 0 the citations will be loaded on the project with @projID.
*
*/
public long importProject(String fileName, long projId, String projName){
Log.i("Backup","(A) Action: Import Backup | Info: filename: "+fileName+ " projName: "+projName);
boolean error=false;
unZipFilesToTemp(fileName);
if(projId<0){
Log.i("Backup","(B) Action: Creating Project: zp_"+fileName+".xml");
ProjectZamiaControler zpControler= new ProjectZamiaControler(baseContext);
zpControler.createProject(projName,"", "");
zpControler.setAutoFields(false);
ZamiaProjectXMLparser zpXM= new ZamiaProjectXMLparser(zpControler);
zpXM.readXML(baseContext,prefC.getBackupPath()+"unzipped/zp_"+fileName+".xml",false);
error=zpXM.isError();
projId=zpControler.getProjId();
Log.i("Backup","(B) Action: Project created | Info: error="+error);
}
if(!error){
Log.i("Backup","(B) Action: Creating Citations: zc_"+fileName+".xml");
ZamiaCitationReader zR= new ZamiaCitationReader(baseContext, projId);
ZamiaCitationXMLparser zCP= new ZamiaCitationXMLparser(zR);
zCP.readXML(baseContext, prefC.getBackupPath()+"unzipped/zc_"+fileName+".xml", false);
error=zCP.isError();
}
if(error) return -1;
else{
String unzippedPath=prefC.getBackupPath() + "unzipped/";
File f=new File(unzippedPath+"photos.zip");
if(f.exists()){
Log.i("Backup","(C) Action: Extracting photos: photos.zip");
importPhotos(f);
f.delete();
}
else{
Log.i("Backup","(C) Action: Extracting photos: no photos' file found");
}
return projId;
}
}
private void importPhotos(File f) {
//Unzip photos.zip
//move photos to default Path
PhotoControler photoCnt=new PhotoControler(baseContext);
IoUtils.unpackZip(f.getAbsolutePath(), photoCnt.getMainPhotoPath());
}
/*
* This method encapsulates citation and project backup file inside a unique compressed ZIP file
* with the name @fileName
*
*/
private long zipFiles(String fileName, boolean backupPhotos){
String zipName = prefC.getBackupPath()+fileName+".zip";
String[] files;
if(backupPhotos) {
Compress c=new Compress(new File(getPhotoTempBackupPath()).list(), getZippedPhotosPath());
c.zipWithRelativePath(getPhotoTempBackupPath());
files = new String[] {prefC.getCitationsPath()+"zc_"+fileName+".xml",prefC.getBackupPath()+"zp_"+fileName+".xml",getZippedPhotosPath()};
}
else{
files = new String[] {prefC.getCitationsPath()+"zc_"+fileName+".xml", prefC.getBackupPath()+"zp_"+fileName+".xml"};
}
Compress c = new Compress(files, zipName);
c.zip();
File file = new File(files[0]);
file.delete();
file = new File(files[1]);
file.delete();
if(backupPhotos){
file=new File(getZippedPhotosPath());
file.delete();
FileUtils.deleteRecursive(new File(getPhotoTempBackupPath()));
}
file = new File(zipName);
return file.length();
}
/*
* This method extracts the citation and project backup file with the name @fileName
*
*/
private void unZipFilesToTemp(String fileName){
String zipFile = Environment.getExternalStorageDirectory() +"/ZamiaDroid/Backups/"+fileName+".zip";
String unzipLocation = getUnzippedPath();
IoUtils.unpackZip(zipFile,unzipLocation);
Log.i("Backup","(B) Action: Unzipping Project "+fileName+".zip");
}
private String getUnzippedPath(){
return Environment.getExternalStorageDirectory() + "/ZamiaDroid/Backups/unzipped/";
}
}