package org.voxe.android.data; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; import org.voxe.android.common.BitmapHelper; import org.voxe.android.common.LogHelper; import org.voxe.android.model.Candidate; import org.voxe.android.model.Election; import org.voxe.android.model.ElectionsHolder; import org.voxe.android.model.Icon; import org.voxe.android.model.Photo; import org.voxe.android.model.PhotoSizeInfo; import org.voxe.android.model.Tag; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import com.google.common.base.Optional; public class ElectionDAO { private final ObjectMapper mapper = new ObjectMapper(); private final Context context; private String dataFilename; public ElectionDAO(Context context) { this.context = context; try { PackageManager manager = context.getPackageManager(); PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0); String version = info.versionName; dataFilename = "electionsFull-" + version + ".json"; } catch (Exception e) { LogHelper.logException("Could not get application version", e); dataFilename = "electionsFull.json"; } mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationConfig.Feature.AUTO_DETECT_SETTERS, false); mapper.configure(DeserializationConfig.Feature.USE_GETTERS_AS_SETTERS, false); mapper.configure(SerializationConfig.Feature.AUTO_DETECT_GETTERS, false); } public Optional<ElectionsHolder> load() { File storageFile = getStorageFile(); if (!storageFile.exists()) { return Optional.absent(); } try { long start = System.currentTimeMillis(); ElectionsHolder electionHolder = mapper.readValue(storageFile, ElectionsHolder.class); electionHolder.lastUpdateTimestamp = 0; LogHelper.logDuration("Loaded election data", start); for (Election election : electionHolder.elections) { if (election.candidacies != null) { long startPhotos = System.currentTimeMillis(); Map<String, Photo> loadedPhotos = new HashMap<String, Photo>(); for (Candidate candidate : election.getMainCandidates()) { Optional<File> optionalFile = getCandidatePhotoFile(candidate.photo); if (optionalFile.isPresent()) { String uniqueId = candidate.photo.sizes.getLargestSize().get().getUniqueId(); if (loadedPhotos.containsKey(uniqueId)) { Photo cachedPhoto = loadedPhotos.get(uniqueId); candidate.photo = cachedPhoto; } else { File file = optionalFile.get(); if (file.exists()) { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inPreferredConfig = Bitmap.Config.ARGB_8888; Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), opts); Bitmap roundedCornerBitmap = BitmapHelper.getRoundedCornerBitmap(bitmap); candidate.photo.photoBitmap = roundedCornerBitmap; loadedPhotos.put(uniqueId, candidate.photo); } } } } Map<String, Icon> loadedIcons = new HashMap<String, Icon>(); for (Tag tag : election.tags) { Optional<File> optionalFile = getTagImageFile(tag.icon); if (optionalFile.isPresent()) { String uniqueId = tag.icon.getUniqueId().get(); if (loadedIcons.containsKey(uniqueId)) { Icon cachedIcon = loadedIcons.get(uniqueId); tag.icon = cachedIcon; } else { File file = optionalFile.get(); if (file.exists()) { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inPreferredConfig = Bitmap.Config.ARGB_8888; Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), opts); tag.icon.bitmap = bitmap; loadedIcons.put(uniqueId, tag.icon); } } } } LogHelper.logDuration("Loaded photos", startPhotos); } } return Optional.of(electionHolder); } catch (Exception e) { LogHelper.logException("Could not read data from storage file " + storageFile, e); return Optional.absent(); } } public void clearData() { File storageFile = getStorageFile(); storageFile.delete(); } public boolean shouldDownloadCandidatePhoto(Photo photo) { Optional<File> optionalFile = getCandidatePhotoFile(photo); return optionalFile.isPresent(); } private Optional<File> getCandidatePhotoFile(Photo photo) { Optional<String> optionalPhotoId = getCandidatePhotoId(photo); return getPhotoFileFromId(optionalPhotoId); } private Optional<File> getPhotoFileFromId(Optional<String> optionalPhotoId) { if (optionalPhotoId.isPresent()) { String filename = optionalPhotoId.get(); File file = getFile(filename); return Optional.of(file); } else { return Optional.absent(); } } private Optional<String> getCandidatePhotoId(Photo photo) { if (photo != null) { Optional<PhotoSizeInfo> largestSize = photo.sizes.getLargestSize(); if (largestSize.isPresent()) { PhotoSizeInfo photoSizeInfo = largestSize.get(); String photoId = photoSizeInfo.getUniqueId(); return Optional.of(photoId); } } return Optional.absent(); } public void saveCandidatePhoto(Photo photo) { Bitmap photoBitmap = photo.photoBitmap; if (photoBitmap != null) { String photoId = getCandidatePhotoId(photo).get(); saveJpegImage(photoBitmap, photoId); } } private void saveJpegImage(Bitmap bitmap, String photoId) { LogHelper.log("Saving JPEG file: " + photoId); File file = getFile(photoId); OutputStream fOut = null; try { fOut = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut); } catch (IOException e) { LogHelper.logException("Could not save bitmap for image with id " + photoId + " to " + file.getAbsolutePath(), e); return; } finally { if (fOut != null) { try { fOut.flush(); fOut.close(); } catch (IOException e) { // Do nothing } } } } private void savePngImage(Bitmap bitmap, String photoId) { LogHelper.log("Saving PNG file: " + photoId); File file = getFile(photoId); OutputStream fOut = null; try { fOut = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut); } catch (IOException e) { LogHelper.logException("Could not save bitmap for image with id " + photoId + " to " + file.getAbsolutePath(), e); return; } finally { if (fOut != null) { try { fOut.flush(); fOut.close(); } catch (IOException e) { // Do nothing } } } } public void save(ElectionsHolder electionHolder) { File storageFile = getStorageFile(); try { long start = System.currentTimeMillis(); mapper.writeValue(storageFile, electionHolder); LogHelper.logDuration("Saving election data", start); } catch (Exception e) { LogHelper.logException("Could not write data to storage file " + storageFile, e); } } private File getStorageFile() { return getFile(dataFilename); } private File getFile(String filename) { File fileAbsolutePath = context.getFileStreamPath(filename); return fileAbsolutePath; } public boolean shouldDownloadTagPhoto(Icon icon) { Optional<File> optionalFile = getTagImageFile(icon); return optionalFile.isPresent(); } private Optional<File> getTagImageFile(Icon icon) { Optional<String> optionalImageId = getTagImageId(icon); return getPhotoFileFromId(optionalImageId); } private Optional<String> getTagImageId(Icon icon) { if (icon != null) { Optional<String> uniqueId = icon.getUniqueId(); return uniqueId; } else { return Optional.absent(); } } public void saveTagImage(Icon icon) { Bitmap bitmap = icon.bitmap; if (bitmap != null) { String imageId = getTagImageId(icon).get(); savePngImage(bitmap, imageId); } } }